diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-06-23 13:03:03 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-06-23 13:04:37 -0300 |
commit | ac5c4d77d022829d1b5b8e0f32ba1cc60427c34b (patch) | |
tree | 92820c51d18a6f7de9af2a0ea5c44c6b26ef5240 /libre | |
parent | 520dcf689922d3bbfd62b7281d55915f0b91c2cb (diff) | |
download | abslibre-ac5c4d77d022829d1b5b8e0f32ba1cc60427c34b.tar.gz abslibre-ac5c4d77d022829d1b5b8e0f32ba1cc60427c34b.tar.bz2 abslibre-ac5c4d77d022829d1b5b8e0f32ba1cc60427c34b.zip |
icecat-38.8.0_gnu1-3: add harfbuzz patch
Diffstat (limited to 'libre')
-rw-r--r-- | libre/icecat/PKGBUILD | 25 | ||||
-rw-r--r-- | libre/icecat/harfbuzz-1.1.3.patch | 27038 |
2 files changed, 27053 insertions, 10 deletions
diff --git a/libre/icecat/PKGBUILD b/libre/icecat/PKGBUILD index f0feee2d9..9a837aac4 100644 --- a/libre/icecat/PKGBUILD +++ b/libre/icecat/PKGBUILD @@ -15,12 +15,12 @@ _pgo=true pkgname=icecat _pkgver=38.8.0-gnu1 pkgver=${_pkgver//-/_} -pkgrel=2 +pkgrel=3 pkgdesc="GNU IceCat, the standalone web browser based on Mozilla Firefox." arch=(i686 x86_64) license=(MPL GPL LGPL) -depends=(alsa-lib dbus-glib gtk2 hicolor-icon-theme hunspell icu=57.1 libevent libvpx=1.5.0 libxt mime-types mozilla-common mozilla-searchplugins nss sqlite startup-notification ttf-font) +depends=(alsa-lib dbus-glib ffmpeg gtk2 hunspell icu=57.1 libevent libvpx=1.5.0 libxt mime-types mozilla-common mozilla-searchplugins nss sqlite startup-notification ttf-font) makedepends=(diffutils gst-plugins-base-libs imake inetutils libpulse mesa python2 unzip yasm zip) options=(!emptydirs !makeflags debug) if $_pgo; then @@ -28,8 +28,7 @@ if $_pgo; then options+=(!ccache) fi optdepends=('networkmanager: Location detection via available WiFi networks' - 'gst-plugins-good: h.264 video' - 'gst-libav: h.264 video') + 'upower: Battery API') url="http://www.gnu.org/software/gnuzilla/" install=$pkgname.install source=(http://ftp.gnu.org/gnu/gnuzilla/${_pkgver%-*}/$pkgname-$_pkgver.tar.bz2{,.sig} @@ -40,12 +39,11 @@ source=(http://ftp.gnu.org/gnu/gnuzilla/${_pkgver%-*}/$pkgname-$_pkgver.tar.bz2{ gnu_headshadow.png $pkgname.desktop $pkgname-install-dir.patch - firefox-gcc-6.0.patch gcc6-fix-compilation-for-IceCat.patch mozilla-1228540-1.patch + firefox-gcc-6.0.patch gcc6-fix-compilation-for-IceCat.patch harfbuzz-1.1.3.patch mozilla-1228540-1.patch vendor.js $pkgname-fixed-loading-icon.png remove-google-play-services-support.patch disable-crypto-hardening-settings.patch) -mksha256sums=('1f58676fc0bdf60dc37145b8c97f507f0acec9bc84582aeef703cf0ed9744ed3') sha256sums=('97f76e85cc6f98463f0e0b0e845826816032770f9b589db69ece6b1cff21936c' 'SKIP' '19783b0cca336bca7c262f597acc176ca640756e7567ca6587a46b860f12ef91' @@ -55,6 +53,7 @@ sha256sums=('97f76e85cc6f98463f0e0b0e845826816032770f9b589db69ece6b1cff21936c' '5bdab2de5520fb4d3dbc453d9f73d20e0e077bf652bc780fc17184ba6c718a47' '4d1e1ddabc9e975ed39f49e134559a29e01cd49439e358233f1ede43bf5a52bf' '329cf6753d29ae64a4336a8a76ee71f0d331a39132159401e4d11de65b708a07' + '8a17454d2be90e94694818a1d1a6bdb615eced4d3a7a75af42080c99ce942f2f' 'd1ccbaf0973615c57f7893355e5cd3a89efb4e91071d0ec376e429b50cf6ed19' '977aa49b940f1da049cefa2878a63ac6669a78e63e9d55bb11db7b8f8fb64c33' '68e3a5b47c6d175cc95b98b069a15205f027cab83af9e075818d38610feb6213' @@ -78,10 +77,13 @@ prepare() { # Install to /usr/lib/$pkgname patch -Np1 -i "$srcdir/$pkgname-install-dir.patch" - # GCC 6 - patch -Np1 -i ../firefox-gcc-6.0.patch - patch -Np1 -i ../gcc6-fix-compilation-for-IceCat.patch - patch -Np1 -i ../mozilla-1228540-1.patch + # Compilation fix (FS#49243 and FS#49363), internet and Icedove package + patch -Np1 -i $srcdir/gcc6-fix-compilation-for-IceCat.patch + patch -Np1 -i $srcdir/firefox-gcc-6.0.patch + + # Update to harfbuzz 1.1.3 (following Icedove in [libre]) + patch -Np0 -i $srcdir/harfbuzz-1.1.3.patch + patch -Np1 -i $srcdir/mozilla-1228540-1.patch # Patch and remove anything that's left patch -Np1 -i "$srcdir/libre.patch" @@ -121,6 +123,9 @@ build() { # _FORTIFY_SOURCE causes configure failures CPPFLAGS+=" -O2" + # Hardening + LDFLAGS+=" -Wl,-z,now" + # GCC 6 CFLAGS+=" -fno-delete-null-pointer-checks -fno-lifetime-dse -fno-schedule-insns2" CXXFLAGS+=" -fno-delete-null-pointer-checks -fno-lifetime-dse -fno-schedule-insns2" diff --git a/libre/icecat/harfbuzz-1.1.3.patch b/libre/icecat/harfbuzz-1.1.3.patch new file mode 100644 index 000000000..98e25914d --- /dev/null +++ b/libre/icecat/harfbuzz-1.1.3.patch @@ -0,0 +1,27038 @@ +diff -uN gfx/harfbuzz/src_old/check-defs.sh gfx/harfbuzz/src/check-defs.sh +--- gfx/harfbuzz/src_old/check-defs.sh 1970-01-01 01:00:00.000000000 +0100 ++++ gfx/harfbuzz/src/check-defs.sh 2016-06-05 23:47:59.650463392 +0200 +@@ -0,0 +1,44 @@ ++#!/bin/sh ++ ++LC_ALL=C ++export LC_ALL ++ ++test -z "$srcdir" && srcdir=. ++test -z "$MAKE" && MAKE=make ++stat=0 ++ ++if which nm 2>/dev/null >/dev/null; then ++ : ++else ++ echo "check-defs.sh: 'nm' not found; skipping test" ++ exit 77 ++fi ++ ++defs="harfbuzz.def" ++$MAKE $defs > /dev/null ++tested=false ++for def in $defs; do ++ lib=`echo "$def" | sed 's/[.]def$//;s@.*/@@'` ++ so=.libs/lib${lib}.so ++ ++ EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>\| __gcov_flush\>\| llvm_' | cut -d' ' -f3`" ++ ++ if test -f "$so"; then ++ ++ echo "Checking that $so has the same symbol list as $def" ++ { ++ echo EXPORTS ++ echo "$EXPORTED_SYMBOLS" ++ # cheat: copy the last line from the def file! ++ tail -n1 "$def" ++ } | diff "$def" - >&2 || stat=1 ++ ++ tested=true ++ fi ++done ++if ! $tested; then ++ echo "check-defs.sh: libharfbuzz shared library not found; skipping test" ++ exit 77 ++fi ++ ++exit $stat +diff -uN gfx/harfbuzz/src_old/check-header-guards.sh gfx/harfbuzz/src/check-header-guards.sh +--- gfx/harfbuzz/src_old/check-header-guards.sh 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/check-header-guards.sh 2016-06-05 23:48:00.885456341 +0200 +@@ -9,13 +9,12 @@ + test "x$HBHEADERS" = x && HBHEADERS=`cd "$srcdir"; find . -maxdepth 1 -name 'hb*.h'` + test "x$HBSOURCES" = x && HBSOURCES=`cd "$srcdir"; find . -maxdepth 1 -name 'hb-*.cc' -or -name 'hb-*.hh'` + +- + for x in $HBHEADERS $HBSOURCES; do + test -f "$srcdir/$x" && x="$srcdir/$x" +- echo "$x" | grep '[^h]$' -q && continue; ++ echo "$x" | grep -q '[^h]$' && continue; + xx=`echo "$x" | sed 's@.*/@@'` + tag=`echo "$xx" | tr 'a-z.-' 'A-Z_'` +- lines=`grep "\<$tag\>" "$x" | wc -l | sed 's/[ ]*//g'` ++ lines=`grep -w "$tag" "$x" | wc -l | sed 's/[ ]*//g'` + if test "x$lines" != x3; then + echo "Ouch, header file $x does not have correct preprocessor guards" + stat=1 +diff -uN gfx/harfbuzz/src_old/check-libstdc++.sh gfx/harfbuzz/src/check-libstdc++.sh +--- gfx/harfbuzz/src_old/check-libstdc++.sh 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/check-libstdc++.sh 2016-06-05 23:48:03.413441951 +0200 +@@ -19,9 +19,9 @@ + so=.libs/libharfbuzz.$suffix + if ! test -f "$so"; then continue; fi + +- echo "Checking that we are not linking to libstdc++" +- if ldd $so | grep 'libstdc[+][+]'; then +- echo "Ouch, linked to libstdc++" ++ echo "Checking that we are not linking to libstdc++ or libc++" ++ if ldd $so | grep 'libstdc[+][+]\|libc[+][+]'; then ++ echo "Ouch, linked to libstdc++ or libc++" + stat=1 + fi + tested=true +diff -uN gfx/harfbuzz/src_old/gen-indic-table.py gfx/harfbuzz/src/gen-indic-table.py +--- gfx/harfbuzz/src_old/gen-indic-table.py 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/gen-indic-table.py 2016-06-05 23:48:08.239414549 +0200 +@@ -91,6 +91,7 @@ + "Visarga": 'Vs', + "Vowel": 'Vo', + "Vowel_Dependent": 'M', ++ "Consonant_Prefixed": 'CPrf', + "Other": 'x', + },{ + "Not_Applicable": 'x', +@@ -209,7 +210,7 @@ + for (start,end) in zip (starts, ends): + if p not in [start>>page_bits, end>>page_bits]: continue + offset = "indic_offset_0x%04xu" % start +- print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return indic_table[u - 0x%04Xu + %s];" % (start, end, start, offset) ++ print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return indic_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset) + for u,d in singles.items (): + if p != u>>page_bits: continue + print " if (unlikely (u == 0x%04Xu)) return _(%s,%s);" % (u, short[0][d[0]], short[1][d[1]]) +diff -uN gfx/harfbuzz/src_old/gen-use-table.py gfx/harfbuzz/src/gen-use-table.py +--- gfx/harfbuzz/src_old/gen-use-table.py 1970-01-01 01:00:00.000000000 +0100 ++++ gfx/harfbuzz/src/gen-use-table.py 2016-06-05 23:48:09.467407592 +0200 +@@ -0,0 +1,476 @@ ++#!/usr/bin/python ++ ++import sys ++ ++if len (sys.argv) != 5: ++ print >>sys.stderr, "usage: ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt" ++ sys.exit (1) ++ ++BLACKLISTED_BLOCKS = ["Thai", "Lao", "Tibetan"] ++ ++files = [file (x) for x in sys.argv[1:]] ++ ++headers = [[f.readline () for i in range (2)] for j,f in enumerate(files) if j != 2] ++headers.append (["UnicodeData.txt does not have a header."]) ++ ++data = [{} for f in files] ++values = [{} for f in files] ++for i, f in enumerate (files): ++ for line in f: ++ ++ j = line.find ('#') ++ if j >= 0: ++ line = line[:j] ++ ++ fields = [x.strip () for x in line.split (';')] ++ if len (fields) == 1: ++ continue ++ ++ uu = fields[0].split ('..') ++ start = int (uu[0], 16) ++ if len (uu) == 1: ++ end = start ++ else: ++ end = int (uu[1], 16) ++ ++ t = fields[1 if i != 2 else 2] ++ ++ for u in range (start, end + 1): ++ data[i][u] = t ++ values[i][t] = values[i].get (t, 0) + end - start + 1 ++ ++defaults = ('Other', 'Not_Applicable', 'Cn', 'No_Block') ++ ++# TODO Characters that are not in Unicode Indic files, but used in USE ++data[0][0x034F] = defaults[0] ++data[0][0x2060] = defaults[0] ++for u in range (0xFE00, 0xFE0F + 1): ++ data[0][u] = defaults[0] ++ ++# Merge data into one dict: ++for i,v in enumerate (defaults): ++ values[i][v] = values[i].get (v, 0) + 1 ++combined = {} ++for i,d in enumerate (data): ++ for u,v in d.items (): ++ if i >= 2 and not u in combined: ++ continue ++ if not u in combined: ++ combined[u] = list (defaults) ++ combined[u][i] = v ++combined = {k:v for k,v in combined.items() if v[3] not in BLACKLISTED_BLOCKS} ++data = combined ++del combined ++num = len (data) ++ ++ ++property_names = [ ++ # General_Category ++ 'Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu', 'Mc', ++ 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf', 'Pi', 'Po', ++ 'Ps', 'Sc', 'Sk', 'Sm', 'So', 'Zl', 'Zp', 'Zs', ++ # Indic_Syllabic_Category ++ 'Other', ++ 'Bindu', ++ 'Visarga', ++ 'Avagraha', ++ 'Nukta', ++ 'Virama', ++ 'Pure_Killer', ++ 'Invisible_Stacker', ++ 'Vowel_Independent', ++ 'Vowel_Dependent', ++ 'Vowel', ++ 'Consonant_Placeholder', ++ 'Consonant', ++ 'Consonant_Dead', ++ 'Consonant_With_Stacker', ++ 'Consonant_Prefixed', ++ 'Consonant_Preceding_Repha', ++ 'Consonant_Succeeding_Repha', ++ 'Consonant_Subjoined', ++ 'Consonant_Medial', ++ 'Consonant_Final', ++ 'Consonant_Head_Letter', ++ 'Modifying_Letter', ++ 'Tone_Letter', ++ 'Tone_Mark', ++ 'Gemination_Mark', ++ 'Cantillation_Mark', ++ 'Register_Shifter', ++ 'Syllable_Modifier', ++ 'Consonant_Killer', ++ 'Non_Joiner', ++ 'Joiner', ++ 'Number_Joiner', ++ 'Number', ++ 'Brahmi_Joining_Number', ++ # Indic_Positional_Category ++ 'Not_Applicable', ++ 'Right', ++ 'Left', ++ 'Visual_Order_Left', ++ 'Left_And_Right', ++ 'Top', ++ 'Bottom', ++ 'Top_And_Bottom', ++ 'Top_And_Right', ++ 'Top_And_Left', ++ 'Top_And_Left_And_Right', ++ 'Bottom_And_Right', ++ 'Top_And_Bottom_And_Right', ++ 'Overstruck', ++] ++ ++class PropertyValue(object): ++ def __init__(self, name_): ++ self.name = name_ ++ def __str__(self): ++ return self.name ++ def __eq__(self, other): ++ return self.name == (other if isinstance(other, basestring) else other.name) ++ def __ne__(self, other): ++ return not (self == other) ++ ++property_values = {} ++ ++for name in property_names: ++ value = PropertyValue(name) ++ assert value not in property_values ++ assert value not in globals() ++ property_values[name] = value ++globals().update(property_values) ++ ++ ++def is_BASE(U, UISC, UGC): ++ return (UISC in [Number, Consonant, Consonant_Head_Letter, ++ #SPEC-OUTDATED Consonant_Placeholder, ++ Tone_Letter] or ++ (UGC == Lo and UISC in [Avagraha, Bindu, Consonant_Final, Consonant_Medial, ++ Consonant_Subjoined, Vowel, Vowel_Dependent])) ++def is_BASE_VOWEL(U, UISC, UGC): ++ return UISC == Vowel_Independent ++def is_BASE_IND(U, UISC, UGC): ++ #SPEC-BROKEN return (UISC in [Consonant_Dead, Modifying_Letter] or UGC == Po) ++ return (UISC in [Consonant_Dead, Modifying_Letter] or ++ (UGC == Po and not is_BASE_OTHER(U, UISC, UGC))) # for 104E ++def is_BASE_NUM(U, UISC, UGC): ++ return UISC == Brahmi_Joining_Number ++def is_BASE_OTHER(U, UISC, UGC): ++ if UISC == Consonant_Placeholder: return True #SPEC-OUTDATED ++ return U in [0x00A0, 0x00D7, 0x2015, 0x2022, 0x25CC, ++ 0x25FB, 0x25FC, 0x25FD, 0x25FE] ++def is_CGJ(U, UISC, UGC): ++ return U == 0x034F ++def is_CONS_FINAL(U, UISC, UGC): ++ return ((UISC == Consonant_Final and UGC != Lo) or ++ UISC == Consonant_Succeeding_Repha) ++def is_CONS_FINAL_MOD(U, UISC, UGC): ++ #SPEC-OUTDATED return UISC in [Consonant_Final_Modifier, Syllable_Modifier] ++ return UISC == Syllable_Modifier ++def is_CONS_MED(U, UISC, UGC): ++ return UISC == Consonant_Medial and UGC != Lo ++def is_CONS_MOD(U, UISC, UGC): ++ return UISC in [Nukta, Gemination_Mark, Consonant_Killer] ++def is_CONS_SUB(U, UISC, UGC): ++ #SPEC-OUTDATED return UISC == Consonant_Subjoined ++ return UISC == Consonant_Subjoined and UGC != Lo ++def is_HALANT(U, UISC, UGC): ++ return UISC in [Virama, Invisible_Stacker] ++def is_HALANT_NUM(U, UISC, UGC): ++ return UISC == Number_Joiner ++def is_ZWNJ(U, UISC, UGC): ++ return UISC == Non_Joiner ++def is_ZWJ(U, UISC, UGC): ++ return UISC == Joiner ++def is_Word_Joiner(U, UISC, UGC): ++ return U == 0x2060 ++def is_OTHER(U, UISC, UGC): ++ #SPEC-OUTDATED return UGC == Zs # or any other SCRIPT_COMMON characters ++ return (UISC == Other ++ and not is_SYM_MOD(U, UISC, UGC) ++ and not is_CGJ(U, UISC, UGC) ++ and not is_Word_Joiner(U, UISC, UGC) ++ and not is_VARIATION_SELECTOR(U, UISC, UGC) ++ ) ++def is_Reserved(U, UISC, UGC): ++ return UGC == 'Cn' ++def is_REPHA(U, UISC, UGC): ++ #return UISC == Consonant_Preceding_Repha ++ #SPEC-OUTDATED hack to categorize Consonant_With_Stacker and Consonant_Prefixed ++ return UISC in [Consonant_Preceding_Repha, Consonant_With_Stacker, Consonant_Prefixed] ++def is_SYM(U, UISC, UGC): ++ if U == 0x25CC: return False #SPEC-OUTDATED ++ #SPEC-OUTDATED return UGC in [So, Sc] or UISC == Symbol_Letter ++ return UGC in [So, Sc] ++def is_SYM_MOD(U, UISC, UGC): ++ return U in [0x1B6B, 0x1B6C, 0x1B6D, 0x1B6E, 0x1B6F, 0x1B70, 0x1B71, 0x1B72, 0x1B73] ++def is_VARIATION_SELECTOR(U, UISC, UGC): ++ return 0xFE00 <= U <= 0xFE0F ++def is_VOWEL(U, UISC, UGC): ++ return (UISC == Pure_Killer or ++ (UGC != Lo and UISC in [Vowel, Vowel_Dependent])) ++def is_VOWEL_MOD(U, UISC, UGC): ++ return (UISC in [Tone_Mark, Cantillation_Mark, Register_Shifter, Visarga] or ++ (UGC != Lo and UISC == Bindu)) ++ ++use_mapping = { ++ 'B': is_BASE, ++ 'IV': is_BASE_VOWEL, ++ 'IND': is_BASE_IND, ++ 'N': is_BASE_NUM, ++ 'GB': is_BASE_OTHER, ++ 'CGJ': is_CGJ, ++ 'F': is_CONS_FINAL, ++ 'FM': is_CONS_FINAL_MOD, ++ 'M': is_CONS_MED, ++ 'CM': is_CONS_MOD, ++ 'SUB': is_CONS_SUB, ++ 'H': is_HALANT, ++ 'HN': is_HALANT_NUM, ++ 'ZWNJ': is_ZWNJ, ++ 'ZWJ': is_ZWJ, ++ 'WJ': is_Word_Joiner, ++ 'O': is_OTHER, ++ 'Rsv': is_Reserved, ++ 'R': is_REPHA, ++ 'S': is_SYM, ++ 'SM': is_SYM_MOD, ++ 'VS': is_VARIATION_SELECTOR, ++ 'V': is_VOWEL, ++ 'VM': is_VOWEL_MOD, ++} ++ ++use_positions = { ++ 'F': { ++ 'Abv': [Top], ++ 'Blw': [Bottom], ++ 'Pst': [Right], ++ }, ++ 'M': { ++ 'Abv': [Top], ++ 'Blw': [Bottom], ++ 'Pst': [Right], ++ 'Pre': [Left], ++ }, ++ 'CM': { ++ 'Abv': [Top], ++ 'Blw': [Bottom], ++ }, ++ 'V': { ++ 'Abv': [Top, Top_And_Bottom, Top_And_Bottom_And_Right, Top_And_Right], ++ 'Blw': [Bottom, Overstruck, Bottom_And_Right], ++ 'Pst': [Right], ++ 'Pre': [Left, Top_And_Left, Top_And_Left_And_Right, Left_And_Right], ++ }, ++ 'VM': { ++ 'Abv': [Top], ++ 'Blw': [Bottom, Overstruck], ++ 'Pst': [Right], ++ 'Pre': [Left], ++ }, ++ 'SM': { ++ 'Abv': [Top], ++ 'Blw': [Bottom], ++ }, ++ 'H': None, ++ 'B': None, ++ 'FM': None, ++ 'SUB': None, ++} ++ ++def map_to_use(data): ++ out = {} ++ items = use_mapping.items() ++ for U,(UISC,UIPC,UGC,UBlock) in data.items(): ++ ++ # Resolve Indic_Syllabic_Category ++ ++ # TODO: These don't have UISC assigned in Unicode 8.0, but ++ # have UIPC ++ if U == 0x17DD: UISC = Vowel_Dependent ++ if 0x1CE2 <= U <= 0x1CE8: UISC = Cantillation_Mark ++ ++ # TODO: U+1CED should only be allowed after some of ++ # the nasalization marks, maybe only for U+1CE9..U+1CF1. ++ if U == 0x1CED: UISC = Tone_Mark ++ ++ evals = [(k, v(U,UISC,UGC)) for k,v in items] ++ values = [k for k,v in evals if v] ++ assert len(values) == 1, "%s %s %s %s" % (hex(U), UISC, UGC, values) ++ USE = values[0] ++ ++ # Resolve Indic_Positional_Category ++ ++ # TODO: Not in Unicode 8.0 yet, but in spec. ++ if U == 0x1B6C: UIPC = Bottom ++ ++ # TODO: These should die, but have UIPC in Unicode 8.0 ++ if U in [0x953, 0x954]: UIPC = Not_Applicable ++ ++ # TODO: In USE's override list but not in Unicode 8.0 ++ if U == 0x103C: UIPC = Left ++ ++ # TODO: These are not in USE's override list that we have, nor are they in Unicode 8.0 ++ if 0xA926 <= U <= 0xA92A: UIPC = Top ++ if U == 0x111CA: UIPC = Bottom ++ if U == 0x11300: UIPC = Top ++ if U == 0x1133C: UIPC = Bottom ++ if U == 0x1171E: UIPC = Left # Correct?! ++ if 0x1CF2 <= U <= 0x1CF3: UIPC = Right ++ if 0x1CF8 <= U <= 0x1CF9: UIPC = Top ++ ++ assert (UIPC in [Not_Applicable, Visual_Order_Left] or ++ USE in use_positions), "%s %s %s %s %s" % (hex(U), UIPC, USE, UISC, UGC) ++ ++ pos_mapping = use_positions.get(USE, None) ++ if pos_mapping: ++ values = [k for k,v in pos_mapping.items() if v and UIPC in v] ++ assert len(values) == 1, "%s %s %s %s %s %s" % (hex(U), UIPC, USE, UISC, UGC, values) ++ USE = USE + values[0] ++ ++ out[U] = (USE, UBlock) ++ return out ++ ++defaults = ('O', 'No_Block') ++data = map_to_use(data) ++ ++# Remove the outliers ++singles = {} ++for u in [0x034F, 0x25CC, 0x1107F]: ++ singles[u] = data[u] ++ del data[u] ++ ++print "/* == Start of generated table == */" ++print "/*" ++print " * The following table is generated by running:" ++print " *" ++print " * ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt" ++print " *" ++print " * on files with these headers:" ++print " *" ++for h in headers: ++ for l in h: ++ print " * %s" % (l.strip()) ++print " */" ++print ++print '#include "hb-ot-shape-complex-use-private.hh"' ++print ++ ++total = 0 ++used = 0 ++last_block = None ++def print_block (block, start, end, data): ++ global total, used, last_block ++ if block and block != last_block: ++ print ++ print ++ print " /* %s */" % block ++ if start % 16: ++ print ' ' * (20 + (start % 16 * 6)), ++ num = 0 ++ assert start % 8 == 0 ++ assert (end+1) % 8 == 0 ++ for u in range (start, end+1): ++ if u % 16 == 0: ++ print ++ print " /* %04X */" % u, ++ if u in data: ++ num += 1 ++ d = data.get (u, defaults) ++ sys.stdout.write ("%6s," % d[0]) ++ ++ total += end - start + 1 ++ used += num ++ if block: ++ last_block = block ++ ++uu = data.keys () ++uu.sort () ++ ++last = -100000 ++num = 0 ++offset = 0 ++starts = [] ++ends = [] ++for k,v in sorted(use_mapping.items()): ++ if k in use_positions and use_positions[k]: continue ++ print "#define %s USE_%s /* %s */" % (k, k, v.__name__[3:]) ++for k,v in sorted(use_positions.items()): ++ if not v: continue ++ for suf in v.keys(): ++ tag = k + suf ++ print "#define %s USE_%s" % (tag, tag) ++print "" ++print "static const USE_TABLE_ELEMENT_TYPE use_table[] = {" ++for u in uu: ++ if u <= last: ++ continue ++ block = data[u][1] ++ ++ start = u//8*8 ++ end = start+1 ++ while end in uu and block == data[end][1]: ++ end += 1 ++ end = (end-1)//8*8 + 7 ++ ++ if start != last + 1: ++ if start - last <= 1+16*3: ++ print_block (None, last+1, start-1, data) ++ last = start-1 ++ else: ++ if last >= 0: ++ ends.append (last + 1) ++ offset += ends[-1] - starts[-1] ++ print ++ print ++ print "#define use_offset_0x%04xu %d" % (start, offset) ++ starts.append (start) ++ ++ print_block (block, start, end, data) ++ last = end ++ends.append (last + 1) ++offset += ends[-1] - starts[-1] ++print ++print ++occupancy = used * 100. / total ++page_bits = 12 ++print "}; /* Table items: %d; occupancy: %d%% */" % (offset, occupancy) ++print ++print "USE_TABLE_ELEMENT_TYPE" ++print "hb_use_get_categories (hb_codepoint_t u)" ++print "{" ++print " switch (u >> %d)" % page_bits ++print " {" ++pages = set([u>>page_bits for u in starts+ends+singles.keys()]) ++for p in sorted(pages): ++ print " case 0x%0Xu:" % p ++ for (start,end) in zip (starts, ends): ++ if p not in [start>>page_bits, end>>page_bits]: continue ++ offset = "use_offset_0x%04xu" % start ++ print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return use_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset) ++ for u,d in singles.items (): ++ if p != u>>page_bits: continue ++ print " if (unlikely (u == 0x%04Xu)) return %s;" % (u, d[0]) ++ print " break;" ++ print "" ++print " default:" ++print " break;" ++print " }" ++print " return USE_O;" ++print "}" ++print ++for k in sorted(use_mapping.keys()): ++ if k in use_positions and use_positions[k]: continue ++ print "#undef %s" % k ++for k,v in sorted(use_positions.items()): ++ if not v: continue ++ for suf in v.keys(): ++ tag = k + suf ++ print "#undef %s" % tag ++print ++print "/* == End of generated table == */" ++ ++# Maintain at least 50% occupancy in the table */ ++if occupancy < 50: ++ raise Exception ("Table too sparse, please investigate: ", occupancy) +diff -uN gfx/harfbuzz/src_old/harfbuzz-icu.pc gfx/harfbuzz/src/harfbuzz-icu.pc +--- gfx/harfbuzz/src_old/harfbuzz-icu.pc 1970-01-01 01:00:00.000000000 +0100 ++++ gfx/harfbuzz/src/harfbuzz-icu.pc 2016-06-05 23:48:12.049392976 +0200 +@@ -0,0 +1,13 @@ ++prefix=/usr/local ++exec_prefix=/usr/local ++libdir=/usr/local/lib ++includedir=/usr/local/include ++ ++Name: harfbuzz ++Description: HarfBuzz text shaping library ICU integration ++Version: 1.0.1 ++ ++Requires: harfbuzz ++Requires.private: icu-uc ++Libs: -L${libdir} -lharfbuzz-icu ++Cflags: -I${includedir}/harfbuzz +diff -uN gfx/harfbuzz/src_old/harfbuzz.pc gfx/harfbuzz/src/harfbuzz.pc +--- gfx/harfbuzz/src_old/harfbuzz.pc 1970-01-01 01:00:00.000000000 +0100 ++++ gfx/harfbuzz/src/harfbuzz.pc 2016-06-05 23:48:14.499379160 +0200 +@@ -0,0 +1,11 @@ ++prefix=/usr/local ++exec_prefix=/usr/local ++libdir=/usr/local/lib ++includedir=/usr/local/include ++ ++Name: harfbuzz ++Description: HarfBuzz text shaping library ++Version: 1.0.1 ++ ++Libs: -L${libdir} -lharfbuzz ++Cflags: -I${includedir}/harfbuzz +diff -uN gfx/harfbuzz/src_old/harfbuzz.pc.in gfx/harfbuzz/src/harfbuzz.pc.in +--- gfx/harfbuzz/src_old/harfbuzz.pc.in 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/harfbuzz.pc.in 2016-06-05 23:48:15.731372204 +0200 +@@ -8,4 +8,6 @@ + Version: %VERSION% + + Libs: -L${libdir} -lharfbuzz ++Libs.private: %libs_private% ++Requires.private: %requires_private% + Cflags: -I${includedir}/harfbuzz +diff -uN gfx/harfbuzz/src_old/hb-atomic-private.hh gfx/harfbuzz/src/hb-atomic-private.hh +--- gfx/harfbuzz/src_old/hb-atomic-private.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-atomic-private.hh 2016-06-05 23:48:16.918365513 +0200 +@@ -39,7 +39,11 @@ + + /* We need external help for these */ + +-#if 0 ++#if defined(hb_atomic_int_impl_add) \ ++ && defined(hb_atomic_ptr_impl_get) \ ++ && defined(hb_atomic_ptr_impl_cmpexch) ++ ++/* Defined externally, i.e. in config.h; must have typedef'ed hb_atomic_int_impl_t as well. */ + + + #elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__)) +@@ -58,11 +62,12 @@ + #endif + } + +-typedef LONG hb_atomic_int_t; +-#define hb_atomic_int_add(AI, V) InterlockedExchangeAdd (&(AI), (V)) ++typedef LONG hb_atomic_int_impl_t; ++#define HB_ATOMIC_INT_IMPL_INIT(V) (V) ++#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd (&(AI), (V)) + +-#define hb_atomic_ptr_get(P) (_HBMemoryBarrier (), (void *) *(P)) +-#define hb_atomic_ptr_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O)) ++#define hb_atomic_ptr_impl_get(P) (_HBMemoryBarrier (), (void *) *(P)) ++#define hb_atomic_ptr_impl_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O)) + + + #elif !defined(HB_NO_MT) && defined(__APPLE__) +@@ -74,28 +79,31 @@ + #include <Availability.h> + #endif + +-typedef int32_t hb_atomic_int_t; +-#define hb_atomic_int_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V)) + +-#define hb_atomic_ptr_get(P) (OSMemoryBarrier (), (void *) *(P)) ++typedef int32_t hb_atomic_int_impl_t; ++#define HB_ATOMIC_INT_IMPL_INIT(V) (V) ++#define hb_atomic_int_impl_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V)) ++ ++#define hb_atomic_ptr_impl_get(P) (OSMemoryBarrier (), (void *) *(P)) + #if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100) +-#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P)) ++#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P)) + #else + #if __ppc64__ || __x86_64__ || __aarch64__ +-#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P)) ++#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P)) + #else +-#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P)) ++#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P)) + #endif + #endif + + + #elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES) + +-typedef int hb_atomic_int_t; +-#define hb_atomic_int_add(AI, V) __sync_fetch_and_add (&(AI), (V)) ++typedef int hb_atomic_int_impl_t; ++#define HB_ATOMIC_INT_IMPL_INIT(V) (V) ++#define hb_atomic_int_impl_add(AI, V) __sync_fetch_and_add (&(AI), (V)) + +-#define hb_atomic_ptr_get(P) (void *) (__sync_synchronize (), *(P)) +-#define hb_atomic_ptr_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N)) ++#define hb_atomic_ptr_impl_get(P) (void *) (__sync_synchronize (), *(P)) ++#define hb_atomic_ptr_impl_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N)) + + + #elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS) +@@ -103,33 +111,79 @@ + #include <atomic.h> + #include <mbarrier.h> + +-typedef unsigned int hb_atomic_int_t; +-#define hb_atomic_int_add(AI, V) ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V)) ++typedef unsigned int hb_atomic_int_impl_t; ++#define HB_ATOMIC_INT_IMPL_INIT(V) (V) ++#define hb_atomic_int_impl_add(AI, V) ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V)) ++ ++#define hb_atomic_ptr_impl_get(P) ( ({__machine_rw_barrier ();}), (void *) *(P)) ++#define hb_atomic_ptr_impl_cmpexch(P,O,N) ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false) ++ ++ ++#elif !defined(HB_NO_MT) && defined(_AIX) && defined(__IBMCPP__) ++ ++#include <builtins.h> ++ ++ ++static inline int hb_fetch_and_add(volatile int* AI, unsigned int V) { ++ __lwsync(); ++ int result = __fetch_and_add(AI, V); ++ __isync(); ++ return result; ++} ++static inline int hb_compare_and_swaplp(volatile long* P, long O, long N) { ++ __sync(); ++ int result = __compare_and_swaplp (P, &O, N); ++ __sync(); ++ return result; ++} + +-#define hb_atomic_ptr_get(P) ( ({__machine_rw_barrier ();}), (void *) *(P)) +-#define hb_atomic_ptr_cmpexch(P,O,N) ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false) ++typedef int hb_atomic_int_impl_t; ++#define HB_ATOMIC_INT_IMPL_INIT(V) (V) ++#define hb_atomic_int_impl_add(AI, V) hb_fetch_and_add (&(AI), (V)) + ++#define hb_atomic_ptr_impl_get(P) (__sync(), (void *) *(P)) ++#define hb_atomic_ptr_impl_cmpexch(P,O,N) hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N)) + + #elif !defined(HB_NO_MT) + + #define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */ +-typedef volatile int hb_atomic_int_t; +-#define hb_atomic_int_add(AI, V) (((AI) += (V)) - (V)) + +-#define hb_atomic_ptr_get(P) ((void *) *(P)) +-#define hb_atomic_ptr_cmpexch(P,O,N) (* (void * volatile *) (P) == (void *) (O) ? (* (void * volatile *) (P) = (void *) (N), true) : false) ++typedef volatile int hb_atomic_int_impl_t; ++#define HB_ATOMIC_INT_IMPL_INIT(V) (V) ++#define hb_atomic_int_impl_add(AI, V) (((AI) += (V)) - (V)) ++ ++#define hb_atomic_ptr_impl_get(P) ((void *) *(P)) ++#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void * volatile *) (P) == (void *) (O) ? (* (void * volatile *) (P) = (void *) (N), true) : false) + + + #else /* HB_NO_MT */ + +-typedef int hb_atomic_int_t; +-#define hb_atomic_int_add(AI, V) (((AI) += (V)) - (V)) ++typedef int hb_atomic_int_impl_t; ++#define HB_ATOMIC_INT_IMPL_INIT(V) (V) ++#define hb_atomic_int_impl_add(AI, V) (((AI) += (V)) - (V)) ++ ++#define hb_atomic_ptr_impl_get(P) ((void *) *(P)) ++#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false) + +-#define hb_atomic_ptr_get(P) ((void *) *(P)) +-#define hb_atomic_ptr_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false) + + #endif + +-/* TODO Add tracing. */ ++ ++#define HB_ATOMIC_INT_INIT(V) {HB_ATOMIC_INT_IMPL_INIT(V)} ++ ++struct hb_atomic_int_t ++{ ++ hb_atomic_int_impl_t v; ++ ++ inline void set_unsafe (int v_) { v = v_; } ++ inline int get_unsafe (void) const { return v; } ++ inline int inc (void) { return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v), 1); } ++ inline int dec (void) { return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v), -1); } ++}; ++ ++ ++#define hb_atomic_ptr_get(P) hb_atomic_ptr_impl_get(P) ++#define hb_atomic_ptr_cmpexch(P,O,N) hb_atomic_ptr_impl_cmpexch((P),(O),(N)) ++ + + #endif /* HB_ATOMIC_PRIVATE_HH */ +diff -uN gfx/harfbuzz/src_old/hb-blob.cc gfx/harfbuzz/src/hb-blob.cc +--- gfx/harfbuzz/src_old/hb-blob.cc 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-blob.cc 2016-06-05 23:48:18.064359059 +0200 +@@ -78,8 +78,8 @@ + } + + /** +- * hb_blob_create: (Xconstructor) +- * @data: (array length=length) (closure user_data) (destroy destroy) (scope notified) (transfer none): Pointer to blob data. ++ * hb_blob_create: (skip) ++ * @data: Pointer to blob data. + * @length: Length of @data in bytes. + * @mode: Memory mode for @data. + * @user_data: Data parameter to pass to @destroy. +@@ -91,7 +91,7 @@ + * Return value: New blob, or the empty blob if something failed or if @length is + * zero. Destroy with hb_blob_destroy(). + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_blob_t * + hb_blob_create (const char *data, +@@ -147,7 +147,7 @@ + * @length is zero or @offset is beyond the end of @parent's data. Destroy + * with hb_blob_destroy(). + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_blob_t * + hb_blob_create_sub_blob (hb_blob_t *parent, +@@ -179,7 +179,7 @@ + * + * Return value: (transfer full): the empty blob. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_blob_t * + hb_blob_get_empty (void) +@@ -210,7 +210,7 @@ + * + * Return value: @blob. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_blob_t * + hb_blob_reference (hb_blob_t *blob) +@@ -228,7 +228,7 @@ + * + * See TODO:link object types for more information. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_blob_destroy (hb_blob_t *blob) +@@ -250,7 +250,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_blob_set_user_data (hb_blob_t *blob, +@@ -271,7 +271,7 @@ + * + * Return value: (transfer none): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void * + hb_blob_get_user_data (hb_blob_t *blob, +@@ -287,7 +287,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_blob_make_immutable (hb_blob_t *blob) +@@ -306,7 +306,7 @@ + * + * Return value: TODO + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_blob_is_immutable (hb_blob_t *blob) +@@ -323,7 +323,7 @@ + * + * Return value: the length of blob data in bytes. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + unsigned int + hb_blob_get_length (hb_blob_t *blob) +@@ -340,7 +340,7 @@ + * + * Returns: (transfer none) (array length=length): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + const char * + hb_blob_get_data (hb_blob_t *blob, unsigned int *length) +@@ -365,7 +365,7 @@ + * Returns: (transfer none) (array length=length): Writable blob data, + * or %NULL if failed. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + char * + hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length) +diff -uN gfx/harfbuzz/src_old/hb-blob.h gfx/harfbuzz/src/hb-blob.h +--- gfx/harfbuzz/src_old/hb-blob.h 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-blob.h 2016-06-05 23:48:19.231352500 +0200 +@@ -64,7 +64,7 @@ + + typedef struct hb_blob_t hb_blob_t; + +-hb_blob_t * ++HB_EXTERN hb_blob_t * + hb_blob_create (const char *data, + unsigned int length, + hb_memory_mode_t mode, +@@ -77,21 +77,21 @@ + * modify the parent data as that data may be + * shared among multiple sub-blobs. + */ +-hb_blob_t * ++HB_EXTERN hb_blob_t * + hb_blob_create_sub_blob (hb_blob_t *parent, + unsigned int offset, + unsigned int length); + +-hb_blob_t * ++HB_EXTERN hb_blob_t * + hb_blob_get_empty (void); + +-hb_blob_t * ++HB_EXTERN hb_blob_t * + hb_blob_reference (hb_blob_t *blob); + +-void ++HB_EXTERN void + hb_blob_destroy (hb_blob_t *blob); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_blob_set_user_data (hb_blob_t *blob, + hb_user_data_key_t *key, + void * data, +@@ -99,25 +99,25 @@ + hb_bool_t replace); + + +-void * ++HB_EXTERN void * + hb_blob_get_user_data (hb_blob_t *blob, + hb_user_data_key_t *key); + + +-void ++HB_EXTERN void + hb_blob_make_immutable (hb_blob_t *blob); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_blob_is_immutable (hb_blob_t *blob); + + +-unsigned int ++HB_EXTERN unsigned int + hb_blob_get_length (hb_blob_t *blob); + +-const char * ++HB_EXTERN const char * + hb_blob_get_data (hb_blob_t *blob, unsigned int *length); + +-char * ++HB_EXTERN char * + hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length); + + +diff -uN gfx/harfbuzz/src_old/hb-buffer.cc gfx/harfbuzz/src/hb-buffer.cc +--- gfx/harfbuzz/src_old/hb-buffer.cc 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-buffer.cc 2016-06-05 23:48:28.261301901 +0200 +@@ -35,7 +35,28 @@ + #define HB_DEBUG_BUFFER (HB_DEBUG+0) + #endif + ++/** ++ * SECTION: hb-buffer ++ * @title: Buffers ++ * @short_description: Input and output buffers ++ * @include: hb.h ++ * ++ * Buffers serve dual role in HarfBuzz; they hold the input characters that are ++ * passed hb_shape(), and after shaping they hold the output glyphs. ++ **/ + ++/** ++ * hb_segment_properties_equal: ++ * @a: first #hb_segment_properties_t to compare. ++ * @b: second #hb_segment_properties_t to compare. ++ * ++ * Checks the equality of two #hb_segment_properties_t's. ++ * ++ * Return value: (transfer full): ++ * %true if all properties of @a equal those of @b, false otherwise. ++ * ++ * Since: 0.9.7 ++ **/ + hb_bool_t + hb_segment_properties_equal (const hb_segment_properties_t *a, + const hb_segment_properties_t *b) +@@ -48,6 +69,17 @@ + + } + ++/** ++ * hb_segment_properties_hash: ++ * @p: #hb_segment_properties_t to hash. ++ * ++ * Creates a hash representing @p. ++ * ++ * Return value: ++ * A hash of @p. ++ * ++ * Since: 0.9.7 ++ **/ + unsigned int + hb_segment_properties_hash (const hb_segment_properties_t *p) + { +@@ -85,6 +117,11 @@ + { + if (unlikely (in_error)) + return false; ++ if (unlikely (size > max_len)) ++ { ++ in_error = true; ++ return false; ++ } + + unsigned int new_allocated = allocated; + hb_glyph_position_t *new_pos = NULL; +@@ -192,6 +229,7 @@ + + hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT; + props = default_props; ++ scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; + + content_type = HB_BUFFER_CONTENT_TYPE_INVALID; + in_error = false; +@@ -443,7 +481,7 @@ + { + unsigned int i, j; + +- if (start == end - 1) ++ if (end - start < 2) + return; + + for (i = start, j = end - 1; i < j; i++, j--) { +@@ -454,7 +492,7 @@ + info[j] = t; + } + +- if (pos) { ++ if (have_positions) { + for (i = start, j = end - 1; i < j; i++, j--) { + hb_glyph_position_t t; + +@@ -498,14 +536,10 @@ + } + + void +-hb_buffer_t::merge_clusters (unsigned int start, +- unsigned int end) ++hb_buffer_t::merge_clusters_impl (unsigned int start, ++ unsigned int end) + { +-#ifdef HB_NO_MERGE_CLUSTERS +- return; +-#endif +- +- if (unlikely (end - start < 2)) ++ if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS) + return; + + unsigned int cluster = info[start].cluster; +@@ -523,7 +557,7 @@ + + /* If we hit the start of buffer, continue in out-buffer. */ + if (idx == start) +- for (unsigned i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--) ++ for (unsigned int i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--) + out_info[i - 1].cluster = cluster; + + for (unsigned int i = start; i < end; i++) +@@ -533,9 +567,8 @@ + hb_buffer_t::merge_out_clusters (unsigned int start, + unsigned int end) + { +-#ifdef HB_NO_MERGE_CLUSTERS +- return; +-#endif ++ if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS) ++ return; + + if (unlikely (end - start < 2)) + return; +@@ -555,12 +588,44 @@ + + /* If we hit the end of out-buffer, continue in buffer. */ + if (end == out_len) +- for (unsigned i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++) ++ for (unsigned int i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++) + info[i].cluster = cluster; + + for (unsigned int i = start; i < end; i++) + out_info[i].cluster = cluster; + } ++void ++hb_buffer_t::delete_glyph () ++{ ++ unsigned int cluster = info[idx].cluster; ++ if (idx + 1 < len && cluster == info[idx + 1].cluster) ++ { ++ /* Cluster survives; do nothing. */ ++ goto done; ++ } ++ ++ if (out_len) ++ { ++ /* Merge cluster backward. */ ++ if (cluster < out_info[out_len - 1].cluster) ++ { ++ unsigned int old_cluster = out_info[out_len - 1].cluster; ++ for (unsigned i = out_len; i && out_info[i - 1].cluster == old_cluster; i--) ++ out_info[i - 1].cluster = cluster; ++ } ++ goto done; ++ } ++ ++ if (idx + 1 < len) ++ { ++ /* Merge cluster forward. */ ++ merge_clusters (idx, idx + 2); ++ goto done; ++ } ++ ++done: ++ skip_glyph (); ++} + + void + hb_buffer_t::guess_segment_properties (void) +@@ -667,11 +732,16 @@ + /** + * hb_buffer_create: (Xconstructor) + * +- * ++ * Creates a new #hb_buffer_t with all properties to defaults. + * +- * Return value: (transfer full) ++ * Return value: (transfer full): ++ * A newly allocated #hb_buffer_t with a reference count of 1. The initial ++ * reference count should be released with hb_buffer_destroy() when you are done ++ * using the #hb_buffer_t. This function never returns %NULL. If memory cannot ++ * be allocated, a special #hb_buffer_t object will be returned on which ++ * hb_buffer_allocation_successful() returns %false. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_buffer_t * + hb_buffer_create (void) +@@ -681,6 +751,8 @@ + if (!(buffer = hb_object_create<hb_buffer_t> ())) + return hb_buffer_get_empty (); + ++ buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT; ++ + buffer->reset (); + + return buffer; +@@ -693,7 +765,7 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_buffer_t * + hb_buffer_get_empty (void) +@@ -703,7 +775,10 @@ + + const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil), + HB_BUFFER_FLAG_DEFAULT, ++ HB_BUFFER_CLUSTER_LEVEL_DEFAULT, + HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT, ++ HB_BUFFER_SCRATCH_FLAG_DEFAULT, ++ HB_BUFFER_MAX_LEN_DEFAULT, + + HB_BUFFER_CONTENT_TYPE_INVALID, + HB_SEGMENT_PROPERTIES_DEFAULT, +@@ -719,13 +794,15 @@ + + /** + * hb_buffer_reference: (skip) +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * Increases the reference count on @buffer by one. This prevents @buffer from ++ * being destroyed until a matching call to hb_buffer_destroy() is made. + * + * Return value: (transfer full): ++ * The referenced #hb_buffer_t. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_buffer_t * + hb_buffer_reference (hb_buffer_t *buffer) +@@ -735,11 +812,13 @@ + + /** + * hb_buffer_destroy: (skip) +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * Deallocate the @buffer. ++ * Decreases the reference count on @buffer by one. If the result is zero, then ++ * @buffer and all associated resources are freed. See hb_buffer_reference(). + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_buffer_destroy (hb_buffer_t *buffer) +@@ -750,13 +829,15 @@ + + free (buffer->info); + free (buffer->pos); ++ if (buffer->message_destroy) ++ buffer->message_destroy (buffer->message_data); + + free (buffer); + } + + /** + * hb_buffer_set_user_data: (skip) +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * @key: + * @data: + * @destroy: +@@ -766,7 +847,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_buffer_set_user_data (hb_buffer_t *buffer, +@@ -780,14 +861,14 @@ + + /** + * hb_buffer_get_user_data: (skip) +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * @key: + * + * + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void * + hb_buffer_get_user_data (hb_buffer_t *buffer, +@@ -799,12 +880,13 @@ + + /** + * hb_buffer_set_content_type: +- * @buffer: a buffer. +- * @content_type: ++ * @buffer: an #hb_buffer_t. ++ * @content_type: the type of buffer contents to set + * +- * ++ * Sets the type of @buffer contents, buffers are either empty, contain ++ * characters (before shaping) or glyphs (the result of shaping). + * +- * Since: 1.0 ++ * Since: 0.9.5 + **/ + void + hb_buffer_set_content_type (hb_buffer_t *buffer, +@@ -815,13 +897,14 @@ + + /** + * hb_buffer_get_content_type: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * see hb_buffer_set_content_type(). + * +- * Return value: ++ * Return value: ++ * The type of @buffer contents. + * +- * Since: 1.0 ++ * Since: 0.9.5 + **/ + hb_buffer_content_type_t + hb_buffer_get_content_type (hb_buffer_t *buffer) +@@ -832,12 +915,12 @@ + + /** + * hb_buffer_set_unicode_funcs: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * @unicode_funcs: + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, +@@ -857,13 +940,13 @@ + + /** + * hb_buffer_get_unicode_funcs: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * + * + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_unicode_funcs_t * + hb_buffer_get_unicode_funcs (hb_buffer_t *buffer) +@@ -873,12 +956,18 @@ + + /** + * hb_buffer_set_direction: +- * @buffer: a buffer. +- * @direction: ++ * @buffer: an #hb_buffer_t. ++ * @direction: the #hb_direction_t of the @buffer + * +- * ++ * Set the text flow direction of the buffer. No shaping can happen without ++ * setting @buffer direction, and it controls the visual direction for the ++ * output glyphs; for RTL direction the glyphs will be reversed. Many layout ++ * features depend on the proper setting of the direction, for example, ++ * reversing RTL text before shaping, then shaping with LTR direction is not ++ * the same as keeping the text in logical order and shaping with RTL ++ * direction. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_buffer_set_direction (hb_buffer_t *buffer, +@@ -893,13 +982,14 @@ + + /** + * hb_buffer_get_direction: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * See hb_buffer_set_direction() + * +- * Return value: ++ * Return value: ++ * The direction of the @buffer. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_direction_t + hb_buffer_get_direction (hb_buffer_t *buffer) +@@ -909,12 +999,20 @@ + + /** + * hb_buffer_set_script: +- * @buffer: a buffer. +- * @script: ++ * @buffer: an #hb_buffer_t. ++ * @script: an #hb_script_t to set. + * +- * ++ * Sets the script of @buffer to @script. + * +- * Since: 1.0 ++ * Script is crucial for choosing the proper shaping behaviour for scripts that ++ * require it (e.g. Arabic) and the which OpenType features defined in the font ++ * to be applied. ++ * ++ * You can pass one of the predefined #hb_script_t values, or use ++ * hb_script_from_string() or hb_script_from_iso15924_tag() to get the ++ * corresponding script from an ISO 15924 script tag. ++ * ++ * Since: 0.9.2 + **/ + void + hb_buffer_set_script (hb_buffer_t *buffer, +@@ -928,13 +1026,14 @@ + + /** + * hb_buffer_get_script: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * See hb_buffer_set_script(). + * +- * Return value: ++ * Return value: ++ * The #hb_script_t of the @buffer. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_script_t + hb_buffer_get_script (hb_buffer_t *buffer) +@@ -944,12 +1043,20 @@ + + /** + * hb_buffer_set_language: +- * @buffer: a buffer. +- * @language: ++ * @buffer: an #hb_buffer_t. ++ * @language: an hb_language_t to set. + * +- * ++ * Sets the language of @buffer to @language. ++ * ++ * Languages are crucial for selecting which OpenType feature to apply to the ++ * buffer which can result in applying language-specific behaviour. Languages ++ * are orthogonal to the scripts, and though they are related, they are ++ * different concepts and should not be confused with each other. ++ * ++ * Use hb_language_from_string() to convert from ISO 639 language codes to ++ * #hb_language_t. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_buffer_set_language (hb_buffer_t *buffer, +@@ -963,13 +1070,14 @@ + + /** + * hb_buffer_get_language: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * See hb_buffer_set_language(). + * +- * Return value: ++ * Return value: (transfer none): ++ * The #hb_language_t of the buffer. Must not be freed by the caller. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_language_t + hb_buffer_get_language (hb_buffer_t *buffer) +@@ -979,12 +1087,14 @@ + + /** + * hb_buffer_set_segment_properties: +- * @buffer: a buffer. +- * @props: ++ * @buffer: an #hb_buffer_t. ++ * @props: an #hb_segment_properties_t to use. + * +- * ++ * Sets the segment properties of the buffer, a shortcut for calling ++ * hb_buffer_set_direction(), hb_buffer_set_script() and ++ * hb_buffer_set_language() individually. + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + void + hb_buffer_set_segment_properties (hb_buffer_t *buffer, +@@ -998,12 +1108,12 @@ + + /** + * hb_buffer_get_segment_properties: +- * @buffer: a buffer. +- * @props: ++ * @buffer: an #hb_buffer_t. ++ * @props: (out): the output #hb_segment_properties_t. + * +- * ++ * Sets @props to the #hb_segment_properties_t of @buffer. + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + void + hb_buffer_get_segment_properties (hb_buffer_t *buffer, +@@ -1015,12 +1125,12 @@ + + /** + * hb_buffer_set_flags: +- * @buffer: a buffer. +- * @flags: ++ * @buffer: an #hb_buffer_t. ++ * @flags: the buffer flags to set. + * +- * ++ * Sets @buffer flags to @flags. See #hb_buffer_flags_t. + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + void + hb_buffer_set_flags (hb_buffer_t *buffer, +@@ -1034,13 +1144,14 @@ + + /** + * hb_buffer_get_flags: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * See hb_buffer_set_flags(). + * + * Return value: ++ * The @buffer flags. + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + hb_buffer_flags_t + hb_buffer_get_flags (hb_buffer_t *buffer) +@@ -1048,15 +1159,53 @@ + return buffer->flags; + } + ++/** ++ * hb_buffer_set_cluster_level: ++ * @buffer: an #hb_buffer_t. ++ * @cluster_level: ++ * ++ * ++ * ++ * Since: 0.9.42 ++ **/ ++void ++hb_buffer_set_cluster_level (hb_buffer_t *buffer, ++ hb_buffer_cluster_level_t cluster_level) ++{ ++ if (unlikely (hb_object_is_inert (buffer))) ++ return; ++ ++ buffer->cluster_level = cluster_level; ++} ++ ++/** ++ * hb_buffer_get_cluster_level: ++ * @buffer: an #hb_buffer_t. ++ * ++ * ++ * ++ * Return value: ++ * ++ * Since: 0.9.42 ++ **/ ++hb_buffer_cluster_level_t ++hb_buffer_get_cluster_level (hb_buffer_t *buffer) ++{ ++ return buffer->cluster_level; ++} ++ + + /** + * hb_buffer_set_replacement_codepoint: +- * @buffer: a buffer. +- * @replacement: ++ * @buffer: an #hb_buffer_t. ++ * @replacement: the replacement #hb_codepoint_t + * +- * ++ * Sets the #hb_codepoint_t that replaces invalid entries for a given encoding ++ * when adding text to @buffer. + * +- * Since: 1.0 ++ * Default is %HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT. ++ * ++ * Since: 0.9.31 + **/ + void + hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer, +@@ -1070,13 +1219,14 @@ + + /** + * hb_buffer_get_replacement_codepoint: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * See hb_buffer_set_replacement_codepoint(). + * + * Return value: ++ * The @buffer replacement #hb_codepoint_t. + * +- * Since: 1.0 ++ * Since: 0.9.31 + **/ + hb_codepoint_t + hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer) +@@ -1087,11 +1237,12 @@ + + /** + * hb_buffer_reset: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * Resets the buffer to its initial status, as if it was just newly created ++ * with hb_buffer_create(). + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_buffer_reset (hb_buffer_t *buffer) +@@ -1101,11 +1252,12 @@ + + /** + * hb_buffer_clear_contents: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * Similar to hb_buffer_reset(), but does not clear the Unicode functions and ++ * the replacement code point. + * +- * Since: 1.0 ++ * Since: 0.9.11 + **/ + void + hb_buffer_clear_contents (hb_buffer_t *buffer) +@@ -1115,14 +1267,15 @@ + + /** + * hb_buffer_pre_allocate: +- * @buffer: a buffer. +- * @size: ++ * @buffer: an #hb_buffer_t. ++ * @size: number of items to pre allocate. + * +- * ++ * Pre allocates memory for @buffer to fit at least @size number of items. + * +- * Return value: ++ * Return value: ++ * %true if @buffer memory allocation succeeded, %false otherwise. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size) +@@ -1132,13 +1285,14 @@ + + /** + * hb_buffer_allocation_successful: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * Check if allocating memory for the buffer succeeded. + * +- * Return value: ++ * Return value: ++ * %true if @buffer memory allocation succeeded, %false otherwise. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_buffer_allocation_successful (hb_buffer_t *buffer) +@@ -1148,13 +1302,20 @@ + + /** + * hb_buffer_add: +- * @buffer: a buffer. +- * @codepoint: +- * @cluster: ++ * @buffer: an #hb_buffer_t. ++ * @codepoint: a Unicode code point. ++ * @cluster: the cluster value of @codepoint. ++ * ++ * Appends a character with the Unicode value of @codepoint to @buffer, and ++ * gives it the initial cluster value of @cluster. Clusters can be any thing ++ * the client wants, they are usually used to refer to the index of the ++ * character in the input text stream and are output in ++ * #hb_glyph_info_t.cluster field. + * +- * ++ * This function does not check the validity of @codepoint, it is up to the ++ * caller to ensure it is a valid Unicode code point. + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + void + hb_buffer_add (hb_buffer_t *buffer, +@@ -1167,14 +1328,16 @@ + + /** + * hb_buffer_set_length: +- * @buffer: a buffer. +- * @length: ++ * @buffer: an #hb_buffer_t. ++ * @length: the new length of @buffer. + * +- * ++ * Similar to hb_buffer_pre_allocate(), but clears any new items added at the ++ * end. + * + * Return value: ++ * %true if @buffer memory allocation succeeded, %false otherwise. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_buffer_set_length (hb_buffer_t *buffer, +@@ -1207,13 +1370,15 @@ + + /** + * hb_buffer_get_length: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * + * Returns the number of items in the buffer. + * +- * Return value: buffer length. ++ * Return value: ++ * The @buffer length. ++ * The value valid as long as buffer has not been modified. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + unsigned int + hb_buffer_get_length (hb_buffer_t *buffer) +@@ -1223,15 +1388,17 @@ + + /** + * hb_buffer_get_glyph_infos: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * @length: (out): output array length. + * +- * Returns buffer glyph information array. Returned pointer +- * is valid as long as buffer contents are not modified. ++ * Returns @buffer glyph information array. Returned pointer ++ * is valid as long as @buffer contents are not modified. + * +- * Return value: (transfer none) (array length=length): buffer glyph information array. ++ * Return value: (transfer none) (array length=length): ++ * The @buffer glyph information array. ++ * The value valid as long as buffer has not been modified. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_glyph_info_t * + hb_buffer_get_glyph_infos (hb_buffer_t *buffer, +@@ -1245,15 +1412,17 @@ + + /** + * hb_buffer_get_glyph_positions: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * @length: (out): output length. + * +- * Returns buffer glyph position array. Returned pointer +- * is valid as long as buffer contents are not modified. ++ * Returns @buffer glyph position array. Returned pointer ++ * is valid as long as @buffer contents are not modified. + * +- * Return value: (transfer none) (array length=length): buffer glyph position array. ++ * Return value: (transfer none) (array length=length): ++ * The @buffer glyph position array. ++ * The value valid as long as buffer has not been modified. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_glyph_position_t * + hb_buffer_get_glyph_positions (hb_buffer_t *buffer, +@@ -1270,11 +1439,11 @@ + + /** + * hb_buffer_reverse: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * + * Reverses buffer contents. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_buffer_reverse (hb_buffer_t *buffer) +@@ -1283,14 +1452,31 @@ + } + + /** ++ * hb_buffer_reverse_range: ++ * @buffer: an #hb_buffer_t. ++ * @start: start index. ++ * @end: end index. ++ * ++ * Reverses buffer contents between start to end. ++ * ++ * Since: 0.9.41 ++ **/ ++void ++hb_buffer_reverse_range (hb_buffer_t *buffer, ++ unsigned int start, unsigned int end) ++{ ++ buffer->reverse_range (start, end); ++} ++ ++/** + * hb_buffer_reverse_clusters: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * + * Reverses buffer clusters. That is, the buffer contents are + * reversed, then each cluster (consecutive items having the + * same cluster number) are reversed again. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_buffer_reverse_clusters (hb_buffer_t *buffer) +@@ -1300,7 +1486,7 @@ + + /** + * hb_buffer_guess_segment_properties: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * + * Sets unset buffer segment properties based on buffer Unicode + * contents. If buffer is not empty, it must have content type +@@ -1320,7 +1506,7 @@ + * hb_language_get_default(). This may change in the future by + * taking buffer script into consideration when choosing a language. + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + void + hb_buffer_guess_segment_properties (hb_buffer_t *buffer) +@@ -1328,15 +1514,15 @@ + buffer->guess_segment_properties (); + } + +-template <bool validate, typename T> ++template <typename utf_t> + static inline void + hb_buffer_add_utf (hb_buffer_t *buffer, +- const T *text, ++ const typename utf_t::codepoint_t *text, + int text_length, + unsigned int item_offset, + int item_length) + { +- typedef hb_utf_t<T, true> utf_t; ++ typedef typename utf_t::codepoint_t T; + const hb_codepoint_t replacement = buffer->replacement; + + assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE || +@@ -1399,15 +1585,20 @@ + + /** + * hb_buffer_add_utf8: +- * @buffer: a buffer. +- * @text: (array length=text_length): +- * @text_length: +- * @item_offset: +- * @item_length: ++ * @buffer: an #hb_buffer_t. ++ * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8 ++ * characters to append. ++ * @text_length: the length of the @text, or -1 if it is %NULL terminated. ++ * @item_offset: the offset of the first character to add to the @buffer. ++ * @item_length: the number of characters to add to the @buffer, or -1 for the ++ * end of @text (assuming it is %NULL terminated). + * +- * ++ * See hb_buffer_add_codepoints(). + * +- * Since: 1.0 ++ * Replaces invalid UTF-8 characters with the @buffer replacement code point, ++ * see hb_buffer_set_replacement_codepoint(). ++ * ++ * Since: 0.9.2 + **/ + void + hb_buffer_add_utf8 (hb_buffer_t *buffer, +@@ -1416,20 +1607,24 @@ + unsigned int item_offset, + int item_length) + { +- hb_buffer_add_utf<true> (buffer, (const uint8_t *) text, text_length, item_offset, item_length); ++ hb_buffer_add_utf<hb_utf8_t> (buffer, (const uint8_t *) text, text_length, item_offset, item_length); + } + + /** + * hb_buffer_add_utf16: +- * @buffer: a buffer. +- * @text: (array length=text_length): +- * @text_length: +- * @item_offset: +- * @item_length: ++ * @buffer: an #hb_buffer_t. ++ * @text: (array length=text_length): an array of UTF-16 characters to append. ++ * @text_length: the length of the @text, or -1 if it is %NULL terminated. ++ * @item_offset: the offset of the first character to add to the @buffer. ++ * @item_length: the number of characters to add to the @buffer, or -1 for the ++ * end of @text (assuming it is %NULL terminated). + * +- * ++ * See hb_buffer_add_codepoints(). + * +- * Since: 1.0 ++ * Replaces invalid UTF-16 characters with the @buffer replacement code point, ++ * see hb_buffer_set_replacement_codepoint(). ++ * ++ * Since: 0.9.2 + **/ + void + hb_buffer_add_utf16 (hb_buffer_t *buffer, +@@ -1438,20 +1633,24 @@ + unsigned int item_offset, + int item_length) + { +- hb_buffer_add_utf<true> (buffer, text, text_length, item_offset, item_length); ++ hb_buffer_add_utf<hb_utf16_t> (buffer, text, text_length, item_offset, item_length); + } + + /** + * hb_buffer_add_utf32: +- * @buffer: a buffer. +- * @text: (array length=text_length): +- * @text_length: +- * @item_offset: +- * @item_length: ++ * @buffer: an #hb_buffer_t. ++ * @text: (array length=text_length): an array of UTF-32 characters to append. ++ * @text_length: the length of the @text, or -1 if it is %NULL terminated. ++ * @item_offset: the offset of the first character to add to the @buffer. ++ * @item_length: the number of characters to add to the @buffer, or -1 for the ++ * end of @text (assuming it is %NULL terminated). + * +- * ++ * See hb_buffer_add_codepoints(). + * +- * Since: 1.0 ++ * Replaces invalid UTF-32 characters with the @buffer replacement code point, ++ * see hb_buffer_set_replacement_codepoint(). ++ * ++ * Since: 0.9.2 + **/ + void + hb_buffer_add_utf32 (hb_buffer_t *buffer, +@@ -1460,20 +1659,59 @@ + unsigned int item_offset, + int item_length) + { +- hb_buffer_add_utf<true> (buffer, text, text_length, item_offset, item_length); ++ hb_buffer_add_utf<hb_utf32_t<> > (buffer, text, text_length, item_offset, item_length); ++} ++ ++/** ++ * hb_buffer_add_latin1: ++ * @buffer: an #hb_buffer_t. ++ * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8 ++ * characters to append. ++ * @text_length: the length of the @text, or -1 if it is %NULL terminated. ++ * @item_offset: the offset of the first character to add to the @buffer. ++ * @item_length: the number of characters to add to the @buffer, or -1 for the ++ * end of @text (assuming it is %NULL terminated). ++ * ++ * Similar to hb_buffer_add_codepoints(), but allows only access to first 256 ++ * Unicode code points that can fit in 8-bit strings. ++ * ++ * <note>Has nothing to do with non-Unicode Latin-1 encoding.</note> ++ * ++ * Since: 0.9.39 ++ **/ ++void ++hb_buffer_add_latin1 (hb_buffer_t *buffer, ++ const uint8_t *text, ++ int text_length, ++ unsigned int item_offset, ++ int item_length) ++{ ++ hb_buffer_add_utf<hb_latin1_t> (buffer, text, text_length, item_offset, item_length); + } + + /** + * hb_buffer_add_codepoints: +- * @buffer: a buffer. +- * @text: (array length=text_length): +- * @text_length: +- * @item_offset: +- * @item_length: ++ * @buffer: a #hb_buffer_t to append characters to. ++ * @text: (array length=text_length): an array of Unicode code points to append. ++ * @text_length: the length of the @text, or -1 if it is %NULL terminated. ++ * @item_offset: the offset of the first code point to add to the @buffer. ++ * @item_length: the number of code points to add to the @buffer, or -1 for the ++ * end of @text (assuming it is %NULL terminated). ++ * ++ * Appends characters from @text array to @buffer. The @item_offset is the ++ * position of the first character from @text that will be appended, and ++ * @item_length is the number of character. When shaping part of a larger text ++ * (e.g. a run of text from a paragraph), instead of passing just the substring ++ * corresponding to the run, it is preferable to pass the whole ++ * paragraph and specify the run start and length as @item_offset and ++ * @item_length, respectively, to give HarfBuzz the full context to be able, ++ * for example, to do cross-run Arabic shaping or properly handle combining ++ * marks at stat of run. + * +- * ++ * This function does not check the validity of @text, it is up to the caller ++ * to ensure it contains a valid Unicode code points. + * +- * Since: 1.0 ++ * Since: 0.9.31 + **/ + void + hb_buffer_add_codepoints (hb_buffer_t *buffer, +@@ -1482,7 +1720,7 @@ + unsigned int item_offset, + int item_length) + { +- hb_buffer_add_utf<false> (buffer, text, text_length, item_offset, item_length); ++ hb_buffer_add_utf<hb_utf32_t<false> > (buffer, text, text_length, item_offset, item_length); + } + + +@@ -1528,7 +1766,7 @@ + pos[end - 1].x_advance = total_x_advance; + pos[end - 1].y_advance = total_y_advance; + +- hb_bubble_sort (buffer->info + start, end - start - 1, compare_info_codepoint, buffer->pos + start); ++ hb_stable_sort (buffer->info + start, end - start - 1, compare_info_codepoint, buffer->pos + start); + } else { + /* Transfer all cluster advance to the first glyph. */ + pos[start].x_advance += total_x_advance; +@@ -1537,17 +1775,20 @@ + pos[i].x_offset -= total_x_advance; + pos[i].y_offset -= total_y_advance; + } +- hb_bubble_sort (buffer->info + start + 1, end - start - 1, compare_info_codepoint, buffer->pos + start + 1); ++ hb_stable_sort (buffer->info + start + 1, end - start - 1, compare_info_codepoint, buffer->pos + start + 1); + } + } + + /** + * hb_buffer_normalize_glyphs: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * Reorders a glyph buffer to have canonical in-cluster glyph order / position. ++ * The resulting clusters should behave identical to pre-reordering clusters. + * +- * Since: 1.0 ++ * <note>This has nothing to do with Unicode normalization.</note> ++ * ++ * Since: 0.9.2 + **/ + void + hb_buffer_normalize_glyphs (hb_buffer_t *buffer) +@@ -1570,3 +1811,66 @@ + } + normalize_glyphs_cluster (buffer, start, end, backward); + } ++ ++void ++hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *)) ++{ ++ assert (!have_positions); ++ for (unsigned int i = start + 1; i < end; i++) ++ { ++ unsigned int j = i; ++ while (j > start && compar (&info[j - 1], &info[i]) > 0) ++ j--; ++ if (i == j) ++ continue; ++ /* Move item i to occupy place for item j, shift what's in between. */ ++ merge_clusters (j, i + 1); ++ { ++ hb_glyph_info_t t = info[i]; ++ memmove (&info[j + 1], &info[j], (i - j) * sizeof (hb_glyph_info_t)); ++ info[j] = t; ++ } ++ } ++} ++ ++/* ++ * Debugging. ++ */ ++ ++/** ++ * hb_buffer_set_message_func: ++ * @buffer: an #hb_buffer_t. ++ * @func: (closure user_data) (destroy destroy) (scope notified): ++ * @user_data: ++ * @destroy: ++ * ++ * ++ * ++ * Since: 1.1.3 ++ **/ ++void ++hb_buffer_set_message_func (hb_buffer_t *buffer, ++ hb_buffer_message_func_t func, ++ void *user_data, hb_destroy_func_t destroy) ++{ ++ if (buffer->message_destroy) ++ buffer->message_destroy (buffer->message_data); ++ ++ if (func) { ++ buffer->message_func = func; ++ buffer->message_data = user_data; ++ buffer->message_destroy = destroy; ++ } else { ++ buffer->message_func = NULL; ++ buffer->message_data = NULL; ++ buffer->message_destroy = NULL; ++ } ++} ++ ++bool ++hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap) ++{ ++ char buf[100]; ++ vsnprintf (buf, sizeof (buf), fmt, ap); ++ return (bool) this->message_func (this, font, buf, this->message_data); ++} +diff -uN gfx/harfbuzz/src_old/hb-buffer-deserialize-json.hh gfx/harfbuzz/src/hb-buffer-deserialize-json.hh +--- gfx/harfbuzz/src_old/hb-buffer-deserialize-json.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-buffer-deserialize-json.hh 2016-06-05 23:48:20.553345078 +0200 +@@ -1,5 +1,5 @@ + +-#line 1 "../../src/hb-buffer-deserialize-json.rl" ++#line 1 "hb-buffer-deserialize-json.rl" + /* + * Copyright © 2013 Google, Inc. + * +@@ -32,7 +32,7 @@ + #include "hb-private.hh" + + +-#line 36 "hb-buffer-deserialize-json.hh.tmp" ++#line 36 "hb-buffer-deserialize-json.hh" + static const unsigned char _deserialize_json_trans_keys[] = { + 0u, 0u, 9u, 123u, 9u, 34u, 97u, 103u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, + 48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, +@@ -435,7 +435,7 @@ + static const int deserialize_json_en_main = 1; + + +-#line 97 "../../src/hb-buffer-deserialize-json.rl" ++#line 97 "hb-buffer-deserialize-json.rl" + + + static hb_bool_t +@@ -459,15 +459,15 @@ + + const char *tok = NULL; + int cs; +- hb_glyph_info_t info; +- hb_glyph_position_t pos; ++ hb_glyph_info_t info = {0}; ++ hb_glyph_position_t pos = {0}; + +-#line 466 "hb-buffer-deserialize-json.hh.tmp" ++#line 466 "hb-buffer-deserialize-json.hh" + { + cs = deserialize_json_start; + } + +-#line 471 "hb-buffer-deserialize-json.hh.tmp" ++#line 471 "hb-buffer-deserialize-json.hh" + { + int _slen; + int _trans; +@@ -493,14 +493,14 @@ + + switch ( _deserialize_json_trans_actions[_trans] ) { + case 1: +-#line 38 "../../src/hb-buffer-deserialize-json.rl" ++#line 38 "hb-buffer-deserialize-json.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); + } + break; + case 5: +-#line 43 "../../src/hb-buffer-deserialize-json.rl" ++#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) +@@ -510,13 +510,13 @@ + } + break; + case 2: +-#line 51 "../../src/hb-buffer-deserialize-json.rl" ++#line 51 "hb-buffer-deserialize-json.rl" + { + tok = p; + } + break; + case 14: +-#line 55 "../../src/hb-buffer-deserialize-json.rl" ++#line 55 "hb-buffer-deserialize-json.rl" + { + if (!hb_font_glyph_from_string (font, + tok, p - tok, +@@ -525,33 +525,33 @@ + } + break; + case 15: +-#line 62 "../../src/hb-buffer-deserialize-json.rl" ++#line 62 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.codepoint)) return false; } + break; + case 8: +-#line 63 "../../src/hb-buffer-deserialize-json.rl" ++#line 63 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } + break; + case 10: +-#line 64 "../../src/hb-buffer-deserialize-json.rl" ++#line 64 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_offset )) return false; } + break; + case 12: +-#line 65 "../../src/hb-buffer-deserialize-json.rl" ++#line 65 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } + break; + case 3: +-#line 66 "../../src/hb-buffer-deserialize-json.rl" ++#line 66 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } + break; + case 6: +-#line 67 "../../src/hb-buffer-deserialize-json.rl" ++#line 67 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } + break; + case 16: +-#line 62 "../../src/hb-buffer-deserialize-json.rl" ++#line 62 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.codepoint)) return false; } +-#line 43 "../../src/hb-buffer-deserialize-json.rl" ++#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) +@@ -561,9 +561,9 @@ + } + break; + case 9: +-#line 63 "../../src/hb-buffer-deserialize-json.rl" ++#line 63 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } +-#line 43 "../../src/hb-buffer-deserialize-json.rl" ++#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) +@@ -573,9 +573,9 @@ + } + break; + case 11: +-#line 64 "../../src/hb-buffer-deserialize-json.rl" ++#line 64 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_offset )) return false; } +-#line 43 "../../src/hb-buffer-deserialize-json.rl" ++#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) +@@ -585,9 +585,9 @@ + } + break; + case 13: +-#line 65 "../../src/hb-buffer-deserialize-json.rl" ++#line 65 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } +-#line 43 "../../src/hb-buffer-deserialize-json.rl" ++#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) +@@ -597,9 +597,9 @@ + } + break; + case 4: +-#line 66 "../../src/hb-buffer-deserialize-json.rl" ++#line 66 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } +-#line 43 "../../src/hb-buffer-deserialize-json.rl" ++#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) +@@ -609,9 +609,9 @@ + } + break; + case 7: +-#line 67 "../../src/hb-buffer-deserialize-json.rl" ++#line 67 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } +-#line 43 "../../src/hb-buffer-deserialize-json.rl" ++#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) +@@ -620,7 +620,7 @@ + *end_ptr = p; + } + break; +-#line 624 "hb-buffer-deserialize-json.hh.tmp" ++#line 624 "hb-buffer-deserialize-json.hh" + } + + _again: +@@ -632,7 +632,7 @@ + _out: {} + } + +-#line 125 "../../src/hb-buffer-deserialize-json.rl" ++#line 125 "hb-buffer-deserialize-json.rl" + + + *end_ptr = p; +diff -uN gfx/harfbuzz/src_old/hb-buffer-deserialize-text.hh gfx/harfbuzz/src/hb-buffer-deserialize-text.hh +--- gfx/harfbuzz/src_old/hb-buffer-deserialize-text.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-buffer-deserialize-text.hh 2016-06-05 23:48:23.120330665 +0200 +@@ -1,5 +1,5 @@ + +-#line 1 "../../src/hb-buffer-deserialize-text.rl" ++#line 1 "hb-buffer-deserialize-text.rl" + /* + * Copyright © 2013 Google, Inc. + * +@@ -32,7 +32,7 @@ + #include "hb-private.hh" + + +-#line 36 "hb-buffer-deserialize-text.hh.tmp" ++#line 36 "hb-buffer-deserialize-text.hh" + static const unsigned char _deserialize_text_trans_keys[] = { + 0u, 0u, 9u, 122u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, + 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, +@@ -312,7 +312,7 @@ + static const int deserialize_text_en_main = 1; + + +-#line 91 "../../src/hb-buffer-deserialize-text.rl" ++#line 91 "hb-buffer-deserialize-text.rl" + + + static hb_bool_t +@@ -336,15 +336,15 @@ + + const char *eof = pe, *tok = NULL; + int cs; +- hb_glyph_info_t info; +- hb_glyph_position_t pos; ++ hb_glyph_info_t info = {0}; ++ hb_glyph_position_t pos = {0}; + +-#line 343 "hb-buffer-deserialize-text.hh.tmp" ++#line 343 "hb-buffer-deserialize-text.hh" + { + cs = deserialize_text_start; + } + +-#line 348 "hb-buffer-deserialize-text.hh.tmp" ++#line 348 "hb-buffer-deserialize-text.hh" + { + int _slen; + int _trans; +@@ -370,13 +370,13 @@ + + switch ( _deserialize_text_trans_actions[_trans] ) { + case 2: +-#line 51 "../../src/hb-buffer-deserialize-text.rl" ++#line 51 "hb-buffer-deserialize-text.rl" + { + tok = p; + } + break; + case 5: +-#line 55 "../../src/hb-buffer-deserialize-text.rl" ++#line 55 "hb-buffer-deserialize-text.rl" + { + if (!hb_font_glyph_from_string (font, + tok, p - tok, +@@ -385,41 +385,41 @@ + } + break; + case 10: +-#line 62 "../../src/hb-buffer-deserialize-text.rl" ++#line 62 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } + break; + case 3: +-#line 63 "../../src/hb-buffer-deserialize-text.rl" ++#line 63 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_offset )) return false; } + break; + case 12: +-#line 64 "../../src/hb-buffer-deserialize-text.rl" ++#line 64 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } + break; + case 7: +-#line 65 "../../src/hb-buffer-deserialize-text.rl" ++#line 65 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } + break; + case 1: +-#line 38 "../../src/hb-buffer-deserialize-text.rl" ++#line 38 "hb-buffer-deserialize-text.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); + } +-#line 51 "../../src/hb-buffer-deserialize-text.rl" ++#line 51 "hb-buffer-deserialize-text.rl" + { + tok = p; + } + break; + case 4: +-#line 55 "../../src/hb-buffer-deserialize-text.rl" ++#line 55 "hb-buffer-deserialize-text.rl" + { + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; + } +-#line 43 "../../src/hb-buffer-deserialize-text.rl" ++#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) +@@ -429,9 +429,9 @@ + } + break; + case 9: +-#line 62 "../../src/hb-buffer-deserialize-text.rl" ++#line 62 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } +-#line 43 "../../src/hb-buffer-deserialize-text.rl" ++#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) +@@ -441,9 +441,9 @@ + } + break; + case 11: +-#line 64 "../../src/hb-buffer-deserialize-text.rl" ++#line 64 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } +-#line 43 "../../src/hb-buffer-deserialize-text.rl" ++#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) +@@ -453,9 +453,9 @@ + } + break; + case 6: +-#line 65 "../../src/hb-buffer-deserialize-text.rl" ++#line 65 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } +-#line 43 "../../src/hb-buffer-deserialize-text.rl" ++#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) +@@ -465,9 +465,9 @@ + } + break; + case 8: +-#line 66 "../../src/hb-buffer-deserialize-text.rl" ++#line 66 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } +-#line 43 "../../src/hb-buffer-deserialize-text.rl" ++#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) +@@ -476,7 +476,7 @@ + *end_ptr = p; + } + break; +-#line 480 "hb-buffer-deserialize-text.hh.tmp" ++#line 480 "hb-buffer-deserialize-text.hh" + } + + _again: +@@ -489,14 +489,14 @@ + { + switch ( _deserialize_text_eof_actions[cs] ) { + case 4: +-#line 55 "../../src/hb-buffer-deserialize-text.rl" ++#line 55 "hb-buffer-deserialize-text.rl" + { + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; + } +-#line 43 "../../src/hb-buffer-deserialize-text.rl" ++#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) +@@ -506,9 +506,9 @@ + } + break; + case 9: +-#line 62 "../../src/hb-buffer-deserialize-text.rl" ++#line 62 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } +-#line 43 "../../src/hb-buffer-deserialize-text.rl" ++#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) +@@ -518,9 +518,9 @@ + } + break; + case 11: +-#line 64 "../../src/hb-buffer-deserialize-text.rl" ++#line 64 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } +-#line 43 "../../src/hb-buffer-deserialize-text.rl" ++#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) +@@ -530,9 +530,9 @@ + } + break; + case 6: +-#line 65 "../../src/hb-buffer-deserialize-text.rl" ++#line 65 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } +-#line 43 "../../src/hb-buffer-deserialize-text.rl" ++#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) +@@ -542,9 +542,9 @@ + } + break; + case 8: +-#line 66 "../../src/hb-buffer-deserialize-text.rl" ++#line 66 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } +-#line 43 "../../src/hb-buffer-deserialize-text.rl" ++#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) +@@ -553,14 +553,14 @@ + *end_ptr = p; + } + break; +-#line 557 "hb-buffer-deserialize-text.hh.tmp" ++#line 557 "hb-buffer-deserialize-text.hh" + } + } + + _out: {} + } + +-#line 119 "../../src/hb-buffer-deserialize-text.rl" ++#line 119 "hb-buffer-deserialize-text.rl" + + + *end_ptr = p; +diff -uN gfx/harfbuzz/src_old/hb-buffer-deserialize-text.rl gfx/harfbuzz/src/hb-buffer-deserialize-text.rl +--- gfx/harfbuzz/src_old/hb-buffer-deserialize-text.rl 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-buffer-deserialize-text.rl 2016-06-05 23:48:24.307324017 +0200 +@@ -111,8 +111,8 @@ + + const char *eof = pe, *tok = NULL; + int cs; +- hb_glyph_info_t info; +- hb_glyph_position_t pos; ++ hb_glyph_info_t info = {0}; ++ hb_glyph_position_t pos = {0}; + %%{ + write init; + write exec; +diff -uN gfx/harfbuzz/src_old/hb-buffer.h gfx/harfbuzz/src/hb-buffer.h +--- gfx/harfbuzz/src_old/hb-buffer.h 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-buffer.h 2016-06-05 23:48:29.670294025 +0200 +@@ -40,7 +40,27 @@ + + HB_BEGIN_DECLS + +- ++/** ++ * hb_glyph_info_t: ++ * @codepoint: either a Unicode code point (before shaping) or a glyph index ++ * (after shaping). ++ * @mask: ++ * @cluster: the index of the character in the original text that corresponds ++ * to this #hb_glyph_info_t, or whatever the client passes to ++ * hb_buffer_add(). More than one #hb_glyph_info_t can have the same ++ * @cluster value, if they resulted from the same character (e.g. one ++ * to many glyph substitution), and when more than one character gets ++ * merged in the same glyph (e.g. many to one glyph substitution) the ++ * #hb_glyph_info_t will have the smallest cluster value of them. ++ * By default some characters are merged into the same cluster ++ * (e.g. combining marks have the same cluster as their bases) ++ * even if they are separate glyphs, hb_buffer_set_cluster_level() ++ * allow selecting more fine-grained cluster handling. ++ * ++ * The #hb_glyph_info_t is the structure that holds information about the ++ * glyphs and their relation to input text. ++ * ++ */ + typedef struct hb_glyph_info_t { + hb_codepoint_t codepoint; + hb_mask_t mask; +@@ -51,6 +71,22 @@ + hb_var_int_t var2; + } hb_glyph_info_t; + ++/** ++ * hb_glyph_position_t: ++ * @x_advance: how much the line advances after drawing this glyph when setting ++ * text in horizontal direction. ++ * @y_advance: how much the line advances after drawing this glyph when setting ++ * text in vertical direction. ++ * @x_offset: how much the glyph moves on the X-axis before drawing it, this ++ * should not affect how much the line advances. ++ * @y_offset: how much the glyph moves on the Y-axis before drawing it, this ++ * should not affect how much the line advances. ++ * ++ * The #hb_glyph_position_t is the structure that holds the positions of the ++ * glyph in both horizontal and vertical directions. All positions in ++ * #hb_glyph_position_t are relative to the current point. ++ * ++ */ + typedef struct hb_glyph_position_t { + hb_position_t x_advance; + hb_position_t y_advance; +@@ -61,7 +97,16 @@ + hb_var_int_t var; + } hb_glyph_position_t; + +- ++/** ++ * hb_segment_properties_t: ++ * @direction: the #hb_direction_t of the buffer, see hb_buffer_set_direction(). ++ * @script: the #hb_script_t of the buffer, see hb_buffer_set_script(). ++ * @language: the #hb_language_t of the buffer, see hb_buffer_set_language(). ++ * ++ * The structure that holds various text properties of an #hb_buffer_t. Can be ++ * set and retrieved using hb_buffer_set_segment_properties() and ++ * hb_buffer_get_segment_properties(), respectively. ++ */ + typedef struct hb_segment_properties_t { + hb_direction_t direction; + hb_script_t script; +@@ -77,100 +122,127 @@ + NULL, \ + NULL} + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_segment_properties_equal (const hb_segment_properties_t *a, + const hb_segment_properties_t *b); + +-unsigned int ++HB_EXTERN unsigned int + hb_segment_properties_hash (const hb_segment_properties_t *p); + + + +-/* +- * hb_buffer_t ++/** ++ * hb_buffer_t: ++ * ++ * The main structure holding the input text and its properties before shaping, ++ * and output glyphs and their information after shaping. + */ + + typedef struct hb_buffer_t hb_buffer_t; + +-hb_buffer_t * ++HB_EXTERN hb_buffer_t * + hb_buffer_create (void); + +-hb_buffer_t * ++HB_EXTERN hb_buffer_t * + hb_buffer_get_empty (void); + +-hb_buffer_t * ++HB_EXTERN hb_buffer_t * + hb_buffer_reference (hb_buffer_t *buffer); + +-void ++HB_EXTERN void + hb_buffer_destroy (hb_buffer_t *buffer); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_buffer_set_user_data (hb_buffer_t *buffer, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace); + +-void * ++HB_EXTERN void * + hb_buffer_get_user_data (hb_buffer_t *buffer, + hb_user_data_key_t *key); + +- ++/** ++ * hb_buffer_content_type_t: ++ * @HB_BUFFER_CONTENT_TYPE_INVALID: Initial value for new buffer. ++ * @HB_BUFFER_CONTENT_TYPE_UNICODE: The buffer contains input characters (before shaping). ++ * @HB_BUFFER_CONTENT_TYPE_GLYPHS: The buffer contains output glyphs (after shaping). ++ */ + typedef enum { + HB_BUFFER_CONTENT_TYPE_INVALID = 0, + HB_BUFFER_CONTENT_TYPE_UNICODE, + HB_BUFFER_CONTENT_TYPE_GLYPHS + } hb_buffer_content_type_t; + +-void ++HB_EXTERN void + hb_buffer_set_content_type (hb_buffer_t *buffer, + hb_buffer_content_type_t content_type); + +-hb_buffer_content_type_t ++HB_EXTERN hb_buffer_content_type_t + hb_buffer_get_content_type (hb_buffer_t *buffer); + + +-void ++HB_EXTERN void + hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, + hb_unicode_funcs_t *unicode_funcs); + +-hb_unicode_funcs_t * ++HB_EXTERN hb_unicode_funcs_t * + hb_buffer_get_unicode_funcs (hb_buffer_t *buffer); + +-void ++HB_EXTERN void + hb_buffer_set_direction (hb_buffer_t *buffer, + hb_direction_t direction); + +-hb_direction_t ++HB_EXTERN hb_direction_t + hb_buffer_get_direction (hb_buffer_t *buffer); + +-void ++HB_EXTERN void + hb_buffer_set_script (hb_buffer_t *buffer, + hb_script_t script); + +-hb_script_t ++HB_EXTERN hb_script_t + hb_buffer_get_script (hb_buffer_t *buffer); + +-void ++HB_EXTERN void + hb_buffer_set_language (hb_buffer_t *buffer, + hb_language_t language); + + +-hb_language_t ++HB_EXTERN hb_language_t + hb_buffer_get_language (hb_buffer_t *buffer); + +-void ++HB_EXTERN void + hb_buffer_set_segment_properties (hb_buffer_t *buffer, + const hb_segment_properties_t *props); + +-void ++HB_EXTERN void + hb_buffer_get_segment_properties (hb_buffer_t *buffer, + hb_segment_properties_t *props); + +-void ++HB_EXTERN void + hb_buffer_guess_segment_properties (hb_buffer_t *buffer); + + ++/** ++ * hb_buffer_flags_t: ++ * @HB_BUFFER_FLAG_DEFAULT: the default buffer flag. ++ * @HB_BUFFER_FLAG_BOT: flag indicating that special handling of the beginning ++ * of text paragraph can be applied to this buffer. Should usually ++ * be set, unless you are passing to the buffer only part ++ * of the text without the full context. ++ * @HB_BUFFER_FLAG_EOT: flag indicating that special handling of the end of text ++ * paragraph can be applied to this buffer, similar to ++ * @HB_BUFFER_FLAG_EOT. ++ * @HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES: ++ * flag indication that character with Default_Ignorable ++ * Unicode property should use the corresponding glyph ++ * from the font, instead of hiding them (currently done ++ * by replacing them with the space glyph and zeroing the ++ * advance width.) ++ * ++ * Since: 0.9.20 ++ */ + typedef enum { /*< flags >*/ + HB_BUFFER_FLAG_DEFAULT = 0x00000000u, + HB_BUFFER_FLAG_BOT = 0x00000001u, /* Beginning-of-text */ +@@ -178,83 +250,109 @@ + HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u + } hb_buffer_flags_t; + +-void ++HB_EXTERN void + hb_buffer_set_flags (hb_buffer_t *buffer, + hb_buffer_flags_t flags); + +-hb_buffer_flags_t ++HB_EXTERN hb_buffer_flags_t + hb_buffer_get_flags (hb_buffer_t *buffer); + +- +- ++/* ++ * Since: 0.9.42 ++ */ ++typedef enum { ++ HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES = 0, ++ HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS = 1, ++ HB_BUFFER_CLUSTER_LEVEL_CHARACTERS = 2, ++ HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES ++} hb_buffer_cluster_level_t; ++ ++HB_EXTERN void ++hb_buffer_set_cluster_level (hb_buffer_t *buffer, ++ hb_buffer_cluster_level_t cluster_level); ++ ++HB_EXTERN hb_buffer_cluster_level_t ++hb_buffer_get_cluster_level (hb_buffer_t *buffer); ++ ++/** ++ * HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT: ++ * ++ * The default code point for replacing invalid characters in a given encoding. ++ * Set to U+FFFD REPLACEMENT CHARACTER. ++ * ++ * Since: 0.9.31 ++ */ + #define HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT 0xFFFDu + +-/* Sets codepoint used to replace invalid UTF-8/16/32 entries. +- * Default is 0xFFFDu. */ +-void ++HB_EXTERN void + hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer, + hb_codepoint_t replacement); + +-hb_codepoint_t ++HB_EXTERN hb_codepoint_t + hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer); + + +-/* Resets the buffer. Afterwards it's as if it was just created, +- * except that it has a larger buffer allocated perhaps... */ +-void ++HB_EXTERN void + hb_buffer_reset (hb_buffer_t *buffer); + +-/* Like reset, but does NOT clear unicode_funcs and replacement_codepoint. */ +-void ++HB_EXTERN void + hb_buffer_clear_contents (hb_buffer_t *buffer); + +-/* Returns false if allocation failed */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_buffer_pre_allocate (hb_buffer_t *buffer, + unsigned int size); + + +-/* Returns false if allocation has failed before */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_buffer_allocation_successful (hb_buffer_t *buffer); + +-void ++HB_EXTERN void + hb_buffer_reverse (hb_buffer_t *buffer); + +-void ++HB_EXTERN void ++hb_buffer_reverse_range (hb_buffer_t *buffer, ++ unsigned int start, unsigned int end); ++ ++HB_EXTERN void + hb_buffer_reverse_clusters (hb_buffer_t *buffer); + + + /* Filling the buffer in */ + +-void ++HB_EXTERN void + hb_buffer_add (hb_buffer_t *buffer, + hb_codepoint_t codepoint, + unsigned int cluster); + +-void ++HB_EXTERN void + hb_buffer_add_utf8 (hb_buffer_t *buffer, + const char *text, + int text_length, + unsigned int item_offset, + int item_length); + +-void ++HB_EXTERN void + hb_buffer_add_utf16 (hb_buffer_t *buffer, + const uint16_t *text, + int text_length, + unsigned int item_offset, + int item_length); + +-void ++HB_EXTERN void + hb_buffer_add_utf32 (hb_buffer_t *buffer, + const uint32_t *text, + int text_length, + unsigned int item_offset, + int item_length); + +-/* Like add_utf32 but does NOT check for invalid Unicode codepoints. */ +-void ++HB_EXTERN void ++hb_buffer_add_latin1 (hb_buffer_t *buffer, ++ const uint8_t *text, ++ int text_length, ++ unsigned int item_offset, ++ int item_length); ++ ++HB_EXTERN void + hb_buffer_add_codepoints (hb_buffer_t *buffer, + const hb_codepoint_t *text, + int text_length, +@@ -262,32 +360,25 @@ + int item_length); + + +-/* Clears any new items added at the end */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_buffer_set_length (hb_buffer_t *buffer, + unsigned int length); + +-/* Return value valid as long as buffer not modified */ +-unsigned int ++HB_EXTERN unsigned int + hb_buffer_get_length (hb_buffer_t *buffer); + + /* Getting glyphs out of the buffer */ + +-/* Return value valid as long as buffer not modified */ +-hb_glyph_info_t * ++HB_EXTERN hb_glyph_info_t * + hb_buffer_get_glyph_infos (hb_buffer_t *buffer, + unsigned int *length); + +-/* Return value valid as long as buffer not modified */ +-hb_glyph_position_t * ++HB_EXTERN hb_glyph_position_t * + hb_buffer_get_glyph_positions (hb_buffer_t *buffer, + unsigned int *length); + + +-/* Reorders a glyph buffer to have canonical in-cluster glyph order / position. +- * The resulting clusters should behave identical to pre-reordering clusters. +- * NOTE: This has nothing to do with Unicode normalization. */ +-void ++HB_EXTERN void + hb_buffer_normalize_glyphs (hb_buffer_t *buffer); + + +@@ -295,50 +386,87 @@ + * Serialize + */ + ++/** ++ * hb_buffer_serialize_flags_t: ++ * @HB_BUFFER_SERIALIZE_FLAG_DEFAULT: serialize glyph names, clusters and positions. ++ * @HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS: do not serialize glyph cluster. ++ * @HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS: do not serialize glyph position information. ++ * @HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES: do no serialize glyph name. ++ * @HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS: serialize glyph extents. ++ * ++ * Flags that control what glyph information are serialized in hb_buffer_serialize_glyphs(). ++ * ++ * Since: 0.9.20 ++ */ + typedef enum { /*< flags >*/ + HB_BUFFER_SERIALIZE_FLAG_DEFAULT = 0x00000000u, + HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS = 0x00000001u, + HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS = 0x00000002u, +- HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u ++ HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u, ++ HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u + } hb_buffer_serialize_flags_t; + ++/** ++ * hb_buffer_serialize_format_t: ++ * @HB_BUFFER_SERIALIZE_FORMAT_TEXT: a human-readable, plain text format. ++ * @HB_BUFFER_SERIALIZE_FORMAT_JSON: a machine-readable JSON format. ++ * @HB_BUFFER_SERIALIZE_FORMAT_INVALID: invalid format. ++ * ++ * The buffer serialization and de-serialization format used in ++ * hb_buffer_serialize_glyphs() and hb_buffer_deserialize_glyphs(). ++ * ++ * Since: 0.9.2 ++ */ + typedef enum { + HB_BUFFER_SERIALIZE_FORMAT_TEXT = HB_TAG('T','E','X','T'), + HB_BUFFER_SERIALIZE_FORMAT_JSON = HB_TAG('J','S','O','N'), + HB_BUFFER_SERIALIZE_FORMAT_INVALID = HB_TAG_NONE + } hb_buffer_serialize_format_t; + +-/* len=-1 means str is NUL-terminated. */ +-hb_buffer_serialize_format_t ++HB_EXTERN hb_buffer_serialize_format_t + hb_buffer_serialize_format_from_string (const char *str, int len); + +-const char * ++HB_EXTERN const char * + hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format); + +-const char ** ++HB_EXTERN const char ** + hb_buffer_serialize_list_formats (void); + +-/* Returns number of items, starting at start, that were serialized. */ +-unsigned int ++HB_EXTERN unsigned int + hb_buffer_serialize_glyphs (hb_buffer_t *buffer, + unsigned int start, + unsigned int end, + char *buf, + unsigned int buf_size, +- unsigned int *buf_consumed, /* May be NULL */ +- hb_font_t *font, /* May be NULL */ ++ unsigned int *buf_consumed, ++ hb_font_t *font, + hb_buffer_serialize_format_t format, + hb_buffer_serialize_flags_t flags); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, + const char *buf, +- int buf_len, /* -1 means nul-terminated */ +- const char **end_ptr, /* May be NULL */ +- hb_font_t *font, /* May be NULL */ ++ int buf_len, ++ const char **end_ptr, ++ hb_font_t *font, + hb_buffer_serialize_format_t format); + + ++/* ++ * Debugging. ++ */ ++ ++typedef hb_bool_t (*hb_buffer_message_func_t) (hb_buffer_t *buffer, ++ hb_font_t *font, ++ const char *message, ++ void *user_data); ++ ++HB_EXTERN void ++hb_buffer_set_message_func (hb_buffer_t *buffer, ++ hb_buffer_message_func_t func, ++ void *user_data, hb_destroy_func_t destroy); ++ ++ + HB_END_DECLS + + #endif /* HB_BUFFER_H */ +diff -uN gfx/harfbuzz/src_old/hb-buffer-private.hh gfx/harfbuzz/src/hb-buffer-private.hh +--- gfx/harfbuzz/src_old/hb-buffer-private.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-buffer-private.hh 2016-06-05 23:48:25.604316742 +0200 +@@ -35,9 +35,37 @@ + #include "hb-unicode-private.hh" + + ++#ifndef HB_BUFFER_MAX_EXPANSION_FACTOR ++#define HB_BUFFER_MAX_EXPANSION_FACTOR 32 ++#endif ++#ifndef HB_BUFFER_MAX_LEN_MIN ++#define HB_BUFFER_MAX_LEN_MIN 8192 ++#endif ++#ifndef HB_BUFFER_MAX_LEN_DEFAULT ++#define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */ ++#endif ++ + ASSERT_STATIC (sizeof (hb_glyph_info_t) == 20); + ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)); + ++HB_MARK_AS_FLAG_T (hb_buffer_flags_t); ++HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t); ++ ++enum hb_buffer_scratch_flags_t { ++ HB_BUFFER_SCRATCH_FLAG_DEFAULT = 0x00000000u, ++ HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII = 0x00000001u, ++ HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u, ++ HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u, ++ HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_CURSIVE = 0x00000008u, ++ HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000010u, ++ /* Reserved for complex shapers' internal use. */ ++ HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u, ++ HB_BUFFER_SCRATCH_FLAG_COMPLEX1 = 0x02000000u, ++ HB_BUFFER_SCRATCH_FLAG_COMPLEX2 = 0x04000000u, ++ HB_BUFFER_SCRATCH_FLAG_COMPLEX3 = 0x08000000u, ++}; ++HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t); ++ + + /* + * hb_buffer_t +@@ -50,7 +78,10 @@ + /* Information about how the text in the buffer should be treated */ + hb_unicode_funcs_t *unicode; /* Unicode functions */ + hb_buffer_flags_t flags; /* BOT / EOT / etc. */ ++ hb_buffer_cluster_level_t cluster_level; + hb_codepoint_t replacement; /* U+FFFD or something else. */ ++ hb_buffer_scratch_flags_t scratch_flags; /* Have space-flallback, etc. */ ++ unsigned int max_len; /* Maximum allowed len. */ + + /* Buffer contents */ + hb_buffer_content_type_t content_type; +@@ -75,8 +106,8 @@ + inline hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; } + inline hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; } + +- inline hb_glyph_info_t &prev (void) { return out_info[out_len - 1]; } +- inline hb_glyph_info_t prev (void) const { return info[out_len - 1]; } ++ inline hb_glyph_info_t &prev (void) { return out_info[out_len ? out_len - 1 : 0]; } ++ inline hb_glyph_info_t prev (void) const { return out_info[out_len ? out_len - 1 : 0]; } + + inline bool has_separate_output (void) const { return info != out_info; } + +@@ -93,6 +124,11 @@ + hb_codepoint_t context[2][CONTEXT_LENGTH]; + unsigned int context_len[2]; + ++ /* Debugging */ ++ hb_buffer_message_func_t message_func; ++ void *message_data; ++ hb_destroy_func_t message_destroy; ++ + + /* Methods */ + +@@ -171,9 +207,18 @@ + unsigned int cluster_end); + + HB_INTERNAL void merge_clusters (unsigned int start, +- unsigned int end); ++ unsigned int end) ++ { ++ if (end - start < 2) ++ return; ++ merge_clusters_impl (start, end); ++ } ++ HB_INTERNAL void merge_clusters_impl (unsigned int start, ++ unsigned int end); + HB_INTERNAL void merge_out_clusters (unsigned int start, + unsigned int end); ++ /* Merge clusters for deleting current glyph, and skip it. */ ++ HB_INTERNAL void delete_glyph (void); + + /* Internal methods */ + HB_INTERNAL bool enlarge (unsigned int size); +@@ -191,6 +236,21 @@ + HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size); + + inline void clear_context (unsigned int side) { context_len[side] = 0; } ++ ++ HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *)); ++ ++ inline bool messaging (void) { return unlikely (message_func); } ++ inline bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4) ++ { ++ if (!messaging ()) ++ return true; ++ va_list ap; ++ va_start (ap, fmt); ++ bool ret = message_impl (font, fmt, ap); ++ va_end (ap); ++ return ret; ++ } ++ HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0); + }; + + +diff -uN gfx/harfbuzz/src_old/hb-buffer-serialize.cc gfx/harfbuzz/src/hb-buffer-serialize.cc +--- gfx/harfbuzz/src_old/hb-buffer-serialize.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-buffer-serialize.cc 2016-06-05 23:48:26.782310166 +0200 +@@ -36,11 +36,12 @@ + /** + * hb_buffer_serialize_list_formats: + * +- * ++ * Returns a list of supported buffer serialization formats. + * + * Return value: (transfer none): ++ * A string array of buffer serialization formats. Should not be freed. + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + const char ** + hb_buffer_serialize_list_formats (void) +@@ -50,14 +51,17 @@ + + /** + * hb_buffer_serialize_format_from_string: +- * @str: +- * @len: ++ * @str: (array length=len) (element-type uint8_t): a string to parse ++ * @len: length of @str, or -1 if string is %NULL terminated + * +- * ++ * Parses a string into an #hb_buffer_serialize_format_t. Does not check if ++ * @str is a valid buffer serialization format, use ++ * hb_buffer_serialize_list_formats() to get the list of supported formats. + * + * Return value: ++ * The parsed #hb_buffer_serialize_format_t. + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + hb_buffer_serialize_format_t + hb_buffer_serialize_format_from_string (const char *str, int len) +@@ -68,13 +72,15 @@ + + /** + * hb_buffer_serialize_format_to_string: +- * @format: ++ * @format: an #hb_buffer_serialize_format_t to convert. + * +- * ++ * Converts @format to the string corresponding it, or %NULL if it is not a valid ++ * #hb_buffer_serialize_format_t. + * +- * Return value: ++ * Return value: (transfer none): ++ * A %NULL terminated string corresponding to @format. Should not be freed. + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + const char * + hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format) +@@ -99,7 +105,8 @@ + hb_buffer_serialize_flags_t flags) + { + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL); +- hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL); ++ hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ? ++ NULL : hb_buffer_get_glyph_positions (buffer, NULL); + + *buf_consumed = 0; + for (unsigned int i = start; i < end; i++) +@@ -144,6 +151,16 @@ + pos[i].x_advance, pos[i].y_advance); + } + ++ if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) ++ { ++ hb_glyph_extents_t extents; ++ hb_font_get_glyph_extents(font, info[i].codepoint, &extents); ++ p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d", ++ extents.x_bearing, extents.y_bearing)); ++ p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d", ++ extents.width, extents.height)); ++ } ++ + *p++ = '}'; + + unsigned int l = p - b; +@@ -172,7 +189,8 @@ + hb_buffer_serialize_flags_t flags) + { + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL); +- hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL); ++ hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ? ++ NULL : hb_buffer_get_glyph_positions (buffer, NULL); + + *buf_consumed = 0; + for (unsigned int i = start; i < end; i++) +@@ -208,6 +226,13 @@ + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance)); + } + ++ if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) ++ { ++ hb_glyph_extents_t extents; ++ hb_font_get_glyph_extents(font, info[i].codepoint, &extents); ++ p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height)); ++ } ++ + unsigned int l = p - b; + if (buf_size > l) + { +@@ -223,24 +248,51 @@ + return end - start; + } + +-/* Returns number of items, starting at start, that were serialized. */ + /** + * hb_buffer_serialize_glyphs: +- * @buffer: a buffer. +- * @start: +- * @end: +- * @buf: (array length=buf_size): +- * @buf_size: +- * @buf_consumed: (out): +- * @font: +- * @format: +- * @flags: ++ * @buffer: an #hb_buffer_t buffer. ++ * @start: the first item in @buffer to serialize. ++ * @end: the last item in @buffer to serialize. ++ * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to ++ * write serialized buffer into. ++ * @buf_size: the size of @buf. ++ * @buf_consumed: (out) (allow-none): if not %NULL, will be set to the number of byes written into @buf. ++ * @font: (allow-none): the #hb_font_t used to shape this buffer, needed to ++ * read glyph names and extents. If %NULL, and empty font will be used. ++ * @format: the #hb_buffer_serialize_format_t to use for formatting the output. ++ * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties ++ * to serialize. ++ * ++ * Serializes @buffer into a textual representation of its glyph content, ++ * useful for showing the contents of the buffer, for example during debugging. ++ * There are currently two supported serialization formats: ++ * ++ * ## text ++ * A human-readable, plain text format. ++ * The serialized glyphs will look something like: ++ * ++ * ``` ++ * [uni0651=0@518,0+0|uni0628=0+1897] ++ * ``` ++ * - The serialized glyphs are delimited with `[` and `]`. ++ * - Glyphs are separated with `|` ++ * - Each glyph starts with glyph name, or glyph index if ++ * #HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES flag is set. Then, ++ * - If #HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS is not set, `=` then #hb_glyph_info_t.cluster. ++ * - If #HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS is not set, the #hb_glyph_position_t in the format: ++ * - If both #hb_glyph_position_t.x_offset and #hb_glyph_position_t.y_offset are not 0, `@x_offset,y_offset`. Then, ++ * - `+x_advance`, then `,y_advance` if #hb_glyph_position_t.y_advance is not 0. Then, ++ * - If #HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS is set, the ++ * #hb_glyph_extents_t in the format ++ * `<x_bearing,y_bearing,width,height>` + * +- * ++ * ## json ++ * TODO. + * + * Return value: ++ * The number of serialized items. + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + unsigned int + hb_buffer_serialize_glyphs (hb_buffer_t *buffer, +@@ -248,8 +300,8 @@ + unsigned int end, + char *buf, + unsigned int buf_size, +- unsigned int *buf_consumed, /* May be NULL */ +- hb_font_t *font, /* May be NULL */ ++ unsigned int *buf_consumed, ++ hb_font_t *font, + hb_buffer_serialize_format_t format, + hb_buffer_serialize_flags_t flags) + { +@@ -263,6 +315,9 @@ + assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || + buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); + ++ if (!buffer->have_positions) ++ flags |= HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS; ++ + if (unlikely (start == end)) + return 0; + +@@ -336,7 +391,7 @@ + + /** + * hb_buffer_deserialize_glyphs: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t buffer. + * @buf: (array length=buf_len): + * @buf_len: + * @end_ptr: (out): +@@ -347,7 +402,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + hb_bool_t + hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, +diff -uN gfx/harfbuzz/src_old/hb-common.cc gfx/harfbuzz/src/hb-common.cc +--- gfx/harfbuzz/src_old/hb-common.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-common.cc 2016-06-05 23:48:32.151280204 +0200 +@@ -57,14 +57,14 @@ + + /** + * hb_tag_from_string: +- * @str: (array length=len): ++ * @str: (array length=len) (element-type uint8_t): + * @len: + * + * + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_tag_t + hb_tag_from_string (const char *str, int len) +@@ -92,7 +92,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.5 + **/ + void + hb_tag_to_string (hb_tag_t tag, char *buf) +@@ -115,14 +115,14 @@ + + /** + * hb_direction_from_string: +- * @str: (array length=len): ++ * @str: (array length=len) (element-type uint8_t): + * @len: + * + * + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_direction_t + hb_direction_from_string (const char *str, int len) +@@ -149,7 +149,7 @@ + * + * Return value: (transfer none): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + const char * + hb_direction_to_string (hb_direction_t direction) +@@ -179,7 +179,7 @@ + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0 + }; + +-static hb_bool_t ++static bool + lang_equal (hb_language_t v1, + const void *v2) + { +@@ -235,7 +235,7 @@ + static hb_language_item_t *langs; + + #ifdef HB_USE_ATEXIT +-static inline ++static + void free_langs (void) + { + while (langs) { +@@ -265,6 +265,7 @@ + *lang = key; + + if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) { ++ lang->finish (); + free (lang); + goto retry; + } +@@ -280,46 +281,51 @@ + + /** + * hb_language_from_string: +- * @str: (array length=len): +- * @len: ++ * @str: (array length=len) (element-type uint8_t): a string representing ++ * ISO 639 language code ++ * @len: length of the @str, or -1 if it is %NULL-terminated. + * +- * ++ * Converts @str representing an ISO 639 language code to the corresponding ++ * #hb_language_t. + * +- * Return value: ++ * Return value: (transfer none): ++ * The #hb_language_t corresponding to the ISO 639 language code. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_language_t + hb_language_from_string (const char *str, int len) + { +- char strbuf[64]; +- + if (!str || !len || !*str) + return HB_LANGUAGE_INVALID; + ++ hb_language_item_t *item = NULL; + if (len >= 0) + { + /* NUL-terminate it. */ ++ char strbuf[64]; + len = MIN (len, (int) sizeof (strbuf) - 1); + memcpy (strbuf, str, len); + strbuf[len] = '\0'; +- str = strbuf; ++ item = lang_find_or_insert (strbuf); + } +- +- hb_language_item_t *item = lang_find_or_insert (str); ++ else ++ item = lang_find_or_insert (str); + + return likely (item) ? item->lang : HB_LANGUAGE_INVALID; + } + + /** + * hb_language_to_string: +- * @language: ++ * @language: an #hb_language_t to convert. + * +- * ++ * See hb_language_from_string(). + * +- * Return value: (transfer none): ++ * Return value: (transfer none): ++ * A %NULL-terminated string representing the @language. Must not be freed by ++ * the caller. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + const char * + hb_language_to_string (hb_language_t language) +@@ -333,9 +339,9 @@ + * + * + * +- * Return value: ++ * Return value: (transfer none): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_language_t + hb_language_get_default (void) +@@ -345,7 +351,7 @@ + hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language); + if (unlikely (language == HB_LANGUAGE_INVALID)) { + language = hb_language_from_string (setlocale (LC_CTYPE, NULL), -1); +- hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language); ++ (void) hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language); + } + + return default_language; +@@ -356,13 +362,14 @@ + + /** + * hb_script_from_iso15924_tag: +- * @tag: ++ * @tag: an #hb_tag_t representing an ISO 15924 tag. + * +- * ++ * Converts an ISO 15924 script tag to a corresponding #hb_script_t. + * + * Return value: ++ * An #hb_script_t corresponding to the ISO 15924 tag. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_script_t + hb_script_from_iso15924_tag (hb_tag_t tag) +@@ -400,30 +407,35 @@ + + /** + * hb_script_from_string: +- * @s: (array length=len): +- * @len: +- * +- * ++ * @str: (array length=len) (element-type uint8_t): a string representing an ++ * ISO 15924 tag. ++ * @len: length of the @str, or -1 if it is %NULL-terminated. ++ * ++ * Converts a string @str representing an ISO 15924 script tag to a ++ * corresponding #hb_script_t. Shorthand for hb_tag_from_string() then ++ * hb_script_from_iso15924_tag(). + * + * Return value: ++ * An #hb_script_t corresponding to the ISO 15924 tag. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_script_t +-hb_script_from_string (const char *s, int len) ++hb_script_from_string (const char *str, int len) + { +- return hb_script_from_iso15924_tag (hb_tag_from_string (s, len)); ++ return hb_script_from_iso15924_tag (hb_tag_from_string (str, len)); + } + + /** + * hb_script_to_iso15924_tag: +- * @script: ++ * @script: an #hb_script_ to convert. + * +- * ++ * See hb_script_from_iso15924_tag(). + * +- * Return value: ++ * Return value: ++ * An #hb_tag_t representing an ISO 15924 script tag. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_tag_t + hb_script_to_iso15924_tag (hb_script_t script) +@@ -439,7 +451,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_direction_t + hb_script_get_horizontal_direction (hb_script_t script) +@@ -492,6 +504,9 @@ + case HB_SCRIPT_PALMYRENE: + case HB_SCRIPT_PSALTER_PAHLAVI: + ++ /* Unicode-8.0 additions */ ++ case HB_SCRIPT_OLD_HUNGARIAN: ++ + return HB_DIRECTION_RTL; + } + +@@ -517,7 +532,7 @@ + } + } + hb_user_data_item_t item = {key, data, destroy}; +- bool ret = !!items.replace_or_insert (item, lock, replace); ++ bool ret = !!items.replace_or_insert (item, lock, (bool) replace); + + return ret; + } +@@ -541,7 +556,7 @@ + * + * Returns library version as three integer components. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_version (unsigned int *major, +@@ -560,7 +575,7 @@ + * + * Return value: library version string. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + const char * + hb_version_string (void) +@@ -578,7 +593,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.30 + **/ + hb_bool_t + hb_version_atleast (unsigned int major, +diff -uN gfx/harfbuzz/src_old/hb-common.h gfx/harfbuzz/src/hb-common.h +--- gfx/harfbuzz/src_old/hb-common.h 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-common.h 2016-06-05 23:48:33.399273253 +0200 +@@ -98,16 +98,22 @@ + #define HB_TAG_MAX_SIGNED HB_TAG(0x7f,0xff,0xff,0xff) + + /* len=-1 means str is NUL-terminated. */ +-hb_tag_t ++HB_EXTERN hb_tag_t + hb_tag_from_string (const char *str, int len); + + /* buf should have 4 bytes. */ +-void ++HB_EXTERN void + hb_tag_to_string (hb_tag_t tag, char *buf); + + +-/* hb_direction_t */ +- ++/** ++ * hb_direction_t: ++ * @HB_DIRECTION_INVALID: Initial, unset direction. ++ * @HB_DIRECTION_LTR: Text is set horizontally from left to right. ++ * @HB_DIRECTION_RTL: Text is set horizontally from right to left. ++ * @HB_DIRECTION_TTB: Text is set vertically from top to bottom. ++ * @HB_DIRECTION_BTT: Text is set vertically from bottom to top. ++ */ + typedef enum { + HB_DIRECTION_INVALID = 0, + HB_DIRECTION_LTR = 4, +@@ -117,10 +123,10 @@ + } hb_direction_t; + + /* len=-1 means str is NUL-terminated */ +-hb_direction_t ++HB_EXTERN hb_direction_t + hb_direction_from_string (const char *str, int len); + +-const char * ++HB_EXTERN const char * + hb_direction_to_string (hb_direction_t direction); + + #define HB_DIRECTION_IS_VALID(dir) ((((unsigned int) (dir)) & ~3U) == 4) +@@ -136,16 +142,15 @@ + + typedef const struct hb_language_impl_t *hb_language_t; + +-/* len=-1 means str is NUL-terminated */ +-hb_language_t ++HB_EXTERN hb_language_t + hb_language_from_string (const char *str, int len); + +-const char * ++HB_EXTERN const char * + hb_language_to_string (hb_language_t language); + + #define HB_LANGUAGE_INVALID ((hb_language_t) NULL) + +-hb_language_t ++HB_EXTERN hb_language_t + hb_language_get_default (void); + + +@@ -272,6 +277,9 @@ + /*6.1*/ HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'), + /*6.1*/ HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), + ++ /* ++ * Since: 0.9.30 ++ */ + /*7.0*/ HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'), + /*7.0*/ HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'), + /*7.0*/ HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'), +@@ -296,6 +304,13 @@ + /*7.0*/ HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'), + /*7.0*/ HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'), + ++ /*8.0*/ HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'), ++ /*8.0*/ HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'), ++ /*8.0*/ HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'), ++ /*8.0*/ HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'), ++ /*8.0*/ HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'), ++ /*8.0*/ HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'), ++ + /* No script set. */ + HB_SCRIPT_INVALID = HB_TAG_NONE, + +@@ -314,18 +329,16 @@ + + /* Script functions */ + +-hb_script_t ++HB_EXTERN hb_script_t + hb_script_from_iso15924_tag (hb_tag_t tag); + +-/* sugar for tag_from_string() then script_from_iso15924_tag */ +-/* len=-1 means s is NUL-terminated */ +-hb_script_t +-hb_script_from_string (const char *s, int len); ++HB_EXTERN hb_script_t ++hb_script_from_string (const char *str, int len); + +-hb_tag_t ++HB_EXTERN hb_tag_t + hb_script_to_iso15924_tag (hb_script_t script); + +-hb_direction_t ++HB_EXTERN hb_direction_t + hb_script_get_horizontal_direction (hb_script_t script); + + +diff -uN gfx/harfbuzz/src_old/hb-coretext.cc gfx/harfbuzz/src/hb-coretext.cc +--- gfx/harfbuzz/src_old/hb-coretext.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-coretext.cc 2016-06-05 23:48:34.938264688 +0200 +@@ -22,7 +22,7 @@ + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * +- * GNU Author(s): Jonathan Kew ++ * Mozilla Author(s): Jonathan Kew + * Google Author(s): Behdad Esfahbod + */ + +@@ -125,6 +125,9 @@ + CFRelease (data); + } + ++/* ++ * Since: 0.9.10 ++ */ + CGFontRef + hb_coretext_face_get_cg_font (hb_face_t *face) + { +@@ -140,6 +143,7 @@ + + struct hb_coretext_shaper_font_data_t { + CTFontRef ct_font; ++ CGFloat x_mult, y_mult; /* From CT space to HB space. */ + }; + + hb_coretext_shaper_font_data_t * +@@ -154,7 +158,55 @@ + hb_face_t *face = font->face; + hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); + +- data->ct_font = CTFontCreateWithGraphicsFont (face_data, font->y_scale, NULL, NULL); ++ /* Choose a CoreText font size and calculate multipliers to convert to HarfBuzz space. */ ++ /* TODO: use upem instead of 36? */ ++ CGFloat font_size = 36.; /* Default... */ ++ /* No idea if the following is even a good idea. */ ++ if (font->y_ppem) ++ font_size = font->y_ppem; ++ ++ if (font_size < 0) ++ font_size = -font_size; ++ data->x_mult = (CGFloat) font->x_scale / font_size; ++ data->y_mult = (CGFloat) font->y_scale / font_size; ++ data->ct_font = CTFontCreateWithGraphicsFont (face_data, font_size, NULL, NULL); ++ if (unlikely (!data->ct_font)) { ++ DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed"); ++ free (data); ++ return NULL; ++ } ++ ++ /* Create font copy with cascade list that has LastResort first; this speeds up CoreText ++ * font fallback which we don't need anyway. */ ++ { ++ // TODO Handle allocation failures? ++ CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize(CFSTR("LastResort"), 0); ++ CFArrayRef cascade_list = CFArrayCreate (kCFAllocatorDefault, ++ (const void **) &last_resort, ++ 1, ++ &kCFTypeArrayCallBacks); ++ CFRelease (last_resort); ++ CFDictionaryRef attributes = CFDictionaryCreate (kCFAllocatorDefault, ++ (const void **) &kCTFontCascadeListAttribute, ++ (const void **) &cascade_list, ++ 1, ++ &kCFTypeDictionaryKeyCallBacks, ++ &kCFTypeDictionaryValueCallBacks); ++ CFRelease (cascade_list); ++ ++ CTFontDescriptorRef new_font_desc = CTFontDescriptorCreateWithAttributes (attributes); ++ CFRelease (attributes); ++ ++ CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (data->ct_font, 0.0, NULL, new_font_desc); ++ if (new_ct_font) ++ { ++ CFRelease (data->ct_font); ++ data->ct_font = new_ct_font; ++ } ++ else ++ DEBUG_MSG (CORETEXT, font, "Font copy with empty cascade list failed"); ++ } ++ + if (unlikely (!data->ct_font)) { + DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed"); + free (data); +@@ -678,7 +730,6 @@ + scratch += old_scratch_used; + scratch_size -= old_scratch_used; + } +-retry: + { + string_ref = CFStringCreateWithCharactersNoCopy (NULL, + pchars, chars_len, +@@ -776,6 +827,18 @@ + + buffer->len = 0; + uint32_t status_and = ~0, status_or = 0; ++ double advances_so_far = 0; ++ /* For right-to-left runs, CoreText returns the glyphs positioned such that ++ * any trailing whitespace is to the left of (0,0). Adjust coordinate system ++ * to fix for that. Test with any RTL string with trailing spaces. ++ * https://code.google.com/p/chromium/issues/detail?id=469028 ++ */ ++ if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) ++ { ++ advances_so_far -= CTLineGetTrailingWhitespaceWidth (line); ++ if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction)) ++ advances_so_far = -advances_so_far; ++ } + + const CFRange range_all = CFRangeMake (0, 0); + +@@ -786,6 +849,10 @@ + status_or |= run_status; + status_and &= run_status; + DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status); ++ double run_advance = CTRunGetTypographicBounds (run, range_all, NULL, NULL, NULL); ++ if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction)) ++ run_advance = -run_advance; ++ DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance); + + /* CoreText does automatic font fallback (AKA "cascading") for characters + * not supported by the requested font, and provides no way to turn it off, +@@ -817,11 +884,9 @@ + * However, even that wouldn't work if we were passed in the CGFont to + * begin with. + * +- * Webkit uses a slightly different approach: it installs LastResort +- * as fallback chain, and then checks PS name of used font against +- * LastResort. That one is safe for any font except for LastResort, +- * as opposed to ours, which can fail if we are using any uninstalled +- * font that has the same name as an installed font. ++ * We might switch to checking PS name against "LastResort". That would ++ * be safe for all fonts except for those named "Last Resort". Might be ++ * better than what we have right now. + * + * See: http://github.com/behdad/harfbuzz/pull/36 + */ +@@ -860,8 +925,14 @@ + goto resize_and_retry; + hb_glyph_info_t *info = buffer->info + buffer->len; + +- CGGlyph notdef = 0; +- double advance = CTFontGetAdvancesForGlyphs (font_data->ct_font, kCTFontHorizontalOrientation, ¬def, NULL, 1); ++ hb_codepoint_t notdef = 0; ++ hb_direction_t dir = buffer->props.direction; ++ hb_position_t x_advance, y_advance, x_offset, y_offset; ++ hb_font_get_glyph_advance_for_direction (font, notdef, dir, &x_advance, &y_advance); ++ hb_font_get_glyph_origin_for_direction (font, notdef, dir, &x_offset, &y_offset); ++ hb_position_t advance = x_advance + y_advance; ++ x_offset = -x_offset; ++ y_offset = -y_offset; + + unsigned int old_len = buffer->len; + for (CFIndex j = range.location; j < range.location + range.length; j++) +@@ -875,19 +946,22 @@ + * for this one. */ + continue; + } ++ if (buffer->unicode->is_default_ignorable (ch)) ++ continue; + + info->codepoint = notdef; + info->cluster = log_clusters[j]; + + info->mask = advance; +- info->var1.u32 = 0; +- info->var2.u32 = 0; ++ info->var1.i32 = x_offset; ++ info->var2.i32 = y_offset; + + info++; + buffer->len++; + } + if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) + buffer->reverse_range (old_len, buffer->len); ++ advances_so_far += run_advance; + continue; + } + } +@@ -917,7 +991,7 @@ + scratch_size = scratch_size_saved; \ + scratch = scratch_saved; + +- { ++ { /* Setup glyphs */ + SCRATCH_SAVE(); + const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : NULL; + if (!glyphs) { +@@ -941,6 +1015,11 @@ + SCRATCH_RESTORE(); + } + { ++ /* Setup positions. ++ * Note that CoreText does not return advances for glyphs. As such, ++ * for all but last glyph, we use the delta position to next glyph as ++ * advance (in the advance direction only), and for last glyph we set ++ * whatever is needed to make the whole run's advance add up. */ + SCRATCH_SAVE(); + const CGPoint* positions = USE_PTR ? CTRunGetPositionsPtr (run) : NULL; + if (!positions) { +@@ -948,33 +1027,42 @@ + CTRunGetPositions (run, range_all, position_buf); + positions = position_buf; + } +- double run_advance = CTRunGetTypographicBounds (run, range_all, NULL, NULL, NULL); +- DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance); + hb_glyph_info_t *info = run_info; ++ CGFloat x_mult = font_data->x_mult, y_mult = font_data->y_mult; + if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) + { ++ hb_position_t x_offset = (positions[0].x - advances_so_far) * x_mult; + for (unsigned int j = 0; j < num_glyphs; j++) + { +- double advance = (j + 1 < num_glyphs ? positions[j + 1].x : positions[0].x + run_advance) - positions[j].x; +- info->mask = advance; +- info->var1.u32 = positions[0].x; /* Yes, zero. */ +- info->var2.u32 = positions[j].y; ++ double advance; ++ if (likely (j + 1 < num_glyphs)) ++ advance = positions[j + 1].x - positions[j].x; ++ else /* last glyph */ ++ advance = run_advance - (positions[j].x - positions[0].x); ++ info->mask = advance * x_mult; ++ info->var1.i32 = x_offset; ++ info->var2.i32 = positions[j].y * y_mult; + info++; + } + } + else + { +- run_advance = -run_advance; ++ hb_position_t y_offset = (positions[0].y - advances_so_far) * y_mult; + for (unsigned int j = 0; j < num_glyphs; j++) + { +- double advance = (j + 1 < num_glyphs ? positions[j + 1].y : positions[0].y + run_advance) - positions[j].y; +- info->mask = advance; +- info->var1.u32 = positions[j].x; +- info->var2.u32 = positions[0].y; /* Yes, zero. */ ++ double advance; ++ if (likely (j + 1 < num_glyphs)) ++ advance = positions[j + 1].y - positions[j].y; ++ else /* last glyph */ ++ advance = run_advance - (positions[j].y - positions[0].y); ++ info->mask = advance * y_mult; ++ info->var1.i32 = positions[j].x * x_mult; ++ info->var2.i32 = y_offset; + info++; + } + } + SCRATCH_RESTORE(); ++ advances_so_far += run_advance; + } + #undef SCRATCH_RESTORE + #undef SCRATCH_SAVE +@@ -984,10 +1072,20 @@ + buffer->len += num_glyphs; + } + +- /* Make sure all runs had the expected direction. */ +- bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); +- assert (bool (status_and & kCTRunStatusRightToLeft) == backward); +- assert (bool (status_or & kCTRunStatusRightToLeft) == backward); ++ /* Mac OS 10.6 doesn't have kCTTypesetterOptionForcedEmbeddingLevel, ++ * or if it does, it doesn't resepct it. So we get runs with wrong ++ * directions. As such, disable the assert... It wouldn't crash, but ++ * cursoring will be off... ++ * ++ * http://crbug.com/419769 ++ */ ++ if (0) ++ { ++ /* Make sure all runs had the expected direction. */ ++ bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); ++ assert (bool (status_and & kCTRunStatusRightToLeft) == backward); ++ assert (bool (status_or & kCTRunStatusRightToLeft) == backward); ++ } + + buffer->clear_positions (); + +@@ -998,16 +1096,16 @@ + for (unsigned int i = 0; i < count; i++) + { + pos->x_advance = info->mask; +- pos->x_offset = info->var1.u32; +- pos->y_offset = info->var2.u32; ++ pos->x_offset = info->var1.i32; ++ pos->y_offset = info->var2.i32; + info++, pos++; + } + else + for (unsigned int i = 0; i < count; i++) + { + pos->y_advance = info->mask; +- pos->x_offset = info->var1.u32; +- pos->y_offset = info->var2.u32; ++ pos->x_offset = info->var1.i32; ++ pos->y_offset = info->var2.i32; + info++, pos++; + } + +@@ -1065,10 +1163,6 @@ + * AAT shaper + */ + +-HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, face) +-HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, font) +- +- + /* + * shaper face data + */ +diff -uN gfx/harfbuzz/src_old/hb-coretext.h gfx/harfbuzz/src/hb-coretext.h +--- gfx/harfbuzz/src_old/hb-coretext.h 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-coretext.h 2016-06-05 23:48:36.098258246 +0200 +@@ -21,7 +21,7 @@ + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * +- * GNU Author(s): Jonathan Kew ++ * Mozilla Author(s): Jonathan Kew + */ + + #ifndef HB_CORETEXT_H +@@ -44,14 +44,14 @@ + #define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x') + + +-hb_face_t * ++HB_EXTERN hb_face_t * + hb_coretext_face_create (CGFontRef cg_font); + + +-CGFontRef ++HB_EXTERN CGFontRef + hb_coretext_face_get_cg_font (hb_face_t *face); + +-CTFontRef ++HB_EXTERN CTFontRef + hb_coretext_font_get_ct_font (hb_font_t *font); + + +diff -uN gfx/harfbuzz/src_old/hb-directwrite.cc gfx/harfbuzz/src/hb-directwrite.cc +--- gfx/harfbuzz/src_old/hb-directwrite.cc 1970-01-01 01:00:00.000000000 +0100 ++++ gfx/harfbuzz/src/hb-directwrite.cc 2016-06-05 23:48:38.757243479 +0200 +@@ -0,0 +1,827 @@ ++/* ++ * Copyright © 2015 Ebrahim Byagowi ++ * ++ * This is part of HarfBuzz, a text shaping library. ++ * ++ * Permission is hereby granted, without written agreement and without ++ * license or royalty fees, to use, copy, modify, and distribute this ++ * software and its documentation for any purpose, provided that the ++ * above copyright notice and the following two paragraphs appear in ++ * all copies of this software. ++ * ++ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR ++ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ++ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN ++ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ++ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, ++ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ++ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ++ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO ++ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ++ */ ++ ++#define HB_SHAPER directwrite ++#include "hb-shaper-impl-private.hh" ++ ++#include <dwrite.h> ++ ++#include "hb-directwrite.h" ++ ++#include "hb-open-file-private.hh" ++#include "hb-ot-name-table.hh" ++#include "hb-ot-tag.h" ++ ++ ++#ifndef HB_DEBUG_DIRECTWRITE ++#define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0) ++#endif ++ ++HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, face) ++HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, font) ++ ++/* ++* shaper face data ++*/ ++ ++struct hb_directwrite_shaper_face_data_t { ++ HANDLE fh; ++ wchar_t face_name[LF_FACESIZE]; ++}; ++ ++/* face_name should point to a wchar_t[LF_FACESIZE] object. */ ++static void ++_hb_generate_unique_face_name(wchar_t *face_name, unsigned int *plen) ++{ ++ /* We'll create a private name for the font from a UUID using a simple, ++ * somewhat base64-like encoding scheme */ ++ const char *enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"; ++ UUID id; ++ UuidCreate ((UUID*)&id); ++ ASSERT_STATIC (2 + 3 * (16 / 2) < LF_FACESIZE); ++ unsigned int name_str_len = 0; ++ face_name[name_str_len++] = 'F'; ++ face_name[name_str_len++] = '_'; ++ unsigned char *p = (unsigned char *)&id; ++ for (unsigned int i = 0; i < 16; i += 2) ++ { ++ /* Spread the 16 bits from two bytes of the UUID across three chars of face_name, ++ * using the bits in groups of 5,5,6 to select chars from enc. ++ * This will generate 24 characters; with the 'F_' prefix we already provided, ++ * the name will be 26 chars (plus the NUL terminator), so will always fit within ++ * face_name (LF_FACESIZE = 32). */ ++ face_name[name_str_len++] = enc[p[i] >> 3]; ++ face_name[name_str_len++] = enc[((p[i] << 2) | (p[i + 1] >> 6)) & 0x1f]; ++ face_name[name_str_len++] = enc[p[i + 1] & 0x3f]; ++ } ++ face_name[name_str_len] = 0; ++ if (plen) ++ *plen = name_str_len; ++} ++ ++/* Destroys blob. */ ++static hb_blob_t * ++_hb_rename_font(hb_blob_t *blob, wchar_t *new_name) ++{ ++ /* Create a copy of the font data, with the 'name' table replaced by a ++ * table that names the font with our private F_* name created above. ++ * For simplicity, we just append a new 'name' table and update the ++ * sfnt directory; the original table is left in place, but unused. ++ * ++ * The new table will contain just 5 name IDs: family, style, unique, ++ * full, PS. All of them point to the same name data with our unique name. ++ */ ++ ++ blob = OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (blob); ++ ++ unsigned int length, new_length, name_str_len; ++ const char *orig_sfnt_data = hb_blob_get_data (blob, &length); ++ ++ _hb_generate_unique_face_name (new_name, &name_str_len); ++ ++ static const uint16_t name_IDs[] = { 1, 2, 3, 4, 6 }; ++ ++ unsigned int name_table_length = OT::name::min_size + ++ ARRAY_LENGTH(name_IDs) * OT::NameRecord::static_size + ++ name_str_len * 2; /* for name data in UTF16BE form */ ++ unsigned int name_table_offset = (length + 3) & ~3; ++ ++ new_length = name_table_offset + ((name_table_length + 3) & ~3); ++ void *new_sfnt_data = calloc(1, new_length); ++ if (!new_sfnt_data) ++ { ++ hb_blob_destroy (blob); ++ return NULL; ++ } ++ ++ memcpy(new_sfnt_data, orig_sfnt_data, length); ++ ++ OT::name &name = OT::StructAtOffset<OT::name> (new_sfnt_data, name_table_offset); ++ name.format.set (0); ++ name.count.set (ARRAY_LENGTH (name_IDs)); ++ name.stringOffset.set (name.get_size()); ++ for (unsigned int i = 0; i < ARRAY_LENGTH (name_IDs); i++) ++ { ++ OT::NameRecord &record = name.nameRecord[i]; ++ record.platformID.set(3); ++ record.encodingID.set(1); ++ record.languageID.set(0x0409u); /* English */ ++ record.nameID.set(name_IDs[i]); ++ record.length.set(name_str_len * 2); ++ record.offset.set(0); ++ } ++ ++ /* Copy string data from new_name, converting wchar_t to UTF16BE. */ ++ unsigned char *p = &OT::StructAfter<unsigned char>(name); ++ for (unsigned int i = 0; i < name_str_len; i++) ++ { ++ *p++ = new_name[i] >> 8; ++ *p++ = new_name[i] & 0xff; ++ } ++ ++ /* Adjust name table entry to point to new name table */ ++ const OT::OpenTypeFontFile &file = *(OT::OpenTypeFontFile *) (new_sfnt_data); ++ unsigned int face_count = file.get_face_count (); ++ for (unsigned int face_index = 0; face_index < face_count; face_index++) ++ { ++ /* Note: doing multiple edits (ie. TTC) can be unsafe. There may be ++ * toe-stepping. But we don't really care. */ ++ const OT::OpenTypeFontFace &face = file.get_face (face_index); ++ unsigned int index; ++ if (face.find_table_index (HB_OT_TAG_name, &index)) ++ { ++ OT::TableRecord &record = const_cast<OT::TableRecord &> (face.get_table (index)); ++ record.checkSum.set_for_data (&name, name_table_length); ++ record.offset.set (name_table_offset); ++ record.length.set (name_table_length); ++ } ++ else if (face_index == 0) /* Fail if first face doesn't have 'name' table. */ ++ { ++ free (new_sfnt_data); ++ hb_blob_destroy (blob); ++ return NULL; ++ } ++ } ++ ++ /* The checkSumAdjustment field in the 'head' table is now wrong, ++ * but that doesn't actually seem to cause any problems so we don't ++ * bother. */ ++ ++ hb_blob_destroy (blob); ++ return hb_blob_create ((const char *)new_sfnt_data, new_length, ++ HB_MEMORY_MODE_WRITABLE, NULL, free); ++} ++ ++hb_directwrite_shaper_face_data_t * ++_hb_directwrite_shaper_face_data_create(hb_face_t *face) ++{ ++ hb_directwrite_shaper_face_data_t *data = (hb_directwrite_shaper_face_data_t *)calloc(1, sizeof (hb_directwrite_shaper_face_data_t)); ++ if (unlikely (!data)) ++ return NULL; ++ ++ hb_blob_t *blob = hb_face_reference_blob (face); ++ if (unlikely (!hb_blob_get_length (blob))) ++ DEBUG_MSG(DIRECTWRITE, face, "Face has empty blob"); ++ ++ blob = _hb_rename_font (blob, data->face_name); ++ if (unlikely (!blob)) ++ { ++ free(data); ++ return NULL; ++ } ++ ++ DWORD num_fonts_installed; ++ data->fh = AddFontMemResourceEx ((void *)hb_blob_get_data(blob, NULL), ++ hb_blob_get_length (blob), ++ 0, &num_fonts_installed); ++ if (unlikely (!data->fh)) ++ { ++ DEBUG_MSG (DIRECTWRITE, face, "Face AddFontMemResourceEx() failed"); ++ free (data); ++ return NULL; ++ } ++ ++ return data; ++} ++ ++void ++_hb_directwrite_shaper_face_data_destroy(hb_directwrite_shaper_face_data_t *data) ++{ ++ RemoveFontMemResourceEx(data->fh); ++ free(data); ++} ++ ++ ++/* ++ * shaper font data ++ */ ++ ++struct hb_directwrite_shaper_font_data_t { ++ HDC hdc; ++ LOGFONTW log_font; ++ HFONT hfont; ++}; ++ ++static bool ++populate_log_font (LOGFONTW *lf, ++ hb_font_t *font) ++{ ++ memset (lf, 0, sizeof (*lf)); ++ lf->lfHeight = -font->y_scale; ++ lf->lfCharSet = DEFAULT_CHARSET; ++ ++ hb_face_t *face = font->face; ++ hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); ++ ++ memcpy (lf->lfFaceName, face_data->face_name, sizeof (lf->lfFaceName)); ++ ++ return true; ++} ++ ++hb_directwrite_shaper_font_data_t * ++_hb_directwrite_shaper_font_data_create (hb_font_t *font) ++{ ++ if (unlikely (!hb_directwrite_shaper_face_data_ensure (font->face))) return NULL; ++ ++ hb_directwrite_shaper_font_data_t *data = (hb_directwrite_shaper_font_data_t *) calloc (1, sizeof (hb_directwrite_shaper_font_data_t)); ++ if (unlikely (!data)) ++ return NULL; ++ ++ data->hdc = GetDC (NULL); ++ ++ if (unlikely (!populate_log_font (&data->log_font, font))) { ++ DEBUG_MSG (DIRECTWRITE, font, "Font populate_log_font() failed"); ++ _hb_directwrite_shaper_font_data_destroy (data); ++ return NULL; ++ } ++ ++ data->hfont = CreateFontIndirectW (&data->log_font); ++ if (unlikely (!data->hfont)) { ++ DEBUG_MSG (DIRECTWRITE, font, "Font CreateFontIndirectW() failed"); ++ _hb_directwrite_shaper_font_data_destroy (data); ++ return NULL; ++ } ++ ++ if (!SelectObject (data->hdc, data->hfont)) { ++ DEBUG_MSG (DIRECTWRITE, font, "Font SelectObject() failed"); ++ _hb_directwrite_shaper_font_data_destroy (data); ++ return NULL; ++ } ++ ++ return data; ++} ++ ++void ++_hb_directwrite_shaper_font_data_destroy (hb_directwrite_shaper_font_data_t *data) ++{ ++ if (data->hdc) ++ ReleaseDC (NULL, data->hdc); ++ if (data->hfont) ++ DeleteObject (data->hfont); ++ free (data); ++} ++ ++LOGFONTW * ++hb_directwrite_font_get_logfontw (hb_font_t *font) ++{ ++ if (unlikely (!hb_directwrite_shaper_font_data_ensure (font))) return NULL; ++ hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); ++ return &font_data->log_font; ++} ++ ++HFONT ++hb_directwrite_font_get_hfont (hb_font_t *font) ++{ ++ if (unlikely (!hb_directwrite_shaper_font_data_ensure (font))) return NULL; ++ hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); ++ return font_data->hfont; ++} ++ ++ ++/* ++ * shaper shape_plan data ++ */ ++ ++struct hb_directwrite_shaper_shape_plan_data_t {}; ++ ++hb_directwrite_shaper_shape_plan_data_t * ++_hb_directwrite_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, ++ const hb_feature_t *user_features HB_UNUSED, ++ unsigned int num_user_features HB_UNUSED) ++{ ++ return (hb_directwrite_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; ++} ++ ++void ++_hb_directwrite_shaper_shape_plan_data_destroy (hb_directwrite_shaper_shape_plan_data_t *data HB_UNUSED) ++{ ++} ++ ++// Most of here TextAnalysis is originally written by Bas Schouten for Mozilla project ++// but now is relicensed to MIT for HarfBuzz use ++class TextAnalysis ++ : public IDWriteTextAnalysisSource, public IDWriteTextAnalysisSink ++{ ++public: ++ ++ IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) { return S_OK; } ++ IFACEMETHOD_(ULONG, AddRef)() { return 1; } ++ IFACEMETHOD_(ULONG, Release)() { return 1; } ++ ++ // A single contiguous run of characters containing the same analysis ++ // results. ++ struct Run ++ { ++ UINT32 mTextStart; // starting text position of this run ++ UINT32 mTextLength; // number of contiguous code units covered ++ UINT32 mGlyphStart; // starting glyph in the glyphs array ++ UINT32 mGlyphCount; // number of glyphs associated with this run of ++ // text ++ DWRITE_SCRIPT_ANALYSIS mScript; ++ UINT8 mBidiLevel; ++ bool mIsSideways; ++ ++ inline bool ContainsTextPosition(UINT32 aTextPosition) const ++ { ++ return aTextPosition >= mTextStart ++ && aTextPosition < mTextStart + mTextLength; ++ } ++ ++ Run *nextRun; ++ }; ++ ++public: ++ TextAnalysis(const wchar_t* text, ++ UINT32 textLength, ++ const wchar_t* localeName, ++ DWRITE_READING_DIRECTION readingDirection) ++ : mText(text) ++ , mTextLength(textLength) ++ , mLocaleName(localeName) ++ , mReadingDirection(readingDirection) ++ , mCurrentRun(NULL) { }; ++ ++ ~TextAnalysis() { ++ // delete runs, except mRunHead which is part of the TextAnalysis object ++ for (Run *run = mRunHead.nextRun; run;) { ++ Run *origRun = run; ++ run = run->nextRun; ++ delete origRun; ++ } ++ } ++ ++ STDMETHODIMP GenerateResults(IDWriteTextAnalyzer* textAnalyzer, ++ Run **runHead) { ++ // Analyzes the text using the script analyzer and returns ++ // the result as a series of runs. ++ ++ HRESULT hr = S_OK; ++ ++ // Initially start out with one result that covers the entire range. ++ // This result will be subdivided by the analysis processes. ++ mRunHead.mTextStart = 0; ++ mRunHead.mTextLength = mTextLength; ++ mRunHead.mBidiLevel = ++ (mReadingDirection == DWRITE_READING_DIRECTION_RIGHT_TO_LEFT); ++ mRunHead.nextRun = NULL; ++ mCurrentRun = &mRunHead; ++ ++ // Call each of the analyzers in sequence, recording their results. ++ if (SUCCEEDED(hr = textAnalyzer->AnalyzeScript(this, ++ 0, ++ mTextLength, ++ this))) { ++ *runHead = &mRunHead; ++ } ++ ++ return hr; ++ } ++ ++ // IDWriteTextAnalysisSource implementation ++ ++ IFACEMETHODIMP GetTextAtPosition(UINT32 textPosition, ++ OUT WCHAR const** textString, ++ OUT UINT32* textLength) ++ { ++ if (textPosition >= mTextLength) { ++ // No text at this position, valid query though. ++ *textString = NULL; ++ *textLength = 0; ++ } ++ else { ++ *textString = mText + textPosition; ++ *textLength = mTextLength - textPosition; ++ } ++ return S_OK; ++ } ++ ++ IFACEMETHODIMP GetTextBeforePosition(UINT32 textPosition, ++ OUT WCHAR const** textString, ++ OUT UINT32* textLength) ++ { ++ if (textPosition == 0 || textPosition > mTextLength) { ++ // Either there is no text before here (== 0), or this ++ // is an invalid position. The query is considered valid thouh. ++ *textString = NULL; ++ *textLength = 0; ++ } ++ else { ++ *textString = mText; ++ *textLength = textPosition; ++ } ++ return S_OK; ++ } ++ ++ IFACEMETHODIMP_(DWRITE_READING_DIRECTION) ++ GetParagraphReadingDirection() { return mReadingDirection; } ++ ++ IFACEMETHODIMP GetLocaleName(UINT32 textPosition, ++ UINT32* textLength, ++ WCHAR const** localeName) { ++ return S_OK; ++ } ++ ++ IFACEMETHODIMP ++ GetNumberSubstitution(UINT32 textPosition, ++ OUT UINT32* textLength, ++ OUT IDWriteNumberSubstitution** numberSubstitution) ++ { ++ // We do not support number substitution. ++ *numberSubstitution = NULL; ++ *textLength = mTextLength - textPosition; ++ ++ return S_OK; ++ } ++ ++ // IDWriteTextAnalysisSink implementation ++ ++ IFACEMETHODIMP ++ SetScriptAnalysis(UINT32 textPosition, ++ UINT32 textLength, ++ DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis) ++ { ++ SetCurrentRun(textPosition); ++ SplitCurrentRun(textPosition); ++ while (textLength > 0) { ++ Run *run = FetchNextRun(&textLength); ++ run->mScript = *scriptAnalysis; ++ } ++ ++ return S_OK; ++ } ++ ++ IFACEMETHODIMP ++ SetLineBreakpoints(UINT32 textPosition, ++ UINT32 textLength, ++ const DWRITE_LINE_BREAKPOINT* lineBreakpoints) { return S_OK; } ++ ++ IFACEMETHODIMP SetBidiLevel(UINT32 textPosition, ++ UINT32 textLength, ++ UINT8 explicitLevel, ++ UINT8 resolvedLevel) { return S_OK; } ++ ++ IFACEMETHODIMP ++ SetNumberSubstitution(UINT32 textPosition, ++ UINT32 textLength, ++ IDWriteNumberSubstitution* numberSubstitution) { return S_OK; } ++ ++protected: ++ Run *FetchNextRun(IN OUT UINT32* textLength) ++ { ++ // Used by the sink setters, this returns a reference to the next run. ++ // Position and length are adjusted to now point after the current run ++ // being returned. ++ ++ Run *origRun = mCurrentRun; ++ // Split the tail if needed (the length remaining is less than the ++ // current run's size). ++ if (*textLength < mCurrentRun->mTextLength) { ++ SplitCurrentRun(mCurrentRun->mTextStart + *textLength); ++ } ++ else { ++ // Just advance the current run. ++ mCurrentRun = mCurrentRun->nextRun; ++ } ++ *textLength -= origRun->mTextLength; ++ ++ // Return a reference to the run that was just current. ++ return origRun; ++ } ++ ++ void SetCurrentRun(UINT32 textPosition) ++ { ++ // Move the current run to the given position. ++ // Since the analyzers generally return results in a forward manner, ++ // this will usually just return early. If not, find the ++ // corresponding run for the text position. ++ ++ if (mCurrentRun && mCurrentRun->ContainsTextPosition(textPosition)) { ++ return; ++ } ++ ++ for (Run *run = &mRunHead; run; run = run->nextRun) { ++ if (run->ContainsTextPosition(textPosition)) { ++ mCurrentRun = run; ++ return; ++ } ++ } ++ //NS_NOTREACHED("We should always be able to find the text position in one \ ++ // of our runs"); ++ } ++ ++ void SplitCurrentRun(UINT32 splitPosition) ++ { ++ if (!mCurrentRun) { ++ //NS_ASSERTION(false, "SplitCurrentRun called without current run."); ++ // Shouldn't be calling this when no current run is set! ++ return; ++ } ++ // Split the current run. ++ if (splitPosition <= mCurrentRun->mTextStart) { ++ // No need to split, already the start of a run ++ // or before it. Usually the first. ++ return; ++ } ++ Run *newRun = new Run; ++ ++ *newRun = *mCurrentRun; ++ ++ // Insert the new run in our linked list. ++ newRun->nextRun = mCurrentRun->nextRun; ++ mCurrentRun->nextRun = newRun; ++ ++ // Adjust runs' text positions and lengths. ++ UINT32 splitPoint = splitPosition - mCurrentRun->mTextStart; ++ newRun->mTextStart += splitPoint; ++ newRun->mTextLength -= splitPoint; ++ mCurrentRun->mTextLength = splitPoint; ++ mCurrentRun = newRun; ++ } ++ ++protected: ++ // Input ++ // (weak references are fine here, since this class is a transient ++ // stack-based helper that doesn't need to copy data) ++ UINT32 mTextLength; ++ const WCHAR* mText; ++ const WCHAR* mLocaleName; ++ DWRITE_READING_DIRECTION mReadingDirection; ++ ++ // Current processing state. ++ Run *mCurrentRun; ++ ++ // Output is a list of runs starting here ++ Run mRunHead; ++}; ++ ++ ++/* ++ * shaper ++ */ ++ ++hb_bool_t ++_hb_directwrite_shape(hb_shape_plan_t *shape_plan, ++ hb_font_t *font, ++ hb_buffer_t *buffer, ++ const hb_feature_t *features, ++ unsigned int num_features) ++{ ++ hb_face_t *face = font->face; ++ hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); ++ hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); ++ ++ // factory probably should be cached ++ IDWriteFactory* dwriteFactory; ++ DWriteCreateFactory( ++ DWRITE_FACTORY_TYPE_SHARED, ++ __uuidof(IDWriteFactory), ++ reinterpret_cast<IUnknown**>(&dwriteFactory) ++ ); ++ ++ IDWriteGdiInterop *gdiInterop; ++ dwriteFactory->GetGdiInterop (&gdiInterop); ++ IDWriteFontFace* fontFace; ++ gdiInterop->CreateFontFaceFromHdc (font_data->hdc, &fontFace); ++ ++ IDWriteTextAnalyzer* analyzer; ++ dwriteFactory->CreateTextAnalyzer (&analyzer); ++ ++ unsigned int scratch_size; ++ hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size); ++#define ALLOCATE_ARRAY(Type, name, len) \ ++ Type *name = (Type *) scratch; \ ++ { \ ++ unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \ ++ assert (_consumed <= scratch_size); \ ++ scratch += _consumed; \ ++ scratch_size -= _consumed; \ ++ } ++ ++#define utf16_index() var1.u32 ++ ++ ALLOCATE_ARRAY(WCHAR, pchars, buffer->len * 2); ++ ++ unsigned int chars_len = 0; ++ for (unsigned int i = 0; i < buffer->len; i++) ++ { ++ hb_codepoint_t c = buffer->info[i].codepoint; ++ buffer->info[i].utf16_index() = chars_len; ++ if (likely(c <= 0xFFFFu)) ++ pchars[chars_len++] = c; ++ else if (unlikely(c > 0x10FFFFu)) ++ pchars[chars_len++] = 0xFFFDu; ++ else { ++ pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10); ++ pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1)); ++ } ++ } ++ ++ ALLOCATE_ARRAY(WORD, log_clusters, chars_len); ++ if (num_features) ++ { ++ /* Need log_clusters to assign features. */ ++ chars_len = 0; ++ for (unsigned int i = 0; i < buffer->len; i++) ++ { ++ hb_codepoint_t c = buffer->info[i].codepoint; ++ unsigned int cluster = buffer->info[i].cluster; ++ log_clusters[chars_len++] = cluster; ++ if (hb_in_range(c, 0x10000u, 0x10FFFFu)) ++ log_clusters[chars_len++] = cluster; /* Surrogates. */ ++ } ++ } ++ ++ HRESULT hr; ++ // TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES ++ ++ DWRITE_READING_DIRECTION readingDirection = buffer->props.direction ? ++ DWRITE_READING_DIRECTION_RIGHT_TO_LEFT : ++ DWRITE_READING_DIRECTION_LEFT_TO_RIGHT; ++ ++ /* ++ * There's an internal 16-bit limit on some things inside the analyzer, ++ * but we never attempt to shape a word longer than 64K characters ++ * in a single gfxShapedWord, so we cannot exceed that limit. ++ */ ++ UINT32 length = buffer->len; ++ ++ TextAnalysis analysis(pchars, length, NULL, readingDirection); ++ TextAnalysis::Run *runHead; ++ hr = analysis.GenerateResults(analyzer, &runHead); ++ ++ if (FAILED(hr)) { ++ //NS_WARNING("Analyzer failed to generate results."); ++ return false; ++ } ++ ++ UINT32 maxGlyphs = 3 * length / 2 + 16; ++ ++#define INITIAL_GLYPH_SIZE 400 ++ UINT16* clusters = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16)); ++ UINT16* glyphs = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16)); ++ DWRITE_SHAPING_TEXT_PROPERTIES* textProperties = (DWRITE_SHAPING_TEXT_PROPERTIES*) ++ malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_TEXT_PROPERTIES)); ++ DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*) ++ malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES)); ++ ++ UINT32 actualGlyphs; ++ ++ bool backward = HB_DIRECTION_IS_BACKWARD(buffer->props.direction); ++ ++ wchar_t lang[4]; ++ mbstowcs(lang, hb_language_to_string(buffer->props.language), 4); ++ hr = analyzer->GetGlyphs(pchars, length, ++ fontFace, FALSE, ++ buffer->props.direction, ++ &runHead->mScript, (const wchar_t*)lang, NULL, NULL, NULL, 0, ++ maxGlyphs, clusters, textProperties, ++ glyphs, glyphProperties, &actualGlyphs); ++ ++ if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) { ++ free(clusters); ++ free(glyphs); ++ free(textProperties); ++ free(glyphProperties); ++ ++ clusters = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16)); ++ glyphs = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16)); ++ textProperties = (DWRITE_SHAPING_TEXT_PROPERTIES*) ++ malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_TEXT_PROPERTIES)); ++ glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*) ++ malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES)); ++ ++ hr = analyzer->GetGlyphs(pchars, length, ++ fontFace, FALSE, ++ buffer->props.direction, ++ &runHead->mScript, (const wchar_t*)lang, NULL, NULL, NULL, 0, ++ maxGlyphs, clusters, textProperties, ++ glyphs, glyphProperties, &actualGlyphs); ++ } ++ if (FAILED(hr)) { ++ //NS_WARNING("Analyzer failed to get glyphs."); ++ return false; ++ } ++ ++ FLOAT advances[400]; ++ DWRITE_GLYPH_OFFSET offsets[400]; ++ ++ ++ /* The -2 in the following is to compensate for possible ++ * alignment needed after the WORD array. sizeof(WORD) == 2. */ ++ unsigned int glyphs_size = (scratch_size * sizeof (int)-2) ++ / (sizeof (WORD) + ++ 4 + // sizeof (SCRIPT_GLYPHPROP) + ++ sizeof (int) + ++ 8 + // sizeof (GOFFSET) + ++ sizeof (uint32_t)); ++ ALLOCATE_ARRAY(uint32_t, vis_clusters, glyphs_size); ++ ++#undef ALLOCATE_ARRAY ++ ++ hr = analyzer->GetGlyphPlacements(pchars, ++ clusters, ++ textProperties, ++ length, ++ glyphs, ++ glyphProperties, ++ actualGlyphs, ++ fontFace, ++ face->get_upem(), ++ FALSE, ++ FALSE, ++ &runHead->mScript, ++ NULL, ++ NULL, ++ NULL, ++ 0, ++ advances, ++ offsets); ++ ++ if (FAILED(hr)) { ++ //NS_WARNING("Analyzer failed to get glyph placements."); ++ return false; ++ } ++ ++ unsigned int glyphs_len = actualGlyphs; ++ ++ /* Ok, we've got everything we need, now compose output buffer, ++ * very, *very*, carefully! */ ++ ++ /* Calculate visual-clusters. That's what we ship. */ ++ for (unsigned int i = 0; i < glyphs_len; i++) ++ vis_clusters[i] = -1; ++ for (unsigned int i = 0; i < buffer->len; i++) { ++ uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]]; ++ //*p = MIN (*p, buffer->info[i].cluster); ++ } ++ for (unsigned int i = 1; i < glyphs_len; i++) ++ if (vis_clusters[i] == -1) ++ vis_clusters[i] = vis_clusters[i - 1]; ++ ++#undef utf16_index ++ ++ //if (unlikely (!buffer->ensure (glyphs_len))) ++ // FAIL ("Buffer in error"); ++ ++#undef FAIL ++ ++ /* Set glyph infos */ ++ buffer->len = 0; ++ for (unsigned int i = 0; i < glyphs_len; i++) ++ { ++ hb_glyph_info_t *info = &buffer->info[buffer->len++]; ++ ++ info->codepoint = glyphs[i]; ++ info->cluster = vis_clusters[i]; ++ ++ /* The rest is crap. Let's store position info there for now. */ ++ info->mask = advances[i]; ++ info->var1.u32 = offsets[i].ascenderOffset; ++ info->var2.u32 = -offsets[i].advanceOffset; ++ } ++ ++ free(clusters); ++ free(glyphs); ++ free(textProperties); ++ free(glyphProperties); ++ ++ /* Set glyph positions */ ++ buffer->clear_positions (); ++ for (unsigned int i = 0; i < glyphs_len; i++) ++ { ++ hb_glyph_info_t *info = &buffer->info[i]; ++ hb_glyph_position_t *pos = &buffer->pos[i]; ++ ++ /* TODO vertical */ ++ pos->x_advance = info->mask; ++ pos->x_offset = backward ? -info->var1.u32 : info->var1.u32; ++ pos->y_offset = info->var2.u32; ++ } ++ ++ if (backward) ++ hb_buffer_reverse (buffer); ++ ++ /* Wow, done! */ ++ return true; ++} +diff -uN gfx/harfbuzz/src_old/hb-directwrite.h gfx/harfbuzz/src/hb-directwrite.h +--- gfx/harfbuzz/src_old/hb-directwrite.h 1970-01-01 01:00:00.000000000 +0100 ++++ gfx/harfbuzz/src/hb-directwrite.h 2016-06-05 23:48:40.059236276 +0200 +@@ -0,0 +1,34 @@ ++/* ++ * Copyright © 2015 Ebrahim Byagowi ++ * ++ * This is part of HarfBuzz, a text shaping library. ++ * ++ * Permission is hereby granted, without written agreement and without ++ * license or royalty fees, to use, copy, modify, and distribute this ++ * software and its documentation for any purpose, provided that the ++ * above copyright notice and the following two paragraphs appear in ++ * all copies of this software. ++ * ++ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR ++ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ++ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN ++ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ++ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, ++ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ++ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ++ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO ++ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ++ */ ++ ++#ifndef HB_DIRECTWRITE_H ++#define HB_DIRECTWRITE_H ++ ++#include "hb.h" ++ ++HB_BEGIN_DECLS ++ ++HB_END_DECLS ++ ++#endif /* HB_UNISCRIBE_H */ +diff -uN gfx/harfbuzz/src_old/hb-face.cc gfx/harfbuzz/src/hb-face.cc +--- gfx/harfbuzz/src_old/hb-face.cc 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-face.cc 2016-06-05 23:48:42.449223049 +0200 +@@ -77,7 +77,7 @@ + * + * Return value: (transfer full) + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_face_t * + hb_face_create_for_tables (hb_reference_table_func_t reference_table_func, +@@ -113,7 +113,7 @@ + { + hb_face_for_data_closure_t *closure; + +- closure = (hb_face_for_data_closure_t *) malloc (sizeof (hb_face_for_data_closure_t)); ++ closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t)); + if (unlikely (!closure)) + return NULL; + +@@ -157,7 +157,7 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_face_t * + hb_face_create (hb_blob_t *blob, +@@ -165,8 +165,8 @@ + { + hb_face_t *face; + +- if (unlikely (!blob || !hb_blob_get_length (blob))) +- return hb_face_get_empty (); ++ if (unlikely (!blob)) ++ blob = hb_blob_get_empty (); + + hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index); + +@@ -189,7 +189,7 @@ + * + * Return value: (transfer full) + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_face_t * + hb_face_get_empty (void) +@@ -206,7 +206,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_face_t * + hb_face_reference (hb_face_t *face) +@@ -220,7 +220,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_face_destroy (hb_face_t *face) +@@ -257,7 +257,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_face_set_user_data (hb_face_t *face, +@@ -278,7 +278,7 @@ + * + * Return value: (transfer none): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void * + hb_face_get_user_data (hb_face_t *face, +@@ -293,7 +293,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_face_make_immutable (hb_face_t *face) +@@ -312,7 +312,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_face_is_immutable (hb_face_t *face) +@@ -330,7 +330,7 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_blob_t * + hb_face_reference_table (hb_face_t *face, +@@ -347,7 +347,7 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_blob_t * + hb_face_reference_blob (hb_face_t *face) +@@ -362,7 +362,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_face_set_index (hb_face_t *face, +@@ -382,7 +382,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + unsigned int + hb_face_get_index (hb_face_t *face) +@@ -397,7 +397,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_face_set_upem (hb_face_t *face, +@@ -417,7 +417,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + unsigned int + hb_face_get_upem (hb_face_t *face) +@@ -441,7 +441,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + void + hb_face_set_glyph_count (hb_face_t *face, +@@ -461,7 +461,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + unsigned int + hb_face_get_glyph_count (hb_face_t *face) +diff -uN gfx/harfbuzz/src_old/hb-face.h gfx/harfbuzz/src/hb-face.h +--- gfx/harfbuzz/src_old/hb-face.h 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-face.h 2016-06-05 23:48:43.669216308 +0200 +@@ -43,28 +43,28 @@ + + typedef struct hb_face_t hb_face_t; + +-hb_face_t * ++HB_EXTERN hb_face_t * + hb_face_create (hb_blob_t *blob, + unsigned int index); + + typedef hb_blob_t * (*hb_reference_table_func_t) (hb_face_t *face, hb_tag_t tag, void *user_data); + + /* calls destroy() when not needing user_data anymore */ +-hb_face_t * ++HB_EXTERN hb_face_t * + hb_face_create_for_tables (hb_reference_table_func_t reference_table_func, + void *user_data, + hb_destroy_func_t destroy); + +-hb_face_t * ++HB_EXTERN hb_face_t * + hb_face_get_empty (void); + +-hb_face_t * ++HB_EXTERN hb_face_t * + hb_face_reference (hb_face_t *face); + +-void ++HB_EXTERN void + hb_face_destroy (hb_face_t *face); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_face_set_user_data (hb_face_t *face, + hb_user_data_key_t *key, + void * data, +@@ -72,43 +72,43 @@ + hb_bool_t replace); + + +-void * ++HB_EXTERN void * + hb_face_get_user_data (hb_face_t *face, + hb_user_data_key_t *key); + +-void ++HB_EXTERN void + hb_face_make_immutable (hb_face_t *face); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_face_is_immutable (hb_face_t *face); + + +-hb_blob_t * ++HB_EXTERN hb_blob_t * + hb_face_reference_table (hb_face_t *face, + hb_tag_t tag); + +-hb_blob_t * ++HB_EXTERN hb_blob_t * + hb_face_reference_blob (hb_face_t *face); + +-void ++HB_EXTERN void + hb_face_set_index (hb_face_t *face, + unsigned int index); + +-unsigned int ++HB_EXTERN unsigned int + hb_face_get_index (hb_face_t *face); + +-void ++HB_EXTERN void + hb_face_set_upem (hb_face_t *face, + unsigned int upem); + +-unsigned int ++HB_EXTERN unsigned int + hb_face_get_upem (hb_face_t *face); + +-void ++HB_EXTERN void + hb_face_set_glyph_count (hb_face_t *face, + unsigned int glyph_count); + +-unsigned int ++HB_EXTERN unsigned int + hb_face_get_glyph_count (hb_face_t *face); + + +diff -uN gfx/harfbuzz/src_old/hb-fallback-shape.cc gfx/harfbuzz/src/hb-fallback-shape.cc +--- gfx/harfbuzz/src_old/hb-fallback-shape.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-fallback-shape.cc 2016-06-05 23:48:44.900209512 +0200 +@@ -106,7 +106,7 @@ + */ + + hb_codepoint_t space; +- bool has_space = font->get_glyph (' ', 0, &space); ++ bool has_space = (bool) font->get_glyph (' ', 0, &space); + + buffer->clear_positions (); + +diff -uN gfx/harfbuzz/src_old/hb-font.cc gfx/harfbuzz/src/hb-font.cc +--- gfx/harfbuzz/src_old/hb-font.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-font.cc 2016-06-05 23:48:47.920192879 +0200 +@@ -45,130 +45,224 @@ + */ + + static hb_bool_t +-hb_font_get_glyph_nil (hb_font_t *font, ++hb_font_get_font_h_extents_nil (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_font_extents_t *metrics, ++ void *user_data HB_UNUSED) ++{ ++ memset (metrics, 0, sizeof (*metrics)); ++ return false; ++} ++static hb_bool_t ++hb_font_get_font_h_extents_parent (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_font_extents_t *metrics, ++ void *user_data HB_UNUSED) ++{ ++ hb_bool_t ret = font->parent->get_font_h_extents (metrics); ++ if (ret) { ++ metrics->ascender = font->parent_scale_y_distance (metrics->ascender); ++ metrics->descender = font->parent_scale_y_distance (metrics->descender); ++ metrics->line_gap = font->parent_scale_y_distance (metrics->line_gap); ++ } ++ return ret; ++} ++ ++static hb_bool_t ++hb_font_get_font_v_extents_nil (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_font_extents_t *metrics, ++ void *user_data HB_UNUSED) ++{ ++ memset (metrics, 0, sizeof (*metrics)); ++ return false; ++} ++static hb_bool_t ++hb_font_get_font_v_extents_parent (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_font_extents_t *metrics, ++ void *user_data HB_UNUSED) ++{ ++ hb_bool_t ret = font->parent->get_font_v_extents (metrics); ++ if (ret) { ++ metrics->ascender = font->parent_scale_x_distance (metrics->ascender); ++ metrics->descender = font->parent_scale_x_distance (metrics->descender); ++ metrics->line_gap = font->parent_scale_x_distance (metrics->line_gap); ++ } ++ return ret; ++} ++ ++static hb_bool_t ++hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t unicode, + hb_codepoint_t variation_selector, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) + { +- if (font->parent) +- return font->parent->get_glyph (unicode, variation_selector, glyph); +- + *glyph = 0; + return false; + } ++static hb_bool_t ++hb_font_get_glyph_parent (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_codepoint_t unicode, ++ hb_codepoint_t variation_selector, ++ hb_codepoint_t *glyph, ++ void *user_data HB_UNUSED) ++{ ++ return font->parent->get_glyph (unicode, variation_selector, glyph); ++} + + static hb_position_t +-hb_font_get_glyph_h_advance_nil (hb_font_t *font, ++hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + void *user_data HB_UNUSED) + { +- if (font->parent) +- return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph)); +- + return font->x_scale; + } ++static hb_position_t ++hb_font_get_glyph_h_advance_parent (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_codepoint_t glyph, ++ void *user_data HB_UNUSED) ++{ ++ return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph)); ++} + + static hb_position_t +-hb_font_get_glyph_v_advance_nil (hb_font_t *font, ++hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + void *user_data HB_UNUSED) + { +- if (font->parent) +- return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph)); +- + return font->y_scale; + } ++static hb_position_t ++hb_font_get_glyph_v_advance_parent (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_codepoint_t glyph, ++ void *user_data HB_UNUSED) ++{ ++ return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph)); ++} + + static hb_bool_t +-hb_font_get_glyph_h_origin_nil (hb_font_t *font, ++hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) + { +- if (font->parent) { +- hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y); +- if (ret) +- font->parent_scale_position (x, y); +- return ret; +- } +- + *x = *y = 0; +- return false; ++ return true; ++} ++static hb_bool_t ++hb_font_get_glyph_h_origin_parent (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_codepoint_t glyph, ++ hb_position_t *x, ++ hb_position_t *y, ++ void *user_data HB_UNUSED) ++{ ++ hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y); ++ if (ret) ++ font->parent_scale_position (x, y); ++ return ret; + } + + static hb_bool_t +-hb_font_get_glyph_v_origin_nil (hb_font_t *font, ++hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) + { +- if (font->parent) { +- hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y); +- if (ret) +- font->parent_scale_position (x, y); +- return ret; +- } +- + *x = *y = 0; + return false; + } ++static hb_bool_t ++hb_font_get_glyph_v_origin_parent (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_codepoint_t glyph, ++ hb_position_t *x, ++ hb_position_t *y, ++ void *user_data HB_UNUSED) ++{ ++ hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y); ++ if (ret) ++ font->parent_scale_position (x, y); ++ return ret; ++} + + static hb_position_t +-hb_font_get_glyph_h_kerning_nil (hb_font_t *font, ++hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t left_glyph, + hb_codepoint_t right_glyph, + void *user_data HB_UNUSED) + { +- if (font->parent) +- return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph)); +- + return 0; + } ++static hb_position_t ++hb_font_get_glyph_h_kerning_parent (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_codepoint_t left_glyph, ++ hb_codepoint_t right_glyph, ++ void *user_data HB_UNUSED) ++{ ++ return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph)); ++} + + static hb_position_t +-hb_font_get_glyph_v_kerning_nil (hb_font_t *font, ++hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t top_glyph, + hb_codepoint_t bottom_glyph, + void *user_data HB_UNUSED) + { +- if (font->parent) +- return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph)); +- + return 0; + } ++static hb_position_t ++hb_font_get_glyph_v_kerning_parent (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_codepoint_t top_glyph, ++ hb_codepoint_t bottom_glyph, ++ void *user_data HB_UNUSED) ++{ ++ return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph)); ++} + + static hb_bool_t +-hb_font_get_glyph_extents_nil (hb_font_t *font, ++hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents, + void *user_data HB_UNUSED) + { +- if (font->parent) { +- hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents); +- if (ret) { +- font->parent_scale_position (&extents->x_bearing, &extents->y_bearing); +- font->parent_scale_distance (&extents->width, &extents->height); +- } +- return ret; +- } +- + memset (extents, 0, sizeof (*extents)); + return false; + } ++static hb_bool_t ++hb_font_get_glyph_extents_parent (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_codepoint_t glyph, ++ hb_glyph_extents_t *extents, ++ void *user_data HB_UNUSED) ++{ ++ hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents); ++ if (ret) { ++ font->parent_scale_position (&extents->x_bearing, &extents->y_bearing); ++ font->parent_scale_distance (&extents->width, &extents->height); ++ } ++ return ret; ++} + + static hb_bool_t +-hb_font_get_glyph_contour_point_nil (hb_font_t *font, ++hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + unsigned int point_index, +@@ -176,45 +270,63 @@ + hb_position_t *y, + void *user_data HB_UNUSED) + { +- if (font->parent) { +- hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y); +- if (ret) +- font->parent_scale_position (x, y); +- return ret; +- } +- + *x = *y = 0; + return false; + } ++static hb_bool_t ++hb_font_get_glyph_contour_point_parent (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_codepoint_t glyph, ++ unsigned int point_index, ++ hb_position_t *x, ++ hb_position_t *y, ++ void *user_data HB_UNUSED) ++{ ++ hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y); ++ if (ret) ++ font->parent_scale_position (x, y); ++ return ret; ++} + + static hb_bool_t +-hb_font_get_glyph_name_nil (hb_font_t *font, ++hb_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + char *name, unsigned int size, + void *user_data HB_UNUSED) + { +- if (font->parent) +- return font->parent->get_glyph_name (glyph, name, size); +- + if (size) *name = '\0'; + return false; + } ++static hb_bool_t ++hb_font_get_glyph_name_parent (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_codepoint_t glyph, ++ char *name, unsigned int size, ++ void *user_data HB_UNUSED) ++{ ++ return font->parent->get_glyph_name (glyph, name, size); ++} + + static hb_bool_t +-hb_font_get_glyph_from_name_nil (hb_font_t *font, ++hb_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + const char *name, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) + { +- if (font->parent) +- return font->parent->get_glyph_from_name (name, len, glyph); +- + *glyph = 0; + return false; + } +- ++static hb_bool_t ++hb_font_get_glyph_from_name_parent (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ const char *name, int len, /* -1 means nul-terminated */ ++ hb_codepoint_t *glyph, ++ void *user_data HB_UNUSED) ++{ ++ return font->parent->get_glyph_from_name (name, len, glyph); ++} + + static const hb_font_funcs_t _hb_font_funcs_nil = { + HB_OBJECT_HEADER_STATIC, +@@ -222,9 +334,44 @@ + true, /* immutable */ + + { ++#define HB_FONT_FUNC_IMPLEMENT(name) NULL, ++ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS ++#undef HB_FONT_FUNC_IMPLEMENT ++ }, ++ { ++#define HB_FONT_FUNC_IMPLEMENT(name) NULL, ++ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS ++#undef HB_FONT_FUNC_IMPLEMENT ++ }, ++ { ++ { + #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil, ++ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS ++#undef HB_FONT_FUNC_IMPLEMENT ++ } ++ } ++}; ++static const hb_font_funcs_t _hb_font_funcs_parent = { ++ HB_OBJECT_HEADER_STATIC, ++ ++ true, /* immutable */ ++ ++ { ++#define HB_FONT_FUNC_IMPLEMENT(name) NULL, ++ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS ++#undef HB_FONT_FUNC_IMPLEMENT ++ }, ++ { ++#define HB_FONT_FUNC_IMPLEMENT(name) NULL, + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS + #undef HB_FONT_FUNC_IMPLEMENT ++ }, ++ { ++ { ++#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_parent, ++ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS ++#undef HB_FONT_FUNC_IMPLEMENT ++ } + } + }; + +@@ -236,7 +383,7 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_font_funcs_t * + hb_font_funcs_create (void) +@@ -246,7 +393,7 @@ + if (!(ffuncs = hb_object_create<hb_font_funcs_t> ())) + return hb_font_funcs_get_empty (); + +- ffuncs->get = _hb_font_funcs_nil.get; ++ ffuncs->get = _hb_font_funcs_parent.get; + + return ffuncs; + } +@@ -258,12 +405,12 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_font_funcs_t * + hb_font_funcs_get_empty (void) + { +- return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil); ++ return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_parent); + } + + /** +@@ -274,7 +421,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_font_funcs_t * + hb_font_funcs_reference (hb_font_funcs_t *ffuncs) +@@ -288,7 +435,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_font_funcs_destroy (hb_font_funcs_t *ffuncs) +@@ -315,7 +462,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, +@@ -336,7 +483,7 @@ + * + * Return value: (transfer none): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void * + hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs, +@@ -352,7 +499,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs) +@@ -371,7 +518,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs) +@@ -398,11 +545,11 @@ + ffuncs->destroy.name (ffuncs->user_data.name); \ + \ + if (func) { \ +- ffuncs->get.name = func; \ ++ ffuncs->get.f.name = func; \ + ffuncs->user_data.name = user_data; \ + ffuncs->destroy.name = destroy; \ + } else { \ +- ffuncs->get.name = hb_font_get_##name##_nil; \ ++ ffuncs->get.f.name = hb_font_get_##name##_parent; \ + ffuncs->user_data.name = NULL; \ + ffuncs->destroy.name = NULL; \ + } \ +@@ -411,10 +558,53 @@ + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS + #undef HB_FONT_FUNC_IMPLEMENT + ++bool ++hb_font_t::has_func (unsigned int i) ++{ ++ if (parent && parent != hb_font_get_empty () && parent->has_func (i)) ++ return true; ++ return this->klass->get.array[i] != _hb_font_funcs_parent.get.array[i]; ++} + + /* Public getters */ + + /** ++ * hb_font_get_h_extents: ++ * @font: a font. ++ * @extents: (out): ++ * ++ * ++ * ++ * Return value: ++ * ++ * Since: 1.1.3 ++ **/ ++hb_bool_t ++hb_font_get_h_extents (hb_font_t *font, ++ hb_font_extents_t *extents) ++{ ++ return font->get_font_h_extents (extents); ++} ++ ++/** ++ * hb_font_get_v_extents: ++ * @font: a font. ++ * @extents: (out): ++ * ++ * ++ * ++ * Return value: ++ * ++ * Since: 1.1.3 ++ **/ ++hb_bool_t ++hb_font_get_v_extents (hb_font_t *font, ++ hb_font_extents_t *extents) ++{ ++ return font->get_font_v_extents (extents); ++} ++ ++/** + * hb_font_get_glyph: + * @font: a font. + * @unicode: +@@ -425,7 +615,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_font_get_glyph (hb_font_t *font, +@@ -444,7 +634,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_position_t + hb_font_get_glyph_h_advance (hb_font_t *font, +@@ -462,7 +652,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_position_t + hb_font_get_glyph_v_advance (hb_font_t *font, +@@ -482,7 +672,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_font_get_glyph_h_origin (hb_font_t *font, +@@ -503,7 +693,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_font_get_glyph_v_origin (hb_font_t *font, +@@ -523,7 +713,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_position_t + hb_font_get_glyph_h_kerning (hb_font_t *font, +@@ -542,7 +732,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_position_t + hb_font_get_glyph_v_kerning (hb_font_t *font, +@@ -561,7 +751,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_font_get_glyph_extents (hb_font_t *font, +@@ -583,7 +773,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_font_get_glyph_contour_point (hb_font_t *font, +@@ -604,7 +794,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_font_get_glyph_name (hb_font_t *font, +@@ -625,7 +815,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_font_get_glyph_from_name (hb_font_t *font, +@@ -639,6 +829,23 @@ + /* A bit higher-level, and with fallback */ + + /** ++ * hb_font_get_extents_for_direction: ++ * @font: a font. ++ * @direction: ++ * @extents: ++ * ++ * ++ * ++ * Since: 1.1.3 ++ **/ ++void ++hb_font_get_extents_for_direction (hb_font_t *font, ++ hb_direction_t direction, ++ hb_font_extents_t *extents) ++{ ++ return font->get_extents_for_direction (direction, extents); ++} ++/** + * hb_font_get_glyph_advance_for_direction: + * @font: a font. + * @glyph: +@@ -648,7 +855,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_font_get_glyph_advance_for_direction (hb_font_t *font, +@@ -669,7 +876,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_font_get_glyph_origin_for_direction (hb_font_t *font, +@@ -690,7 +897,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_font_add_glyph_origin_for_direction (hb_font_t *font, +@@ -711,7 +918,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_font_subtract_glyph_origin_for_direction (hb_font_t *font, +@@ -733,7 +940,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_font_get_glyph_kerning_for_direction (hb_font_t *font, +@@ -755,7 +962,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_font_get_glyph_extents_for_origin (hb_font_t *font, +@@ -779,7 +986,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_font_get_glyph_contour_point_for_origin (hb_font_t *font, +@@ -800,7 +1007,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_font_glyph_to_string (hb_font_t *font, +@@ -814,7 +1021,7 @@ + /** + * hb_font_glyph_from_string: + * @font: a font. +- * @s: (array length=len): ++ * @s: (array length=len) (element-type uint8_t): + * @len: + * @glyph: (out): + * +@@ -822,7 +1029,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_font_glyph_from_string (hb_font_t *font, +@@ -845,7 +1052,7 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_font_t * + hb_font_create (hb_face_t *face) +@@ -854,15 +1061,16 @@ + + if (unlikely (!face)) + face = hb_face_get_empty (); +- if (unlikely (hb_object_is_inert (face))) +- return hb_font_get_empty (); + if (!(font = hb_object_create<hb_font_t> ())) + return hb_font_get_empty (); + + hb_face_make_immutable (face); ++ font->parent = hb_font_get_empty (); + font->face = hb_face_reference (face); + font->klass = hb_font_funcs_get_empty (); + ++ font->x_scale = font->y_scale = hb_face_get_upem (face); ++ + return font; + } + +@@ -874,20 +1082,19 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_font_t * + hb_font_create_sub_font (hb_font_t *parent) + { + if (unlikely (!parent)) +- return hb_font_get_empty (); ++ parent = hb_font_get_empty (); + + hb_font_t *font = hb_font_create (parent->face); + + if (unlikely (hb_object_is_inert (font))) + return font; + +- hb_font_make_immutable (parent); + font->parent = hb_font_reference (parent); + + font->x_scale = parent->x_scale; +@@ -905,7 +1112,7 @@ + * + * Return value: (transfer full) + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_font_t * + hb_font_get_empty (void) +@@ -918,8 +1125,8 @@ + NULL, /* parent */ + const_cast<hb_face_t *> (&_hb_face_nil), + +- 0, /* x_scale */ +- 0, /* y_scale */ ++ 1000, /* x_scale */ ++ 1000, /* y_scale */ + + 0, /* x_ppem */ + 0, /* y_ppem */ +@@ -946,7 +1153,7 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_font_t * + hb_font_reference (hb_font_t *font) +@@ -960,7 +1167,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_font_destroy (hb_font_t *font) +@@ -993,7 +1200,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_font_set_user_data (hb_font_t *font, +@@ -1014,7 +1221,7 @@ + * + * Return value: (transfer none): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void * + hb_font_get_user_data (hb_font_t *font, +@@ -1029,7 +1236,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_font_make_immutable (hb_font_t *font) +@@ -1037,6 +1244,9 @@ + if (unlikely (hb_object_is_inert (font))) + return; + ++ if (font->parent) ++ hb_font_make_immutable (font->parent); ++ + font->immutable = true; + } + +@@ -1048,7 +1258,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_font_is_immutable (hb_font_t *font) +@@ -1057,6 +1267,32 @@ + } + + /** ++ * hb_font_set_parent: ++ * @font: a font. ++ * @parent: new parent. ++ * ++ * Sets parent font of @font. ++ * ++ * Since: 1.0.5 ++ **/ ++void ++hb_font_set_parent (hb_font_t *font, ++ hb_font_t *parent) ++{ ++ if (font->immutable) ++ return; ++ ++ if (!parent) ++ parent = hb_font_get_empty (); ++ ++ hb_font_t *old = font->parent; ++ ++ font->parent = hb_font_reference (parent); ++ ++ hb_font_destroy (old); ++} ++ ++/** + * hb_font_get_parent: + * @font: a font. + * +@@ -1064,7 +1300,7 @@ + * + * Return value: (transfer none): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_font_t * + hb_font_get_parent (hb_font_t *font) +@@ -1080,7 +1316,7 @@ + * + * Return value: (transfer none): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_face_t * + hb_font_get_face (hb_font_t *font) +@@ -1098,7 +1334,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_font_set_funcs (hb_font_t *font, +@@ -1133,7 +1369,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_font_set_funcs_data (hb_font_t *font, +@@ -1163,7 +1399,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_font_set_scale (hb_font_t *font, +@@ -1185,7 +1421,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_font_get_scale (hb_font_t *font, +@@ -1204,7 +1440,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_font_set_ppem (hb_font_t *font, +@@ -1226,7 +1462,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_font_get_ppem (hb_font_t *font, +diff -uN gfx/harfbuzz/src_old/hb-font.h gfx/harfbuzz/src/hb-font.h +--- gfx/harfbuzz/src_old/hb-font.h 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-font.h 2016-06-05 23:48:49.311185210 +0200 +@@ -46,19 +46,19 @@ + + typedef struct hb_font_funcs_t hb_font_funcs_t; + +-hb_font_funcs_t * ++HB_EXTERN hb_font_funcs_t * + hb_font_funcs_create (void); + +-hb_font_funcs_t * ++HB_EXTERN hb_font_funcs_t * + hb_font_funcs_get_empty (void); + +-hb_font_funcs_t * ++HB_EXTERN hb_font_funcs_t * + hb_font_funcs_reference (hb_font_funcs_t *ffuncs); + +-void ++HB_EXTERN void + hb_font_funcs_destroy (hb_font_funcs_t *ffuncs); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, + hb_user_data_key_t *key, + void * data, +@@ -66,31 +66,56 @@ + hb_bool_t replace); + + +-void * ++HB_EXTERN void * + hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs, + hb_user_data_key_t *key); + + +-void ++HB_EXTERN void + hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs); + + +-/* glyph extents */ ++/* font and glyph extents */ + ++/* Note that typically ascender is positive and descender negative in coordinate systems that grow up. */ ++typedef struct hb_font_extents_t ++{ ++ hb_position_t ascender; /* typographic ascender. */ ++ hb_position_t descender; /* typographic descender. */ ++ hb_position_t line_gap; /* suggested line spacing gap. */ ++ /*< private >*/ ++ hb_position_t reserved9; ++ hb_position_t reserved8; ++ hb_position_t reserved7; ++ hb_position_t reserved6; ++ hb_position_t reserved5; ++ hb_position_t reserved4; ++ hb_position_t reserved3; ++ hb_position_t reserved2; ++ hb_position_t reserved1; ++} hb_font_extents_t; ++ ++/* Note that height is negative in coordinate systems that grow up. */ + typedef struct hb_glyph_extents_t + { +- hb_position_t x_bearing; +- hb_position_t y_bearing; +- hb_position_t width; +- hb_position_t height; ++ hb_position_t x_bearing; /* left side of glyph from origin. */ ++ hb_position_t y_bearing; /* top side of glyph from origin. */ ++ hb_position_t width; /* distance from left to right side. */ ++ hb_position_t height; /* distance from top to bottom side. */ + } hb_glyph_extents_t; + +- + /* func types */ + ++typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *font_data, ++ hb_font_extents_t *metrics, ++ void *user_data); ++typedef hb_font_get_font_extents_func_t hb_font_get_font_h_extents_func_t; ++typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t; ++ ++ + typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t unicode, hb_codepoint_t variation_selector, + hb_codepoint_t *glyph, +@@ -140,6 +165,38 @@ + /* func setters */ + + /** ++ * hb_font_funcs_set_font_h_extents_func: ++ * @ffuncs: font functions. ++ * @func: (closure user_data) (destroy destroy) (scope notified): ++ * @user_data: ++ * @destroy: ++ * ++ * ++ * ++ * Since: 1.1.2 ++ **/ ++HB_EXTERN void ++hb_font_funcs_set_font_h_extents_func (hb_font_funcs_t *ffuncs, ++ hb_font_get_font_h_extents_func_t func, ++ void *user_data, hb_destroy_func_t destroy); ++ ++/** ++ * hb_font_funcs_set_font_v_extents_func: ++ * @ffuncs: font functions. ++ * @func: (closure user_data) (destroy destroy) (scope notified): ++ * @user_data: ++ * @destroy: ++ * ++ * ++ * ++ * Since: 1.1.2 ++ **/ ++HB_EXTERN void ++hb_font_funcs_set_font_v_extents_func (hb_font_funcs_t *ffuncs, ++ hb_font_get_font_v_extents_func_t func, ++ void *user_data, hb_destroy_func_t destroy); ++ ++/** + * hb_font_funcs_set_glyph_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): +@@ -148,9 +205,9 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_func_t func, + void *user_data, hb_destroy_func_t destroy); +@@ -164,9 +221,9 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_h_advance_func_t func, + void *user_data, hb_destroy_func_t destroy); +@@ -180,9 +237,9 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_v_advance_func_t func, + void *user_data, hb_destroy_func_t destroy); +@@ -196,9 +253,9 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_h_origin_func_t func, + void *user_data, hb_destroy_func_t destroy); +@@ -212,9 +269,9 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_v_origin_func_t func, + void *user_data, hb_destroy_func_t destroy); +@@ -228,9 +285,9 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_h_kerning_func_t func, + void *user_data, hb_destroy_func_t destroy); +@@ -244,9 +301,9 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_v_kerning_func_t func, + void *user_data, hb_destroy_func_t destroy); +@@ -260,9 +317,9 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_extents_func_t func, + void *user_data, hb_destroy_func_t destroy); +@@ -276,9 +333,9 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_contour_point_func_t func, + void *user_data, hb_destroy_func_t destroy); +@@ -292,9 +349,9 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_name_func_t func, + void *user_data, hb_destroy_func_t destroy); +@@ -308,59 +365,65 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_from_name_func_t func, + void *user_data, hb_destroy_func_t destroy); + +- + /* func dispatch */ + +-hb_bool_t ++HB_EXTERN hb_bool_t ++hb_font_get_h_extents (hb_font_t *font, ++ hb_font_extents_t *extents); ++HB_EXTERN hb_bool_t ++hb_font_get_v_extents (hb_font_t *font, ++ hb_font_extents_t *extents); ++ ++HB_EXTERN hb_bool_t + hb_font_get_glyph (hb_font_t *font, + hb_codepoint_t unicode, hb_codepoint_t variation_selector, + hb_codepoint_t *glyph); + +-hb_position_t ++HB_EXTERN hb_position_t + hb_font_get_glyph_h_advance (hb_font_t *font, + hb_codepoint_t glyph); +-hb_position_t ++HB_EXTERN hb_position_t + hb_font_get_glyph_v_advance (hb_font_t *font, + hb_codepoint_t glyph); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_get_glyph_h_origin (hb_font_t *font, + hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y); +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_get_glyph_v_origin (hb_font_t *font, + hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y); + +-hb_position_t ++HB_EXTERN hb_position_t + hb_font_get_glyph_h_kerning (hb_font_t *font, + hb_codepoint_t left_glyph, hb_codepoint_t right_glyph); +-hb_position_t ++HB_EXTERN hb_position_t + hb_font_get_glyph_v_kerning (hb_font_t *font, + hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_get_glyph_extents (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_get_glyph_contour_point (hb_font_t *font, + hb_codepoint_t glyph, unsigned int point_index, + hb_position_t *x, hb_position_t *y); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_get_glyph_name (hb_font_t *font, + hb_codepoint_t glyph, + char *name, unsigned int size); +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_get_glyph_from_name (hb_font_t *font, + const char *name, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph); +@@ -368,52 +431,56 @@ + + /* high-level funcs, with fallback */ + +-void ++HB_EXTERN void ++hb_font_get_extents_for_direction (hb_font_t *font, ++ hb_direction_t direction, ++ hb_font_extents_t *extents); ++HB_EXTERN void + hb_font_get_glyph_advance_for_direction (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); +-void ++HB_EXTERN void + hb_font_get_glyph_origin_for_direction (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); +-void ++HB_EXTERN void + hb_font_add_glyph_origin_for_direction (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); +-void ++HB_EXTERN void + hb_font_subtract_glyph_origin_for_direction (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); + +-void ++HB_EXTERN void + hb_font_get_glyph_kerning_for_direction (hb_font_t *font, + hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_get_glyph_extents_for_origin (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_glyph_extents_t *extents); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_get_glyph_contour_point_for_origin (hb_font_t *font, + hb_codepoint_t glyph, unsigned int point_index, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); + + /* Generates gidDDD if glyph has no name. */ +-void ++HB_EXTERN void + hb_font_glyph_to_string (hb_font_t *font, + hb_codepoint_t glyph, + char *s, unsigned int size); + /* Parses gidDDD and uniUUUU strings automatically. */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_glyph_from_string (hb_font_t *font, + const char *s, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph); +@@ -425,22 +492,22 @@ + + /* Fonts are very light-weight objects */ + +-hb_font_t * ++HB_EXTERN hb_font_t * + hb_font_create (hb_face_t *face); + +-hb_font_t * ++HB_EXTERN hb_font_t * + hb_font_create_sub_font (hb_font_t *parent); + +-hb_font_t * ++HB_EXTERN hb_font_t * + hb_font_get_empty (void); + +-hb_font_t * ++HB_EXTERN hb_font_t * + hb_font_reference (hb_font_t *font); + +-void ++HB_EXTERN void + hb_font_destroy (hb_font_t *font); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_set_user_data (hb_font_t *font, + hb_user_data_key_t *key, + void * data, +@@ -448,42 +515,46 @@ + hb_bool_t replace); + + +-void * ++HB_EXTERN void * + hb_font_get_user_data (hb_font_t *font, + hb_user_data_key_t *key); + +-void ++HB_EXTERN void + hb_font_make_immutable (hb_font_t *font); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_is_immutable (hb_font_t *font); + +-hb_font_t * ++HB_EXTERN void ++hb_font_set_parent (hb_font_t *font, ++ hb_font_t *parent); ++ ++HB_EXTERN hb_font_t * + hb_font_get_parent (hb_font_t *font); + +-hb_face_t * ++HB_EXTERN hb_face_t * + hb_font_get_face (hb_font_t *font); + + +-void ++HB_EXTERN void + hb_font_set_funcs (hb_font_t *font, + hb_font_funcs_t *klass, + void *font_data, + hb_destroy_func_t destroy); + + /* Be *very* careful with this function! */ +-void ++HB_EXTERN void + hb_font_set_funcs_data (hb_font_t *font, + void *font_data, + hb_destroy_func_t destroy); + + +-void ++HB_EXTERN void + hb_font_set_scale (hb_font_t *font, + int x_scale, + int y_scale); + +-void ++HB_EXTERN void + hb_font_get_scale (hb_font_t *font, + int *x_scale, + int *y_scale); +@@ -491,12 +562,12 @@ + /* + * A zero value means "no hinting in that direction" + */ +-void ++HB_EXTERN void + hb_font_set_ppem (hb_font_t *font, + unsigned int x_ppem, + unsigned int y_ppem); + +-void ++HB_EXTERN void + hb_font_get_ppem (hb_font_t *font, + unsigned int *x_ppem, + unsigned int *y_ppem); +diff -uN gfx/harfbuzz/src_old/hb-font-private.hh gfx/harfbuzz/src/hb-font-private.hh +--- gfx/harfbuzz/src_old/hb-font-private.hh 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-font-private.hh 2016-06-05 23:48:46.442201028 +0200 +@@ -42,6 +42,8 @@ + */ + + #define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \ ++ HB_FONT_FUNC_IMPLEMENT (font_h_extents) \ ++ HB_FONT_FUNC_IMPLEMENT (font_v_extents) \ + HB_FONT_FUNC_IMPLEMENT (glyph) \ + HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \ + HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \ +@@ -61,14 +63,6 @@ + + hb_bool_t immutable; + +- /* Don't access these directly. Call hb_font_get_*() instead. */ +- +- struct { +-#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name; +- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +-#undef HB_FONT_FUNC_IMPLEMENT +- } get; +- + struct { + #define HB_FONT_FUNC_IMPLEMENT(name) void *name; + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +@@ -80,6 +74,16 @@ + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS + #undef HB_FONT_FUNC_IMPLEMENT + } destroy; ++ ++ /* Don't access these directly. Call font->get_*() instead. */ ++ union get_t { ++ struct get_funcs_t { ++#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name; ++ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS ++#undef HB_FONT_FUNC_IMPLEMENT ++ } f; ++ void (*array[VAR]) (void); ++ } get; + }; + + +@@ -144,7 +148,36 @@ + + /* Public getters */ + +- inline hb_bool_t has_glyph (hb_codepoint_t unicode) ++ HB_INTERNAL bool has_func (unsigned int i); ++ ++ /* has_* ... */ ++#define HB_FONT_FUNC_IMPLEMENT(name) \ ++ bool \ ++ has_##name##_func (void) \ ++ { \ ++ hb_font_funcs_t *funcs = this->klass; \ ++ unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \ ++ return has_func (i); \ ++ } ++ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS ++#undef HB_FONT_FUNC_IMPLEMENT ++ ++ inline hb_bool_t get_font_h_extents (hb_font_extents_t *extents) ++ { ++ memset (extents, 0, sizeof (*extents)); ++ return klass->get.f.font_h_extents (this, user_data, ++ extents, ++ klass->user_data.font_h_extents); ++ } ++ inline hb_bool_t get_font_v_extents (hb_font_extents_t *extents) ++ { ++ memset (extents, 0, sizeof (*extents)); ++ return klass->get.f.font_v_extents (this, user_data, ++ extents, ++ klass->user_data.font_v_extents); ++ } ++ ++ inline bool has_glyph (hb_codepoint_t unicode) + { + hb_codepoint_t glyph; + return get_glyph (unicode, 0, &glyph); +@@ -154,85 +187,85 @@ + hb_codepoint_t *glyph) + { + *glyph = 0; +- return klass->get.glyph (this, user_data, +- unicode, variation_selector, glyph, +- klass->user_data.glyph); ++ return klass->get.f.glyph (this, user_data, ++ unicode, variation_selector, glyph, ++ klass->user_data.glyph); + } + + inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) + { +- return klass->get.glyph_h_advance (this, user_data, +- glyph, +- klass->user_data.glyph_h_advance); ++ return klass->get.f.glyph_h_advance (this, user_data, ++ glyph, ++ klass->user_data.glyph_h_advance); + } + + inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph) + { +- return klass->get.glyph_v_advance (this, user_data, +- glyph, +- klass->user_data.glyph_v_advance); ++ return klass->get.f.glyph_v_advance (this, user_data, ++ glyph, ++ klass->user_data.glyph_v_advance); + } + + inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + *x = *y = 0; +- return klass->get.glyph_h_origin (this, user_data, +- glyph, x, y, +- klass->user_data.glyph_h_origin); ++ return klass->get.f.glyph_h_origin (this, user_data, ++ glyph, x, y, ++ klass->user_data.glyph_h_origin); + } + + inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + *x = *y = 0; +- return klass->get.glyph_v_origin (this, user_data, +- glyph, x, y, +- klass->user_data.glyph_v_origin); ++ return klass->get.f.glyph_v_origin (this, user_data, ++ glyph, x, y, ++ klass->user_data.glyph_v_origin); + } + + inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) + { +- return klass->get.glyph_h_kerning (this, user_data, +- left_glyph, right_glyph, +- klass->user_data.glyph_h_kerning); ++ return klass->get.f.glyph_h_kerning (this, user_data, ++ left_glyph, right_glyph, ++ klass->user_data.glyph_h_kerning); + } + + inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph) + { +- return klass->get.glyph_v_kerning (this, user_data, +- top_glyph, bottom_glyph, +- klass->user_data.glyph_v_kerning); ++ return klass->get.f.glyph_v_kerning (this, user_data, ++ top_glyph, bottom_glyph, ++ klass->user_data.glyph_v_kerning); + } + + inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph, + hb_glyph_extents_t *extents) + { + memset (extents, 0, sizeof (*extents)); +- return klass->get.glyph_extents (this, user_data, +- glyph, +- extents, +- klass->user_data.glyph_extents); ++ return klass->get.f.glyph_extents (this, user_data, ++ glyph, ++ extents, ++ klass->user_data.glyph_extents); + } + + inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index, + hb_position_t *x, hb_position_t *y) + { + *x = *y = 0; +- return klass->get.glyph_contour_point (this, user_data, +- glyph, point_index, +- x, y, +- klass->user_data.glyph_contour_point); ++ return klass->get.f.glyph_contour_point (this, user_data, ++ glyph, point_index, ++ x, y, ++ klass->user_data.glyph_contour_point); + } + + inline hb_bool_t get_glyph_name (hb_codepoint_t glyph, + char *name, unsigned int size) + { + if (size) *name = '\0'; +- return klass->get.glyph_name (this, user_data, +- glyph, +- name, size, +- klass->user_data.glyph_name); ++ return klass->get.f.glyph_name (this, user_data, ++ glyph, ++ name, size, ++ klass->user_data.glyph_name); + } + + inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */ +@@ -240,15 +273,35 @@ + { + *glyph = 0; + if (len == -1) len = strlen (name); +- return klass->get.glyph_from_name (this, user_data, +- name, len, +- glyph, +- klass->user_data.glyph_from_name); ++ return klass->get.f.glyph_from_name (this, user_data, ++ name, len, ++ glyph, ++ klass->user_data.glyph_from_name); + } + + + /* A bit higher-level, and with fallback */ + ++ inline void get_extents_for_direction (hb_direction_t direction, ++ hb_font_extents_t *extents) ++ { ++ if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { ++ if (!get_font_h_extents (extents)) ++ { ++ extents->ascender = y_scale * .8; ++ extents->descender = y_scale - extents->ascender; ++ extents->line_gap = 0; ++ } ++ } else { ++ if (!get_font_v_extents (extents)) ++ { ++ extents->ascender = x_scale / 2; ++ extents->descender = x_scale - extents->ascender; ++ extents->line_gap = 0; ++ } ++ } ++ } ++ + inline void get_glyph_advance_for_direction (hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) +@@ -268,7 +321,7 @@ + { + *x = get_glyph_h_advance (glyph) / 2; + +- /* TODO use font_metics.ascent */ ++ /* TODO use font_extents.ascender */ + *y = y_scale; + } + +@@ -298,6 +351,26 @@ + } + } + ++ inline void add_glyph_h_origin (hb_codepoint_t glyph, ++ hb_position_t *x, hb_position_t *y) ++ { ++ hb_position_t origin_x, origin_y; ++ ++ get_glyph_h_origin (glyph, &origin_x, &origin_y); ++ ++ *x += origin_x; ++ *y += origin_y; ++ } ++ inline void add_glyph_v_origin (hb_codepoint_t glyph, ++ hb_position_t *x, hb_position_t *y) ++ { ++ hb_position_t origin_x, origin_y; ++ ++ get_glyph_v_origin (glyph, &origin_x, &origin_y); ++ ++ *x += origin_x; ++ *y += origin_y; ++ } + inline void add_glyph_origin_for_direction (hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) +@@ -310,6 +383,26 @@ + *y += origin_y; + } + ++ inline void subtract_glyph_h_origin (hb_codepoint_t glyph, ++ hb_position_t *x, hb_position_t *y) ++ { ++ hb_position_t origin_x, origin_y; ++ ++ get_glyph_h_origin (glyph, &origin_x, &origin_y); ++ ++ *x -= origin_x; ++ *y -= origin_y; ++ } ++ inline void subtract_glyph_v_origin (hb_codepoint_t glyph, ++ hb_position_t *x, hb_position_t *y) ++ { ++ hb_position_t origin_x, origin_y; ++ ++ get_glyph_v_origin (glyph, &origin_x, &origin_y); ++ ++ *x -= origin_x; ++ *y -= origin_y; ++ } + inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) +diff -uN gfx/harfbuzz/src_old/hb-ft.cc gfx/harfbuzz/src/hb-ft.cc +--- gfx/harfbuzz/src_old/hb-ft.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ft.cc 2016-06-05 23:48:50.916176399 +0200 +@@ -1,6 +1,7 @@ + /* + * Copyright © 2009 Red Hat, Inc. + * Copyright © 2009 Keith Stribley ++ * Copyright © 2015 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * +@@ -23,6 +24,7 @@ + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod ++ * Google Author(s): Behdad Esfahbod + */ + + #include "hb-private.hh" +@@ -46,10 +48,15 @@ + * In general, this file does a fine job of what it's supposed to do. + * There are, however, things that need more work: + * +- * - We don't handle any load_flags. That definitely has API implications. :( +- * I believe hb_ft_font_create() should take load_flags input. +- * In particular, FT_Get_Advance() without the NO_HINTING flag seems to be +- * buggy. ++ * - I remember seeing FT_Get_Advance() without the NO_HINTING flag to be buggy. ++ * Have not investigated. ++ * ++ * - FreeType works in 26.6 mode. Clients can decide to use that mode, and everything ++ * would work fine. However, we also abuse this API for performing in font-space, ++ * but don't pass the correct flags to FreeType. We just abuse the no-hinting mode ++ * for that, such that no rounding etc happens. As such, we don't set ppem, and ++ * pass NO_HINTING as load_flags. Would be much better to use NO_SCALE, and scale ++ * ourselves, like we do in uniscribe, etc. + * + * - We don't handle / allow for emboldening / obliqueing. + * +@@ -59,6 +66,94 @@ + */ + + ++struct hb_ft_font_t ++{ ++ FT_Face ft_face; ++ int load_flags; ++ bool unref; /* Whether to destroy ft_face when done. */ ++}; ++ ++static hb_ft_font_t * ++_hb_ft_font_create (FT_Face ft_face, bool unref) ++{ ++ hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t)); ++ ++ if (unlikely (!ft_font)) ++ return NULL; ++ ++ ft_font->ft_face = ft_face; ++ ft_font->unref = unref; ++ ++ ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; ++ ++ return ft_font; ++} ++ ++static void ++_hb_ft_font_destroy (hb_ft_font_t *ft_font) ++{ ++ if (ft_font->unref) ++ FT_Done_Face (ft_font->ft_face); ++ ++ free (ft_font); ++} ++ ++/** ++ * hb_ft_font_set_load_flags: ++ * @font: ++ * @load_flags: ++ * ++ * ++ * ++ * Since: 1.0.5 ++ **/ ++void ++hb_ft_font_set_load_flags (hb_font_t *font, int load_flags) ++{ ++ if (font->immutable) ++ return; ++ ++ if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) ++ return; ++ ++ hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data; ++ ++ ft_font->load_flags = load_flags; ++} ++ ++/** ++ * hb_ft_font_get_load_flags: ++ * @font: ++ * ++ * ++ * ++ * Return value: ++ * Since: 1.0.5 ++ **/ ++int ++hb_ft_font_get_load_flags (hb_font_t *font) ++{ ++ if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) ++ return 0; ++ ++ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data; ++ ++ return ft_font->load_flags; ++} ++ ++FT_Face ++hb_ft_font_get_face (hb_font_t *font) ++{ ++ if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) ++ return NULL; ++ ++ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data; ++ ++ return ft_font->ft_face; ++} ++ ++ ++ + static hb_bool_t + hb_ft_get_glyph (hb_font_t *font HB_UNUSED, + void *font_data, +@@ -68,17 +163,19 @@ + void *user_data HB_UNUSED) + + { +- FT_Face ft_face = (FT_Face) font_data; ++ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; ++ unsigned int g; + +-#ifdef HAVE_FT_FACE_GETCHARVARIANTINDEX +- if (unlikely (variation_selector)) { +- *glyph = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector); +- return *glyph != 0; +- } +-#endif ++ if (likely (!variation_selector)) ++ g = FT_Get_Char_Index (ft_font->ft_face, unicode); ++ else ++ g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector); + +- *glyph = FT_Get_Char_Index (ft_face, unicode); +- return *glyph != 0; ++ if (unlikely (!g)) ++ return false; ++ ++ *glyph = g; ++ return true; + } + + static hb_position_t +@@ -87,13 +184,15 @@ + hb_codepoint_t glyph, + void *user_data HB_UNUSED) + { +- FT_Face ft_face = (FT_Face) font_data; +- int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; ++ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + FT_Fixed v; + +- if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v))) ++ if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags, &v))) + return 0; + ++ if (font->x_scale < 0) ++ v = -v; ++ + return (v + (1<<9)) >> 10; + } + +@@ -103,31 +202,21 @@ + hb_codepoint_t glyph, + void *user_data HB_UNUSED) + { +- FT_Face ft_face = (FT_Face) font_data; +- int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING | FT_LOAD_VERTICAL_LAYOUT; ++ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + FT_Fixed v; + +- if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v))) ++ if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v))) + return 0; + ++ if (font->y_scale < 0) ++ v = -v; ++ + /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates + * have a Y growing upward. Hence the extra negation. */ + return (-v + (1<<9)) >> 10; + } + + static hb_bool_t +-hb_ft_get_glyph_h_origin (hb_font_t *font HB_UNUSED, +- void *font_data HB_UNUSED, +- hb_codepoint_t glyph HB_UNUSED, +- hb_position_t *x HB_UNUSED, +- hb_position_t *y HB_UNUSED, +- void *user_data HB_UNUSED) +-{ +- /* We always work in the horizontal coordinates. */ +- return true; +-} +- +-static hb_bool_t + hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED, + void *font_data, + hb_codepoint_t glyph, +@@ -135,10 +224,10 @@ + hb_position_t *y, + void *user_data HB_UNUSED) + { +- FT_Face ft_face = (FT_Face) font_data; +- int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; ++ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; ++ FT_Face ft_face = ft_font->ft_face; + +- if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags))) ++ if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) + return false; + + /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates +@@ -146,6 +235,11 @@ + *x = ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBearingX; + *y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY); + ++ if (font->x_scale < 0) ++ *x = -*x; ++ if (font->y_scale < 0) ++ *y = -*y; ++ + return true; + } + +@@ -156,27 +250,16 @@ + hb_codepoint_t right_glyph, + void *user_data HB_UNUSED) + { +- FT_Face ft_face = (FT_Face) font_data; ++ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + FT_Vector kerningv; + + FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED; +- if (FT_Get_Kerning (ft_face, left_glyph, right_glyph, mode, &kerningv)) ++ if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv)) + return 0; + + return kerningv.x; + } + +-static hb_position_t +-hb_ft_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, +- void *font_data HB_UNUSED, +- hb_codepoint_t top_glyph HB_UNUSED, +- hb_codepoint_t bottom_glyph HB_UNUSED, +- void *user_data HB_UNUSED) +-{ +- /* FreeType API doesn't support vertical kerning */ +- return 0; +-} +- + static hb_bool_t + hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED, + void *font_data, +@@ -184,16 +267,26 @@ + hb_glyph_extents_t *extents, + void *user_data HB_UNUSED) + { +- FT_Face ft_face = (FT_Face) font_data; +- int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; ++ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; ++ FT_Face ft_face = ft_font->ft_face; + +- if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags))) ++ if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) + return false; + + extents->x_bearing = ft_face->glyph->metrics.horiBearingX; + extents->y_bearing = ft_face->glyph->metrics.horiBearingY; + extents->width = ft_face->glyph->metrics.width; + extents->height = -ft_face->glyph->metrics.height; ++ if (font->x_scale < 0) ++ { ++ extents->x_bearing = -extents->x_bearing; ++ extents->width = -extents->width; ++ } ++ if (font->y_scale < 0) ++ { ++ extents->y_bearing = -extents->y_bearing; ++ extents->height = -extents->height; ++ } + return true; + } + +@@ -206,10 +299,10 @@ + hb_position_t *y, + void *user_data HB_UNUSED) + { +- FT_Face ft_face = (FT_Face) font_data; +- int load_flags = FT_LOAD_DEFAULT; ++ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; ++ FT_Face ft_face = ft_font->ft_face; + +- if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags))) ++ if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) + return false; + + if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)) +@@ -231,9 +324,9 @@ + char *name, unsigned int size, + void *user_data HB_UNUSED) + { +- FT_Face ft_face = (FT_Face) font_data; ++ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + +- hb_bool_t ret = !FT_Get_Glyph_Name (ft_face, glyph, name, size); ++ hb_bool_t ret = !FT_Get_Glyph_Name (ft_font->ft_face, glyph, name, size); + if (ret && (size && !*name)) + ret = false; + +@@ -247,7 +340,8 @@ + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) + { +- FT_Face ft_face = (FT_Face) font_data; ++ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; ++ FT_Face ft_face = ft_font->ft_face; + + if (len < 0) + *glyph = FT_Get_Name_Index (ft_face, (FT_String *) name); +@@ -272,23 +366,76 @@ + return *glyph != 0; + } + ++static hb_bool_t ++hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED, ++ void *font_data, ++ hb_font_extents_t *metrics, ++ void *user_data HB_UNUSED) ++{ ++ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; ++ FT_Face ft_face = ft_font->ft_face; ++ metrics->ascender = ft_face->size->metrics.ascender; ++ metrics->descender = ft_face->size->metrics.descender; ++ metrics->line_gap = ft_face->size->metrics.height - (ft_face->size->metrics.ascender - ft_face->size->metrics.descender); ++ if (font->y_scale < 0) ++ { ++ metrics->ascender = -metrics->ascender; ++ metrics->descender = -metrics->descender; ++ metrics->line_gap = -metrics->line_gap; ++ } ++ return true; ++} ++ ++static hb_font_funcs_t *static_ft_funcs = NULL; ++ ++#ifdef HB_USE_ATEXIT ++static ++void free_static_ft_funcs (void) ++{ ++ hb_font_funcs_destroy (static_ft_funcs); ++} ++#endif + +-static hb_font_funcs_t * +-_hb_ft_get_font_funcs (void) ++static void ++_hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref) + { +- static const hb_font_funcs_t ft_ffuncs = { +- HB_OBJECT_HEADER_STATIC, ++retry: ++ hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs); ++ ++ if (unlikely (!funcs)) ++ { ++ funcs = hb_font_funcs_create (); ++ ++ hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, NULL, NULL); ++ //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, NULL, NULL); ++ hb_font_funcs_set_glyph_func (funcs, hb_ft_get_glyph, NULL, NULL); ++ hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, NULL, NULL); ++ hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, NULL, NULL); ++ //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, NULL, NULL); ++ hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, NULL, NULL); ++ hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, NULL, NULL); ++ //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, NULL, NULL); ++ hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, NULL, NULL); ++ hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, NULL, NULL); ++ hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, NULL, NULL); ++ hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, NULL, NULL); + +- true, /* immutable */ ++ hb_font_funcs_make_immutable (funcs); + +- { +-#define HB_FONT_FUNC_IMPLEMENT(name) hb_ft_get_##name, +- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +-#undef HB_FONT_FUNC_IMPLEMENT ++ if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, NULL, funcs)) { ++ hb_font_funcs_destroy (funcs); ++ goto retry; + } ++ ++#ifdef HB_USE_ATEXIT ++ atexit (free_static_ft_funcs); /* First person registers atexit() callback. */ ++#endif + }; + +- return const_cast<hb_font_funcs_t *> (&ft_ffuncs); ++ hb_font_set_funcs (font, ++ funcs, ++ _hb_ft_font_create (ft_face, unref), ++ (hb_destroy_func_t) _hb_ft_font_destroy); + } + + +@@ -327,7 +474,7 @@ + * + * + * Return value: (transfer full): +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_face_t * + hb_ft_face_create (FT_Face ft_face, +@@ -340,11 +487,7 @@ + + blob = hb_blob_create ((const char *) ft_face->stream->base, + (unsigned int) ft_face->stream->size, +- /* TODO: We assume that it's mmap()'ed, but FreeType code +- * suggests that there are cases we reach here but font is +- * not mmapped. For example, when mmap() fails. No idea +- * how to deal with it better here. */ +- HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, ++ HB_MEMORY_MODE_READONLY, + ft_face, destroy); + face = hb_face_create (blob, ft_face->face_index); + hb_blob_destroy (blob); +@@ -358,6 +501,22 @@ + return face; + } + ++/** ++ * hb_ft_face_create_referenced: ++ * @ft_face: ++ * ++ * ++ * ++ * Return value: (transfer full): ++ * Since: 0.9.38 ++ **/ ++hb_face_t * ++hb_ft_face_create_referenced (FT_Face ft_face) ++{ ++ FT_Reference_Face (ft_face); ++ return hb_ft_face_create (ft_face, (hb_destroy_func_t) FT_Done_Face); ++} ++ + static void + hb_ft_face_finalize (FT_Face ft_face) + { +@@ -371,7 +530,7 @@ + * + * + * Return value: (transfer full): +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_face_t * + hb_ft_face_create_cached (FT_Face ft_face) +@@ -388,11 +547,6 @@ + return hb_face_reference ((hb_face_t *) ft_face->generic.data); + } + +-static void +-_do_nothing (void) +-{ +-} +- + + /** + * hb_ft_font_create: +@@ -402,7 +556,7 @@ + * + * + * Return value: (transfer full): +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_font_t * + hb_ft_font_create (FT_Face ft_face, +@@ -414,29 +568,47 @@ + face = hb_ft_face_create (ft_face, destroy); + font = hb_font_create (face); + hb_face_destroy (face); +- hb_font_set_funcs (font, +- _hb_ft_get_font_funcs (), +- ft_face, (hb_destroy_func_t) _do_nothing); ++ _hb_ft_font_set_funcs (font, ft_face, false); + hb_font_set_scale (font, + (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16), + (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16)); ++#if 0 /* hb-ft works in no-hinting model */ + hb_font_set_ppem (font, + ft_face->size->metrics.x_ppem, + ft_face->size->metrics.y_ppem); ++#endif + + return font; + } + ++/** ++ * hb_ft_font_create_referenced: ++ * @ft_face: ++ * ++ * ++ * ++ * Return value: (transfer full): ++ * Since: 0.9.38 ++ **/ ++hb_font_t * ++hb_ft_font_create_referenced (FT_Face ft_face) ++{ ++ FT_Reference_Face (ft_face); ++ return hb_ft_font_create (ft_face, (hb_destroy_func_t) FT_Done_Face); ++} ++ + + /* Thread-safe, lock-free, FT_Library */ + + static FT_Library ft_library; + +-static inline ++#ifdef HB_USE_ATEXIT ++static + void free_ft_library (void) + { + FT_Done_FreeType (ft_library); + } ++#endif + + static FT_Library + get_ft_library (void) +@@ -493,30 +665,23 @@ + + FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE); + +- assert (font->y_scale >= 0); + FT_Set_Char_Size (ft_face, +- font->x_scale, font->y_scale, ++ abs (font->x_scale), abs (font->y_scale), + 0, 0); + #if 0 + font->x_ppem * 72 * 64 / font->x_scale, + font->y_ppem * 72 * 64 / font->y_scale); + #endif ++ if (font->x_scale < 0 || font->y_scale < 0) ++ { ++ FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0, ++ 0, font->y_scale < 0 ? -1 : +1}; ++ FT_Set_Transform (ft_face, &matrix, NULL); ++ } + + ft_face->generic.data = blob; + ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob; + +- hb_font_set_funcs (font, +- _hb_ft_get_font_funcs (), +- ft_face, +- (hb_destroy_func_t) FT_Done_Face); +-} +- +-FT_Face +-hb_ft_font_get_face (hb_font_t *font) +-{ +- if (font->destroy == (hb_destroy_func_t) FT_Done_Face || +- font->destroy == (hb_destroy_func_t) _do_nothing) +- return (FT_Face) font->user_data; +- +- return NULL; ++ _hb_ft_font_set_funcs (font, ft_face, true); ++ hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING); + } +diff -uN gfx/harfbuzz/src_old/hb-ft.h gfx/harfbuzz/src/hb-ft.h +--- gfx/harfbuzz/src_old/hb-ft.h 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ft.h 2016-06-05 23:48:52.044170188 +0200 +@@ -1,5 +1,6 @@ + /* + * Copyright © 2009 Red Hat, Inc. ++ * Copyright © 2015 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * +@@ -22,6 +23,7 @@ + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod ++ * Google Author(s): Behdad Esfahbod + */ + + #ifndef HB_FT_H +@@ -34,28 +36,90 @@ + + HB_BEGIN_DECLS + +-/* Note: FreeType is not thread-safe. Hence, these functions are not either. */ ++/* ++ * Note: FreeType is not thread-safe. ++ * Hence, these functions are not either. ++ */ + +-hb_face_t * ++/* ++ * hb-face from ft-face. ++ */ ++ ++/* This one creates a new hb-face for given ft-face. ++ * When the returned hb-face is destroyed, the destroy ++ * callback is called (if not NULL), with the ft-face passed ++ * to it. ++ * ++ * The client is responsible to make sure that ft-face is ++ * destroyed after hb-face is destroyed. ++ * ++ * Most often you don't want this function. You should use either ++ * hb_ft_face_create_cached(), or hb_ft_face_create_referenced(). ++ * In particular, if you are going to pass NULL as destroy, you ++ * probably should use (the more recent) hb_ft_face_create_referenced() ++ * instead. ++ */ ++HB_EXTERN hb_face_t * + hb_ft_face_create (FT_Face ft_face, + hb_destroy_func_t destroy); + +-hb_face_t * ++/* This version is like hb_ft_face_create(), except that it caches ++ * the hb-face using the generic pointer of the ft-face. This means ++ * that subsequent calls to this function with the same ft-face will ++ * return the same hb-face (correctly referenced). ++ * ++ * Client is still responsible for making sure that ft-face is destroyed ++ * after hb-face is. ++ */ ++HB_EXTERN hb_face_t * + hb_ft_face_create_cached (FT_Face ft_face); + +-hb_font_t * ++/* This version is like hb_ft_face_create(), except that it calls ++ * FT_Reference_Face() on ft-face, as such keeping ft-face alive ++ * as long as the hb-face is. ++ * ++ * This is the most convenient version to use. Use it unless you have ++ * very good reasons not to. ++ */ ++HB_EXTERN hb_face_t * ++hb_ft_face_create_referenced (FT_Face ft_face); ++ ++ ++/* ++ * hb-font from ft-face. ++ */ ++ ++/* ++ * Note: ++ * ++ * Set face size on ft-face before creating hb-font from it. ++ * Otherwise hb-ft would NOT pick up the font size correctly. ++ */ ++ ++/* See notes on hb_ft_face_create(). Same issues re lifecycle-management ++ * apply here. Use hb_ft_font_create_referenced() if you can. */ ++HB_EXTERN hb_font_t * + hb_ft_font_create (FT_Face ft_face, + hb_destroy_func_t destroy); + ++/* See notes on hb_ft_face_create_referenced() re lifecycle-management ++ * issues. */ ++HB_EXTERN hb_font_t * ++hb_ft_font_create_referenced (FT_Face ft_face); ++ ++HB_EXTERN FT_Face ++hb_ft_font_get_face (hb_font_t *font); ++ ++HB_EXTERN void ++hb_ft_font_set_load_flags (hb_font_t *font, int load_flags); + ++HB_EXTERN int ++hb_ft_font_get_load_flags (hb_font_t *font); + + /* Makes an hb_font_t use FreeType internally to implement font functions. */ +-void ++HB_EXTERN void + hb_ft_font_set_funcs (hb_font_t *font); + +-FT_Face +-hb_ft_font_get_face (hb_font_t *font); +- + + HB_END_DECLS + +diff -uN gfx/harfbuzz/src_old/hb-glib.cc gfx/harfbuzz/src/hb-glib.cc +--- gfx/harfbuzz/src_old/hb-glib.cc 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-glib.cc 2016-06-05 23:48:53.244163610 +0200 +@@ -382,3 +382,19 @@ + return const_cast<hb_unicode_funcs_t *> (&_hb_glib_unicode_funcs); + } + ++/** ++ * hb_glib_blob_create: ++ * ++ * Since: 0.9.38 ++ **/ ++hb_blob_t * ++hb_glib_blob_create (GBytes *gbytes) ++{ ++ gsize size = 0; ++ gconstpointer data = g_bytes_get_data (gbytes, &size); ++ return hb_blob_create ((const char *) data, ++ size, ++ HB_MEMORY_MODE_READONLY, ++ g_bytes_ref (gbytes), ++ (hb_destroy_func_t) g_bytes_unref); ++} +diff -uN gfx/harfbuzz/src_old/hb-glib.h gfx/harfbuzz/src/hb-glib.h +--- gfx/harfbuzz/src_old/hb-glib.h 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-glib.h 2016-06-05 23:48:54.401157255 +0200 +@@ -36,16 +36,19 @@ + HB_BEGIN_DECLS + + +-hb_script_t ++HB_EXTERN hb_script_t + hb_glib_script_to_script (GUnicodeScript script); + +-GUnicodeScript ++HB_EXTERN GUnicodeScript + hb_glib_script_from_script (hb_script_t script); + + +-hb_unicode_funcs_t * ++HB_EXTERN hb_unicode_funcs_t * + hb_glib_get_unicode_funcs (void); + ++HB_EXTERN hb_blob_t * ++hb_glib_blob_create (GBytes *gbytes); ++ + + HB_END_DECLS + +diff -uN gfx/harfbuzz/src_old/hb-gobject-enums.h.tmpl gfx/harfbuzz/src/hb-gobject-enums.h.tmpl +--- gfx/harfbuzz/src_old/hb-gobject-enums.h.tmpl 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-gobject-enums.h.tmpl 2016-06-05 23:48:57.189141987 +0200 +@@ -42,7 +42,7 @@ + /*** END file-header ***/ + + /*** BEGIN value-header ***/ +-GType @enum_name@_get_type (void) G_GNUC_CONST; ++HB_EXTERN GType @enum_name@_get_type (void) G_GNUC_CONST; + #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) + + /*** END value-header ***/ +diff -uN gfx/harfbuzz/src_old/hb-gobject-structs.cc gfx/harfbuzz/src/hb-gobject-structs.cc +--- gfx/harfbuzz/src_old/hb-gobject-structs.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-gobject-structs.cc 2016-06-05 23:48:58.408135321 +0200 +@@ -54,6 +54,17 @@ + #define HB_DEFINE_OBJECT_TYPE(name) \ + HB_DEFINE_BOXED_TYPE (name, hb_##name##_reference, hb_##name##_destroy); + ++#define HB_DEFINE_VALUE_TYPE(name) \ ++ static hb_##name##_t *_hb_##name##_reference (const hb_##name##_t *l) \ ++ { \ ++ hb_##name##_t *c = (hb_##name##_t *) calloc (1, sizeof (hb_##name##_t)); \ ++ if (unlikely (!c)) return NULL; \ ++ *c = *l; \ ++ return c; \ ++ } \ ++ static void _hb_##name##_destroy (hb_##name##_t *l) { free (l); } \ ++ HB_DEFINE_BOXED_TYPE (name, _hb_##name##_reference, _hb_##name##_destroy); ++ + HB_DEFINE_OBJECT_TYPE (buffer) + HB_DEFINE_OBJECT_TYPE (blob) + HB_DEFINE_OBJECT_TYPE (face) +@@ -62,59 +73,8 @@ + HB_DEFINE_OBJECT_TYPE (set) + HB_DEFINE_OBJECT_TYPE (shape_plan) + HB_DEFINE_OBJECT_TYPE (unicode_funcs) +- +- +-static hb_feature_t *feature_reference (hb_feature_t *g) +-{ +- hb_feature_t *c = (hb_feature_t *) calloc (1, sizeof (hb_feature_t)); +- if (unlikely (!c)) return NULL; +- *c = *g; +- return c; +-} +-static void feature_destroy (hb_feature_t *g) { free (g); } +-HB_DEFINE_BOXED_TYPE (feature, feature_reference, feature_destroy) +- +-static hb_glyph_info_t *glyph_info_reference (hb_glyph_info_t *g) +-{ +- hb_glyph_info_t *c = (hb_glyph_info_t *) calloc (1, sizeof (hb_glyph_info_t)); +- if (unlikely (!c)) return NULL; +- *c = *g; +- return c; +-} +-static void glyph_info_destroy (hb_glyph_info_t *g) { free (g); } +-HB_DEFINE_BOXED_TYPE (glyph_info, glyph_info_reference, glyph_info_destroy) +- +-static hb_glyph_position_t *glyph_position_reference (hb_glyph_position_t *g) +-{ +- hb_glyph_position_t *c = (hb_glyph_position_t *) calloc (1, sizeof (hb_glyph_position_t)); +- if (unlikely (!c)) return NULL; +- *c = *g; +- return c; +-} +-static void glyph_position_destroy (hb_glyph_position_t *g) { free (g); } +-HB_DEFINE_BOXED_TYPE (glyph_position, glyph_position_reference, glyph_position_destroy) +- +-static hb_segment_properties_t *segment_properties_reference (hb_segment_properties_t *g) +-{ +- hb_segment_properties_t *c = (hb_segment_properties_t *) calloc (1, sizeof (hb_segment_properties_t)); +- if (unlikely (!c)) return NULL; +- *c = *g; +- return c; +-} +-static void segment_properties_destroy (hb_segment_properties_t *g) { free (g); } +-HB_DEFINE_BOXED_TYPE (segment_properties, segment_properties_reference, segment_properties_destroy) +- +-static hb_user_data_key_t user_data_key_reference (hb_user_data_key_t l) { return l; } +-static void user_data_key_destroy (hb_user_data_key_t l) { } +-HB_DEFINE_BOXED_TYPE (user_data_key, user_data_key_reference, user_data_key_destroy) +- +- +-static hb_language_t *language_reference (hb_language_t *l) +-{ +- hb_language_t *c = (hb_language_t *) calloc (1, sizeof (hb_language_t)); +- if (unlikely (!c)) return NULL; +- *c = *l; +- return c; +-} +-static void language_destroy (hb_language_t *l) { free (l); } +-HB_DEFINE_BOXED_TYPE (language, language_reference, language_destroy) ++HB_DEFINE_VALUE_TYPE (feature) ++HB_DEFINE_VALUE_TYPE (glyph_info) ++HB_DEFINE_VALUE_TYPE (glyph_position) ++HB_DEFINE_VALUE_TYPE (segment_properties) ++HB_DEFINE_VALUE_TYPE (user_data_key) +diff -uN gfx/harfbuzz/src_old/hb-gobject-structs.h gfx/harfbuzz/src/hb-gobject-structs.h +--- gfx/harfbuzz/src_old/hb-gobject-structs.h 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-gobject-structs.h 2016-06-05 23:48:59.577128929 +0200 +@@ -40,55 +40,65 @@ + + /* Object types */ + +-GType hb_gobject_blob_get_type (void); ++/** ++ * Since: 0.9.2 ++ **/ ++HB_EXTERN GType hb_gobject_blob_get_type (void); + #define HB_GOBJECT_TYPE_BLOB (hb_gobject_blob_get_type ()) + +-GType hb_gobject_buffer_get_type (void); ++/** ++ * Since: 0.9.2 ++ **/ ++HB_EXTERN GType hb_gobject_buffer_get_type (void); + #define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ()) + +-GType hb_gobject_face_get_type (void); ++/** ++ * Since: 0.9.2 ++ **/ ++HB_EXTERN GType hb_gobject_face_get_type (void); + #define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ()) + +-GType hb_gobject_font_get_type (void); ++/** ++ * Since: 0.9.2 ++ **/ ++HB_EXTERN GType hb_gobject_font_get_type (void); + #define HB_GOBJECT_TYPE_FONT (hb_gobject_font_get_type ()) + +-GType hb_gobject_font_funcs_get_type (void); ++/** ++ * Since: 0.9.2 ++ **/ ++HB_EXTERN GType hb_gobject_font_funcs_get_type (void); + #define HB_GOBJECT_TYPE_FONT_FUNCS (hb_gobject_font_funcs_get_type ()) + +-GType hb_gobject_set_get_type (void); ++HB_EXTERN GType hb_gobject_set_get_type (void); + #define HB_GOBJECT_TYPE_SET (hb_gobject_set_get_type ()) + +-GType hb_gobject_shape_plan_get_type (void); ++HB_EXTERN GType hb_gobject_shape_plan_get_type (void); + #define HB_GOBJECT_TYPE_SHAPE_PLAN (hb_gobject_shape_plan_get_type ()) + +-GType hb_gobject_unicode_funcs_get_type (void); ++/** ++ * Since: 0.9.2 ++ **/ ++HB_EXTERN GType hb_gobject_unicode_funcs_get_type (void); + #define HB_GOBJECT_TYPE_UNICODE_FUNCS (hb_gobject_unicode_funcs_get_type ()) + + /* Value types */ + +-GType hb_gobject_feature_get_type (void); ++HB_EXTERN GType hb_gobject_feature_get_type (void); + #define HB_GOBJECT_TYPE_FEATURE (hb_gobject_feature_get_type ()) + +-GType hb_gobject_glyph_info_get_type (void); ++HB_EXTERN GType hb_gobject_glyph_info_get_type (void); + #define HB_GOBJECT_TYPE_GLYPH_INFO (hb_gobject_glyph_info_get_type ()) + +-GType hb_gobject_glyph_position_get_type (void); ++HB_EXTERN GType hb_gobject_glyph_position_get_type (void); + #define HB_GOBJECT_TYPE_GLYPH_POSITION (hb_gobject_glyph_position_get_type ()) + +-GType hb_gobject_segment_properties_get_type (void); ++HB_EXTERN GType hb_gobject_segment_properties_get_type (void); + #define HB_GOBJECT_TYPE_SEGMENT_PROPERTIES (hb_gobject_segment_properties_get_type ()) + +-GType hb_gobject_user_data_key_get_type (void); ++HB_EXTERN GType hb_gobject_user_data_key_get_type (void); + #define HB_GOBJECT_TYPE_USER_DATA_KEY (hb_gobject_user_data_key_get_type ()) + +-/* Currently gobject-introspection doesn't understand that hb_language_t +- * can be passed by-value. As such we box it up. May remove in the +- * future. +- * +- * https://bugzilla.gnome.org/show_bug.cgi?id=707656 +- */ +-GType hb_gobject_language_get_type (void); +-#define HB_GOBJECT_TYPE_LANGUAGE (hb_gobject_language_get_type ()) + + HB_END_DECLS + +diff -uN gfx/harfbuzz/src_old/hb-graphite2.cc gfx/harfbuzz/src/hb-graphite2.cc +--- gfx/harfbuzz/src_old/hb-graphite2.cc 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-graphite2.cc 2016-06-05 23:49:01.899116257 +0200 +@@ -138,6 +138,9 @@ + free (data); + } + ++/* ++ * Since: 0.9.10 ++ */ + gr_face * + hb_graphite2_face_get_gr_face (hb_face_t *face) + { +@@ -172,6 +175,9 @@ + gr_font_destroy (data); + } + ++/* ++ * Since: 0.9.10 ++ */ + gr_font * + hb_graphite2_font_get_gr_font (hb_font_t *font) + { +@@ -228,12 +234,11 @@ + int lang_len = lang_end ? lang_end - lang : -1; + gr_feature_val *feats = gr_face_featureval_for_lang (grface, lang ? hb_tag_from_string (lang, lang_len) : 0); + +- while (num_features--) ++ for (unsigned int i = 0; i < num_features; i++) + { +- const gr_feature_ref *fref = gr_face_find_fref (grface, features->tag); ++ const gr_feature_ref *fref = gr_face_find_fref (grface, features[i].tag); + if (fref) +- gr_fref_set_feature_value (fref, features->value, feats); +- features++; ++ gr_fref_set_feature_value (fref, features[i].value, feats); + } + + gr_segment *seg = NULL; +@@ -249,6 +254,8 @@ + for (unsigned int i = 0; i < buffer->len; ++i) + chars[i] = buffer->info[i].codepoint; + ++ /* TODO ensure_native_direction. */ ++ + hb_tag_t script_tag[2]; + hb_ot_tags_from_script (hb_buffer_get_script (buffer), &script_tag[0], &script_tag[1]); + +@@ -267,9 +274,11 @@ + if (unlikely (!glyph_count)) { + if (feats) gr_featureval_destroy (feats); + gr_seg_destroy (seg); +- return false; ++ buffer->len = 0; ++ return true; + } + ++ buffer->ensure (glyph_count); + scratch = buffer->get_scratch_buffer (&scratch_size); + while ((DIV_CEIL (sizeof (hb_graphite2_cluster_t) * buffer->len, sizeof (*scratch)) + + DIV_CEIL (sizeof (hb_codepoint_t) * glyph_count, sizeof (*scratch))) > scratch_size) +@@ -331,7 +340,6 @@ + } + ci++; + +- //buffer->clear_output (); + for (unsigned int i = 0; i < ci; ++i) + { + for (unsigned int j = 0; j < clusters[i].num_glyphs; ++j) +@@ -342,32 +350,58 @@ + } + } + buffer->len = glyph_count; +- //buffer->swap_buffers (); +- +- if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) +- curradvx = gr_seg_advance_X(seg); + +- hb_glyph_position_t *pPos; +- for (pPos = hb_buffer_get_glyph_positions (buffer, NULL), is = gr_seg_first_slot (seg); +- is; pPos++, is = gr_slot_next_in_segment (is)) +- { +- pPos->x_offset = gr_slot_origin_X (is) - curradvx; +- pPos->y_offset = gr_slot_origin_Y (is) - curradvy; +- pPos->x_advance = gr_slot_advance_X (is, grface, grfont); +- pPos->y_advance = gr_slot_advance_Y (is, grface, grfont); +- if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) +- curradvx -= pPos->x_advance; +- pPos->x_offset = gr_slot_origin_X (is) - curradvx; +- if (!HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) ++ float yscale = font->y_scale / font->x_scale; ++ /* Positioning. */ ++ if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) ++ { ++ hb_glyph_position_t *pPos; ++ for (pPos = hb_buffer_get_glyph_positions (buffer, NULL), is = gr_seg_first_slot (seg); ++ is; pPos++, is = gr_slot_next_in_segment (is)) ++ { ++ pPos->x_offset = gr_slot_origin_X (is) - curradvx; ++ pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy; ++ pPos->x_advance = gr_slot_advance_X (is, grface, grfont); ++ pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale; + curradvx += pPos->x_advance; +- pPos->y_offset = gr_slot_origin_Y (is) - curradvy; +- curradvy += pPos->y_advance; +- } +- if (!HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) ++ curradvy += pPos->y_advance; ++ } + pPos[-1].x_advance += gr_seg_advance_X(seg) - curradvx; +- +- if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) ++ } ++ else ++ { ++ hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, NULL) + buffer->len - 1; ++ const hb_glyph_info_t *info = buffer->info + buffer->len - 1; ++ const hb_glyph_info_t *tinfo; ++ const gr_slot *tis; ++ int currclus = -1; ++ float clusx = 0., clusy = 0.; ++ for (is = gr_seg_last_slot (seg); is; pPos--, info--, is = gr_slot_prev_in_segment (is)) ++ { ++ if (info->cluster != currclus) ++ { ++ curradvx += clusx; ++ curradvy += clusy; ++ currclus = info->cluster; ++ clusx = 0.; ++ clusy = 0.; ++ for (tis = is, tinfo = info; tis && tinfo->cluster == currclus; tis = gr_slot_prev_in_segment (tis), tinfo--) ++ { ++ clusx += gr_slot_advance_X (tis, grface, grfont); ++ clusy += gr_slot_advance_Y (tis, grface, grfont) * yscale; ++ } ++ curradvx += clusx; ++ curradvy += clusy; ++ } ++ pPos->x_advance = gr_slot_advance_X (is, grface, grfont); ++ pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale; ++ curradvx -= pPos->x_advance; ++ curradvy -= pPos->y_advance; ++ pPos->x_offset = gr_slot_origin_X (is) - curradvx; ++ pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy; ++ } + hb_buffer_reverse_clusters (buffer); ++ } + + if (feats) gr_featureval_destroy (feats); + gr_seg_destroy (seg); +diff -uN gfx/harfbuzz/src_old/hb-graphite2.h gfx/harfbuzz/src/hb-graphite2.h +--- gfx/harfbuzz/src_old/hb-graphite2.h 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-graphite2.h 2016-06-05 23:49:03.057109946 +0200 +@@ -36,10 +36,10 @@ + #define HB_GRAPHITE2_TAG_SILF HB_TAG('S','i','l','f') + + +-gr_face * ++HB_EXTERN gr_face * + hb_graphite2_face_get_gr_face (hb_face_t *face); + +-gr_font * ++HB_EXTERN gr_font * + hb_graphite2_font_get_gr_font (hb_font_t *font); + + +diff -uN gfx/harfbuzz/src_old/hb.h gfx/harfbuzz/src/hb.h +--- gfx/harfbuzz/src_old/hb.h 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb.h 2016-06-05 23:50:56.057516793 +0200 +@@ -28,6 +28,10 @@ + #define HB_H + #define HB_H_IN + ++#ifndef HB_EXTERN ++#define HB_EXTERN extern ++#endif ++ + #include "hb-blob.h" + #include "hb-buffer.h" + #include "hb-common.h" +diff -uN gfx/harfbuzz/src_old/hb-icu.cc gfx/harfbuzz/src/hb-icu.cc +--- gfx/harfbuzz/src_old/hb-icu.cc 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-icu.cc 2016-06-05 23:49:04.387102711 +0200 +@@ -363,10 +363,8 @@ + if (!hb_atomic_ptr_get (&normalizer)) { + UErrorCode icu_err = U_ZERO_ERROR; + /* We ignore failure in getNFCInstace(). */ +- hb_atomic_ptr_cmpexch (&normalizer, NULL, unorm2_getNFCInstance (&icu_err)); ++ (void) hb_atomic_ptr_cmpexch (&normalizer, NULL, unorm2_getNFCInstance (&icu_err)); + } + #endif + return const_cast<hb_unicode_funcs_t *> (&_hb_icu_unicode_funcs); + } +- +- +diff -uN gfx/harfbuzz/src_old/hb-icu.h gfx/harfbuzz/src/hb-icu.h +--- gfx/harfbuzz/src_old/hb-icu.h 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-icu.h 2016-06-05 23:49:05.565096299 +0200 +@@ -36,14 +36,14 @@ + HB_BEGIN_DECLS + + +-hb_script_t ++HB_EXTERN hb_script_t + hb_icu_script_to_script (UScriptCode script); + +-UScriptCode ++HB_EXTERN UScriptCode + hb_icu_script_from_script (hb_script_t script); + + +-hb_unicode_funcs_t * ++HB_EXTERN hb_unicode_funcs_t * + hb_icu_get_unicode_funcs (void); + + +diff -uN gfx/harfbuzz/src_old/hb-mutex-private.hh gfx/harfbuzz/src/hb-mutex-private.hh +--- gfx/harfbuzz/src_old/hb-mutex-private.hh 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-mutex-private.hh 2016-06-05 23:49:06.735089929 +0200 +@@ -39,7 +39,13 @@ + + /* We need external help for these */ + +-#if 0 ++#if defined(HB_MUTEX_IMPL_INIT) \ ++ && defined(hb_mutex_impl_init) \ ++ && defined(hb_mutex_impl_lock) \ ++ && defined(hb_mutex_impl_unlock) \ ++ && defined(hb_mutex_impl_finish) ++ ++/* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */ + + + #elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__)) +@@ -47,7 +53,11 @@ + #include <windows.h> + typedef CRITICAL_SECTION hb_mutex_impl_t; + #define HB_MUTEX_IMPL_INIT {0} ++#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) ++#define hb_mutex_impl_init(M) InitializeCriticalSectionEx (M, 0, 0) ++#else + #define hb_mutex_impl_init(M) InitializeCriticalSection (M) ++#endif + #define hb_mutex_impl_lock(M) EnterCriticalSection (M) + #define hb_mutex_impl_unlock(M) LeaveCriticalSection (M) + #define hb_mutex_impl_finish(M) DeleteCriticalSection (M) +@@ -109,10 +119,12 @@ + #define hb_mutex_impl_unlock(M) HB_STMT_START {} HB_STMT_END + #define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END + ++ + #endif + + + #define HB_MUTEX_INIT {HB_MUTEX_IMPL_INIT} ++ + struct hb_mutex_t + { + /* TODO Add tracing. */ +diff -uN gfx/harfbuzz/src_old/hb-object-private.hh gfx/harfbuzz/src/hb-object-private.hh +--- gfx/harfbuzz/src_old/hb-object-private.hh 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-object-private.hh 2016-06-05 23:49:07.940083385 +0200 +@@ -47,19 +47,22 @@ + + /* reference_count */ + +-#define HB_REFERENCE_COUNT_INVALID_VALUE ((hb_atomic_int_t) -1) +-#define HB_REFERENCE_COUNT_INVALID {HB_REFERENCE_COUNT_INVALID_VALUE} ++#define HB_REFERENCE_COUNT_INERT_VALUE -1 ++#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD ++#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT(HB_REFERENCE_COUNT_INERT_VALUE)} ++ + struct hb_reference_count_t + { + hb_atomic_int_t ref_count; + +- inline void init (int v) { ref_count = v; } +- inline int inc (void) { return hb_atomic_int_add (const_cast<hb_atomic_int_t &> (ref_count), 1); } +- inline int dec (void) { return hb_atomic_int_add (const_cast<hb_atomic_int_t &> (ref_count), -1); } +- inline void finish (void) { ref_count = HB_REFERENCE_COUNT_INVALID_VALUE; } +- +- inline bool is_invalid (void) const { return ref_count == HB_REFERENCE_COUNT_INVALID_VALUE; } ++ inline void init (int v) { ref_count.set_unsafe (v); } ++ inline int get_unsafe (void) const { return ref_count.get_unsafe (); } ++ inline int inc (void) { return ref_count.inc (); } ++ inline int dec (void) { return ref_count.dec (); } ++ inline void finish (void) { ref_count.set_unsafe (HB_REFERENCE_COUNT_POISON_VALUE); } + ++ inline bool is_inert (void) const { return ref_count.get_unsafe () == HB_REFERENCE_COUNT_INERT_VALUE; } ++ inline bool is_valid (void) const { return ref_count.get_unsafe () > 0; } + }; + + +@@ -102,7 +105,7 @@ + hb_reference_count_t ref_count; + hb_user_data_array_t user_data; + +-#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INVALID, HB_USER_DATA_ARRAY_INIT} ++#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, HB_USER_DATA_ARRAY_INIT} + + private: + ASSERT_POD (); +@@ -117,7 +120,7 @@ + DEBUG_MSG (OBJECT, (void *) obj, + "%s refcount=%d", + function, +- obj ? obj->header.ref_count.ref_count : 0); ++ obj ? obj->header.ref_count.get_unsafe () : 0); + } + + template <typename Type> +@@ -141,7 +144,12 @@ + template <typename Type> + static inline bool hb_object_is_inert (const Type *obj) + { +- return unlikely (obj->header.ref_count.is_invalid ()); ++ return unlikely (obj->header.ref_count.is_inert ()); ++} ++template <typename Type> ++static inline bool hb_object_is_valid (const Type *obj) ++{ ++ return likely (obj->header.ref_count.is_valid ()); + } + template <typename Type> + static inline Type *hb_object_reference (Type *obj) +@@ -149,6 +157,7 @@ + hb_object_trace (obj, HB_FUNC); + if (unlikely (!obj || hb_object_is_inert (obj))) + return obj; ++ assert (hb_object_is_valid (obj)); + obj->header.ref_count.inc (); + return obj; + } +@@ -158,6 +167,7 @@ + hb_object_trace (obj, HB_FUNC); + if (unlikely (!obj || hb_object_is_inert (obj))) + return false; ++ assert (hb_object_is_valid (obj)); + if (obj->header.ref_count.dec () != 1) + return false; + +@@ -174,6 +184,7 @@ + { + if (unlikely (!obj || hb_object_is_inert (obj))) + return false; ++ assert (hb_object_is_valid (obj)); + return obj->header.user_data.set (key, data, destroy, replace); + } + +@@ -183,6 +194,7 @@ + { + if (unlikely (!obj || hb_object_is_inert (obj))) + return NULL; ++ assert (hb_object_is_valid (obj)); + return obj->header.user_data.get (key); + } + +diff -uN gfx/harfbuzz/src_old/hb-open-file-private.hh gfx/harfbuzz/src/hb-open-file-private.hh +--- gfx/harfbuzz/src_old/hb-open-file-private.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-open-file-private.hh 2016-06-05 23:49:09.207076516 +0200 +@@ -53,9 +53,10 @@ + + typedef struct TableRecord + { +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this)); ++ return_trace (c->check_struct (this)); + } + + Tag tag; /* 4-byte identifier. */ +@@ -102,9 +103,10 @@ + } + + public: +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables)); ++ return_trace (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables)); + } + + protected: +@@ -130,9 +132,10 @@ + inline unsigned int get_face_count (void) const { return table.len; } + inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (table.sanitize (c, this)); ++ return_trace (table.sanitize (c, this)); + } + + protected: +@@ -169,13 +172,14 @@ + } + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- if (unlikely (!u.header.version.sanitize (c))) return TRACE_RETURN (false); ++ if (unlikely (!u.header.version.sanitize (c))) return_trace (false); + switch (u.header.version.major) { + case 2: /* version 2 is compatible with version 1 */ +- case 1: return TRACE_RETURN (u.version1.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (u.version1.sanitize (c)); ++ default:return_trace (true); + } + } + +@@ -233,16 +237,17 @@ + } + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- if (unlikely (!u.tag.sanitize (c))) return TRACE_RETURN (false); ++ if (unlikely (!u.tag.sanitize (c))) return_trace (false); + switch (u.tag) { + case CFFTag: /* All the non-collection tags */ + case TrueTag: + case Typ1Tag: +- case TrueTypeTag: return TRACE_RETURN (u.fontFace.sanitize (c)); +- case TTCTag: return TRACE_RETURN (u.ttcHeader.sanitize (c)); +- default: return TRACE_RETURN (true); ++ case TrueTypeTag: return_trace (u.fontFace.sanitize (c)); ++ case TTCTag: return_trace (u.ttcHeader.sanitize (c)); ++ default: return_trace (true); + } + } + +diff -uN gfx/harfbuzz/src_old/hb-open-type-private.hh gfx/harfbuzz/src/hb-open-type-private.hh +--- gfx/harfbuzz/src_old/hb-open-type-private.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-open-type-private.hh 2016-06-05 23:49:10.574069085 +0200 +@@ -103,9 +103,6 @@ + static const unsigned int static_size = (size); \ + static const unsigned int min_size = (size) + +-/* Size signifying variable-sized array */ +-#define VAR 1 +- + #define DEFINE_SIZE_UNION(size, _member) \ + DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \ + static const unsigned int min_size = (size) +@@ -154,6 +151,20 @@ + #define Null(Type) Null<Type>() + + ++/* ++ * Dispatch ++ */ ++ ++template <typename Context, typename Return, unsigned int MaxDebugDepth> ++struct hb_dispatch_context_t ++{ ++ static const unsigned int max_debug_depth = MaxDebugDepth; ++ typedef Return return_t; ++ template <typename T, typename F> ++ inline bool may_dispatch (const T *obj, const F *format) { return true; } ++ static return_t no_dispatch_return_value (void) { return Context::default_return_value (); } ++}; ++ + + /* + * Sanitize +@@ -171,18 +182,27 @@ + + /* This limits sanitizing time on really broken fonts. */ + #ifndef HB_SANITIZE_MAX_EDITS +-#define HB_SANITIZE_MAX_EDITS 100 ++#define HB_SANITIZE_MAX_EDITS 32 + #endif + +-struct hb_sanitize_context_t ++struct hb_sanitize_context_t : ++ hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE> + { ++ inline hb_sanitize_context_t (void) : ++ debug_depth (0), ++ start (NULL), end (NULL), ++ writable (false), edit_count (0), ++ blob (NULL) {} ++ + inline const char *get_name (void) { return "SANITIZE"; } +- static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE; +- typedef bool return_t; ++ template <typename T, typename F> ++ inline bool may_dispatch (const T *obj, const F *format) ++ { return format->sanitize (this); } + template <typename T> + inline return_t dispatch (const T &obj) { return obj.sanitize (this); } + static return_t default_return_value (void) { return true; } +- bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; } ++ static return_t no_dispatch_return_value (void) { return false; } ++ bool stop_sublookup_iteration (const return_t r) const { return !r; } + + inline void init (hb_blob_t *b) + { +@@ -270,9 +290,9 @@ + } + + template <typename Type, typename ValueType> +- inline bool try_set (Type *obj, const ValueType &v) { ++ inline bool try_set (const Type *obj, const ValueType &v) { + if (this->may_edit (obj, obj->static_size)) { +- obj->set (v); ++ const_cast<Type *> (obj)->set (v); + return true; + } + return false; +@@ -292,7 +312,7 @@ + struct Sanitizer + { + static hb_blob_t *sanitize (hb_blob_t *blob) { +- hb_sanitize_context_t c[1] = {{0, NULL, NULL, false, 0, NULL}}; ++ hb_sanitize_context_t c[1]; + bool sane; + + /* TODO is_sane() stuff */ +@@ -376,9 +396,9 @@ + + struct hb_serialize_context_t + { +- inline hb_serialize_context_t (void *start, unsigned int size) ++ inline hb_serialize_context_t (void *start_, unsigned int size) + { +- this->start = (char *) start; ++ this->start = (char *) start_; + this->end = this->start + size; + + this->ran_out_of_room = false; +@@ -472,10 +492,10 @@ + return reinterpret_cast<Type *> (&obj); + } + +- inline void truncate (void *head) ++ inline void truncate (void *new_head) + { +- assert (this->start < head && head <= this->head); +- this->head = (char *) head; ++ assert (this->start < new_head && new_head <= this->head); ++ this->head = (char *) new_head; + } + + unsigned int debug_depth; +@@ -533,6 +553,20 @@ + template <typename Type, int Bytes> struct BEInt; + + template <typename Type> ++struct BEInt<Type, 1> ++{ ++ public: ++ inline void set (Type V) ++ { ++ v = V; ++ } ++ inline operator Type (void) const ++ { ++ return v; ++ } ++ private: uint8_t v; ++}; ++template <typename Type> + struct BEInt<Type, 2> + { + public: +@@ -546,12 +580,6 @@ + return (v[0] << 8) + + (v[1] ); + } +- inline bool operator == (const BEInt<Type, 2>& o) const +- { +- return v[0] == o.v[0] +- && v[1] == o.v[1]; +- } +- inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); } + private: uint8_t v[2]; + }; + template <typename Type> +@@ -570,13 +598,6 @@ + + (v[1] << 8) + + (v[2] ); + } +- inline bool operator == (const BEInt<Type, 3>& o) const +- { +- return v[0] == o.v[0] +- && v[1] == o.v[1] +- && v[2] == o.v[2]; +- } +- inline bool operator != (const BEInt<Type, 3>& o) const { return !(*this == o); } + private: uint8_t v[3]; + }; + template <typename Type> +@@ -597,14 +618,6 @@ + + (v[2] << 8) + + (v[3] ); + } +- inline bool operator == (const BEInt<Type, 4>& o) const +- { +- return v[0] == o.v[0] +- && v[1] == o.v[1] +- && v[2] == o.v[2] +- && v[3] == o.v[3]; +- } +- inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); } + private: uint8_t v[4]; + }; + +@@ -614,14 +627,21 @@ + { + inline void set (Type i) { v.set (i); } + inline operator Type(void) const { return v; } +- inline bool operator == (const IntType<Type,Size> &o) const { return v == o.v; } +- inline bool operator != (const IntType<Type,Size> &o) const { return v != o.v; } ++ inline bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; } ++ inline bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); } + static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); } +- inline int cmp (IntType<Type,Size> va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; } +- inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; } +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline int cmp (Type a) const ++ { ++ Type b = v; ++ if (sizeof (Type) < sizeof (int)) ++ return (int) a - (int) b; ++ else ++ return a < b ? -1 : a == b ? 0 : +1; ++ } ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (likely (c->check_struct (this))); ++ return_trace (likely (c->check_struct (this))); + } + protected: + BEInt<Type, Size> v; +@@ -629,7 +649,7 @@ + DEFINE_SIZE_STATIC (Size); + }; + +-typedef uint8_t BYTE; /* 8-bit unsigned integer. */ ++typedef IntType<uint8_t , 1> BYTE; /* 8-bit unsigned integer. */ + typedef IntType<uint16_t, 2> USHORT; /* 16-bit unsigned integer. */ + typedef IntType<int16_t, 2> SHORT; /* 16-bit signed integer. */ + typedef IntType<uint32_t, 4> ULONG; /* 32-bit unsigned integer. */ +@@ -646,9 +666,10 @@ + * 1904. The value is represented as a signed 64-bit integer. */ + struct LONGDATETIME + { +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (likely (c->check_struct (this))); ++ return_trace (likely (c->check_struct (this))); + } + protected: + LONG major; +@@ -670,7 +691,10 @@ + DEFINE_NULL_DATA (Tag, " "); + + /* Glyph index number, same as uint16 (length = 16 bits) */ +-typedef USHORT GlyphID; ++struct GlyphID : USHORT { ++ static inline int cmp (const GlyphID *a, const GlyphID *b) { return b->USHORT::cmp (*a); } ++ inline int cmp (hb_codepoint_t a) const { return (int) a - (int) *this; } ++}; + + /* Script/language-system/feature index */ + struct Index : USHORT { +@@ -719,9 +743,10 @@ + { + inline uint32_t to_int (void) const { return (major << 16) + minor; } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this)); ++ return_trace (c->check_struct (this)); + } + + USHORT major; +@@ -747,33 +772,35 @@ + return StructAtOffset<Type> (base, offset); + } + +- inline Type& serialize (hb_serialize_context_t *c, void *base) ++ inline Type& serialize (hb_serialize_context_t *c, const void *base) + { + Type *t = c->start_embed<Type> (); + this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */ + return *t; + } + +- inline bool sanitize (hb_sanitize_context_t *c, void *base) { ++ inline bool sanitize (hb_sanitize_context_t *c, const void *base) const ++ { + TRACE_SANITIZE (this); +- if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); ++ if (unlikely (!c->check_struct (this))) return_trace (false); + unsigned int offset = *this; +- if (unlikely (!offset)) return TRACE_RETURN (true); +- Type &obj = StructAtOffset<Type> (base, offset); +- return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c)); ++ if (unlikely (!offset)) return_trace (true); ++ const Type &obj = StructAtOffset<Type> (base, offset); ++ return_trace (likely (obj.sanitize (c)) || neuter (c)); + } + template <typename T> +- inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { ++ inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const ++ { + TRACE_SANITIZE (this); +- if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); ++ if (unlikely (!c->check_struct (this))) return_trace (false); + unsigned int offset = *this; +- if (unlikely (!offset)) return TRACE_RETURN (true); +- Type &obj = StructAtOffset<Type> (base, offset); +- return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c)); ++ if (unlikely (!offset)) return_trace (true); ++ const Type &obj = StructAtOffset<Type> (base, offset); ++ return_trace (likely (obj.sanitize (c, user_data)) || neuter (c)); + } + + /* Set the offset to Null */ +- inline bool neuter (hb_sanitize_context_t *c) { ++ inline bool neuter (hb_sanitize_context_t *c) const { + return c->try_set (this, 0); + } + DEFINE_SIZE_STATIC (sizeof(OffsetType)); +@@ -820,10 +847,10 @@ + unsigned int items_len) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend_min (*this))) return_trace (false); + len.set (items_len); /* TODO(serialize) Overflow? */ +- if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); +- return TRACE_RETURN (true); ++ if (unlikely (!c->extend (*this))) return_trace (false); ++ return_trace (true); + } + + inline bool serialize (hb_serialize_context_t *c, +@@ -831,16 +858,17 @@ + unsigned int items_len) + { + TRACE_SERIALIZE (this); +- if (unlikely (!serialize (c, items_len))) return TRACE_RETURN (false); ++ if (unlikely (!serialize (c, items_len))) return_trace (false); + for (unsigned int i = 0; i < items_len; i++) + array[i] = items[i]; + items.advance (items_len); +- return TRACE_RETURN (true); ++ return_trace (true); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); ++ if (unlikely (!sanitize_shallow (c))) return_trace (false); + + /* Note: for structs that do not reference other structs, + * we do not need to call their sanitize() as we already did +@@ -851,26 +879,28 @@ + */ + (void) (false && array[0].sanitize (c)); + +- return TRACE_RETURN (true); ++ return_trace (true); + } +- inline bool sanitize (hb_sanitize_context_t *c, void *base) { ++ inline bool sanitize (hb_sanitize_context_t *c, const void *base) const ++ { + TRACE_SANITIZE (this); +- if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); ++ if (unlikely (!sanitize_shallow (c))) return_trace (false); + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + if (unlikely (!array[i].sanitize (c, base))) +- return TRACE_RETURN (false); +- return TRACE_RETURN (true); ++ return_trace (false); ++ return_trace (true); + } + template <typename T> +- inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { ++ inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const ++ { + TRACE_SANITIZE (this); +- if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); ++ if (unlikely (!sanitize_shallow (c))) return_trace (false); + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + if (unlikely (!array[i].sanitize (c, base, user_data))) +- return TRACE_RETURN (false); +- return TRACE_RETURN (true); ++ return_trace (false); ++ return_trace (true); + } + + template <typename SearchType> +@@ -884,9 +914,10 @@ + } + + private: +- inline bool sanitize_shallow (hb_sanitize_context_t *c) { ++ inline bool sanitize_shallow (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len)); ++ return_trace (c->check_struct (this) && c->check_array (array, Type::static_size, len)); + } + + public: +@@ -910,14 +941,16 @@ + return this+this->array[i]; + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this)); ++ return_trace (OffsetArrayOf<Type>::sanitize (c, this)); + } + template <typename T> +- inline bool sanitize (hb_sanitize_context_t *c, T user_data) { ++ inline bool sanitize (hb_sanitize_context_t *c, T user_data) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data)); ++ return_trace (OffsetArrayOf<Type>::sanitize (c, this, user_data)); + } + }; + +@@ -939,24 +972,26 @@ + unsigned int items_len) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend_min (*this))) return_trace (false); + len.set (items_len); /* TODO(serialize) Overflow? */ +- if (unlikely (!items_len)) return TRACE_RETURN (true); +- if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); ++ if (unlikely (!items_len)) return_trace (true); ++ if (unlikely (!c->extend (*this))) return_trace (false); + for (unsigned int i = 0; i < items_len - 1; i++) + array[i] = items[i]; + items.advance (items_len - 1); +- return TRACE_RETURN (true); ++ return_trace (true); + } + +- inline bool sanitize_shallow (hb_sanitize_context_t *c) { ++ inline bool sanitize_shallow (hb_sanitize_context_t *c) const ++ { + return c->check_struct (this) + && c->check_array (this, Type::static_size, len); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); ++ if (unlikely (!sanitize_shallow (c))) return_trace (false); + + /* Note: for structs that do not reference other structs, + * we do not need to call their sanitize() as we already did +@@ -967,7 +1002,7 @@ + */ + (void) (false && array[0].sanitize (c)); + +- return TRACE_RETURN (true); ++ return_trace (true); + } + + LenType len; +diff -uN gfx/harfbuzz/src_old/hb-ot-cmap-table.hh gfx/harfbuzz/src/hb-ot-cmap-table.hh +--- gfx/harfbuzz/src_old/hb-ot-cmap-table.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-cmap-table.hh 2016-06-05 23:49:11.982061464 +0200 +@@ -51,9 +51,10 @@ + return true; + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this)); ++ return_trace (c->check_struct (this)); + } + + protected: +@@ -125,11 +126,11 @@ + return true; + } + +- inline bool sanitize (hb_sanitize_context_t *c) ++ inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (unlikely (!c->check_struct (this))) +- return TRACE_RETURN (false); ++ return_trace (false); + + if (unlikely (!c->check_range (this, length))) + { +@@ -140,10 +141,10 @@ + (uintptr_t) (c->end - + (char *) this)); + if (!c->try_set (&length, new_length)) +- return TRACE_RETURN (false); ++ return_trace (false); + } + +- return TRACE_RETURN (16 + 4 * (unsigned int) segCountX2 <= length); ++ return_trace (16 + 4 * (unsigned int) segCountX2 <= length); + } + + protected: +@@ -183,9 +184,10 @@ + return 0; + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this)); ++ return_trace (c->check_struct (this)); + } + + private: +@@ -210,9 +212,10 @@ + return true; + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && glyphIdArray.sanitize (c)); ++ return_trace (c->check_struct (this) && glyphIdArray.sanitize (c)); + } + + protected: +@@ -242,9 +245,10 @@ + return true; + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && groups.sanitize (c)); ++ return_trace (c->check_struct (this) && groups.sanitize (c)); + } + + protected: +@@ -288,9 +292,10 @@ + return 0; + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this)); ++ return_trace (c->check_struct (this)); + } + + UINT24 startUnicodeValue; /* First value in this range. */ +@@ -309,9 +314,10 @@ + return unicodeValue.cmp (codepoint); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this)); ++ return_trace (c->check_struct (this)); + } + + UINT24 unicodeValue; /* Base Unicode value of the UVS */ +@@ -348,11 +354,12 @@ + return varSelector.cmp (variation_selector); + } + +- inline bool sanitize (hb_sanitize_context_t *c, void *base) { ++ inline bool sanitize (hb_sanitize_context_t *c, const void *base) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && +- defaultUVS.sanitize (c, base) && +- nonDefaultUVS.sanitize (c, base)); ++ return_trace (c->check_struct (this) && ++ defaultUVS.sanitize (c, base) && ++ nonDefaultUVS.sanitize (c, base)); + } + + UINT24 varSelector; /* Variation selector. */ +@@ -373,10 +380,11 @@ + return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && +- record.sanitize (c, this)); ++ return_trace (c->check_struct (this) && ++ record.sanitize (c, this)); + } + + protected: +@@ -418,18 +426,19 @@ + } + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); ++ if (!u.format.sanitize (c)) return_trace (false); + switch (u.format) { +- case 0: return TRACE_RETURN (u.format0 .sanitize (c)); +- case 4: return TRACE_RETURN (u.format4 .sanitize (c)); +- case 6: return TRACE_RETURN (u.format6 .sanitize (c)); +- case 10: return TRACE_RETURN (u.format10.sanitize (c)); +- case 12: return TRACE_RETURN (u.format12.sanitize (c)); +- case 13: return TRACE_RETURN (u.format13.sanitize (c)); +- case 14: return TRACE_RETURN (u.format14.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 0: return_trace (u.format0 .sanitize (c)); ++ case 4: return_trace (u.format4 .sanitize (c)); ++ case 6: return_trace (u.format6 .sanitize (c)); ++ case 10: return_trace (u.format10.sanitize (c)); ++ case 12: return_trace (u.format12.sanitize (c)); ++ case 13: return_trace (u.format13.sanitize (c)); ++ case 14: return_trace (u.format14.sanitize (c)); ++ default:return_trace (true); + } + } + +@@ -461,10 +470,11 @@ + return 0; + } + +- inline bool sanitize (hb_sanitize_context_t *c, void *base) { ++ inline bool sanitize (hb_sanitize_context_t *c, const void *base) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && +- subtable.sanitize (c, base)); ++ return_trace (c->check_struct (this) && ++ subtable.sanitize (c, base)); + } + + USHORT platformID; /* Platform ID. */ +@@ -496,11 +506,12 @@ + return &(this+encodingRecord[result].subtable); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && +- likely (version == 0) && +- encodingRecord.sanitize (c, this)); ++ return_trace (c->check_struct (this) && ++ likely (version == 0) && ++ encodingRecord.sanitize (c, this)); + } + + USHORT version; /* Table version number (0). */ +diff -uN gfx/harfbuzz/src_old/hb-ot-font.cc gfx/harfbuzz/src/hb-ot-font.cc +--- gfx/harfbuzz/src_old/hb-ot-font.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-font.cc 2016-06-05 23:49:13.433053614 +0200 +@@ -31,8 +31,11 @@ + #include "hb-font-private.hh" + + #include "hb-ot-cmap-table.hh" ++#include "hb-ot-glyf-table.hh" ++#include "hb-ot-head-table.hh" + #include "hb-ot-hhea-table.hh" + #include "hb-ot-hmtx-table.hh" ++#include "hb-ot-os2-table.hh" + + + struct hb_ot_face_metrics_accelerator_t +@@ -40,24 +43,58 @@ + unsigned int num_metrics; + unsigned int num_advances; + unsigned int default_advance; ++ unsigned short ascender; ++ unsigned short descender; ++ unsigned short line_gap; ++ + const OT::_mtx *table; + hb_blob_t *blob; + + inline void init (hb_face_t *face, +- hb_tag_t _hea_tag, hb_tag_t _mtx_tag, +- unsigned int default_advance) ++ hb_tag_t _hea_tag, ++ hb_tag_t _mtx_tag, ++ hb_tag_t os2_tag) + { +- this->default_advance = default_advance; +- this->num_metrics = face->get_num_glyphs (); ++ this->default_advance = face->get_upem (); ++ ++ bool got_font_extents = false; ++ if (os2_tag) ++ { ++ hb_blob_t *os2_blob = OT::Sanitizer<OT::os2>::sanitize (face->reference_table (os2_tag)); ++ const OT::os2 *os2 = OT::Sanitizer<OT::os2>::lock_instance (os2_blob); ++#define USE_TYPO_METRICS (1u<<7) ++ if (0 != (os2->fsSelection & USE_TYPO_METRICS)) ++ { ++ this->ascender = os2->sTypoAscender; ++ this->descender = os2->sTypoDescender; ++ this->line_gap = os2->sTypoLineGap; ++ got_font_extents = (this->ascender | this->descender) != 0; ++ } ++ hb_blob_destroy (os2_blob); ++ } + + hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag)); + const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob); + this->num_advances = _hea->numberOfLongMetrics; ++ if (!got_font_extents) ++ { ++ this->ascender = _hea->ascender; ++ this->descender = _hea->descender; ++ this->line_gap = _hea->lineGap; ++ } + hb_blob_destroy (_hea_blob); + + this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag)); +- if (unlikely (!this->num_advances || +- 2 * (this->num_advances + this->num_metrics) < hb_blob_get_length (this->blob))) ++ ++ /* Cap num_metrics() and num_advances() based on table length. */ ++ unsigned int len = hb_blob_get_length (this->blob); ++ if (unlikely (this->num_advances * 4 > len)) ++ this->num_advances = len / 4; ++ this->num_metrics = this->num_advances + (len - 4 * this->num_advances) / 2; ++ ++ /* We MUST set num_metrics to zero if num_advances is zero. ++ * Our get_advance() depends on that. */ ++ if (unlikely (!this->num_advances)) + { + this->num_metrics = this->num_advances = 0; + hb_blob_destroy (this->blob); +@@ -76,8 +113,8 @@ + if (unlikely (glyph >= this->num_metrics)) + { + /* If this->num_metrics is zero, it means we don't have the metrics table +- * for this direction: return one EM. Otherwise, it means that the glyph +- * index is out of bound: return zero. */ ++ * for this direction: return default advance. Otherwise, it means that the ++ * glyph index is out of bound: return zero. */ + if (this->num_metrics) + return 0; + else +@@ -91,6 +128,79 @@ + } + }; + ++struct hb_ot_face_glyf_accelerator_t ++{ ++ bool short_offset; ++ unsigned int num_glyphs; ++ const OT::loca *loca; ++ const OT::glyf *glyf; ++ hb_blob_t *loca_blob; ++ hb_blob_t *glyf_blob; ++ unsigned int glyf_len; ++ ++ inline void init (hb_face_t *face) ++ { ++ hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (face->reference_table (HB_OT_TAG_head)); ++ const OT::head *head = OT::Sanitizer<OT::head>::lock_instance (head_blob); ++ if ((unsigned int) head->indexToLocFormat > 1 || head->glyphDataFormat != 0) ++ { ++ /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */ ++ hb_blob_destroy (head_blob); ++ return; ++ } ++ this->short_offset = 0 == head->indexToLocFormat; ++ hb_blob_destroy (head_blob); ++ ++ this->loca_blob = OT::Sanitizer<OT::loca>::sanitize (face->reference_table (HB_OT_TAG_loca)); ++ this->loca = OT::Sanitizer<OT::loca>::lock_instance (this->loca_blob); ++ this->glyf_blob = OT::Sanitizer<OT::glyf>::sanitize (face->reference_table (HB_OT_TAG_glyf)); ++ this->glyf = OT::Sanitizer<OT::glyf>::lock_instance (this->glyf_blob); ++ ++ this->num_glyphs = MAX (1u, hb_blob_get_length (this->loca_blob) / (this->short_offset ? 2 : 4)) - 1; ++ this->glyf_len = hb_blob_get_length (this->glyf_blob); ++ } ++ ++ inline void fini (void) ++ { ++ hb_blob_destroy (this->loca_blob); ++ hb_blob_destroy (this->glyf_blob); ++ } ++ ++ inline bool get_extents (hb_codepoint_t glyph, ++ hb_glyph_extents_t *extents) const ++ { ++ if (unlikely (glyph >= this->num_glyphs)) ++ return false; ++ ++ unsigned int start_offset, end_offset; ++ if (this->short_offset) ++ { ++ start_offset = 2 * this->loca->u.shortsZ[glyph]; ++ end_offset = 2 * this->loca->u.shortsZ[glyph + 1]; ++ } ++ else ++ { ++ start_offset = this->loca->u.longsZ[glyph]; ++ end_offset = this->loca->u.longsZ[glyph + 1]; ++ } ++ ++ if (start_offset > end_offset || end_offset > this->glyf_len) ++ return false; ++ ++ if (end_offset - start_offset < OT::glyfGlyphHeader::static_size) ++ return true; /* Empty glyph; zero extents. */ ++ ++ const OT::glyfGlyphHeader &glyph_header = OT::StructAtOffset<OT::glyfGlyphHeader> (this->glyf, start_offset); ++ ++ extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax); ++ extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax); ++ extents->width = MAX (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing; ++ extents->height = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing; ++ ++ return true; ++ } ++}; ++ + struct hb_ot_face_cmap_accelerator_t + { + const OT::CmapSubtable *table; +@@ -114,6 +224,7 @@ + if (!subtable) subtable = cmap->find_subtable (0, 2); + if (!subtable) subtable = cmap->find_subtable (0, 1); + if (!subtable) subtable = cmap->find_subtable (0, 0); ++ if (!subtable) subtable = cmap->find_subtable (3, 0); + /* Meh. */ + if (!subtable) subtable = &OT::Null(OT::CmapSubtable); + +@@ -157,23 +268,22 @@ + hb_ot_face_cmap_accelerator_t cmap; + hb_ot_face_metrics_accelerator_t h_metrics; + hb_ot_face_metrics_accelerator_t v_metrics; ++ hb_ot_face_glyf_accelerator_t glyf; + }; + + + static hb_ot_font_t * +-_hb_ot_font_create (hb_font_t *font) ++_hb_ot_font_create (hb_face_t *face) + { + hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t)); +- hb_face_t *face = font->face; + + if (unlikely (!ot_font)) + return NULL; + +- unsigned int upem = face->get_upem (); +- + ot_font->cmap.init (face); +- ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1); +- ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); /* TODO Can we do this lazily? */ ++ ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_os2); ++ ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE); /* TODO Can we do this lazily? */ ++ ot_font->glyf.init (face); + + return ot_font; + } +@@ -184,6 +294,7 @@ + ot_font->cmap.fini (); + ot_font->h_metrics.fini (); + ot_font->v_metrics.fini (); ++ ot_font->glyf.fini (); + + free (ot_font); + } +@@ -219,53 +330,7 @@ + void *user_data HB_UNUSED) + { + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; +- return font->em_scale_y (-ot_font->v_metrics.get_advance (glyph)); +-} +- +-static hb_bool_t +-hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED, +- void *font_data HB_UNUSED, +- hb_codepoint_t glyph HB_UNUSED, +- hb_position_t *x HB_UNUSED, +- hb_position_t *y HB_UNUSED, +- void *user_data HB_UNUSED) +-{ +- /* We always work in the horizontal coordinates. */ +- return true; +-} +- +-static hb_bool_t +-hb_ot_get_glyph_v_origin (hb_font_t *font HB_UNUSED, +- void *font_data, +- hb_codepoint_t glyph, +- hb_position_t *x, +- hb_position_t *y, +- void *user_data HB_UNUSED) +-{ +- /* TODO */ +- return false; +-} +- +-static hb_position_t +-hb_ot_get_glyph_h_kerning (hb_font_t *font, +- void *font_data, +- hb_codepoint_t left_glyph, +- hb_codepoint_t right_glyph, +- void *user_data HB_UNUSED) +-{ +- /* TODO */ +- return 0; +-} +- +-static hb_position_t +-hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, +- void *font_data HB_UNUSED, +- hb_codepoint_t top_glyph HB_UNUSED, +- hb_codepoint_t bottom_glyph HB_UNUSED, +- void *user_data HB_UNUSED) +-{ +- /* OpenType doesn't have vertical-kerning other than GPOS. */ +- return 0; ++ return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph)); + } + + static hb_bool_t +@@ -275,69 +340,100 @@ + hb_glyph_extents_t *extents, + void *user_data HB_UNUSED) + { +- /* TODO */ +- return false; ++ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; ++ bool ret = ot_font->glyf.get_extents (glyph, extents); ++ extents->x_bearing = font->em_scale_x (extents->x_bearing); ++ extents->y_bearing = font->em_scale_y (extents->y_bearing); ++ extents->width = font->em_scale_x (extents->width); ++ extents->height = font->em_scale_y (extents->height); ++ return ret; + } + + static hb_bool_t +-hb_ot_get_glyph_contour_point (hb_font_t *font HB_UNUSED, +- void *font_data, +- hb_codepoint_t glyph, +- unsigned int point_index, +- hb_position_t *x, +- hb_position_t *y, +- void *user_data HB_UNUSED) ++hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED, ++ void *font_data, ++ hb_font_extents_t *metrics, ++ void *user_data HB_UNUSED) + { +- /* TODO */ +- return false; ++ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; ++ metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender); ++ metrics->descender = font->em_scale_y (ot_font->h_metrics.descender); ++ metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap); ++ return true; + } + + static hb_bool_t +-hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED, +- void *font_data, +- hb_codepoint_t glyph, +- char *name, unsigned int size, +- void *user_data HB_UNUSED) ++hb_ot_get_font_v_extents (hb_font_t *font HB_UNUSED, ++ void *font_data, ++ hb_font_extents_t *metrics, ++ void *user_data HB_UNUSED) + { +- /* TODO */ +- return false; ++ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; ++ metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender); ++ metrics->descender = font->em_scale_x (ot_font->v_metrics.descender); ++ metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap); ++ return true; + } + +-static hb_bool_t +-hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED, +- void *font_data, +- const char *name, int len, /* -1 means nul-terminated */ +- hb_codepoint_t *glyph, +- void *user_data HB_UNUSED) ++static hb_font_funcs_t *static_ot_funcs = NULL; ++ ++#ifdef HB_USE_ATEXIT ++static ++void free_static_ot_funcs (void) + { +- /* TODO */ +- return false; ++ hb_font_funcs_destroy (static_ot_funcs); + } +- ++#endif + + static hb_font_funcs_t * + _hb_ot_get_font_funcs (void) + { +- static const hb_font_funcs_t ot_ffuncs = { +- HB_OBJECT_HEADER_STATIC, ++retry: ++ hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs); + +- true, /* immutable */ ++ if (unlikely (!funcs)) ++ { ++ funcs = hb_font_funcs_create (); + +- { +-#define HB_FONT_FUNC_IMPLEMENT(name) hb_ot_get_##name, +- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +-#undef HB_FONT_FUNC_IMPLEMENT ++ hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, NULL, NULL); ++ hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, NULL, NULL); ++ hb_font_funcs_set_glyph_func (funcs, hb_ot_get_glyph, NULL, NULL); ++ hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, NULL, NULL); ++ hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, NULL, NULL); ++ //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, NULL, NULL); ++ //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, NULL, NULL); ++ //hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, NULL, NULL); TODO ++ //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, NULL, NULL); ++ hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, NULL, NULL); ++ //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, NULL, NULL); TODO ++ //hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, NULL, NULL); TODO ++ //hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, NULL, NULL); TODO ++ ++ hb_font_funcs_make_immutable (funcs); ++ ++ if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, NULL, funcs)) { ++ hb_font_funcs_destroy (funcs); ++ goto retry; + } ++ ++#ifdef HB_USE_ATEXIT ++ atexit (free_static_ot_funcs); /* First person registers atexit() callback. */ ++#endif + }; + +- return const_cast<hb_font_funcs_t *> (&ot_ffuncs); ++ return funcs; + } + + ++/** ++ * hb_ot_font_set_funcs: ++ * ++ * Since: 0.9.28 ++ **/ + void + hb_ot_font_set_funcs (hb_font_t *font) + { +- hb_ot_font_t *ot_font = _hb_ot_font_create (font); ++ hb_ot_font_t *ot_font = _hb_ot_font_create (font->face); + if (unlikely (!ot_font)) + return; + +diff -uN gfx/harfbuzz/src_old/hb-ot-font.h gfx/harfbuzz/src/hb-ot-font.h +--- gfx/harfbuzz/src_old/hb-ot-font.h 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-font.h 2016-06-05 23:49:14.679046863 +0200 +@@ -24,6 +24,10 @@ + * Google Author(s): Behdad Esfahbod, Roozbeh Pournader + */ + ++#ifndef HB_OT_H_IN ++#error "Include <hb-ot.h> instead." ++#endif ++ + #ifndef HB_OT_FONT_H + #define HB_OT_FONT_H + +@@ -32,7 +36,7 @@ + HB_BEGIN_DECLS + + +-void ++HB_EXTERN void + hb_ot_font_set_funcs (hb_font_t *font); + + +diff -uN gfx/harfbuzz/src_old/hb-ot-glyf-table.hh gfx/harfbuzz/src/hb-ot-glyf-table.hh +--- gfx/harfbuzz/src_old/hb-ot-glyf-table.hh 1970-01-01 01:00:00.000000000 +0100 ++++ gfx/harfbuzz/src/hb-ot-glyf-table.hh 2016-06-05 23:49:15.900040281 +0200 +@@ -0,0 +1,104 @@ ++/* ++ * Copyright © 2015 Google, Inc. ++ * ++ * This is part of HarfBuzz, a text shaping library. ++ * ++ * Permission is hereby granted, without written agreement and without ++ * license or royalty fees, to use, copy, modify, and distribute this ++ * software and its documentation for any purpose, provided that the ++ * above copyright notice and the following two paragraphs appear in ++ * all copies of this software. ++ * ++ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR ++ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ++ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN ++ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ++ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, ++ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ++ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ++ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO ++ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ++ * ++ * Google Author(s): Behdad Esfahbod ++ */ ++ ++#ifndef HB_OT_GLYF_TABLE_HH ++#define HB_OT_GLYF_TABLE_HH ++ ++#include "hb-open-type-private.hh" ++ ++ ++namespace OT { ++ ++ ++/* ++ * loca -- Index to Location ++ */ ++ ++#define HB_OT_TAG_loca HB_TAG('l','o','c','a') ++ ++ ++struct loca ++{ ++ static const hb_tag_t tableTag = HB_OT_TAG_loca; ++ ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { ++ TRACE_SANITIZE (this); ++ return_trace (true); ++ } ++ ++ public: ++ union { ++ USHORT shortsZ[VAR]; /* Location offset divided by 2. */ ++ ULONG longsZ[VAR]; /* Location offset. */ ++ } u; ++ DEFINE_SIZE_ARRAY (0, u.longsZ); ++}; ++ ++ ++/* ++ * glyf -- TrueType Glyph Data ++ */ ++ ++#define HB_OT_TAG_glyf HB_TAG('g','l','y','f') ++ ++ ++struct glyf ++{ ++ static const hb_tag_t tableTag = HB_OT_TAG_glyf; ++ ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { ++ TRACE_SANITIZE (this); ++ /* We don't check for anything specific here. The users of the ++ * struct do all the hard work... */ ++ return_trace (true); ++ } ++ ++ public: ++ BYTE dataX[VAR]; /* Glyphs data. */ ++ ++ DEFINE_SIZE_ARRAY (0, dataX); ++}; ++ ++struct glyfGlyphHeader ++{ ++ SHORT numberOfContours; /* If the number of contours is ++ * greater than or equal to zero, ++ * this is a simple glyph; if negative, ++ * this is a composite glyph. */ ++ SHORT xMin; /* Minimum x for coordinate data. */ ++ SHORT yMin; /* Minimum y for coordinate data. */ ++ SHORT xMax; /* Maximum x for coordinate data. */ ++ SHORT yMax; /* Maximum y for coordinate data. */ ++ ++ DEFINE_SIZE_STATIC (10); ++}; ++ ++} /* namespace OT */ ++ ++ ++#endif /* HB_OT_GLYF_TABLE_HH */ +diff -uN gfx/harfbuzz/src_old/hb-ot-head-table.hh gfx/harfbuzz/src/hb-ot-head-table.hh +--- gfx/harfbuzz/src_old/hb-ot-head-table.hh 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-head-table.hh 2016-06-05 23:49:17.080033892 +0200 +@@ -45,15 +45,19 @@ + { + static const hb_tag_t tableTag = HB_OT_TAG_head; + +- inline unsigned int get_upem (void) const { ++ inline unsigned int get_upem (void) const ++ { + unsigned int upem = unitsPerEm; + /* If no valid head table found, assume 1000, which matches typical Type1 usage. */ + return 16 <= upem && upem <= 16384 ? upem : 1000; + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1)); ++ return_trace (c->check_struct (this) && ++ version.major == 1 && ++ magicNumber == 0x5F0F3CF5u); + } + + protected: +@@ -136,9 +140,10 @@ + * 2: Like 1 but also contains neutrals; + * -1: Only strongly right to left; + * -2: Like -1 but also contains neutrals. */ ++ public: + SHORT indexToLocFormat; /* 0 for short offsets, 1 for long. */ + SHORT glyphDataFormat; /* 0 for current format. */ +- public: ++ + DEFINE_SIZE_STATIC (54); + }; + +diff -uN gfx/harfbuzz/src_old/hb-ot-hhea-table.hh gfx/harfbuzz/src/hb-ot-hhea-table.hh +--- gfx/harfbuzz/src_old/hb-ot-hhea-table.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-hhea-table.hh 2016-06-05 23:49:18.320027217 +0200 +@@ -49,9 +49,10 @@ + static const hb_tag_t hheaTag = HB_OT_TAG_hhea; + static const hb_tag_t vheaTag = HB_OT_TAG_vhea; + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1)); ++ return_trace (c->check_struct (this) && likely (version.major == 1)); + } + + public: +diff -uN gfx/harfbuzz/src_old/hb-ot-hmtx-table.hh gfx/harfbuzz/src/hb-ot-hmtx-table.hh +--- gfx/harfbuzz/src_old/hb-ot-hmtx-table.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-hmtx-table.hh 2016-06-05 23:49:19.601020309 +0200 +@@ -57,11 +57,12 @@ + static const hb_tag_t hmtxTag = HB_OT_TAG_hmtx; + static const hb_tag_t vmtxTag = HB_OT_TAG_vmtx; + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); + /* We don't check for anything specific here. The users of the + * struct do all the hard work... */ +- return TRACE_RETURN (true); ++ return_trace (true); + } + + public: +diff -uN gfx/harfbuzz/src_old/hb-ot-layout.cc gfx/harfbuzz/src/hb-ot-layout.cc +--- gfx/harfbuzz/src_old/hb-ot-layout.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-layout.cc 2016-06-05 23:49:31.325957413 +0200 +@@ -28,6 +28,7 @@ + * Google Author(s): Behdad Esfahbod + */ + ++#include "hb-open-type-private.hh" + #include "hb-ot-layout-private.hh" + + #include "hb-ot-layout-gdef-table.hh" +@@ -84,9 +85,9 @@ + _hb_ot_layout_destroy (hb_ot_layout_t *layout) + { + for (unsigned int i = 0; i < layout->gsub_lookup_count; i++) +- layout->gsub_accels[i].fini (layout->gsub->get_lookup (i)); ++ layout->gsub_accels[i].fini (); + for (unsigned int i = 0; i < layout->gpos_lookup_count; i++) +- layout->gpos_accels[i].fini (layout->gpos->get_lookup (i)); ++ layout->gpos_accels[i].fini (); + + free (layout->gsub_accels); + free (layout->gpos_accels); +@@ -128,6 +129,11 @@ + return _get_gdef (face).has_glyph_classes (); + } + ++/** ++ * hb_ot_layout_get_glyph_class: ++ * ++ * Since: 0.9.7 ++ **/ + hb_ot_layout_glyph_class_t + hb_ot_layout_get_glyph_class (hb_face_t *face, + hb_codepoint_t glyph) +@@ -135,6 +141,11 @@ + return (hb_ot_layout_glyph_class_t) _get_gdef (face).get_glyph_class (glyph); + } + ++/** ++ * hb_ot_layout_get_glyphs_in_class: ++ * ++ * Since: 0.9.7 ++ **/ + void + hb_ot_layout_get_glyphs_in_class (hb_face_t *face, + hb_ot_layout_glyph_class_t klass, +@@ -285,6 +296,28 @@ + return g.get_feature_tags (start_offset, feature_count, feature_tags); + } + ++hb_bool_t ++hb_ot_layout_table_find_feature (hb_face_t *face, ++ hb_tag_t table_tag, ++ hb_tag_t feature_tag, ++ unsigned int *feature_index) ++{ ++ ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX); ++ const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); ++ ++ unsigned int num_features = g.get_feature_count (); ++ for (unsigned int i = 0; i < num_features; i++) ++ { ++ if (feature_tag == g.get_feature_tag (i)) { ++ if (feature_index) *feature_index = i; ++ return true; ++ } ++ } ++ ++ if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX; ++ return false; ++} ++ + + unsigned int + hb_ot_layout_script_get_language_tags (hb_face_t *face, +@@ -335,6 +368,11 @@ + NULL); + } + ++/** ++ * hb_ot_layout_language_get_required_feature: ++ * ++ * Since: 0.9.30 ++ **/ + hb_bool_t + hb_ot_layout_language_get_required_feature (hb_face_t *face, + hb_tag_t table_tag, +@@ -419,6 +457,11 @@ + return false; + } + ++/** ++ * hb_ot_layout_feature_get_lookups: ++ * ++ * Since: 0.9.7 ++ **/ + unsigned int + hb_ot_layout_feature_get_lookups (hb_face_t *face, + hb_tag_t table_tag, +@@ -433,6 +476,11 @@ + return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes); + } + ++/** ++ * hb_ot_layout_table_get_lookup_count: ++ * ++ * Since: 0.9.22 ++ **/ + unsigned int + hb_ot_layout_table_get_lookup_count (hb_face_t *face, + hb_tag_t table_tag) +@@ -590,6 +638,11 @@ + } + } + ++/** ++ * hb_ot_layout_collect_lookups: ++ * ++ * Since: 0.9.8 ++ **/ + void + hb_ot_layout_collect_lookups (hb_face_t *face, + hb_tag_t table_tag, +@@ -631,6 +684,11 @@ + } + } + ++/** ++ * hb_ot_layout_lookup_collect_glyphs: ++ * ++ * Since: 0.9.7 ++ **/ + void + hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, + hb_tag_t table_tag, +@@ -676,6 +734,11 @@ + return &_get_gsub (face) != &OT::Null(OT::GSUB); + } + ++/** ++ * hb_ot_layout_lookup_would_substitute: ++ * ++ * Since: 0.9.7 ++ **/ + hb_bool_t + hb_ot_layout_lookup_would_substitute (hb_face_t *face, + unsigned int lookup_index, +@@ -695,11 +758,11 @@ + hb_bool_t zero_context) + { + if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false; +- OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, zero_context); ++ OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context); + + const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index); + +- return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index].digest); ++ return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index]); + } + + void +@@ -714,6 +777,11 @@ + OT::GSUB::substitute_finish (font, buffer); + } + ++/** ++ * hb_ot_layout_lookup_substitute_closure: ++ * ++ * Since: 0.9.7 ++ **/ + void + hb_ot_layout_lookup_substitute_closure (hb_face_t *face, + unsigned int lookup_index, +@@ -748,6 +816,11 @@ + OT::GPOS::position_finish (font, buffer); + } + ++/** ++ * hb_ot_layout_get_size_params: ++ * ++ * Since: 0.9.10 ++ **/ + hb_bool_t + hb_ot_layout_get_size_params (hb_face_t *face, + unsigned int *design_size, /* OUT. May be NULL */ +@@ -829,28 +902,82 @@ + }; + + +-template <typename Lookup> +-static inline bool apply_once (OT::hb_apply_context_t *c, +- const Lookup &lookup) ++template <typename Obj> ++static inline bool ++apply_forward (OT::hb_apply_context_t *c, ++ const Obj &obj, ++ const hb_ot_layout_lookup_accelerator_t &accel) + { +- if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props)) +- return false; +- return lookup.dispatch (c); ++ bool ret = false; ++ hb_buffer_t *buffer = c->buffer; ++ while (buffer->idx < buffer->len && !buffer->in_error) ++ { ++ if (accel.may_have (buffer->cur().codepoint) && ++ (buffer->cur().mask & c->lookup_mask) && ++ c->check_glyph_property (&buffer->cur(), c->lookup_props) && ++ obj.apply (c)) ++ ret = true; ++ else ++ buffer->next_glyph (); ++ } ++ return ret; + } + +-template <typename Proxy> ++template <typename Obj> + static inline bool ++apply_backward (OT::hb_apply_context_t *c, ++ const Obj &obj, ++ const hb_ot_layout_lookup_accelerator_t &accel) ++{ ++ bool ret = false; ++ hb_buffer_t *buffer = c->buffer; ++ do ++ { ++ if (accel.may_have (buffer->cur().codepoint) && ++ (buffer->cur().mask & c->lookup_mask) && ++ c->check_glyph_property (&buffer->cur(), c->lookup_props) && ++ obj.apply (c)) ++ ret = true; ++ /* The reverse lookup doesn't "advance" cursor (for good reason). */ ++ buffer->idx--; ++ ++ } ++ while ((int) buffer->idx >= 0); ++ return ret; ++} ++ ++struct hb_apply_forward_context_t : ++ OT::hb_dispatch_context_t<hb_apply_forward_context_t, bool, HB_DEBUG_APPLY> ++{ ++ inline const char *get_name (void) { return "APPLY_FWD"; } ++ template <typename T> ++ inline return_t dispatch (const T &obj) { return apply_forward (c, obj, accel); } ++ static return_t default_return_value (void) { return false; } ++ bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return true; } ++ ++ hb_apply_forward_context_t (OT::hb_apply_context_t *c_, ++ const hb_ot_layout_lookup_accelerator_t &accel_) : ++ c (c_), ++ accel (accel_), ++ debug_depth (0) {} ++ ++ OT::hb_apply_context_t *c; ++ const hb_ot_layout_lookup_accelerator_t &accel; ++ unsigned int debug_depth; ++}; ++ ++template <typename Proxy> ++static inline void + apply_string (OT::hb_apply_context_t *c, + const typename Proxy::Lookup &lookup, + const hb_ot_layout_lookup_accelerator_t &accel) + { +- bool ret = false; + hb_buffer_t *buffer = c->buffer; + + if (unlikely (!buffer->len || !c->lookup_mask)) +- return false; ++ return; + +- c->set_lookup (lookup); ++ c->set_lookup_props (lookup.get_props ()); + + if (likely (!lookup.is_reverse ())) + { +@@ -859,21 +986,20 @@ + buffer->clear_output (); + buffer->idx = 0; + +- while (buffer->idx < buffer->len) ++ bool ret; ++ if (lookup.get_subtable_count () == 1) + { +- if (accel.digest.may_have (buffer->cur().codepoint) && +- (buffer->cur().mask & c->lookup_mask) && +- apply_once (c, lookup)) +- ret = true; +- else +- buffer->next_glyph (); ++ hb_apply_forward_context_t c_forward (c, accel); ++ ret = lookup.dispatch (&c_forward); + } ++ else ++ ret = apply_forward (c, lookup, accel); + if (ret) + { + if (!Proxy::inplace) + buffer->swap_buffers (); + else +- assert (!buffer->has_separate_output ()); ++ assert (!buffer->has_separate_output ()); + } + } + else +@@ -882,20 +1008,9 @@ + if (Proxy::table_index == 0) + buffer->remove_output (); + buffer->idx = buffer->len - 1; +- do +- { +- if (accel.digest.may_have (buffer->cur().codepoint) && +- (buffer->cur().mask & c->lookup_mask) && +- apply_once (c, lookup)) +- ret = true; +- /* The reverse lookup doesn't "advance" cursor (for good reason). */ +- buffer->idx--; + +- } +- while ((int) buffer->idx >= 0); ++ apply_backward (c, lookup, accel); + } +- +- return ret; + } + + template <typename Proxy> +@@ -914,11 +1029,14 @@ + for (; i < stage->last_lookup; i++) + { + unsigned int lookup_index = lookups[table_index][i].index; ++ if (!buffer->message (font, "start lookup %d", lookup_index)) continue; ++ c.set_lookup_index (lookup_index); + c.set_lookup_mask (lookups[table_index][i].mask); + c.set_auto_zwj (lookups[table_index][i].auto_zwj); + apply_string<Proxy> (&c, + proxy.table.get_lookup (lookup_index), + proxy.accels[lookup_index]); ++ (void) buffer->message (font, "end lookup %d", lookup_index); + } + + if (stage->pause_func) +diff -uN gfx/harfbuzz/src_old/hb-ot-layout-common-private.hh gfx/harfbuzz/src/hb-ot-layout-common-private.hh +--- gfx/harfbuzz/src_old/hb-ot-layout-common-private.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-layout-common-private.hh 2016-06-05 23:49:21.127012094 +0200 +@@ -34,12 +34,24 @@ + #include "hb-set-private.hh" + + ++#ifndef HB_MAX_NESTING_LEVEL ++#define HB_MAX_NESTING_LEVEL 6 ++#endif ++#ifndef HB_MAX_CONTEXT_LENGTH ++#define HB_MAX_CONTEXT_LENGTH 64 ++#endif ++ ++ + namespace OT { + + ++#define TRACE_DISPATCH(this, format) \ ++ hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \ ++ (&c->debug_depth, c->get_name (), this, HB_FUNC, \ ++ "format %d", (int) format); ++ ++ + #define NOT_COVERED ((unsigned int) -1) +-#define MAX_NESTING_LEVEL 8 +-#define MAX_CONTEXT_LENGTH 64 + + + +@@ -63,12 +75,13 @@ + + struct sanitize_closure_t { + hb_tag_t tag; +- void *list_base; ++ const void *list_base; + }; +- inline bool sanitize (hb_sanitize_context_t *c, void *base) { ++ inline bool sanitize (hb_sanitize_context_t *c, const void *base) const ++ { + TRACE_SANITIZE (this); + const sanitize_closure_t closure = {tag, base}; +- return TRACE_RETURN (c->check_struct (this) && offset.sanitize (c, base, &closure)); ++ return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure)); + } + + Tag tag; /* 4-byte Tag identifier */ +@@ -121,9 +134,10 @@ + inline const Type& operator [] (unsigned int i) const + { return this+RecordArrayOf<Type>::operator [](i).offset; } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (RecordArrayOf<Type>::sanitize (c, this)); ++ return_trace (RecordArrayOf<Type>::sanitize (c, this)); + } + }; + +@@ -134,9 +148,10 @@ + return g < start ? -1 : g <= end ? 0 : +1 ; + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this)); ++ return_trace (c->check_struct (this)); + } + + inline bool intersects (const hb_set_t *glyphs) const { +@@ -199,9 +214,10 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c, +- const Record<LangSys>::sanitize_closure_t * = NULL) { ++ const Record<LangSys>::sanitize_closure_t * = NULL) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c)); ++ return_trace (c->check_struct (this) && featureIndex.sanitize (c)); + } + + Offset<> lookupOrderZ; /* = Null (reserved for an offset to a +@@ -238,9 +254,10 @@ + inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; } + + inline bool sanitize (hb_sanitize_context_t *c, +- const Record<Script>::sanitize_closure_t * = NULL) { ++ const Record<Script>::sanitize_closure_t * = NULL) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this)); ++ return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this)); + } + + protected: +@@ -260,9 +277,10 @@ + /* http://www.microsoft.com/typography/otspec/features_pt.htm#size */ + struct FeatureParamsSize + { +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); ++ if (unlikely (!c->check_struct (this))) return_trace (false); + + /* This subtable has some "history", if you will. Some earlier versions of + * Adobe tools calculated the offset of the FeatureParams sutable from the +@@ -314,19 +332,19 @@ + */ + + if (!designSize) +- return TRACE_RETURN (false); ++ return_trace (false); + else if (subfamilyID == 0 && + subfamilyNameID == 0 && + rangeStart == 0 && + rangeEnd == 0) +- return TRACE_RETURN (true); ++ return_trace (true); + else if (designSize < rangeStart || + designSize > rangeEnd || + subfamilyNameID < 256 || + subfamilyNameID > 32767) +- return TRACE_RETURN (false); ++ return_trace (false); + else +- return TRACE_RETURN (true); ++ return_trace (true); + } + + USHORT designSize; /* Represents the design size in 720/inch +@@ -371,11 +389,12 @@ + /* http://www.microsoft.com/typography/otspec/features_pt.htm#ssxx */ + struct FeatureParamsStylisticSet + { +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); + /* Right now minorVersion is at zero. Which means, any table supports + * the uiNameID field. */ +- return TRACE_RETURN (c->check_struct (this)); ++ return_trace (c->check_struct (this)); + } + + USHORT version; /* (set to 0): This corresponds to a “minor” +@@ -404,10 +423,11 @@ + /* http://www.microsoft.com/typography/otspec/features_ae.htm#cv01-cv99 */ + struct FeatureParamsCharacterVariants + { +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && +- characters.sanitize (c)); ++ return_trace (c->check_struct (this) && ++ characters.sanitize (c)); + } + + USHORT format; /* Format number is set to 0. */ +@@ -444,15 +464,16 @@ + + struct FeatureParams + { +- inline bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) { ++ inline bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) const ++ { + TRACE_SANITIZE (this); + if (tag == HB_TAG ('s','i','z','e')) +- return TRACE_RETURN (u.size.sanitize (c)); ++ return_trace (u.size.sanitize (c)); + if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */ +- return TRACE_RETURN (u.stylisticSet.sanitize (c)); ++ return_trace (u.stylisticSet.sanitize (c)); + if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */ +- return TRACE_RETURN (u.characterVariants.sanitize (c)); +- return TRACE_RETURN (true); ++ return_trace (u.characterVariants.sanitize (c)); ++ return_trace (true); + } + + inline const FeatureParamsSize& get_size_params (hb_tag_t tag) const +@@ -486,10 +507,11 @@ + { return this+featureParams; } + + inline bool sanitize (hb_sanitize_context_t *c, +- const Record<Feature>::sanitize_closure_t *closure) { ++ const Record<Feature>::sanitize_closure_t *closure) const ++ { + TRACE_SANITIZE (this); + if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c)))) +- return TRACE_RETURN (false); ++ return_trace (false); + + /* Some earlier versions of Adobe tools calculated the offset of the + * FeatureParams subtable from the beginning of the FeatureList table! +@@ -504,10 +526,10 @@ + + OffsetTo<FeatureParams> orig_offset = featureParams; + if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))) +- return TRACE_RETURN (false); ++ return_trace (false); + + if (likely (orig_offset.is_null ())) +- return TRACE_RETURN (true); ++ return_trace (true); + + if (featureParams == 0 && closure && + closure->tag == HB_TAG ('s','i','z','e') && +@@ -522,10 +544,13 @@ + if (new_offset == new_offset_int && + c->try_set (&featureParams, new_offset) && + !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)) +- return TRACE_RETURN (false); ++ return_trace (false); ++ ++ if (c->edit_count > 1) ++ c->edit_count--; /* This was a "legitimate" edit; don't contribute to error count. */ + } + +- return TRACE_RETURN (true); ++ return_trace (true); + } + + OffsetTo<FeatureParams> +@@ -557,10 +582,26 @@ + DEFINE_SIZE_STATIC (2); + }; + ++} /* namespace OT */ ++/* This has to be outside the namespace. */ ++HB_MARK_AS_FLAG_T (OT::LookupFlag::Flags); ++namespace OT { ++ + struct Lookup + { + inline unsigned int get_subtable_count (void) const { return subTable.len; } + ++ template <typename SubTableType> ++ inline const SubTableType& get_subtable (unsigned int i) const ++ { return this+CastR<OffsetArrayOf<SubTableType> > (subTable)[i]; } ++ ++ template <typename SubTableType> ++ inline const OffsetArrayOf<SubTableType>& get_subtables (void) const ++ { return CastR<OffsetArrayOf<SubTableType> > (subTable); } ++ template <typename SubTableType> ++ inline OffsetArrayOf<SubTableType>& get_subtables (void) ++ { return CastR<OffsetArrayOf<SubTableType> > (subTable); } ++ + inline unsigned int get_type (void) const { return lookupType; } + + /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and +@@ -577,36 +618,52 @@ + return flag; + } + ++ template <typename SubTableType, typename context_t> ++ inline typename context_t::return_t dispatch (context_t *c) const ++ { ++ unsigned int lookup_type = get_type (); ++ TRACE_DISPATCH (this, lookup_type); ++ unsigned int count = get_subtable_count (); ++ for (unsigned int i = 0; i < count; i++) { ++ typename context_t::return_t r = get_subtable<SubTableType> (i).dispatch (c, lookup_type); ++ if (c->stop_sublookup_iteration (r)) ++ return_trace (r); ++ } ++ return_trace (c->default_return_value ()); ++ } ++ + inline bool serialize (hb_serialize_context_t *c, + unsigned int lookup_type, + uint32_t lookup_props, + unsigned int num_subtables) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend_min (*this))) return_trace (false); + lookupType.set (lookup_type); + lookupFlag.set (lookup_props & 0xFFFFu); +- if (unlikely (!subTable.serialize (c, num_subtables))) return TRACE_RETURN (false); ++ if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false); + if (lookupFlag & LookupFlag::UseMarkFilteringSet) + { + USHORT &markFilteringSet = StructAfter<USHORT> (subTable); + markFilteringSet.set (lookup_props >> 16); + } +- return TRACE_RETURN (true); ++ return_trace (true); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); + /* Real sanitize of the subtables is done by GSUB/GPOS/... */ +- if (!(c->check_struct (this) && subTable.sanitize (c))) return TRACE_RETURN (false); ++ if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false); + if (lookupFlag & LookupFlag::UseMarkFilteringSet) + { +- USHORT &markFilteringSet = StructAfter<USHORT> (subTable); +- if (!markFilteringSet.sanitize (c)) return TRACE_RETURN (false); ++ const USHORT &markFilteringSet = StructAfter<USHORT> (subTable); ++ if (!markFilteringSet.sanitize (c)) return_trace (false); + } +- return TRACE_RETURN (true); ++ return_trace (true); + } + ++ private: + USHORT lookupType; /* Different enumerations for GSUB and GPOS */ + USHORT lookupFlag; /* Lookup qualifiers */ + ArrayOf<Offset<> > +@@ -642,18 +699,19 @@ + unsigned int num_glyphs) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend_min (*this))) return_trace (false); + glyphArray.len.set (num_glyphs); +- if (unlikely (!c->extend (glyphArray))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend (glyphArray))) return_trace (false); + for (unsigned int i = 0; i < num_glyphs; i++) + glyphArray[i] = glyphs[i]; + glyphs.advance (num_glyphs); +- return TRACE_RETURN (true); ++ return_trace (true); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (glyphArray.sanitize (c)); ++ return_trace (glyphArray.sanitize (c)); + } + + inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const { +@@ -710,16 +768,16 @@ + unsigned int num_glyphs) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend_min (*this))) return_trace (false); + +- if (unlikely (!num_glyphs)) return TRACE_RETURN (true); ++ if (unlikely (!num_glyphs)) return_trace (true); + + unsigned int num_ranges = 1; + for (unsigned int i = 1; i < num_glyphs; i++) + if (glyphs[i - 1] + 1 != glyphs[i]) + num_ranges++; + rangeRecord.len.set (num_ranges); +- if (unlikely (!c->extend (rangeRecord))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend (rangeRecord))) return_trace (false); + + unsigned int range = 0; + rangeRecord[range].start = glyphs[0]; +@@ -734,12 +792,13 @@ + rangeRecord[range].end = glyphs[i]; + } + glyphs.advance (num_glyphs); +- return TRACE_RETURN (true); ++ return_trace (true); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (rangeRecord.sanitize (c)); ++ return_trace (rangeRecord.sanitize (c)); + } + + inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const { +@@ -819,26 +878,27 @@ + unsigned int num_glyphs) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend_min (*this))) return_trace (false); + unsigned int num_ranges = 1; + for (unsigned int i = 1; i < num_glyphs; i++) + if (glyphs[i - 1] + 1 != glyphs[i]) + num_ranges++; + u.format.set (num_glyphs * 2 < num_ranges * 3 ? 1 : 2); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, num_glyphs)); +- case 2: return TRACE_RETURN (u.format2.serialize (c, glyphs, num_glyphs)); +- default:return TRACE_RETURN (false); ++ case 1: return_trace (u.format1.serialize (c, glyphs, num_glyphs)); ++ case 2: return_trace (u.format2.serialize (c, glyphs, num_glyphs)); ++ default:return_trace (false); + } + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); ++ if (!u.format.sanitize (c)) return_trace (false); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- case 2: return TRACE_RETURN (u.format2.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (u.format1.sanitize (c)); ++ case 2: return_trace (u.format2.sanitize (c)); ++ default:return_trace (true); + } + } + +@@ -938,14 +998,16 @@ + private: + inline unsigned int get_class (hb_codepoint_t glyph_id) const + { +- if (unlikely ((unsigned int) (glyph_id - startGlyph) < classValue.len)) +- return classValue[glyph_id - startGlyph]; ++ unsigned int i = (unsigned int) (glyph_id - startGlyph); ++ if (unlikely (i < classValue.len)) ++ return classValue[i]; + return 0; + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && classValue.sanitize (c)); ++ return_trace (c->check_struct (this) && classValue.sanitize (c)); + } + + template <typename set_t> +@@ -994,14 +1056,15 @@ + inline unsigned int get_class (hb_codepoint_t glyph_id) const + { + int i = rangeRecord.bsearch (glyph_id); +- if (i != -1) ++ if (unlikely (i != -1)) + return rangeRecord[i].value; + return 0; + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (rangeRecord.sanitize (c)); ++ return_trace (rangeRecord.sanitize (c)); + } + + template <typename set_t> +@@ -1056,13 +1119,14 @@ + } + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); ++ if (!u.format.sanitize (c)) return_trace (false); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- case 2: return TRACE_RETURN (u.format2.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (u.format1.sanitize (c)); ++ case 2: return_trace (u.format2.sanitize (c)); ++ default:return_trace (true); + } + } + +@@ -1148,9 +1212,10 @@ + return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f))); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && c->check_range (this, this->get_size ())); ++ return_trace (c->check_struct (this) && c->check_range (this, this->get_size ())); + } + + protected: +diff -uN gfx/harfbuzz/src_old/hb-ot-layout-gdef-table.hh gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh +--- gfx/harfbuzz/src_old/hb-ot-layout-gdef-table.hh 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh 2016-06-05 23:49:22.476004876 +0200 +@@ -71,9 +71,10 @@ + return points.len; + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (coverage.sanitize (c, this) && attachPoint.sanitize (c, this)); ++ return_trace (coverage.sanitize (c, this) && attachPoint.sanitize (c, this)); + } + + protected: +@@ -101,9 +102,10 @@ + return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this)); ++ return_trace (c->check_struct (this)); + } + + protected: +@@ -127,9 +129,10 @@ + return 0; + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this)); ++ return_trace (c->check_struct (this)); + } + + protected: +@@ -150,9 +153,10 @@ + font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && deviceTable.sanitize (c, this)); ++ return_trace (c->check_struct (this) && deviceTable.sanitize (c, this)); + } + + protected: +@@ -178,14 +182,15 @@ + } + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); ++ if (!u.format.sanitize (c)) return_trace (false); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- case 2: return TRACE_RETURN (u.format2.sanitize (c)); +- case 3: return TRACE_RETURN (u.format3.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (u.format1.sanitize (c)); ++ case 2: return_trace (u.format2.sanitize (c)); ++ case 3: return_trace (u.format3.sanitize (c)); ++ default:return_trace (true); + } + } + +@@ -219,9 +224,10 @@ + return carets.len; + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (carets.sanitize (c, this)); ++ return_trace (carets.sanitize (c, this)); + } + + protected: +@@ -253,9 +259,10 @@ + return lig_glyph.get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this)); ++ return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this)); + } + + protected: +@@ -275,9 +282,10 @@ + inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const + { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (coverage.sanitize (c, this)); ++ return_trace (coverage.sanitize (c, this)); + } + + protected: +@@ -299,12 +307,13 @@ + } + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); ++ if (!u.format.sanitize (c)) return_trace (false); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (u.format1.sanitize (c)); ++ default:return_trace (true); + } + } + +@@ -364,15 +373,16 @@ + inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const + { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (version.sanitize (c) && +- likely (version.major == 1) && +- glyphClassDef.sanitize (c, this) && +- attachList.sanitize (c, this) && +- ligCaretList.sanitize (c, this) && +- markAttachClassDef.sanitize (c, this) && +- (version.to_int () < 0x00010002u || markGlyphSetsDef[0].sanitize (c, this))); ++ return_trace (version.sanitize (c) && ++ likely (version.major == 1) && ++ glyphClassDef.sanitize (c, this) && ++ attachList.sanitize (c, this) && ++ ligCaretList.sanitize (c, this) && ++ markAttachClassDef.sanitize (c, this) && ++ (version.to_int () < 0x00010002u || markGlyphSetsDef[0].sanitize (c, this))); + } + + +diff -uN gfx/harfbuzz/src_old/hb-ot-layout-gpos-table.hh gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh +--- gfx/harfbuzz/src_old/hb-ot-layout-gpos-table.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh 2016-06-05 23:49:23.921997102 +0200 +@@ -146,7 +146,8 @@ + } + + private: +- inline bool sanitize_value_devices (hb_sanitize_context_t *c, void *base, Value *values) { ++ inline bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const ++ { + unsigned int format = *this; + + if (format & xPlacement) values++; +@@ -177,41 +178,44 @@ + return (format & devices) != 0; + } + +- inline bool sanitize_value (hb_sanitize_context_t *c, void *base, Value *values) { ++ inline bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values))); ++ return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values))); + } + +- inline bool sanitize_values (hb_sanitize_context_t *c, void *base, Value *values, unsigned int count) { ++ inline bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const ++ { + TRACE_SANITIZE (this); + unsigned int len = get_len (); + +- if (!c->check_array (values, get_size (), count)) return TRACE_RETURN (false); ++ if (!c->check_array (values, get_size (), count)) return_trace (false); + +- if (!has_device ()) return TRACE_RETURN (true); ++ if (!has_device ()) return_trace (true); + + for (unsigned int i = 0; i < count; i++) { + if (!sanitize_value_devices (c, base, values)) +- return TRACE_RETURN (false); ++ return_trace (false); + values += len; + } + +- return TRACE_RETURN (true); ++ return_trace (true); + } + + /* Just sanitize referenced Device tables. Doesn't check the values themselves. */ +- inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, void *base, Value *values, unsigned int count, unsigned int stride) { ++ inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const ++ { + TRACE_SANITIZE (this); + +- if (!has_device ()) return TRACE_RETURN (true); ++ if (!has_device ()) return_trace (true); + + for (unsigned int i = 0; i < count; i++) { + if (!sanitize_value_devices (c, base, values)) +- return TRACE_RETURN (false); ++ return_trace (false); + values += stride; + } + +- return TRACE_RETURN (true); ++ return_trace (true); + } + }; + +@@ -225,9 +229,10 @@ + *y = font->em_scale_y (yCoordinate); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this)); ++ return_trace (c->check_struct (this)); + } + + protected: +@@ -254,9 +259,10 @@ + *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this)); ++ return_trace (c->check_struct (this)); + } + + protected: +@@ -282,9 +288,10 @@ + *y += (this+yDeviceTable).get_x_delta (font); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this)); ++ return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this)); + } + + protected: +@@ -317,14 +324,15 @@ + } + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); ++ if (!u.format.sanitize (c)) return_trace (false); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- case 2: return TRACE_RETURN (u.format2.sanitize (c)); +- case 3: return TRACE_RETURN (u.format3.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (u.format1.sanitize (c)); ++ case 2: return_trace (u.format2.sanitize (c)); ++ case 3: return_trace (u.format3.sanitize (c)); ++ default:return_trace (true); + } + } + +@@ -349,15 +357,16 @@ + return this+matrixZ[row * cols + col]; + } + +- inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) { ++ inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const ++ { + TRACE_SANITIZE (this); +- if (!c->check_struct (this)) return TRACE_RETURN (false); +- if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return TRACE_RETURN (false); ++ if (!c->check_struct (this)) return_trace (false); ++ if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return_trace (false); + unsigned int count = rows * cols; +- if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return TRACE_RETURN (false); ++ if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return_trace (false); + for (unsigned int i = 0; i < count; i++) +- if (!matrixZ[i].sanitize (c, this)) return TRACE_RETURN (false); +- return TRACE_RETURN (true); ++ if (!matrixZ[i].sanitize (c, this)) return_trace (false); ++ return_trace (true); + } + + USHORT rows; /* Number of rows */ +@@ -374,9 +383,10 @@ + { + friend struct MarkArray; + +- inline bool sanitize (hb_sanitize_context_t *c, void *base) { ++ inline bool sanitize (hb_sanitize_context_t *c, const void *base) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && markAnchor.sanitize (c, base)); ++ return_trace (c->check_struct (this) && markAnchor.sanitize (c, base)); + } + + protected: +@@ -405,7 +415,7 @@ + const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found); + /* If this subtable doesn't have an anchor for this base and this class, + * return false such that the subsequent subtables have a chance at it. */ +- if (unlikely (!found)) return TRACE_RETURN (false); ++ if (unlikely (!found)) return_trace (false); + + hb_position_t mark_x, mark_y, base_x, base_y; + +@@ -416,14 +426,16 @@ + o.x_offset = base_x - mark_x; + o.y_offset = base_y - mark_y; + o.attach_lookback() = buffer->idx - glyph_pos; ++ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT; + + buffer->idx++; +- return TRACE_RETURN (true); ++ return_trace (true); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (ArrayOf<MarkRecord>::sanitize (c, this)); ++ return_trace (ArrayOf<MarkRecord>::sanitize (c, this)); + } + }; + +@@ -448,18 +460,21 @@ + TRACE_APPLY (this); + hb_buffer_t *buffer = c->buffer; + unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); +- if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (index == NOT_COVERED)) return_trace (false); + + valueFormat.apply_value (c->font, c->direction, this, + values, buffer->cur_pos()); + + buffer->idx++; +- return TRACE_RETURN (true); ++ return_trace (true); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) && valueFormat.sanitize_value (c, this, values)); ++ return_trace (c->check_struct (this) && ++ coverage.sanitize (c, this) && ++ valueFormat.sanitize_value (c, this, values)); + } + + protected: +@@ -494,21 +509,24 @@ + TRACE_APPLY (this); + hb_buffer_t *buffer = c->buffer; + unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); +- if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (index == NOT_COVERED)) return_trace (false); + +- if (likely (index >= valueCount)) return TRACE_RETURN (false); ++ if (likely (index >= valueCount)) return_trace (false); + + valueFormat.apply_value (c->font, c->direction, this, + &values[index * valueFormat.get_len ()], + buffer->cur_pos()); + + buffer->idx++; +- return TRACE_RETURN (true); ++ return_trace (true); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) && valueFormat.sanitize_values (c, this, values, valueCount)); ++ return_trace (c->check_struct (this) && ++ coverage.sanitize (c, this) && ++ valueFormat.sanitize_values (c, this, values, valueCount)); + } + + protected: +@@ -531,20 +549,11 @@ + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this, u.format); ++ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { +- case 1: return TRACE_RETURN (c->dispatch (u.format1)); +- case 2: return TRACE_RETURN (c->dispatch (u.format2)); +- default:return TRACE_RETURN (c->default_return_value ()); +- } +- } +- +- inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- case 2: return TRACE_RETURN (u.format2.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (c->dispatch (u.format1)); ++ case 2: return_trace (c->dispatch (u.format2)); ++ default:return_trace (c->default_return_value ()); + } + } + +@@ -602,12 +611,24 @@ + unsigned int len2 = valueFormats[1].get_len (); + unsigned int record_size = USHORT::static_size * (1 + len1 + len2); + +- const PairValueRecord *record = CastP<PairValueRecord> (arrayZ); ++ const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ); + unsigned int count = len; +- for (unsigned int i = 0; i < count; i++) ++ ++ /* Hand-coded bsearch. */ ++ if (unlikely (!count)) ++ return_trace (false); ++ hb_codepoint_t x = buffer->info[pos].codepoint; ++ int min = 0, max = (int) count - 1; ++ while (min <= max) + { +- /* TODO bsearch */ +- if (buffer->info[pos].codepoint == record->secondGlyph) ++ int mid = (min + max) / 2; ++ const PairValueRecord *record = &StructAtOffset<PairValueRecord> (record_array, record_size * mid); ++ hb_codepoint_t mid_x = record->secondGlyph; ++ if (x < mid_x) ++ max = mid - 1; ++ else if (x > mid_x) ++ min = mid + 1; ++ else + { + valueFormats[0].apply_value (c->font, c->direction, this, + &record->values[0], buffer->cur_pos()); +@@ -616,30 +637,30 @@ + if (len2) + pos++; + buffer->idx = pos; +- return TRACE_RETURN (true); ++ return_trace (true); + } +- record = &StructAtOffset<PairValueRecord> (record, record_size); + } + +- return TRACE_RETURN (false); ++ return_trace (false); + } + + struct sanitize_closure_t { +- void *base; +- ValueFormat *valueFormats; ++ const void *base; ++ const ValueFormat *valueFormats; + unsigned int len1; /* valueFormats[0].get_len() */ + unsigned int stride; /* 1 + len1 + len2 */ + }; + +- inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) { ++ inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const ++ { + TRACE_SANITIZE (this); + if (!(c->check_struct (this) +- && c->check_array (arrayZ, USHORT::static_size * closure->stride, len))) return TRACE_RETURN (false); ++ && c->check_array (arrayZ, USHORT::static_size * closure->stride, len))) return_trace (false); + + unsigned int count = len; +- PairValueRecord *record = CastP<PairValueRecord> (arrayZ); +- return TRACE_RETURN (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride) +- && closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride)); ++ const PairValueRecord *record = CastP<PairValueRecord> (arrayZ); ++ return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride) && ++ closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride)); + } + + protected: +@@ -670,20 +691,22 @@ + { + TRACE_APPLY (this); + hb_buffer_t *buffer = c->buffer; +- hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, 1); +- if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); +- + unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); +- if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (index == NOT_COVERED)) return_trace (false); + +- if (!skippy_iter.next ()) return TRACE_RETURN (false); ++ hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; ++ skippy_iter.reset (buffer->idx, 1); ++ if (!skippy_iter.next ()) return_trace (false); + +- return TRACE_RETURN ((this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx)); ++ return_trace ((this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx)); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); + ++ if (!c->check_struct (this)) return_trace (false); ++ + unsigned int len1 = valueFormat1.get_len (); + unsigned int len2 = valueFormat2.get_len (); + PairSet::sanitize_closure_t closure = { +@@ -693,7 +716,7 @@ + 1 + len1 + len2 + }; + +- return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure)); ++ return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure)); + } + + protected: +@@ -719,7 +742,7 @@ + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + TRACE_COLLECT_GLYPHS (this); +- /* (this+coverage).add_coverage (c->input); // Don't need this. */ ++ (this+coverage).add_coverage (c->input); + + unsigned int count1 = class1Count; + const ClassDef &klass1 = this+classDef1; +@@ -741,13 +764,12 @@ + { + TRACE_APPLY (this); + hb_buffer_t *buffer = c->buffer; +- hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, 1); +- if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); +- + unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); +- if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (index == NOT_COVERED)) return_trace (false); + +- if (!skippy_iter.next ()) return TRACE_RETURN (false); ++ hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; ++ skippy_iter.reset (buffer->idx, 1); ++ if (!skippy_iter.next ()) return_trace (false); + + unsigned int len1 = valueFormat1.get_len (); + unsigned int len2 = valueFormat2.get_len (); +@@ -755,7 +777,7 @@ + + unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint); + unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint); +- if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return TRACE_RETURN (false); ++ if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false); + + const Value *v = &values[record_len * (klass1 * class2Count + klass2)]; + valueFormat1.apply_value (c->font, c->direction, this, +@@ -767,24 +789,25 @@ + if (len2) + buffer->idx++; + +- return TRACE_RETURN (true); ++ return_trace (true); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); + if (!(c->check_struct (this) + && coverage.sanitize (c, this) + && classDef1.sanitize (c, this) +- && classDef2.sanitize (c, this))) return TRACE_RETURN (false); ++ && classDef2.sanitize (c, this))) return_trace (false); + + unsigned int len1 = valueFormat1.get_len (); + unsigned int len2 = valueFormat2.get_len (); + unsigned int stride = len1 + len2; + unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size (); + unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count; +- return TRACE_RETURN (c->check_array (values, record_size, count) && +- valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) && +- valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride)); ++ return_trace (c->check_array (values, record_size, count) && ++ valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) && ++ valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride)); + } + + protected: +@@ -823,20 +846,11 @@ + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this, u.format); ++ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { +- case 1: return TRACE_RETURN (c->dispatch (u.format1)); +- case 2: return TRACE_RETURN (c->dispatch (u.format2)); +- default:return TRACE_RETURN (c->default_return_value ()); +- } +- } +- +- inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- case 2: return TRACE_RETURN (u.format2.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (c->dispatch (u.format1)); ++ case 2: return_trace (c->dispatch (u.format2)); ++ default:return_trace (c->default_return_value ()); + } + } + +@@ -853,9 +867,10 @@ + { + friend struct CursivePosFormat1; + +- inline bool sanitize (hb_sanitize_context_t *c, void *base) { ++ inline bool sanitize (hb_sanitize_context_t *c, const void *base) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base)); ++ return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base)); + } + + protected: +@@ -871,6 +886,9 @@ + DEFINE_SIZE_STATIC (4); + }; + ++static void ++reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent); ++ + struct CursivePosFormat1 + { + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const +@@ -890,18 +908,17 @@ + hb_buffer_t *buffer = c->buffer; + + /* We don't handle mark glyphs here. */ +- if (unlikely (_hb_glyph_info_is_mark (&buffer->cur()))) return TRACE_RETURN (false); +- +- hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, 1); +- if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); ++ if (unlikely (_hb_glyph_info_is_mark (&buffer->cur()))) return_trace (false); + + const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)]; +- if (!this_record.exitAnchor) return TRACE_RETURN (false); ++ if (!this_record.exitAnchor) return_trace (false); + +- if (!skippy_iter.next ()) return TRACE_RETURN (false); ++ hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; ++ skippy_iter.reset (buffer->idx, 1); ++ if (!skippy_iter.next ()) return_trace (false); + + const EntryExitRecord &next_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)]; +- if (!next_record.entryAnchor) return TRACE_RETURN (false); ++ if (!next_record.entryAnchor) return_trace (false); + + unsigned int i = buffer->idx; + unsigned int j = skippy_iter.idx; +@@ -949,27 +966,48 @@ + } + + /* Cross-direction adjustment */ +- if (c->lookup_props & LookupFlag::RightToLeft) { +- pos[i].cursive_chain() = j - i; +- if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction))) +- pos[i].y_offset = entry_y - exit_y; +- else +- pos[i].x_offset = entry_x - exit_x; +- } else { +- pos[j].cursive_chain() = i - j; +- if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction))) +- pos[j].y_offset = exit_y - entry_y; +- else +- pos[j].x_offset = exit_x - entry_x; +- } ++ ++ /* We attach child to parent (think graph theory and rooted trees whereas ++ * the root stays on baseline and each node aligns itself against its ++ * parent. ++ * ++ * Optimize things for the case of RightToLeft, as that's most common in ++ * Arabinc. */ ++ unsigned int child = i; ++ unsigned int parent = j; ++ hb_position_t x_offset = entry_x - exit_x; ++ hb_position_t y_offset = entry_y - exit_y; ++ if (!(c->lookup_props & LookupFlag::RightToLeft)) ++ { ++ unsigned int k = child; ++ child = parent; ++ parent = k; ++ x_offset = -x_offset; ++ y_offset = -y_offset; ++ } ++ ++ /* If child was already connected to someone else, walk through its old ++ * chain and reverse the link direction, such that the whole tree of its ++ * previous connection now attaches to new parent. Watch out for case ++ * where new parent is on the path from old chain... ++ */ ++ reverse_cursive_minor_offset (pos, child, c->direction, parent); ++ ++ pos[child].cursive_chain() = parent - child; ++ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_CURSIVE; ++ if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction))) ++ pos[child].y_offset = y_offset; ++ else ++ pos[child].x_offset = x_offset; + + buffer->idx = j; +- return TRACE_RETURN (true); ++ return_trace (true); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this)); ++ return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this)); + } + + protected: +@@ -990,18 +1028,10 @@ + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this, u.format); ++ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { +- case 1: return TRACE_RETURN (c->dispatch (u.format1)); +- default:return TRACE_RETURN (c->default_return_value ()); +- } +- } +- +- inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (c->dispatch (u.format1)); ++ default:return_trace (c->default_return_value ()); + } + } + +@@ -1037,31 +1067,36 @@ + TRACE_APPLY (this); + hb_buffer_t *buffer = c->buffer; + unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint); +- if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (mark_index == NOT_COVERED)) return_trace (false); + + /* now we search backwards for a non-mark glyph */ +- hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, buffer->idx, 1); ++ hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; ++ skippy_iter.reset (buffer->idx, 1); + skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); + do { +- if (!skippy_iter.prev ()) return TRACE_RETURN (false); ++ if (!skippy_iter.prev ()) return_trace (false); + /* We only want to attach to the first of a MultipleSubst sequence. Reject others. */ + if (0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx])) break; + skippy_iter.reject (); + } while (1); + + /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */ +- if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { /*return TRACE_RETURN (false);*/ } ++ if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { /*return_trace (false);*/ } + + unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint); +- if (base_index == NOT_COVERED) return TRACE_RETURN (false); ++ if (base_index == NOT_COVERED) return_trace (false); + +- return TRACE_RETURN ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx)); ++ return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx)); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, this) && baseCoverage.sanitize (c, this) && +- markArray.sanitize (c, this) && baseArray.sanitize (c, this, (unsigned int) classCount)); ++ return_trace (c->check_struct (this) && ++ markCoverage.sanitize (c, this) && ++ baseCoverage.sanitize (c, this) && ++ markArray.sanitize (c, this) && ++ baseArray.sanitize (c, this, (unsigned int) classCount)); + } + + protected: +@@ -1089,18 +1124,10 @@ + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this, u.format); ++ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { +- case 1: return TRACE_RETURN (c->dispatch (u.format1)); +- default:return TRACE_RETURN (c->default_return_value ()); +- } +- } +- +- inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (c->dispatch (u.format1)); ++ default:return_trace (c->default_return_value ()); + } + } + +@@ -1141,26 +1168,27 @@ + TRACE_APPLY (this); + hb_buffer_t *buffer = c->buffer; + unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint); +- if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (mark_index == NOT_COVERED)) return_trace (false); + + /* now we search backwards for a non-mark glyph */ +- hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, buffer->idx, 1); ++ hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; ++ skippy_iter.reset (buffer->idx, 1); + skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); +- if (!skippy_iter.prev ()) return TRACE_RETURN (false); ++ if (!skippy_iter.prev ()) return_trace (false); + + /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */ +- if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { /*return TRACE_RETURN (false);*/ } ++ if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { /*return_trace (false);*/ } + + unsigned int j = skippy_iter.idx; + unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint); +- if (lig_index == NOT_COVERED) return TRACE_RETURN (false); ++ if (lig_index == NOT_COVERED) return_trace (false); + + const LigatureArray& lig_array = this+ligatureArray; + const LigatureAttach& lig_attach = lig_array[lig_index]; + + /* Find component to attach to */ + unsigned int comp_count = lig_attach.rows; +- if (unlikely (!comp_count)) return TRACE_RETURN (false); ++ if (unlikely (!comp_count)) return_trace (false); + + /* We must now check whether the ligature ID of the current mark glyph + * is identical to the ligature ID of the found ligature. If yes, we +@@ -1175,13 +1203,17 @@ + else + comp_index = comp_count - 1; + +- return TRACE_RETURN ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j)); ++ return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j)); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, this) && ligatureCoverage.sanitize (c, this) && +- markArray.sanitize (c, this) && ligatureArray.sanitize (c, this, (unsigned int) classCount)); ++ return_trace (c->check_struct (this) && ++ markCoverage.sanitize (c, this) && ++ ligatureCoverage.sanitize (c, this) && ++ markArray.sanitize (c, this) && ++ ligatureArray.sanitize (c, this, (unsigned int) classCount)); + } + + protected: +@@ -1210,18 +1242,10 @@ + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this, u.format); ++ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { +- case 1: return TRACE_RETURN (c->dispatch (u.format1)); +- default:return TRACE_RETURN (c->default_return_value ()); +- } +- } +- +- inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (c->dispatch (u.format1)); ++ default:return_trace (c->default_return_value ()); + } + } + +@@ -1257,14 +1281,15 @@ + TRACE_APPLY (this); + hb_buffer_t *buffer = c->buffer; + unsigned int mark1_index = (this+mark1Coverage).get_coverage (buffer->cur().codepoint); +- if (likely (mark1_index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (mark1_index == NOT_COVERED)) return_trace (false); + + /* now we search backwards for a suitable mark glyph until a non-mark glyph */ +- hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, buffer->idx, 1); ++ hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; ++ skippy_iter.reset (buffer->idx, 1); + skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags); +- if (!skippy_iter.prev ()) return TRACE_RETURN (false); ++ if (!skippy_iter.prev ()) return_trace (false); + +- if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) { return TRACE_RETURN (false); } ++ if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) { return_trace (false); } + + unsigned int j = skippy_iter.idx; + +@@ -1286,20 +1311,23 @@ + } + + /* Didn't match. */ +- return TRACE_RETURN (false); ++ return_trace (false); + + good: + unsigned int mark2_index = (this+mark2Coverage).get_coverage (buffer->info[j].codepoint); +- if (mark2_index == NOT_COVERED) return TRACE_RETURN (false); ++ if (mark2_index == NOT_COVERED) return_trace (false); + +- return TRACE_RETURN ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j)); ++ return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j)); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && mark1Coverage.sanitize (c, this) && +- mark2Coverage.sanitize (c, this) && mark1Array.sanitize (c, this) +- && mark2Array.sanitize (c, this, (unsigned int) classCount)); ++ return_trace (c->check_struct (this) && ++ mark1Coverage.sanitize (c, this) && ++ mark2Coverage.sanitize (c, this) && ++ mark1Array.sanitize (c, this) && ++ mark2Array.sanitize (c, this, (unsigned int) classCount)); + } + + protected: +@@ -1329,18 +1357,10 @@ + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this, u.format); ++ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { +- case 1: return TRACE_RETURN (c->dispatch (u.format1)); +- default:return TRACE_RETURN (c->default_return_value ()); +- } +- } +- +- inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (c->dispatch (u.format1)); ++ default:return_trace (c->default_return_value ()); + } + } + +@@ -1388,43 +1408,24 @@ + inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const + { + TRACE_DISPATCH (this, lookup_type); ++ if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace (c->no_dispatch_return_value ()); + switch (lookup_type) { +- case Single: return TRACE_RETURN (u.single.dispatch (c)); +- case Pair: return TRACE_RETURN (u.pair.dispatch (c)); +- case Cursive: return TRACE_RETURN (u.cursive.dispatch (c)); +- case MarkBase: return TRACE_RETURN (u.markBase.dispatch (c)); +- case MarkLig: return TRACE_RETURN (u.markLig.dispatch (c)); +- case MarkMark: return TRACE_RETURN (u.markMark.dispatch (c)); +- case Context: return TRACE_RETURN (u.context.dispatch (c)); +- case ChainContext: return TRACE_RETURN (u.chainContext.dispatch (c)); +- case Extension: return TRACE_RETURN (u.extension.dispatch (c)); +- default: return TRACE_RETURN (c->default_return_value ()); +- } +- } +- +- inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) { +- TRACE_SANITIZE (this); +- if (!u.header.sub_format.sanitize (c)) +- return TRACE_RETURN (false); +- switch (lookup_type) { +- case Single: return TRACE_RETURN (u.single.sanitize (c)); +- case Pair: return TRACE_RETURN (u.pair.sanitize (c)); +- case Cursive: return TRACE_RETURN (u.cursive.sanitize (c)); +- case MarkBase: return TRACE_RETURN (u.markBase.sanitize (c)); +- case MarkLig: return TRACE_RETURN (u.markLig.sanitize (c)); +- case MarkMark: return TRACE_RETURN (u.markMark.sanitize (c)); +- case Context: return TRACE_RETURN (u.context.sanitize (c)); +- case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c)); +- case Extension: return TRACE_RETURN (u.extension.sanitize (c)); +- default: return TRACE_RETURN (true); ++ case Single: return_trace (u.single.dispatch (c)); ++ case Pair: return_trace (u.pair.dispatch (c)); ++ case Cursive: return_trace (u.cursive.dispatch (c)); ++ case MarkBase: return_trace (u.markBase.dispatch (c)); ++ case MarkLig: return_trace (u.markLig.dispatch (c)); ++ case MarkMark: return_trace (u.markMark.dispatch (c)); ++ case Context: return_trace (u.context.dispatch (c)); ++ case ChainContext: return_trace (u.chainContext.dispatch (c)); ++ case Extension: return_trace (u.extension.dispatch (c)); ++ default: return_trace (c->default_return_value ()); + } + } + + protected: + union { +- struct { +- USHORT sub_format; +- } header; ++ USHORT sub_format; + SinglePos single; + PairPos pair; + CursivePos cursive; +@@ -1436,48 +1437,37 @@ + ExtensionPos extension; + } u; + public: +- DEFINE_SIZE_UNION (2, header.sub_format); ++ DEFINE_SIZE_UNION (2, sub_format); + }; + + + struct PosLookup : Lookup + { + inline const PosLookupSubTable& get_subtable (unsigned int i) const +- { return this+CastR<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; } ++ { return Lookup::get_subtable<PosLookupSubTable> (i); } + + inline bool is_reverse (void) const + { + return false; + } + ++ inline bool apply (hb_apply_context_t *c) const ++ { ++ TRACE_APPLY (this); ++ return_trace (dispatch (c)); ++ } ++ + inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const + { + TRACE_COLLECT_GLYPHS (this); +- c->set_recurse_func (NULL); +- return TRACE_RETURN (dispatch (c)); ++ return_trace (dispatch (c)); + } + + template <typename set_t> + inline void add_coverage (set_t *glyphs) const + { +- hb_get_coverage_context_t c; +- const Coverage *last = NULL; +- unsigned int count = get_subtable_count (); +- for (unsigned int i = 0; i < count; i++) { +- const Coverage *coverage = &get_subtable (i).dispatch (&c, get_type ()); +- if (coverage != last) { +- coverage->add_coverage (glyphs); +- last = coverage; +- } +- } +- } +- +- inline bool apply_once (hb_apply_context_t *c) const +- { +- TRACE_APPLY (this); +- if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props)) +- return TRACE_RETURN (false); +- return TRACE_RETURN (dispatch (c)); ++ hb_add_coverage_context_t<set_t> c (glyphs); ++ dispatch (&c); + } + + static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index); +@@ -1487,23 +1477,13 @@ + + template <typename context_t> + inline typename context_t::return_t dispatch (context_t *c) const +- { +- unsigned int lookup_type = get_type (); +- TRACE_DISPATCH (this, lookup_type); +- unsigned int count = get_subtable_count (); +- for (unsigned int i = 0; i < count; i++) { +- typename context_t::return_t r = get_subtable (i).dispatch (c, lookup_type); +- if (c->stop_sublookup_iteration (r)) +- return TRACE_RETURN (r); +- } +- return TRACE_RETURN (c->default_return_value ()); +- } ++ { return Lookup::dispatch<PosLookupSubTable> (c); } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false); +- OffsetArrayOf<PosLookupSubTable> &list = CastR<OffsetArrayOf<PosLookupSubTable> > (subTable); +- return TRACE_RETURN (list.sanitize (c, this, get_type ())); ++ if (unlikely (!Lookup::sanitize (c))) return_trace (false); ++ return_trace (dispatch (c)); + } + }; + +@@ -1523,11 +1503,12 @@ + static inline void position_start (hb_font_t *font, hb_buffer_t *buffer); + static inline void position_finish (hb_font_t *font, hb_buffer_t *buffer); + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false); +- OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList); +- return TRACE_RETURN (list.sanitize (c, this)); ++ if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false); ++ const OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList); ++ return_trace (list.sanitize (c, this)); + } + public: + DEFINE_SIZE_STATIC (10); +@@ -1535,6 +1516,30 @@ + + + static void ++reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent) ++{ ++ unsigned int j = pos[i].cursive_chain(); ++ if (likely (!j)) ++ return; ++ ++ j += i; ++ ++ pos[i].cursive_chain() = 0; ++ ++ /* Stop if we see new parent in the chain. */ ++ if (j == new_parent) ++ return; ++ ++ reverse_cursive_minor_offset (pos, j, direction, new_parent); ++ ++ if (HB_DIRECTION_IS_HORIZONTAL (direction)) ++ pos[j].y_offset = -pos[i].y_offset; ++ else ++ pos[j].x_offset = -pos[i].x_offset; ++ ++ pos[j].cursive_chain() = i - j; ++} ++static void + fix_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction) + { + unsigned int j = pos[i].cursive_chain(); +@@ -1596,12 +1601,14 @@ + hb_direction_t direction = buffer->props.direction; + + /* Handle cursive connections */ +- for (unsigned int i = 0; i < len; i++) +- fix_cursive_minor_offset (pos, i, direction); ++ if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_CURSIVE) ++ for (unsigned int i = 0; i < len; i++) ++ fix_cursive_minor_offset (pos, i, direction); + + /* Handle attachments */ +- for (unsigned int i = 0; i < len; i++) +- fix_mark_attachment (pos, i, direction); ++ if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT) ++ for (unsigned int i = 0; i < len; i++) ++ fix_mark_attachment (pos, i, direction); + } + + +@@ -1620,9 +1627,12 @@ + const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos); + const PosLookup &l = gpos.get_lookup (lookup_index); + unsigned int saved_lookup_props = c->lookup_props; +- c->set_lookup (l); +- bool ret = l.apply_once (c); +- c->lookup_props = saved_lookup_props; ++ unsigned int saved_lookup_index = c->lookup_index; ++ c->set_lookup_index (lookup_index); ++ c->set_lookup_props (l.get_props ()); ++ bool ret = l.dispatch (c); ++ c->set_lookup_index (saved_lookup_index); ++ c->set_lookup_props (saved_lookup_props); + return ret; + } + +diff -uN gfx/harfbuzz/src_old/hb-ot-layout-gsubgpos-private.hh gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh +--- gfx/harfbuzz/src_old/hb-ot-layout-gsubgpos-private.hh 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh 2016-06-05 23:49:27.351978674 +0200 +@@ -37,12 +37,6 @@ + namespace OT { + + +- +-#define TRACE_DISPATCH(this, format) \ +- hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \ +- (&c->debug_depth, c->get_name (), this, HB_FUNC, \ +- "format %d", (int) format); +- + #ifndef HB_DEBUG_CLOSURE + #define HB_DEBUG_CLOSURE (HB_DEBUG+0) + #endif +@@ -52,11 +46,10 @@ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + ""); + +-struct hb_closure_context_t ++struct hb_closure_context_t : ++ hb_dispatch_context_t<hb_closure_context_t, hb_void_t, HB_DEBUG_CLOSURE> + { + inline const char *get_name (void) { return "CLOSURE"; } +- static const unsigned int max_debug_depth = HB_DEBUG_CLOSURE; +- typedef hb_void_t return_t; + typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index); + template <typename T> + inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; } +@@ -81,7 +74,7 @@ + + hb_closure_context_t (hb_face_t *face_, + hb_set_t *glyphs_, +- unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) : ++ unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) : + face (face_), + glyphs (glyphs_), + recurse_func (NULL), +@@ -102,11 +95,10 @@ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + "%d glyphs", c->len); + +-struct hb_would_apply_context_t ++struct hb_would_apply_context_t : ++ hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY> + { + inline const char *get_name (void) { return "WOULD_APPLY"; } +- static const unsigned int max_debug_depth = HB_DEBUG_WOULD_APPLY; +- typedef bool return_t; + template <typename T> + inline return_t dispatch (const T &obj) { return obj.would_apply (this); } + static return_t default_return_value (void) { return false; } +@@ -140,11 +132,10 @@ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + ""); + +-struct hb_collect_glyphs_context_t ++struct hb_collect_glyphs_context_t : ++ hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, HB_DEBUG_COLLECT_GLYPHS> + { + inline const char *get_name (void) { return "COLLECT_GLYPHS"; } +- static const unsigned int max_debug_depth = HB_DEBUG_COLLECT_GLYPHS; +- typedef hb_void_t return_t; + typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index); + template <typename T> + inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; } +@@ -205,7 +196,7 @@ + hb_set_t *glyphs_input, /* OUT. May be NULL */ + hb_set_t *glyphs_after, /* OUT. May be NULL */ + hb_set_t *glyphs_output, /* OUT. May be NULL */ +- unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) : ++ unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) : + face (face_), + before (glyphs_before ? glyphs_before : hb_set_get_empty ()), + input (glyphs_input ? glyphs_input : hb_set_get_empty ()), +@@ -232,18 +223,28 @@ + #define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0) + #endif + +-struct hb_get_coverage_context_t ++/* XXX Can we remove this? */ ++ ++template <typename set_t> ++struct hb_add_coverage_context_t : ++ hb_dispatch_context_t<hb_add_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE> + { + inline const char *get_name (void) { return "GET_COVERAGE"; } +- static const unsigned int max_debug_depth = HB_DEBUG_GET_COVERAGE; + typedef const Coverage &return_t; + template <typename T> + inline return_t dispatch (const T &obj) { return obj.get_coverage (); } + static return_t default_return_value (void) { return Null(Coverage); } ++ bool stop_sublookup_iteration (return_t r) const ++ { ++ r.add_coverage (set); ++ return false; ++ } + +- hb_get_coverage_context_t (void) : ++ hb_add_coverage_context_t (set_t *set_) : ++ set (set_), + debug_depth (0) {} + ++ set_t *set; + unsigned int debug_depth; + }; + +@@ -256,65 +257,12 @@ + #define TRACE_APPLY(this) \ + hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ +- "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint); ++ "idx %d gid %u lookup %d", \ ++ c->buffer->idx, c->buffer->cur().codepoint, (int) c->lookup_index); + +-struct hb_apply_context_t ++struct hb_apply_context_t : ++ hb_dispatch_context_t<hb_apply_context_t, bool, HB_DEBUG_APPLY> + { +- inline const char *get_name (void) { return "APPLY"; } +- static const unsigned int max_debug_depth = HB_DEBUG_APPLY; +- typedef bool return_t; +- typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup_index); +- template <typename T> +- inline return_t dispatch (const T &obj) { return obj.apply (this); } +- static return_t default_return_value (void) { return false; } +- bool stop_sublookup_iteration (return_t r) const { return r; } +- return_t recurse (unsigned int lookup_index) +- { +- if (unlikely (nesting_level_left == 0 || !recurse_func)) +- return default_return_value (); +- +- nesting_level_left--; +- bool ret = recurse_func (this, lookup_index); +- nesting_level_left++; +- return ret; +- } +- +- unsigned int table_index; /* GSUB/GPOS */ +- hb_font_t *font; +- hb_face_t *face; +- hb_buffer_t *buffer; +- hb_direction_t direction; +- hb_mask_t lookup_mask; +- bool auto_zwj; +- recurse_func_t recurse_func; +- unsigned int nesting_level_left; +- unsigned int lookup_props; +- const GDEF &gdef; +- bool has_glyph_classes; +- unsigned int debug_depth; +- +- +- hb_apply_context_t (unsigned int table_index_, +- hb_font_t *font_, +- hb_buffer_t *buffer_) : +- table_index (table_index_), +- font (font_), face (font->face), buffer (buffer_), +- direction (buffer_->props.direction), +- lookup_mask (1), +- auto_zwj (true), +- recurse_func (NULL), +- nesting_level_left (MAX_NESTING_LEVEL), +- lookup_props (0), +- gdef (*hb_ot_layout_from_face (face)->gdef), +- has_glyph_classes (gdef.has_glyph_classes ()), +- debug_depth (0) {} +- +- inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; } +- inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; } +- inline void set_recurse_func (recurse_func_t func) { recurse_func = func; } +- inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; } +- inline void set_lookup (const Lookup &l) { lookup_props = l.get_props (); } +- + struct matcher_t + { + inline matcher_t (void) : +@@ -373,8 +321,7 @@ + + if (unlikely (_hb_glyph_info_is_default_ignorable (&info) && + (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) && +- (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) && +- !_hb_glyph_info_ligated (&info))) ++ (ignore_zwj || !_hb_glyph_info_is_zwj (&info)))) + return SKIP_MAYBE; + + return SKIP_NO; +@@ -390,43 +337,47 @@ + const void *match_data; + }; + +- struct skipping_forward_iterator_t ++ struct skipping_iterator_t + { +- inline skipping_forward_iterator_t (hb_apply_context_t *c_, +- unsigned int start_index_, +- unsigned int num_items_, +- bool context_match = false) : +- idx (start_index_), +- c (c_), +- match_glyph_data (NULL), +- num_items (num_items_), +- end (c->buffer->len) ++ inline void init (hb_apply_context_t *c_, bool context_match = false) + { ++ c = c_; ++ match_glyph_data = NULL, ++ matcher.set_match_func (NULL, NULL); + matcher.set_lookup_props (c->lookup_props); + /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */ + matcher.set_ignore_zwnj (context_match || c->table_index == 1); + /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */ + matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj); +- if (!context_match) +- matcher.set_mask (c->lookup_mask); +- matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0); ++ matcher.set_mask (context_match ? -1 : c->lookup_mask); + } +- inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); } +- inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); } +- inline void set_match_func (matcher_t::match_func_t match_func, +- const void *match_data, ++ inline void set_lookup_props (unsigned int lookup_props) ++ { ++ matcher.set_lookup_props (lookup_props); ++ } ++ inline void set_match_func (matcher_t::match_func_t match_func_, ++ const void *match_data_, + const USHORT glyph_data[]) + { +- matcher.set_match_func (match_func, match_data); ++ matcher.set_match_func (match_func_, match_data_); + match_glyph_data = glyph_data; + } + +- inline bool has_no_chance (void) const { return unlikely (num_items && idx + num_items >= end); } ++ inline void reset (unsigned int start_index_, ++ unsigned int num_items_) ++ { ++ idx = start_index_; ++ num_items = num_items_; ++ end = c->buffer->len; ++ matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0); ++ } ++ + inline void reject (void) { num_items++; match_glyph_data--; } ++ + inline bool next (void) + { + assert (num_items > 0); +- while (!has_no_chance ()) ++ while (idx + num_items < end) + { + idx++; + const hb_glyph_info_t &info = c->buffer->info[idx]; +@@ -450,53 +401,10 @@ + } + return false; + } +- +- unsigned int idx; +- protected: +- hb_apply_context_t *c; +- matcher_t matcher; +- const USHORT *match_glyph_data; +- +- unsigned int num_items; +- unsigned int end; +- }; +- +- struct skipping_backward_iterator_t +- { +- inline skipping_backward_iterator_t (hb_apply_context_t *c_, +- unsigned int start_index_, +- unsigned int num_items_, +- bool context_match = false) : +- idx (start_index_), +- c (c_), +- match_glyph_data (NULL), +- num_items (num_items_) +- { +- matcher.set_lookup_props (c->lookup_props); +- /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */ +- matcher.set_ignore_zwnj (context_match || c->table_index == 1); +- /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */ +- matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj); +- if (!context_match) +- matcher.set_mask (c->lookup_mask); +- matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0); +- } +- inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); } +- inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); } +- inline void set_match_func (matcher_t::match_func_t match_func, +- const void *match_data, +- const USHORT glyph_data[]) +- { +- matcher.set_match_func (match_func, match_data); +- match_glyph_data = glyph_data; +- } +- +- inline bool has_no_chance (void) const { return unlikely (idx < num_items); } +- inline void reject (void) { num_items++; } + inline bool prev (void) + { + assert (num_items > 0); +- while (!has_no_chance ()) ++ while (idx >= num_items) + { + idx--; + const hb_glyph_info_t &info = c->buffer->out_info[idx]; +@@ -528,44 +436,109 @@ + const USHORT *match_glyph_data; + + unsigned int num_items; ++ unsigned int end; + }; + ++ ++ inline const char *get_name (void) { return "APPLY"; } ++ typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup_index); ++ template <typename T> ++ inline return_t dispatch (const T &obj) { return obj.apply (this); } ++ static return_t default_return_value (void) { return false; } ++ bool stop_sublookup_iteration (return_t r) const { return r; } ++ return_t recurse (unsigned int lookup_index) ++ { ++ if (unlikely (nesting_level_left == 0 || !recurse_func)) ++ return default_return_value (); ++ ++ nesting_level_left--; ++ bool ret = recurse_func (this, lookup_index); ++ nesting_level_left++; ++ return ret; ++ } ++ ++ unsigned int table_index; /* GSUB/GPOS */ ++ hb_font_t *font; ++ hb_face_t *face; ++ hb_buffer_t *buffer; ++ hb_direction_t direction; ++ hb_mask_t lookup_mask; ++ bool auto_zwj; ++ recurse_func_t recurse_func; ++ unsigned int nesting_level_left; ++ unsigned int lookup_props; ++ const GDEF &gdef; ++ bool has_glyph_classes; ++ skipping_iterator_t iter_input, iter_context; ++ unsigned int lookup_index; ++ unsigned int debug_depth; ++ ++ ++ hb_apply_context_t (unsigned int table_index_, ++ hb_font_t *font_, ++ hb_buffer_t *buffer_) : ++ table_index (table_index_), ++ font (font_), face (font->face), buffer (buffer_), ++ direction (buffer_->props.direction), ++ lookup_mask (1), ++ auto_zwj (true), ++ recurse_func (NULL), ++ nesting_level_left (HB_MAX_NESTING_LEVEL), ++ lookup_props (0), ++ gdef (*hb_ot_layout_from_face (face)->gdef), ++ has_glyph_classes (gdef.has_glyph_classes ()), ++ iter_input (), ++ iter_context (), ++ lookup_index ((unsigned int) -1), ++ debug_depth (0) {} ++ ++ inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; } ++ inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; } ++ inline void set_recurse_func (recurse_func_t func) { recurse_func = func; } ++ inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; } ++ inline void set_lookup_props (unsigned int lookup_props_) ++ { ++ lookup_props = lookup_props_; ++ iter_input.init (this, false); ++ iter_context.init (this, true); ++ } ++ + inline bool + match_properties_mark (hb_codepoint_t glyph, + unsigned int glyph_props, +- unsigned int lookup_props) const ++ unsigned int match_props) const + { + /* If using mark filtering sets, the high short of +- * lookup_props has the set index. ++ * match_props has the set index. + */ +- if (lookup_props & LookupFlag::UseMarkFilteringSet) +- return gdef.mark_set_covers (lookup_props >> 16, glyph); ++ if (match_props & LookupFlag::UseMarkFilteringSet) ++ return gdef.mark_set_covers (match_props >> 16, glyph); + +- /* The second byte of lookup_props has the meaning ++ /* The second byte of match_props has the meaning + * "ignore marks of attachment type different than + * the attachment type specified." + */ +- if (lookup_props & LookupFlag::MarkAttachmentType) +- return (lookup_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType); ++ if (match_props & LookupFlag::MarkAttachmentType) ++ return (match_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType); + + return true; + } + + inline bool + check_glyph_property (const hb_glyph_info_t *info, +- unsigned int lookup_props) const ++ unsigned int match_props) const + { + hb_codepoint_t glyph = info->codepoint; + unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info); + + /* Not covered, if, for example, glyph class is ligature and +- * lookup_props includes LookupFlags::IgnoreLigatures ++ * match_props includes LookupFlags::IgnoreLigatures + */ +- if (glyph_props & lookup_props & LookupFlag::IgnoreFlags) ++ if (glyph_props & match_props & LookupFlag::IgnoreFlags) + return false; + + if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) +- return match_properties_mark (glyph, glyph_props, lookup_props); ++ return match_properties_mark (glyph, glyph_props, match_props); + + return true; + } +@@ -731,19 +704,19 @@ + match_func_t match_func, + const void *match_data, + unsigned int *end_offset, +- unsigned int match_positions[MAX_CONTEXT_LENGTH], ++ unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], + bool *p_is_mark_ligature = NULL, + unsigned int *p_total_component_count = NULL) + { + TRACE_APPLY (NULL); + +- if (unlikely (count > MAX_CONTEXT_LENGTH)) TRACE_RETURN (false); ++ if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false); + + hb_buffer_t *buffer = c->buffer; + +- hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, count - 1); ++ hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; ++ skippy_iter.reset (buffer->idx, count - 1); + skippy_iter.set_match_func (match_func, match_data, input); +- if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); + + /* + * This is perhaps the trickiest part of OpenType... Remarks: +@@ -774,7 +747,7 @@ + match_positions[0] = buffer->idx; + for (unsigned int i = 1; i < count; i++) + { +- if (!skippy_iter.next ()) return TRACE_RETURN (false); ++ if (!skippy_iter.next ()) return_trace (false); + + match_positions[i] = skippy_iter.idx; + +@@ -786,13 +759,13 @@ + * all subsequent components should be attached to the same ligature + * component, otherwise we shouldn't ligate them. */ + if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp) +- return TRACE_RETURN (false); ++ return_trace (false); + } else { + /* If first component was NOT attached to a previous ligature component, + * all subsequent components should also NOT be attached to any ligature + * component, unless they are attached to the first component itself! */ + if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id)) +- return TRACE_RETURN (false); ++ return_trace (false); + } + + is_mark_ligature = is_mark_ligature && _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]); +@@ -807,11 +780,11 @@ + if (p_total_component_count) + *p_total_component_count = total_component_count; + +- return TRACE_RETURN (true); ++ return_trace (true); + } +-static inline void ligate_input (hb_apply_context_t *c, ++static inline bool ligate_input (hb_apply_context_t *c, + unsigned int count, /* Including the first glyph */ +- unsigned int match_positions[MAX_CONTEXT_LENGTH], /* Including the first glyph */ ++ unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */ + unsigned int match_length, + hb_codepoint_t lig_glyph, + bool is_mark_ligature, +@@ -863,19 +836,21 @@ + if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) + { + _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER); +- _hb_glyph_info_set_modified_combining_class (&buffer->cur(), 0); + } + } + c->replace_glyph_with_ligature (lig_glyph, klass); + + for (unsigned int i = 1; i < count; i++) + { +- while (buffer->idx < match_positions[i]) ++ while (buffer->idx < match_positions[i] && !buffer->in_error) + { + if (!is_mark_ligature) { ++ unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur()); ++ if (this_comp == 0) ++ this_comp = last_num_components; + unsigned int new_lig_comp = components_so_far - last_num_components + +- MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->cur()), 1u), last_num_components); +- _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp); ++ MIN (this_comp, last_num_components); ++ _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp); + } + buffer->next_glyph (); + } +@@ -892,14 +867,17 @@ + /* Re-adjust components for any marks following. */ + for (unsigned int i = buffer->idx; i < buffer->len; i++) { + if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) { ++ unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]); ++ if (!this_comp) ++ break; + unsigned int new_lig_comp = components_so_far - last_num_components + +- MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->info[i]), 1u), last_num_components); ++ MIN (this_comp, last_num_components); + _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp); + } else + break; + } + } +- TRACE_RETURN (true); ++ return_trace (true); + } + + static inline bool match_backtrack (hb_apply_context_t *c, +@@ -910,15 +888,15 @@ + { + TRACE_APPLY (NULL); + +- hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count, true); ++ hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context; ++ skippy_iter.reset (c->buffer->backtrack_len (), count); + skippy_iter.set_match_func (match_func, match_data, backtrack); +- if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); + + for (unsigned int i = 0; i < count; i++) + if (!skippy_iter.prev ()) +- return TRACE_RETURN (false); ++ return_trace (false); + +- return TRACE_RETURN (true); ++ return_trace (true); + } + + static inline bool match_lookahead (hb_apply_context_t *c, +@@ -930,24 +908,25 @@ + { + TRACE_APPLY (NULL); + +- hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count, true); ++ hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context; ++ skippy_iter.reset (c->buffer->idx + offset - 1, count); + skippy_iter.set_match_func (match_func, match_data, lookahead); +- if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); + + for (unsigned int i = 0; i < count; i++) + if (!skippy_iter.next ()) +- return TRACE_RETURN (false); ++ return_trace (false); + +- return TRACE_RETURN (true); ++ return_trace (true); + } + + + + struct LookupRecord + { +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this)); ++ return_trace (c->check_struct (this)); + } + + USHORT sequenceIndex; /* Index into current glyph +@@ -970,7 +949,7 @@ + + static inline bool apply_lookup (hb_apply_context_t *c, + unsigned int count, /* Including the first glyph */ +- unsigned int match_positions[MAX_CONTEXT_LENGTH], /* Including the first glyph */ ++ unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */ + unsigned int lookupCount, + const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */ + unsigned int match_length) +@@ -998,6 +977,11 @@ + if (idx >= count) + continue; + ++ /* Don't recurse to ourself at same position. ++ * Note that this test is too naive, it doesn't catch longer loops. */ ++ if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index) ++ continue; ++ + buffer->move_to (match_positions[idx]); + + unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len (); +@@ -1015,13 +999,13 @@ + /* end can't go back past the current match position. + * Note: this is only true because we do NOT allow MultipleSubst + * with zero sequence len. */ +- end = MAX ((int) match_positions[idx] + 1, int (end) + delta); ++ end = MAX (MIN((int) match_positions[idx] + 1, (int) new_len), int (end) + delta); + + unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */ + + if (delta > 0) + { +- if (unlikely (delta + count > MAX_CONTEXT_LENGTH)) ++ if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH)) + break; + } + else +@@ -1048,7 +1032,7 @@ + + buffer->move_to (end); + +- return TRACE_RETURN (true); ++ return_trace (true); + } + + +@@ -1120,7 +1104,7 @@ + ContextApplyLookupContext &lookup_context) + { + unsigned int match_length = 0; +- unsigned int match_positions[MAX_CONTEXT_LENGTH]; ++ unsigned int match_positions[HB_MAX_CONTEXT_LENGTH]; + return match_input (c, + inputCount, input, + lookup_context.funcs.match, lookup_context.match_data, +@@ -1157,18 +1141,19 @@ + { + TRACE_WOULD_APPLY (this); + const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0)); +- return TRACE_RETURN (context_would_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context)); ++ return_trace (context_would_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context)); + } + + inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const + { + TRACE_APPLY (this); + const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0)); +- return TRACE_RETURN (context_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context)); ++ return_trace (context_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context)); + } + + public: +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); + return inputCount.sanitize (c) + && lookupCount.sanitize (c) +@@ -1215,9 +1200,9 @@ + for (unsigned int i = 0; i < num_rules; i++) + { + if ((this+rule[i]).would_apply (c, lookup_context)) +- return TRACE_RETURN (true); ++ return_trace (true); + } +- return TRACE_RETURN (false); ++ return_trace (false); + } + + inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const +@@ -1227,14 +1212,15 @@ + for (unsigned int i = 0; i < num_rules; i++) + { + if ((this+rule[i]).apply (c, lookup_context)) +- return TRACE_RETURN (true); ++ return_trace (true); + } +- return TRACE_RETURN (false); ++ return_trace (false); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (rule.sanitize (c, this)); ++ return_trace (rule.sanitize (c, this)); + } + + protected: +@@ -1291,7 +1277,7 @@ + {match_glyph}, + NULL + }; +- return TRACE_RETURN (rule_set.would_apply (c, lookup_context)); ++ return_trace (rule_set.would_apply (c, lookup_context)); + } + + inline const Coverage &get_coverage (void) const +@@ -1304,19 +1290,20 @@ + TRACE_APPLY (this); + unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); + if (likely (index == NOT_COVERED)) +- return TRACE_RETURN (false); ++ return_trace (false); + + const RuleSet &rule_set = this+ruleSet[index]; + struct ContextApplyLookupContext lookup_context = { + {match_glyph}, + NULL + }; +- return TRACE_RETURN (rule_set.apply (c, lookup_context)); ++ return_trace (rule_set.apply (c, lookup_context)); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this)); ++ return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this)); + } + + protected: +@@ -1382,7 +1369,7 @@ + {match_class}, + &class_def + }; +- return TRACE_RETURN (rule_set.would_apply (c, lookup_context)); ++ return_trace (rule_set.would_apply (c, lookup_context)); + } + + inline const Coverage &get_coverage (void) const +@@ -1394,7 +1381,7 @@ + { + TRACE_APPLY (this); + unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); +- if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (index == NOT_COVERED)) return_trace (false); + + const ClassDef &class_def = this+classDef; + index = class_def.get_class (c->buffer->cur().codepoint); +@@ -1403,12 +1390,13 @@ + {match_class}, + &class_def + }; +- return TRACE_RETURN (rule_set.apply (c, lookup_context)); ++ return_trace (rule_set.apply (c, lookup_context)); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this)); ++ return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this)); + } + + protected: +@@ -1472,7 +1460,7 @@ + {match_coverage}, + this + }; +- return TRACE_RETURN (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context)); ++ return_trace (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context)); + } + + inline const Coverage &get_coverage (void) const +@@ -1484,26 +1472,27 @@ + { + TRACE_APPLY (this); + unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint); +- if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (index == NOT_COVERED)) return_trace (false); + + const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount); + struct ContextApplyLookupContext lookup_context = { + {match_coverage}, + this + }; +- return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context)); ++ return_trace (context_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context)); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- if (!c->check_struct (this)) return TRACE_RETURN (false); ++ if (!c->check_struct (this)) return_trace (false); + unsigned int count = glyphCount; +- if (!count) return TRACE_RETURN (false); /* We want to access coverageZ[0] freely. */ +- if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return TRACE_RETURN (false); ++ if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */ ++ if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return_trace (false); + for (unsigned int i = 0; i < count; i++) +- if (!coverageZ[i].sanitize (c, this)) return TRACE_RETURN (false); +- LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count); +- return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount)); ++ if (!coverageZ[i].sanitize (c, this)) return_trace (false); ++ const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count); ++ return_trace (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount)); + } + + protected: +@@ -1526,22 +1515,12 @@ + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this, u.format); ++ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { +- case 1: return TRACE_RETURN (c->dispatch (u.format1)); +- case 2: return TRACE_RETURN (c->dispatch (u.format2)); +- case 3: return TRACE_RETURN (c->dispatch (u.format3)); +- default:return TRACE_RETURN (c->default_return_value ()); +- } +- } +- +- inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- case 2: return TRACE_RETURN (u.format2.sanitize (c)); +- case 3: return TRACE_RETURN (u.format3.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (c->dispatch (u.format1)); ++ case 2: return_trace (c->dispatch (u.format2)); ++ case 3: return_trace (c->dispatch (u.format3)); ++ default:return_trace (c->default_return_value ()); + } + } + +@@ -1652,7 +1631,7 @@ + ChainContextApplyLookupContext &lookup_context) + { + unsigned int match_length = 0; +- unsigned int match_positions[MAX_CONTEXT_LENGTH]; ++ unsigned int match_positions[HB_MAX_CONTEXT_LENGTH]; + return match_input (c, + inputCount, input, + lookup_context.funcs.match, lookup_context.match_data[1], +@@ -1706,11 +1685,11 @@ + const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack); + const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); + const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); +- return TRACE_RETURN (chain_context_would_apply_lookup (c, +- backtrack.len, backtrack.array, +- input.len, input.array, +- lookahead.len, lookahead.array, lookup.len, +- lookup.array, lookup_context)); ++ return_trace (chain_context_would_apply_lookup (c, ++ backtrack.len, backtrack.array, ++ input.len, input.array, ++ lookahead.len, lookahead.array, lookup.len, ++ lookup.array, lookup_context)); + } + + inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const +@@ -1719,22 +1698,23 @@ + const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack); + const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); + const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); +- return TRACE_RETURN (chain_context_apply_lookup (c, +- backtrack.len, backtrack.array, +- input.len, input.array, +- lookahead.len, lookahead.array, lookup.len, +- lookup.array, lookup_context)); ++ return_trace (chain_context_apply_lookup (c, ++ backtrack.len, backtrack.array, ++ input.len, input.array, ++ lookahead.len, lookahead.array, lookup.len, ++ lookup.array, lookup_context)); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- if (!backtrack.sanitize (c)) return TRACE_RETURN (false); +- HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack); +- if (!input.sanitize (c)) return TRACE_RETURN (false); +- ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); +- if (!lookahead.sanitize (c)) return TRACE_RETURN (false); +- ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); +- return TRACE_RETURN (lookup.sanitize (c)); ++ if (!backtrack.sanitize (c)) return_trace (false); ++ const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack); ++ if (!input.sanitize (c)) return_trace (false); ++ const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); ++ if (!lookahead.sanitize (c)) return_trace (false); ++ const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); ++ return_trace (lookup.sanitize (c)); + } + + protected: +@@ -1779,9 +1759,9 @@ + unsigned int num_rules = rule.len; + for (unsigned int i = 0; i < num_rules; i++) + if ((this+rule[i]).would_apply (c, lookup_context)) +- return TRACE_RETURN (true); ++ return_trace (true); + +- return TRACE_RETURN (false); ++ return_trace (false); + } + + inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const +@@ -1790,14 +1770,15 @@ + unsigned int num_rules = rule.len; + for (unsigned int i = 0; i < num_rules; i++) + if ((this+rule[i]).apply (c, lookup_context)) +- return TRACE_RETURN (true); ++ return_trace (true); + +- return TRACE_RETURN (false); ++ return_trace (false); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (rule.sanitize (c, this)); ++ return_trace (rule.sanitize (c, this)); + } + + protected: +@@ -1852,7 +1833,7 @@ + {match_glyph}, + {NULL, NULL, NULL} + }; +- return TRACE_RETURN (rule_set.would_apply (c, lookup_context)); ++ return_trace (rule_set.would_apply (c, lookup_context)); + } + + inline const Coverage &get_coverage (void) const +@@ -1864,19 +1845,20 @@ + { + TRACE_APPLY (this); + unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); +- if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (index == NOT_COVERED)) return_trace (false); + + const ChainRuleSet &rule_set = this+ruleSet[index]; + struct ChainContextApplyLookupContext lookup_context = { + {match_glyph}, + {NULL, NULL, NULL} + }; +- return TRACE_RETURN (rule_set.apply (c, lookup_context)); ++ return_trace (rule_set.apply (c, lookup_context)); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this)); ++ return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this)); + } + + protected: +@@ -1955,7 +1937,7 @@ + &input_class_def, + &lookahead_class_def} + }; +- return TRACE_RETURN (rule_set.would_apply (c, lookup_context)); ++ return_trace (rule_set.would_apply (c, lookup_context)); + } + + inline const Coverage &get_coverage (void) const +@@ -1967,7 +1949,7 @@ + { + TRACE_APPLY (this); + unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); +- if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (index == NOT_COVERED)) return_trace (false); + + const ClassDef &backtrack_class_def = this+backtrackClassDef; + const ClassDef &input_class_def = this+inputClassDef; +@@ -1981,14 +1963,17 @@ + &input_class_def, + &lookahead_class_def} + }; +- return TRACE_RETURN (rule_set.apply (c, lookup_context)); ++ return_trace (rule_set.apply (c, lookup_context)); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (coverage.sanitize (c, this) && backtrackClassDef.sanitize (c, this) && +- inputClassDef.sanitize (c, this) && lookaheadClassDef.sanitize (c, this) && +- ruleSet.sanitize (c, this)); ++ return_trace (coverage.sanitize (c, this) && ++ backtrackClassDef.sanitize (c, this) && ++ inputClassDef.sanitize (c, this) && ++ lookaheadClassDef.sanitize (c, this) && ++ ruleSet.sanitize (c, this)); + } + + protected: +@@ -2071,11 +2056,11 @@ + {match_coverage}, + {this, this, this} + }; +- return TRACE_RETURN (chain_context_would_apply_lookup (c, +- backtrack.len, (const USHORT *) backtrack.array, +- input.len, (const USHORT *) input.array + 1, +- lookahead.len, (const USHORT *) lookahead.array, +- lookup.len, lookup.array, lookup_context)); ++ return_trace (chain_context_would_apply_lookup (c, ++ backtrack.len, (const USHORT *) backtrack.array, ++ input.len, (const USHORT *) input.array + 1, ++ lookahead.len, (const USHORT *) lookahead.array, ++ lookup.len, lookup.array, lookup_context)); + } + + inline const Coverage &get_coverage (void) const +@@ -2090,7 +2075,7 @@ + const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack); + + unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint); +- if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (index == NOT_COVERED)) return_trace (false); + + const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input); + const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); +@@ -2098,23 +2083,24 @@ + {match_coverage}, + {this, this, this} + }; +- return TRACE_RETURN (chain_context_apply_lookup (c, +- backtrack.len, (const USHORT *) backtrack.array, +- input.len, (const USHORT *) input.array + 1, +- lookahead.len, (const USHORT *) lookahead.array, +- lookup.len, lookup.array, lookup_context)); ++ return_trace (chain_context_apply_lookup (c, ++ backtrack.len, (const USHORT *) backtrack.array, ++ input.len, (const USHORT *) input.array + 1, ++ lookahead.len, (const USHORT *) lookahead.array, ++ lookup.len, lookup.array, lookup_context)); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false); +- OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack); +- if (!input.sanitize (c, this)) return TRACE_RETURN (false); +- if (!input.len) return TRACE_RETURN (false); /* To be consistent with Context. */ +- OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input); +- if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false); +- ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); +- return TRACE_RETURN (lookup.sanitize (c)); ++ if (!backtrack.sanitize (c, this)) return_trace (false); ++ const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack); ++ if (!input.sanitize (c, this)) return_trace (false); ++ if (!input.len) return_trace (false); /* To be consistent with Context. */ ++ const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input); ++ if (!lookahead.sanitize (c, this)) return_trace (false); ++ const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); ++ return_trace (lookup.sanitize (c)); + } + + protected: +@@ -2144,22 +2130,12 @@ + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this, u.format); ++ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { +- case 1: return TRACE_RETURN (c->dispatch (u.format1)); +- case 2: return TRACE_RETURN (c->dispatch (u.format2)); +- case 3: return TRACE_RETURN (c->dispatch (u.format3)); +- default:return TRACE_RETURN (c->default_return_value ()); +- } +- } +- +- inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- case 2: return TRACE_RETURN (u.format2.sanitize (c)); +- case 3: return TRACE_RETURN (u.format3.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (c->dispatch (u.format1)); ++ case 2: return_trace (c->dispatch (u.format2)); ++ case 3: return_trace (c->dispatch (u.format3)); ++ default:return_trace (c->default_return_value ()); + } + } + +@@ -2173,14 +2149,32 @@ + }; + + ++template <typename T> + struct ExtensionFormat1 + { + inline unsigned int get_type (void) const { return extensionLookupType; } +- inline unsigned int get_offset (void) const { return extensionOffset; } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ template <typename X> ++ inline const X& get_subtable (void) const ++ { ++ unsigned int offset = extensionOffset; ++ if (unlikely (!offset)) return Null(typename T::LookupSubTable); ++ return StructAtOffset<typename T::LookupSubTable> (this, offset); ++ } ++ ++ template <typename context_t> ++ inline typename context_t::return_t dispatch (context_t *c) const ++ { ++ TRACE_DISPATCH (this, format); ++ if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ()); ++ return_trace (get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ())); ++ } ++ ++ /* This is called from may_dispatch() above with hb_sanitize_context_t. */ ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this)); ++ return_trace (c->check_struct (this) && extensionOffset != 0); + } + + protected: +@@ -2204,49 +2198,30 @@ + default:return 0; + } + } +- inline unsigned int get_offset (void) const +- { +- switch (u.format) { +- case 1: return u.format1.get_offset (); +- default:return 0; +- } +- } +- + template <typename X> + inline const X& get_subtable (void) const + { +- unsigned int offset = get_offset (); +- if (unlikely (!offset)) return Null(typename T::LookupSubTable); +- return StructAtOffset<typename T::LookupSubTable> (this, offset); ++ switch (u.format) { ++ case 1: return u.format1.template get_subtable<typename T::LookupSubTable> (); ++ default:return Null(typename T::LookupSubTable); ++ } + } + + template <typename context_t> + inline typename context_t::return_t dispatch (context_t *c) const + { +- return get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ()); +- } +- +- inline bool sanitize_self (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); ++ TRACE_DISPATCH (this, u.format); ++ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (u.format1.dispatch (c)); ++ default:return_trace (c->default_return_value ()); + } + } + +- inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (this); +- if (!sanitize_self (c)) return TRACE_RETURN (false); +- unsigned int offset = get_offset (); +- if (unlikely (!offset)) return TRACE_RETURN (true); +- return TRACE_RETURN (StructAtOffset<typename T::LookupSubTable> (this, offset).sanitize (c, get_type ())); +- } +- + protected: + union { + USHORT format; /* Format identifier */ +- ExtensionFormat1 format1; ++ ExtensionFormat1<T> format1; + } u; + }; + +@@ -2291,12 +2266,14 @@ + inline const Lookup& get_lookup (unsigned int i) const + { return (this+lookupList)[i]; } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) && +- scriptList.sanitize (c, this) && +- featureList.sanitize (c, this) && +- lookupList.sanitize (c, this)); ++ return_trace (version.sanitize (c) && ++ likely (version.major == 1) && ++ scriptList.sanitize (c, this) && ++ featureList.sanitize (c, this) && ++ lookupList.sanitize (c, this)); + } + + protected: +diff -uN gfx/harfbuzz/src_old/hb-ot-layout-gsub-table.hh gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh +--- gfx/harfbuzz/src_old/hb-ot-layout-gsub-table.hh 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh 2016-06-05 23:49:25.602988064 +0200 +@@ -67,7 +67,7 @@ + inline bool would_apply (hb_would_apply_context_t *c) const + { + TRACE_WOULD_APPLY (this); +- return TRACE_RETURN (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); ++ return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); + } + + inline bool apply (hb_apply_context_t *c) const +@@ -75,14 +75,14 @@ + TRACE_APPLY (this); + hb_codepoint_t glyph_id = c->buffer->cur().codepoint; + unsigned int index = (this+coverage).get_coverage (glyph_id); +- if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (index == NOT_COVERED)) return_trace (false); + + /* According to the Adobe Annotated OpenType Suite, result is always + * limited to 16bit. */ + glyph_id = (glyph_id + deltaGlyphID) & 0xFFFFu; + c->replace_glyph (glyph_id); + +- return TRACE_RETURN (true); ++ return_trace (true); + } + + inline bool serialize (hb_serialize_context_t *c, +@@ -91,15 +91,16 @@ + int delta) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); +- if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend_min (*this))) return_trace (false); ++ if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false); + deltaGlyphID.set (delta); /* TODO(serilaize) overflow? */ +- return TRACE_RETURN (true); ++ return_trace (true); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c)); ++ return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c)); + } + + protected: +@@ -143,7 +144,7 @@ + inline bool would_apply (hb_would_apply_context_t *c) const + { + TRACE_WOULD_APPLY (this); +- return TRACE_RETURN (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); ++ return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); + } + + inline bool apply (hb_apply_context_t *c) const +@@ -151,14 +152,14 @@ + TRACE_APPLY (this); + hb_codepoint_t glyph_id = c->buffer->cur().codepoint; + unsigned int index = (this+coverage).get_coverage (glyph_id); +- if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (index == NOT_COVERED)) return_trace (false); + +- if (unlikely (index >= substitute.len)) return TRACE_RETURN (false); ++ if (unlikely (index >= substitute.len)) return_trace (false); + + glyph_id = substitute[index]; + c->replace_glyph (glyph_id); + +- return TRACE_RETURN (true); ++ return_trace (true); + } + + inline bool serialize (hb_serialize_context_t *c, +@@ -167,15 +168,16 @@ + unsigned int num_glyphs) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); +- if (unlikely (!substitute.serialize (c, substitutes, num_glyphs))) return TRACE_RETURN (false); +- if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false); +- return TRACE_RETURN (true); ++ if (unlikely (!c->extend_min (*this))) return_trace (false); ++ if (unlikely (!substitute.serialize (c, substitutes, num_glyphs))) return_trace (false); ++ if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false); ++ return_trace (true); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (coverage.sanitize (c, this) && substitute.sanitize (c)); ++ return_trace (coverage.sanitize (c, this) && substitute.sanitize (c)); + } + + protected: +@@ -198,7 +200,7 @@ + unsigned int num_glyphs) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend_min (u.format))) return_trace (false); + unsigned int format = 2; + int delta = 0; + if (num_glyphs) { +@@ -213,9 +215,9 @@ + } + u.format.set (format); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, num_glyphs, delta)); +- case 2: return TRACE_RETURN (u.format2.serialize (c, glyphs, substitutes, num_glyphs)); +- default:return TRACE_RETURN (false); ++ case 1: return_trace (u.format1.serialize (c, glyphs, num_glyphs, delta)); ++ case 2: return_trace (u.format2.serialize (c, glyphs, substitutes, num_glyphs)); ++ default:return_trace (false); + } + } + +@@ -223,20 +225,11 @@ + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this, u.format); ++ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { +- case 1: return TRACE_RETURN (c->dispatch (u.format1)); +- case 2: return TRACE_RETURN (c->dispatch (u.format2)); +- default:return TRACE_RETURN (c->default_return_value ()); +- } +- } +- +- inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- case 2: return TRACE_RETURN (u.format2.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (c->dispatch (u.format1)); ++ case 2: return_trace (c->dispatch (u.format2)); ++ default:return_trace (c->default_return_value ()); + } + } + +@@ -280,14 +273,14 @@ + * buffer->move_to() makes assumptions about this too. Perhaps fix + * in the future after figuring out what to do with the clusters. + */ +- if (unlikely (!count)) return TRACE_RETURN (false); ++ if (unlikely (!count)) return_trace (false); + + /* Special-case to make it in-place and not consider this + * as a "multiplied" substitution. */ + if (unlikely (count == 1)) + { + c->replace_glyph (substitute.array[0]); +- return TRACE_RETURN (true); ++ return_trace (true); + } + + unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ? +@@ -299,7 +292,7 @@ + } + c->buffer->skip_glyph (); + +- return TRACE_RETURN (true); ++ return_trace (true); + } + + inline bool serialize (hb_serialize_context_t *c, +@@ -307,14 +300,15 @@ + unsigned int num_glyphs) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); +- if (unlikely (!substitute.serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false); +- return TRACE_RETURN (true); ++ if (unlikely (!c->extend_min (*this))) return_trace (false); ++ if (unlikely (!substitute.serialize (c, glyphs, num_glyphs))) return_trace (false); ++ return_trace (true); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (substitute.sanitize (c)); ++ return_trace (substitute.sanitize (c)); + } + + protected: +@@ -353,7 +347,7 @@ + inline bool would_apply (hb_would_apply_context_t *c) const + { + TRACE_WOULD_APPLY (this); +- return TRACE_RETURN (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); ++ return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); + } + + inline bool apply (hb_apply_context_t *c) const +@@ -361,9 +355,9 @@ + TRACE_APPLY (this); + + unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); +- if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (index == NOT_COVERED)) return_trace (false); + +- return TRACE_RETURN ((this+sequence[index]).apply (c)); ++ return_trace ((this+sequence[index]).apply (c)); + } + + inline bool serialize (hb_serialize_context_t *c, +@@ -373,20 +367,21 @@ + Supplier<GlyphID> &substitute_glyphs_list) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); +- if (unlikely (!sequence.serialize (c, num_glyphs))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend_min (*this))) return_trace (false); ++ if (unlikely (!sequence.serialize (c, num_glyphs))) return_trace (false); + for (unsigned int i = 0; i < num_glyphs; i++) + if (unlikely (!sequence[i].serialize (c, this).serialize (c, + substitute_glyphs_list, +- substitute_len_list[i]))) return TRACE_RETURN (false); ++ substitute_len_list[i]))) return_trace (false); + substitute_len_list.advance (num_glyphs); +- if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false); +- return TRACE_RETURN (true); ++ if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false); ++ return_trace (true); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (coverage.sanitize (c, this) && sequence.sanitize (c, this)); ++ return_trace (coverage.sanitize (c, this) && sequence.sanitize (c, this)); + } + + protected: +@@ -410,12 +405,12 @@ + Supplier<GlyphID> &substitute_glyphs_list) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend_min (u.format))) return_trace (false); + unsigned int format = 1; + u.format.set (format); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, substitute_len_list, num_glyphs, substitute_glyphs_list)); +- default:return TRACE_RETURN (false); ++ case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, num_glyphs, substitute_glyphs_list)); ++ default:return_trace (false); + } + } + +@@ -423,18 +418,10 @@ + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this, u.format); ++ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { +- case 1: return TRACE_RETURN (c->dispatch (u.format1)); +- default:return TRACE_RETURN (c->default_return_value ()); +- } +- } +- +- inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (c->dispatch (u.format1)); ++ default:return_trace (c->default_return_value ()); + } + } + +@@ -486,7 +473,7 @@ + inline bool would_apply (hb_would_apply_context_t *c) const + { + TRACE_WOULD_APPLY (this); +- return TRACE_RETURN (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); ++ return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); + } + + inline bool apply (hb_apply_context_t *c) const +@@ -495,11 +482,11 @@ + hb_codepoint_t glyph_id = c->buffer->cur().codepoint; + + unsigned int index = (this+coverage).get_coverage (glyph_id); +- if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (index == NOT_COVERED)) return_trace (false); + + const AlternateSet &alt_set = this+alternateSet[index]; + +- if (unlikely (!alt_set.len)) return TRACE_RETURN (false); ++ if (unlikely (!alt_set.len)) return_trace (false); + + hb_mask_t glyph_mask = c->buffer->cur().mask; + hb_mask_t lookup_mask = c->lookup_mask; +@@ -508,13 +495,13 @@ + unsigned int shift = _hb_ctz (lookup_mask); + unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift); + +- if (unlikely (alt_index > alt_set.len || alt_index == 0)) return TRACE_RETURN (false); ++ if (unlikely (alt_index > alt_set.len || alt_index == 0)) return_trace (false); + + glyph_id = alt_set[alt_index - 1]; + + c->replace_glyph (glyph_id); + +- return TRACE_RETURN (true); ++ return_trace (true); + } + + inline bool serialize (hb_serialize_context_t *c, +@@ -524,20 +511,21 @@ + Supplier<GlyphID> &alternate_glyphs_list) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); +- if (unlikely (!alternateSet.serialize (c, num_glyphs))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend_min (*this))) return_trace (false); ++ if (unlikely (!alternateSet.serialize (c, num_glyphs))) return_trace (false); + for (unsigned int i = 0; i < num_glyphs; i++) + if (unlikely (!alternateSet[i].serialize (c, this).serialize (c, + alternate_glyphs_list, +- alternate_len_list[i]))) return TRACE_RETURN (false); ++ alternate_len_list[i]))) return_trace (false); + alternate_len_list.advance (num_glyphs); +- if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false); +- return TRACE_RETURN (true); ++ if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false); ++ return_trace (true); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (coverage.sanitize (c, this) && alternateSet.sanitize (c, this)); ++ return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this)); + } + + protected: +@@ -561,12 +549,12 @@ + Supplier<GlyphID> &alternate_glyphs_list) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend_min (u.format))) return_trace (false); + unsigned int format = 1; + u.format.set (format); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, alternate_len_list, num_glyphs, alternate_glyphs_list)); +- default:return TRACE_RETURN (false); ++ case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, num_glyphs, alternate_glyphs_list)); ++ default:return_trace (false); + } + } + +@@ -574,18 +562,10 @@ + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this, u.format); ++ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { +- case 1: return TRACE_RETURN (c->dispatch (u.format1)); +- default:return TRACE_RETURN (c->default_return_value ()); +- } +- } +- +- inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (c->dispatch (u.format1)); ++ default:return_trace (c->default_return_value ()); + } + } + +@@ -622,13 +602,13 @@ + { + TRACE_WOULD_APPLY (this); + if (c->len != component.len) +- return TRACE_RETURN (false); ++ return_trace (false); + + for (unsigned int i = 1; i < c->len; i++) + if (likely (c->glyphs[i] != component[i])) +- return TRACE_RETURN (false); ++ return_trace (false); + +- return TRACE_RETURN (true); ++ return_trace (true); + } + + inline bool apply (hb_apply_context_t *c) const +@@ -636,21 +616,21 @@ + TRACE_APPLY (this); + unsigned int count = component.len; + +- if (unlikely (!count)) return TRACE_RETURN (false); ++ if (unlikely (!count)) return_trace (false); + + /* Special-case to make it in-place and not consider this + * as a "ligated" substitution. */ + if (unlikely (count == 1)) + { + c->replace_glyph (ligGlyph); +- return TRACE_RETURN (true); ++ return_trace (true); + } + + bool is_mark_ligature = false; + unsigned int total_component_count = 0; + + unsigned int match_length = 0; +- unsigned int match_positions[MAX_CONTEXT_LENGTH]; ++ unsigned int match_positions[HB_MAX_CONTEXT_LENGTH]; + + if (likely (!match_input (c, count, + &component[1], +@@ -660,7 +640,7 @@ + match_positions, + &is_mark_ligature, + &total_component_count))) +- return TRACE_RETURN (false); ++ return_trace (false); + + ligate_input (c, + count, +@@ -670,7 +650,7 @@ + is_mark_ligature, + total_component_count); + +- return TRACE_RETURN (true); ++ return_trace (true); + } + + inline bool serialize (hb_serialize_context_t *c, +@@ -679,16 +659,17 @@ + unsigned int num_components /* Including first component */) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend_min (*this))) return_trace (false); + ligGlyph = ligature; +- if (unlikely (!component.serialize (c, components, num_components))) return TRACE_RETURN (false); +- return TRACE_RETURN (true); ++ if (unlikely (!component.serialize (c, components, num_components))) return_trace (false); ++ return_trace (true); + } + + public: +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (ligGlyph.sanitize (c) && component.sanitize (c)); ++ return_trace (ligGlyph.sanitize (c) && component.sanitize (c)); + } + + protected: +@@ -727,9 +708,9 @@ + { + const Ligature &lig = this+ligature[i]; + if (lig.would_apply (c)) +- return TRACE_RETURN (true); ++ return_trace (true); + } +- return TRACE_RETURN (false); ++ return_trace (false); + } + + inline bool apply (hb_apply_context_t *c) const +@@ -739,10 +720,10 @@ + for (unsigned int i = 0; i < num_ligs; i++) + { + const Ligature &lig = this+ligature[i]; +- if (lig.apply (c)) return TRACE_RETURN (true); ++ if (lig.apply (c)) return_trace (true); + } + +- return TRACE_RETURN (false); ++ return_trace (false); + } + + inline bool serialize (hb_serialize_context_t *c, +@@ -752,21 +733,22 @@ + Supplier<GlyphID> &component_list /* Starting from second for each ligature */) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); +- if (unlikely (!ligature.serialize (c, num_ligatures))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend_min (*this))) return_trace (false); ++ if (unlikely (!ligature.serialize (c, num_ligatures))) return_trace (false); + for (unsigned int i = 0; i < num_ligatures; i++) + if (unlikely (!ligature[i].serialize (c, this).serialize (c, + ligatures[i], + component_list, +- component_count_list[i]))) return TRACE_RETURN (false); ++ component_count_list[i]))) return_trace (false); + ligatures.advance (num_ligatures); + component_count_list.advance (num_ligatures); +- return TRACE_RETURN (true); ++ return_trace (true); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (ligature.sanitize (c, this)); ++ return_trace (ligature.sanitize (c, this)); + } + + protected: +@@ -808,10 +790,10 @@ + { + TRACE_WOULD_APPLY (this); + unsigned int index = (this+coverage).get_coverage (c->glyphs[0]); +- if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (index == NOT_COVERED)) return_trace (false); + + const LigatureSet &lig_set = this+ligatureSet[index]; +- return TRACE_RETURN (lig_set.would_apply (c)); ++ return_trace (lig_set.would_apply (c)); + } + + inline bool apply (hb_apply_context_t *c) const +@@ -820,10 +802,10 @@ + hb_codepoint_t glyph_id = c->buffer->cur().codepoint; + + unsigned int index = (this+coverage).get_coverage (glyph_id); +- if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (index == NOT_COVERED)) return_trace (false); + + const LigatureSet &lig_set = this+ligatureSet[index]; +- return TRACE_RETURN (lig_set.apply (c)); ++ return_trace (lig_set.apply (c)); + } + + inline bool serialize (hb_serialize_context_t *c, +@@ -835,22 +817,23 @@ + Supplier<GlyphID> &component_list /* Starting from second for each ligature */) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); +- if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend_min (*this))) return_trace (false); ++ if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return_trace (false); + for (unsigned int i = 0; i < num_first_glyphs; i++) + if (unlikely (!ligatureSet[i].serialize (c, this).serialize (c, + ligatures_list, + component_count_list, + ligature_per_first_glyph_count_list[i], +- component_list))) return TRACE_RETURN (false); ++ component_list))) return_trace (false); + ligature_per_first_glyph_count_list.advance (num_first_glyphs); +- if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_first_glyphs))) return TRACE_RETURN (false); +- return TRACE_RETURN (true); ++ if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_first_glyphs))) return_trace (false); ++ return_trace (true); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this)); ++ return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this)); + } + + protected: +@@ -876,13 +859,18 @@ + Supplier<GlyphID> &component_list /* Starting from second for each ligature */) + { + TRACE_SERIALIZE (this); +- if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); ++ if (unlikely (!c->extend_min (u.format))) return_trace (false); + unsigned int format = 1; + u.format.set (format); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.serialize (c, first_glyphs, ligature_per_first_glyph_count_list, num_first_glyphs, +- ligatures_list, component_count_list, component_list)); +- default:return TRACE_RETURN (false); ++ case 1: return_trace (u.format1.serialize (c, ++ first_glyphs, ++ ligature_per_first_glyph_count_list, ++ num_first_glyphs, ++ ligatures_list, ++ component_count_list, ++ component_list)); ++ default:return_trace (false); + } + } + +@@ -890,18 +878,10 @@ + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this, u.format); ++ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { +- case 1: return TRACE_RETURN (c->dispatch (u.format1)); +- default:return TRACE_RETURN (c->default_return_value ()); +- } +- } +- +- inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (c->dispatch (u.format1)); ++ default:return_trace (c->default_return_value ()); + } + } + +@@ -984,17 +964,17 @@ + inline bool would_apply (hb_would_apply_context_t *c) const + { + TRACE_WOULD_APPLY (this); +- return TRACE_RETURN (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); ++ return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); + } + + inline bool apply (hb_apply_context_t *c) const + { + TRACE_APPLY (this); +- if (unlikely (c->nesting_level_left != MAX_NESTING_LEVEL)) +- return TRACE_RETURN (false); /* No chaining to this type */ ++ if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL)) ++ return_trace (false); /* No chaining to this type */ + + unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); +- if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); ++ if (likely (index == NOT_COVERED)) return_trace (false); + + const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack); + const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead); +@@ -1011,21 +991,22 @@ + /* Note: We DON'T decrease buffer->idx. The main loop does it + * for us. This is useful for preventing surprises if someone + * calls us through a Context lookup. */ +- return TRACE_RETURN (true); ++ return_trace (true); + } + +- return TRACE_RETURN (false); ++ return_trace (false); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); + if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this))) +- return TRACE_RETURN (false); +- OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack); ++ return_trace (false); ++ const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack); + if (!lookahead.sanitize (c, this)) +- return TRACE_RETURN (false); +- ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead); +- return TRACE_RETURN (substitute.sanitize (c)); ++ return_trace (false); ++ const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead); ++ return_trace (substitute.sanitize (c)); + } + + protected: +@@ -1054,18 +1035,10 @@ + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this, u.format); ++ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { +- case 1: return TRACE_RETURN (c->dispatch (u.format1)); +- default:return TRACE_RETURN (c->default_return_value ()); +- } +- } +- +- inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (this); +- if (!u.format.sanitize (c)) return TRACE_RETURN (false); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.sanitize (c)); +- default:return TRACE_RETURN (true); ++ case 1: return_trace (c->dispatch (u.format1)); ++ default:return_trace (c->default_return_value ()); + } + } + +@@ -1101,41 +1074,23 @@ + inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const + { + TRACE_DISPATCH (this, lookup_type); ++ if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace (c->no_dispatch_return_value ()); + switch (lookup_type) { +- case Single: return TRACE_RETURN (u.single.dispatch (c)); +- case Multiple: return TRACE_RETURN (u.multiple.dispatch (c)); +- case Alternate: return TRACE_RETURN (u.alternate.dispatch (c)); +- case Ligature: return TRACE_RETURN (u.ligature.dispatch (c)); +- case Context: return TRACE_RETURN (u.context.dispatch (c)); +- case ChainContext: return TRACE_RETURN (u.chainContext.dispatch (c)); +- case Extension: return TRACE_RETURN (u.extension.dispatch (c)); +- case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle.dispatch (c)); +- default: return TRACE_RETURN (c->default_return_value ()); +- } +- } +- +- inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) { +- TRACE_SANITIZE (this); +- if (!u.header.sub_format.sanitize (c)) +- return TRACE_RETURN (false); +- switch (lookup_type) { +- case Single: return TRACE_RETURN (u.single.sanitize (c)); +- case Multiple: return TRACE_RETURN (u.multiple.sanitize (c)); +- case Alternate: return TRACE_RETURN (u.alternate.sanitize (c)); +- case Ligature: return TRACE_RETURN (u.ligature.sanitize (c)); +- case Context: return TRACE_RETURN (u.context.sanitize (c)); +- case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c)); +- case Extension: return TRACE_RETURN (u.extension.sanitize (c)); +- case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle.sanitize (c)); +- default: return TRACE_RETURN (true); ++ case Single: return_trace (u.single.dispatch (c)); ++ case Multiple: return_trace (u.multiple.dispatch (c)); ++ case Alternate: return_trace (u.alternate.dispatch (c)); ++ case Ligature: return_trace (u.ligature.dispatch (c)); ++ case Context: return_trace (u.context.dispatch (c)); ++ case ChainContext: return_trace (u.chainContext.dispatch (c)); ++ case Extension: return_trace (u.extension.dispatch (c)); ++ case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c)); ++ default: return_trace (c->default_return_value ()); + } + } + + protected: + union { +- struct { +- USHORT sub_format; +- } header; ++ USHORT sub_format; + SingleSubst single; + MultipleSubst multiple; + AlternateSubst alternate; +@@ -1146,14 +1101,14 @@ + ReverseChainSingleSubst reverseChainContextSingle; + } u; + public: +- DEFINE_SIZE_UNION (2, header.sub_format); ++ DEFINE_SIZE_UNION (2, sub_format); + }; + + + struct SubstLookup : Lookup + { + inline const SubstLookupSubTable& get_subtable (unsigned int i) const +- { return this+CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable)[i]; } ++ { return Lookup::get_subtable<SubstLookupSubTable> (i); } + + inline static bool lookup_type_is_reverse (unsigned int lookup_type) + { return lookup_type == SubstLookupSubTable::ReverseChainSingle; } +@@ -1166,56 +1121,47 @@ + return lookup_type_is_reverse (type); + } + ++ inline bool apply (hb_apply_context_t *c) const ++ { ++ TRACE_APPLY (this); ++ return_trace (dispatch (c)); ++ } ++ + inline hb_closure_context_t::return_t closure (hb_closure_context_t *c) const + { + TRACE_CLOSURE (this); + c->set_recurse_func (dispatch_recurse_func<hb_closure_context_t>); +- return TRACE_RETURN (dispatch (c)); ++ return_trace (dispatch (c)); + } + + inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const + { + TRACE_COLLECT_GLYPHS (this); + c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>); +- return TRACE_RETURN (dispatch (c)); ++ return_trace (dispatch (c)); + } + + template <typename set_t> + inline void add_coverage (set_t *glyphs) const + { +- hb_get_coverage_context_t c; +- const Coverage *last = NULL; +- unsigned int count = get_subtable_count (); +- for (unsigned int i = 0; i < count; i++) { +- const Coverage *coverage = &get_subtable (i).dispatch (&c, get_type ()); +- if (coverage != last) { +- coverage->add_coverage (glyphs); +- last = coverage; +- } +- } ++ hb_add_coverage_context_t<set_t> c (glyphs); ++ dispatch (&c); + } + +- inline bool would_apply (hb_would_apply_context_t *c, const hb_set_digest_t *digest) const ++ inline bool would_apply (hb_would_apply_context_t *c, ++ const hb_ot_layout_lookup_accelerator_t *accel) const + { + TRACE_WOULD_APPLY (this); +- if (unlikely (!c->len)) return TRACE_RETURN (false); +- if (!digest->may_have (c->glyphs[0])) return TRACE_RETURN (false); +- return TRACE_RETURN (dispatch (c)); +- } +- +- inline bool apply_once (hb_apply_context_t *c) const +- { +- TRACE_APPLY (this); +- if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props)) +- return TRACE_RETURN (false); +- return TRACE_RETURN (dispatch (c)); ++ if (unlikely (!c->len)) return_trace (false); ++ if (!accel->may_have (c->glyphs[0])) return_trace (false); ++ return_trace (dispatch (c)); + } + + static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index); + + inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c, + unsigned int i) +- { return CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable)[i].serialize (c, this); } ++ { return get_subtables<SubstLookupSubTable> ()[i].serialize (c, this); } + + inline bool serialize_single (hb_serialize_context_t *c, + uint32_t lookup_props, +@@ -1224,8 +1170,8 @@ + unsigned int num_glyphs) + { + TRACE_SERIALIZE (this); +- if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Single, lookup_props, 1))) return TRACE_RETURN (false); +- return TRACE_RETURN (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes, num_glyphs)); ++ if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Single, lookup_props, 1))) return_trace (false); ++ return_trace (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes, num_glyphs)); + } + + inline bool serialize_multiple (hb_serialize_context_t *c, +@@ -1236,9 +1182,12 @@ + Supplier<GlyphID> &substitute_glyphs_list) + { + TRACE_SERIALIZE (this); +- if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Multiple, lookup_props, 1))) return TRACE_RETURN (false); +- return TRACE_RETURN (serialize_subtable (c, 0).u.multiple.serialize (c, glyphs, substitute_len_list, num_glyphs, +- substitute_glyphs_list)); ++ if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Multiple, lookup_props, 1))) return_trace (false); ++ return_trace (serialize_subtable (c, 0).u.multiple.serialize (c, ++ glyphs, ++ substitute_len_list, ++ num_glyphs, ++ substitute_glyphs_list)); + } + + inline bool serialize_alternate (hb_serialize_context_t *c, +@@ -1249,9 +1198,12 @@ + Supplier<GlyphID> &alternate_glyphs_list) + { + TRACE_SERIALIZE (this); +- if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Alternate, lookup_props, 1))) return TRACE_RETURN (false); +- return TRACE_RETURN (serialize_subtable (c, 0).u.alternate.serialize (c, glyphs, alternate_len_list, num_glyphs, +- alternate_glyphs_list)); ++ if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Alternate, lookup_props, 1))) return_trace (false); ++ return_trace (serialize_subtable (c, 0).u.alternate.serialize (c, ++ glyphs, ++ alternate_len_list, ++ num_glyphs, ++ alternate_glyphs_list)); + } + + inline bool serialize_ligature (hb_serialize_context_t *c, +@@ -1264,9 +1216,14 @@ + Supplier<GlyphID> &component_list /* Starting from second for each ligature */) + { + TRACE_SERIALIZE (this); +- if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Ligature, lookup_props, 1))) return TRACE_RETURN (false); +- return TRACE_RETURN (serialize_subtable (c, 0).u.ligature.serialize (c, first_glyphs, ligature_per_first_glyph_count_list, num_first_glyphs, +- ligatures_list, component_count_list, component_list)); ++ if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Ligature, lookup_props, 1))) return_trace (false); ++ return_trace (serialize_subtable (c, 0).u.ligature.serialize (c, ++ first_glyphs, ++ ligature_per_first_glyph_count_list, ++ num_first_glyphs, ++ ligatures_list, ++ component_count_list, ++ component_list)); + } + + template <typename context_t> +@@ -1274,24 +1231,13 @@ + + template <typename context_t> + inline typename context_t::return_t dispatch (context_t *c) const +- { +- unsigned int lookup_type = get_type (); +- TRACE_DISPATCH (this, lookup_type); +- unsigned int count = get_subtable_count (); +- for (unsigned int i = 0; i < count; i++) { +- typename context_t::return_t r = get_subtable (i).dispatch (c, lookup_type); +- if (c->stop_sublookup_iteration (r)) +- return TRACE_RETURN (r); +- } +- return TRACE_RETURN (c->default_return_value ()); +- } ++ { return Lookup::dispatch<SubstLookupSubTable> (c); } + +- inline bool sanitize (hb_sanitize_context_t *c) ++ inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); +- if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false); +- OffsetArrayOf<SubstLookupSubTable> &list = CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable); +- if (unlikely (!list.sanitize (c, this, get_type ()))) return TRACE_RETURN (false); ++ if (unlikely (!Lookup::sanitize (c))) return_trace (false); ++ if (unlikely (!dispatch (c))) return_trace (false); + + if (unlikely (get_type () == SubstLookupSubTable::Extension)) + { +@@ -1302,9 +1248,9 @@ + unsigned int count = get_subtable_count (); + for (unsigned int i = 1; i < count; i++) + if (get_subtable (i).u.extension.get_type () != type) +- return TRACE_RETURN (false); ++ return_trace (false); + } +- return TRACE_RETURN (true); ++ return_trace (true); + } + }; + +@@ -1324,11 +1270,12 @@ + static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer); + static inline void substitute_finish (hb_font_t *font, hb_buffer_t *buffer); + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false); +- OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupList); +- return TRACE_RETURN (list.sanitize (c, this)); ++ if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false); ++ const OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupList); ++ return_trace (list.sanitize (c, this)); + } + public: + DEFINE_SIZE_STATIC (10); +@@ -1362,7 +1309,7 @@ + { + unsigned int type = get_type (); + if (unlikely (type == SubstLookupSubTable::Extension)) +- return CastR<ExtensionSubst> (get_subtable<SubstLookupSubTable>()).is_reverse (); ++ return CastR<ExtensionSubst> (get_subtable<LookupSubTable>()).is_reverse (); + return SubstLookup::lookup_type_is_reverse (type); + } + +@@ -1379,9 +1326,12 @@ + const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); + const SubstLookup &l = gsub.get_lookup (lookup_index); + unsigned int saved_lookup_props = c->lookup_props; +- c->set_lookup (l); +- bool ret = l.apply_once (c); +- c->lookup_props = saved_lookup_props; ++ unsigned int saved_lookup_index = c->lookup_index; ++ c->set_lookup_index (lookup_index); ++ c->set_lookup_props (l.get_props ()); ++ bool ret = l.dispatch (c); ++ c->set_lookup_index (saved_lookup_index); ++ c->set_lookup_props (saved_lookup_props); + return ret; + } + +diff -uN gfx/harfbuzz/src_old/hb-ot-layout.h gfx/harfbuzz/src/hb-ot-layout.h +--- gfx/harfbuzz/src_old/hb-ot-layout.h 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-layout.h 2016-06-05 23:49:32.503951121 +0200 +@@ -48,7 +48,7 @@ + * GDEF + */ + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_has_glyph_classes (hb_face_t *face); + + typedef enum { +@@ -59,11 +59,11 @@ + HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT = 4 + } hb_ot_layout_glyph_class_t; + +-hb_ot_layout_glyph_class_t ++HB_EXTERN hb_ot_layout_glyph_class_t + hb_ot_layout_get_glyph_class (hb_face_t *face, + hb_codepoint_t glyph); + +-void ++HB_EXTERN void + hb_ot_layout_get_glyphs_in_class (hb_face_t *face, + hb_ot_layout_glyph_class_t klass, + hb_set_t *glyphs /* OUT */); +@@ -71,7 +71,7 @@ + + /* Not that useful. Provides list of attach points for a glyph that a + * client may want to cache */ +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_get_attach_points (hb_face_t *face, + hb_codepoint_t glyph, + unsigned int start_offset, +@@ -79,7 +79,7 @@ + unsigned int *point_array /* OUT */); + + /* Ligature caret positions */ +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_get_ligature_carets (hb_font_t *font, + hb_direction_t direction, + hb_codepoint_t glyph, +@@ -96,35 +96,35 @@ + #define HB_OT_LAYOUT_NO_FEATURE_INDEX 0xFFFFu + #define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX 0xFFFFu + +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_table_get_script_tags (hb_face_t *face, + hb_tag_t table_tag, + unsigned int start_offset, + unsigned int *script_count /* IN/OUT */, + hb_tag_t *script_tags /* OUT */); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_table_find_script (hb_face_t *face, + hb_tag_t table_tag, + hb_tag_t script_tag, + unsigned int *script_index); + + /* Like find_script, but takes zero-terminated array of scripts to test */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_table_choose_script (hb_face_t *face, + hb_tag_t table_tag, + const hb_tag_t *script_tags, + unsigned int *script_index, + hb_tag_t *chosen_script); + +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_table_get_feature_tags (hb_face_t *face, + hb_tag_t table_tag, + unsigned int start_offset, + unsigned int *feature_count /* IN/OUT */, + hb_tag_t *feature_tags /* OUT */); + +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_script_get_language_tags (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, +@@ -132,21 +132,21 @@ + unsigned int *language_count /* IN/OUT */, + hb_tag_t *language_tags /* OUT */); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_script_find_language (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, + hb_tag_t language_tag, + unsigned int *language_index); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_language_get_required_feature_index (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, + unsigned int language_index, + unsigned int *feature_index); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_language_get_required_feature (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, +@@ -154,7 +154,7 @@ + unsigned int *feature_index, + hb_tag_t *feature_tag); + +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_language_get_feature_indexes (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, +@@ -163,7 +163,7 @@ + unsigned int *feature_count /* IN/OUT */, + unsigned int *feature_indexes /* OUT */); + +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_language_get_feature_tags (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, +@@ -172,7 +172,7 @@ + unsigned int *feature_count /* IN/OUT */, + hb_tag_t *feature_tags /* OUT */); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_language_find_feature (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, +@@ -180,7 +180,7 @@ + hb_tag_t feature_tag, + unsigned int *feature_index); + +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_feature_get_lookups (hb_face_t *face, + hb_tag_t table_tag, + unsigned int feature_index, +@@ -188,12 +188,12 @@ + unsigned int *lookup_count /* IN/OUT */, + unsigned int *lookup_indexes /* OUT */); + +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_table_get_lookup_count (hb_face_t *face, + hb_tag_t table_tag); + + +-void ++HB_EXTERN void + hb_ot_layout_collect_lookups (hb_face_t *face, + hb_tag_t table_tag, + const hb_tag_t *scripts, +@@ -201,7 +201,7 @@ + const hb_tag_t *features, + hb_set_t *lookup_indexes /* OUT */); + +-void ++HB_EXTERN void + hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, + hb_tag_t table_tag, + unsigned int lookup_index, +@@ -228,7 +228,7 @@ + const hb_ot_layout_glyph_sequence_t *sequence, + void *user_data); + +-void ++HB_EXTERN void + Xhb_ot_layout_lookup_enumerate_sequences (hb_face_t *face, + hb_tag_t table_tag, + unsigned int lookup_index, +@@ -241,17 +241,17 @@ + * GSUB + */ + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_has_substitution (hb_face_t *face); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_lookup_would_substitute (hb_face_t *face, + unsigned int lookup_index, + const hb_codepoint_t *glyphs, + unsigned int glyphs_length, + hb_bool_t zero_context); + +-void ++HB_EXTERN void + hb_ot_layout_lookup_substitute_closure (hb_face_t *face, + unsigned int lookup_index, + hb_set_t *glyphs +@@ -259,7 +259,7 @@ + + #ifdef HB_NOT_IMPLEMENTED + /* Note: You better have GDEF when using this API, or marks won't do much. */ +-hb_bool_t ++HB_EXTERN hb_bool_t + Xhb_ot_layout_lookup_substitute (hb_font_t *font, + unsigned int lookup_index, + const hb_ot_layout_glyph_sequence_t *sequence, +@@ -274,12 +274,12 @@ + * GPOS + */ + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_has_positioning (hb_face_t *face); + + #ifdef HB_NOT_IMPLEMENTED + /* Note: You better have GDEF when using this API, or marks won't do much. */ +-hb_bool_t ++HB_EXTERN hb_bool_t + Xhb_ot_layout_lookup_position (hb_font_t *font, + unsigned int lookup_index, + const hb_ot_layout_glyph_sequence_t *sequence, +@@ -288,7 +288,7 @@ + + /* Optical 'size' feature info. Returns true if found. + * http://www.microsoft.com/typography/otspec/features_pt.htm#size */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_get_size_params (hb_face_t *face, + unsigned int *design_size, /* OUT. May be NULL */ + unsigned int *subfamily_id, /* OUT. May be NULL */ +diff -uN gfx/harfbuzz/src_old/hb-ot-layout-jstf-table.hh gfx/harfbuzz/src/hb-ot-layout-jstf-table.hh +--- gfx/harfbuzz/src_old/hb-ot-layout-jstf-table.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-layout-jstf-table.hh 2016-06-05 23:49:28.544972286 +0200 +@@ -54,19 +54,20 @@ + + struct JstfPriority + { +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && +- shrinkageEnableGSUB.sanitize (c, this) && +- shrinkageDisableGSUB.sanitize (c, this) && +- shrinkageEnableGPOS.sanitize (c, this) && +- shrinkageDisableGPOS.sanitize (c, this) && +- shrinkageJstfMax.sanitize (c, this) && +- extensionEnableGSUB.sanitize (c, this) && +- extensionDisableGSUB.sanitize (c, this) && +- extensionEnableGPOS.sanitize (c, this) && +- extensionDisableGPOS.sanitize (c, this) && +- extensionJstfMax.sanitize (c, this)); ++ return_trace (c->check_struct (this) && ++ shrinkageEnableGSUB.sanitize (c, this) && ++ shrinkageDisableGSUB.sanitize (c, this) && ++ shrinkageEnableGPOS.sanitize (c, this) && ++ shrinkageDisableGPOS.sanitize (c, this) && ++ shrinkageJstfMax.sanitize (c, this) && ++ extensionEnableGSUB.sanitize (c, this) && ++ extensionDisableGSUB.sanitize (c, this) && ++ extensionEnableGPOS.sanitize (c, this) && ++ extensionDisableGPOS.sanitize (c, this) && ++ extensionJstfMax.sanitize (c, this)); + } + + protected: +@@ -123,9 +124,10 @@ + struct JstfLangSys : OffsetListOf<JstfPriority> + { + inline bool sanitize (hb_sanitize_context_t *c, +- const Record<JstfLangSys>::sanitize_closure_t * = NULL) { ++ const Record<JstfLangSys>::sanitize_closure_t * = NULL) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (OffsetListOf<JstfPriority>::sanitize (c)); ++ return_trace (OffsetListOf<JstfPriority>::sanitize (c)); + } + }; + +@@ -163,11 +165,12 @@ + inline const JstfLangSys& get_default_lang_sys (void) const { return this+defaultLangSys; } + + inline bool sanitize (hb_sanitize_context_t *c, +- const Record<JstfScript>::sanitize_closure_t * = NULL) { ++ const Record<JstfScript>::sanitize_closure_t * = NULL) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (extenderGlyphs.sanitize (c, this) && +- defaultLangSys.sanitize (c, this) && +- langSys.sanitize (c, this)); ++ return_trace (extenderGlyphs.sanitize (c, this) && ++ defaultLangSys.sanitize (c, this) && ++ langSys.sanitize (c, this)); + } + + protected: +@@ -206,10 +209,12 @@ + inline bool find_script_index (hb_tag_t tag, unsigned int *index) const + { return scriptList.find_index (tag, index); } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) && +- scriptList.sanitize (c, this)); ++ return_trace (version.sanitize (c) && ++ likely (version.major == 1) && ++ scriptList.sanitize (c, this)); + } + + protected: +diff -uN gfx/harfbuzz/src_old/hb-ot-layout-private.hh gfx/harfbuzz/src/hb-ot-layout-private.hh +--- gfx/harfbuzz/src_old/hb-ot-layout-private.hh 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-layout-private.hh 2016-06-05 23:49:29.952964753 +0200 +@@ -36,11 +36,20 @@ + #include "hb-set-private.hh" + + ++/* Private API corresponding to hb-ot-layout.h: */ ++ ++HB_INTERNAL hb_bool_t ++hb_ot_layout_table_find_feature (hb_face_t *face, ++ hb_tag_t table_tag, ++ hb_tag_t feature_tag, ++ unsigned int *feature_index); ++ ++ + /* + * GDEF + */ + +-typedef enum ++enum hb_ot_layout_glyph_props_flags_t + { + /* The following three match LookupFlags::Ignore* numbers. */ + HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH = 0x02u, +@@ -55,7 +64,8 @@ + HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED | + HB_OT_LAYOUT_GLYPH_PROPS_LIGATED | + HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED +-} hb_ot_layout_glyph_class_mask_t; ++}; ++HB_MARK_AS_FLAG_T (hb_ot_layout_glyph_props_flags_t); + + + /* +@@ -126,11 +136,15 @@ + lookup.add_coverage (&digest); + } + +- template <typename TLookup> +- inline void fini (const TLookup &lookup HB_UNUSED) ++ inline void fini (void) + { + } + ++ inline bool may_have (hb_codepoint_t g) const { ++ return digest.may_have (g); ++ } ++ ++ private: + hb_set_digest_t digest; + }; + +@@ -167,82 +181,182 @@ + */ + + /* buffer var allocations, used during the entire shaping process */ +-#define unicode_props0() var2.u8[0] +-#define unicode_props1() var2.u8[1] ++#define unicode_props() var2.u16[0] + + /* buffer var allocations, used during the GSUB/GPOS processing */ + #define glyph_props() var1.u16[0] /* GDEF glyph properties */ + #define lig_props() var1.u8[2] /* GSUB/GPOS ligature tracking */ + #define syllable() var1.u8[3] /* GSUB/GPOS shaping boundaries */ + ++ ++/* loop over syllables */ ++ ++#define foreach_syllable(buffer, start, end) \ ++ for (unsigned int \ ++ _count = buffer->len, \ ++ start = 0, end = _count ? _next_syllable (buffer, 0) : 0; \ ++ start < _count; \ ++ start = end, end = _next_syllable (buffer, start)) ++ ++static inline unsigned int ++_next_syllable (hb_buffer_t *buffer, unsigned int start) ++{ ++ hb_glyph_info_t *info = buffer->info; ++ unsigned int count = buffer->len; ++ ++ unsigned int syllable = info[start].syllable(); ++ while (++start < count && syllable == info[start].syllable()) ++ ; ++ ++ return start; ++} ++ ++ + /* unicode_props */ + +-enum { +- MASK0_ZWJ = 0x20u, +- MASK0_ZWNJ = 0x40u, +- MASK0_IGNORABLE = 0x80u, +- MASK0_GEN_CAT = 0x1Fu ++/* Design: ++ * unicode_props() is a two-byte number. The low byte includes: ++ * - General_Category: 5 bits. ++ * - A bit each for: ++ * * Is it Default_Ignorable(); we have a modified Default_Ignorable(). ++ * * Is it U+200D ZWJ? ++ * * Is it U+200C ZWNJ? ++ * ++ * The high-byte has different meanings, switched by the Gen-Cat: ++ * - For Mn,Mc,Me: the modified Combining_Class. ++ * - For Ws: index of which space character this is, if space fallback ++ * is needed, ie. we don't set this by default, only if asked to. ++ * ++ * If needed, we can use the ZWJ/ZWNJ to use the high byte as well, ++ * freeing two more bits. ++ */ ++ ++enum hb_unicode_props_flags_t { ++ UPROPS_MASK_ZWJ = 0x20u, ++ UPROPS_MASK_ZWNJ = 0x40u, ++ UPROPS_MASK_IGNORABLE = 0x80u, ++ UPROPS_MASK_GEN_CAT = 0x1Fu + }; ++HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t); + + static inline void +-_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_unicode_funcs_t *unicode) ++_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer) + { +- /* XXX This shouldn't be inlined, or at least not while is_default_ignorable() is inline. */ +- info->unicode_props0() = ((unsigned int) unicode->general_category (info->codepoint)) | +- (unicode->is_default_ignorable (info->codepoint) ? MASK0_IGNORABLE : 0) | +- (info->codepoint == 0x200Cu ? MASK0_ZWNJ : 0) | +- (info->codepoint == 0x200Du ? MASK0_ZWJ : 0); +- info->unicode_props1() = unicode->modified_combining_class (info->codepoint); ++ hb_unicode_funcs_t *unicode = buffer->unicode; ++ unsigned int u = info->codepoint; ++ unsigned int gen_cat = (unsigned int) unicode->general_category (u); ++ unsigned int props = gen_cat; ++ ++ if (u >= 0x80) ++ { ++ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII; ++ if (unlikely (unicode->is_default_ignorable (u))) ++ { ++ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES; ++ props |= UPROPS_MASK_IGNORABLE; ++ if (u == 0x200Cu) props |= UPROPS_MASK_ZWNJ; ++ if (u == 0x200Du) props |= UPROPS_MASK_ZWJ; ++ } ++ else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK (gen_cat))) ++ { ++ /* Only Mn and Mc can have non-zero ccc: ++ * http://www.unicode.org/policies/stability_policy.html#Property_Value ++ * """ ++ * Canonical_Combining_Class, General_Category ++ * All characters other than those with General_Category property values ++ * Spacing_Mark (Mc) and Nonspacing_Mark (Mn) have the Canonical_Combining_Class ++ * property value 0. ++ * 1.1.5+ ++ * """ ++ * ++ * Also, all Mn's that are Default_Ignorable, have ccc=0, hence ++ * the "else if". ++ */ ++ props |= unicode->modified_combining_class (info->codepoint)<<8; ++ } ++ } ++ ++ info->unicode_props() = props; + } + + static inline void + _hb_glyph_info_set_general_category (hb_glyph_info_t *info, + hb_unicode_general_category_t gen_cat) + { +- info->unicode_props0() = (unsigned int) gen_cat | ((info->unicode_props0()) & ~MASK0_GEN_CAT); ++ /* Clears top-byte. */ ++ info->unicode_props() = (unsigned int) gen_cat | (info->unicode_props() & (0xFF & ~UPROPS_MASK_GEN_CAT)); + } + + static inline hb_unicode_general_category_t + _hb_glyph_info_get_general_category (const hb_glyph_info_t *info) + { +- return (hb_unicode_general_category_t) (info->unicode_props0() & MASK0_GEN_CAT); ++ return (hb_unicode_general_category_t) (info->unicode_props() & UPROPS_MASK_GEN_CAT); + } + ++static inline bool ++_hb_glyph_info_is_unicode_mark (const hb_glyph_info_t *info) ++{ ++ return HB_UNICODE_GENERAL_CATEGORY_IS_MARK (info->unicode_props() & UPROPS_MASK_GEN_CAT); ++} + static inline void + _hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info, + unsigned int modified_class) + { +- info->unicode_props1() = modified_class; ++ if (unlikely (!_hb_glyph_info_is_unicode_mark (info))) ++ return; ++ info->unicode_props() = (modified_class<<8) | (info->unicode_props() & 0xFF); + } +- + static inline unsigned int + _hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info) + { +- return info->unicode_props1(); ++ return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0; ++} ++ ++static inline bool ++_hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info) ++{ ++ return _hb_glyph_info_get_general_category (info) == ++ HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR; ++} ++static inline void ++_hb_glyph_info_set_unicode_space_fallback_type (hb_glyph_info_t *info, hb_unicode_funcs_t::space_t s) ++{ ++ if (unlikely (!_hb_glyph_info_is_unicode_space (info))) ++ return; ++ info->unicode_props() = (((unsigned int) s)<<8) | (info->unicode_props() & 0xFF); ++} ++static inline hb_unicode_funcs_t::space_t ++_hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info) ++{ ++ return _hb_glyph_info_is_unicode_space (info) ? ++ (hb_unicode_funcs_t::space_t) (info->unicode_props()>>8) : ++ hb_unicode_funcs_t::NOT_SPACE; + } + ++static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info); ++ + static inline hb_bool_t + _hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info) + { +- return !!(info->unicode_props0() & MASK0_IGNORABLE); ++ return (info->unicode_props() & UPROPS_MASK_IGNORABLE) && !_hb_glyph_info_ligated (info); + } + + static inline hb_bool_t + _hb_glyph_info_is_zwnj (const hb_glyph_info_t *info) + { +- return !!(info->unicode_props0() & MASK0_ZWNJ); ++ return !!(info->unicode_props() & UPROPS_MASK_ZWNJ); + } + + static inline hb_bool_t + _hb_glyph_info_is_zwj (const hb_glyph_info_t *info) + { +- return !!(info->unicode_props0() & MASK0_ZWJ); ++ return !!(info->unicode_props() & UPROPS_MASK_ZWJ); + } + + static inline void + _hb_glyph_info_flip_joiners (hb_glyph_info_t *info) + { +- info->unicode_props0() ^= MASK0_ZWNJ | MASK0_ZWJ; ++ info->unicode_props() ^= UPROPS_MASK_ZWNJ | UPROPS_MASK_ZWJ; + } + + /* lig_props: aka lig_id / lig_comp +@@ -402,28 +516,31 @@ + HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED); + } + ++static inline void ++_hb_glyph_info_clear_substituted (hb_glyph_info_t *info) ++{ ++ info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED); ++} ++ + + /* Allocation / deallocation. */ + + static inline void + _hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer) + { +- HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props0); +- HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props1); ++ HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props); + } + + static inline void + _hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer) + { +- HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props0); +- HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props1); ++ HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props); + } + + static inline void + _hb_buffer_assert_unicode_vars (hb_buffer_t *buffer) + { +- HB_BUFFER_ASSERT_VAR (buffer, unicode_props0); +- HB_BUFFER_ASSERT_VAR (buffer, unicode_props1); ++ HB_BUFFER_ASSERT_VAR (buffer, unicode_props); + } + + static inline void +diff -uN gfx/harfbuzz/src_old/hb-ot-map.cc gfx/harfbuzz/src/hb-ot-map.cc +--- gfx/harfbuzz/src_old/hb-ot-map.cc 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-map.cc 2016-06-05 23:49:34.955938050 +0200 +@@ -89,7 +89,7 @@ + + for (unsigned int table_index = 0; table_index < 2; table_index++) { + hb_tag_t table_tag = table_tags[table_index]; +- found_script[table_index] = hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]); ++ found_script[table_index] = (bool) hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]); + hb_ot_layout_script_find_language (face, table_tag, script_index[table_index], language_tag, &language_index[table_index]); + } + } +@@ -216,6 +216,16 @@ + info->tag, + &feature_index[table_index]); + } ++ if (!found && (info->flags & F_GLOBAL_SEARCH)) ++ { ++ for (unsigned int table_index = 0; table_index < 2; table_index++) ++ { ++ found |= hb_ot_layout_table_find_feature (face, ++ table_tags[table_index], ++ info->tag, ++ &feature_index[table_index]); ++ } ++ } + if (!found && !(info->flags & F_HAS_FALLBACK)) + continue; + +diff -uN gfx/harfbuzz/src_old/hb-ot-map-private.hh gfx/harfbuzz/src/hb-ot-map-private.hh +--- gfx/harfbuzz/src_old/hb-ot-map-private.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-map-private.hh 2016-06-05 23:49:33.714944647 +0200 +@@ -154,27 +154,14 @@ + + enum hb_ot_map_feature_flags_t { + F_NONE = 0x0000u, +- F_GLOBAL = 0x0001u, +- F_HAS_FALLBACK = 0x0002u, +- F_MANUAL_ZWJ = 0x0004u ++ F_GLOBAL = 0x0001u, /* Feature applies to all characters; results in no mask allocated for it. */ ++ F_HAS_FALLBACK = 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */ ++ F_MANUAL_ZWJ = 0x0004u, /* Don't skip over ZWJ when matching. */ ++ F_GLOBAL_SEARCH = 0x0008u /* If feature not found in LangSys, look for it in global feature list and pick one. */ + }; ++HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t); + /* Macro version for where const is desired. */ + #define F_COMBINE(l,r) (hb_ot_map_feature_flags_t ((unsigned int) (l) | (unsigned int) (r))) +-static inline hb_ot_map_feature_flags_t +-operator | (hb_ot_map_feature_flags_t l, hb_ot_map_feature_flags_t r) +-{ return hb_ot_map_feature_flags_t ((unsigned int) l | (unsigned int) r); } +-static inline hb_ot_map_feature_flags_t +-operator & (hb_ot_map_feature_flags_t l, hb_ot_map_feature_flags_t r) +-{ return hb_ot_map_feature_flags_t ((unsigned int) l & (unsigned int) r); } +-static inline hb_ot_map_feature_flags_t +-operator ~ (hb_ot_map_feature_flags_t r) +-{ return hb_ot_map_feature_flags_t (~(unsigned int) r); } +-static inline hb_ot_map_feature_flags_t& +-operator |= (hb_ot_map_feature_flags_t &l, hb_ot_map_feature_flags_t r) +-{ l = l | r; return l; } +-static inline hb_ot_map_feature_flags_t& +-operator &= (hb_ot_map_feature_flags_t& l, hb_ot_map_feature_flags_t r) +-{ l = l & r; return l; } + + + struct hb_ot_map_builder_t +@@ -216,7 +203,8 @@ + unsigned int stage[2]; /* GSUB/GPOS */ + + static int cmp (const feature_info_t *a, const feature_info_t *b) +- { return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : (a->seq < b->seq ? -1 : 1); } ++ { return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : ++ (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0); } + }; + + struct stage_info_t { +diff -uN gfx/harfbuzz/src_old/hb-ot-maxp-table.hh gfx/harfbuzz/src/hb-ot-maxp-table.hh +--- gfx/harfbuzz/src_old/hb-ot-maxp-table.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-maxp-table.hh 2016-06-05 23:49:36.145931692 +0200 +@@ -43,14 +43,17 @@ + { + static const hb_tag_t tableTag = HB_OT_TAG_maxp; + +- inline unsigned int get_num_glyphs (void) const { ++ inline unsigned int get_num_glyphs (void) const ++ { + return numGlyphs; + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && +- likely (version.major == 1 || (version.major == 0 && version.minor == 0x5000u))); ++ return_trace (c->check_struct (this) && ++ likely (version.major == 1 || ++ (version.major == 0 && version.minor == 0x5000u))); + } + + /* We only implement version 0.5 as none of the extra fields in version 1.0 are useful. */ +diff -uN gfx/harfbuzz/src_old/hb-ot-name-table.hh gfx/harfbuzz/src/hb-ot-name-table.hh +--- gfx/harfbuzz/src_old/hb-ot-name-table.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-name-table.hh 2016-06-05 23:49:37.289925602 +0200 +@@ -56,10 +56,11 @@ + return 0; + } + +- inline bool sanitize (hb_sanitize_context_t *c, void *base) { ++ inline bool sanitize (hb_sanitize_context_t *c, const void *base) const ++ { + TRACE_SANITIZE (this); + /* We can check from base all the way up to the end of string... */ +- return TRACE_RETURN (c->check_struct (this) && c->check_range ((char *) base, (unsigned int) length + offset)); ++ return_trace (c->check_struct (this) && c->check_range ((char *) base, (unsigned int) length + offset)); + } + + USHORT platformID; /* Platform ID. */ +@@ -101,21 +102,22 @@ + inline unsigned int get_size (void) const + { return min_size + count * nameRecord[0].min_size; } + +- inline bool sanitize_records (hb_sanitize_context_t *c) { ++ inline bool sanitize_records (hb_sanitize_context_t *c) const { + TRACE_SANITIZE (this); + char *string_pool = (char *) this + stringOffset; + unsigned int _count = count; + for (unsigned int i = 0; i < _count; i++) +- if (!nameRecord[i].sanitize (c, string_pool)) return TRACE_RETURN (false); +- return TRACE_RETURN (true); ++ if (!nameRecord[i].sanitize (c, string_pool)) return_trace (false); ++ return_trace (true); + } + +- inline bool sanitize (hb_sanitize_context_t *c) { ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { + TRACE_SANITIZE (this); +- return TRACE_RETURN (c->check_struct (this) && +- likely (format == 0 || format == 1) && +- c->check_array (nameRecord, nameRecord[0].static_size, count) && +- sanitize_records (c)); ++ return_trace (c->check_struct (this) && ++ likely (format == 0 || format == 1) && ++ c->check_array (nameRecord, nameRecord[0].static_size, count) && ++ sanitize_records (c)); + } + + /* We only implement format 0 for now. */ +diff -uN gfx/harfbuzz/src_old/hb-ot-os2-table.hh gfx/harfbuzz/src/hb-ot-os2-table.hh +--- gfx/harfbuzz/src_old/hb-ot-os2-table.hh 1970-01-01 01:00:00.000000000 +0100 ++++ gfx/harfbuzz/src/hb-ot-os2-table.hh 2016-06-05 23:49:38.776917678 +0200 +@@ -0,0 +1,105 @@ ++/* ++ * Copyright © 2011,2012 Google, Inc. ++ * ++ * This is part of HarfBuzz, a text shaping library. ++ * ++ * Permission is hereby granted, without written agreement and without ++ * license or royalty fees, to use, copy, modify, and distribute this ++ * software and its documentation for any purpose, provided that the ++ * above copyright notice and the following two paragraphs appear in ++ * all copies of this software. ++ * ++ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR ++ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ++ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN ++ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ++ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, ++ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ++ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ++ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO ++ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ++ * ++ * Google Author(s): Behdad Esfahbod ++ */ ++ ++#ifndef HB_OT_OS2_TABLE_HH ++#define HB_OT_OS2_TABLE_HH ++ ++#include "hb-open-type-private.hh" ++ ++ ++namespace OT { ++ ++/* ++ * OS/2 and Windows Metrics ++ * http://www.microsoft.com/typography/otspec/os2.htm ++ */ ++ ++#define HB_OT_TAG_os2 HB_TAG('O','S','/','2') ++ ++struct os2 ++{ ++ static const hb_tag_t tableTag = HB_OT_TAG_os2; ++ ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { ++ TRACE_SANITIZE (this); ++ return_trace (c->check_struct (this)); ++ } ++ ++ public: ++ USHORT version; ++ ++ /* Version 0 */ ++ SHORT xAvgCharWidth; ++ USHORT usWeightClass; ++ USHORT usWidthClass; ++ USHORT fsType; ++ SHORT ySubscriptXSize; ++ SHORT ySubscriptYSize; ++ SHORT ySubscriptXOffset; ++ SHORT ySubscriptYOffset; ++ SHORT ySuperscriptXSize; ++ SHORT ySuperscriptYSize; ++ SHORT ySuperscriptXOffset; ++ SHORT ySuperscriptYOffset; ++ SHORT yStrikeoutSize; ++ SHORT yStrikeoutPosition; ++ SHORT sFamilyClass; ++ BYTE panose[10]; ++ ULONG ulUnicodeRange[4]; ++ Tag achVendID; ++ USHORT fsSelection; ++ USHORT usFirstCharIndex; ++ USHORT usLastCharIndex; ++ SHORT sTypoAscender; ++ SHORT sTypoDescender; ++ SHORT sTypoLineGap; ++ USHORT usWinAscent; ++ USHORT usWinDescent; ++ ++ /* Version 1 */ ++ //ULONG ulCodePageRange1; ++ //ULONG ulCodePageRange2; ++ ++ /* Version 2 */ ++ //SHORT sxHeight; ++ //SHORT sCapHeight; ++ //USHORT usDefaultChar; ++ //USHORT usBreakChar; ++ //USHORT usMaxContext; ++ ++ /* Version 5 */ ++ //USHORT usLowerOpticalPointSize; ++ //USHORT usUpperOpticalPointSize; ++ ++ public: ++ DEFINE_SIZE_STATIC (78); ++}; ++ ++} /* namespace OT */ ++ ++ ++#endif /* HB_OT_OS2_TABLE_HH */ +diff -uN gfx/harfbuzz/src_old/hb-ot-shape.cc gfx/harfbuzz/src/hb-ot-shape.cc +--- gfx/harfbuzz/src_old/hb-ot-shape.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape.cc 2016-06-05 23:50:19.596703497 +0200 +@@ -59,10 +59,6 @@ + HB_TAG('r','c','l','t'), + }; + +-static hb_tag_t vertical_features[] = { +- HB_TAG('v','e','r','t'), +-}; +- + + + static void +@@ -105,10 +101,13 @@ + (horizontal_features[i] == HB_TAG('k','e','r','n') ? + F_HAS_FALLBACK : F_NONE)); + else +- for (unsigned int i = 0; i < ARRAY_LENGTH (vertical_features); i++) +- map->add_feature (vertical_features[i], 1, F_GLOBAL | +- (vertical_features[i] == HB_TAG('v','k','r','n') ? +- F_HAS_FALLBACK : F_NONE)); ++ { ++ /* We really want to find a 'vert' feature if there's any in the font, no ++ * matter which script/langsys it is listed (or not) under. ++ * See various bugs referenced from: ++ * https://github.com/behdad/harfbuzz/issues/63 */ ++ map->add_feature (HB_TAG ('v','e','r','t'), 1, F_GLOBAL | F_GLOBAL_SEARCH); ++ } + + if (planner->shaper->override_features) + planner->shaper->override_features (planner); +@@ -229,7 +228,7 @@ + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 0; i < count; i++) +- _hb_glyph_info_set_unicode_props (&info[i], buffer->unicode); ++ _hb_glyph_info_set_unicode_props (&info[i], buffer); + } + + static void +@@ -246,7 +245,7 @@ + + hb_glyph_info_t dottedcircle = {0}; + dottedcircle.codepoint = 0x25CCu; +- _hb_glyph_info_set_unicode_props (&dottedcircle, buffer->unicode); ++ _hb_glyph_info_set_unicode_props (&dottedcircle, buffer); + + buffer->clear_output (); + +@@ -255,7 +254,7 @@ + info.cluster = buffer->cur().cluster; + info.mask = buffer->cur().mask; + buffer->output_info (info); +- while (buffer->idx < buffer->len) ++ while (buffer->idx < buffer->len && !buffer->in_error) + buffer->next_glyph (); + + buffer->swap_buffers (); +@@ -264,11 +263,23 @@ + static void + hb_form_clusters (hb_buffer_t *buffer) + { ++ if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) || ++ buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) ++ return; ++ ++ /* Loop duplicated in hb_ensure_native_direction(). */ ++ unsigned int base = 0; + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 1; i < count; i++) +- if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i]))) +- buffer->merge_clusters (i - 1, i + 1); ++ { ++ if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))) ++ { ++ buffer->merge_clusters (base, i); ++ base = i; ++ } ++ } ++ buffer->merge_clusters (base, count); + } + + static void +@@ -283,7 +294,28 @@ + if ((HB_DIRECTION_IS_HORIZONTAL (direction) && direction != hb_script_get_horizontal_direction (buffer->props.script)) || + (HB_DIRECTION_IS_VERTICAL (direction) && direction != HB_DIRECTION_TTB)) + { +- hb_buffer_reverse_clusters (buffer); ++ /* Same loop as hb_form_clusters(). ++ * Since form_clusters() merged clusters already, we don't merge. */ ++ unsigned int base = 0; ++ unsigned int count = buffer->len; ++ hb_glyph_info_t *info = buffer->info; ++ for (unsigned int i = 1; i < count; i++) ++ { ++ if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))) ++ { ++ if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) ++ buffer->merge_clusters (base, i); ++ buffer->reverse_range (base, i); ++ ++ base = i; ++ } ++ } ++ if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) ++ buffer->merge_clusters (base, count); ++ buffer->reverse_range (base, count); ++ ++ buffer->reverse (); ++ + buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction); + } + } +@@ -305,7 +337,7 @@ + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 0; i < count; i++) { + hb_codepoint_t codepoint = unicode->mirroring (info[i].codepoint); +- if (likely (codepoint == info[i].codepoint)) ++ if (likely (codepoint == info[i].codepoint || !c->font->has_glyph (codepoint))) + info[i].mask |= rtlm_mask; + else + info[i].codepoint = codepoint; +@@ -315,7 +347,8 @@ + static inline void + hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c) + { +- if (!c->plan->has_frac) ++ if (!(c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) || ++ !c->plan->has_frac) + return; + + hb_buffer_t *buffer = c->buffer; +@@ -380,6 +413,103 @@ + } + } + ++static void ++hb_ot_zero_width_default_ignorables (hb_ot_shape_context_t *c) ++{ ++ hb_buffer_t *buffer = c->buffer; ++ ++ if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) || ++ (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES)) ++ return; ++ ++ unsigned int count = buffer->len; ++ hb_glyph_info_t *info = buffer->info; ++ hb_glyph_position_t *pos = buffer->pos; ++ unsigned int i = 0; ++ for (i = 0; i < count; i++) ++ if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i]))) ++ pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0; ++} ++ ++static void ++hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c) ++{ ++ hb_buffer_t *buffer = c->buffer; ++ ++ if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) || ++ (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES)) ++ return; ++ ++ unsigned int count = buffer->len; ++ hb_glyph_info_t *info = buffer->info; ++ hb_glyph_position_t *pos = buffer->pos; ++ unsigned int i = 0; ++ for (i = 0; i < count; i++) ++ { ++ if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i]))) ++ break; ++ } ++ ++ /* No default-ignorables found; return. */ ++ if (i == count) ++ return; ++ ++ hb_codepoint_t space; ++ if (c->font->get_glyph (' ', 0, &space)) ++ { ++ /* Replace default-ignorables with a zero-advance space glyph. */ ++ for (/*continue*/; i < count; i++) ++ { ++ if (_hb_glyph_info_is_default_ignorable (&info[i])) ++ info[i].codepoint = space; ++ } ++ } ++ else ++ { ++ /* Merge clusters and delete default-ignorables. ++ * NOTE! We can't use out-buffer as we have positioning data. */ ++ unsigned int j = i; ++ for (; i < count; i++) ++ { ++ if (_hb_glyph_info_is_default_ignorable (&info[i])) ++ { ++ /* Merge clusters. ++ * Same logic as buffer->delete_glyph(), but for in-place removal. */ ++ ++ unsigned int cluster = info[i].cluster; ++ if (i + 1 < count && cluster == info[i + 1].cluster) ++ continue; /* Cluster survives; do nothing. */ ++ ++ if (j) ++ { ++ /* Merge cluster backward. */ ++ if (cluster < info[j - 1].cluster) ++ { ++ unsigned int old_cluster = info[j - 1].cluster; ++ for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--) ++ info[k - 1].cluster = cluster; ++ } ++ continue; ++ } ++ ++ if (i + 1 < count) ++ buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */ ++ ++ continue; ++ } ++ ++ if (j != i) ++ { ++ info[j] = info[i]; ++ pos[j] = pos[i]; ++ } ++ j++; ++ } ++ buffer->len = j; ++ } ++} ++ ++ + static inline void + hb_ot_map_glyphs_fast (hb_buffer_t *buffer) + { +@@ -388,6 +518,8 @@ + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 0; i < count; i++) + info[i].codepoint = info[i].glyph_index(); ++ ++ buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS; + } + + static inline void +@@ -397,7 +529,7 @@ + hb_glyph_info_t *info = c->buffer->info; + for (unsigned int i = 0; i < count; i++) + { +- hb_ot_layout_glyph_class_mask_t klass; ++ hb_ot_layout_glyph_props_flags_t klass; + + /* Never mark default-ignorables as marks. + * They won't get in the way of lookups anyway, +@@ -421,9 +553,6 @@ + { + hb_buffer_t *buffer = c->buffer; + +- if (c->plan->shaper->preprocess_text) +- c->plan->shaper->preprocess_text (c->plan, buffer, c->font); +- + hb_ot_shape_initialize_masks (c); + + hb_ot_mirror_chars (c); +@@ -448,7 +577,6 @@ + { + hb_buffer_t *buffer = c->buffer; + +- _hb_buffer_allocate_gsubgpos_vars (buffer); + hb_ot_layout_substitute_start (c->font, buffer); + + if (!hb_ot_layout_has_glyph_classes (c->face)) +@@ -465,6 +593,9 @@ + hb_ot_substitute (hb_ot_shape_context_t *c) + { + hb_ot_substitute_default (c); ++ ++ _hb_buffer_allocate_gsubgpos_vars (c->buffer); ++ + hb_ot_substitute_complex (c); + } + +@@ -487,6 +618,9 @@ + static inline void + zero_mark_widths_by_unicode (hb_buffer_t *buffer, bool adjust_offsets) + { ++ if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII)) ++ return; ++ + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 0; i < count; i++) +@@ -501,6 +635,10 @@ + static inline void + zero_mark_widths_by_gdef (hb_buffer_t *buffer, bool adjust_offsets) + { ++ /* This one is a hack; Technically GDEF can mark ASCII glyphs as marks, but we don't listen. */ ++ if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII)) ++ return; ++ + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 0; i < count; i++) +@@ -519,18 +657,30 @@ + unsigned int count = c->buffer->len; + hb_glyph_info_t *info = c->buffer->info; + hb_glyph_position_t *pos = c->buffer->pos; +- for (unsigned int i = 0; i < count; i++) +- { +- c->font->get_glyph_advance_for_direction (info[i].codepoint, +- direction, +- &pos[i].x_advance, +- &pos[i].y_advance); +- c->font->subtract_glyph_origin_for_direction (info[i].codepoint, +- direction, +- &pos[i].x_offset, +- &pos[i].y_offset); + ++ if (HB_DIRECTION_IS_HORIZONTAL (direction)) ++ { ++ for (unsigned int i = 0; i < count; i++) ++ pos[i].x_advance = c->font->get_glyph_h_advance (info[i].codepoint); ++ /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ ++ if (c->font->has_glyph_h_origin_func ()) ++ for (unsigned int i = 0; i < count; i++) ++ c->font->subtract_glyph_h_origin (info[i].codepoint, ++ &pos[i].x_offset, ++ &pos[i].y_offset); ++ } ++ else ++ { ++ for (unsigned int i = 0; i < count; i++) ++ { ++ pos[i].y_advance = c->font->get_glyph_v_advance (info[i].codepoint); ++ c->font->subtract_glyph_v_origin (info[i].codepoint, ++ &pos[i].x_offset, ++ &pos[i].y_offset); ++ } + } ++ if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK) ++ _hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer); + } + + static inline bool +@@ -538,7 +688,7 @@ + { + bool ret = false; + unsigned int count = c->buffer->len; +- bool has_positioning = hb_ot_layout_has_positioning (c->face); ++ bool has_positioning = (bool) hb_ot_layout_has_positioning (c->face); + /* If the font has no GPOS, AND, no fallback positioning will + * happen, AND, direction is forward, then when zeroing mark + * widths, we shift the mark with it, such that the mark +@@ -575,23 +725,23 @@ + hb_glyph_info_t *info = c->buffer->info; + hb_glyph_position_t *pos = c->buffer->pos; + +- /* Change glyph origin to what GPOS expects, apply GPOS, change it back. */ ++ /* Change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */ + +- for (unsigned int i = 0; i < count; i++) { +- c->font->add_glyph_origin_for_direction (info[i].codepoint, +- HB_DIRECTION_LTR, +- &pos[i].x_offset, +- &pos[i].y_offset); +- } ++ /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ ++ if (c->font->has_glyph_h_origin_func ()) ++ for (unsigned int i = 0; i < count; i++) ++ c->font->add_glyph_h_origin (info[i].codepoint, ++ &pos[i].x_offset, ++ &pos[i].y_offset); + + c->plan->position (c->font, c->buffer); + +- for (unsigned int i = 0; i < count; i++) { +- c->font->subtract_glyph_origin_for_direction (info[i].codepoint, +- HB_DIRECTION_LTR, +- &pos[i].x_offset, +- &pos[i].y_offset); +- } ++ /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ ++ if (c->font->has_glyph_h_origin_func ()) ++ for (unsigned int i = 0; i < count; i++) ++ c->font->subtract_glyph_h_origin (info[i].codepoint, ++ &pos[i].x_offset, ++ &pos[i].y_offset); + + ret = true; + } +@@ -625,6 +775,8 @@ + + hb_bool_t fallback = !hb_ot_position_complex (c); + ++ hb_ot_zero_width_default_ignorables (c); ++ + hb_ot_layout_position_finish (c->font, c->buffer); + + if (fallback && c->plan->shaper->fallback_position) +@@ -642,59 +794,18 @@ + } + + +-/* Post-process */ +- +-static void +-hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c) +-{ +- if (c->buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES) +- return; +- +- hb_codepoint_t space; +- enum { +- SPACE_DONT_KNOW, +- SPACE_AVAILABLE, +- SPACE_UNAVAILABLE +- } space_status = SPACE_DONT_KNOW; +- +- unsigned int count = c->buffer->len; +- hb_glyph_info_t *info = c->buffer->info; +- hb_glyph_position_t *pos = c->buffer->pos; +- unsigned int j = 0; +- for (unsigned int i = 0; i < count; i++) +- { +- if (unlikely (!_hb_glyph_info_ligated (&info[i]) && +- _hb_glyph_info_is_default_ignorable (&info[i]))) +- { +- if (space_status == SPACE_DONT_KNOW) +- space_status = c->font->get_glyph (' ', 0, &space) ? SPACE_AVAILABLE : SPACE_UNAVAILABLE; +- +- if (space_status == SPACE_AVAILABLE) +- { +- info[i].codepoint = space; +- pos[i].x_advance = 0; +- pos[i].y_advance = 0; +- } +- else +- continue; /* Delete it. */ +- } +- if (j != i) +- { +- info[j] = info[i]; +- pos[j] = pos[i]; +- } +- j++; +- } +- c->buffer->len = j; +-} +- +- + /* Pull it all together! */ + + static void + hb_ot_shape_internal (hb_ot_shape_context_t *c) + { + c->buffer->deallocate_var_all (); ++ c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; ++ if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_EXPANSION_FACTOR))) ++ { ++ c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_EXPANSION_FACTOR, ++ (unsigned) HB_BUFFER_MAX_LEN_MIN); ++ } + + /* Save the original direction, we use it later. */ + c->target_direction = c->buffer->props.direction; +@@ -709,15 +820,22 @@ + + hb_ensure_native_direction (c->buffer); + ++ if (c->plan->shaper->preprocess_text) ++ c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font); ++ + hb_ot_substitute (c); + hb_ot_position (c); + + hb_ot_hide_default_ignorables (c); + ++ if (c->plan->shaper->postprocess_glyphs) ++ c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font); ++ + _hb_buffer_deallocate_unicode_vars (c->buffer); + + c->buffer->props.direction = c->target_direction; + ++ c->buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT; + c->buffer->deallocate_var_all (); + } + +@@ -736,6 +854,11 @@ + } + + ++/** ++ * hb_ot_shape_plan_collect_lookups: ++ * ++ * Since: 0.9.7 ++ **/ + void + hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan, + hb_tag_t table_tag, +@@ -766,6 +889,11 @@ + } + + ++/** ++ * hb_ot_shape_glyphs_closure: ++ * ++ * Since: 0.9.2 ++ **/ + void + hb_ot_shape_glyphs_closure (hb_font_t *font, + hb_buffer_t *buffer, +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-arabic.cc gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-arabic.cc 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc 2016-06-05 23:49:45.590881534 +0200 +@@ -24,18 +24,51 @@ + * Google Author(s): Behdad Esfahbod + */ + +-#include "hb-ot-shape-complex-private.hh" ++#include "hb-ot-shape-complex-arabic-private.hh" + #include "hb-ot-shape-private.hh" + + ++#ifndef HB_DEBUG_ARABIC ++#define HB_DEBUG_ARABIC (HB_DEBUG+0) ++#endif ++ ++ + /* buffer var allocations */ + #define arabic_shaping_action() complex_var_u8_0() /* arabic shaping action */ + ++#define HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH HB_BUFFER_SCRATCH_FLAG_COMPLEX0 ++ ++/* See: ++ * https://github.com/behdad/harfbuzz/commit/6e6f82b6f3dde0fc6c3c7d991d9ec6cfff57823d#commitcomment-14248516 */ ++#define HB_ARABIC_GENERAL_CATEGORY_IS_WORD(gen_cat) \ ++ (FLAG_SAFE (gen_cat) & \ ++ (FLAG (HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED) | \ ++ FLAG (HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE) | \ ++ /*FLAG (HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER) |*/ \ ++ FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER) | \ ++ FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER) | \ ++ /*FLAG (HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER) |*/ \ ++ /*FLAG (HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER) |*/ \ ++ FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \ ++ FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \ ++ FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | \ ++ FLAG (HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) | \ ++ FLAG (HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER) | \ ++ FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER) | \ ++ FLAG (HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL) | \ ++ FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL) | \ ++ FLAG (HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL) | \ ++ FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL))) ++ ++ ++/* ++ * Joining types: ++ */ + + /* + * Bits used in the joining tables + */ +-enum { ++enum hb_arabic_joining_type_t { + JOINING_TYPE_U = 0, + JOINING_TYPE_L = 1, + JOINING_TYPE_R = 2, +@@ -49,10 +82,6 @@ + JOINING_TYPE_X = 8 /* means: use general-category to choose between U or T. */ + }; + +-/* +- * Joining types: +- */ +- + #include "hb-ot-shape-complex-arabic-table.hh" + + static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_category_t gen_cat) +@@ -61,7 +90,7 @@ + if (likely (j_type != JOINING_TYPE_X)) + return j_type; + +- return (FLAG(gen_cat) & ++ return (FLAG_SAFE(gen_cat) & + (FLAG(HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | + FLAG(HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | + FLAG(HB_UNICODE_GENERAL_CATEGORY_FORMAT)) +@@ -84,7 +113,7 @@ + + + /* Same order as the feature array */ +-enum { ++enum arabic_action_t { + ISOL, + FINA, + FIN2, +@@ -95,7 +124,11 @@ + + NONE, + +- ARABIC_NUM_FEATURES = NONE ++ ARABIC_NUM_FEATURES = NONE, ++ ++ /* We abuse the same byte for other things... */ ++ STCH_FIXED, ++ STCH_REPEATING, + }; + + static const struct arabic_state_table_entry { +@@ -140,6 +173,11 @@ + hb_buffer_t *buffer); + + static void ++record_stch (const hb_ot_shape_plan_t *plan, ++ hb_font_t *font, ++ hb_buffer_t *buffer); ++ ++static void + collect_features_arabic (hb_ot_shape_planner_t *plan) + { + hb_ot_map_builder_t *map = &plan->map; +@@ -165,6 +203,9 @@ + + map->add_gsub_pause (nuke_joiners); + ++ map->add_global_bool_feature (HB_TAG('s','t','c','h')); ++ map->add_gsub_pause (record_stch); ++ + map->add_global_bool_feature (HB_TAG('c','c','m','p')); + map->add_global_bool_feature (HB_TAG('l','o','c','l')); + +@@ -182,7 +223,6 @@ + map->add_gsub_pause (arabic_fallback_shape); + + map->add_global_bool_feature (HB_TAG('c','a','l','t')); +- map->add_gsub_pause (NULL); + + /* The spec includes 'cswh'. Earlier versions of Windows + * used to enable this by default, but testing suggests +@@ -192,6 +232,7 @@ + * Note that IranNastaliq uses this feature extensively + * to fixup broken glyph sequences. Oh well... + * Test case: U+0643,U+0640,U+0631. */ ++ //map->add_gsub_pause (NULL); + //map->add_global_bool_feature (HB_TAG('c','s','w','h')); + map->add_global_bool_feature (HB_TAG('m','s','e','t')); + } +@@ -208,11 +249,13 @@ + * mask_array[NONE] == 0. */ + hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1]; + +- bool do_fallback; + arabic_fallback_plan_t *fallback_plan; ++ ++ unsigned int do_fallback : 1; ++ unsigned int has_stch : 1; + }; + +-static void * ++void * + data_create_arabic (const hb_ot_shape_plan_t *plan) + { + arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) calloc (1, sizeof (arabic_shape_plan_t)); +@@ -220,6 +263,7 @@ + return NULL; + + arabic_plan->do_fallback = plan->props.script == HB_SCRIPT_ARABIC; ++ arabic_plan->has_stch = !!plan->map.get_1_mask (HB_TAG ('s','t','c','h')); + for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) { + arabic_plan->mask_array[i] = plan->map.get_1_mask (arabic_features[i]); + arabic_plan->do_fallback = arabic_plan->do_fallback && +@@ -230,7 +274,7 @@ + return arabic_plan; + } + +-static void ++void + data_destroy_arabic (void *data) + { + arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) data; +@@ -305,25 +349,30 @@ + info[i].arabic_shaping_action() = info[i - 1].arabic_shaping_action(); + } + +-static void +-setup_masks_arabic (const hb_ot_shape_plan_t *plan, +- hb_buffer_t *buffer, +- hb_font_t *font HB_UNUSED) ++void ++setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan, ++ hb_buffer_t *buffer, ++ hb_script_t script) + { + HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action); + +- const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data; +- + arabic_joining (buffer); +- if (plan->props.script == HB_SCRIPT_MONGOLIAN) ++ if (script == HB_SCRIPT_MONGOLIAN) + mongolian_variation_selectors (buffer); + + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 0; i < count; i++) + info[i].mask |= arabic_plan->mask_array[info[i].arabic_shaping_action()]; ++} + +- HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action); ++static void ++setup_masks_arabic (const hb_ot_shape_plan_t *plan, ++ hb_buffer_t *buffer, ++ hb_font_t *font HB_UNUSED) ++{ ++ const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data; ++ setup_masks_arabic_plan (arabic_plan, buffer, plan->props.script); + } + + +@@ -364,6 +413,197 @@ + arabic_fallback_plan_shape (fallback_plan, font, buffer); + } + ++/* ++ * Stretch feature: "stch". ++ * See example here: ++ * https://www.microsoft.com/typography/OpenTypeDev/syriac/intro.htm ++ * We implement this in a generic way, such that the Arabic subtending ++ * marks can use it as well. ++ */ ++ ++static void ++record_stch (const hb_ot_shape_plan_t *plan, ++ hb_font_t *font, ++ hb_buffer_t *buffer) ++{ ++ const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data; ++ if (!arabic_plan->has_stch) ++ return; ++ ++ /* 'stch' feature was just applied. Look for anything that multiplied, ++ * and record it for stch treatment later. Note that rtlm, frac, etc ++ * are applied before stch, but we assume that they didn't result in ++ * anything multiplying into 5 pieces, so it's safe-ish... */ ++ ++ unsigned int count = buffer->len; ++ hb_glyph_info_t *info = buffer->info; ++ for (unsigned int i = 0; i < count; i++) ++ if (unlikely (_hb_glyph_info_multiplied (&info[i]))) ++ { ++ unsigned int comp = _hb_glyph_info_get_lig_comp (&info[i]); ++ info[i].arabic_shaping_action() = comp % 2 ? STCH_REPEATING : STCH_FIXED; ++ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH; ++ } ++} ++ ++static void ++apply_stch (const hb_ot_shape_plan_t *plan, ++ hb_buffer_t *buffer, ++ hb_font_t *font) ++{ ++ if (likely (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH))) ++ return; ++ ++ /* The Arabic shaper currently always processes in RTL mode, so we should ++ * stretch / position the stretched pieces to the left / preceding glyphs. */ ++ ++ /* We do a two pass implementation: ++ * First pass calculates the exact number of extra glyphs we need, ++ * We then enlarge buffer to have that much room, ++ * Second pass applies the stretch, copying things to the end of buffer. ++ */ ++ ++ int sign = font->x_scale < 0 ? -1 : +1; ++ unsigned int extra_glyphs_needed = 0; // Set during MEASURE, used during CUT ++ typedef enum { MEASURE, CUT } step_t; ++ ++ for (step_t step = MEASURE; step <= CUT; step = (step_t) (step + 1)) ++ { ++ unsigned int count = buffer->len; ++ hb_glyph_info_t *info = buffer->info; ++ hb_glyph_position_t *pos = buffer->pos; ++ unsigned int new_len = count + extra_glyphs_needed; // write head during CUT ++ unsigned int j = new_len; ++ for (unsigned int i = count; i; i--) ++ { ++ if (!hb_in_range<unsigned> (info[i - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING)) ++ { ++ if (step == CUT) ++ { ++ --j; ++ info[j] = info[i - 1]; ++ pos[j] = pos[i - 1]; ++ } ++ continue; ++ } ++ ++ /* Yay, justification! */ ++ ++ hb_position_t w_total = 0; // Total to be filled ++ hb_position_t w_fixed = 0; // Sum of fixed tiles ++ hb_position_t w_repeating = 0; // Sum of repeating tiles ++ int n_fixed = 0; ++ int n_repeating = 0; ++ ++ unsigned int end = i; ++ while (i && ++ hb_in_range<unsigned> (info[i - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING)) ++ { ++ i--; ++ hb_position_t width = font->get_glyph_h_advance (info[i].codepoint); ++ if (info[i].arabic_shaping_action() == STCH_FIXED) ++ { ++ w_fixed += width; ++ n_fixed++; ++ } ++ else ++ { ++ w_repeating += width; ++ n_repeating++; ++ } ++ } ++ unsigned int start = i; ++ unsigned int context = i; ++ while (context && ++ !hb_in_range<unsigned> (info[context - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING) && ++ (_hb_glyph_info_is_default_ignorable (&info[context - 1]) || ++ HB_ARABIC_GENERAL_CATEGORY_IS_WORD (_hb_glyph_info_get_general_category (&info[context - 1])))) ++ { ++ context--; ++ w_total += pos[context].x_advance; ++ } ++ i++; // Don't touch i again. ++ ++ DEBUG_MSG (ARABIC, NULL, "%s stretch at (%d,%d,%d)", ++ step == MEASURE ? "measuring" : "cutting", context, start, end); ++ DEBUG_MSG (ARABIC, NULL, "rest of word: count=%d width %d", start - context, w_total); ++ DEBUG_MSG (ARABIC, NULL, "fixed tiles: count=%d width=%d", n_fixed, w_fixed); ++ DEBUG_MSG (ARABIC, NULL, "repeating tiles: count=%d width=%d", n_repeating, w_repeating); ++ ++ /* Number of additional times to repeat each repeating tile. */ ++ int n_copies = 0; ++ ++ hb_position_t w_remaining = w_total - w_fixed; ++ if (sign * w_remaining > sign * w_repeating && sign * w_repeating > 0) ++ n_copies = (sign * w_remaining) / (sign * w_repeating) - 1; ++ ++ /* See if we can improve the fit by adding an extra repeat and squeezing them together a bit. */ ++ hb_position_t extra_repeat_overlap = 0; ++ hb_position_t shortfall = sign * w_remaining - sign * w_repeating * (n_copies + 1); ++ if (shortfall > 0) ++ { ++ ++n_copies; ++ hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining; ++ if (excess > 0) ++ extra_repeat_overlap = excess / (n_copies * n_repeating); ++ } ++ ++ if (step == MEASURE) ++ { ++ extra_glyphs_needed += n_copies * n_repeating; ++ DEBUG_MSG (ARABIC, NULL, "will add extra %d copies of repeating tiles", n_copies); ++ } ++ else ++ { ++ hb_position_t x_offset = 0; ++ for (unsigned int k = end; k > start; k--) ++ { ++ hb_position_t width = font->get_glyph_h_advance (info[k - 1].codepoint); ++ ++ unsigned int repeat = 1; ++ if (info[k - 1].arabic_shaping_action() == STCH_REPEATING) ++ repeat += n_copies; ++ ++ DEBUG_MSG (ARABIC, NULL, "appending %d copies of glyph %d; j=%d", ++ repeat, info[k - 1].codepoint, j); ++ for (unsigned int n = 0; n < repeat; n++) ++ { ++ x_offset -= width; ++ if (n > 0) ++ x_offset += extra_repeat_overlap; ++ pos[k - 1].x_offset = x_offset; ++ /* Append copy. */ ++ --j; ++ info[j] = info[k - 1]; ++ pos[j] = pos[k - 1]; ++ } ++ } ++ } ++ } ++ ++ if (step == MEASURE) ++ { ++ if (unlikely (!buffer->ensure (count + extra_glyphs_needed))) ++ break; ++ } ++ else ++ { ++ assert (j == 0); ++ buffer->len = new_len; ++ } ++ } ++} ++ ++ ++static void ++postprocess_glyphs_arabic (const hb_ot_shape_plan_t *plan, ++ hb_buffer_t *buffer, ++ hb_font_t *font) ++{ ++ apply_stch (plan, buffer, font); ++ ++ HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action); ++} + + const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic = + { +@@ -372,7 +612,8 @@ + NULL, /* override_features */ + data_create_arabic, + data_destroy_arabic, +- NULL, /* preprocess_text_arabic */ ++ NULL, /* preprocess_text */ ++ postprocess_glyphs_arabic, + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, + NULL, /* decompose */ + NULL, /* compose */ +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-arabic-fallback.hh gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-arabic-fallback.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh 2016-06-05 23:49:40.225909984 +0200 +@@ -75,9 +75,9 @@ + if (!num_glyphs) + return NULL; + +- /* Bubble-sort! ++ /* Bubble-sort or something equally good! + * May not be good-enough for presidential candidate interviews, but good-enough for us... */ +- hb_bubble_sort (&glyphs[0], num_glyphs, OT::GlyphID::cmp, &substitutes[0]); ++ hb_stable_sort (&glyphs[0], num_glyphs, OT::GlyphID::cmp, &substitutes[0]); + + OT::Supplier<OT::GlyphID> glyphs_supplier (glyphs, num_glyphs); + OT::Supplier<OT::GlyphID> substitutes_supplier (substitutes, num_glyphs); +@@ -126,7 +126,7 @@ + first_glyphs_indirection[num_first_glyphs] = first_glyph_idx; + num_first_glyphs++; + } +- hb_bubble_sort (&first_glyphs[0], num_first_glyphs, OT::GlyphID::cmp, &first_glyphs_indirection[0]); ++ hb_stable_sort (&first_glyphs[0], num_first_glyphs, OT::GlyphID::cmp, &first_glyphs_indirection[0]); + + /* Now that the first-glyphs are sorted, walk again, populate ligatures. */ + for (unsigned int i = 0; i < num_first_glyphs; i++) +@@ -327,7 +327,7 @@ + for (unsigned int i = 0; i < fallback_plan->num_lookups; i++) + if (fallback_plan->lookup_array[i]) + { +- fallback_plan->accel_array[i].fini (fallback_plan->lookup_array[i]); ++ fallback_plan->accel_array[i].fini (); + if (fallback_plan->free_lookups) + free (fallback_plan->lookup_array[i]); + } +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-arabic-private.hh gfx/harfbuzz/src/hb-ot-shape-complex-arabic-private.hh +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-arabic-private.hh 1970-01-01 01:00:00.000000000 +0100 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-arabic-private.hh 2016-06-05 23:49:41.475903336 +0200 +@@ -0,0 +1,50 @@ ++/* ++ * Copyright © 2015 Mozilla Foundation. ++ * Copyright © 2015 Google, Inc. ++ * ++ * This is part of HarfBuzz, a text shaping library. ++ * ++ * Permission is hereby granted, without written agreement and without ++ * license or royalty fees, to use, copy, modify, and distribute this ++ * software and its documentation for any purpose, provided that the ++ * above copyright notice and the following two paragraphs appear in ++ * all copies of this software. ++ * ++ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR ++ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ++ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN ++ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ++ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, ++ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ++ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ++ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO ++ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ++ * ++ * Mozilla Author(s): Jonathan Kew ++ * Google Author(s): Behdad Esfahbod ++ */ ++ ++#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH ++#define HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH ++ ++#include "hb-private.hh" ++ ++#include "hb-ot-shape-complex-private.hh" ++ ++ ++struct arabic_shape_plan_t; ++ ++HB_INTERNAL void * ++data_create_arabic (const hb_ot_shape_plan_t *plan); ++ ++HB_INTERNAL void ++data_destroy_arabic (void *data); ++ ++HB_INTERNAL void ++setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan, ++ hb_buffer_t *buffer, ++ hb_script_t script); ++ ++#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH */ +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-arabic-table.hh gfx/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-arabic-table.hh 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh 2016-06-05 23:49:42.902895782 +0200 +@@ -6,10 +6,10 @@ + * + * on files with these headers: + * +- * # ArabicShaping-7.0.0.txt +- * # Date: 2014-02-14, 21:00:00 GMT [RP, KW, LI] +- * # Blocks-7.0.0.txt +- * # Date: 2014-04-03, 23:23:00 GMT [RP, KW] ++ * # ArabicShaping-8.0.0.txt ++ * # Date: 2015-02-17, 23:33:00 GMT [RP] ++ * # Blocks-8.0.0.txt ++ * # Date: 2014-11-10, 23:04:00 GMT [KW] + * UnicodeData.txt does not have a header. + */ + +@@ -76,9 +76,9 @@ + + /* Arabic Extended-A */ + +- /* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R, ++ /* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,D,D, + +-#define joining_offset_0x1806u 691 ++#define joining_offset_0x1806u 693 + + /* Mongolian */ + +@@ -89,40 +89,40 @@ + /* 1880 */ U,U,U,U,U,U,U,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D, + /* 18A0 */ D,D,D,D,D,D,D,D,D,X,D, + +-#define joining_offset_0x200cu 856 ++#define joining_offset_0x200cu 858 + + /* General Punctuation */ + + /* 2000 */ U,C, + +-#define joining_offset_0x2066u 858 ++#define joining_offset_0x2066u 860 + + /* General Punctuation */ + + /* 2060 */ U,U,U,U, + +-#define joining_offset_0xa840u 862 ++#define joining_offset_0xa840u 864 + + /* Phags-pa */ + + /* A840 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D, + /* A860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,L,U, + +-#define joining_offset_0x10ac0u 914 ++#define joining_offset_0x10ac0u 916 + + /* Manichaean */ + + /* 10AC0 */ D,D,D,D,D,R,U,R,U,R,R,U,U,L,R,R,R,R,R,D,D,D,D,L,D,D,D,D,D,R,D,D, + /* 10AE0 */ D,R,U,U,R,X,X,X,X,X,X,D,D,D,D,R, + +-#define joining_offset_0x10b80u 962 ++#define joining_offset_0x10b80u 964 + + /* Psalter Pahlavi */ + + /* 10B80 */ D,R,D,R,R,R,D,D,D,R,D,D,R,D,R,R,D,R,X,X,X,X,X,X,X,X,X,X,X,X,X,X, + /* 10BA0 */ X,X,X,X,X,X,X,X,X,R,R,R,R,D,D,U, + +-}; /* Table items: 1010; occupancy: 57% */ ++}; /* Table items: 1012; occupancy: 57% */ + + + static unsigned int +@@ -131,7 +131,7 @@ + switch (u >> 12) + { + case 0x0u: +- if (hb_in_range (u, 0x0600u, 0x08B2u)) return joining_table[u - 0x0600u + joining_offset_0x0600u]; ++ if (hb_in_range (u, 0x0600u, 0x08B4u)) return joining_table[u - 0x0600u + joining_offset_0x0600u]; + break; + + case 0x1u: +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-arabic-win1256.hh gfx/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-arabic-win1256.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh 2016-06-05 23:49:44.102889415 +0200 +@@ -133,7 +133,6 @@ + */ + + #define OT_LOOKUP_TYPE_SUBST_SINGLE 1u +-#define OT_LOOKUP_TYPE_SUBST_MULTIPLE 2u + #define OT_LOOKUP_TYPE_SUBST_LIGATURE 4u + + #define OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(Name, FromGlyphs, ToGlyphs) \ +@@ -143,7 +142,7 @@ + OT_UARRAY(Name##Substitute, OT_LIST(ToGlyphs)) \ + ) \ + OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \ +- /* ASSERT_STATIC_EXPR len(FromGlyphs) == len(ToGlyphs) */ ++ /* ASSERT_STATIC_EXPR_ZERO (len(FromGlyphs) == len(ToGlyphs)) */ + + #define OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(Name, FirstGlyphs, LigatureSetOffsets) \ + OT_SUBLOOKUP(Name, 1, \ +@@ -152,7 +151,7 @@ + OT_UARRAY(Name##LigatureSetOffsetsArray, OT_LIST(LigatureSetOffsets)) \ + ) \ + OT_COVERAGE1(Name##Coverage, OT_LIST(FirstGlyphs)) \ +- /* ASSERT_STATIC_EXPR len(FirstGlyphs) == len(LigatureSetOffsets) */ ++ /* ASSERT_STATIC_EXPR_ZERO (len(FirstGlyphs) == len(LigatureSetOffsets)) */ + + #define OT_LIGATURE_SET(Name, LigatureSetOffsets) \ + OT_UARRAY(Name, OT_LIST(LigatureSetOffsets)) +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-default.cc gfx/harfbuzz/src/hb-ot-shape-complex-default.cc +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-default.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-default.cc 2016-06-05 23:49:46.803875109 +0200 +@@ -35,10 +35,11 @@ + NULL, /* data_create */ + NULL, /* data_destroy */ + NULL, /* preprocess_text */ ++ NULL, /* postprocess_glyphs */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, + NULL, /* decompose */ + NULL, /* compose */ + NULL, /* setup_masks */ +- HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, ++ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE, + true, /* fallback_position */ + }; +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-hangul.cc gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-hangul.cc 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc 2016-06-05 23:49:47.978868903 +0200 +@@ -188,7 +188,7 @@ + */ + unsigned int count = buffer->len; + +- for (buffer->idx = 0; buffer->idx < count;) ++ for (buffer->idx = 0; buffer->idx < count && !buffer->in_error;) + { + hb_codepoint_t u = buffer->cur().codepoint; + +@@ -205,17 +205,12 @@ + buffer->next_glyph (); + if (!is_zero_width_char (font, u)) + { ++ buffer->merge_out_clusters (start, end + 1); + hb_glyph_info_t *info = buffer->out_info; + hb_glyph_info_t tone = info[end]; + memmove (&info[start + 1], &info[start], (end - start) * sizeof (hb_glyph_info_t)); + info[start] = tone; + } +- /* Merge clusters across the (possibly reordered) syllable+tone. +- * We want to merge even in the zero-width tone mark case here, +- * so that clustering behavior isn't dependent on how the tone mark +- * is handled by the font. +- */ +- buffer->merge_out_clusters (start, end + 1); + } + else + { +@@ -296,7 +291,8 @@ + } + else + end = start + 2; +- buffer->merge_out_clusters (start, end); ++ if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) ++ buffer->merge_out_clusters (start, end); + continue; + } + } +@@ -368,7 +364,8 @@ + info[i++].hangul_shaping_feature() = VJMO; + if (i < end) + info[i++].hangul_shaping_feature() = TJMO; +- buffer->merge_out_clusters (start, end); ++ if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) ++ buffer->merge_out_clusters (start, end); + continue; + } + } +@@ -414,13 +411,14 @@ + "hangul", + collect_features_hangul, + override_features_hangul, +- data_create_hangul, /* data_create */ +- data_destroy_hangul, /* data_destroy */ ++ data_create_hangul, ++ data_destroy_hangul, + preprocess_text_hangul, ++ NULL, /* postprocess_glyphs */ + HB_OT_SHAPE_NORMALIZATION_MODE_NONE, + NULL, /* decompose */ + NULL, /* compose */ +- setup_masks_hangul, /* setup_masks */ ++ setup_masks_hangul, + HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, + false, /* fallback_position */ + }; +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-hebrew.cc gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-hebrew.cc 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc 2016-06-05 23:49:49.094863009 +0200 +@@ -68,7 +68,7 @@ + 0xFB4Au /* TAV */ + }; + +- bool found = c->unicode->compose (a, b, ab); ++ bool found = (bool) c->unicode->compose (a, b, ab); + + if (!found && !c->plan->has_mark) + { +@@ -163,6 +163,7 @@ + NULL, /* data_create */ + NULL, /* data_destroy */ + NULL, /* preprocess_text */ ++ NULL, /* postprocess_glyphs */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, + NULL, /* decompose */ + compose_hebrew, +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-indic.cc gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-indic.cc 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc 2016-06-05 23:49:56.649823205 +0200 +@@ -142,7 +142,7 @@ + { + /* If it ligated, all bets are off. */ + if (_hb_glyph_info_ligated (&info)) return false; +- return !!(FLAG (info.indic_category()) & flags); ++ return !!(FLAG_SAFE (info.indic_category()) & flags); + } + + static inline bool +@@ -176,24 +176,8 @@ + * Re-assign category + */ + +- +- /* The spec says U+0952 is OT_A. However, testing shows that Uniscribe +- * treats a whole bunch of characters similarly. +- * TESTS: For example, for U+0951: +- * U+092E,U+0947,U+0952 +- * U+092E,U+0952,U+0947 +- * U+092E,U+0947,U+0951 +- * U+092E,U+0951,U+0947 +- * U+092E,U+0951,U+0952 +- * U+092E,U+0952,U+0951 +- */ +- if (unlikely (hb_in_ranges (u, 0x0951u, 0x0952u, +- 0x1CD0u, 0x1CD2u, +- 0x1CD4u, 0x1CE1u) || +- u == 0x1CF4u)) +- cat = OT_A; + /* The following act more like the Bindus. */ +- else if (unlikely (hb_in_range (u, 0x0953u, 0x0954u))) ++ if (unlikely (hb_in_range (u, 0x0953u, 0x0954u))) + cat = OT_SM; + /* The following act like consonants. */ + else if (unlikely (hb_in_ranges (u, 0x0A72u, 0x0A73u, +@@ -216,15 +200,12 @@ + cat = OT_Symbol; + ASSERT_STATIC ((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol); + } +- else if (unlikely (hb_in_range (u, 0x17CDu, 0x17D1u) || +- u == 0x17CBu || u == 0x17D3u || u == 0x17DDu)) /* Khmer Various signs */ ++ else if (unlikely (u == 0x17DDu)) /* https://github.com/roozbehp/unicode-data/issues/2 */ + { +- /* These are like Top Matras. */ + cat = OT_M; + pos = POS_ABOVE_C; + } + else if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */ +- else if (unlikely (u == 0x17D2u)) cat = OT_Coeng; /* Khmer coeng */ + else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u))) + cat = OT_PLACEHOLDER; + else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE; +@@ -237,7 +218,7 @@ + * Re-assign position. + */ + +- if ((FLAG (cat) & CONSONANT_FLAGS)) ++ if ((FLAG_SAFE (cat) & CONSONANT_FLAGS)) + { + pos = POS_BASE_C; + if (is_ra (u)) +@@ -247,7 +228,7 @@ + { + pos = matra_position (u, pos); + } +- else if ((FLAG (cat) & (FLAG (OT_SM) | FLAG (OT_VD) | FLAG (OT_A) | FLAG (OT_Symbol)))) ++ else if ((FLAG_SAFE (cat) & (FLAG (OT_SM) | FLAG (OT_VD) | FLAG (OT_A) | FLAG (OT_Symbol)))) + { + pos = POS_SMVD; + } +@@ -557,8 +538,15 @@ + indic_plan->virama_glyph = (hb_codepoint_t) -1; + + /* Use zero-context would_substitute() matching for new-spec of the main +- * Indic scripts, and scripts with one spec only, but not for old-specs. */ +- bool zero_context = !indic_plan->is_old_spec; ++ * Indic scripts, and scripts with one spec only, but not for old-specs. ++ * The new-spec for all dual-spec scripts says zero-context matching happens. ++ * ++ * However, testing with Malayalam shows that old and new spec both allow ++ * context. Testing with Bengali new-spec however shows that it doesn't. ++ * So, the heuristic here is the way it is. It should *only* be changed, ++ * as we discover more cases of what Windows does. DON'T TOUCH OTHERWISE. ++ */ ++ bool zero_context = !indic_plan->is_old_spec && plan->props.script != HB_SCRIPT_MALAYALAM; + indic_plan->rphf.init (&plan->map, HB_TAG('r','p','h','f'), zero_context); + indic_plan->pref.init (&plan->map, HB_TAG('p','r','e','f'), zero_context); + indic_plan->blwf.init (&plan->map, HB_TAG('b','l','w','f'), zero_context); +@@ -756,7 +744,7 @@ + { + default: + assert (false); +- /* fallthrough */ ++ HB_FALLTHROUGH; + + case BASE_POS_LAST: + { +@@ -963,7 +951,7 @@ + indic_position_t last_pos = POS_START; + for (unsigned int i = start; i < end; i++) + { +- if ((FLAG (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | HALANT_OR_COENG_FLAGS))) ++ if ((FLAG_SAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | HALANT_OR_COENG_FLAGS))) + { + info[i].indic_position() = last_pos; + if (unlikely (info[i].indic_category() == OT_H && +@@ -1012,7 +1000,7 @@ + info[i].syllable() = i - start; + + /* Sit tight, rock 'n roll! */ +- hb_bubble_sort (info + start, end - start, compare_indic_order); ++ hb_stable_sort (info + start, end - start, compare_indic_order); + /* Find base again */ + base = end; + for (unsigned int i = start; i < end; i++) +@@ -1025,7 +1013,11 @@ + * around like crazy. In old-spec mode, we move halants around, so in + * that case merge all clusters after base. Otherwise, check the sort + * order and merge as needed. +- * For pre-base stuff, we handle cluster issues in final reordering. */ ++ * For pre-base stuff, we handle cluster issues in final reordering. ++ * ++ * We could use buffer->sort() for this, if there was no special ++ * reordering of pre-base stuff happening later... ++ */ + if (indic_plan->is_old_spec || end - base > 127) + buffer->merge_clusters (base, end); + else +@@ -1161,17 +1153,6 @@ + } + } + +- +-static void +-initial_reordering_vowel_syllable (const hb_ot_shape_plan_t *plan, +- hb_face_t *face, +- hb_buffer_t *buffer, +- unsigned int start, unsigned int end) +-{ +- /* We made the vowels look like consonants. So let's call the consonant logic! */ +- initial_reordering_consonant_syllable (plan, face, buffer, start, end); +-} +- + static void + initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan, + hb_face_t *face, +@@ -1194,50 +1175,27 @@ + } + + static void +-initial_reordering_broken_cluster (const hb_ot_shape_plan_t *plan, +- hb_face_t *face, +- hb_buffer_t *buffer, +- unsigned int start, unsigned int end) +-{ +- /* We already inserted dotted-circles, so just call the standalone_cluster. */ +- initial_reordering_standalone_cluster (plan, face, buffer, start, end); +-} +- +-static void +-initial_reordering_symbol_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED, +- hb_face_t *face HB_UNUSED, +- hb_buffer_t *buffer HB_UNUSED, +- unsigned int start HB_UNUSED, unsigned int end HB_UNUSED) +-{ +- /* Nothing to do right now. If we ever switch to using the output +- * buffer in the reordering process, we'd need to next_glyph() here. */ +-} +- +-static void +-initial_reordering_non_indic_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED, +- hb_face_t *face HB_UNUSED, +- hb_buffer_t *buffer HB_UNUSED, +- unsigned int start HB_UNUSED, unsigned int end HB_UNUSED) +-{ +- /* Nothing to do right now. If we ever switch to using the output +- * buffer in the reordering process, we'd need to next_glyph() here. */ +-} +- +- +-static void + initial_reordering_syllable (const hb_ot_shape_plan_t *plan, + hb_face_t *face, + hb_buffer_t *buffer, + unsigned int start, unsigned int end) + { + syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F); +- switch (syllable_type) { +- case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return; +- case vowel_syllable: initial_reordering_vowel_syllable (plan, face, buffer, start, end); return; +- case standalone_cluster: initial_reordering_standalone_cluster (plan, face, buffer, start, end); return; +- case symbol_cluster: initial_reordering_symbol_cluster (plan, face, buffer, start, end); return; +- case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return; +- case non_indic_cluster: initial_reordering_non_indic_cluster (plan, face, buffer, start, end); return; ++ switch (syllable_type) ++ { ++ case vowel_syllable: /* We made the vowels look like consonants. So let's call the consonant logic! */ ++ case consonant_syllable: ++ initial_reordering_consonant_syllable (plan, face, buffer, start, end); ++ break; ++ ++ case broken_cluster: /* We already inserted dotted-circles, so just call the standalone_cluster. */ ++ case standalone_cluster: ++ initial_reordering_standalone_cluster (plan, face, buffer, start, end); ++ break; ++ ++ case symbol_cluster: ++ case non_indic_cluster: ++ break; + } + } + +@@ -1273,7 +1231,7 @@ + + buffer->idx = 0; + unsigned int last_syllable = 0; +- while (buffer->idx < buffer->len) ++ while (buffer->idx < buffer->len && !buffer->in_error) + { + unsigned int syllable = buffer->cur().syllable(); + syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F); +@@ -1281,10 +1239,10 @@ + { + last_syllable = syllable; + +- hb_glyph_info_t info = dottedcircle; +- info.cluster = buffer->cur().cluster; +- info.mask = buffer->cur().mask; +- info.syllable() = buffer->cur().syllable(); ++ hb_glyph_info_t ginfo = dottedcircle; ++ ginfo.cluster = buffer->cur().cluster; ++ ginfo.mask = buffer->cur().mask; ++ ginfo.syllable() = buffer->cur().syllable(); + /* TODO Set glyph_props? */ + + /* Insert dottedcircle after possible Repha. */ +@@ -1293,7 +1251,7 @@ + buffer->cur().indic_category() == OT_Repha) + buffer->next_glyph (); + +- buffer->output_info (info); ++ buffer->output_info (ginfo); + } + else + buffer->next_glyph (); +@@ -1310,18 +1268,8 @@ + update_consonant_positions (plan, font, buffer); + insert_dotted_circles (plan, font, buffer); + +- hb_glyph_info_t *info = buffer->info; +- unsigned int count = buffer->len; +- if (unlikely (!count)) return; +- unsigned int last = 0; +- unsigned int last_syllable = info[0].syllable(); +- for (unsigned int i = 1; i < count; i++) +- if (last_syllable != info[i].syllable()) { +- initial_reordering_syllable (plan, font->face, buffer, last, i); +- last = i; +- last_syllable = info[last].syllable(); +- } +- initial_reordering_syllable (plan, font->face, buffer, last, count); ++ foreach_syllable (buffer, start, end) ++ initial_reordering_syllable (plan, font->face, buffer, start, end); + } + + static void +@@ -1388,6 +1336,25 @@ + break; + } + } ++ /* For Malayalam, skip over unformed below- (but NOT post-) forms. */ ++ if (buffer->props.script == HB_SCRIPT_MALAYALAM) ++ { ++ for (unsigned int i = base + 1; i < end; i++) ++ { ++ while (i < end && is_joiner (info[i])) ++ i++; ++ if (i == end || !is_halant_or_coeng (info[i])) ++ break; ++ i++; /* Skip halant. */ ++ while (i < end && is_joiner (info[i])) ++ i++; ++ if (i < end && is_consonant (info[i]) && info[i].indic_position() == POS_BELOW_C) ++ { ++ base = i; ++ info[base].indic_position() = POS_BASE_C; ++ } ++ } ++ } + + if (start < base && info[base].indic_position() > POS_BASE_C) + base--; +@@ -1448,12 +1415,17 @@ + if (info[i - 1].indic_position () == POS_PRE_M) + { + unsigned int old_pos = i - 1; ++ if (old_pos < base && base <= new_pos) /* Shouldn't actually happen. */ ++ base--; ++ + hb_glyph_info_t tmp = info[old_pos]; + memmove (&info[old_pos], &info[old_pos + 1], (new_pos - old_pos) * sizeof (info[0])); + info[new_pos] = tmp; +- if (old_pos < base && base <= new_pos) /* Shouldn't actually happen. */ +- base--; ++ ++ /* Note: this merge_clusters() is intentionally *after* the reordering. ++ * Indic matra reordering is special and tricky... */ + buffer->merge_clusters (new_pos, MIN (end, base + 1)); ++ + new_pos--; + } + } else { +@@ -1550,7 +1522,7 @@ + { + new_reph_pos = base; + while (new_reph_pos < end && +- !( FLAG (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_POST_C) | FLAG (POS_AFTER_POST) | FLAG (POS_SMVD)))) ++ !( FLAG_SAFE (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_POST_C) | FLAG (POS_AFTER_POST) | FLAG (POS_SMVD)))) + new_reph_pos++; + if (new_reph_pos < end) + goto reph_move; +@@ -1606,12 +1578,12 @@ + + reph_move: + { +- buffer->merge_clusters (start, new_reph_pos + 1); +- + /* Move */ ++ buffer->merge_clusters (start, new_reph_pos + 1); + hb_glyph_info_t reph = info[start]; + memmove (&info[start], &info[start + 1], (new_reph_pos - start) * sizeof (info[0])); + info[new_reph_pos] = reph; ++ + if (start < base && base <= new_reph_pos) + base--; + } +@@ -1666,8 +1638,8 @@ + if (new_pos > start && info[new_pos - 1].indic_category() == OT_M) + { + unsigned int old_pos = i; +- for (unsigned int i = base + 1; i < old_pos; i++) +- if (info[i].indic_category() == OT_M) ++ for (unsigned int j = base + 1; j < old_pos; j++) ++ if (info[j].indic_category() == OT_M) + { + new_pos--; + break; +@@ -1684,10 +1656,12 @@ + + { + unsigned int old_pos = i; ++ + buffer->merge_clusters (new_pos, old_pos + 1); + hb_glyph_info_t tmp = info[old_pos]; + memmove (&info[new_pos + 1], &info[new_pos], (old_pos - new_pos) * sizeof (info[0])); + info[new_pos] = tmp; ++ + if (new_pos <= base && base < old_pos) + base++; + } +@@ -1701,7 +1675,7 @@ + /* Apply 'init' to the Left Matra if it's a word start. */ + if (info[start].indic_position () == POS_PRE_M && + (!start || +- !(FLAG (_hb_glyph_info_get_general_category (&info[start - 1])) & ++ !(FLAG_SAFE (_hb_glyph_info_get_general_category (&info[start - 1])) & + FLAG_RANGE (HB_UNICODE_GENERAL_CATEGORY_FORMAT, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))) + info[start].mask |= indic_plan->mask_array[INIT]; + +@@ -1737,16 +1711,8 @@ + unsigned int count = buffer->len; + if (unlikely (!count)) return; + +- hb_glyph_info_t *info = buffer->info; +- unsigned int last = 0; +- unsigned int last_syllable = info[0].syllable(); +- for (unsigned int i = 1; i < count; i++) +- if (last_syllable != info[i].syllable()) { +- final_reordering_syllable (plan, buffer, last, i); +- last = i; +- last_syllable = info[last].syllable(); +- } +- final_reordering_syllable (plan, buffer, last, count); ++ foreach_syllable (buffer, start, end) ++ final_reordering_syllable (plan, buffer, start, end); + + HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category); + HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position); +@@ -1847,7 +1813,7 @@ + } + } + +- return c->unicode->decompose (ab, a, b); ++ return (bool) c->unicode->decompose (ab, a, b); + } + + static bool +@@ -1863,7 +1829,7 @@ + /* Composition-exclusion exceptions that we want to recompose. */ + if (a == 0x09AFu && b == 0x09BCu) { *ab = 0x09DFu; return true; } + +- return c->unicode->compose (a, b, ab); ++ return (bool) c->unicode->compose (a, b, ab); + } + + +@@ -1875,6 +1841,7 @@ + data_create_indic, + data_destroy_indic, + NULL, /* preprocess_text */ ++ NULL, /* postprocess_glyphs */ + HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, + decompose_indic, + compose_indic, +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-indic-machine.hh gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-indic-machine.hh 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh 2016-06-05 23:49:50.772854137 +0200 +@@ -1,5 +1,5 @@ + +-#line 1 "../../src/hb-ot-shape-complex-indic-machine.rl" ++#line 1 "hb-ot-shape-complex-indic-machine.rl" + /* + * Copyright © 2011,2012 Google, Inc. + * +@@ -32,1281 +32,1304 @@ + #include "hb-private.hh" + + +-#line 36 "hb-ot-shape-complex-indic-machine.hh.tmp" ++#line 36 "hb-ot-shape-complex-indic-machine.hh" + static const unsigned char _indic_syllable_machine_trans_keys[] = { +- 1u, 16u, 13u, 13u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, +- 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 4u, 4u, 6u, 6u, +- 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, +- 6u, 6u, 16u, 16u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, +- 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 1u, 16u, 13u, 13u, 5u, 7u, 5u, 7u, +- 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, +- 5u, 7u, 7u, 7u, 4u, 4u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, +- 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 14u, 4u, 14u, ++ 8u, 8u, 1u, 16u, 8u, 13u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, ++ 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, ++ 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, ++ 4u, 8u, 6u, 6u, 16u, 16u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, ++ 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 8u, 8u, 1u, 16u, 8u, 13u, ++ 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, ++ 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, ++ 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, + 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, +- 1u, 16u, 13u, 13u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, +- 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 4u, 4u, 6u, 6u, +- 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, +- 6u, 6u, 16u, 16u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, +- 4u, 14u, 4u, 14u, 4u, 14u, 1u, 16u, 13u, 13u, 5u, 7u, 5u, 7u, 7u, 7u, +- 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, +- 7u, 7u, 4u, 4u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, +- 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 14u, 4u, 14u, 4u, 14u, +- 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, +- 4u, 14u, 5u, 7u, 5u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, +- 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 1u, 16u, 13u, 13u, 4u, 4u, 6u, 6u, +- 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, +- 6u, 6u, 16u, 16u, 1u, 31u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, ++ 4u, 14u, 4u, 14u, 8u, 8u, 1u, 16u, 8u, 13u, 5u, 8u, 5u, 7u, 7u, 7u, ++ 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, ++ 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, ++ 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 14u, 4u, 14u, 4u, 14u, ++ 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 8u, 8u, 1u, 16u, ++ 8u, 13u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, ++ 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, ++ 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, ++ 16u, 16u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, ++ 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 5u, 8u, 4u, 14u, 4u, 14u, 5u, 8u, ++ 5u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, ++ 5u, 7u, 7u, 7u, 8u, 8u, 1u, 16u, 8u, 13u, 4u, 8u, 6u, 6u, 16u, 16u, ++ 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, ++ 16u, 16u, 8u, 8u, 1u, 31u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, + 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, +- 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 8u, 14u, ++ 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 5u, 14u, + 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u, +- 3u, 10u, 8u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, ++ 3u, 10u, 5u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, + 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, +- 6u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, ++ 5u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, + 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, + 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, + 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, + 1u, 16u, 3u, 31u, 3u, 31u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, + 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, +- 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 8u, 14u, ++ 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 5u, 14u, + 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u, +- 3u, 10u, 8u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, ++ 3u, 10u, 5u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, + 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, +- 6u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, ++ 5u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, + 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, + 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, + 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, + 4u, 14u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, + 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, +- 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 8u, 14u, 5u, 10u, ++ 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 5u, 14u, 5u, 10u, + 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u, 3u, 10u, +- 8u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, +- 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 6u, 14u, ++ 5u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, ++ 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, + 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, + 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, + 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, + 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, + 4u, 14u, 3u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, + 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, +- 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 8u, 14u, ++ 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 5u, 14u, + 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u, +- 3u, 10u, 8u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, ++ 3u, 10u, 5u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, + 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, +- 6u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, ++ 5u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, + 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, + 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, + 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, +- 1u, 16u, 3u, 31u, 1u, 31u, 3u, 31u, 1u, 31u, 4u, 14u, 1u, 16u, 3u, 31u, +- 3u, 31u, 4u, 31u, 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, +- 5u, 10u, 3u, 31u, 3u, 31u, 1u, 16u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, +- 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 8u, 14u, +- 3u, 13u, 3u, 10u, 8u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 3u, 10u, 8u, 10u, ++ 1u, 16u, 3u, 31u, 1u, 31u, 3u, 31u, 1u, 31u, 4u, 14u, 5u, 10u, 9u, 10u, ++ 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 1u, 16u, 3u, 31u, 3u, 31u, ++ 4u, 31u, 3u, 31u, 3u, 31u, 1u, 16u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, ++ 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, ++ 3u, 13u, 3u, 10u, 5u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 3u, 10u, 5u, 10u, + 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 0 + }; + + static const char _indic_syllable_machine_key_spans[] = { +- 16, 1, 3, 3, 1, 3, 3, 1, +- 3, 3, 1, 3, 3, 1, 1, 1, +- 1, 4, 1, 1, 4, 1, 1, 4, +- 1, 1, 11, 11, 11, 11, 11, 11, +- 11, 11, 11, 11, 16, 1, 3, 3, +- 1, 3, 3, 1, 3, 3, 1, 3, +- 3, 1, 1, 1, 1, 4, 1, 1, +- 4, 1, 1, 4, 1, 1, 11, 11, +- 11, 11, 11, 11, 11, 11, 11, 11, +- 16, 1, 3, 3, 1, 3, 3, 1, +- 3, 3, 1, 3, 3, 1, 1, 1, +- 1, 4, 1, 1, 4, 1, 1, 4, +- 1, 1, 11, 11, 11, 11, 11, 11, +- 11, 11, 11, 16, 1, 3, 3, 1, +- 3, 3, 1, 3, 3, 1, 3, 3, +- 1, 1, 1, 1, 4, 1, 1, 4, +- 1, 1, 4, 1, 1, 11, 11, 11, ++ 1, 16, 6, 4, 3, 1, 4, 3, ++ 1, 4, 3, 1, 4, 3, 1, 5, ++ 1, 1, 5, 1, 1, 5, 1, 1, ++ 5, 1, 1, 11, 11, 11, 11, 11, ++ 11, 11, 11, 11, 11, 1, 16, 6, ++ 4, 3, 1, 4, 3, 1, 4, 3, ++ 1, 4, 3, 1, 5, 1, 1, 5, ++ 1, 1, 5, 1, 1, 5, 1, 1, + 11, 11, 11, 11, 11, 11, 11, 11, +- 11, 3, 3, 3, 3, 1, 3, 3, +- 1, 3, 3, 1, 16, 1, 1, 1, +- 1, 4, 1, 1, 4, 1, 1, 4, ++ 11, 11, 1, 16, 6, 4, 3, 1, ++ 4, 3, 1, 4, 3, 1, 4, 3, ++ 1, 5, 1, 1, 5, 1, 1, 5, ++ 1, 1, 5, 1, 1, 11, 11, 11, ++ 11, 11, 11, 11, 11, 11, 1, 16, ++ 6, 4, 3, 1, 4, 3, 1, 4, ++ 3, 1, 4, 3, 1, 5, 1, 1, ++ 5, 1, 1, 5, 1, 1, 5, 1, ++ 1, 11, 11, 11, 11, 11, 11, 11, ++ 11, 11, 11, 11, 4, 11, 11, 4, ++ 3, 4, 3, 1, 4, 3, 1, 4, ++ 3, 1, 1, 16, 6, 5, 1, 1, ++ 5, 1, 1, 5, 1, 1, 5, 1, + 1, 1, 31, 29, 29, 28, 16, 29, + 29, 28, 16, 29, 29, 28, 16, 29, +- 29, 28, 16, 29, 29, 28, 10, 7, ++ 29, 28, 16, 29, 29, 28, 10, 10, + 6, 2, 1, 2, 2, 1, 6, 11, +- 8, 3, 8, 11, 12, 12, 11, 10, ++ 8, 6, 8, 11, 12, 12, 11, 10, + 12, 11, 10, 12, 11, 10, 12, 11, +- 9, 12, 16, 28, 11, 29, 29, 16, ++ 10, 12, 16, 28, 11, 29, 29, 16, + 16, 16, 16, 16, 29, 29, 16, 16, + 16, 16, 16, 29, 29, 16, 16, 16, + 16, 16, 29, 29, 16, 16, 16, 16, + 16, 29, 29, 29, 29, 28, 16, 29, + 29, 28, 16, 29, 29, 28, 16, 29, +- 29, 28, 16, 29, 29, 28, 10, 7, ++ 29, 28, 16, 29, 29, 28, 10, 10, + 6, 2, 1, 2, 2, 1, 6, 11, +- 8, 3, 8, 11, 12, 12, 11, 10, ++ 8, 6, 8, 11, 12, 12, 11, 10, + 12, 11, 10, 12, 11, 10, 12, 11, +- 9, 12, 16, 28, 11, 29, 29, 16, ++ 10, 12, 16, 28, 11, 29, 29, 16, + 16, 16, 16, 16, 29, 29, 16, 16, + 16, 16, 16, 29, 29, 16, 16, 16, + 16, 16, 29, 29, 16, 16, 16, 16, + 11, 16, 29, 29, 28, 16, 29, 29, + 28, 16, 29, 29, 28, 16, 29, 29, +- 28, 16, 29, 29, 28, 10, 7, 6, ++ 28, 16, 29, 29, 28, 10, 10, 6, + 2, 1, 2, 2, 1, 6, 11, 8, +- 3, 8, 11, 12, 12, 11, 10, 12, +- 11, 10, 12, 11, 10, 12, 11, 9, ++ 6, 8, 11, 12, 12, 11, 10, 12, ++ 11, 10, 12, 11, 10, 12, 11, 10, + 12, 16, 28, 11, 29, 29, 16, 16, + 16, 16, 16, 29, 29, 16, 16, 16, + 16, 16, 29, 29, 16, 16, 16, 16, + 16, 29, 29, 16, 16, 16, 16, 16, + 11, 29, 11, 29, 29, 28, 16, 29, + 29, 28, 16, 29, 29, 28, 16, 29, +- 29, 28, 16, 29, 29, 28, 10, 7, ++ 29, 28, 16, 29, 29, 28, 10, 10, + 6, 2, 1, 2, 2, 1, 6, 11, +- 8, 3, 8, 11, 12, 12, 11, 10, ++ 8, 6, 8, 11, 12, 12, 11, 10, + 12, 11, 10, 12, 11, 10, 12, 11, +- 9, 12, 16, 28, 11, 29, 29, 16, ++ 10, 12, 16, 28, 11, 29, 29, 16, + 16, 16, 16, 16, 29, 29, 16, 16, + 16, 16, 16, 29, 29, 16, 16, 16, + 16, 16, 29, 29, 16, 16, 16, 16, +- 16, 29, 31, 29, 31, 11, 16, 29, +- 29, 28, 6, 2, 1, 2, 2, 1, +- 6, 29, 29, 16, 12, 11, 10, 12, +- 11, 10, 12, 11, 10, 12, 11, 7, +- 11, 8, 3, 8, 11, 16, 8, 3, ++ 16, 29, 31, 29, 31, 11, 6, 2, ++ 1, 2, 2, 1, 6, 16, 29, 29, ++ 28, 29, 29, 16, 12, 11, 10, 12, ++ 11, 10, 12, 11, 10, 12, 11, 10, ++ 11, 8, 6, 8, 11, 16, 8, 6, + 6, 2, 1, 2, 2, 1, 6 + }; + + static const short _indic_syllable_machine_index_offsets[] = { +- 0, 17, 19, 23, 27, 29, 33, 37, +- 39, 43, 47, 49, 53, 57, 59, 61, +- 63, 65, 70, 72, 74, 79, 81, 83, +- 88, 90, 92, 104, 116, 128, 140, 152, +- 164, 176, 188, 200, 212, 229, 231, 235, +- 239, 241, 245, 249, 251, 255, 259, 261, +- 265, 269, 271, 273, 275, 277, 282, 284, +- 286, 291, 293, 295, 300, 302, 304, 316, +- 328, 340, 352, 364, 376, 388, 400, 412, +- 424, 441, 443, 447, 451, 453, 457, 461, +- 463, 467, 471, 473, 477, 481, 483, 485, +- 487, 489, 494, 496, 498, 503, 505, 507, +- 512, 514, 516, 528, 540, 552, 564, 576, +- 588, 600, 612, 624, 641, 643, 647, 651, +- 653, 657, 661, 663, 667, 671, 673, 677, +- 681, 683, 685, 687, 689, 694, 696, 698, +- 703, 705, 707, 712, 714, 716, 728, 740, +- 752, 764, 776, 788, 800, 812, 824, 836, +- 848, 860, 864, 868, 872, 876, 878, 882, +- 886, 888, 892, 896, 898, 915, 917, 919, +- 921, 923, 928, 930, 932, 937, 939, 941, +- 946, 948, 950, 982, 1012, 1042, 1071, 1088, +- 1118, 1148, 1177, 1194, 1224, 1254, 1283, 1300, +- 1330, 1360, 1389, 1406, 1436, 1466, 1495, 1506, +- 1514, 1521, 1524, 1526, 1529, 1532, 1534, 1541, +- 1553, 1562, 1566, 1575, 1587, 1600, 1613, 1625, +- 1636, 1649, 1661, 1672, 1685, 1697, 1708, 1721, +- 1733, 1743, 1756, 1773, 1802, 1814, 1844, 1874, +- 1891, 1908, 1925, 1942, 1959, 1989, 2019, 2036, +- 2053, 2070, 2087, 2104, 2134, 2164, 2181, 2198, +- 2215, 2232, 2249, 2279, 2309, 2326, 2343, 2360, +- 2377, 2394, 2424, 2454, 2484, 2514, 2543, 2560, +- 2590, 2620, 2649, 2666, 2696, 2726, 2755, 2772, +- 2802, 2832, 2861, 2878, 2908, 2938, 2967, 2978, +- 2986, 2993, 2996, 2998, 3001, 3004, 3006, 3013, +- 3025, 3034, 3038, 3047, 3059, 3072, 3085, 3097, +- 3108, 3121, 3133, 3144, 3157, 3169, 3180, 3193, +- 3205, 3215, 3228, 3245, 3274, 3286, 3316, 3346, +- 3363, 3380, 3397, 3414, 3431, 3461, 3491, 3508, +- 3525, 3542, 3559, 3576, 3606, 3636, 3653, 3670, +- 3687, 3704, 3721, 3751, 3781, 3798, 3815, 3832, +- 3849, 3861, 3878, 3908, 3938, 3967, 3984, 4014, +- 4044, 4073, 4090, 4120, 4150, 4179, 4196, 4226, +- 4256, 4285, 4302, 4332, 4362, 4391, 4402, 4410, +- 4417, 4420, 4422, 4425, 4428, 4430, 4437, 4449, +- 4458, 4462, 4471, 4483, 4496, 4509, 4521, 4532, +- 4545, 4557, 4568, 4581, 4593, 4604, 4617, 4629, +- 4639, 4652, 4669, 4698, 4710, 4740, 4770, 4787, +- 4804, 4821, 4838, 4855, 4885, 4915, 4932, 4949, +- 4966, 4983, 5000, 5030, 5060, 5077, 5094, 5111, +- 5128, 5145, 5175, 5205, 5222, 5239, 5256, 5273, +- 5290, 5302, 5332, 5344, 5374, 5404, 5433, 5450, +- 5480, 5510, 5539, 5556, 5586, 5616, 5645, 5662, +- 5692, 5722, 5751, 5768, 5798, 5828, 5857, 5868, +- 5876, 5883, 5886, 5888, 5891, 5894, 5896, 5903, +- 5915, 5924, 5928, 5937, 5949, 5962, 5975, 5987, +- 5998, 6011, 6023, 6034, 6047, 6059, 6070, 6083, +- 6095, 6105, 6118, 6135, 6164, 6176, 6206, 6236, +- 6253, 6270, 6287, 6304, 6321, 6351, 6381, 6398, +- 6415, 6432, 6449, 6466, 6496, 6526, 6543, 6560, +- 6577, 6594, 6611, 6641, 6671, 6688, 6705, 6722, +- 6739, 6756, 6786, 6818, 6848, 6880, 6892, 6909, +- 6939, 6969, 6998, 7005, 7008, 7010, 7013, 7016, +- 7018, 7025, 7055, 7085, 7102, 7115, 7127, 7138, +- 7151, 7163, 7174, 7187, 7199, 7210, 7223, 7235, +- 7243, 7255, 7264, 7268, 7277, 7289, 7306, 7315, +- 7319, 7326, 7329, 7331, 7334, 7337, 7339 ++ 0, 2, 19, 26, 31, 35, 37, 42, ++ 46, 48, 53, 57, 59, 64, 68, 70, ++ 76, 78, 80, 86, 88, 90, 96, 98, ++ 100, 106, 108, 110, 122, 134, 146, 158, ++ 170, 182, 194, 206, 218, 230, 232, 249, ++ 256, 261, 265, 267, 272, 276, 278, 283, ++ 287, 289, 294, 298, 300, 306, 308, 310, ++ 316, 318, 320, 326, 328, 330, 336, 338, ++ 340, 352, 364, 376, 388, 400, 412, 424, ++ 436, 448, 460, 462, 479, 486, 491, 495, ++ 497, 502, 506, 508, 513, 517, 519, 524, ++ 528, 530, 536, 538, 540, 546, 548, 550, ++ 556, 558, 560, 566, 568, 570, 582, 594, ++ 606, 618, 630, 642, 654, 666, 678, 680, ++ 697, 704, 709, 713, 715, 720, 724, 726, ++ 731, 735, 737, 742, 746, 748, 754, 756, ++ 758, 764, 766, 768, 774, 776, 778, 784, ++ 786, 788, 800, 812, 824, 836, 848, 860, ++ 872, 884, 896, 908, 920, 925, 937, 949, ++ 954, 958, 963, 967, 969, 974, 978, 980, ++ 985, 989, 991, 993, 1010, 1017, 1023, 1025, ++ 1027, 1033, 1035, 1037, 1043, 1045, 1047, 1053, ++ 1055, 1057, 1059, 1091, 1121, 1151, 1180, 1197, ++ 1227, 1257, 1286, 1303, 1333, 1363, 1392, 1409, ++ 1439, 1469, 1498, 1515, 1545, 1575, 1604, 1615, ++ 1626, 1633, 1636, 1638, 1641, 1644, 1646, 1653, ++ 1665, 1674, 1681, 1690, 1702, 1715, 1728, 1740, ++ 1751, 1764, 1776, 1787, 1800, 1812, 1823, 1836, ++ 1848, 1859, 1872, 1889, 1918, 1930, 1960, 1990, ++ 2007, 2024, 2041, 2058, 2075, 2105, 2135, 2152, ++ 2169, 2186, 2203, 2220, 2250, 2280, 2297, 2314, ++ 2331, 2348, 2365, 2395, 2425, 2442, 2459, 2476, ++ 2493, 2510, 2540, 2570, 2600, 2630, 2659, 2676, ++ 2706, 2736, 2765, 2782, 2812, 2842, 2871, 2888, ++ 2918, 2948, 2977, 2994, 3024, 3054, 3083, 3094, ++ 3105, 3112, 3115, 3117, 3120, 3123, 3125, 3132, ++ 3144, 3153, 3160, 3169, 3181, 3194, 3207, 3219, ++ 3230, 3243, 3255, 3266, 3279, 3291, 3302, 3315, ++ 3327, 3338, 3351, 3368, 3397, 3409, 3439, 3469, ++ 3486, 3503, 3520, 3537, 3554, 3584, 3614, 3631, ++ 3648, 3665, 3682, 3699, 3729, 3759, 3776, 3793, ++ 3810, 3827, 3844, 3874, 3904, 3921, 3938, 3955, ++ 3972, 3984, 4001, 4031, 4061, 4090, 4107, 4137, ++ 4167, 4196, 4213, 4243, 4273, 4302, 4319, 4349, ++ 4379, 4408, 4425, 4455, 4485, 4514, 4525, 4536, ++ 4543, 4546, 4548, 4551, 4554, 4556, 4563, 4575, ++ 4584, 4591, 4600, 4612, 4625, 4638, 4650, 4661, ++ 4674, 4686, 4697, 4710, 4722, 4733, 4746, 4758, ++ 4769, 4782, 4799, 4828, 4840, 4870, 4900, 4917, ++ 4934, 4951, 4968, 4985, 5015, 5045, 5062, 5079, ++ 5096, 5113, 5130, 5160, 5190, 5207, 5224, 5241, ++ 5258, 5275, 5305, 5335, 5352, 5369, 5386, 5403, ++ 5420, 5432, 5462, 5474, 5504, 5534, 5563, 5580, ++ 5610, 5640, 5669, 5686, 5716, 5746, 5775, 5792, ++ 5822, 5852, 5881, 5898, 5928, 5958, 5987, 5998, ++ 6009, 6016, 6019, 6021, 6024, 6027, 6029, 6036, ++ 6048, 6057, 6064, 6073, 6085, 6098, 6111, 6123, ++ 6134, 6147, 6159, 6170, 6183, 6195, 6206, 6219, ++ 6231, 6242, 6255, 6272, 6301, 6313, 6343, 6373, ++ 6390, 6407, 6424, 6441, 6458, 6488, 6518, 6535, ++ 6552, 6569, 6586, 6603, 6633, 6663, 6680, 6697, ++ 6714, 6731, 6748, 6778, 6808, 6825, 6842, 6859, ++ 6876, 6893, 6923, 6955, 6985, 7017, 7029, 7036, ++ 7039, 7041, 7044, 7047, 7049, 7056, 7073, 7103, ++ 7133, 7162, 7192, 7222, 7239, 7252, 7264, 7275, ++ 7288, 7300, 7311, 7324, 7336, 7347, 7360, 7372, ++ 7383, 7395, 7404, 7411, 7420, 7432, 7449, 7458, ++ 7465, 7472, 7475, 7477, 7480, 7483, 7485 + }; + + static const short _indic_syllable_machine_indicies[] = { +- 1, 2, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 1, +- 0, 3, 0, 4, 4, 5, 0, 6, +- 6, 5, 0, 5, 0, 7, 7, 8, +- 0, 9, 9, 8, 0, 8, 0, 10, +- 10, 11, 0, 12, 12, 11, 0, 11, +- 0, 13, 13, 14, 0, 15, 15, 14, +- 0, 14, 0, 16, 0, 17, 0, 18, +- 0, 19, 13, 13, 14, 0, 20, 0, +- 21, 0, 22, 10, 10, 11, 0, 23, +- 0, 24, 0, 25, 7, 7, 8, 0, +- 26, 0, 27, 0, 28, 4, 4, 5, +- 0, 0, 0, 0, 0, 0, 28, 0, +- 28, 4, 4, 5, 0, 0, 0, 0, +- 0, 29, 28, 0, 30, 4, 4, 5, +- 0, 0, 0, 0, 0, 0, 30, 0, +- 30, 4, 4, 5, 0, 0, 0, 0, +- 0, 31, 30, 0, 32, 4, 4, 5, +- 0, 0, 0, 0, 0, 0, 32, 0, +- 32, 4, 4, 5, 0, 0, 0, 0, +- 0, 33, 32, 0, 34, 4, 4, 5, +- 0, 0, 0, 0, 0, 0, 34, 0, +- 34, 4, 4, 5, 0, 0, 0, 0, +- 0, 35, 34, 0, 36, 4, 4, 5, +- 0, 0, 0, 0, 0, 0, 36, 0, +- 36, 4, 4, 5, 0, 0, 0, 0, +- 0, 37, 36, 0, 39, 40, 38, 38, +- 38, 38, 38, 38, 38, 38, 38, 38, +- 38, 38, 38, 39, 38, 41, 38, 42, +- 42, 43, 38, 44, 44, 43, 38, 43, +- 38, 45, 45, 46, 38, 47, 47, 46, +- 38, 46, 38, 48, 48, 49, 38, 50, +- 50, 49, 38, 49, 38, 51, 51, 52, +- 38, 53, 53, 52, 38, 52, 38, 54, +- 38, 55, 38, 56, 38, 57, 51, 51, +- 52, 38, 58, 38, 59, 38, 60, 48, +- 48, 49, 38, 61, 38, 62, 38, 63, +- 45, 45, 46, 38, 64, 38, 65, 38, +- 66, 42, 42, 43, 38, 38, 38, 38, +- 38, 38, 66, 38, 66, 42, 42, 43, +- 38, 38, 38, 38, 38, 67, 66, 38, +- 68, 42, 42, 43, 38, 38, 38, 38, +- 38, 38, 68, 38, 68, 42, 42, 43, +- 38, 38, 38, 38, 38, 69, 68, 38, +- 70, 42, 42, 43, 38, 38, 38, 38, +- 38, 38, 70, 38, 70, 42, 42, 43, +- 38, 38, 38, 38, 38, 71, 70, 38, +- 72, 42, 42, 43, 38, 38, 38, 38, +- 38, 38, 72, 38, 72, 42, 42, 43, +- 38, 38, 38, 38, 38, 73, 72, 38, +- 74, 42, 42, 43, 38, 38, 38, 38, +- 38, 38, 74, 38, 74, 42, 42, 43, +- 38, 38, 38, 38, 38, 75, 74, 38, +- 77, 78, 76, 76, 76, 76, 76, 76, +- 76, 76, 76, 76, 76, 76, 76, 77, +- 76, 79, 76, 80, 80, 81, 76, 83, +- 83, 81, 82, 81, 82, 84, 84, 85, +- 76, 86, 86, 85, 76, 85, 76, 87, +- 87, 88, 76, 89, 89, 88, 76, 88, +- 76, 90, 90, 91, 76, 92, 92, 91, +- 76, 91, 76, 93, 76, 94, 76, 95, +- 76, 96, 90, 90, 91, 76, 97, 76, +- 98, 76, 99, 87, 87, 88, 76, 100, +- 76, 101, 76, 102, 84, 84, 85, 76, +- 103, 76, 104, 76, 105, 80, 80, 81, +- 76, 76, 76, 76, 76, 76, 105, 76, +- 105, 80, 80, 81, 76, 76, 76, 76, +- 76, 106, 105, 76, 107, 80, 80, 81, +- 76, 76, 76, 76, 76, 76, 107, 76, +- 107, 80, 80, 81, 76, 76, 76, 76, +- 76, 108, 107, 76, 109, 80, 80, 81, +- 76, 76, 76, 76, 76, 76, 109, 76, +- 109, 80, 80, 81, 76, 76, 76, 76, +- 76, 110, 109, 76, 111, 80, 80, 81, +- 82, 82, 82, 82, 82, 82, 111, 82, +- 111, 80, 80, 81, 76, 76, 76, 76, +- 76, 112, 111, 76, 113, 80, 80, 81, +- 76, 76, 76, 76, 76, 76, 113, 76, +- 115, 116, 114, 114, 114, 114, 114, 114, +- 114, 114, 114, 114, 114, 114, 114, 115, +- 114, 117, 114, 118, 118, 119, 114, 120, +- 120, 119, 114, 119, 114, 121, 121, 122, +- 114, 123, 123, 122, 114, 122, 114, 124, +- 124, 125, 114, 126, 126, 125, 114, 125, +- 114, 127, 127, 128, 114, 129, 129, 128, +- 114, 128, 114, 130, 114, 131, 114, 132, +- 114, 133, 127, 127, 128, 114, 134, 114, +- 135, 114, 136, 124, 124, 125, 114, 137, +- 114, 138, 114, 139, 121, 121, 122, 114, +- 140, 114, 141, 114, 142, 118, 118, 119, +- 114, 114, 114, 114, 114, 114, 142, 114, +- 142, 118, 118, 119, 114, 114, 114, 114, +- 114, 143, 142, 114, 144, 118, 118, 119, +- 114, 114, 114, 114, 114, 114, 144, 114, +- 144, 118, 118, 119, 114, 114, 114, 114, +- 114, 145, 144, 114, 146, 118, 118, 119, +- 114, 114, 114, 114, 114, 114, 146, 114, +- 146, 118, 118, 119, 114, 114, 114, 114, +- 114, 147, 146, 114, 148, 118, 118, 119, +- 114, 114, 114, 114, 114, 114, 148, 114, +- 148, 118, 118, 119, 114, 114, 114, 114, +- 114, 149, 148, 114, 150, 118, 118, 119, +- 114, 114, 114, 114, 114, 114, 150, 114, +- 150, 118, 118, 119, 114, 114, 114, 114, +- 114, 151, 150, 114, 113, 80, 80, 81, +- 76, 76, 76, 76, 76, 152, 113, 76, +- 111, 80, 80, 81, 0, 0, 0, 0, +- 0, 153, 111, 0, 154, 154, 155, 0, +- 6, 6, 155, 0, 156, 156, 157, 0, +- 158, 158, 157, 0, 157, 0, 159, 159, +- 160, 0, 161, 161, 160, 0, 160, 0, +- 162, 162, 163, 0, 164, 164, 163, 0, +- 163, 0, 165, 166, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 165, 0, 167, 0, 168, 0, 169, +- 0, 170, 0, 171, 162, 162, 163, 0, +- 172, 0, 173, 0, 174, 159, 159, 160, +- 0, 175, 0, 176, 0, 177, 156, 156, +- 157, 0, 178, 0, 179, 0, 181, 182, +- 183, 184, 185, 186, 81, 187, 188, 189, +- 190, 190, 152, 191, 192, 193, 194, 195, +- 180, 180, 180, 180, 180, 180, 180, 180, +- 180, 180, 180, 180, 196, 180, 198, 199, +- 200, 201, 5, 202, 203, 204, 197, 197, +- 37, 205, 197, 197, 206, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 207, 197, 208, 199, 209, 209, +- 5, 202, 203, 204, 197, 197, 197, 205, +- 197, 197, 206, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 207, 197, 199, 209, 209, 5, 202, 203, +- 204, 197, 197, 197, 205, 197, 197, 206, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 207, 197, 210, +- 197, 197, 197, 18, 211, 197, 202, 203, +- 204, 197, 197, 197, 212, 197, 210, 197, +- 213, 214, 215, 216, 5, 202, 203, 204, +- 197, 197, 35, 217, 197, 197, 206, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 207, 197, 218, 214, +- 219, 219, 5, 202, 203, 204, 197, 197, +- 197, 217, 197, 197, 206, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 207, 197, 214, 219, 219, 5, +- 202, 203, 204, 197, 197, 197, 217, 197, +- 197, 206, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 207, +- 197, 220, 197, 197, 197, 18, 221, 197, +- 202, 203, 204, 197, 197, 197, 212, 197, +- 220, 197, 222, 223, 224, 225, 5, 202, +- 203, 204, 197, 197, 33, 226, 197, 197, +- 206, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 207, 197, +- 227, 223, 228, 228, 5, 202, 203, 204, +- 197, 197, 197, 226, 197, 197, 206, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 207, 197, 223, 228, +- 228, 5, 202, 203, 204, 197, 197, 197, +- 226, 197, 197, 206, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 207, 197, 229, 197, 197, 197, 18, +- 230, 197, 202, 203, 204, 197, 197, 197, +- 212, 197, 229, 197, 231, 232, 233, 234, +- 5, 202, 203, 204, 197, 197, 31, 235, +- 197, 197, 206, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 207, 197, 236, 232, 237, 237, 5, 202, +- 203, 204, 197, 197, 197, 235, 197, 197, +- 206, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 207, 197, +- 232, 237, 237, 5, 202, 203, 204, 197, +- 197, 197, 235, 197, 197, 206, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 207, 197, 238, 197, 197, +- 197, 18, 239, 197, 202, 203, 204, 197, +- 197, 197, 212, 197, 238, 197, 240, 241, +- 242, 243, 5, 202, 203, 204, 197, 197, +- 29, 244, 197, 197, 206, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 207, 197, 245, 241, 246, 246, +- 5, 202, 203, 204, 197, 197, 197, 244, +- 197, 197, 206, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 207, 197, 241, 246, 246, 5, 202, 203, +- 204, 197, 197, 197, 244, 197, 197, 206, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 207, 197, 18, +- 247, 197, 202, 203, 204, 197, 197, 197, +- 212, 197, 202, 203, 204, 197, 197, 197, +- 212, 197, 248, 197, 197, 249, 203, 204, +- 197, 203, 204, 197, 250, 197, 203, 251, +- 197, 203, 252, 197, 203, 197, 248, 197, +- 197, 197, 203, 204, 197, 253, 197, 254, +- 255, 197, 202, 203, 204, 197, 197, 3, +- 197, 2, 197, 197, 197, 197, 202, 203, +- 204, 197, 202, 203, 204, 197, 253, 197, +- 197, 197, 197, 202, 203, 204, 197, 253, +- 197, 254, 197, 197, 202, 203, 204, 197, +- 197, 3, 197, 18, 197, 256, 256, 5, +- 202, 203, 204, 197, 197, 197, 212, 197, +- 257, 27, 258, 259, 8, 202, 203, 204, +- 197, 197, 197, 212, 197, 27, 258, 259, +- 8, 202, 203, 204, 197, 197, 197, 212, +- 197, 258, 258, 8, 202, 203, 204, 197, +- 197, 197, 212, 197, 260, 24, 261, 262, +- 11, 202, 203, 204, 197, 197, 197, 212, +- 197, 24, 261, 262, 11, 202, 203, 204, +- 197, 197, 197, 212, 197, 261, 261, 11, +- 202, 203, 204, 197, 197, 197, 212, 197, +- 263, 21, 264, 265, 14, 202, 203, 204, +- 197, 197, 197, 212, 197, 21, 264, 265, +- 14, 202, 203, 204, 197, 197, 197, 212, +- 197, 264, 264, 14, 202, 203, 204, 197, +- 197, 197, 212, 197, 266, 18, 197, 267, +- 197, 202, 203, 204, 197, 197, 197, 212, +- 197, 18, 197, 267, 197, 202, 203, 204, +- 197, 197, 197, 212, 197, 268, 197, 202, +- 203, 204, 197, 197, 197, 212, 197, 18, +- 197, 197, 197, 197, 202, 203, 204, 197, +- 197, 197, 212, 197, 1, 2, 197, 197, +- 18, 247, 197, 202, 203, 204, 197, 197, +- 197, 212, 197, 1, 197, 241, 246, 246, +- 5, 202, 203, 204, 197, 197, 197, 244, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 207, 197, 241, 246, 246, 5, 202, 203, +- 204, 197, 197, 197, 244, 197, 240, 241, +- 246, 246, 5, 202, 203, 204, 197, 197, +- 197, 244, 197, 197, 206, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 207, 197, 240, 241, 242, 246, +- 5, 202, 203, 204, 197, 197, 29, 244, +- 197, 197, 206, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 207, 197, 238, 197, 269, 197, 256, 256, +- 5, 202, 203, 204, 197, 197, 197, 212, +- 197, 238, 197, 238, 197, 197, 197, 197, +- 197, 197, 202, 203, 204, 197, 197, 197, +- 212, 197, 238, 197, 238, 197, 197, 197, +- 197, 270, 197, 202, 203, 204, 197, 197, +- 197, 212, 197, 238, 197, 238, 197, 269, +- 197, 197, 197, 197, 202, 203, 204, 197, +- 197, 197, 212, 197, 238, 197, 238, 2, +- 197, 197, 18, 239, 197, 202, 203, 204, +- 197, 197, 197, 212, 197, 238, 197, 231, +- 232, 237, 237, 5, 202, 203, 204, 197, +- 197, 197, 235, 197, 197, 206, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 207, 197, 231, 232, 233, +- 237, 5, 202, 203, 204, 197, 197, 31, +- 235, 197, 197, 206, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 207, 197, 229, 197, 271, 197, 256, +- 256, 5, 202, 203, 204, 197, 197, 197, +- 212, 197, 229, 197, 229, 197, 197, 197, +- 197, 197, 197, 202, 203, 204, 197, 197, +- 197, 212, 197, 229, 197, 229, 197, 197, +- 197, 197, 272, 197, 202, 203, 204, 197, +- 197, 197, 212, 197, 229, 197, 229, 197, +- 271, 197, 197, 197, 197, 202, 203, 204, +- 197, 197, 197, 212, 197, 229, 197, 229, +- 2, 197, 197, 18, 230, 197, 202, 203, +- 204, 197, 197, 197, 212, 197, 229, 197, +- 222, 223, 228, 228, 5, 202, 203, 204, +- 197, 197, 197, 226, 197, 197, 206, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 207, 197, 222, 223, +- 224, 228, 5, 202, 203, 204, 197, 197, +- 33, 226, 197, 197, 206, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 207, 197, 220, 197, 273, 197, +- 256, 256, 5, 202, 203, 204, 197, 197, +- 197, 212, 197, 220, 197, 220, 197, 197, +- 197, 197, 197, 197, 202, 203, 204, 197, +- 197, 197, 212, 197, 220, 197, 220, 197, +- 197, 197, 197, 274, 197, 202, 203, 204, +- 197, 197, 197, 212, 197, 220, 197, 220, +- 197, 273, 197, 197, 197, 197, 202, 203, +- 204, 197, 197, 197, 212, 197, 220, 197, +- 220, 2, 197, 197, 18, 221, 197, 202, +- 203, 204, 197, 197, 197, 212, 197, 220, +- 197, 213, 214, 219, 219, 5, 202, 203, +- 204, 197, 197, 197, 217, 197, 197, 206, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 207, 197, 213, +- 214, 215, 219, 5, 202, 203, 204, 197, +- 197, 35, 217, 197, 197, 206, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 207, 197, 210, 197, 275, +- 197, 256, 256, 5, 202, 203, 204, 197, +- 197, 197, 212, 197, 210, 197, 210, 197, +- 197, 197, 197, 197, 197, 202, 203, 204, +- 197, 197, 197, 212, 197, 210, 197, 210, +- 197, 197, 197, 197, 276, 197, 202, 203, +- 204, 197, 197, 197, 212, 197, 210, 197, +- 210, 197, 275, 197, 197, 197, 197, 202, +- 203, 204, 197, 197, 197, 212, 197, 210, +- 197, 210, 2, 197, 197, 18, 211, 197, +- 202, 203, 204, 197, 197, 197, 212, 197, +- 210, 197, 198, 199, 209, 209, 5, 202, +- 203, 204, 197, 197, 197, 205, 197, 197, +- 206, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 207, 197, +- 198, 199, 200, 209, 5, 202, 203, 204, +- 197, 197, 37, 205, 197, 197, 206, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 207, 197, 278, 279, +- 280, 281, 43, 282, 283, 284, 277, 277, +- 75, 285, 277, 277, 286, 277, 277, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 287, 277, 288, 279, 289, 281, +- 43, 282, 283, 284, 277, 277, 277, 285, +- 277, 277, 286, 277, 277, 277, 277, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 287, 277, 279, 289, 281, 43, 282, 283, +- 284, 277, 277, 277, 285, 277, 277, 286, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 277, 277, 277, 287, 277, 290, +- 277, 277, 277, 56, 291, 277, 282, 283, +- 284, 277, 277, 277, 292, 277, 290, 277, +- 293, 294, 295, 296, 43, 282, 283, 284, +- 277, 277, 73, 297, 277, 277, 286, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 277, 277, 287, 277, 298, 294, +- 299, 299, 43, 282, 283, 284, 277, 277, +- 277, 297, 277, 277, 286, 277, 277, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 287, 277, 294, 299, 299, 43, +- 282, 283, 284, 277, 277, 277, 297, 277, +- 277, 286, 277, 277, 277, 277, 277, 277, +- 277, 277, 277, 277, 277, 277, 277, 287, +- 277, 300, 277, 277, 277, 56, 301, 277, +- 282, 283, 284, 277, 277, 277, 292, 277, +- 300, 277, 302, 303, 304, 305, 43, 282, +- 283, 284, 277, 277, 71, 306, 277, 277, +- 286, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 277, 277, 277, 277, 287, 277, +- 307, 303, 308, 308, 43, 282, 283, 284, +- 277, 277, 277, 306, 277, 277, 286, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 277, 277, 287, 277, 303, 308, +- 308, 43, 282, 283, 284, 277, 277, 277, +- 306, 277, 277, 286, 277, 277, 277, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 287, 277, 309, 277, 277, 277, 56, +- 310, 277, 282, 283, 284, 277, 277, 277, +- 292, 277, 309, 277, 311, 312, 313, 314, +- 43, 282, 283, 284, 277, 277, 69, 315, +- 277, 277, 286, 277, 277, 277, 277, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 287, 277, 316, 312, 317, 317, 43, 282, +- 283, 284, 277, 277, 277, 315, 277, 277, +- 286, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 277, 277, 277, 277, 287, 277, +- 312, 317, 317, 43, 282, 283, 284, 277, +- 277, 277, 315, 277, 277, 286, 277, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 277, 287, 277, 318, 277, 277, +- 277, 56, 319, 277, 282, 283, 284, 277, +- 277, 277, 292, 277, 318, 277, 320, 321, +- 322, 323, 43, 282, 283, 284, 277, 277, +- 67, 324, 277, 277, 286, 277, 277, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 287, 277, 325, 321, 326, 326, +- 43, 282, 283, 284, 277, 277, 277, 324, +- 277, 277, 286, 277, 277, 277, 277, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 287, 277, 321, 326, 326, 43, 282, 283, +- 284, 277, 277, 277, 324, 277, 277, 286, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 277, 277, 277, 287, 277, 56, +- 327, 277, 282, 283, 284, 277, 277, 277, +- 292, 277, 282, 283, 284, 277, 277, 277, +- 292, 277, 328, 277, 277, 329, 283, 284, +- 277, 283, 284, 277, 330, 277, 283, 331, +- 277, 283, 332, 277, 283, 277, 328, 277, +- 277, 277, 283, 284, 277, 333, 277, 334, +- 335, 277, 282, 283, 284, 277, 277, 41, +- 277, 40, 277, 277, 277, 277, 282, 283, +- 284, 277, 282, 283, 284, 277, 333, 277, +- 277, 277, 277, 282, 283, 284, 277, 333, +- 277, 334, 277, 277, 282, 283, 284, 277, +- 277, 41, 277, 56, 277, 336, 336, 43, +- 282, 283, 284, 277, 277, 277, 292, 277, +- 337, 65, 338, 339, 46, 282, 283, 284, +- 277, 277, 277, 292, 277, 65, 338, 339, +- 46, 282, 283, 284, 277, 277, 277, 292, +- 277, 338, 338, 46, 282, 283, 284, 277, +- 277, 277, 292, 277, 340, 62, 341, 342, +- 49, 282, 283, 284, 277, 277, 277, 292, +- 277, 62, 341, 342, 49, 282, 283, 284, +- 277, 277, 277, 292, 277, 341, 341, 49, +- 282, 283, 284, 277, 277, 277, 292, 277, +- 343, 59, 344, 345, 52, 282, 283, 284, +- 277, 277, 277, 292, 277, 59, 344, 345, +- 52, 282, 283, 284, 277, 277, 277, 292, +- 277, 344, 344, 52, 282, 283, 284, 277, +- 277, 277, 292, 277, 346, 56, 277, 347, +- 277, 282, 283, 284, 277, 277, 277, 292, +- 277, 56, 277, 347, 277, 282, 283, 284, +- 277, 277, 277, 292, 277, 348, 277, 282, +- 283, 284, 277, 277, 277, 292, 277, 56, +- 277, 277, 277, 277, 282, 283, 284, 277, +- 277, 277, 292, 277, 39, 40, 277, 277, +- 56, 327, 277, 282, 283, 284, 277, 277, +- 277, 292, 277, 39, 277, 321, 326, 326, +- 43, 282, 283, 284, 277, 277, 277, 324, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 287, 277, 321, 326, 326, 43, 282, 283, +- 284, 277, 277, 277, 324, 277, 320, 321, +- 326, 326, 43, 282, 283, 284, 277, 277, +- 277, 324, 277, 277, 286, 277, 277, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 287, 277, 320, 321, 322, 326, +- 43, 282, 283, 284, 277, 277, 67, 324, +- 277, 277, 286, 277, 277, 277, 277, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 287, 277, 318, 277, 349, 277, 336, 336, +- 43, 282, 283, 284, 277, 277, 277, 292, +- 277, 318, 277, 318, 277, 277, 277, 277, +- 277, 277, 282, 283, 284, 277, 277, 277, +- 292, 277, 318, 277, 318, 277, 277, 277, +- 277, 350, 277, 282, 283, 284, 277, 277, +- 277, 292, 277, 318, 277, 318, 277, 349, +- 277, 277, 277, 277, 282, 283, 284, 277, +- 277, 277, 292, 277, 318, 277, 318, 40, +- 277, 277, 56, 319, 277, 282, 283, 284, +- 277, 277, 277, 292, 277, 318, 277, 311, +- 312, 317, 317, 43, 282, 283, 284, 277, +- 277, 277, 315, 277, 277, 286, 277, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 277, 287, 277, 311, 312, 313, +- 317, 43, 282, 283, 284, 277, 277, 69, +- 315, 277, 277, 286, 277, 277, 277, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 287, 277, 309, 277, 351, 277, 336, +- 336, 43, 282, 283, 284, 277, 277, 277, +- 292, 277, 309, 277, 309, 277, 277, 277, +- 277, 277, 277, 282, 283, 284, 277, 277, +- 277, 292, 277, 309, 277, 309, 277, 277, +- 277, 277, 352, 277, 282, 283, 284, 277, +- 277, 277, 292, 277, 309, 277, 309, 277, +- 351, 277, 277, 277, 277, 282, 283, 284, +- 277, 277, 277, 292, 277, 309, 277, 309, +- 40, 277, 277, 56, 310, 277, 282, 283, +- 284, 277, 277, 277, 292, 277, 309, 277, +- 302, 303, 308, 308, 43, 282, 283, 284, +- 277, 277, 277, 306, 277, 277, 286, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 277, 277, 287, 277, 302, 303, +- 304, 308, 43, 282, 283, 284, 277, 277, +- 71, 306, 277, 277, 286, 277, 277, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 287, 277, 300, 277, 353, 277, +- 336, 336, 43, 282, 283, 284, 277, 277, +- 277, 292, 277, 300, 277, 300, 277, 277, +- 277, 277, 277, 277, 282, 283, 284, 277, +- 277, 277, 292, 277, 300, 277, 300, 277, +- 277, 277, 277, 354, 277, 282, 283, 284, +- 277, 277, 277, 292, 277, 300, 277, 300, +- 277, 353, 277, 277, 277, 277, 282, 283, +- 284, 277, 277, 277, 292, 277, 300, 277, +- 300, 40, 277, 277, 56, 301, 277, 282, +- 283, 284, 277, 277, 277, 292, 277, 300, +- 277, 293, 294, 299, 299, 43, 282, 283, +- 284, 277, 277, 277, 297, 277, 277, 286, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 277, 277, 277, 287, 277, 293, +- 294, 295, 299, 43, 282, 283, 284, 277, +- 277, 73, 297, 277, 277, 286, 277, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 277, 287, 277, 290, 277, 355, +- 277, 336, 336, 43, 282, 283, 284, 277, +- 277, 277, 292, 277, 290, 277, 290, 277, +- 277, 277, 277, 277, 277, 282, 283, 284, +- 277, 277, 277, 292, 277, 290, 277, 290, +- 277, 277, 277, 277, 356, 277, 282, 283, +- 284, 277, 277, 277, 292, 277, 290, 277, +- 290, 277, 355, 277, 277, 277, 277, 282, +- 283, 284, 277, 277, 277, 292, 277, 290, +- 277, 74, 42, 42, 43, 277, 277, 277, +- 277, 277, 277, 74, 277, 290, 40, 277, +- 277, 56, 291, 277, 282, 283, 284, 277, +- 277, 277, 292, 277, 290, 277, 278, 279, +- 289, 281, 43, 282, 283, 284, 277, 277, +- 277, 285, 277, 277, 286, 277, 277, 277, +- 277, 277, 277, 277, 277, 277, 277, 277, +- 277, 277, 287, 277, 358, 184, 359, 359, +- 81, 187, 188, 189, 357, 357, 357, 191, +- 357, 357, 194, 357, 357, 357, 357, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 196, 357, 184, 359, 359, 81, 187, 188, +- 189, 357, 357, 357, 191, 357, 357, 194, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 357, 357, 357, 357, 357, 196, 357, 360, +- 357, 357, 357, 95, 361, 357, 187, 188, +- 189, 357, 357, 357, 362, 357, 360, 357, +- 363, 364, 365, 366, 81, 187, 188, 189, +- 357, 357, 112, 367, 357, 357, 194, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 357, 357, 357, 357, 196, 357, 368, 364, +- 369, 369, 81, 187, 188, 189, 357, 357, +- 357, 367, 357, 357, 194, 357, 357, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 357, 357, 196, 357, 364, 369, 369, 81, +- 187, 188, 189, 357, 357, 357, 367, 357, +- 357, 194, 357, 357, 357, 357, 357, 357, +- 357, 357, 357, 357, 357, 357, 357, 196, +- 357, 370, 357, 357, 357, 95, 371, 357, +- 187, 188, 189, 357, 357, 357, 362, 357, +- 370, 357, 372, 373, 374, 375, 81, 187, +- 188, 189, 357, 357, 110, 376, 357, 357, +- 194, 357, 357, 357, 357, 357, 357, 357, +- 357, 357, 357, 357, 357, 357, 196, 357, +- 377, 373, 378, 378, 81, 187, 188, 189, +- 357, 357, 357, 376, 357, 357, 194, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 357, 357, 357, 357, 196, 357, 373, 378, +- 378, 81, 187, 188, 189, 357, 357, 357, +- 376, 357, 357, 194, 357, 357, 357, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 357, 196, 357, 379, 357, 357, 357, 95, +- 380, 357, 187, 188, 189, 357, 357, 357, +- 362, 357, 379, 357, 381, 382, 383, 384, +- 81, 187, 188, 189, 357, 357, 108, 385, +- 357, 357, 194, 357, 357, 357, 357, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 196, 357, 386, 382, 387, 387, 81, 187, +- 188, 189, 357, 357, 357, 385, 357, 357, +- 194, 357, 357, 357, 357, 357, 357, 357, +- 357, 357, 357, 357, 357, 357, 196, 357, +- 382, 387, 387, 81, 187, 188, 189, 357, +- 357, 357, 385, 357, 357, 194, 357, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 357, 357, 357, 196, 357, 388, 357, 357, +- 357, 95, 389, 357, 187, 188, 189, 357, +- 357, 357, 362, 357, 388, 357, 390, 391, +- 392, 393, 81, 187, 188, 189, 357, 357, +- 106, 394, 357, 357, 194, 357, 357, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 357, 357, 196, 357, 395, 391, 396, 396, +- 81, 187, 188, 189, 357, 357, 357, 394, +- 357, 357, 194, 357, 357, 357, 357, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 196, 357, 391, 396, 396, 81, 187, 188, +- 189, 357, 357, 357, 394, 357, 357, 194, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 357, 357, 357, 357, 357, 196, 357, 95, +- 397, 357, 187, 188, 189, 357, 357, 357, +- 362, 357, 187, 188, 189, 357, 357, 357, +- 362, 357, 398, 357, 357, 399, 188, 189, +- 357, 188, 189, 357, 400, 357, 188, 401, +- 357, 188, 402, 357, 188, 357, 398, 357, +- 357, 357, 188, 189, 357, 403, 357, 404, +- 405, 357, 187, 188, 189, 357, 357, 79, +- 357, 78, 357, 357, 357, 357, 187, 188, +- 189, 357, 187, 188, 189, 357, 403, 357, +- 357, 357, 357, 187, 188, 189, 357, 403, +- 357, 404, 357, 357, 187, 188, 189, 357, +- 357, 79, 357, 95, 357, 406, 406, 81, +- 187, 188, 189, 357, 357, 357, 362, 357, +- 407, 104, 408, 409, 85, 187, 188, 189, +- 357, 357, 357, 362, 357, 104, 408, 409, +- 85, 187, 188, 189, 357, 357, 357, 362, +- 357, 408, 408, 85, 187, 188, 189, 357, +- 357, 357, 362, 357, 410, 101, 411, 412, +- 88, 187, 188, 189, 357, 357, 357, 362, +- 357, 101, 411, 412, 88, 187, 188, 189, +- 357, 357, 357, 362, 357, 411, 411, 88, +- 187, 188, 189, 357, 357, 357, 362, 357, +- 413, 98, 414, 415, 91, 187, 188, 189, +- 357, 357, 357, 362, 357, 98, 414, 415, +- 91, 187, 188, 189, 357, 357, 357, 362, +- 357, 414, 414, 91, 187, 188, 189, 357, +- 357, 357, 362, 357, 416, 95, 357, 417, +- 357, 187, 188, 189, 357, 357, 357, 362, +- 357, 95, 357, 417, 357, 187, 188, 189, +- 357, 357, 357, 362, 357, 418, 357, 187, +- 188, 189, 357, 357, 357, 362, 357, 95, +- 357, 357, 357, 357, 187, 188, 189, 357, +- 357, 357, 362, 357, 77, 78, 357, 357, +- 95, 397, 357, 187, 188, 189, 357, 357, +- 357, 362, 357, 77, 357, 391, 396, 396, +- 81, 187, 188, 189, 357, 357, 357, 394, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 196, 357, 391, 396, 396, 81, 187, 188, +- 189, 357, 357, 357, 394, 357, 390, 391, +- 396, 396, 81, 187, 188, 189, 357, 357, +- 357, 394, 357, 357, 194, 357, 357, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 357, 357, 196, 357, 390, 391, 392, 396, +- 81, 187, 188, 189, 357, 357, 106, 394, +- 357, 357, 194, 357, 357, 357, 357, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 196, 357, 388, 357, 419, 357, 406, 406, +- 81, 187, 188, 189, 357, 357, 357, 362, +- 357, 388, 357, 388, 357, 357, 357, 357, +- 357, 357, 187, 188, 189, 357, 357, 357, +- 362, 357, 388, 357, 388, 357, 357, 357, +- 357, 420, 357, 187, 188, 189, 357, 357, +- 357, 362, 357, 388, 357, 388, 357, 419, +- 357, 357, 357, 357, 187, 188, 189, 357, +- 357, 357, 362, 357, 388, 357, 388, 78, +- 357, 357, 95, 389, 357, 187, 188, 189, +- 357, 357, 357, 362, 357, 388, 357, 381, +- 382, 387, 387, 81, 187, 188, 189, 357, +- 357, 357, 385, 357, 357, 194, 357, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 357, 357, 357, 196, 357, 381, 382, 383, +- 387, 81, 187, 188, 189, 357, 357, 108, +- 385, 357, 357, 194, 357, 357, 357, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 357, 196, 357, 379, 357, 421, 357, 406, +- 406, 81, 187, 188, 189, 357, 357, 357, +- 362, 357, 379, 357, 379, 357, 357, 357, +- 357, 357, 357, 187, 188, 189, 357, 357, +- 357, 362, 357, 379, 357, 379, 357, 357, +- 357, 357, 422, 357, 187, 188, 189, 357, +- 357, 357, 362, 357, 379, 357, 379, 357, +- 421, 357, 357, 357, 357, 187, 188, 189, +- 357, 357, 357, 362, 357, 379, 357, 379, +- 78, 357, 357, 95, 380, 357, 187, 188, +- 189, 357, 357, 357, 362, 357, 379, 357, +- 372, 373, 378, 378, 81, 187, 188, 189, +- 357, 357, 357, 376, 357, 357, 194, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 357, 357, 357, 357, 196, 357, 372, 373, +- 374, 378, 81, 187, 188, 189, 357, 357, +- 110, 376, 357, 357, 194, 357, 357, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 357, 357, 196, 357, 370, 357, 423, 357, +- 406, 406, 81, 187, 188, 189, 357, 357, +- 357, 362, 357, 370, 357, 370, 357, 357, +- 357, 357, 357, 357, 187, 188, 189, 357, +- 357, 357, 362, 357, 370, 357, 370, 357, +- 357, 357, 357, 424, 357, 187, 188, 189, +- 357, 357, 357, 362, 357, 370, 357, 370, +- 357, 423, 357, 357, 357, 357, 187, 188, +- 189, 357, 357, 357, 362, 357, 370, 357, +- 370, 78, 357, 357, 95, 371, 357, 187, +- 188, 189, 357, 357, 357, 362, 357, 370, +- 357, 363, 364, 369, 369, 81, 187, 188, +- 189, 357, 357, 357, 367, 357, 357, 194, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 357, 357, 357, 357, 357, 196, 357, 363, +- 364, 365, 369, 81, 187, 188, 189, 357, +- 357, 112, 367, 357, 357, 194, 357, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 357, 357, 357, 196, 357, 360, 357, 425, +- 357, 406, 406, 81, 187, 188, 189, 357, +- 357, 357, 362, 357, 360, 357, 360, 357, +- 357, 357, 357, 357, 357, 187, 188, 189, +- 357, 357, 357, 362, 357, 360, 357, 360, +- 357, 357, 357, 357, 426, 357, 187, 188, +- 189, 357, 357, 357, 362, 357, 360, 357, +- 360, 357, 425, 357, 357, 357, 357, 187, +- 188, 189, 357, 357, 357, 362, 357, 360, +- 357, 360, 78, 357, 357, 95, 361, 357, +- 187, 188, 189, 357, 357, 357, 362, 357, +- 360, 357, 113, 80, 80, 81, 427, 427, +- 427, 427, 427, 152, 113, 427, 183, 184, +- 359, 359, 81, 187, 188, 189, 357, 357, +- 357, 191, 357, 357, 194, 357, 357, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 357, 357, 196, 357, 113, 80, 80, 81, +- 427, 427, 427, 427, 427, 427, 113, 427, +- 429, 430, 431, 432, 119, 433, 434, 435, +- 428, 428, 151, 436, 428, 428, 437, 428, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 438, 428, 439, 430, +- 432, 432, 119, 433, 434, 435, 428, 428, +- 428, 436, 428, 428, 437, 428, 428, 428, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 438, 428, 430, 432, 432, 119, +- 433, 434, 435, 428, 428, 428, 436, 428, +- 428, 437, 428, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 428, 428, 428, 438, +- 428, 440, 428, 428, 428, 132, 441, 428, +- 433, 434, 435, 428, 428, 428, 442, 428, +- 440, 428, 443, 444, 445, 446, 119, 433, +- 434, 435, 428, 428, 149, 447, 428, 428, +- 437, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 428, 428, 438, 428, +- 448, 444, 449, 449, 119, 433, 434, 435, +- 428, 428, 428, 447, 428, 428, 437, 428, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 438, 428, 444, 449, +- 449, 119, 433, 434, 435, 428, 428, 428, +- 447, 428, 428, 437, 428, 428, 428, 428, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 428, 438, 428, 450, 428, 428, 428, 132, +- 451, 428, 433, 434, 435, 428, 428, 428, +- 442, 428, 450, 428, 452, 453, 454, 455, +- 119, 433, 434, 435, 428, 428, 147, 456, +- 428, 428, 437, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 438, 428, 457, 453, 458, 458, 119, 433, +- 434, 435, 428, 428, 428, 456, 428, 428, +- 437, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 428, 428, 438, 428, +- 453, 458, 458, 119, 433, 434, 435, 428, +- 428, 428, 456, 428, 428, 437, 428, 428, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 428, 438, 428, 459, 428, 428, +- 428, 132, 460, 428, 433, 434, 435, 428, +- 428, 428, 442, 428, 459, 428, 461, 462, +- 463, 464, 119, 433, 434, 435, 428, 428, +- 145, 465, 428, 428, 437, 428, 428, 428, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 438, 428, 466, 462, 467, 467, +- 119, 433, 434, 435, 428, 428, 428, 465, +- 428, 428, 437, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 438, 428, 462, 467, 467, 119, 433, 434, +- 435, 428, 428, 428, 465, 428, 428, 437, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 428, 438, 428, 468, +- 428, 428, 428, 132, 469, 428, 433, 434, +- 435, 428, 428, 428, 442, 428, 468, 428, +- 470, 471, 472, 473, 119, 433, 434, 435, +- 428, 428, 143, 474, 428, 428, 437, 428, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 438, 428, 475, 471, +- 476, 476, 119, 433, 434, 435, 428, 428, +- 428, 474, 428, 428, 437, 428, 428, 428, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 438, 428, 471, 476, 476, 119, +- 433, 434, 435, 428, 428, 428, 474, 428, +- 428, 437, 428, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 428, 428, 428, 438, +- 428, 132, 477, 428, 433, 434, 435, 428, +- 428, 428, 442, 428, 433, 434, 435, 428, +- 428, 428, 442, 428, 478, 428, 428, 479, +- 434, 435, 428, 434, 435, 428, 480, 428, +- 434, 481, 428, 434, 482, 428, 434, 428, +- 478, 428, 428, 428, 434, 435, 428, 483, +- 428, 484, 485, 428, 433, 434, 435, 428, +- 428, 117, 428, 116, 428, 428, 428, 428, +- 433, 434, 435, 428, 433, 434, 435, 428, +- 483, 428, 428, 428, 428, 433, 434, 435, +- 428, 483, 428, 484, 428, 428, 433, 434, +- 435, 428, 428, 117, 428, 132, 428, 486, +- 486, 119, 433, 434, 435, 428, 428, 428, +- 442, 428, 487, 141, 488, 489, 122, 433, +- 434, 435, 428, 428, 428, 442, 428, 141, +- 488, 489, 122, 433, 434, 435, 428, 428, +- 428, 442, 428, 488, 488, 122, 433, 434, +- 435, 428, 428, 428, 442, 428, 490, 138, +- 491, 492, 125, 433, 434, 435, 428, 428, +- 428, 442, 428, 138, 491, 492, 125, 433, +- 434, 435, 428, 428, 428, 442, 428, 491, +- 491, 125, 433, 434, 435, 428, 428, 428, +- 442, 428, 493, 135, 494, 495, 128, 433, +- 434, 435, 428, 428, 428, 442, 428, 135, +- 494, 495, 128, 433, 434, 435, 428, 428, +- 428, 442, 428, 494, 494, 128, 433, 434, +- 435, 428, 428, 428, 442, 428, 496, 132, +- 428, 497, 428, 433, 434, 435, 428, 428, +- 428, 442, 428, 132, 428, 497, 428, 433, +- 434, 435, 428, 428, 428, 442, 428, 498, +- 428, 433, 434, 435, 428, 428, 428, 442, +- 428, 132, 428, 428, 428, 428, 433, 434, +- 435, 428, 428, 428, 442, 428, 115, 116, +- 428, 428, 132, 477, 428, 433, 434, 435, +- 428, 428, 428, 442, 428, 115, 428, 471, +- 476, 476, 119, 433, 434, 435, 428, 428, +- 428, 474, 428, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 438, 428, 471, 476, 476, 119, +- 433, 434, 435, 428, 428, 428, 474, 428, +- 470, 471, 476, 476, 119, 433, 434, 435, +- 428, 428, 428, 474, 428, 428, 437, 428, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 438, 428, 470, 471, +- 472, 476, 119, 433, 434, 435, 428, 428, +- 143, 474, 428, 428, 437, 428, 428, 428, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 438, 428, 468, 428, 499, 428, +- 486, 486, 119, 433, 434, 435, 428, 428, +- 428, 442, 428, 468, 428, 468, 428, 428, +- 428, 428, 428, 428, 433, 434, 435, 428, +- 428, 428, 442, 428, 468, 428, 468, 428, +- 428, 428, 428, 500, 428, 433, 434, 435, +- 428, 428, 428, 442, 428, 468, 428, 468, +- 428, 499, 428, 428, 428, 428, 433, 434, +- 435, 428, 428, 428, 442, 428, 468, 428, +- 468, 116, 428, 428, 132, 469, 428, 433, +- 434, 435, 428, 428, 428, 442, 428, 468, +- 428, 461, 462, 467, 467, 119, 433, 434, +- 435, 428, 428, 428, 465, 428, 428, 437, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 428, 438, 428, 461, +- 462, 463, 467, 119, 433, 434, 435, 428, +- 428, 145, 465, 428, 428, 437, 428, 428, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 428, 438, 428, 459, 428, 501, +- 428, 486, 486, 119, 433, 434, 435, 428, +- 428, 428, 442, 428, 459, 428, 459, 428, +- 428, 428, 428, 428, 428, 433, 434, 435, +- 428, 428, 428, 442, 428, 459, 428, 459, +- 428, 428, 428, 428, 502, 428, 433, 434, +- 435, 428, 428, 428, 442, 428, 459, 428, +- 459, 428, 501, 428, 428, 428, 428, 433, +- 434, 435, 428, 428, 428, 442, 428, 459, +- 428, 459, 116, 428, 428, 132, 460, 428, +- 433, 434, 435, 428, 428, 428, 442, 428, +- 459, 428, 452, 453, 458, 458, 119, 433, +- 434, 435, 428, 428, 428, 456, 428, 428, +- 437, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 428, 428, 438, 428, +- 452, 453, 454, 458, 119, 433, 434, 435, +- 428, 428, 147, 456, 428, 428, 437, 428, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 438, 428, 450, 428, +- 503, 428, 486, 486, 119, 433, 434, 435, +- 428, 428, 428, 442, 428, 450, 428, 450, +- 428, 428, 428, 428, 428, 428, 433, 434, +- 435, 428, 428, 428, 442, 428, 450, 428, +- 450, 428, 428, 428, 428, 504, 428, 433, +- 434, 435, 428, 428, 428, 442, 428, 450, +- 428, 450, 428, 503, 428, 428, 428, 428, +- 433, 434, 435, 428, 428, 428, 442, 428, +- 450, 428, 450, 116, 428, 428, 132, 451, +- 428, 433, 434, 435, 428, 428, 428, 442, +- 428, 450, 428, 443, 444, 449, 449, 119, +- 433, 434, 435, 428, 428, 428, 447, 428, +- 428, 437, 428, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 428, 428, 428, 438, +- 428, 443, 444, 445, 449, 119, 433, 434, +- 435, 428, 428, 149, 447, 428, 428, 437, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 428, 438, 428, 440, +- 428, 505, 428, 486, 486, 119, 433, 434, +- 435, 428, 428, 428, 442, 428, 440, 428, +- 440, 428, 428, 428, 428, 428, 428, 433, +- 434, 435, 428, 428, 428, 442, 428, 440, +- 428, 440, 428, 428, 428, 428, 506, 428, +- 433, 434, 435, 428, 428, 428, 442, 428, +- 440, 428, 440, 428, 505, 428, 428, 428, +- 428, 433, 434, 435, 428, 428, 428, 442, +- 428, 440, 428, 440, 116, 428, 428, 132, +- 441, 428, 433, 434, 435, 428, 428, 428, +- 442, 428, 440, 428, 429, 430, 432, 432, +- 119, 433, 434, 435, 428, 428, 428, 436, +- 428, 428, 437, 428, 428, 428, 428, 428, +- 428, 428, 428, 428, 428, 428, 428, 428, +- 438, 428, 181, 182, 183, 184, 507, 359, +- 81, 187, 188, 189, 190, 190, 152, 191, +- 357, 181, 194, 357, 357, 357, 357, 357, +- 357, 357, 357, 357, 357, 357, 357, 357, +- 196, 357, 198, 508, 200, 201, 5, 202, +- 203, 204, 197, 197, 37, 205, 197, 197, +- 206, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 207, 197, +- 210, 182, 183, 184, 509, 510, 81, 511, +- 512, 513, 197, 190, 152, 514, 197, 210, +- 194, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 196, 197, +- 113, 80, 80, 81, 202, 203, 204, 197, +- 197, 152, 515, 197, 516, 2, 357, 357, +- 357, 426, 357, 187, 188, 189, 357, 357, +- 357, 362, 357, 516, 357, 517, 364, 518, +- 519, 81, 511, 512, 513, 197, 197, 153, +- 367, 197, 197, 194, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 196, 197, 520, 364, 369, 369, 81, +- 511, 512, 513, 197, 197, 197, 367, 197, +- 197, 194, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 196, +- 197, 364, 369, 369, 81, 511, 512, 513, +- 197, 197, 197, 367, 197, 197, 194, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 196, 197, 521, 197, +- 197, 522, 512, 513, 197, 512, 513, 197, +- 250, 197, 512, 523, 197, 512, 524, 197, +- 512, 197, 521, 197, 197, 197, 512, 513, +- 197, 517, 364, 369, 369, 81, 511, 512, +- 513, 197, 197, 197, 367, 197, 197, 194, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 197, 197, 196, 197, 517, +- 364, 518, 369, 81, 511, 512, 513, 197, +- 197, 153, 367, 197, 197, 194, 197, 197, +- 197, 197, 197, 197, 197, 197, 197, 197, +- 197, 197, 197, 196, 197, 210, 197, 275, +- 113, 525, 525, 155, 202, 203, 204, 197, +- 197, 197, 515, 197, 210, 197, 526, 179, +- 527, 528, 157, 511, 512, 513, 197, 197, +- 197, 529, 197, 179, 527, 528, 157, 511, +- 512, 513, 197, 197, 197, 529, 197, 527, +- 527, 157, 511, 512, 513, 197, 197, 197, +- 529, 197, 530, 176, 531, 532, 160, 511, +- 512, 513, 197, 197, 197, 529, 197, 176, +- 531, 532, 160, 511, 512, 513, 197, 197, +- 197, 529, 197, 531, 531, 160, 511, 512, +- 513, 197, 197, 197, 529, 197, 533, 173, +- 534, 535, 163, 511, 512, 513, 197, 197, +- 197, 529, 197, 173, 534, 535, 163, 511, +- 512, 513, 197, 197, 197, 529, 197, 534, +- 534, 163, 511, 512, 513, 197, 197, 197, +- 529, 197, 536, 170, 197, 537, 197, 511, +- 512, 513, 197, 197, 197, 529, 197, 170, +- 197, 537, 197, 511, 512, 513, 197, 197, +- 197, 529, 197, 511, 512, 513, 197, 197, +- 197, 529, 197, 538, 197, 539, 540, 197, +- 511, 512, 513, 197, 197, 167, 197, 166, +- 197, 197, 197, 197, 511, 512, 513, 197, +- 511, 512, 513, 197, 538, 197, 197, 197, +- 197, 511, 512, 513, 197, 538, 197, 539, +- 197, 197, 511, 512, 513, 197, 197, 167, +- 197, 516, 166, 357, 357, 95, 361, 357, +- 187, 188, 189, 357, 357, 357, 362, 357, +- 516, 357, 542, 541, 541, 541, 541, 543, +- 544, 545, 541, 543, 544, 545, 541, 546, +- 541, 541, 547, 544, 545, 541, 544, 545, +- 541, 548, 541, 544, 549, 541, 544, 550, +- 541, 544, 541, 546, 541, 541, 541, 544, +- 545, 541, 0 ++ 1, 0, 2, 3, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 2, 0, 1, 0, 0, 0, 0, ++ 4, 0, 5, 5, 6, 1, 0, 7, ++ 7, 6, 0, 6, 0, 8, 8, 9, ++ 1, 0, 10, 10, 9, 0, 9, 0, ++ 11, 11, 12, 1, 0, 13, 13, 12, ++ 0, 12, 0, 14, 14, 15, 1, 0, ++ 16, 16, 15, 0, 15, 0, 17, 0, ++ 0, 0, 1, 0, 18, 0, 19, 0, ++ 20, 14, 14, 15, 1, 0, 21, 0, ++ 22, 0, 23, 11, 11, 12, 1, 0, ++ 24, 0, 25, 0, 26, 8, 8, 9, ++ 1, 0, 27, 0, 28, 0, 29, 5, ++ 5, 6, 1, 0, 0, 0, 0, 0, ++ 29, 0, 29, 5, 5, 6, 1, 0, ++ 0, 0, 0, 30, 29, 0, 31, 5, ++ 5, 6, 1, 0, 0, 0, 0, 0, ++ 31, 0, 31, 5, 5, 6, 1, 0, ++ 0, 0, 0, 32, 31, 0, 33, 5, ++ 5, 6, 1, 0, 0, 0, 0, 0, ++ 33, 0, 33, 5, 5, 6, 1, 0, ++ 0, 0, 0, 34, 33, 0, 35, 5, ++ 5, 6, 1, 0, 0, 0, 0, 0, ++ 35, 0, 35, 5, 5, 6, 1, 0, ++ 0, 0, 0, 36, 35, 0, 37, 5, ++ 5, 6, 1, 0, 0, 0, 0, 0, ++ 37, 0, 37, 5, 5, 6, 1, 0, ++ 0, 0, 0, 38, 37, 0, 40, 39, ++ 41, 42, 39, 39, 39, 39, 39, 39, ++ 39, 39, 39, 39, 39, 39, 39, 41, ++ 39, 40, 39, 39, 39, 39, 43, 39, ++ 44, 44, 45, 40, 39, 46, 46, 45, ++ 39, 45, 39, 47, 47, 48, 40, 39, ++ 49, 49, 48, 39, 48, 39, 50, 50, ++ 51, 40, 39, 52, 52, 51, 39, 51, ++ 39, 53, 53, 54, 40, 39, 55, 55, ++ 54, 39, 54, 39, 56, 39, 39, 39, ++ 40, 39, 57, 39, 58, 39, 59, 53, ++ 53, 54, 40, 39, 60, 39, 61, 39, ++ 62, 50, 50, 51, 40, 39, 63, 39, ++ 64, 39, 65, 47, 47, 48, 40, 39, ++ 66, 39, 67, 39, 68, 44, 44, 45, ++ 40, 39, 39, 39, 39, 39, 68, 39, ++ 68, 44, 44, 45, 40, 39, 39, 39, ++ 39, 69, 68, 39, 70, 44, 44, 45, ++ 40, 39, 39, 39, 39, 39, 70, 39, ++ 70, 44, 44, 45, 40, 39, 39, 39, ++ 39, 71, 70, 39, 72, 44, 44, 45, ++ 40, 39, 39, 39, 39, 39, 72, 39, ++ 72, 44, 44, 45, 40, 39, 39, 39, ++ 39, 73, 72, 39, 74, 44, 44, 45, ++ 40, 39, 39, 39, 39, 39, 74, 39, ++ 74, 44, 44, 45, 40, 39, 39, 39, ++ 39, 75, 74, 39, 76, 44, 44, 45, ++ 40, 39, 39, 39, 39, 39, 76, 39, ++ 76, 44, 44, 45, 40, 39, 39, 39, ++ 39, 77, 76, 39, 79, 78, 80, 81, ++ 78, 78, 78, 78, 78, 78, 78, 78, ++ 78, 78, 78, 78, 78, 80, 78, 79, ++ 78, 78, 78, 78, 82, 78, 83, 83, ++ 84, 79, 78, 86, 86, 84, 85, 84, ++ 85, 87, 87, 88, 79, 78, 89, 89, ++ 88, 78, 88, 78, 90, 90, 91, 79, ++ 78, 92, 92, 91, 78, 91, 78, 93, ++ 93, 94, 79, 78, 95, 95, 94, 78, ++ 94, 78, 96, 78, 78, 78, 79, 78, ++ 97, 78, 98, 78, 99, 93, 93, 94, ++ 79, 78, 100, 78, 101, 78, 102, 90, ++ 90, 91, 79, 78, 103, 78, 104, 78, ++ 105, 87, 87, 88, 79, 78, 106, 78, ++ 107, 78, 108, 83, 83, 84, 79, 78, ++ 78, 78, 78, 78, 108, 78, 108, 83, ++ 83, 84, 79, 78, 78, 78, 78, 109, ++ 108, 78, 110, 83, 83, 84, 79, 78, ++ 78, 78, 78, 78, 110, 78, 110, 83, ++ 83, 84, 79, 78, 78, 78, 78, 111, ++ 110, 78, 112, 83, 83, 84, 79, 78, ++ 78, 78, 78, 78, 112, 78, 112, 83, ++ 83, 84, 79, 78, 78, 78, 78, 113, ++ 112, 78, 114, 83, 83, 84, 79, 78, ++ 78, 78, 78, 78, 114, 78, 114, 83, ++ 83, 84, 79, 78, 78, 78, 78, 115, ++ 114, 78, 116, 83, 83, 84, 79, 78, ++ 78, 78, 78, 78, 116, 78, 118, 117, ++ 119, 120, 117, 117, 117, 117, 117, 117, ++ 117, 117, 117, 117, 117, 117, 117, 119, ++ 117, 118, 117, 117, 117, 117, 121, 117, ++ 122, 122, 123, 118, 117, 124, 124, 123, ++ 117, 123, 117, 125, 125, 126, 118, 117, ++ 127, 127, 126, 117, 126, 117, 128, 128, ++ 129, 118, 117, 130, 130, 129, 117, 129, ++ 117, 131, 131, 132, 118, 117, 133, 133, ++ 132, 117, 132, 117, 134, 117, 117, 117, ++ 118, 117, 135, 117, 136, 117, 137, 131, ++ 131, 132, 118, 117, 138, 117, 139, 117, ++ 140, 128, 128, 129, 118, 117, 141, 117, ++ 142, 117, 143, 125, 125, 126, 118, 117, ++ 144, 117, 145, 117, 146, 122, 122, 123, ++ 118, 117, 117, 117, 117, 117, 146, 117, ++ 146, 122, 122, 123, 118, 117, 117, 117, ++ 117, 147, 146, 117, 148, 122, 122, 123, ++ 118, 117, 117, 117, 117, 117, 148, 117, ++ 148, 122, 122, 123, 118, 117, 117, 117, ++ 117, 149, 148, 117, 150, 122, 122, 123, ++ 118, 117, 117, 117, 117, 117, 150, 117, ++ 150, 122, 122, 123, 118, 117, 117, 117, ++ 117, 151, 150, 117, 152, 122, 122, 123, ++ 118, 117, 117, 117, 117, 117, 152, 117, ++ 152, 122, 122, 123, 118, 117, 117, 117, ++ 117, 153, 152, 117, 154, 122, 122, 123, ++ 118, 117, 117, 117, 117, 117, 154, 117, ++ 154, 122, 122, 123, 118, 117, 117, 117, ++ 117, 155, 154, 117, 116, 83, 83, 84, ++ 79, 78, 78, 78, 78, 156, 116, 78, ++ 86, 86, 84, 1, 0, 114, 83, 83, ++ 84, 157, 0, 0, 0, 0, 0, 114, ++ 0, 114, 83, 83, 84, 157, 0, 0, ++ 0, 0, 158, 114, 0, 159, 159, 160, ++ 1, 0, 7, 7, 160, 0, 161, 161, ++ 162, 157, 0, 163, 163, 162, 0, 162, ++ 0, 164, 164, 165, 157, 0, 166, 166, ++ 165, 0, 165, 0, 167, 167, 168, 157, ++ 0, 169, 169, 168, 0, 168, 0, 157, ++ 0, 170, 171, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 170, 0, 157, 0, 0, 0, 0, 172, ++ 0, 173, 0, 0, 0, 157, 0, 174, ++ 0, 175, 0, 176, 167, 167, 168, 157, ++ 0, 177, 0, 178, 0, 179, 164, 164, ++ 165, 157, 0, 180, 0, 181, 0, 182, ++ 161, 161, 162, 157, 0, 183, 0, 184, ++ 0, 186, 185, 188, 189, 190, 191, 192, ++ 193, 84, 79, 194, 195, 196, 196, 156, ++ 197, 198, 199, 200, 201, 187, 187, 187, ++ 187, 187, 187, 187, 187, 187, 187, 187, ++ 187, 202, 187, 204, 205, 206, 207, 6, ++ 1, 208, 209, 203, 203, 38, 210, 203, ++ 203, 211, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 212, ++ 203, 213, 205, 214, 214, 6, 1, 208, ++ 209, 203, 203, 203, 210, 203, 203, 211, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 212, 203, 205, ++ 214, 214, 6, 1, 208, 209, 203, 203, ++ 203, 210, 203, 203, 211, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 212, 203, 215, 203, 203, 203, ++ 19, 216, 203, 1, 208, 209, 203, 203, ++ 203, 217, 203, 215, 203, 218, 219, 220, ++ 221, 6, 1, 208, 209, 203, 203, 36, ++ 222, 203, 203, 211, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 212, 203, 223, 219, 224, 224, 6, ++ 1, 208, 209, 203, 203, 203, 222, 203, ++ 203, 211, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 212, ++ 203, 219, 224, 224, 6, 1, 208, 209, ++ 203, 203, 203, 222, 203, 203, 211, 203, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 212, 203, 225, 203, ++ 203, 203, 19, 226, 203, 1, 208, 209, ++ 203, 203, 203, 217, 203, 225, 203, 227, ++ 228, 229, 230, 6, 1, 208, 209, 203, ++ 203, 34, 231, 203, 203, 211, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 212, 203, 232, 228, 233, ++ 233, 6, 1, 208, 209, 203, 203, 203, ++ 231, 203, 203, 211, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 212, 203, 228, 233, 233, 6, 1, ++ 208, 209, 203, 203, 203, 231, 203, 203, ++ 211, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 212, 203, ++ 234, 203, 203, 203, 19, 235, 203, 1, ++ 208, 209, 203, 203, 203, 217, 203, 234, ++ 203, 236, 237, 238, 239, 6, 1, 208, ++ 209, 203, 203, 32, 240, 203, 203, 211, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 212, 203, 241, ++ 237, 242, 242, 6, 1, 208, 209, 203, ++ 203, 203, 240, 203, 203, 211, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 212, 203, 237, 242, 242, ++ 6, 1, 208, 209, 203, 203, 203, 240, ++ 203, 203, 211, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 212, 203, 243, 203, 203, 203, 19, 244, ++ 203, 1, 208, 209, 203, 203, 203, 217, ++ 203, 243, 203, 245, 246, 247, 248, 6, ++ 1, 208, 209, 203, 203, 30, 249, 203, ++ 203, 211, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 212, ++ 203, 250, 246, 251, 251, 6, 1, 208, ++ 209, 203, 203, 203, 249, 203, 203, 211, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 212, 203, 246, ++ 251, 251, 6, 1, 208, 209, 203, 203, ++ 203, 249, 203, 203, 211, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 212, 203, 19, 252, 203, 1, ++ 208, 209, 203, 203, 203, 217, 203, 253, ++ 253, 203, 1, 208, 209, 203, 203, 203, ++ 217, 203, 254, 203, 203, 255, 208, 209, ++ 203, 208, 209, 203, 256, 203, 208, 257, ++ 203, 208, 258, 203, 208, 203, 254, 203, ++ 203, 203, 208, 209, 203, 259, 203, 260, ++ 261, 203, 1, 208, 209, 203, 203, 4, ++ 203, 3, 203, 253, 253, 203, 1, 208, ++ 209, 203, 253, 253, 203, 1, 208, 209, ++ 203, 259, 203, 253, 253, 203, 1, 208, ++ 209, 203, 259, 203, 260, 253, 203, 1, ++ 208, 209, 203, 203, 4, 203, 19, 203, ++ 262, 262, 6, 1, 208, 209, 203, 203, ++ 203, 217, 203, 263, 28, 264, 265, 9, ++ 1, 208, 209, 203, 203, 203, 217, 203, ++ 28, 264, 265, 9, 1, 208, 209, 203, ++ 203, 203, 217, 203, 264, 264, 9, 1, ++ 208, 209, 203, 203, 203, 217, 203, 266, ++ 25, 267, 268, 12, 1, 208, 209, 203, ++ 203, 203, 217, 203, 25, 267, 268, 12, ++ 1, 208, 209, 203, 203, 203, 217, 203, ++ 267, 267, 12, 1, 208, 209, 203, 203, ++ 203, 217, 203, 269, 22, 270, 271, 15, ++ 1, 208, 209, 203, 203, 203, 217, 203, ++ 22, 270, 271, 15, 1, 208, 209, 203, ++ 203, 203, 217, 203, 270, 270, 15, 1, ++ 208, 209, 203, 203, 203, 217, 203, 272, ++ 19, 253, 273, 203, 1, 208, 209, 203, ++ 203, 203, 217, 203, 19, 253, 273, 203, ++ 1, 208, 209, 203, 203, 203, 217, 203, ++ 253, 274, 203, 1, 208, 209, 203, 203, ++ 203, 217, 203, 19, 203, 253, 253, 203, ++ 1, 208, 209, 203, 203, 203, 217, 203, ++ 2, 3, 203, 203, 19, 252, 203, 1, ++ 208, 209, 203, 203, 203, 217, 203, 2, ++ 203, 246, 251, 251, 6, 1, 208, 209, ++ 203, 203, 203, 249, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 212, 203, 246, 251, ++ 251, 6, 1, 208, 209, 203, 203, 203, ++ 249, 203, 245, 246, 251, 251, 6, 1, ++ 208, 209, 203, 203, 203, 249, 203, 203, ++ 211, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 212, 203, ++ 245, 246, 247, 251, 6, 1, 208, 209, ++ 203, 203, 30, 249, 203, 203, 211, 203, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 212, 203, 243, 203, ++ 275, 203, 262, 262, 6, 1, 208, 209, ++ 203, 203, 203, 217, 203, 243, 203, 243, ++ 203, 203, 203, 253, 253, 203, 1, 208, ++ 209, 203, 203, 203, 217, 203, 243, 203, ++ 243, 203, 203, 203, 253, 276, 203, 1, ++ 208, 209, 203, 203, 203, 217, 203, 243, ++ 203, 243, 203, 275, 203, 253, 253, 203, ++ 1, 208, 209, 203, 203, 203, 217, 203, ++ 243, 203, 243, 3, 203, 203, 19, 244, ++ 203, 1, 208, 209, 203, 203, 203, 217, ++ 203, 243, 203, 236, 237, 242, 242, 6, ++ 1, 208, 209, 203, 203, 203, 240, 203, ++ 203, 211, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 212, ++ 203, 236, 237, 238, 242, 6, 1, 208, ++ 209, 203, 203, 32, 240, 203, 203, 211, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 212, 203, 234, ++ 203, 277, 203, 262, 262, 6, 1, 208, ++ 209, 203, 203, 203, 217, 203, 234, 203, ++ 234, 203, 203, 203, 253, 253, 203, 1, ++ 208, 209, 203, 203, 203, 217, 203, 234, ++ 203, 234, 203, 203, 203, 253, 278, 203, ++ 1, 208, 209, 203, 203, 203, 217, 203, ++ 234, 203, 234, 203, 277, 203, 253, 253, ++ 203, 1, 208, 209, 203, 203, 203, 217, ++ 203, 234, 203, 234, 3, 203, 203, 19, ++ 235, 203, 1, 208, 209, 203, 203, 203, ++ 217, 203, 234, 203, 227, 228, 233, 233, ++ 6, 1, 208, 209, 203, 203, 203, 231, ++ 203, 203, 211, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 212, 203, 227, 228, 229, 233, 6, 1, ++ 208, 209, 203, 203, 34, 231, 203, 203, ++ 211, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 212, 203, ++ 225, 203, 279, 203, 262, 262, 6, 1, ++ 208, 209, 203, 203, 203, 217, 203, 225, ++ 203, 225, 203, 203, 203, 253, 253, 203, ++ 1, 208, 209, 203, 203, 203, 217, 203, ++ 225, 203, 225, 203, 203, 203, 253, 280, ++ 203, 1, 208, 209, 203, 203, 203, 217, ++ 203, 225, 203, 225, 203, 279, 203, 253, ++ 253, 203, 1, 208, 209, 203, 203, 203, ++ 217, 203, 225, 203, 225, 3, 203, 203, ++ 19, 226, 203, 1, 208, 209, 203, 203, ++ 203, 217, 203, 225, 203, 218, 219, 224, ++ 224, 6, 1, 208, 209, 203, 203, 203, ++ 222, 203, 203, 211, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 212, 203, 218, 219, 220, 224, 6, ++ 1, 208, 209, 203, 203, 36, 222, 203, ++ 203, 211, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 212, ++ 203, 215, 203, 281, 203, 262, 262, 6, ++ 1, 208, 209, 203, 203, 203, 217, 203, ++ 215, 203, 215, 203, 203, 203, 253, 253, ++ 203, 1, 208, 209, 203, 203, 203, 217, ++ 203, 215, 203, 215, 203, 203, 203, 253, ++ 282, 203, 1, 208, 209, 203, 203, 203, ++ 217, 203, 215, 203, 215, 203, 281, 203, ++ 253, 253, 203, 1, 208, 209, 203, 203, ++ 203, 217, 203, 215, 203, 215, 3, 203, ++ 203, 19, 216, 203, 1, 208, 209, 203, ++ 203, 203, 217, 203, 215, 203, 204, 205, ++ 214, 214, 6, 1, 208, 209, 203, 203, ++ 203, 210, 203, 203, 211, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 212, 203, 204, 205, 206, 214, ++ 6, 1, 208, 209, 203, 203, 38, 210, ++ 203, 203, 211, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 212, 203, 284, 285, 286, 287, 45, 40, ++ 288, 289, 283, 283, 77, 290, 283, 283, ++ 291, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 283, 283, 292, 283, ++ 293, 285, 294, 287, 45, 40, 288, 289, ++ 283, 283, 283, 290, 283, 283, 291, 283, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 292, 283, 285, 294, ++ 287, 45, 40, 288, 289, 283, 283, 283, ++ 290, 283, 283, 291, 283, 283, 283, 283, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 283, 292, 283, 295, 283, 283, 283, 58, ++ 296, 283, 40, 288, 289, 283, 283, 283, ++ 297, 283, 295, 283, 298, 299, 300, 301, ++ 45, 40, 288, 289, 283, 283, 75, 302, ++ 283, 283, 291, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 292, 283, 303, 299, 304, 304, 45, 40, ++ 288, 289, 283, 283, 283, 302, 283, 283, ++ 291, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 283, 283, 292, 283, ++ 299, 304, 304, 45, 40, 288, 289, 283, ++ 283, 283, 302, 283, 283, 291, 283, 283, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 292, 283, 305, 283, 283, ++ 283, 58, 306, 283, 40, 288, 289, 283, ++ 283, 283, 297, 283, 305, 283, 307, 308, ++ 309, 310, 45, 40, 288, 289, 283, 283, ++ 73, 311, 283, 283, 291, 283, 283, 283, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 292, 283, 312, 308, 313, 313, ++ 45, 40, 288, 289, 283, 283, 283, 311, ++ 283, 283, 291, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 292, 283, 308, 313, 313, 45, 40, 288, ++ 289, 283, 283, 283, 311, 283, 283, 291, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 283, 292, 283, 314, ++ 283, 283, 283, 58, 315, 283, 40, 288, ++ 289, 283, 283, 283, 297, 283, 314, 283, ++ 316, 317, 318, 319, 45, 40, 288, 289, ++ 283, 283, 71, 320, 283, 283, 291, 283, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 292, 283, 321, 317, ++ 322, 322, 45, 40, 288, 289, 283, 283, ++ 283, 320, 283, 283, 291, 283, 283, 283, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 292, 283, 317, 322, 322, 45, ++ 40, 288, 289, 283, 283, 283, 320, 283, ++ 283, 291, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 283, 283, 283, 292, ++ 283, 323, 283, 283, 283, 58, 324, 283, ++ 40, 288, 289, 283, 283, 283, 297, 283, ++ 323, 283, 325, 326, 327, 328, 45, 40, ++ 288, 289, 283, 283, 69, 329, 283, 283, ++ 291, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 283, 283, 292, 283, ++ 330, 326, 331, 331, 45, 40, 288, 289, ++ 283, 283, 283, 329, 283, 283, 291, 283, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 292, 283, 326, 331, ++ 331, 45, 40, 288, 289, 283, 283, 283, ++ 329, 283, 283, 291, 283, 283, 283, 283, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 283, 292, 283, 58, 332, 283, 40, 288, ++ 289, 283, 283, 283, 297, 283, 333, 333, ++ 283, 40, 288, 289, 283, 283, 283, 297, ++ 283, 334, 283, 283, 335, 288, 289, 283, ++ 288, 289, 283, 336, 283, 288, 337, 283, ++ 288, 338, 283, 288, 283, 334, 283, 283, ++ 283, 288, 289, 283, 339, 283, 340, 341, ++ 283, 40, 288, 289, 283, 283, 43, 283, ++ 42, 283, 333, 333, 283, 40, 288, 289, ++ 283, 333, 333, 283, 40, 288, 289, 283, ++ 339, 283, 333, 333, 283, 40, 288, 289, ++ 283, 339, 283, 340, 333, 283, 40, 288, ++ 289, 283, 283, 43, 283, 58, 283, 342, ++ 342, 45, 40, 288, 289, 283, 283, 283, ++ 297, 283, 343, 67, 344, 345, 48, 40, ++ 288, 289, 283, 283, 283, 297, 283, 67, ++ 344, 345, 48, 40, 288, 289, 283, 283, ++ 283, 297, 283, 344, 344, 48, 40, 288, ++ 289, 283, 283, 283, 297, 283, 346, 64, ++ 347, 348, 51, 40, 288, 289, 283, 283, ++ 283, 297, 283, 64, 347, 348, 51, 40, ++ 288, 289, 283, 283, 283, 297, 283, 347, ++ 347, 51, 40, 288, 289, 283, 283, 283, ++ 297, 283, 349, 61, 350, 351, 54, 40, ++ 288, 289, 283, 283, 283, 297, 283, 61, ++ 350, 351, 54, 40, 288, 289, 283, 283, ++ 283, 297, 283, 350, 350, 54, 40, 288, ++ 289, 283, 283, 283, 297, 283, 352, 58, ++ 333, 353, 283, 40, 288, 289, 283, 283, ++ 283, 297, 283, 58, 333, 353, 283, 40, ++ 288, 289, 283, 283, 283, 297, 283, 333, ++ 354, 283, 40, 288, 289, 283, 283, 283, ++ 297, 283, 58, 283, 333, 333, 283, 40, ++ 288, 289, 283, 283, 283, 297, 283, 41, ++ 42, 283, 283, 58, 332, 283, 40, 288, ++ 289, 283, 283, 283, 297, 283, 41, 283, ++ 326, 331, 331, 45, 40, 288, 289, 283, ++ 283, 283, 329, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 292, 283, 326, 331, 331, ++ 45, 40, 288, 289, 283, 283, 283, 329, ++ 283, 325, 326, 331, 331, 45, 40, 288, ++ 289, 283, 283, 283, 329, 283, 283, 291, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 283, 292, 283, 325, ++ 326, 327, 331, 45, 40, 288, 289, 283, ++ 283, 69, 329, 283, 283, 291, 283, 283, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 292, 283, 323, 283, 355, ++ 283, 342, 342, 45, 40, 288, 289, 283, ++ 283, 283, 297, 283, 323, 283, 323, 283, ++ 283, 283, 333, 333, 283, 40, 288, 289, ++ 283, 283, 283, 297, 283, 323, 283, 323, ++ 283, 283, 283, 333, 356, 283, 40, 288, ++ 289, 283, 283, 283, 297, 283, 323, 283, ++ 323, 283, 355, 283, 333, 333, 283, 40, ++ 288, 289, 283, 283, 283, 297, 283, 323, ++ 283, 323, 42, 283, 283, 58, 324, 283, ++ 40, 288, 289, 283, 283, 283, 297, 283, ++ 323, 283, 316, 317, 322, 322, 45, 40, ++ 288, 289, 283, 283, 283, 320, 283, 283, ++ 291, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 283, 283, 292, 283, ++ 316, 317, 318, 322, 45, 40, 288, 289, ++ 283, 283, 71, 320, 283, 283, 291, 283, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 292, 283, 314, 283, ++ 357, 283, 342, 342, 45, 40, 288, 289, ++ 283, 283, 283, 297, 283, 314, 283, 314, ++ 283, 283, 283, 333, 333, 283, 40, 288, ++ 289, 283, 283, 283, 297, 283, 314, 283, ++ 314, 283, 283, 283, 333, 358, 283, 40, ++ 288, 289, 283, 283, 283, 297, 283, 314, ++ 283, 314, 283, 357, 283, 333, 333, 283, ++ 40, 288, 289, 283, 283, 283, 297, 283, ++ 314, 283, 314, 42, 283, 283, 58, 315, ++ 283, 40, 288, 289, 283, 283, 283, 297, ++ 283, 314, 283, 307, 308, 313, 313, 45, ++ 40, 288, 289, 283, 283, 283, 311, 283, ++ 283, 291, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 283, 283, 283, 292, ++ 283, 307, 308, 309, 313, 45, 40, 288, ++ 289, 283, 283, 73, 311, 283, 283, 291, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 283, 292, 283, 305, ++ 283, 359, 283, 342, 342, 45, 40, 288, ++ 289, 283, 283, 283, 297, 283, 305, 283, ++ 305, 283, 283, 283, 333, 333, 283, 40, ++ 288, 289, 283, 283, 283, 297, 283, 305, ++ 283, 305, 283, 283, 283, 333, 360, 283, ++ 40, 288, 289, 283, 283, 283, 297, 283, ++ 305, 283, 305, 283, 359, 283, 333, 333, ++ 283, 40, 288, 289, 283, 283, 283, 297, ++ 283, 305, 283, 305, 42, 283, 283, 58, ++ 306, 283, 40, 288, 289, 283, 283, 283, ++ 297, 283, 305, 283, 298, 299, 304, 304, ++ 45, 40, 288, 289, 283, 283, 283, 302, ++ 283, 283, 291, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 292, 283, 298, 299, 300, 304, 45, 40, ++ 288, 289, 283, 283, 75, 302, 283, 283, ++ 291, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 283, 283, 292, 283, ++ 295, 283, 361, 283, 342, 342, 45, 40, ++ 288, 289, 283, 283, 283, 297, 283, 295, ++ 283, 295, 283, 283, 283, 333, 333, 283, ++ 40, 288, 289, 283, 283, 283, 297, 283, ++ 295, 283, 295, 283, 283, 283, 333, 362, ++ 283, 40, 288, 289, 283, 283, 283, 297, ++ 283, 295, 283, 295, 283, 361, 283, 333, ++ 333, 283, 40, 288, 289, 283, 283, 283, ++ 297, 283, 295, 283, 76, 44, 44, 45, ++ 40, 283, 283, 283, 283, 283, 76, 283, ++ 295, 42, 283, 283, 58, 296, 283, 40, ++ 288, 289, 283, 283, 283, 297, 283, 295, ++ 283, 284, 285, 294, 287, 45, 40, 288, ++ 289, 283, 283, 283, 290, 283, 283, 291, ++ 283, 283, 283, 283, 283, 283, 283, 283, ++ 283, 283, 283, 283, 283, 292, 283, 364, ++ 191, 365, 365, 84, 79, 194, 195, 363, ++ 363, 363, 197, 363, 363, 200, 363, 363, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 202, 363, 191, 365, 365, ++ 84, 79, 194, 195, 363, 363, 363, 197, ++ 363, 363, 200, 363, 363, 363, 363, 363, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 202, 363, 366, 363, 363, 363, 98, 367, ++ 363, 79, 194, 195, 363, 363, 363, 368, ++ 363, 366, 363, 369, 370, 371, 372, 84, ++ 79, 194, 195, 363, 363, 115, 373, 363, ++ 363, 200, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 363, 363, 363, 363, 202, ++ 363, 374, 370, 375, 375, 84, 79, 194, ++ 195, 363, 363, 363, 373, 363, 363, 200, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 363, 363, 202, 363, 370, ++ 375, 375, 84, 79, 194, 195, 363, 363, ++ 363, 373, 363, 363, 200, 363, 363, 363, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 363, 202, 363, 376, 363, 363, 363, ++ 98, 377, 363, 79, 194, 195, 363, 363, ++ 363, 368, 363, 376, 363, 378, 379, 380, ++ 381, 84, 79, 194, 195, 363, 363, 113, ++ 382, 363, 363, 200, 363, 363, 363, 363, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 202, 363, 383, 379, 384, 384, 84, ++ 79, 194, 195, 363, 363, 363, 382, 363, ++ 363, 200, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 363, 363, 363, 363, 202, ++ 363, 379, 384, 384, 84, 79, 194, 195, ++ 363, 363, 363, 382, 363, 363, 200, 363, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 363, 202, 363, 385, 363, ++ 363, 363, 98, 386, 363, 79, 194, 195, ++ 363, 363, 363, 368, 363, 385, 363, 387, ++ 388, 389, 390, 84, 79, 194, 195, 363, ++ 363, 111, 391, 363, 363, 200, 363, 363, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 202, 363, 392, 388, 393, ++ 393, 84, 79, 194, 195, 363, 363, 363, ++ 391, 363, 363, 200, 363, 363, 363, 363, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 202, 363, 388, 393, 393, 84, 79, ++ 194, 195, 363, 363, 363, 391, 363, 363, ++ 200, 363, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 363, 363, 363, 202, 363, ++ 394, 363, 363, 363, 98, 395, 363, 79, ++ 194, 195, 363, 363, 363, 368, 363, 394, ++ 363, 396, 397, 398, 399, 84, 79, 194, ++ 195, 363, 363, 109, 400, 363, 363, 200, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 363, 363, 202, 363, 401, ++ 397, 402, 402, 84, 79, 194, 195, 363, ++ 363, 363, 400, 363, 363, 200, 363, 363, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 202, 363, 397, 402, 402, ++ 84, 79, 194, 195, 363, 363, 363, 400, ++ 363, 363, 200, 363, 363, 363, 363, 363, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 202, 363, 98, 403, 363, 79, 194, 195, ++ 363, 363, 363, 368, 363, 404, 404, 363, ++ 79, 194, 195, 363, 363, 363, 368, 363, ++ 405, 363, 363, 406, 194, 195, 363, 194, ++ 195, 363, 407, 363, 194, 408, 363, 194, ++ 409, 363, 194, 363, 405, 363, 363, 363, ++ 194, 195, 363, 410, 363, 411, 412, 363, ++ 79, 194, 195, 363, 363, 82, 363, 81, ++ 363, 404, 404, 363, 79, 194, 195, 363, ++ 404, 404, 363, 79, 194, 195, 363, 410, ++ 363, 404, 404, 363, 79, 194, 195, 363, ++ 410, 363, 411, 404, 363, 79, 194, 195, ++ 363, 363, 82, 363, 98, 363, 413, 413, ++ 84, 79, 194, 195, 363, 363, 363, 368, ++ 363, 414, 107, 415, 416, 88, 79, 194, ++ 195, 363, 363, 363, 368, 363, 107, 415, ++ 416, 88, 79, 194, 195, 363, 363, 363, ++ 368, 363, 415, 415, 88, 79, 194, 195, ++ 363, 363, 363, 368, 363, 417, 104, 418, ++ 419, 91, 79, 194, 195, 363, 363, 363, ++ 368, 363, 104, 418, 419, 91, 79, 194, ++ 195, 363, 363, 363, 368, 363, 418, 418, ++ 91, 79, 194, 195, 363, 363, 363, 368, ++ 363, 420, 101, 421, 422, 94, 79, 194, ++ 195, 363, 363, 363, 368, 363, 101, 421, ++ 422, 94, 79, 194, 195, 363, 363, 363, ++ 368, 363, 421, 421, 94, 79, 194, 195, ++ 363, 363, 363, 368, 363, 423, 98, 404, ++ 424, 363, 79, 194, 195, 363, 363, 363, ++ 368, 363, 98, 404, 424, 363, 79, 194, ++ 195, 363, 363, 363, 368, 363, 404, 425, ++ 363, 79, 194, 195, 363, 363, 363, 368, ++ 363, 98, 363, 404, 404, 363, 79, 194, ++ 195, 363, 363, 363, 368, 363, 80, 81, ++ 363, 363, 98, 403, 363, 79, 194, 195, ++ 363, 363, 363, 368, 363, 80, 363, 397, ++ 402, 402, 84, 79, 194, 195, 363, 363, ++ 363, 400, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 363, 202, 363, 397, 402, 402, 84, ++ 79, 194, 195, 363, 363, 363, 400, 363, ++ 396, 397, 402, 402, 84, 79, 194, 195, ++ 363, 363, 363, 400, 363, 363, 200, 363, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 363, 202, 363, 396, 397, ++ 398, 402, 84, 79, 194, 195, 363, 363, ++ 109, 400, 363, 363, 200, 363, 363, 363, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 363, 202, 363, 394, 363, 426, 363, ++ 413, 413, 84, 79, 194, 195, 363, 363, ++ 363, 368, 363, 394, 363, 394, 363, 363, ++ 363, 404, 404, 363, 79, 194, 195, 363, ++ 363, 363, 368, 363, 394, 363, 394, 363, ++ 363, 363, 404, 427, 363, 79, 194, 195, ++ 363, 363, 363, 368, 363, 394, 363, 394, ++ 363, 426, 363, 404, 404, 363, 79, 194, ++ 195, 363, 363, 363, 368, 363, 394, 363, ++ 394, 81, 363, 363, 98, 395, 363, 79, ++ 194, 195, 363, 363, 363, 368, 363, 394, ++ 363, 387, 388, 393, 393, 84, 79, 194, ++ 195, 363, 363, 363, 391, 363, 363, 200, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 363, 363, 202, 363, 387, ++ 388, 389, 393, 84, 79, 194, 195, 363, ++ 363, 111, 391, 363, 363, 200, 363, 363, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 202, 363, 385, 363, 428, ++ 363, 413, 413, 84, 79, 194, 195, 363, ++ 363, 363, 368, 363, 385, 363, 385, 363, ++ 363, 363, 404, 404, 363, 79, 194, 195, ++ 363, 363, 363, 368, 363, 385, 363, 385, ++ 363, 363, 363, 404, 429, 363, 79, 194, ++ 195, 363, 363, 363, 368, 363, 385, 363, ++ 385, 363, 428, 363, 404, 404, 363, 79, ++ 194, 195, 363, 363, 363, 368, 363, 385, ++ 363, 385, 81, 363, 363, 98, 386, 363, ++ 79, 194, 195, 363, 363, 363, 368, 363, ++ 385, 363, 378, 379, 384, 384, 84, 79, ++ 194, 195, 363, 363, 363, 382, 363, 363, ++ 200, 363, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 363, 363, 363, 202, 363, ++ 378, 379, 380, 384, 84, 79, 194, 195, ++ 363, 363, 113, 382, 363, 363, 200, 363, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 363, 202, 363, 376, 363, ++ 430, 363, 413, 413, 84, 79, 194, 195, ++ 363, 363, 363, 368, 363, 376, 363, 376, ++ 363, 363, 363, 404, 404, 363, 79, 194, ++ 195, 363, 363, 363, 368, 363, 376, 363, ++ 376, 363, 363, 363, 404, 431, 363, 79, ++ 194, 195, 363, 363, 363, 368, 363, 376, ++ 363, 376, 363, 430, 363, 404, 404, 363, ++ 79, 194, 195, 363, 363, 363, 368, 363, ++ 376, 363, 376, 81, 363, 363, 98, 377, ++ 363, 79, 194, 195, 363, 363, 363, 368, ++ 363, 376, 363, 369, 370, 375, 375, 84, ++ 79, 194, 195, 363, 363, 363, 373, 363, ++ 363, 200, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 363, 363, 363, 363, 202, ++ 363, 369, 370, 371, 375, 84, 79, 194, ++ 195, 363, 363, 115, 373, 363, 363, 200, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 363, 363, 202, 363, 366, ++ 363, 432, 363, 413, 413, 84, 79, 194, ++ 195, 363, 363, 363, 368, 363, 366, 363, ++ 366, 363, 363, 363, 404, 404, 363, 79, ++ 194, 195, 363, 363, 363, 368, 363, 366, ++ 363, 366, 363, 363, 363, 404, 433, 363, ++ 79, 194, 195, 363, 363, 363, 368, 363, ++ 366, 363, 366, 363, 432, 363, 404, 404, ++ 363, 79, 194, 195, 363, 363, 363, 368, ++ 363, 366, 363, 366, 81, 363, 363, 98, ++ 367, 363, 79, 194, 195, 363, 363, 363, ++ 368, 363, 366, 363, 116, 83, 83, 84, ++ 79, 434, 434, 434, 434, 156, 116, 434, ++ 190, 191, 365, 365, 84, 79, 194, 195, ++ 363, 363, 363, 197, 363, 363, 200, 363, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 363, 363, 363, 202, 363, 116, 83, ++ 83, 84, 79, 434, 434, 434, 434, 434, ++ 116, 434, 436, 437, 438, 439, 123, 118, ++ 440, 441, 435, 435, 155, 442, 435, 435, ++ 443, 435, 435, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 435, 435, 444, 435, ++ 445, 437, 439, 439, 123, 118, 440, 441, ++ 435, 435, 435, 442, 435, 435, 443, 435, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 444, 435, 437, 439, ++ 439, 123, 118, 440, 441, 435, 435, 435, ++ 442, 435, 435, 443, 435, 435, 435, 435, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 435, 444, 435, 446, 435, 435, 435, 136, ++ 447, 435, 118, 440, 441, 435, 435, 435, ++ 448, 435, 446, 435, 449, 450, 451, 452, ++ 123, 118, 440, 441, 435, 435, 153, 453, ++ 435, 435, 443, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 444, 435, 454, 450, 455, 455, 123, 118, ++ 440, 441, 435, 435, 435, 453, 435, 435, ++ 443, 435, 435, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 435, 435, 444, 435, ++ 450, 455, 455, 123, 118, 440, 441, 435, ++ 435, 435, 453, 435, 435, 443, 435, 435, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 435, 435, 435, 444, 435, 456, 435, 435, ++ 435, 136, 457, 435, 118, 440, 441, 435, ++ 435, 435, 448, 435, 456, 435, 458, 459, ++ 460, 461, 123, 118, 440, 441, 435, 435, ++ 151, 462, 435, 435, 443, 435, 435, 435, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 435, 435, 444, 435, 463, 459, 464, 464, ++ 123, 118, 440, 441, 435, 435, 435, 462, ++ 435, 435, 443, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 444, 435, 459, 464, 464, 123, 118, 440, ++ 441, 435, 435, 435, 462, 435, 435, 443, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 435, 444, 435, 465, ++ 435, 435, 435, 136, 466, 435, 118, 440, ++ 441, 435, 435, 435, 448, 435, 465, 435, ++ 467, 468, 469, 470, 123, 118, 440, 441, ++ 435, 435, 149, 471, 435, 435, 443, 435, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 444, 435, 472, 468, ++ 473, 473, 123, 118, 440, 441, 435, 435, ++ 435, 471, 435, 435, 443, 435, 435, 435, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 435, 435, 444, 435, 468, 473, 473, 123, ++ 118, 440, 441, 435, 435, 435, 471, 435, ++ 435, 443, 435, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 435, 435, 435, 444, ++ 435, 474, 435, 435, 435, 136, 475, 435, ++ 118, 440, 441, 435, 435, 435, 448, 435, ++ 474, 435, 476, 477, 478, 479, 123, 118, ++ 440, 441, 435, 435, 147, 480, 435, 435, ++ 443, 435, 435, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 435, 435, 444, 435, ++ 481, 477, 482, 482, 123, 118, 440, 441, ++ 435, 435, 435, 480, 435, 435, 443, 435, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 444, 435, 477, 482, ++ 482, 123, 118, 440, 441, 435, 435, 435, ++ 480, 435, 435, 443, 435, 435, 435, 435, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 435, 444, 435, 136, 483, 435, 118, 440, ++ 441, 435, 435, 435, 448, 435, 484, 484, ++ 435, 118, 440, 441, 435, 435, 435, 448, ++ 435, 485, 435, 435, 486, 440, 441, 435, ++ 440, 441, 435, 487, 435, 440, 488, 435, ++ 440, 489, 435, 440, 435, 485, 435, 435, ++ 435, 440, 441, 435, 490, 435, 491, 492, ++ 435, 118, 440, 441, 435, 435, 121, 435, ++ 120, 435, 484, 484, 435, 118, 440, 441, ++ 435, 484, 484, 435, 118, 440, 441, 435, ++ 490, 435, 484, 484, 435, 118, 440, 441, ++ 435, 490, 435, 491, 484, 435, 118, 440, ++ 441, 435, 435, 121, 435, 136, 435, 493, ++ 493, 123, 118, 440, 441, 435, 435, 435, ++ 448, 435, 494, 145, 495, 496, 126, 118, ++ 440, 441, 435, 435, 435, 448, 435, 145, ++ 495, 496, 126, 118, 440, 441, 435, 435, ++ 435, 448, 435, 495, 495, 126, 118, 440, ++ 441, 435, 435, 435, 448, 435, 497, 142, ++ 498, 499, 129, 118, 440, 441, 435, 435, ++ 435, 448, 435, 142, 498, 499, 129, 118, ++ 440, 441, 435, 435, 435, 448, 435, 498, ++ 498, 129, 118, 440, 441, 435, 435, 435, ++ 448, 435, 500, 139, 501, 502, 132, 118, ++ 440, 441, 435, 435, 435, 448, 435, 139, ++ 501, 502, 132, 118, 440, 441, 435, 435, ++ 435, 448, 435, 501, 501, 132, 118, 440, ++ 441, 435, 435, 435, 448, 435, 503, 136, ++ 484, 504, 435, 118, 440, 441, 435, 435, ++ 435, 448, 435, 136, 484, 504, 435, 118, ++ 440, 441, 435, 435, 435, 448, 435, 484, ++ 505, 435, 118, 440, 441, 435, 435, 435, ++ 448, 435, 136, 435, 484, 484, 435, 118, ++ 440, 441, 435, 435, 435, 448, 435, 119, ++ 120, 435, 435, 136, 483, 435, 118, 440, ++ 441, 435, 435, 435, 448, 435, 119, 435, ++ 477, 482, 482, 123, 118, 440, 441, 435, ++ 435, 435, 480, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 435, 435, 435, 444, 435, 477, 482, 482, ++ 123, 118, 440, 441, 435, 435, 435, 480, ++ 435, 476, 477, 482, 482, 123, 118, 440, ++ 441, 435, 435, 435, 480, 435, 435, 443, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 435, 444, 435, 476, ++ 477, 478, 482, 123, 118, 440, 441, 435, ++ 435, 147, 480, 435, 435, 443, 435, 435, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 435, 435, 435, 444, 435, 474, 435, 506, ++ 435, 493, 493, 123, 118, 440, 441, 435, ++ 435, 435, 448, 435, 474, 435, 474, 435, ++ 435, 435, 484, 484, 435, 118, 440, 441, ++ 435, 435, 435, 448, 435, 474, 435, 474, ++ 435, 435, 435, 484, 507, 435, 118, 440, ++ 441, 435, 435, 435, 448, 435, 474, 435, ++ 474, 435, 506, 435, 484, 484, 435, 118, ++ 440, 441, 435, 435, 435, 448, 435, 474, ++ 435, 474, 120, 435, 435, 136, 475, 435, ++ 118, 440, 441, 435, 435, 435, 448, 435, ++ 474, 435, 467, 468, 473, 473, 123, 118, ++ 440, 441, 435, 435, 435, 471, 435, 435, ++ 443, 435, 435, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 435, 435, 444, 435, ++ 467, 468, 469, 473, 123, 118, 440, 441, ++ 435, 435, 149, 471, 435, 435, 443, 435, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 444, 435, 465, 435, ++ 508, 435, 493, 493, 123, 118, 440, 441, ++ 435, 435, 435, 448, 435, 465, 435, 465, ++ 435, 435, 435, 484, 484, 435, 118, 440, ++ 441, 435, 435, 435, 448, 435, 465, 435, ++ 465, 435, 435, 435, 484, 509, 435, 118, ++ 440, 441, 435, 435, 435, 448, 435, 465, ++ 435, 465, 435, 508, 435, 484, 484, 435, ++ 118, 440, 441, 435, 435, 435, 448, 435, ++ 465, 435, 465, 120, 435, 435, 136, 466, ++ 435, 118, 440, 441, 435, 435, 435, 448, ++ 435, 465, 435, 458, 459, 464, 464, 123, ++ 118, 440, 441, 435, 435, 435, 462, 435, ++ 435, 443, 435, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 435, 435, 435, 444, ++ 435, 458, 459, 460, 464, 123, 118, 440, ++ 441, 435, 435, 151, 462, 435, 435, 443, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 435, 444, 435, 456, ++ 435, 510, 435, 493, 493, 123, 118, 440, ++ 441, 435, 435, 435, 448, 435, 456, 435, ++ 456, 435, 435, 435, 484, 484, 435, 118, ++ 440, 441, 435, 435, 435, 448, 435, 456, ++ 435, 456, 435, 435, 435, 484, 511, 435, ++ 118, 440, 441, 435, 435, 435, 448, 435, ++ 456, 435, 456, 435, 510, 435, 484, 484, ++ 435, 118, 440, 441, 435, 435, 435, 448, ++ 435, 456, 435, 456, 120, 435, 435, 136, ++ 457, 435, 118, 440, 441, 435, 435, 435, ++ 448, 435, 456, 435, 449, 450, 455, 455, ++ 123, 118, 440, 441, 435, 435, 435, 453, ++ 435, 435, 443, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 444, 435, 449, 450, 451, 455, 123, 118, ++ 440, 441, 435, 435, 153, 453, 435, 435, ++ 443, 435, 435, 435, 435, 435, 435, 435, ++ 435, 435, 435, 435, 435, 435, 444, 435, ++ 446, 435, 512, 435, 493, 493, 123, 118, ++ 440, 441, 435, 435, 435, 448, 435, 446, ++ 435, 446, 435, 435, 435, 484, 484, 435, ++ 118, 440, 441, 435, 435, 435, 448, 435, ++ 446, 435, 446, 435, 435, 435, 484, 513, ++ 435, 118, 440, 441, 435, 435, 435, 448, ++ 435, 446, 435, 446, 435, 512, 435, 484, ++ 484, 435, 118, 440, 441, 435, 435, 435, ++ 448, 435, 446, 435, 446, 120, 435, 435, ++ 136, 447, 435, 118, 440, 441, 435, 435, ++ 435, 448, 435, 446, 435, 436, 437, 439, ++ 439, 123, 118, 440, 441, 435, 435, 435, ++ 442, 435, 435, 443, 435, 435, 435, 435, ++ 435, 435, 435, 435, 435, 435, 435, 435, ++ 435, 444, 435, 188, 189, 190, 191, 514, ++ 365, 84, 79, 194, 195, 196, 196, 156, ++ 197, 363, 188, 200, 363, 363, 363, 363, ++ 363, 363, 363, 363, 363, 363, 363, 363, ++ 363, 202, 363, 204, 515, 206, 207, 6, ++ 1, 208, 209, 203, 203, 38, 210, 203, ++ 203, 211, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 212, ++ 203, 215, 189, 190, 191, 516, 517, 84, ++ 157, 518, 519, 203, 196, 156, 520, 203, ++ 215, 200, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 202, ++ 203, 116, 521, 521, 84, 157, 208, 209, ++ 203, 203, 156, 522, 203, 523, 203, 203, ++ 524, 518, 519, 203, 518, 519, 203, 256, ++ 203, 518, 525, 203, 518, 526, 203, 518, ++ 203, 523, 203, 203, 203, 518, 519, 203, ++ 527, 3, 363, 363, 404, 433, 363, 79, ++ 194, 195, 363, 363, 363, 368, 363, 527, ++ 363, 528, 370, 529, 530, 84, 157, 518, ++ 519, 203, 203, 158, 373, 203, 203, 200, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 202, 203, 531, ++ 370, 532, 532, 84, 157, 518, 519, 203, ++ 203, 203, 373, 203, 203, 200, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 202, 203, 370, 532, 532, ++ 84, 157, 518, 519, 203, 203, 203, 373, ++ 203, 203, 200, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 202, 203, 528, 370, 532, 532, 84, 157, ++ 518, 519, 203, 203, 203, 373, 203, 203, ++ 200, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 203, 203, 202, 203, ++ 528, 370, 529, 532, 84, 157, 518, 519, ++ 203, 203, 158, 373, 203, 203, 200, 203, ++ 203, 203, 203, 203, 203, 203, 203, 203, ++ 203, 203, 203, 203, 202, 203, 215, 203, ++ 281, 116, 533, 533, 160, 157, 208, 209, ++ 203, 203, 203, 522, 203, 215, 203, 534, ++ 184, 535, 536, 162, 157, 518, 519, 203, ++ 203, 203, 537, 203, 184, 535, 536, 162, ++ 157, 518, 519, 203, 203, 203, 537, 203, ++ 535, 535, 162, 157, 518, 519, 203, 203, ++ 203, 537, 203, 538, 181, 539, 540, 165, ++ 157, 518, 519, 203, 203, 203, 537, 203, ++ 181, 539, 540, 165, 157, 518, 519, 203, ++ 203, 203, 537, 203, 539, 539, 165, 157, ++ 518, 519, 203, 203, 203, 537, 203, 541, ++ 178, 542, 543, 168, 157, 518, 519, 203, ++ 203, 203, 537, 203, 178, 542, 543, 168, ++ 157, 518, 519, 203, 203, 203, 537, 203, ++ 542, 542, 168, 157, 518, 519, 203, 203, ++ 203, 537, 203, 544, 175, 545, 546, 203, ++ 157, 518, 519, 203, 203, 203, 537, 203, ++ 175, 545, 546, 203, 157, 518, 519, 203, ++ 203, 203, 537, 203, 545, 545, 203, 157, ++ 518, 519, 203, 203, 203, 537, 203, 547, ++ 203, 548, 549, 203, 157, 518, 519, 203, ++ 203, 172, 203, 171, 203, 545, 545, 203, ++ 157, 518, 519, 203, 545, 545, 203, 157, ++ 518, 519, 203, 547, 203, 545, 545, 203, ++ 157, 518, 519, 203, 547, 203, 548, 545, ++ 203, 157, 518, 519, 203, 203, 172, 203, ++ 527, 171, 363, 363, 98, 367, 363, 79, ++ 194, 195, 363, 363, 363, 368, 363, 527, ++ 363, 551, 550, 552, 552, 550, 186, 553, ++ 554, 550, 552, 552, 550, 186, 553, 554, ++ 550, 555, 550, 550, 556, 553, 554, 550, ++ 553, 554, 550, 557, 550, 553, 558, 550, ++ 553, 559, 550, 553, 550, 555, 550, 550, ++ 550, 553, 554, 550, 0 + }; + + static const short _indic_syllable_machine_trans_targs[] = { +- 170, 199, 201, 202, 3, 205, 4, 6, +- 208, 7, 9, 211, 10, 12, 214, 13, +- 15, 16, 191, 18, 19, 213, 21, 22, +- 210, 24, 25, 207, 216, 221, 225, 228, +- 232, 235, 239, 242, 246, 249, 170, 279, +- 281, 282, 39, 285, 40, 42, 288, 43, +- 45, 291, 46, 48, 294, 49, 51, 52, +- 271, 54, 55, 293, 57, 58, 290, 60, +- 61, 287, 296, 301, 305, 308, 312, 315, +- 319, 322, 326, 330, 170, 358, 360, 361, +- 75, 364, 170, 76, 78, 367, 79, 81, +- 370, 82, 84, 373, 85, 87, 88, 350, +- 90, 91, 372, 93, 94, 369, 96, 97, +- 366, 375, 380, 384, 387, 391, 394, 398, +- 401, 405, 170, 439, 441, 442, 110, 445, +- 111, 113, 448, 114, 116, 451, 117, 119, +- 454, 120, 122, 123, 431, 125, 126, 453, +- 128, 129, 450, 131, 132, 447, 456, 461, +- 465, 468, 472, 475, 479, 482, 486, 489, +- 409, 505, 146, 508, 148, 511, 149, 151, +- 514, 152, 154, 517, 155, 520, 522, 523, +- 159, 160, 519, 162, 163, 516, 165, 166, +- 513, 168, 169, 510, 170, 171, 251, 331, +- 333, 408, 410, 351, 353, 354, 411, 407, +- 490, 491, 378, 526, 379, 170, 172, 174, +- 35, 250, 192, 194, 195, 248, 219, 220, +- 173, 34, 175, 244, 0, 176, 178, 33, +- 243, 241, 177, 32, 179, 237, 180, 182, +- 31, 236, 234, 181, 30, 183, 230, 184, +- 186, 29, 229, 227, 185, 28, 187, 223, +- 188, 190, 27, 222, 218, 189, 26, 204, +- 193, 198, 170, 196, 197, 200, 1, 203, +- 2, 206, 5, 23, 209, 8, 20, 212, +- 11, 17, 215, 14, 217, 224, 226, 231, +- 233, 238, 240, 245, 247, 170, 252, 254, +- 71, 328, 272, 274, 275, 329, 299, 300, +- 253, 70, 255, 324, 36, 256, 258, 69, +- 323, 321, 257, 68, 259, 317, 260, 262, +- 67, 316, 314, 261, 66, 263, 310, 264, +- 266, 65, 309, 307, 265, 64, 267, 303, +- 268, 270, 63, 302, 298, 269, 62, 284, +- 273, 278, 170, 276, 277, 280, 37, 283, +- 38, 286, 41, 59, 289, 44, 56, 292, +- 47, 53, 295, 50, 297, 304, 306, 311, +- 313, 318, 320, 325, 327, 170, 332, 106, +- 334, 403, 72, 335, 337, 105, 402, 400, +- 336, 104, 338, 396, 339, 341, 103, 395, +- 393, 340, 102, 342, 389, 343, 345, 101, +- 388, 386, 344, 100, 346, 382, 347, 349, +- 99, 381, 377, 348, 98, 363, 352, 357, +- 170, 355, 356, 359, 73, 362, 74, 365, +- 77, 95, 368, 80, 92, 371, 83, 89, +- 374, 86, 376, 383, 385, 390, 392, 397, +- 399, 404, 406, 170, 170, 412, 414, 142, +- 141, 432, 434, 435, 488, 459, 460, 413, +- 415, 484, 107, 416, 418, 140, 483, 481, +- 417, 139, 419, 477, 420, 422, 138, 476, +- 474, 421, 137, 423, 470, 424, 426, 136, +- 469, 467, 425, 135, 427, 463, 428, 430, +- 134, 462, 458, 429, 133, 444, 433, 438, +- 170, 436, 437, 440, 108, 443, 109, 446, +- 112, 130, 449, 115, 127, 452, 118, 124, +- 455, 121, 457, 464, 466, 471, 473, 478, +- 480, 485, 487, 143, 492, 493, 507, 498, +- 500, 501, 525, 494, 495, 496, 144, 506, +- 497, 499, 504, 502, 503, 145, 509, 147, +- 167, 156, 512, 150, 164, 515, 153, 161, +- 518, 158, 521, 157, 524, 170, 527, 528, +- 530, 531, 529, 534, 170, 532, 533 ++ 178, 200, 207, 209, 210, 4, 213, 5, ++ 7, 216, 8, 10, 219, 11, 13, 222, ++ 14, 16, 17, 199, 19, 20, 221, 22, ++ 23, 218, 25, 26, 215, 224, 229, 233, ++ 236, 240, 243, 247, 250, 254, 257, 178, ++ 280, 287, 289, 290, 41, 293, 42, 44, ++ 296, 45, 47, 299, 48, 50, 302, 51, ++ 53, 54, 279, 56, 57, 301, 59, 60, ++ 298, 62, 63, 295, 304, 309, 313, 316, ++ 320, 323, 327, 330, 334, 338, 178, 359, ++ 366, 368, 369, 78, 372, 178, 79, 81, ++ 375, 82, 84, 378, 85, 87, 381, 88, ++ 90, 91, 358, 93, 94, 380, 96, 97, ++ 377, 99, 100, 374, 383, 388, 392, 395, ++ 399, 402, 406, 409, 413, 178, 440, 447, ++ 449, 450, 114, 453, 115, 117, 456, 118, ++ 120, 459, 121, 123, 462, 124, 126, 127, ++ 439, 129, 130, 461, 132, 133, 458, 135, ++ 136, 455, 464, 469, 473, 476, 480, 483, ++ 487, 490, 494, 497, 417, 502, 513, 152, ++ 516, 154, 519, 155, 157, 522, 158, 160, ++ 525, 161, 528, 530, 531, 166, 167, 527, ++ 169, 170, 524, 172, 173, 521, 175, 176, ++ 518, 178, 536, 178, 179, 259, 339, 341, ++ 416, 418, 361, 362, 419, 415, 498, 499, ++ 386, 534, 387, 178, 180, 182, 36, 258, ++ 202, 203, 256, 227, 228, 181, 35, 183, ++ 252, 1, 184, 186, 34, 251, 249, 185, ++ 33, 187, 245, 188, 190, 32, 244, 242, ++ 189, 31, 191, 238, 192, 194, 30, 237, ++ 235, 193, 29, 195, 231, 196, 198, 28, ++ 230, 226, 197, 27, 212, 0, 201, 206, ++ 178, 204, 205, 208, 2, 211, 3, 214, ++ 6, 24, 217, 9, 21, 220, 12, 18, ++ 223, 15, 225, 232, 234, 239, 241, 246, ++ 248, 253, 255, 178, 260, 262, 73, 336, ++ 282, 283, 337, 307, 308, 261, 72, 263, ++ 332, 38, 264, 266, 71, 331, 329, 265, ++ 70, 267, 325, 268, 270, 69, 324, 322, ++ 269, 68, 271, 318, 272, 274, 67, 317, ++ 315, 273, 66, 275, 311, 276, 278, 65, ++ 310, 306, 277, 64, 292, 37, 281, 286, ++ 178, 284, 285, 288, 39, 291, 40, 294, ++ 43, 61, 297, 46, 58, 300, 49, 55, ++ 303, 52, 305, 312, 314, 319, 321, 326, ++ 328, 333, 335, 178, 340, 109, 342, 411, ++ 75, 343, 345, 108, 410, 408, 344, 107, ++ 346, 404, 347, 349, 106, 403, 401, 348, ++ 105, 350, 397, 351, 353, 104, 396, 394, ++ 352, 103, 354, 390, 355, 357, 102, 389, ++ 385, 356, 101, 371, 74, 360, 365, 178, ++ 363, 364, 367, 76, 370, 77, 373, 80, ++ 98, 376, 83, 95, 379, 86, 92, 382, ++ 89, 384, 391, 393, 398, 400, 405, 407, ++ 412, 414, 178, 178, 420, 422, 146, 145, ++ 442, 443, 496, 467, 468, 421, 423, 492, ++ 111, 424, 426, 144, 491, 489, 425, 143, ++ 427, 485, 428, 430, 142, 484, 482, 429, ++ 141, 431, 478, 432, 434, 140, 477, 475, ++ 433, 139, 435, 471, 436, 438, 138, 470, ++ 466, 437, 137, 452, 110, 441, 446, 178, ++ 444, 445, 448, 112, 451, 113, 454, 116, ++ 134, 457, 119, 131, 460, 122, 128, 463, ++ 125, 465, 472, 474, 479, 481, 486, 488, ++ 493, 495, 147, 500, 501, 515, 504, 505, ++ 533, 148, 509, 503, 508, 506, 507, 510, ++ 511, 150, 514, 512, 149, 151, 517, 153, ++ 174, 163, 520, 156, 171, 523, 159, 168, ++ 526, 162, 165, 529, 164, 532, 178, 535, ++ 177, 538, 539, 537, 542, 178, 540, 541 + }; + + static const char _indic_syllable_machine_trans_actions[] = { +- 1, 2, 0, 0, 0, 2, 0, 0, ++ 1, 0, 2, 2, 2, 0, 2, 0, ++ 0, 2, 0, 0, 2, 0, 0, 2, ++ 0, 0, 0, 2, 0, 0, 2, 0, ++ 0, 2, 0, 0, 2, 2, 2, 2, ++ 2, 2, 2, 2, 2, 2, 2, 3, ++ 0, 2, 2, 2, 0, 2, 0, 0, + 2, 0, 0, 2, 0, 0, 2, 0, + 0, 0, 2, 0, 0, 2, 0, 0, + 2, 0, 0, 2, 2, 2, 2, 2, +- 2, 2, 2, 2, 2, 2, 3, 2, +- 0, 0, 0, 2, 0, 0, 2, 0, ++ 2, 2, 2, 2, 2, 2, 4, 0, ++ 2, 2, 2, 0, 2, 5, 0, 0, ++ 2, 0, 0, 2, 0, 0, 2, 0, ++ 0, 0, 2, 0, 0, 2, 0, 0, ++ 2, 0, 0, 2, 2, 6, 2, 6, ++ 2, 6, 2, 6, 2, 7, 0, 2, ++ 2, 2, 0, 2, 0, 0, 2, 0, + 0, 2, 0, 0, 2, 0, 0, 0, + 2, 0, 0, 2, 0, 0, 2, 0, + 0, 2, 2, 2, 2, 2, 2, 2, +- 2, 2, 2, 2, 4, 2, 0, 0, +- 0, 2, 5, 0, 0, 2, 0, 0, +- 2, 0, 0, 2, 0, 0, 0, 2, +- 0, 0, 2, 0, 0, 2, 0, 0, +- 2, 2, 6, 2, 6, 2, 6, 2, +- 6, 2, 7, 2, 0, 0, 0, 2, ++ 2, 2, 2, 2, 6, 0, 8, 0, ++ 2, 0, 2, 0, 0, 2, 0, 0, ++ 2, 0, 2, 2, 2, 0, 0, 2, + 0, 0, 2, 0, 0, 2, 0, 0, +- 2, 0, 0, 0, 2, 0, 0, 2, +- 0, 0, 2, 0, 0, 2, 2, 2, +- 2, 2, 2, 2, 2, 2, 2, 2, +- 6, 8, 0, 2, 0, 2, 0, 0, +- 2, 0, 0, 2, 0, 2, 0, 0, +- 0, 0, 2, 0, 0, 2, 0, 0, +- 2, 0, 0, 2, 11, 2, 2, 6, +- 2, 12, 12, 0, 0, 0, 2, 2, +- 6, 2, 6, 0, 6, 13, 2, 2, +- 0, 2, 0, 0, 0, 2, 2, 2, +- 2, 0, 2, 2, 0, 2, 2, 0, +- 2, 2, 2, 0, 2, 2, 2, 2, +- 0, 2, 2, 2, 0, 2, 2, 2, +- 2, 0, 2, 2, 2, 0, 2, 2, +- 2, 2, 0, 2, 2, 2, 0, 2, +- 0, 0, 14, 0, 0, 0, 0, 2, +- 0, 2, 0, 0, 2, 0, 0, 2, +- 0, 0, 2, 0, 2, 2, 2, 2, +- 2, 2, 2, 2, 2, 15, 2, 2, +- 0, 2, 0, 0, 0, 2, 2, 2, +- 2, 0, 2, 2, 0, 2, 2, 0, +- 2, 2, 2, 0, 2, 2, 2, 2, +- 0, 2, 2, 2, 0, 2, 2, 2, +- 2, 0, 2, 2, 2, 0, 2, 2, +- 2, 2, 0, 2, 2, 2, 0, 2, +- 0, 0, 16, 0, 0, 0, 0, 2, +- 0, 2, 0, 0, 2, 0, 0, 2, +- 0, 0, 2, 0, 2, 2, 2, 2, +- 2, 2, 2, 2, 2, 17, 6, 0, +- 6, 6, 0, 6, 2, 0, 6, 2, +- 6, 0, 6, 6, 6, 2, 0, 6, +- 2, 6, 0, 6, 6, 6, 2, 0, +- 6, 2, 6, 0, 6, 6, 6, 2, +- 0, 6, 2, 6, 0, 6, 0, 0, +- 18, 0, 0, 0, 0, 2, 0, 2, ++ 2, 9, 0, 12, 2, 2, 6, 2, ++ 13, 13, 0, 0, 2, 2, 6, 2, ++ 6, 2, 6, 14, 2, 2, 0, 2, ++ 0, 0, 2, 2, 2, 2, 0, 2, ++ 2, 0, 2, 2, 0, 2, 2, 2, ++ 0, 2, 2, 2, 2, 0, 2, 2, ++ 2, 0, 2, 2, 2, 2, 0, 2, ++ 2, 2, 0, 2, 2, 2, 2, 0, ++ 2, 2, 2, 0, 2, 0, 0, 0, ++ 15, 0, 0, 2, 0, 2, 0, 2, + 0, 0, 2, 0, 0, 2, 0, 0, + 2, 0, 2, 2, 2, 2, 2, 2, +- 2, 2, 2, 19, 20, 2, 2, 0, +- 0, 0, 0, 0, 2, 2, 2, 2, +- 2, 2, 0, 2, 2, 0, 2, 2, ++ 2, 2, 2, 16, 2, 2, 0, 2, ++ 0, 0, 2, 2, 2, 2, 0, 2, ++ 2, 0, 2, 2, 0, 2, 2, 2, ++ 0, 2, 2, 2, 2, 0, 2, 2, + 2, 0, 2, 2, 2, 2, 0, 2, + 2, 2, 0, 2, 2, 2, 2, 0, +- 2, 2, 2, 0, 2, 2, 2, 2, +- 0, 2, 2, 2, 0, 2, 0, 0, +- 21, 0, 0, 0, 0, 2, 0, 2, ++ 2, 2, 2, 0, 2, 0, 0, 0, ++ 17, 0, 0, 2, 0, 2, 0, 2, + 0, 0, 2, 0, 0, 2, 0, 0, + 2, 0, 2, 2, 2, 2, 2, 2, +- 2, 2, 2, 0, 0, 8, 2, 0, +- 0, 0, 2, 2, 8, 8, 0, 8, +- 8, 0, 0, 0, 0, 0, 2, 0, ++ 2, 2, 2, 18, 6, 0, 6, 6, ++ 0, 6, 2, 0, 6, 2, 6, 0, ++ 6, 6, 6, 2, 0, 6, 2, 6, ++ 0, 6, 6, 6, 2, 0, 6, 2, ++ 6, 0, 6, 6, 6, 2, 0, 6, ++ 2, 6, 0, 6, 0, 0, 0, 19, ++ 0, 0, 2, 0, 2, 0, 2, 0, ++ 0, 2, 0, 0, 2, 0, 0, 2, ++ 0, 2, 2, 2, 2, 2, 2, 2, ++ 2, 2, 20, 21, 2, 2, 0, 0, ++ 0, 0, 2, 2, 2, 2, 2, 2, ++ 0, 2, 2, 0, 2, 2, 2, 0, ++ 2, 2, 2, 2, 0, 2, 2, 2, ++ 0, 2, 2, 2, 2, 0, 2, 2, ++ 2, 0, 2, 2, 2, 2, 0, 2, ++ 2, 2, 0, 2, 0, 0, 0, 22, ++ 0, 0, 2, 0, 2, 0, 2, 0, ++ 0, 2, 0, 0, 2, 0, 0, 2, ++ 0, 2, 2, 2, 2, 2, 2, 2, ++ 2, 2, 0, 0, 8, 2, 0, 0, ++ 2, 0, 2, 0, 0, 0, 0, 8, ++ 8, 0, 8, 8, 0, 0, 2, 0, + 0, 0, 2, 0, 0, 2, 0, 0, +- 2, 0, 0, 0, 2, 22, 0, 0, +- 0, 0, 0, 0, 23, 0, 0 ++ 2, 0, 0, 2, 0, 2, 23, 2, ++ 0, 0, 0, 0, 0, 24, 0, 0 + }; + + static const char _indic_syllable_machine_to_state_actions[] = { +@@ -1331,7 +1354,8 @@ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 9, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 10, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +@@ -1401,7 +1425,8 @@ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 10, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 11, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +@@ -1454,83 +1479,84 @@ + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, +- 1, 1, 1, 1, 39, 39, 39, 39, +- 39, 39, 39, 39, 39, 39, 39, 39, +- 39, 39, 39, 39, 39, 39, 39, 39, +- 39, 39, 39, 39, 39, 39, 39, 39, +- 39, 39, 39, 39, 39, 39, 39, 39, +- 77, 77, 77, 83, 83, 77, 77, 77, +- 77, 77, 77, 77, 77, 77, 77, 77, +- 77, 77, 77, 77, 77, 77, 77, 77, +- 77, 77, 77, 77, 77, 77, 77, 77, +- 83, 77, 77, 115, 115, 115, 115, 115, +- 115, 115, 115, 115, 115, 115, 115, 115, +- 115, 115, 115, 115, 115, 115, 115, 115, +- 115, 115, 115, 115, 115, 115, 115, 115, +- 115, 115, 115, 115, 115, 115, 115, 77, ++ 1, 1, 1, 1, 1, 40, 40, 40, ++ 40, 40, 40, 40, 40, 40, 40, 40, ++ 40, 40, 40, 40, 40, 40, 40, 40, ++ 40, 40, 40, 40, 40, 40, 40, 40, ++ 40, 40, 40, 40, 40, 40, 40, 40, ++ 40, 40, 79, 79, 79, 79, 86, 86, ++ 79, 79, 79, 79, 79, 79, 79, 79, ++ 79, 79, 79, 79, 79, 79, 79, 79, ++ 79, 79, 79, 79, 79, 79, 79, 79, ++ 79, 79, 79, 79, 79, 79, 118, 118, ++ 118, 118, 118, 118, 118, 118, 118, 118, ++ 118, 118, 118, 118, 118, 118, 118, 118, ++ 118, 118, 118, 118, 118, 118, 118, 118, ++ 118, 118, 118, 118, 118, 118, 118, 118, ++ 118, 118, 118, 79, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, +- 1, 1, 0, 198, 198, 198, 198, 198, +- 198, 198, 198, 198, 198, 198, 198, 198, +- 198, 198, 198, 198, 198, 198, 198, 198, +- 198, 198, 198, 198, 198, 198, 198, 198, +- 198, 198, 198, 198, 198, 198, 198, 198, +- 198, 198, 198, 198, 198, 198, 198, 198, +- 198, 198, 198, 198, 198, 198, 198, 198, +- 198, 198, 198, 198, 198, 198, 198, 198, +- 198, 198, 198, 198, 198, 198, 198, 198, +- 198, 198, 198, 198, 198, 198, 198, 198, +- 198, 198, 198, 278, 278, 278, 278, 278, +- 278, 278, 278, 278, 278, 278, 278, 278, +- 278, 278, 278, 278, 278, 278, 278, 278, +- 278, 278, 278, 278, 278, 278, 278, 278, +- 278, 278, 278, 278, 278, 278, 278, 278, +- 278, 278, 278, 278, 278, 278, 278, 278, +- 278, 278, 278, 278, 278, 278, 278, 278, +- 278, 278, 278, 278, 278, 278, 278, 278, +- 278, 278, 278, 278, 278, 278, 278, 278, +- 278, 278, 278, 278, 278, 278, 278, 278, +- 278, 278, 278, 358, 358, 358, 358, 358, +- 358, 358, 358, 358, 358, 358, 358, 358, +- 358, 358, 358, 358, 358, 358, 358, 358, +- 358, 358, 358, 358, 358, 358, 358, 358, +- 358, 358, 358, 358, 358, 358, 358, 358, +- 358, 358, 358, 358, 358, 358, 358, 358, +- 358, 358, 358, 358, 358, 358, 358, 358, +- 358, 358, 358, 358, 358, 358, 358, 358, +- 358, 358, 358, 358, 358, 358, 358, 358, +- 358, 358, 358, 358, 358, 358, 358, 358, +- 428, 358, 428, 429, 429, 429, 429, 429, +- 429, 429, 429, 429, 429, 429, 429, 429, +- 429, 429, 429, 429, 429, 429, 429, 429, +- 429, 429, 429, 429, 429, 429, 429, 429, +- 429, 429, 429, 429, 429, 429, 429, 429, +- 429, 429, 429, 429, 429, 429, 429, 429, +- 429, 429, 429, 429, 429, 429, 429, 429, +- 429, 429, 429, 429, 429, 429, 429, 429, +- 429, 429, 429, 429, 429, 429, 429, 429, +- 429, 429, 429, 429, 429, 429, 429, 429, +- 429, 429, 358, 198, 198, 198, 358, 198, +- 198, 198, 198, 198, 198, 198, 198, 198, +- 198, 198, 198, 198, 198, 198, 198, 198, +- 198, 198, 198, 198, 198, 198, 198, 198, +- 198, 198, 198, 198, 198, 358, 542, 542, +- 542, 542, 542, 542, 542, 542, 542 ++ 1, 186, 0, 204, 204, 204, 204, 204, ++ 204, 204, 204, 204, 204, 204, 204, 204, ++ 204, 204, 204, 204, 204, 204, 204, 204, ++ 204, 204, 204, 204, 204, 204, 204, 204, ++ 204, 204, 204, 204, 204, 204, 204, 204, ++ 204, 204, 204, 204, 204, 204, 204, 204, ++ 204, 204, 204, 204, 204, 204, 204, 204, ++ 204, 204, 204, 204, 204, 204, 204, 204, ++ 204, 204, 204, 204, 204, 204, 204, 204, ++ 204, 204, 204, 204, 204, 204, 204, 204, ++ 204, 204, 204, 284, 284, 284, 284, 284, ++ 284, 284, 284, 284, 284, 284, 284, 284, ++ 284, 284, 284, 284, 284, 284, 284, 284, ++ 284, 284, 284, 284, 284, 284, 284, 284, ++ 284, 284, 284, 284, 284, 284, 284, 284, ++ 284, 284, 284, 284, 284, 284, 284, 284, ++ 284, 284, 284, 284, 284, 284, 284, 284, ++ 284, 284, 284, 284, 284, 284, 284, 284, ++ 284, 284, 284, 284, 284, 284, 284, 284, ++ 284, 284, 284, 284, 284, 284, 284, 284, ++ 284, 284, 284, 364, 364, 364, 364, 364, ++ 364, 364, 364, 364, 364, 364, 364, 364, ++ 364, 364, 364, 364, 364, 364, 364, 364, ++ 364, 364, 364, 364, 364, 364, 364, 364, ++ 364, 364, 364, 364, 364, 364, 364, 364, ++ 364, 364, 364, 364, 364, 364, 364, 364, ++ 364, 364, 364, 364, 364, 364, 364, 364, ++ 364, 364, 364, 364, 364, 364, 364, 364, ++ 364, 364, 364, 364, 364, 364, 364, 364, ++ 364, 364, 364, 364, 364, 364, 364, 364, ++ 435, 364, 435, 436, 436, 436, 436, 436, ++ 436, 436, 436, 436, 436, 436, 436, 436, ++ 436, 436, 436, 436, 436, 436, 436, 436, ++ 436, 436, 436, 436, 436, 436, 436, 436, ++ 436, 436, 436, 436, 436, 436, 436, 436, ++ 436, 436, 436, 436, 436, 436, 436, 436, ++ 436, 436, 436, 436, 436, 436, 436, 436, ++ 436, 436, 436, 436, 436, 436, 436, 436, ++ 436, 436, 436, 436, 436, 436, 436, 436, ++ 436, 436, 436, 436, 436, 436, 436, 436, ++ 436, 436, 364, 204, 204, 204, 204, 204, ++ 204, 204, 204, 204, 204, 364, 204, 204, ++ 204, 204, 204, 204, 204, 204, 204, 204, ++ 204, 204, 204, 204, 204, 204, 204, 204, ++ 204, 204, 204, 204, 204, 364, 551, 551, ++ 551, 551, 551, 551, 551, 551, 551 + }; + +-static const int indic_syllable_machine_start = 170; +-static const int indic_syllable_machine_first_final = 170; ++static const int indic_syllable_machine_start = 178; ++static const int indic_syllable_machine_first_final = 178; + static const int indic_syllable_machine_error = -1; + +-static const int indic_syllable_machine_en_main = 170; ++static const int indic_syllable_machine_en_main = 178; + + +-#line 36 "../../src/hb-ot-shape-complex-indic-machine.rl" ++#line 36 "hb-ot-shape-complex-indic-machine.rl" + + + +-#line 97 "../../src/hb-ot-shape-complex-indic-machine.rl" ++#line 97 "hb-ot-shape-complex-indic-machine.rl" + + + #define found_syllable(syllable_type) \ +@@ -1550,7 +1576,7 @@ + int cs; + hb_glyph_info_t *info = buffer->info; + +-#line 1554 "hb-ot-shape-complex-indic-machine.hh.tmp" ++#line 1580 "hb-ot-shape-complex-indic-machine.hh" + { + cs = indic_syllable_machine_start; + ts = 0; +@@ -1558,7 +1584,7 @@ + act = 0; + } + +-#line 118 "../../src/hb-ot-shape-complex-indic-machine.rl" ++#line 118 "hb-ot-shape-complex-indic-machine.rl" + + + p = 0; +@@ -1567,7 +1593,7 @@ + unsigned int last = 0; + unsigned int syllable_serial = 1; + +-#line 1571 "hb-ot-shape-complex-indic-machine.hh.tmp" ++#line 1597 "hb-ot-shape-complex-indic-machine.hh" + { + int _slen; + int _trans; +@@ -1577,11 +1603,11 @@ + goto _test_eof; + _resume: + switch ( _indic_syllable_machine_from_state_actions[cs] ) { +- case 10: ++ case 11: + #line 1 "NONE" + {ts = p;} + break; +-#line 1585 "hb-ot-shape-complex-indic-machine.hh.tmp" ++#line 1611 "hb-ot-shape-complex-indic-machine.hh" + } + + _keys = _indic_syllable_machine_trans_keys + (cs<<1); +@@ -1603,68 +1629,72 @@ + #line 1 "NONE" + {te = p+1;} + break; +- case 14: +-#line 88 "../../src/hb-ot-shape-complex-indic-machine.rl" ++ case 15: ++#line 88 "hb-ot-shape-complex-indic-machine.rl" + {te = p+1;{ found_syllable (consonant_syllable); }} + break; +- case 16: +-#line 89 "../../src/hb-ot-shape-complex-indic-machine.rl" ++ case 17: ++#line 89 "hb-ot-shape-complex-indic-machine.rl" + {te = p+1;{ found_syllable (vowel_syllable); }} + break; +- case 21: +-#line 90 "../../src/hb-ot-shape-complex-indic-machine.rl" ++ case 22: ++#line 90 "hb-ot-shape-complex-indic-machine.rl" + {te = p+1;{ found_syllable (standalone_cluster); }} + break; +- case 23: +-#line 91 "../../src/hb-ot-shape-complex-indic-machine.rl" ++ case 24: ++#line 91 "hb-ot-shape-complex-indic-machine.rl" + {te = p+1;{ found_syllable (symbol_cluster); }} + break; +- case 18: +-#line 92 "../../src/hb-ot-shape-complex-indic-machine.rl" ++ case 19: ++#line 92 "hb-ot-shape-complex-indic-machine.rl" + {te = p+1;{ found_syllable (broken_cluster); }} + break; +- case 11: +-#line 93 "../../src/hb-ot-shape-complex-indic-machine.rl" ++ case 12: ++#line 93 "hb-ot-shape-complex-indic-machine.rl" + {te = p+1;{ found_syllable (non_indic_cluster); }} + break; +- case 13: +-#line 88 "../../src/hb-ot-shape-complex-indic-machine.rl" ++ case 14: ++#line 88 "hb-ot-shape-complex-indic-machine.rl" + {te = p;p--;{ found_syllable (consonant_syllable); }} + break; +- case 15: +-#line 89 "../../src/hb-ot-shape-complex-indic-machine.rl" ++ case 16: ++#line 89 "hb-ot-shape-complex-indic-machine.rl" + {te = p;p--;{ found_syllable (vowel_syllable); }} + break; +- case 20: +-#line 90 "../../src/hb-ot-shape-complex-indic-machine.rl" ++ case 21: ++#line 90 "hb-ot-shape-complex-indic-machine.rl" + {te = p;p--;{ found_syllable (standalone_cluster); }} + break; +- case 22: +-#line 91 "../../src/hb-ot-shape-complex-indic-machine.rl" ++ case 23: ++#line 91 "hb-ot-shape-complex-indic-machine.rl" + {te = p;p--;{ found_syllable (symbol_cluster); }} + break; +- case 17: +-#line 92 "../../src/hb-ot-shape-complex-indic-machine.rl" ++ case 18: ++#line 92 "hb-ot-shape-complex-indic-machine.rl" + {te = p;p--;{ found_syllable (broken_cluster); }} + break; +- case 19: +-#line 93 "../../src/hb-ot-shape-complex-indic-machine.rl" ++ case 20: ++#line 93 "hb-ot-shape-complex-indic-machine.rl" + {te = p;p--;{ found_syllable (non_indic_cluster); }} + break; + case 1: +-#line 88 "../../src/hb-ot-shape-complex-indic-machine.rl" ++#line 88 "hb-ot-shape-complex-indic-machine.rl" + {{p = ((te))-1;}{ found_syllable (consonant_syllable); }} + break; + case 3: +-#line 89 "../../src/hb-ot-shape-complex-indic-machine.rl" ++#line 89 "hb-ot-shape-complex-indic-machine.rl" + {{p = ((te))-1;}{ found_syllable (vowel_syllable); }} + break; + case 7: +-#line 90 "../../src/hb-ot-shape-complex-indic-machine.rl" ++#line 90 "hb-ot-shape-complex-indic-machine.rl" + {{p = ((te))-1;}{ found_syllable (standalone_cluster); }} + break; ++ case 9: ++#line 91 "hb-ot-shape-complex-indic-machine.rl" ++ {{p = ((te))-1;}{ found_syllable (symbol_cluster); }} ++ break; + case 4: +-#line 92 "../../src/hb-ot-shape-complex-indic-machine.rl" ++#line 92 "hb-ot-shape-complex-indic-machine.rl" + {{p = ((te))-1;}{ found_syllable (broken_cluster); }} + break; + case 5: +@@ -1685,31 +1715,31 @@ + case 8: + #line 1 "NONE" + {te = p+1;} +-#line 88 "../../src/hb-ot-shape-complex-indic-machine.rl" ++#line 88 "hb-ot-shape-complex-indic-machine.rl" + {act = 1;} + break; + case 6: + #line 1 "NONE" + {te = p+1;} +-#line 92 "../../src/hb-ot-shape-complex-indic-machine.rl" ++#line 92 "hb-ot-shape-complex-indic-machine.rl" + {act = 5;} + break; +- case 12: ++ case 13: + #line 1 "NONE" + {te = p+1;} +-#line 93 "../../src/hb-ot-shape-complex-indic-machine.rl" ++#line 93 "hb-ot-shape-complex-indic-machine.rl" + {act = 6;} + break; +-#line 1704 "hb-ot-shape-complex-indic-machine.hh.tmp" ++#line 1734 "hb-ot-shape-complex-indic-machine.hh" + } + + _again: + switch ( _indic_syllable_machine_to_state_actions[cs] ) { +- case 9: ++ case 10: + #line 1 "NONE" + {ts = 0;} + break; +-#line 1713 "hb-ot-shape-complex-indic-machine.hh.tmp" ++#line 1743 "hb-ot-shape-complex-indic-machine.hh" + } + + if ( ++p != pe ) +@@ -1725,7 +1755,7 @@ + + } + +-#line 127 "../../src/hb-ot-shape-complex-indic-machine.rl" ++#line 127 "hb-ot-shape-complex-indic-machine.rl" + + } + +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-indic-private.hh gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-indic-private.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh 2016-06-05 23:49:53.168841514 +0200 +@@ -109,27 +109,31 @@ + + INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_Symbol, + INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM, +- INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER = OT_PLACEHOLDER, /* TODO */ ++ INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER = OT_PLACEHOLDER, /* Don't care. */ + INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK = OT_A, + INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C, + INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C, + INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_CM, + INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C, ++ INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER = OT_M, /* U+17CD only. */ + INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_CM, + INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_PLACEHOLDER, + INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA = OT_Repha, ++ INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED = OT_X, /* Don't care. */ + INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_CM, + INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA = OT_N, ++ INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER = OT_Repha, /* TODO */ + INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK = OT_SM, +- INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_H, /* TODO */ ++ INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_Coeng, + INDIC_SYLLABIC_CATEGORY_JOINER = OT_ZWJ, + INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X, + INDIC_SYLLABIC_CATEGORY_NON_JOINER = OT_ZWNJ, + INDIC_SYLLABIC_CATEGORY_NUKTA = OT_N, + INDIC_SYLLABIC_CATEGORY_NUMBER = OT_PLACEHOLDER, +- INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER = OT_PLACEHOLDER, /* TODO */ +- INDIC_SYLLABIC_CATEGORY_PURE_KILLER = OT_H, /* TODO */ ++ INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER = OT_PLACEHOLDER, /* Don't care. */ ++ INDIC_SYLLABIC_CATEGORY_PURE_KILLER = OT_M, /* Is like a vowel matra. */ + INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER = OT_RS, ++ INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER = OT_M, /* Misc Khmer signs. */ + INDIC_SYLLABIC_CATEGORY_TONE_LETTER = OT_X, + INDIC_SYLLABIC_CATEGORY_TONE_MARK = OT_N, + INDIC_SYLLABIC_CATEGORY_VIRAMA = OT_H, +@@ -161,20 +165,24 @@ + INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT = POS_PRE_M + }; + +-/* Note: We use ASSERT_STATIC_EXPR_ZERO() instead of ASSERT_STATIC_EXPR() and the comma operation +- * because gcc fails to optimize the latter and fills the table in at runtime. */ + #define INDIC_COMBINE_CATEGORIES(S,M) \ +- (ASSERT_STATIC_EXPR_ZERO (M == INDIC_MATRA_CATEGORY_NOT_APPLICABLE || \ +- ( \ +- S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \ +- S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \ +- S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \ +- S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \ +- S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \ +- S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \ +- false)) + \ +- ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \ +- ((M << 8) | S)) ++ ( \ ++ ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \ ++ ( S | \ ++ ( \ ++ ( \ ++ S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \ ++ S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \ ++ S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \ ++ S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \ ++ S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \ ++ S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \ ++ false \ ++ ? M : INDIC_MATRA_CATEGORY_NOT_APPLICABLE \ ++ ) << 8 \ ++ ) \ ++ ) \ ++ ) + + HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE + hb_indic_get_categories (hb_codepoint_t u); +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-indic-table.cc gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-indic-table.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc 2016-06-05 23:49:54.888832464 +0200 +@@ -6,63 +6,67 @@ + * + * on files with these headers: + * +- * # IndicSyllabicCategory-7.0.0.txt +- * # Date: 2014-06-03, 07:00:00 GMT [KW, LI, AG, RP] +- * # IndicMatraCategory-7.0.0.txt +- * # Date: 2014-06-03, 07:00:00 GMT [KW, LI, AG, RP] +- * # Blocks-7.0.0.txt +- * # Date: 2014-04-03, 23:23:00 GMT [RP, KW] ++ * # IndicSyllabicCategory-8.0.0.txt ++ * # Date: 2015-05-12, 10:00:00 GMT [RP, KW, LI] ++ * # IndicPositionalCategory-8.0.0.txt ++ * # Date: 2015-05-12, 10:00:00 GMT [RP, KW, LI] ++ * # Blocks-8.0.0.txt ++ * # Date: 2014-11-10, 23:04:00 GMT [KW] + */ + + #include "hb-ot-shape-complex-indic-private.hh" + + + #define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 13 chars; Avagraha */ +-#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 59 chars; Bindu */ ++#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 60 chars; Bindu */ + #define ISC_BJN INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER /* 20 chars; Brahmi_Joining_Number */ +-#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 30 chars; Cantillation_Mark */ +-#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 1744 chars; Consonant */ ++#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 52 chars; Cantillation_Mark */ ++#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 1805 chars; Consonant */ + #define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 7 chars; Consonant_Dead */ +-#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 61 chars; Consonant_Final */ ++#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 62 chars; Consonant_Final */ + #define ISC_CHL INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER /* 5 chars; Consonant_Head_Letter */ +-#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 19 chars; Consonant_Medial */ +-#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 11 chars; Consonant_Placeholder */ ++#define ISC_CK INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER /* 2 chars; Consonant_Killer */ ++#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 22 chars; Consonant_Medial */ ++#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 13 chars; Consonant_Placeholder */ + #define ISC_CPR INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA /* 1 chars; Consonant_Preceding_Repha */ ++#define ISC_CPrf INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED /* 2 chars; Consonant_Prefixed */ + #define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 61 chars; Consonant_Subjoined */ + #define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 4 chars; Consonant_Succeeding_Repha */ ++#define ISC_CWS INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER /* 4 chars; Consonant_With_Stacker */ + #define ISC_GM INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK /* 2 chars; Gemination_Mark */ + #define ISC_IS INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER /* 7 chars; Invisible_Stacker */ + #define ISC_ZWJ INDIC_SYLLABIC_CATEGORY_JOINER /* 1 chars; Joiner */ + #define ISC_ML INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER /* 1 chars; Modifying_Letter */ + #define ISC_ZWNJ INDIC_SYLLABIC_CATEGORY_NON_JOINER /* 1 chars; Non_Joiner */ +-#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 18 chars; Nukta */ +-#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 408 chars; Number */ ++#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 23 chars; Nukta */ ++#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 420 chars; Number */ + #define ISC_NJ INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER /* 1 chars; Number_Joiner */ + #define ISC_x INDIC_SYLLABIC_CATEGORY_OTHER /* 1 chars; Other */ +-#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 15 chars; Pure_Killer */ +-#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 3 chars; Register_Shifter */ ++#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 16 chars; Pure_Killer */ ++#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 2 chars; Register_Shifter */ ++#define ISC_SM INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER /* 20 chars; Syllable_Modifier */ + #define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 7 chars; Tone_Letter */ +-#define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 62 chars; Tone_Mark */ ++#define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 42 chars; Tone_Mark */ + #define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 22 chars; Virama */ + #define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 29 chars; Visarga */ + #define ISC_Vo INDIC_SYLLABIC_CATEGORY_VOWEL /* 30 chars; Vowel */ +-#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 553 chars; Vowel_Dependent */ +-#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 395 chars; Vowel_Independent */ ++#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 572 chars; Vowel_Dependent */ ++#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 404 chars; Vowel_Independent */ + +-#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 142 chars; Bottom */ ++#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 256 chars; Bottom */ + #define IMC_BR INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT /* 2 chars; Bottom_And_Right */ +-#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 57 chars; Left */ ++#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 55 chars; Left */ + #define IMC_LR INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT /* 21 chars; Left_And_Right */ + #define IMC_x INDIC_MATRA_CATEGORY_NOT_APPLICABLE /* 1 chars; Not_Applicable */ +-#define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 2 chars; Overstruck */ +-#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 163 chars; Right */ +-#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 169 chars; Top */ ++#define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 10 chars; Overstruck */ ++#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 249 chars; Right */ ++#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 324 chars; Top */ + #define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 10 chars; Top_And_Bottom */ + #define IMC_TBR INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT /* 1 chars; Top_And_Bottom_And_Right */ + #define IMC_TL INDIC_MATRA_CATEGORY_TOP_AND_LEFT /* 6 chars; Top_And_Left */ + #define IMC_TLR INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT /* 4 chars; Top_And_Left_And_Right */ + #define IMC_TR INDIC_MATRA_CATEGORY_TOP_AND_RIGHT /* 13 chars; Top_And_Right */ +-#define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT /* 15 chars; Visual_Order_Left */ ++#define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT /* 19 chars; Visual_Order_Left */ + + #define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M) + +@@ -79,29 +83,33 @@ + /* 0030 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 0038 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x00d0u 24 ++#define indic_offset_0x00b0u 24 + + + /* Latin-1 Supplement */ + ++ /* 00B0 */ _(x,x), _(x,x), _(SM,x), _(SM,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 00B8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 00C0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 00C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 00D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x), + +-#define indic_offset_0x0900u 32 ++#define indic_offset_0x0900u 64 + + + /* Devanagari */ + +- /* 0900 */ _(Bi,x), _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0900 */ _(Bi,T), _(Bi,T), _(Bi,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 0908 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 0910 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 0918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0920 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0928 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0930 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 0938 */ _(C,x), _(C,x), _(M,T), _(M,R), _(N,x), _(A,x), _(M,R), _(M,L), ++ /* 0938 */ _(C,x), _(C,x), _(M,T), _(M,R), _(N,B), _(A,x), _(M,R), _(M,L), + /* 0940 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), + /* 0948 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(V,B), _(M,L), _(M,R), +- /* 0950 */ _(x,x), _(TM,x), _(TM,x), _(x,x), _(x,x), _(M,T), _(M,B), _(M,B), ++ /* 0950 */ _(x,x), _(Ca,T), _(Ca,B), _(x,T), _(x,T), _(M,T), _(M,B), _(M,B), + /* 0958 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0960 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 0968 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), +@@ -110,14 +118,14 @@ + + /* Bengali */ + +- /* 0980 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0980 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0988 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x), + /* 0990 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 0998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 09A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 09A8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 09B0 */ _(C,x), _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), +- /* 09B8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,L), ++ /* 09B8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,L), + /* 09C0 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), _(M,L), + /* 09C8 */ _(M,L), _(x,x), _(x,x), _(M,LR), _(M,LR), _(V,B), _(CD,x), _(x,x), + /* 09D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), +@@ -129,33 +137,33 @@ + + /* Gurmukhi */ + +- /* 0A00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0A00 */ _(x,x), _(Bi,T), _(Bi,T), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0A08 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x), + /* 0A10 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 0A18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0A28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0A30 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), +- /* 0A38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(x,x), _(M,R), _(M,L), ++ /* 0A38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(x,x), _(M,R), _(M,L), + /* 0A40 */ _(M,R), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), + /* 0A48 */ _(M,T), _(x,x), _(x,x), _(M,T), _(M,T), _(V,B), _(x,x), _(x,x), + /* 0A50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0A58 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), + /* 0A60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 0A68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), +- /* 0A70 */ _(Bi,x), _(GM,T), _(CP,x), _(CP,x), _(x,x), _(CM,x), _(x,x), _(x,x), ++ /* 0A70 */ _(Bi,T), _(GM,T), _(CP,x), _(CP,x), _(x,x), _(CM,B), _(x,x), _(x,x), + /* 0A78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Gujarati */ + +- /* 0A80 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0A80 */ _(x,x), _(Bi,T), _(Bi,T), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0A88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), + /* 0A90 */ _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 0A98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0AA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0AA8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0AB0 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), +- /* 0AB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,L), ++ /* 0AB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,L), + /* 0AC0 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(x,x), _(M,T), + /* 0AC8 */ _(M,T), _(M,TR), _(x,x), _(M,R), _(M,R), _(V,B), _(x,x), _(x,x), + /* 0AD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +@@ -163,18 +171,18 @@ + /* 0AE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 0AE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 0AF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 0AF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 0AF8 */ _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Oriya */ + +- /* 0B00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0B00 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x), + /* 0B10 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 0B18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0B20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0B28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0B30 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), +- /* 0B38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,T), ++ /* 0B38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,T), + /* 0B40 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), _(M,L), + /* 0B48 */ _(M,TL), _(x,x), _(x,x), _(M,LR),_(M,TLR), _(V,B), _(x,x), _(x,x), + /* 0B50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,TR), +@@ -186,7 +194,7 @@ + + /* Tamil */ + +- /* 0B80 */ _(x,x), _(x,x), _(Bi,x), _(ML,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0B80 */ _(x,x), _(x,x), _(Bi,T), _(ML,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0B88 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(VI,x), _(VI,x), + /* 0B90 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(x,x), _(x,x), + /* 0B98 */ _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(C,x), _(C,x), +@@ -194,7 +202,7 @@ + /* 0BA8 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), + /* 0BB0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0BB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R), +- /* 0BC0 */ _(M,T), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(M,L), _(M,L), ++ /* 0BC0 */ _(M,T), _(M,R), _(M,R), _(x,x), _(x,x), _(x,x), _(M,L), _(M,L), + /* 0BC8 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T), _(x,x), _(x,x), + /* 0BD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), + /* 0BD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +@@ -205,7 +213,7 @@ + + /* Telugu */ + +- /* 0C00 */ _(Bi,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0C00 */ _(Bi,T), _(Bi,R), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0C08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), + /* 0C10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 0C18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +@@ -216,7 +224,7 @@ + /* 0C40 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,T), + /* 0C48 */ _(M,TB), _(x,x), _(M,T), _(M,T), _(M,T), _(V,T), _(x,x), _(x,x), + /* 0C50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,B), _(x,x), +- /* 0C58 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 0C58 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0C60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 0C68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 0C70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +@@ -224,26 +232,26 @@ + + /* Kannada */ + +- /* 0C80 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0C80 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0C88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), + /* 0C90 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 0C98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0CA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0CA8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0CB0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), +- /* 0CB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,T), ++ /* 0CB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,T), + /* 0CC0 */ _(M,TR), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,TR), + /* 0CC8 */ _(M,TR), _(x,x), _(M,TR), _(M,TR), _(M,T), _(V,T), _(x,x), _(x,x), + /* 0CD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R), _(x,x), + /* 0CD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(x,x), + /* 0CE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 0CE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), +- /* 0CF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 0CF0 */ _(x,x),_(CWS,x),_(CWS,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0CF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Malayalam */ + +- /* 0D00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0D00 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0D08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), + /* 0D10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 0D18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +@@ -254,7 +262,7 @@ + /* 0D40 */ _(M,R), _(M,R), _(M,R), _(M,B), _(M,B), _(x,x), _(M,L), _(M,L), + /* 0D48 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T),_(CPR,x), _(x,x), + /* 0D50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), +- /* 0D58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 0D58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x), + /* 0D60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 0D68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 0D70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +@@ -262,7 +270,7 @@ + + /* Sinhala */ + +- /* 0D80 */ _(x,x), _(x,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0D80 */ _(x,x), _(x,x), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0D88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 0D90 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), + /* 0D98 */ _(x,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +@@ -278,7 +286,7 @@ + /* 0DE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 0DF0 */ _(x,x), _(x,x), _(M,R), _(M,R), _(x,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x1000u 1304 ++#define indic_offset_0x1000u 1336 + + + /* Myanmar */ +@@ -289,22 +297,22 @@ + /* 1018 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1020 */ _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 1028 */ _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R), _(M,T), _(M,T), _(M,B), +- /* 1030 */ _(M,B), _(M,L), _(M,T), _(M,T), _(M,T), _(M,T), _(Bi,x), _(TM,x), +- /* 1038 */ _(Vs,x), _(IS,x), _(PK,T), _(CM,x), _(CM,x), _(CM,x), _(CM,x), _(C,x), ++ /* 1030 */ _(M,B), _(M,L), _(M,T), _(M,T), _(M,T), _(M,T), _(Bi,T), _(TM,B), ++ /* 1038 */ _(Vs,R), _(IS,x), _(PK,T), _(CM,R), _(CM,x), _(CM,B), _(CM,B), _(C,x), + /* 1040 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 1048 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x), _(x,x), + /* 1050 */ _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R), +- /* 1058 */ _(M,B), _(M,B), _(C,x), _(C,x), _(C,x), _(C,x), _(CM,x), _(CM,x), +- /* 1060 */ _(CM,x), _(C,x), _(M,R), _(TM,x), _(TM,x), _(C,x), _(C,x), _(M,R), +- /* 1068 */ _(M,R), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(C,x), _(C,x), ++ /* 1058 */ _(M,B), _(M,B), _(C,x), _(C,x), _(C,x), _(C,x), _(CM,B), _(CM,B), ++ /* 1060 */ _(CM,B), _(C,x), _(M,R), _(TM,R), _(TM,R), _(C,x), _(C,x), _(M,R), ++ /* 1068 */ _(M,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(C,x), _(C,x), + /* 1070 */ _(C,x), _(M,T), _(M,T), _(M,T), _(M,T), _(C,x), _(C,x), _(C,x), + /* 1078 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 1080 */ _(C,x), _(C,x), _(CM,x), _(M,R), _(M,L), _(M,T), _(M,T), _(TM,x), +- /* 1088 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(C,x), _(TM,x), ++ /* 1080 */ _(C,x), _(C,x), _(CM,B), _(M,R), _(M,L), _(M,T), _(M,T), _(TM,R), ++ /* 1088 */ _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,B), _(C,x), _(TM,R), + /* 1090 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), +- /* 1098 */ _(Nd,x), _(Nd,x), _(TM,x), _(TM,x), _(M,R), _(M,T), _(x,x), _(x,x), ++ /* 1098 */ _(Nd,x), _(Nd,x), _(TM,R), _(TM,R), _(M,R), _(M,T), _(x,x), _(x,x), + +-#define indic_offset_0x1700u 1464 ++#define indic_offset_0x1700u 1496 + + + /* Tagalog */ +@@ -345,14 +353,14 @@ + /* 17A8 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 17B0 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(M,R), _(M,T), + /* 17B8 */ _(M,T), _(M,T), _(M,T), _(M,B), _(M,B), _(M,B), _(M,TL),_(M,TLR), +- /* 17C0 */ _(M,LR), _(M,L), _(M,L), _(M,L), _(M,LR), _(M,LR), _(Bi,x), _(Vs,x), +- /* 17C8 */ _(M,R), _(RS,T), _(RS,T), _(RS,T),_(CSR,T), _(M,T), _(M,T), _(M,T), +- /* 17D0 */ _(M,T), _(PK,T), _(IS,x), _(M,T), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 17D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(A,x), _(x,x), _(x,x), _(x,x), ++ /* 17C0 */ _(M,LR), _(M,L), _(M,L), _(M,L), _(M,LR), _(M,LR), _(Bi,T), _(Vs,R), ++ /* 17C8 */ _(M,R), _(RS,T), _(RS,T), _(SM,T),_(CSR,T), _(CK,T), _(SM,T), _(SM,T), ++ /* 17D0 */ _(SM,T), _(PK,T), _(IS,x), _(SM,T), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 17D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(A,x), _(x,T), _(x,x), _(x,x), + /* 17E0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 17E8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x1900u 1704 ++#define indic_offset_0x1900u 1736 + + + /* Limbu */ +@@ -362,9 +370,9 @@ + /* 1910 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), + /* 1920 */ _(M,T), _(M,T), _(M,B), _(M,R), _(M,R), _(M,TR), _(M,TR), _(M,T), +- /* 1928 */ _(M,T), _(CS,x), _(CS,x), _(CS,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 1930 */ _(CF,x), _(CF,x), _(Bi,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), +- /* 1938 */ _(CF,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 1928 */ _(M,T), _(CS,R), _(CS,R), _(CS,R), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 1930 */ _(CF,R), _(CF,R), _(Bi,B), _(CF,R), _(CF,R), _(CF,R), _(CF,R), _(CF,R), ++ /* 1938 */ _(CF,R), _(CF,B), _(M,T), _(SM,B), _(x,x), _(x,x), _(x,x), _(x,x), + /* 1940 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 1948 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + +@@ -385,10 +393,10 @@ + /* 1998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 19A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 19A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 19B0 */ _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,L), _(M,L), _(M,L), +- /* 19B8 */ _(M,R), _(M,R), _(M,L), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), ++ /* 19B0 */ _(M,R), _(M,R), _(M,R), _(M,R), _(M,R),_(M,VOL),_(M,VOL),_(M,VOL), ++ /* 19B8 */ _(M,R), _(M,R),_(M,VOL), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), + /* 19C0 */ _(M,R), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), +- /* 19C8 */ _(TM,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 19C8 */ _(TM,R), _(TM,R), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 19D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 19D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 19E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +@@ -411,47 +419,47 @@ + /* 1A38 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1A40 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1A48 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), +- /* 1A50 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(CM,L), _(CM,x), _(CF,x), +- /* 1A58 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(x,x), ++ /* 1A50 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(CM,L), _(CM,B), _(CF,R), ++ /* 1A58 */ _(CF,T), _(CF,T), _(CF,T), _(CF,B), _(CF,B), _(CF,B), _(CF,B), _(x,x), + /* 1A60 */ _(IS,x), _(M,R), _(M,T), _(M,R), _(M,R), _(M,T), _(M,T), _(M,T), + /* 1A68 */ _(M,T), _(M,B), _(M,B), _(M,T), _(M,B), _(M,R), _(M,L), _(M,L), +- /* 1A70 */ _(M,L), _(M,L), _(M,L), _(M,T), _(M,T), _(TM,x), _(TM,x), _(TM,x), +- /* 1A78 */ _(TM,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 1A70 */ _(M,L), _(M,L), _(M,L), _(M,T), _(M,T), _(TM,T), _(TM,T), _(TM,T), ++ /* 1A78 */ _(TM,T), _(TM,T), _(SM,T), _(SM,T), _(SM,T), _(x,x), _(x,x), _(SM,B), + /* 1A80 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 1A88 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 1A90 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 1A98 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x1b00u 2120 ++#define indic_offset_0x1b00u 2152 + + + /* Balinese */ + +- /* 1B00 */ _(Bi,x), _(Bi,x), _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 1B00 */ _(Bi,T), _(Bi,T), _(Bi,T),_(CSR,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), + /* 1B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 1B10 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1B18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1B20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1B28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 1B30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(N,x), _(M,R), _(M,T), _(M,T), ++ /* 1B30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(N,T), _(M,R), _(M,T), _(M,T), + /* 1B38 */ _(M,B), _(M,B), _(M,B), _(M,BR), _(M,TB),_(M,TBR), _(M,L), _(M,L), + /* 1B40 */ _(M,LR), _(M,LR), _(M,T), _(M,TR), _(V,R), _(C,x), _(C,x), _(C,x), + /* 1B48 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 1B50 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 1B58 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 1B60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 1B68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 1B70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 1B68 */ _(x,x), _(x,x), _(x,x), _(x,T), _(x,B), _(x,T), _(x,T), _(x,T), ++ /* 1B70 */ _(x,T), _(x,T), _(x,T), _(x,T), _(x,x), _(x,x), _(x,x), _(x,x), + /* 1B78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Sundanese */ + +- /* 1B80 */ _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 1B80 */ _(Bi,T),_(CSR,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 1B88 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1B90 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1B98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 1BA0 */ _(C,x), _(CS,x), _(CS,x), _(CS,x), _(M,T), _(M,B), _(M,L), _(M,R), +- /* 1BA8 */ _(M,T), _(M,T), _(PK,R), _(IS,x), _(CS,x), _(CS,x), _(C,x), _(C,x), ++ /* 1BA0 */ _(C,x), _(CS,R), _(CS,B), _(CS,B), _(M,T), _(M,B), _(M,L), _(M,R), ++ /* 1BA8 */ _(M,T), _(M,T), _(PK,R), _(IS,x), _(CS,B), _(CS,B), _(C,x), _(C,x), + /* 1BB0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 1BB8 */ _(Nd,x), _(Nd,x), _(A,x), _(C,x), _(C,x), _(C,x), _(CF,x), _(CF,x), + +@@ -461,9 +469,9 @@ + /* 1BC8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1BD0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1BD8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 1BE0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(N,x), _(M,R), ++ /* 1BE0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(N,T), _(M,R), + /* 1BE8 */ _(M,T), _(M,T), _(M,R), _(M,R), _(M,R), _(M,T), _(M,R), _(M,T), +- /* 1BF0 */ _(CF,x), _(CF,x), _(PK,R), _(PK,R), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 1BF0 */ _(CF,T), _(CF,T), _(PK,R), _(PK,R), _(x,x), _(x,x), _(x,x), _(x,x), + /* 1BF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Lepcha */ +@@ -472,39 +480,49 @@ + /* 1C08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1C10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1C18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 1C20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(CS,x), _(CS,x), _(M,R), _(M,L), +- /* 1C28 */ _(M,L), _(M,TL), _(M,R), _(M,R), _(M,B), _(CF,x), _(CF,x), _(CF,x), +- /* 1C30 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(Bi,L), _(Bi,L), _(x,x), _(N,x), ++ /* 1C20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(CS,R), _(CS,R), _(M,R), _(M,L), ++ /* 1C28 */ _(M,L), _(M,TL), _(M,R), _(M,R), _(M,B), _(CF,T), _(CF,T), _(CF,T), ++ /* 1C30 */ _(CF,T), _(CF,T), _(CF,T), _(CF,T), _(Bi,L), _(Bi,L), _(SM,T), _(N,B), + /* 1C38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 1C40 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 1C48 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(C,x), + +-#define indic_offset_0x1cd0u 2456 ++#define indic_offset_0x1cd0u 2488 + + + /* Vedic Extensions */ + +- /* 1CD0 */ _(TM,x), _(TM,x), _(TM,x), _(x,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), +- /* 1CD8 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), +- /* 1CE0 */ _(TM,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 1CE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 1CF0 */ _(x,x), _(x,x), _(Vs,x), _(Vs,x), _(TM,x), _(x,x), _(x,x), _(x,x), ++ /* 1CD0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(x,x), _(Ca,O), _(Ca,B), _(Ca,B), _(Ca,B), ++ /* 1CD8 */ _(Ca,B), _(Ca,B), _(Ca,T), _(Ca,T), _(Ca,B), _(Ca,B), _(Ca,B), _(Ca,B), ++ /* 1CE0 */ _(Ca,T), _(Ca,R), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O), ++ /* 1CE8 */ _(x,O), _(x,x), _(x,x), _(x,x), _(x,x), _(x,B), _(x,x), _(x,x), ++ /* 1CF0 */ _(x,x), _(x,x), _(Vs,x), _(Vs,x), _(Ca,T), _(x,x), _(x,x), _(x,x), ++ /* 1CF8 */ _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x2008u 2496 ++#define indic_offset_0x2008u 2536 + + + /* General Punctuation */ + + /* 2008 */ _(x,x), _(x,x), _(x,x), _(x,x),_(ZWNJ,x),_(ZWJ,x), _(x,x), _(x,x), +- /* 2010 */ _(x,x), _(x,x), _(CP,x), _(CP,x), _(CP,x), _(x,x), _(x,x), _(x,x), ++ /* 2010 */ _(CP,x), _(CP,x), _(CP,x), _(CP,x), _(CP,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0xa800u 2512 ++#define indic_offset_0x2070u 2552 ++ ++ ++ /* Superscripts and Subscripts */ ++ ++ /* 2070 */ _(x,x), _(x,x), _(x,x), _(x,x), _(SM,x), _(x,x), _(x,x), _(x,x), ++ /* 2078 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 2080 */ _(x,x), _(x,x), _(SM,x), _(SM,x), _(SM,x), _(x,x), _(x,x), _(x,x), ++ ++#define indic_offset_0xa800u 2576 + + + /* Syloti Nagri */ + + /* A800 */ _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(PK,T), _(C,x), +- /* A808 */ _(C,x), _(C,x), _(C,x), _(Bi,x), _(C,x), _(C,x), _(C,x), _(C,x), ++ /* A808 */ _(C,x), _(C,x), _(C,x), _(Bi,T), _(C,x), _(C,x), _(C,x), _(C,x), + /* A810 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A818 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A820 */ _(C,x), _(C,x), _(C,x), _(M,R), _(M,R), _(M,B), _(M,T), _(M,R), +@@ -525,13 +543,13 @@ + + /* Saurashtra */ + +- /* A880 */ _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), ++ /* A880 */ _(Bi,R), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* A888 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* A890 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A898 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A8A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A8A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* A8B0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(CF,x), _(M,R), _(M,R), _(M,R), ++ /* A8B0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(CF,R), _(M,R), _(M,R), _(M,R), + /* A8B8 */ _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), + /* A8C0 */ _(M,R), _(M,R), _(M,R), _(M,R), _(V,B), _(x,x), _(x,x), _(x,x), + /* A8C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +@@ -540,9 +558,9 @@ + + /* Devanagari Extended */ + +- /* A8E0 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), +- /* A8E8 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), +- /* A8F0 */ _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* A8E0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), ++ /* A8E8 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), ++ /* A8F0 */ _(Ca,T), _(Ca,T), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A8F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Kayah Li */ +@@ -552,15 +570,15 @@ + /* A910 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A920 */ _(C,x), _(C,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), +- /* A928 */ _(Vo,x), _(Vo,x), _(Vo,x), _(TM,x), _(TM,x), _(TM,x), _(x,x), _(x,x), ++ /* A928 */ _(Vo,x), _(Vo,x), _(Vo,x), _(TM,B), _(TM,B), _(TM,B), _(x,x), _(x,x), + + /* Rejang */ + + /* A930 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A938 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A940 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,B), +- /* A948 */ _(M,B), _(M,B), _(M,T), _(M,B), _(M,B), _(M,B), _(M,B), _(CF,x), +- /* A950 */ _(CF,x), _(CF,x), _(CF,x), _(PK,R), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* A948 */ _(M,B), _(M,B), _(M,T), _(M,B), _(M,B), _(M,B), _(M,B), _(CF,T), ++ /* A950 */ _(CF,T), _(CF,T), _(CF,R), _(PK,R), _(x,x), _(x,x), _(x,x), _(x,x), + /* A958 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A960 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A968 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +@@ -569,14 +587,14 @@ + + /* Javanese */ + +- /* A980 */ _(Bi,x), _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), ++ /* A980 */ _(Bi,T), _(Bi,T),_(CSR,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* A988 */ _(VI,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), + /* A990 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A9A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A9A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* A9B0 */ _(C,x), _(C,x), _(C,x), _(N,x), _(M,R), _(M,R), _(M,T), _(M,T), +- /* A9B8 */ _(M,B), _(M,B), _(M,L), _(M,L), _(M,T), _(CS,x), _(CM,x), _(CM,x), ++ /* A9B0 */ _(C,x), _(C,x), _(C,x), _(N,T), _(M,R), _(M,R), _(M,T), _(M,T), ++ /* A9B8 */ _(M,B), _(M,B), _(M,L), _(M,L), _(M,T), _(CS,R), _(CM,R), _(CM,R), + /* A9C0 */ _(V,BR), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A9C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A9D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), +@@ -584,7 +602,7 @@ + + /* Myanmar Extended-B */ + +- /* A9E0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(C,x), ++ /* A9E0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,T), _(x,x), _(C,x), + /* A9E8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A9F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* A9F8 */ _(Nd,x), _(Nd,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), +@@ -597,10 +615,10 @@ + /* AA18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AA20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AA28 */ _(C,x), _(M,T), _(M,T), _(M,T), _(M,T), _(M,B), _(M,T), _(M,L), +- /* AA30 */ _(M,L), _(M,T), _(M,B), _(CM,x), _(CM,L), _(CM,x), _(CM,x), _(x,x), ++ /* AA30 */ _(M,L), _(M,T), _(M,B), _(CM,R), _(CM,L), _(CM,B), _(CM,B), _(x,x), + /* AA38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* AA40 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), +- /* AA48 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(x,x), _(x,x), ++ /* AA40 */ _(CF,x), _(CF,x), _(CF,x), _(CF,T), _(CF,x), _(CF,x), _(CF,x), _(CF,x), ++ /* AA48 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,T), _(CF,R), _(x,x), _(x,x), + /* AA50 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* AA58 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + +@@ -609,7 +627,7 @@ + /* AA60 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AA68 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AA70 */ _(x,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,x), _(TM,x), _(TM,x), _(C,x), _(C,x), ++ /* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,R), _(TM,T), _(TM,R), _(C,x), _(C,x), + + /* Tai Viet */ + +@@ -620,8 +638,8 @@ + /* AAA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AAA8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AAB0 */ _(M,T), _(M,R), _(M,T), _(M,T), _(M,B),_(M,VOL),_(M,VOL), _(M,T), +- /* AAB8 */ _(M,T),_(M,VOL), _(M,R),_(M,VOL),_(M,VOL), _(M,R), _(M,T), _(TM,x), +- /* AAC0 */ _(TL,x), _(TM,x), _(TL,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* AAB8 */ _(M,T),_(M,VOL), _(M,R),_(M,VOL),_(M,VOL), _(M,R), _(M,T), _(TM,T), ++ /* AAC0 */ _(TL,x), _(TM,T), _(TL,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* AAC8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* AAD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* AAD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +@@ -630,9 +648,9 @@ + + /* AAE0 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AAE8 */ _(C,x), _(C,x), _(C,x), _(M,L), _(M,B), _(M,T), _(M,L), _(M,R), +- /* AAF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Vs,x), _(IS,x), _(x,x), ++ /* AAF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Vs,R), _(IS,x), _(x,x), + +-#define indic_offset_0xabc0u 3272 ++#define indic_offset_0xabc0u 3336 + + + /* Meetei Mayek */ +@@ -642,31 +660,31 @@ + /* ABD0 */ _(C,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* ABD8 */ _(C,x), _(C,x), _(C,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), + /* ABE0 */ _(CF,x), _(CF,x), _(CF,x), _(M,R), _(M,R), _(M,T), _(M,R), _(M,R), +- /* ABE8 */ _(M,B), _(M,R), _(M,R), _(x,x), _(TM,x), _(PK,B), _(x,x), _(x,x), ++ /* ABE8 */ _(M,B), _(M,R), _(M,R), _(x,x), _(TM,R), _(PK,B), _(x,x), _(x,x), + /* ABF0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* ABF8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x10a00u 3336 ++#define indic_offset_0x10a00u 3400 + + + /* Kharoshthi */ + + /* 10A00 */ _(C,x), _(M,O), _(M,B), _(M,B), _(x,x), _(M,T), _(M,O), _(x,x), +- /* 10A08 */ _(x,x), _(x,x), _(x,x), _(x,x), _(M,B), _(x,x), _(Bi,x), _(Vs,x), ++ /* 10A08 */ _(x,x), _(x,x), _(x,x), _(x,x), _(M,B), _(M,B), _(Bi,B), _(Vs,T), + /* 10A10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), + /* 10A18 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 10A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 10A28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 10A30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 10A38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(IS,x), ++ /* 10A38 */ _(N,T), _(N,B), _(N,B), _(x,x), _(x,x), _(x,x), _(x,x), _(IS,x), + /* 10A40 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + +-#define indic_offset_0x11000u 3408 ++#define indic_offset_0x11000u 3472 + + + /* Brahmi */ + +- /* 11000 */ _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 11000 */ _(Bi,R), _(Bi,T), _(Vs,R),_(CWS,x),_(CWS,x), _(VI,x), _(VI,x), _(VI,x), + /* 11008 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 11010 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11018 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +@@ -685,21 +703,21 @@ + + /* Kaithi */ + +- /* 11080 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 11080 */ _(Bi,T), _(Bi,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 11088 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 11090 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11098 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 110A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 110A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 110B0 */ _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), _(M,T), _(M,T), _(M,R), +- /* 110B8 */ _(M,R), _(V,B), _(N,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 110B8 */ _(M,R), _(V,B), _(N,B), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x11100u 3600 ++#define indic_offset_0x11100u 3664 + + + /* Chakma */ + +- /* 11100 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), ++ /* 11100 */ _(Bi,T), _(Bi,T), _(Vs,T), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), + /* 11108 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11110 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11118 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +@@ -716,12 +734,12 @@ + /* 11158 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11160 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11168 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 11170 */ _(C,x), _(C,x), _(C,x), _(N,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 11170 */ _(C,x), _(C,x), _(C,x), _(N,B), _(x,x), _(x,x), _(x,x), _(x,x), + /* 11178 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Sharada */ + +- /* 11180 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 11180 */ _(Bi,T), _(Bi,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 11188 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 11190 */ _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11198 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +@@ -729,8 +747,8 @@ + /* 111A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 111B0 */ _(C,x), _(C,x), _(C,x), _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), + /* 111B8 */ _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,TR), +- /* 111C0 */ _(V,R), _(A,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 111C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 111C0 */ _(V,R), _(A,x),_(CPrf,x),_(CPrf,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 111C8 */ _(x,x), _(x,x), _(N,x), _(M,T), _(M,B), _(x,x), _(x,x), _(x,x), + /* 111D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 111D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + +@@ -749,11 +767,20 @@ + /* 11218 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11220 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11228 */ _(C,x), _(C,x), _(C,x), _(C,x), _(M,R), _(M,R), _(M,R), _(M,B), +- /* 11230 */ _(M,T), _(M,T), _(M,TR), _(M,TR), _(Bi,x), _(V,R), _(N,x), _(GM,T), ++ /* 11230 */ _(M,T), _(M,T), _(M,TR), _(M,TR), _(Bi,T), _(V,R), _(N,T), _(GM,T), + +-#define indic_offset_0x112b0u 3912 ++#define indic_offset_0x11280u 3976 + + ++ /* Multani */ ++ ++ /* 11280 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(x,x), ++ /* 11288 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), ++ /* 11290 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), ++ /* 11298 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), ++ /* 112A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), ++ /* 112A8 */ _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ + /* Khudawadi */ + + /* 112B0 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), +@@ -761,15 +788,15 @@ + /* 112C0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 112C8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 112D0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 112D8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(Bi,x), ++ /* 112D8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(Bi,T), + /* 112E0 */ _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), +- /* 112E8 */ _(M,T), _(N,x), _(PK,B), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 112E8 */ _(M,T), _(N,B), _(PK,B), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 112F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 112F8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Grantha */ + +- /* 11300 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 11300 */ _(Bi,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 11308 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x), + /* 11310 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 11318 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +@@ -781,11 +808,11 @@ + /* 11348 */ _(M,L), _(x,x), _(x,x), _(M,LR), _(M,LR), _(V,R), _(x,x), _(x,x), + /* 11350 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), + /* 11358 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 11360 */ _(VI,x), _(VI,x), _(M,R), _(M,R), _(x,x), _(x,x), _(Ca,x), _(Ca,x), +- /* 11368 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), +- /* 11370 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), ++ /* 11360 */ _(VI,x), _(VI,x), _(M,R), _(M,R), _(x,x), _(x,x), _(Ca,T), _(Ca,T), ++ /* 11368 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(x,x), _(x,x), _(x,x), ++ /* 11370 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x11480u 4112 ++#define indic_offset_0x11480u 4224 + + + /* Tirhuta */ +@@ -797,13 +824,13 @@ + /* 114A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 114A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 114B0 */ _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,B), +- /* 114B8 */ _(M,B), _(M,L), _(M,T), _(M,TL), _(M,LR), _(M,R), _(M,LR), _(Bi,x), +- /* 114C0 */ _(Bi,x), _(Vs,x), _(V,B), _(N,x), _(A,x), _(x,x), _(x,x), _(x,x), ++ /* 114B8 */ _(M,B), _(M,L), _(M,T), _(M,TL), _(M,LR), _(M,R), _(M,LR), _(Bi,T), ++ /* 114C0 */ _(Bi,T), _(Vs,R), _(V,B), _(N,B), _(A,x), _(x,x), _(x,x), _(x,x), + /* 114C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 114D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 114D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x11580u 4208 ++#define indic_offset_0x11580u 4320 + + + /* Siddham */ +@@ -815,11 +842,15 @@ + /* 115A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 115A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,R), + /* 115B0 */ _(M,L), _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), +- /* 115B8 */ _(M,L), _(M,TL), _(M,LR),_(M,TLR), _(Bi,x), _(Bi,x), _(Vs,x), _(V,B), +- /* 115C0 */ _(N,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- +-#define indic_offset_0x11600u 4280 +- ++ /* 115B8 */ _(M,L), _(M,TL), _(M,LR),_(M,TLR), _(Bi,T), _(Bi,T), _(Vs,R), _(V,B), ++ /* 115C0 */ _(N,B), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 115C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 115D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 115D8 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), ++ /* 115E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 115E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 115F0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 115F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Modi */ + +@@ -830,8 +861,8 @@ + /* 11620 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11628 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11630 */ _(M,R), _(M,R), _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,B), +- /* 11638 */ _(M,B), _(M,T), _(M,T), _(M,R), _(M,R), _(Bi,x), _(Vs,x), _(V,B), +- /* 11640 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 11638 */ _(M,B), _(M,T), _(M,T), _(M,R), _(M,R), _(Bi,T), _(Vs,R), _(V,B), ++ /* 11640 */ _(M,T), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 11648 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 11650 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 11658 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +@@ -847,13 +878,30 @@ + /* 11690 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11698 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 116A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 116A8 */ _(C,x), _(C,x), _(C,x), _(Bi,x), _(Vs,x), _(M,T), _(M,L), _(M,R), +- /* 116B0 */ _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,T), _(V,T), _(N,x), ++ /* 116A8 */ _(C,x), _(C,x), _(C,x), _(Bi,T), _(Vs,R), _(M,T), _(M,L), _(M,R), ++ /* 116B0 */ _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,T), _(V,R), _(N,B), + /* 116B8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 116C0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 116C8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 116D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 116D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 116E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 116E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 116F0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 116F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ ++ /* Ahom */ ++ ++ /* 11700 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), ++ /* 11708 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), ++ /* 11710 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), ++ /* 11718 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(CM,B), _(CM,x), _(CM,T), ++ /* 11720 */ _(M,R), _(M,R), _(M,T), _(M,T), _(M,B), _(M,B), _(M,L), _(M,T), ++ /* 11728 */ _(M,B), _(M,T), _(M,T), _(PK,T), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 11730 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), ++ /* 11738 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), + +-}; /* Table items: 4488; occupancy: 73% */ ++}; /* Table items: 4768; occupancy: 72% */ + + INDIC_TABLE_ELEMENT_TYPE + hb_indic_get_categories (hb_codepoint_t u) +@@ -861,41 +909,41 @@ + switch (u >> 12) + { + case 0x0u: +- if (hb_in_range (u, 0x0028u, 0x0040u)) return indic_table[u - 0x0028u + indic_offset_0x0028u]; +- if (hb_in_range (u, 0x00D0u, 0x00D8u)) return indic_table[u - 0x00D0u + indic_offset_0x00d0u]; +- if (hb_in_range (u, 0x0900u, 0x0DF8u)) return indic_table[u - 0x0900u + indic_offset_0x0900u]; ++ if (hb_in_range (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u]; ++ if (hb_in_range (u, 0x00B0u, 0x00D7u)) return indic_table[u - 0x00B0u + indic_offset_0x00b0u]; ++ if (hb_in_range (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u]; + if (unlikely (u == 0x00A0u)) return _(CP,x); + break; + + case 0x1u: +- if (hb_in_range (u, 0x1000u, 0x10A0u)) return indic_table[u - 0x1000u + indic_offset_0x1000u]; +- if (hb_in_range (u, 0x1700u, 0x17F0u)) return indic_table[u - 0x1700u + indic_offset_0x1700u]; +- if (hb_in_range (u, 0x1900u, 0x1AA0u)) return indic_table[u - 0x1900u + indic_offset_0x1900u]; +- if (hb_in_range (u, 0x1B00u, 0x1C50u)) return indic_table[u - 0x1B00u + indic_offset_0x1b00u]; +- if (hb_in_range (u, 0x1CD0u, 0x1CF8u)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u]; ++ if (hb_in_range (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u]; ++ if (hb_in_range (u, 0x1700u, 0x17EFu)) return indic_table[u - 0x1700u + indic_offset_0x1700u]; ++ if (hb_in_range (u, 0x1900u, 0x1A9Fu)) return indic_table[u - 0x1900u + indic_offset_0x1900u]; ++ if (hb_in_range (u, 0x1B00u, 0x1C4Fu)) return indic_table[u - 0x1B00u + indic_offset_0x1b00u]; ++ if (hb_in_range (u, 0x1CD0u, 0x1CFFu)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u]; + break; + + case 0x2u: +- if (hb_in_range (u, 0x2008u, 0x2018u)) return indic_table[u - 0x2008u + indic_offset_0x2008u]; ++ if (hb_in_range (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u]; ++ if (hb_in_range (u, 0x2070u, 0x2087u)) return indic_table[u - 0x2070u + indic_offset_0x2070u]; + if (unlikely (u == 0x25CCu)) return _(CP,x); + break; + + case 0xAu: +- if (hb_in_range (u, 0xA800u, 0xAAF8u)) return indic_table[u - 0xA800u + indic_offset_0xa800u]; +- if (hb_in_range (u, 0xABC0u, 0xAC00u)) return indic_table[u - 0xABC0u + indic_offset_0xabc0u]; ++ if (hb_in_range (u, 0xA800u, 0xAAF7u)) return indic_table[u - 0xA800u + indic_offset_0xa800u]; ++ if (hb_in_range (u, 0xABC0u, 0xABFFu)) return indic_table[u - 0xABC0u + indic_offset_0xabc0u]; + break; + + case 0x10u: +- if (hb_in_range (u, 0x10A00u, 0x10A48u)) return indic_table[u - 0x10A00u + indic_offset_0x10a00u]; ++ if (hb_in_range (u, 0x10A00u, 0x10A47u)) return indic_table[u - 0x10A00u + indic_offset_0x10a00u]; + break; + + case 0x11u: +- if (hb_in_range (u, 0x11000u, 0x110C0u)) return indic_table[u - 0x11000u + indic_offset_0x11000u]; +- if (hb_in_range (u, 0x11100u, 0x11238u)) return indic_table[u - 0x11100u + indic_offset_0x11100u]; +- if (hb_in_range (u, 0x112B0u, 0x11378u)) return indic_table[u - 0x112B0u + indic_offset_0x112b0u]; +- if (hb_in_range (u, 0x11480u, 0x114E0u)) return indic_table[u - 0x11480u + indic_offset_0x11480u]; +- if (hb_in_range (u, 0x11580u, 0x115C8u)) return indic_table[u - 0x11580u + indic_offset_0x11580u]; +- if (hb_in_range (u, 0x11600u, 0x116D0u)) return indic_table[u - 0x11600u + indic_offset_0x11600u]; ++ if (hb_in_range (u, 0x11000u, 0x110BFu)) return indic_table[u - 0x11000u + indic_offset_0x11000u]; ++ if (hb_in_range (u, 0x11100u, 0x11237u)) return indic_table[u - 0x11100u + indic_offset_0x11100u]; ++ if (hb_in_range (u, 0x11280u, 0x11377u)) return indic_table[u - 0x11280u + indic_offset_0x11280u]; ++ if (hb_in_range (u, 0x11480u, 0x114DFu)) return indic_table[u - 0x11480u + indic_offset_0x11480u]; ++ if (hb_in_range (u, 0x11580u, 0x1173Fu)) return indic_table[u - 0x11580u + indic_offset_0x11580u]; + break; + + default: +@@ -914,11 +962,14 @@ + #undef ISC_CD + #undef ISC_CF + #undef ISC_CHL ++#undef ISC_CK + #undef ISC_CM + #undef ISC_CP + #undef ISC_CPR ++#undef ISC_CPrf + #undef ISC_CS + #undef ISC_CSR ++#undef ISC_CWS + #undef ISC_GM + #undef ISC_IS + #undef ISC_ZWJ +@@ -930,6 +981,7 @@ + #undef ISC_x + #undef ISC_PK + #undef ISC_RS ++#undef ISC_SM + #undef ISC_TL + #undef ISC_TM + #undef ISC_V +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-myanmar.cc gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-myanmar.cc 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc 2016-06-05 23:50:00.982800449 +0200 +@@ -154,7 +154,7 @@ + { + /* If it ligated, all bets are off. */ + if (_hb_glyph_info_ligated (&info)) return false; +- return !!(FLAG (info.myanmar_category()) & flags); ++ return !!(FLAG_SAFE (info.myanmar_category()) & flags); + } + + static inline bool +@@ -199,6 +199,10 @@ + cat = (indic_category_t) OT_A; + break; + ++ case 0x1039u: ++ cat = (indic_category_t) OT_H; ++ break; ++ + case 0x103Au: + cat = (indic_category_t) OT_As; + break; +@@ -304,9 +308,7 @@ + * http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm */ + + static void +-initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, +- hb_face_t *face, +- hb_buffer_t *buffer, ++initial_reordering_consonant_syllable (hb_buffer_t *buffer, + unsigned int start, unsigned int end) + { + hb_glyph_info_t *info = buffer->info; +@@ -393,42 +395,10 @@ + } + } + +- buffer->merge_clusters (start, end); + /* Sit tight, rock 'n roll! */ +- hb_bubble_sort (info + start, end - start, compare_myanmar_order); +-} +- +-static void +-initial_reordering_broken_cluster (const hb_ot_shape_plan_t *plan, +- hb_face_t *face, +- hb_buffer_t *buffer, +- unsigned int start, unsigned int end) +-{ +- /* We already inserted dotted-circles, so just call the consonant_syllable. */ +- initial_reordering_consonant_syllable (plan, face, buffer, start, end); +-} +- +-static void +-initial_reordering_punctuation_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED, +- hb_face_t *face HB_UNUSED, +- hb_buffer_t *buffer HB_UNUSED, +- unsigned int start HB_UNUSED, unsigned int end HB_UNUSED) +-{ +- /* Nothing to do right now. If we ever switch to using the output +- * buffer in the reordering process, we'd need to next_glyph() here. */ +-} +- +-static void +-initial_reordering_non_myanmar_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED, +- hb_face_t *face HB_UNUSED, +- hb_buffer_t *buffer HB_UNUSED, +- unsigned int start HB_UNUSED, unsigned int end HB_UNUSED) +-{ +- /* Nothing to do right now. If we ever switch to using the output +- * buffer in the reordering process, we'd need to next_glyph() here. */ ++ buffer->sort (start, end, compare_myanmar_order); + } + +- + static void + initial_reordering_syllable (const hb_ot_shape_plan_t *plan, + hb_face_t *face, +@@ -437,10 +407,15 @@ + { + syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F); + switch (syllable_type) { +- case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return; +- case punctuation_cluster: initial_reordering_punctuation_cluster (plan, face, buffer, start, end); return; +- case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return; +- case non_myanmar_cluster: initial_reordering_non_myanmar_cluster (plan, face, buffer, start, end); return; ++ ++ case broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */ ++ case consonant_syllable: ++ initial_reordering_consonant_syllable (buffer, start, end); ++ break; ++ ++ case punctuation_cluster: ++ case non_myanmar_cluster: ++ break; + } + } + +@@ -484,12 +459,12 @@ + { + last_syllable = syllable; + +- hb_glyph_info_t info = dottedcircle; +- info.cluster = buffer->cur().cluster; +- info.mask = buffer->cur().mask; +- info.syllable() = buffer->cur().syllable(); ++ hb_glyph_info_t ginfo = dottedcircle; ++ ginfo.cluster = buffer->cur().cluster; ++ ginfo.mask = buffer->cur().mask; ++ ginfo.syllable() = buffer->cur().syllable(); + +- buffer->output_info (info); ++ buffer->output_info (ginfo); + } + else + buffer->next_glyph (); +@@ -505,18 +480,8 @@ + { + insert_dotted_circles (plan, font, buffer); + +- hb_glyph_info_t *info = buffer->info; +- unsigned int count = buffer->len; +- if (unlikely (!count)) return; +- unsigned int last = 0; +- unsigned int last_syllable = info[0].syllable(); +- for (unsigned int i = 1; i < count; i++) +- if (last_syllable != info[i].syllable()) { +- initial_reordering_syllable (plan, font->face, buffer, last, i); +- last = i; +- last_syllable = info[last].syllable(); +- } +- initial_reordering_syllable (plan, font->face, buffer, last, count); ++ foreach_syllable (buffer, start, end) ++ initial_reordering_syllable (plan, font->face, buffer, start, end); + } + + static void +@@ -546,6 +511,7 @@ + NULL, /* data_create */ + NULL, /* data_destroy */ + NULL, /* preprocess_text */ ++ NULL, /* postprocess_glyphs */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, + NULL, /* decompose */ + NULL, /* compose */ +@@ -562,6 +528,7 @@ + NULL, /* data_create */ + NULL, /* data_destroy */ + NULL, /* preprocess_text */ ++ NULL, /* postprocess_glyphs */ + HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, + NULL, /* decompose */ + NULL, /* compose */ +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-myanmar-machine.hh gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-myanmar-machine.hh 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh 2016-06-05 23:49:58.177815172 +0200 +@@ -1,5 +1,5 @@ + +-#line 1 "../../src/hb-ot-shape-complex-myanmar-machine.rl" ++#line 1 "hb-ot-shape-complex-myanmar-machine.rl" + /* + * Copyright © 2011,2012 Google, Inc. + * +@@ -32,7 +32,7 @@ + #include "hb-private.hh" + + +-#line 36 "hb-ot-shape-complex-myanmar-machine.hh.tmp" ++#line 36 "hb-ot-shape-complex-myanmar-machine.hh" + static const unsigned char _myanmar_syllable_machine_trans_keys[] = { + 1u, 31u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, + 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u, +@@ -261,11 +261,11 @@ + static const int myanmar_syllable_machine_en_main = 0; + + +-#line 36 "../../src/hb-ot-shape-complex-myanmar-machine.rl" ++#line 36 "hb-ot-shape-complex-myanmar-machine.rl" + + + +-#line 93 "../../src/hb-ot-shape-complex-myanmar-machine.rl" ++#line 93 "hb-ot-shape-complex-myanmar-machine.rl" + + + #define found_syllable(syllable_type) \ +@@ -285,7 +285,7 @@ + int cs; + hb_glyph_info_t *info = buffer->info; + +-#line 289 "hb-ot-shape-complex-myanmar-machine.hh.tmp" ++#line 289 "hb-ot-shape-complex-myanmar-machine.hh" + { + cs = myanmar_syllable_machine_start; + ts = 0; +@@ -293,7 +293,7 @@ + act = 0; + } + +-#line 114 "../../src/hb-ot-shape-complex-myanmar-machine.rl" ++#line 114 "hb-ot-shape-complex-myanmar-machine.rl" + + + p = 0; +@@ -302,7 +302,7 @@ + unsigned int last = 0; + unsigned int syllable_serial = 1; + +-#line 306 "hb-ot-shape-complex-myanmar-machine.hh.tmp" ++#line 306 "hb-ot-shape-complex-myanmar-machine.hh" + { + int _slen; + int _trans; +@@ -316,7 +316,7 @@ + #line 1 "NONE" + {ts = p;} + break; +-#line 320 "hb-ot-shape-complex-myanmar-machine.hh.tmp" ++#line 320 "hb-ot-shape-complex-myanmar-machine.hh" + } + + _keys = _myanmar_syllable_machine_trans_keys + (cs<<1); +@@ -335,38 +335,38 @@ + + switch ( _myanmar_syllable_machine_trans_actions[_trans] ) { + case 7: +-#line 85 "../../src/hb-ot-shape-complex-myanmar-machine.rl" ++#line 85 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p+1;{ found_syllable (consonant_syllable); }} + break; + case 5: +-#line 86 "../../src/hb-ot-shape-complex-myanmar-machine.rl" ++#line 86 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p+1;{ found_syllable (non_myanmar_cluster); }} + break; + case 10: +-#line 87 "../../src/hb-ot-shape-complex-myanmar-machine.rl" ++#line 87 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p+1;{ found_syllable (punctuation_cluster); }} + break; + case 4: +-#line 88 "../../src/hb-ot-shape-complex-myanmar-machine.rl" ++#line 88 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p+1;{ found_syllable (broken_cluster); }} + break; + case 3: +-#line 89 "../../src/hb-ot-shape-complex-myanmar-machine.rl" ++#line 89 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p+1;{ found_syllable (non_myanmar_cluster); }} + break; + case 6: +-#line 85 "../../src/hb-ot-shape-complex-myanmar-machine.rl" ++#line 85 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p;p--;{ found_syllable (consonant_syllable); }} + break; + case 8: +-#line 88 "../../src/hb-ot-shape-complex-myanmar-machine.rl" ++#line 88 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p;p--;{ found_syllable (broken_cluster); }} + break; + case 9: +-#line 89 "../../src/hb-ot-shape-complex-myanmar-machine.rl" ++#line 89 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p;p--;{ found_syllable (non_myanmar_cluster); }} + break; +-#line 370 "hb-ot-shape-complex-myanmar-machine.hh.tmp" ++#line 370 "hb-ot-shape-complex-myanmar-machine.hh" + } + + _again: +@@ -375,7 +375,7 @@ + #line 1 "NONE" + {ts = 0;} + break; +-#line 379 "hb-ot-shape-complex-myanmar-machine.hh.tmp" ++#line 379 "hb-ot-shape-complex-myanmar-machine.hh" + } + + if ( ++p != pe ) +@@ -391,7 +391,7 @@ + + } + +-#line 123 "../../src/hb-ot-shape-complex-myanmar-machine.rl" ++#line 123 "hb-ot-shape-complex-myanmar-machine.rl" + + } + +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-private.hh gfx/harfbuzz/src/hb-ot-shape-complex-private.hh +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-private.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-private.hh 2016-06-05 23:50:02.264793753 +0200 +@@ -44,9 +44,7 @@ + // HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY, + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE, + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, +- HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, +- +- HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT = HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE ++ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE + }; + + +@@ -59,9 +57,9 @@ + HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_old) \ + HB_COMPLEX_SHAPER_IMPLEMENT (indic) \ + HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \ +- HB_COMPLEX_SHAPER_IMPLEMENT (sea) \ + HB_COMPLEX_SHAPER_IMPLEMENT (thai) \ + HB_COMPLEX_SHAPER_IMPLEMENT (tibetan) \ ++ HB_COMPLEX_SHAPER_IMPLEMENT (use) \ + /* ^--- Add new shapers here */ + + +@@ -110,6 +108,15 @@ + hb_buffer_t *buffer, + hb_font_t *font); + ++ /* postprocess_glyphs() ++ * Called during shape(). ++ * Shapers can use to modify glyphs after shaping ends. ++ * May be NULL. ++ */ ++ void (*postprocess_glyphs) (const hb_ot_shape_plan_t *plan, ++ hb_buffer_t *buffer, ++ hb_font_t *font); ++ + + hb_ot_shape_normalization_mode_t normalization_preference; + +@@ -179,9 +186,12 @@ + case HB_SCRIPT_PSALTER_PAHLAVI: + + /* For Arabic script, use the Arabic shaper even if no OT script tag was found. +- * This is because we do fallback shaping for Arabic script (and not others). */ +- if (planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT || +- planner->props.script == HB_SCRIPT_ARABIC) ++ * This is because we do fallback shaping for Arabic script (and not others). ++ * But note that Arabic shaping is applicable only to horizontal layout; for ++ * vertical text, just use the generic shaper instead. */ ++ if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT || ++ planner->props.script == HB_SCRIPT_ARABIC) && ++ HB_DIRECTION_IS_HORIZONTAL(planner->props.direction)) + return &_hb_ot_complex_shaper_arabic; + else + return &_hb_ot_complex_shaper_default; +@@ -214,60 +224,9 @@ + + /* ^--- Add new shapers here */ + +- + #if 0 +- /* Note: +- * +- * These disabled scripts are listed in ucd/IndicSyllabicCategory.txt, but according +- * to Martin Hosken and Jonathan Kew do not require complex shaping. +- * +- * TODO We should automate figuring out which scripts do not need complex shaping +- * +- * TODO We currently keep data for these scripts in our indic table. Need to fix the +- * generator to not do that. +- */ +- +- +- /* Simple? */ +- +- /* Unicode-3.2 additions */ +- case HB_SCRIPT_BUHID: +- case HB_SCRIPT_HANUNOO: +- +- /* Unicode-5.1 additions */ +- case HB_SCRIPT_SAURASHTRA: +- +- /* Unicode-6.0 additions */ +- case HB_SCRIPT_BATAK: +- case HB_SCRIPT_BRAHMI: +- +- +- /* Simple */ +- +- /* Unicode-1.1 additions */ +- /* These have their own shaper now. */ +- case HB_SCRIPT_LAO: +- case HB_SCRIPT_THAI: +- +- /* Unicode-3.2 additions */ +- case HB_SCRIPT_TAGALOG: +- case HB_SCRIPT_TAGBANWA: +- +- /* Unicode-4.0 additions */ +- case HB_SCRIPT_LIMBU: +- case HB_SCRIPT_TAI_LE: +- + /* Unicode-4.1 additions */ +- case HB_SCRIPT_KHAROSHTHI: +- case HB_SCRIPT_SYLOTI_NAGRI: +- +- /* Unicode-5.1 additions */ +- case HB_SCRIPT_KAYAH_LI: +- +- /* Unicode-5.2 additions */ +- case HB_SCRIPT_TAI_VIET: +- +- ++ case HB_SCRIPT_NEW_TAI_LUE: + #endif + + /* Unicode-1.1 additions */ +@@ -284,28 +243,11 @@ + /* Unicode-3.0 additions */ + case HB_SCRIPT_SINHALA: + +- /* Unicode-5.0 additions */ +- case HB_SCRIPT_BALINESE: +- +- /* Unicode-5.1 additions */ +- case HB_SCRIPT_LEPCHA: +- case HB_SCRIPT_REJANG: +- case HB_SCRIPT_SUNDANESE: +- + /* Unicode-5.2 additions */ + case HB_SCRIPT_JAVANESE: +- case HB_SCRIPT_KAITHI: +- case HB_SCRIPT_MEETEI_MAYEK: +- +- /* Unicode-6.0 additions */ +- +- /* Unicode-6.1 additions */ +- case HB_SCRIPT_CHAKMA: +- case HB_SCRIPT_SHARADA: +- case HB_SCRIPT_TAKRI: + + /* If the designer designed the font for the 'DFLT' script, +- * use the default shaper. Otherwise, use the Indic shaper. ++ * use the default shaper. Otherwise, use the specific shaper. + * Note that for some simple scripts, there may not be *any* + * GSUB/GPOS needed, so there may be no scripts found! */ + if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T')) +@@ -337,24 +279,82 @@ + else + return &_hb_ot_complex_shaper_default; + ++ ++ /* Unicode-2.0 additions */ ++ //case HB_SCRIPT_TIBETAN: ++ ++ /* Unicode-3.0 additions */ ++ //case HB_SCRIPT_MONGOLIAN: ++ //case HB_SCRIPT_SINHALA: ++ ++ /* Unicode-3.2 additions */ ++ case HB_SCRIPT_BUHID: ++ case HB_SCRIPT_HANUNOO: ++ case HB_SCRIPT_TAGALOG: ++ case HB_SCRIPT_TAGBANWA: ++ ++ /* Unicode-4.0 additions */ ++ case HB_SCRIPT_LIMBU: ++ case HB_SCRIPT_TAI_LE: ++ + /* Unicode-4.1 additions */ + case HB_SCRIPT_BUGINESE: +- case HB_SCRIPT_NEW_TAI_LUE: ++ case HB_SCRIPT_KHAROSHTHI: ++ case HB_SCRIPT_SYLOTI_NAGRI: ++ case HB_SCRIPT_TIFINAGH: ++ ++ /* Unicode-5.0 additions */ ++ case HB_SCRIPT_BALINESE: ++ //case HB_SCRIPT_NKO: ++ //case HB_SCRIPT_PHAGS_PA: + + /* Unicode-5.1 additions */ + case HB_SCRIPT_CHAM: ++ case HB_SCRIPT_KAYAH_LI: ++ case HB_SCRIPT_LEPCHA: ++ case HB_SCRIPT_REJANG: ++ case HB_SCRIPT_SAURASHTRA: ++ case HB_SCRIPT_SUNDANESE: + + /* Unicode-5.2 additions */ ++ case HB_SCRIPT_EGYPTIAN_HIEROGLYPHS: ++ //case HB_SCRIPT_JAVANESE: ++ case HB_SCRIPT_KAITHI: ++ case HB_SCRIPT_MEETEI_MAYEK: + case HB_SCRIPT_TAI_THAM: ++ case HB_SCRIPT_TAI_VIET: ++ ++ /* Unicode-6.0 additions */ ++ case HB_SCRIPT_BATAK: ++ case HB_SCRIPT_BRAHMI: ++ //case HB_SCRIPT_MANDAIC: ++ ++ /* Unicode-6.1 additions */ ++ case HB_SCRIPT_CHAKMA: ++ case HB_SCRIPT_SHARADA: ++ case HB_SCRIPT_TAKRI: ++ ++ /* Unicode-7.0 additions */ ++ case HB_SCRIPT_DUPLOYAN: ++ case HB_SCRIPT_GRANTHA: ++ case HB_SCRIPT_KHOJKI: ++ case HB_SCRIPT_KHUDAWADI: ++ case HB_SCRIPT_MAHAJANI: ++ //case HB_SCRIPT_MANICHAEAN: ++ case HB_SCRIPT_MODI: ++ case HB_SCRIPT_PAHAWH_HMONG: ++ //case HB_SCRIPT_PSALTER_PAHLAVI: ++ case HB_SCRIPT_SIDDHAM: ++ case HB_SCRIPT_TIRHUTA: + + /* If the designer designed the font for the 'DFLT' script, +- * use the default shaper. Otherwise, use the Indic shaper. ++ * use the default shaper. Otherwise, use the specific shaper. + * Note that for some simple scripts, there may not be *any* + * GSUB/GPOS needed, so there may be no scripts found! */ + if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T')) + return &_hb_ot_complex_shaper_default; + else +- return &_hb_ot_complex_shaper_sea; ++ return &_hb_ot_complex_shaper_use; + } + } + +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-sea.cc gfx/harfbuzz/src/hb-ot-shape-complex-sea.cc +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-sea.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-sea.cc 1970-01-01 01:00:00.000000000 +0100 +@@ -1,380 +0,0 @@ +-/* +- * Copyright © 2011,2012,2013 Google, Inc. +- * +- * This is part of HarfBuzz, a text shaping library. +- * +- * Permission is hereby granted, without written agreement and without +- * license or royalty fees, to use, copy, modify, and distribute this +- * software and its documentation for any purpose, provided that the +- * above copyright notice and the following two paragraphs appear in +- * all copies of this software. +- * +- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR +- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN +- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +- * DAMAGE. +- * +- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, +- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO +- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +- * +- * Google Author(s): Behdad Esfahbod +- */ +- +-#include "hb-ot-shape-complex-indic-private.hh" +- +-/* buffer var allocations */ +-#define sea_category() complex_var_u8_0() /* indic_category_t */ +-#define sea_position() complex_var_u8_1() /* indic_position_t */ +- +- +-/* +- * South-East Asian shaper. +- * Loosely based on the Myanmar spec / shaper. +- * There is no OpenType spec for this. +- */ +- +-static const hb_tag_t +-basic_features[] = +-{ +- /* +- * Basic features. +- * These features are applied in order, one at a time, after initial_reordering. +- */ +- HB_TAG('p','r','e','f'), +- HB_TAG('a','b','v','f'), +- HB_TAG('b','l','w','f'), +- HB_TAG('p','s','t','f'), +-}; +-static const hb_tag_t +-other_features[] = +-{ +- /* +- * Other features. +- * These features are applied all at once, after final_reordering. +- */ +- HB_TAG('p','r','e','s'), +- HB_TAG('a','b','v','s'), +- HB_TAG('b','l','w','s'), +- HB_TAG('p','s','t','s'), +- /* Positioning features, though we don't care about the types. */ +- HB_TAG('d','i','s','t'), +-}; +- +-static void +-setup_syllables (const hb_ot_shape_plan_t *plan, +- hb_font_t *font, +- hb_buffer_t *buffer); +-static void +-initial_reordering (const hb_ot_shape_plan_t *plan, +- hb_font_t *font, +- hb_buffer_t *buffer); +-static void +-final_reordering (const hb_ot_shape_plan_t *plan, +- hb_font_t *font, +- hb_buffer_t *buffer); +- +-static void +-collect_features_sea (hb_ot_shape_planner_t *plan) +-{ +- hb_ot_map_builder_t *map = &plan->map; +- +- /* Do this before any lookups have been applied. */ +- map->add_gsub_pause (setup_syllables); +- +- map->add_global_bool_feature (HB_TAG('l','o','c','l')); +- /* The Indic specs do not require ccmp, but we apply it here since if +- * there is a use of it, it's typically at the beginning. */ +- map->add_global_bool_feature (HB_TAG('c','c','m','p')); +- +- map->add_gsub_pause (initial_reordering); +- for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++) +- { +- map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ); +- map->add_gsub_pause (NULL); +- } +- map->add_gsub_pause (final_reordering); +- for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++) +- map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ); +-} +- +-static void +-override_features_sea (hb_ot_shape_planner_t *plan) +-{ +- plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL); +-} +- +- +-enum syllable_type_t { +- consonant_syllable, +- broken_cluster, +- non_sea_cluster, +-}; +- +-#include "hb-ot-shape-complex-sea-machine.hh" +- +- +-/* Note: This enum is duplicated in the -machine.rl source file. +- * Not sure how to avoid duplication. */ +-enum sea_category_t { +-// OT_C = 1, +- OT_GB = 12, /* Generic Base XXX DOTTED CIRCLE only for now */ +-// OT_H = 4, /* Halant */ +- OT_IV = 2, /* Independent Vowel */ +- OT_MR = 22, /* Medial Ra */ +-// OT_CM = 17, /* Consonant Medial */ +- OT_VAbv = 26, +- OT_VBlw = 27, +- OT_VPre = 28, +- OT_VPst = 29, +- OT_T = 3, /* Tone Marks */ +-// OT_A = 10, /* Anusvara */ +-}; +- +-static inline void +-set_sea_properties (hb_glyph_info_t &info) +-{ +- hb_codepoint_t u = info.codepoint; +- unsigned int type = hb_indic_get_categories (u); +- indic_category_t cat = (indic_category_t) (type & 0x7Fu); +- indic_position_t pos = (indic_position_t) (type >> 8); +- +- /* Medial Ra */ +- if (u == 0x1A55u || u == 0xAA34u) +- cat = (indic_category_t) OT_MR; +- +- if (cat == OT_M) +- { +- switch ((int) pos) +- { +- case POS_PRE_C: cat = (indic_category_t) OT_VPre; break; +- case POS_ABOVE_C: cat = (indic_category_t) OT_VAbv; break; +- case POS_BELOW_C: cat = (indic_category_t) OT_VBlw; break; +- case POS_POST_C: cat = (indic_category_t) OT_VPst; break; +- } +- } +- +- info.sea_category() = (sea_category_t) cat; +- info.sea_position() = pos; +-} +- +- +-static void +-setup_masks_sea (const hb_ot_shape_plan_t *plan HB_UNUSED, +- hb_buffer_t *buffer, +- hb_font_t *font HB_UNUSED) +-{ +- HB_BUFFER_ALLOCATE_VAR (buffer, sea_category); +- HB_BUFFER_ALLOCATE_VAR (buffer, sea_position); +- +- /* We cannot setup masks here. We save information about characters +- * and setup masks later on in a pause-callback. */ +- +- unsigned int count = buffer->len; +- hb_glyph_info_t *info = buffer->info; +- for (unsigned int i = 0; i < count; i++) +- set_sea_properties (info[i]); +-} +- +-static void +-setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, +- hb_font_t *font HB_UNUSED, +- hb_buffer_t *buffer) +-{ +- find_syllables (buffer); +-} +- +-static int +-compare_sea_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb) +-{ +- int a = pa->sea_position(); +- int b = pb->sea_position(); +- +- return a < b ? -1 : a == b ? 0 : +1; +-} +- +- +-static void +-initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, +- hb_face_t *face, +- hb_buffer_t *buffer, +- unsigned int start, unsigned int end) +-{ +- hb_glyph_info_t *info = buffer->info; +- unsigned int base = start; +- +- /* Reorder! */ +- unsigned int i = start; +- for (; i < base; i++) +- info[i].sea_position() = POS_PRE_C; +- if (i < end) +- { +- info[i].sea_position() = POS_BASE_C; +- i++; +- } +- for (; i < end; i++) +- { +- if (info[i].sea_category() == OT_MR) /* Pre-base reordering */ +- { +- info[i].sea_position() = POS_PRE_C; +- continue; +- } +- if (info[i].sea_category() == OT_VPre) /* Left matra */ +- { +- info[i].sea_position() = POS_PRE_M; +- continue; +- } +- +- info[i].sea_position() = POS_AFTER_MAIN; +- } +- +- buffer->merge_clusters (start, end); +- /* Sit tight, rock 'n roll! */ +- hb_bubble_sort (info + start, end - start, compare_sea_order); +-} +- +-static void +-initial_reordering_broken_cluster (const hb_ot_shape_plan_t *plan, +- hb_face_t *face, +- hb_buffer_t *buffer, +- unsigned int start, unsigned int end) +-{ +- /* We already inserted dotted-circles, so just call the consonant_syllable. */ +- initial_reordering_consonant_syllable (plan, face, buffer, start, end); +-} +- +-static void +-initial_reordering_non_sea_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED, +- hb_face_t *face HB_UNUSED, +- hb_buffer_t *buffer HB_UNUSED, +- unsigned int start HB_UNUSED, unsigned int end HB_UNUSED) +-{ +- /* Nothing to do right now. If we ever switch to using the output +- * buffer in the reordering process, we'd need to next_glyph() here. */ +-} +- +- +-static void +-initial_reordering_syllable (const hb_ot_shape_plan_t *plan, +- hb_face_t *face, +- hb_buffer_t *buffer, +- unsigned int start, unsigned int end) +-{ +- syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F); +- switch (syllable_type) { +- case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return; +- case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return; +- case non_sea_cluster: initial_reordering_non_sea_cluster (plan, face, buffer, start, end); return; +- } +-} +- +-static inline void +-insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, +- hb_font_t *font, +- hb_buffer_t *buffer) +-{ +- /* Note: This loop is extra overhead, but should not be measurable. */ +- bool has_broken_syllables = false; +- unsigned int count = buffer->len; +- hb_glyph_info_t *info = buffer->info; +- for (unsigned int i = 0; i < count; i++) +- if ((info[i].syllable() & 0x0F) == broken_cluster) +- { +- has_broken_syllables = true; +- break; +- } +- if (likely (!has_broken_syllables)) +- return; +- +- +- hb_codepoint_t dottedcircle_glyph; +- if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph)) +- return; +- +- hb_glyph_info_t dottedcircle = {0}; +- dottedcircle.codepoint = 0x25CCu; +- set_sea_properties (dottedcircle); +- dottedcircle.codepoint = dottedcircle_glyph; +- +- buffer->clear_output (); +- +- buffer->idx = 0; +- unsigned int last_syllable = 0; +- while (buffer->idx < buffer->len) +- { +- unsigned int syllable = buffer->cur().syllable(); +- syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F); +- if (unlikely (last_syllable != syllable && syllable_type == broken_cluster)) +- { +- last_syllable = syllable; +- +- hb_glyph_info_t info = dottedcircle; +- info.cluster = buffer->cur().cluster; +- info.mask = buffer->cur().mask; +- info.syllable() = buffer->cur().syllable(); +- +- buffer->output_info (info); +- } +- else +- buffer->next_glyph (); +- } +- +- buffer->swap_buffers (); +-} +- +-static void +-initial_reordering (const hb_ot_shape_plan_t *plan, +- hb_font_t *font, +- hb_buffer_t *buffer) +-{ +- insert_dotted_circles (plan, font, buffer); +- +- hb_glyph_info_t *info = buffer->info; +- unsigned int count = buffer->len; +- if (unlikely (!count)) return; +- unsigned int last = 0; +- unsigned int last_syllable = info[0].syllable(); +- for (unsigned int i = 1; i < count; i++) +- if (last_syllable != info[i].syllable()) { +- initial_reordering_syllable (plan, font->face, buffer, last, i); +- last = i; +- last_syllable = info[last].syllable(); +- } +- initial_reordering_syllable (plan, font->face, buffer, last, count); +-} +- +-static void +-final_reordering (const hb_ot_shape_plan_t *plan, +- hb_font_t *font HB_UNUSED, +- hb_buffer_t *buffer) +-{ +- hb_glyph_info_t *info = buffer->info; +- unsigned int count = buffer->len; +- +- /* Zero syllables now... */ +- for (unsigned int i = 0; i < count; i++) +- info[i].syllable() = 0; +- +- HB_BUFFER_DEALLOCATE_VAR (buffer, sea_category); +- HB_BUFFER_DEALLOCATE_VAR (buffer, sea_position); +-} +- +- +-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_sea = +-{ +- "sea", +- collect_features_sea, +- override_features_sea, +- NULL, /* data_create */ +- NULL, /* data_destroy */ +- NULL, /* preprocess_text */ +- HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, +- NULL, /* decompose */ +- NULL, /* compose */ +- setup_masks_sea, +- HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, +- false, /* fallback_position */ +-}; +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-sea-machine.hh gfx/harfbuzz/src/hb-ot-shape-complex-sea-machine.hh +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-sea-machine.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-sea-machine.hh 1970-01-01 01:00:00.000000000 +0100 +@@ -1,224 +0,0 @@ +- +-#line 1 "../../src/hb-ot-shape-complex-sea-machine.rl" +-/* +- * Copyright © 2011,2012,2013 Google, Inc. +- * +- * This is part of HarfBuzz, a text shaping library. +- * +- * Permission is hereby granted, without written agreement and without +- * license or royalty fees, to use, copy, modify, and distribute this +- * software and its documentation for any purpose, provided that the +- * above copyright notice and the following two paragraphs appear in +- * all copies of this software. +- * +- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR +- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN +- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +- * DAMAGE. +- * +- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, +- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO +- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +- * +- * Google Author(s): Behdad Esfahbod +- */ +- +-#ifndef HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH +-#define HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH +- +-#include "hb-private.hh" +- +- +-#line 36 "hb-ot-shape-complex-sea-machine.hh.tmp" +-static const unsigned char _sea_syllable_machine_trans_keys[] = { +- 1u, 1u, 1u, 1u, 1u, 29u, 3u, 29u, 3u, 29u, 1u, 1u, 0 +-}; +- +-static const char _sea_syllable_machine_key_spans[] = { +- 1, 1, 29, 27, 27, 1 +-}; +- +-static const char _sea_syllable_machine_index_offsets[] = { +- 0, 2, 4, 34, 62, 90 +-}; +- +-static const char _sea_syllable_machine_indicies[] = { +- 1, 0, 3, 2, 1, 1, 3, 5, +- 4, 4, 4, 4, 4, 3, 4, 1, +- 4, 4, 4, 4, 3, 4, 4, 4, +- 4, 3, 4, 4, 4, 3, 3, 3, +- 3, 4, 1, 7, 6, 6, 6, 6, +- 6, 1, 6, 6, 6, 6, 6, 6, +- 1, 6, 6, 6, 6, 1, 6, 6, +- 6, 1, 1, 1, 1, 6, 3, 9, +- 8, 8, 8, 8, 8, 3, 8, 8, +- 8, 8, 8, 8, 3, 8, 8, 8, +- 8, 3, 8, 8, 8, 3, 3, 3, +- 3, 8, 3, 10, 0 +-}; +- +-static const char _sea_syllable_machine_trans_targs[] = { +- 2, 3, 2, 4, 2, 5, 2, 0, +- 2, 1, 2 +-}; +- +-static const char _sea_syllable_machine_trans_actions[] = { +- 1, 2, 3, 2, 6, 0, 7, 0, +- 8, 0, 9 +-}; +- +-static const char _sea_syllable_machine_to_state_actions[] = { +- 0, 0, 4, 0, 0, 0 +-}; +- +-static const char _sea_syllable_machine_from_state_actions[] = { +- 0, 0, 5, 0, 0, 0 +-}; +- +-static const char _sea_syllable_machine_eof_trans[] = { +- 1, 3, 0, 7, 9, 11 +-}; +- +-static const int sea_syllable_machine_start = 2; +-static const int sea_syllable_machine_first_final = 2; +-static const int sea_syllable_machine_error = -1; +- +-static const int sea_syllable_machine_en_main = 2; +- +- +-#line 36 "../../src/hb-ot-shape-complex-sea-machine.rl" +- +- +- +-#line 67 "../../src/hb-ot-shape-complex-sea-machine.rl" +- +- +-#define found_syllable(syllable_type) \ +- HB_STMT_START { \ +- if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \ +- for (unsigned int i = last; i < p+1; i++) \ +- info[i].syllable() = (syllable_serial << 4) | syllable_type; \ +- last = p+1; \ +- syllable_serial++; \ +- if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ +- } HB_STMT_END +- +-static void +-find_syllables (hb_buffer_t *buffer) +-{ +- unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED; +- int cs; +- hb_glyph_info_t *info = buffer->info; +- +-#line 117 "hb-ot-shape-complex-sea-machine.hh.tmp" +- { +- cs = sea_syllable_machine_start; +- ts = 0; +- te = 0; +- act = 0; +- } +- +-#line 88 "../../src/hb-ot-shape-complex-sea-machine.rl" +- +- +- p = 0; +- pe = eof = buffer->len; +- +- unsigned int last = 0; +- unsigned int syllable_serial = 1; +- +-#line 134 "hb-ot-shape-complex-sea-machine.hh.tmp" +- { +- int _slen; +- int _trans; +- const unsigned char *_keys; +- const char *_inds; +- if ( p == pe ) +- goto _test_eof; +-_resume: +- switch ( _sea_syllable_machine_from_state_actions[cs] ) { +- case 5: +-#line 1 "NONE" +- {ts = p;} +- break; +-#line 148 "hb-ot-shape-complex-sea-machine.hh.tmp" +- } +- +- _keys = _sea_syllable_machine_trans_keys + (cs<<1); +- _inds = _sea_syllable_machine_indicies + _sea_syllable_machine_index_offsets[cs]; +- +- _slen = _sea_syllable_machine_key_spans[cs]; +- _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].sea_category()) && +- ( info[p].sea_category()) <= _keys[1] ? +- ( info[p].sea_category()) - _keys[0] : _slen ]; +- +-_eof_trans: +- cs = _sea_syllable_machine_trans_targs[_trans]; +- +- if ( _sea_syllable_machine_trans_actions[_trans] == 0 ) +- goto _again; +- +- switch ( _sea_syllable_machine_trans_actions[_trans] ) { +- case 2: +-#line 1 "NONE" +- {te = p+1;} +- break; +- case 6: +-#line 63 "../../src/hb-ot-shape-complex-sea-machine.rl" +- {te = p+1;{ found_syllable (non_sea_cluster); }} +- break; +- case 7: +-#line 61 "../../src/hb-ot-shape-complex-sea-machine.rl" +- {te = p;p--;{ found_syllable (consonant_syllable); }} +- break; +- case 8: +-#line 62 "../../src/hb-ot-shape-complex-sea-machine.rl" +- {te = p;p--;{ found_syllable (broken_cluster); }} +- break; +- case 9: +-#line 63 "../../src/hb-ot-shape-complex-sea-machine.rl" +- {te = p;p--;{ found_syllable (non_sea_cluster); }} +- break; +- case 1: +-#line 61 "../../src/hb-ot-shape-complex-sea-machine.rl" +- {{p = ((te))-1;}{ found_syllable (consonant_syllable); }} +- break; +- case 3: +-#line 62 "../../src/hb-ot-shape-complex-sea-machine.rl" +- {{p = ((te))-1;}{ found_syllable (broken_cluster); }} +- break; +-#line 194 "hb-ot-shape-complex-sea-machine.hh.tmp" +- } +- +-_again: +- switch ( _sea_syllable_machine_to_state_actions[cs] ) { +- case 4: +-#line 1 "NONE" +- {ts = 0;} +- break; +-#line 203 "hb-ot-shape-complex-sea-machine.hh.tmp" +- } +- +- if ( ++p != pe ) +- goto _resume; +- _test_eof: {} +- if ( p == eof ) +- { +- if ( _sea_syllable_machine_eof_trans[cs] > 0 ) { +- _trans = _sea_syllable_machine_eof_trans[cs] - 1; +- goto _eof_trans; +- } +- } +- +- } +- +-#line 97 "../../src/hb-ot-shape-complex-sea-machine.rl" +- +-} +- +-#undef found_syllable +- +-#endif /* HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH */ +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-sea-machine.rl gfx/harfbuzz/src/hb-ot-shape-complex-sea-machine.rl +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-sea-machine.rl 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-sea-machine.rl 1970-01-01 01:00:00.000000000 +0100 +@@ -1,102 +0,0 @@ +-/* +- * Copyright © 2011,2012,2013 Google, Inc. +- * +- * This is part of HarfBuzz, a text shaping library. +- * +- * Permission is hereby granted, without written agreement and without +- * license or royalty fees, to use, copy, modify, and distribute this +- * software and its documentation for any purpose, provided that the +- * above copyright notice and the following two paragraphs appear in +- * all copies of this software. +- * +- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR +- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN +- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +- * DAMAGE. +- * +- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, +- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO +- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +- * +- * Google Author(s): Behdad Esfahbod +- */ +- +-#ifndef HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH +-#define HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH +- +-#include "hb-private.hh" +- +-%%{ +- machine sea_syllable_machine; +- alphtype unsigned char; +- write data; +-}%% +- +-%%{ +- +-# Same order as enum sea_category_t. Not sure how to avoid duplication. +-C = 1; +-GB = 12; # Generic Base +-H = 4; # Halant +-IV = 2; # Independent Vowel +-MR = 22; # Medial Ra +-CM = 17; # Consonant Medial +-VAbv = 26; +-VBlw = 27; +-VPre = 28; +-VPst = 29; +-T = 3; # Tone Marks +-A = 10; # Anusvara +- +-syllable_tail = (VPre|VAbv|VBlw|VPst|H.C|CM|MR|T|A)*; +- +-consonant_syllable = (C|IV|GB) syllable_tail; +-broken_cluster = syllable_tail; +-other = any; +- +-main := |* +- consonant_syllable => { found_syllable (consonant_syllable); }; +- broken_cluster => { found_syllable (broken_cluster); }; +- other => { found_syllable (non_sea_cluster); }; +-*|; +- +- +-}%% +- +-#define found_syllable(syllable_type) \ +- HB_STMT_START { \ +- if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \ +- for (unsigned int i = last; i < p+1; i++) \ +- info[i].syllable() = (syllable_serial << 4) | syllable_type; \ +- last = p+1; \ +- syllable_serial++; \ +- if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ +- } HB_STMT_END +- +-static void +-find_syllables (hb_buffer_t *buffer) +-{ +- unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED; +- int cs; +- hb_glyph_info_t *info = buffer->info; +- %%{ +- write init; +- getkey info[p].sea_category(); +- }%% +- +- p = 0; +- pe = eof = buffer->len; +- +- unsigned int last = 0; +- unsigned int syllable_serial = 1; +- %%{ +- write exec; +- }%% +-} +- +-#undef found_syllable +- +-#endif /* HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH */ +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-thai.cc gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-thai.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc 2016-06-05 23:50:03.390787882 +0200 +@@ -139,7 +139,7 @@ + }; + + switch (action) { +- default: assert (false); /* Fallthrough */ ++ default: assert (false); HB_FALLTHROUGH; + case NOP: return u; + case SD: pua_mappings = SD_mappings; break; + case SDL: pua_mappings = SDL_mappings; break; +@@ -315,7 +315,7 @@ + + buffer->clear_output (); + unsigned int count = buffer->len; +- for (buffer->idx = 0; buffer->idx < count;) ++ for (buffer->idx = 0; buffer->idx < count && !buffer->in_error;) + { + hb_codepoint_t u = buffer->cur().codepoint; + if (likely (!IS_SARA_AM (u))) { +@@ -330,7 +330,7 @@ + if (unlikely (buffer->in_error)) + return; + +- /* Make Nikhahit be recognized as a mark when zeroing widths. */ ++ /* Make Nikhahit be recognized as a ccc=0 mark when zeroing widths. */ + unsigned int end = buffer->out_len; + _hb_glyph_info_set_general_category (&buffer->out_info[end - 2], HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK); + +@@ -353,7 +353,7 @@ + { + /* Since we decomposed, and NIKHAHIT is combining, merge clusters with the + * previous cluster. */ +- if (start) ++ if (start && buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) + buffer->merge_out_clusters (start - 1, end); + } + } +@@ -372,10 +372,11 @@ + NULL, /* data_create */ + NULL, /* data_destroy */ + preprocess_text_thai, ++ NULL, /* postprocess_glyphs */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, + NULL, /* decompose */ + NULL, /* compose */ + NULL, /* setup_masks */ +- HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, ++ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE, + false,/* fallback_position */ + }; +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-tibetan.cc gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-tibetan.cc 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc 2016-06-05 23:50:04.665781201 +0200 +@@ -52,10 +52,11 @@ + NULL, /* data_create */ + NULL, /* data_destroy */ + NULL, /* preprocess_text */ ++ NULL, /* postprocess_glyphs */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, + NULL, /* decompose */ + NULL, /* compose */ + NULL, /* setup_masks */ +- HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, ++ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE, + true, /* fallback_position */ + }; +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-use.cc gfx/harfbuzz/src/hb-ot-shape-complex-use.cc +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-use.cc 1970-01-01 01:00:00.000000000 +0100 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-use.cc 2016-06-05 23:50:11.851743709 +0200 +@@ -0,0 +1,588 @@ ++/* ++ * Copyright © 2015 Mozilla Foundation. ++ * Copyright © 2015 Google, Inc. ++ * ++ * This is part of HarfBuzz, a text shaping library. ++ * ++ * Permission is hereby granted, without written agreement and without ++ * license or royalty fees, to use, copy, modify, and distribute this ++ * software and its documentation for any purpose, provided that the ++ * above copyright notice and the following two paragraphs appear in ++ * all copies of this software. ++ * ++ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR ++ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ++ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN ++ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ++ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, ++ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ++ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ++ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO ++ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ++ * ++ * Mozilla Author(s): Jonathan Kew ++ * Google Author(s): Behdad Esfahbod ++ */ ++ ++#include "hb-ot-shape-complex-use-private.hh" ++#include "hb-ot-shape-complex-arabic-private.hh" ++ ++/* buffer var allocations */ ++#define use_category() complex_var_u8_0() ++ ++ ++/* ++ * Universal Shaping Engine. ++ * https://www.microsoft.com/typography/OpenTypeDev/USE/intro.htm ++ */ ++ ++static const hb_tag_t ++basic_features[] = ++{ ++ /* ++ * Basic features. ++ * These features are applied all at once, before reordering. ++ */ ++ HB_TAG('r','k','r','f'), ++ HB_TAG('a','b','v','f'), ++ HB_TAG('b','l','w','f'), ++ HB_TAG('h','a','l','f'), ++ HB_TAG('p','s','t','f'), ++ HB_TAG('v','a','t','u'), ++ HB_TAG('c','j','c','t'), ++}; ++static const hb_tag_t ++arabic_features[] = ++{ ++ HB_TAG('i','s','o','l'), ++ HB_TAG('i','n','i','t'), ++ HB_TAG('m','e','d','i'), ++ HB_TAG('f','i','n','a'), ++ /* The spec doesn't specify these but we apply anyway, since our Arabic shaper ++ * does. These are only used in Syriac spec. */ ++ HB_TAG('m','e','d','2'), ++ HB_TAG('f','i','n','2'), ++ HB_TAG('f','i','n','3'), ++}; ++/* Same order as arabic_features. Don't need Syriac stuff.*/ ++enum joining_form_t { ++ ISOL, ++ INIT, ++ MEDI, ++ FINA, ++ _NONE ++}; ++static const hb_tag_t ++other_features[] = ++{ ++ /* ++ * Other features. ++ * These features are applied all at once, after reordering. ++ */ ++ HB_TAG('a','b','v','s'), ++ HB_TAG('b','l','w','s'), ++ HB_TAG('h','a','l','n'), ++ HB_TAG('p','r','e','s'), ++ HB_TAG('p','s','t','s'), ++ /* Positioning features, though we don't care about the types. */ ++ HB_TAG('d','i','s','t'), ++ HB_TAG('a','b','v','m'), ++ HB_TAG('b','l','w','m'), ++}; ++ ++static void ++setup_syllables (const hb_ot_shape_plan_t *plan, ++ hb_font_t *font, ++ hb_buffer_t *buffer); ++static void ++clear_substitution_flags (const hb_ot_shape_plan_t *plan, ++ hb_font_t *font, ++ hb_buffer_t *buffer); ++static void ++record_rphf (const hb_ot_shape_plan_t *plan, ++ hb_font_t *font, ++ hb_buffer_t *buffer); ++static void ++record_pref (const hb_ot_shape_plan_t *plan, ++ hb_font_t *font, ++ hb_buffer_t *buffer); ++static void ++reorder (const hb_ot_shape_plan_t *plan, ++ hb_font_t *font, ++ hb_buffer_t *buffer); ++ ++static void ++collect_features_use (hb_ot_shape_planner_t *plan) ++{ ++ hb_ot_map_builder_t *map = &plan->map; ++ ++ /* Do this before any lookups have been applied. */ ++ map->add_gsub_pause (setup_syllables); ++ ++ /* "Default glyph pre-processing group" */ ++ map->add_global_bool_feature (HB_TAG('l','o','c','l')); ++ map->add_global_bool_feature (HB_TAG('c','c','m','p')); ++ map->add_global_bool_feature (HB_TAG('n','u','k','t')); ++ map->add_global_bool_feature (HB_TAG('a','k','h','n')); ++ ++ /* "Reordering group" */ ++ map->add_gsub_pause (clear_substitution_flags); ++ map->add_feature (HB_TAG('r','p','h','f'), 1, F_MANUAL_ZWJ); ++ map->add_gsub_pause (record_rphf); ++ map->add_gsub_pause (clear_substitution_flags); ++ map->add_feature (HB_TAG('p','r','e','f'), 1, F_GLOBAL | F_MANUAL_ZWJ); ++ map->add_gsub_pause (record_pref); ++ ++ /* "Orthographic unit shaping group" */ ++ for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++) ++ map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ); ++ ++ map->add_gsub_pause (reorder); ++ ++ /* "Topographical features" */ ++ for (unsigned int i = 0; i < ARRAY_LENGTH (arabic_features); i++) ++ map->add_feature (arabic_features[i], 1, F_NONE); ++ map->add_gsub_pause (NULL); ++ ++ /* "Standard typographic presentation" and "Positional feature application" */ ++ for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++) ++ map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ); ++} ++ ++struct use_shape_plan_t ++{ ++ ASSERT_POD (); ++ ++ hb_mask_t rphf_mask; ++ ++ arabic_shape_plan_t *arabic_plan; ++}; ++ ++static bool ++has_arabic_joining (hb_script_t script) ++{ ++ /* List of scripts that have data in arabic-table. */ ++ switch ((int) script) ++ { ++ /* Unicode-1.1 additions */ ++ case HB_SCRIPT_ARABIC: ++ ++ /* Unicode-3.0 additions */ ++ case HB_SCRIPT_MONGOLIAN: ++ case HB_SCRIPT_SYRIAC: ++ ++ /* Unicode-5.0 additions */ ++ case HB_SCRIPT_NKO: ++ case HB_SCRIPT_PHAGS_PA: ++ ++ /* Unicode-6.0 additions */ ++ case HB_SCRIPT_MANDAIC: ++ ++ /* Unicode-7.0 additions */ ++ case HB_SCRIPT_MANICHAEAN: ++ case HB_SCRIPT_PSALTER_PAHLAVI: ++ ++ return true; ++ ++ default: ++ return false; ++ } ++} ++ ++static void * ++data_create_use (const hb_ot_shape_plan_t *plan) ++{ ++ use_shape_plan_t *use_plan = (use_shape_plan_t *) calloc (1, sizeof (use_shape_plan_t)); ++ if (unlikely (!use_plan)) ++ return NULL; ++ ++ use_plan->rphf_mask = plan->map.get_1_mask (HB_TAG('r','p','h','f')); ++ ++ if (has_arabic_joining (plan->props.script)) ++ { ++ use_plan->arabic_plan = (arabic_shape_plan_t *) data_create_arabic (plan); ++ if (unlikely (!use_plan->arabic_plan)) ++ { ++ free (use_plan); ++ return NULL; ++ } ++ } ++ ++ return use_plan; ++} ++ ++static void ++data_destroy_use (void *data) ++{ ++ use_shape_plan_t *use_plan = (use_shape_plan_t *) data; ++ ++ if (use_plan->arabic_plan) ++ data_destroy_arabic (use_plan->arabic_plan); ++ ++ free (data); ++} ++ ++enum syllable_type_t { ++ independent_cluster, ++ virama_terminated_cluster, ++ consonant_cluster, ++ vowel_cluster, ++ number_joiner_terminated_cluster, ++ numeral_cluster, ++ symbol_cluster, ++ broken_cluster, ++}; ++ ++#include "hb-ot-shape-complex-use-machine.hh" ++ ++ ++static void ++setup_masks_use (const hb_ot_shape_plan_t *plan, ++ hb_buffer_t *buffer, ++ hb_font_t *font HB_UNUSED) ++{ ++ const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data; ++ ++ /* Do this before allocating use_category(). */ ++ if (use_plan->arabic_plan) ++ { ++ setup_masks_arabic_plan (use_plan->arabic_plan, buffer, plan->props.script); ++ } ++ ++ HB_BUFFER_ALLOCATE_VAR (buffer, use_category); ++ ++ /* We cannot setup masks here. We save information about characters ++ * and setup masks later on in a pause-callback. */ ++ ++ unsigned int count = buffer->len; ++ hb_glyph_info_t *info = buffer->info; ++ for (unsigned int i = 0; i < count; i++) ++ info[i].use_category() = hb_use_get_categories (info[i].codepoint); ++} ++ ++static void ++setup_rphf_mask (const hb_ot_shape_plan_t *plan, ++ hb_buffer_t *buffer) ++{ ++ const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data; ++ ++ hb_mask_t mask = use_plan->rphf_mask; ++ if (!mask) return; ++ ++ hb_glyph_info_t *info = buffer->info; ++ ++ foreach_syllable (buffer, start, end) ++ { ++ unsigned int limit = info[start].use_category() == USE_R ? 1 : MIN (3u, end - start); ++ for (unsigned int i = start; i < start + limit; i++) ++ info[i].mask |= mask; ++ } ++} ++ ++static void ++setup_topographical_masks (const hb_ot_shape_plan_t *plan, ++ hb_buffer_t *buffer) ++{ ++ const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data; ++ if (use_plan->arabic_plan) ++ return; ++ ++ ASSERT_STATIC (INIT < 4 && ISOL < 4 && MEDI < 4 && FINA < 4); ++ hb_mask_t masks[4], all_masks = 0; ++ for (unsigned int i = 0; i < 4; i++) ++ { ++ masks[i] = plan->map.get_1_mask (arabic_features[i]); ++ if (masks[i] == plan->map.get_global_mask ()) ++ masks[i] = 0; ++ all_masks |= masks[i]; ++ } ++ if (!all_masks) ++ return; ++ hb_mask_t other_masks = ~all_masks; ++ ++ unsigned int last_start = 0; ++ joining_form_t last_form = _NONE; ++ hb_glyph_info_t *info = buffer->info; ++ foreach_syllable (buffer, start, end) ++ { ++ syllable_type_t syllable_type = (syllable_type_t) (info[start].syllable() & 0x0F); ++ switch (syllable_type) ++ { ++ case independent_cluster: ++ case symbol_cluster: ++ /* These don't join. Nothing to do. */ ++ last_form = _NONE; ++ break; ++ ++ case virama_terminated_cluster: ++ case consonant_cluster: ++ case vowel_cluster: ++ case number_joiner_terminated_cluster: ++ case numeral_cluster: ++ case broken_cluster: ++ ++ bool join = last_form == FINA || last_form == ISOL; ++ ++ if (join) ++ { ++ /* Fixup previous syllable's form. */ ++ last_form = last_form == FINA ? MEDI : INIT; ++ for (unsigned int i = last_start; i < start; i++) ++ info[i].mask = (info[i].mask & other_masks) | masks[last_form]; ++ } ++ ++ /* Form for this syllable. */ ++ last_form = join ? FINA : ISOL; ++ for (unsigned int i = start; i < end; i++) ++ info[i].mask = (info[i].mask & other_masks) | masks[last_form]; ++ ++ break; ++ } ++ ++ last_start = start; ++ } ++} ++ ++static void ++setup_syllables (const hb_ot_shape_plan_t *plan, ++ hb_font_t *font HB_UNUSED, ++ hb_buffer_t *buffer) ++{ ++ find_syllables (buffer); ++ setup_rphf_mask (plan, buffer); ++ setup_topographical_masks (plan, buffer); ++} ++ ++static void ++clear_substitution_flags (const hb_ot_shape_plan_t *plan, ++ hb_font_t *font HB_UNUSED, ++ hb_buffer_t *buffer) ++{ ++ hb_glyph_info_t *info = buffer->info; ++ unsigned int count = buffer->len; ++ for (unsigned int i = 0; i < count; i++) ++ _hb_glyph_info_clear_substituted (&info[i]); ++} ++ ++static void ++record_rphf (const hb_ot_shape_plan_t *plan, ++ hb_font_t *font, ++ hb_buffer_t *buffer) ++{ ++ const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data; ++ ++ hb_mask_t mask = use_plan->rphf_mask; ++ if (!mask) return; ++ hb_glyph_info_t *info = buffer->info; ++ ++ foreach_syllable (buffer, start, end) ++ { ++ /* Mark a substituted repha as USE_R. */ ++ for (unsigned int i = start; i < end && (info[i].mask & mask); i++) ++ if (_hb_glyph_info_substituted (&info[i])) ++ { ++ info[i].use_category() = USE_R; ++ break; ++ } ++ } ++} ++ ++static void ++record_pref (const hb_ot_shape_plan_t *plan, ++ hb_font_t *font, ++ hb_buffer_t *buffer) ++{ ++ hb_glyph_info_t *info = buffer->info; ++ ++ foreach_syllable (buffer, start, end) ++ { ++ /* Mark a substituted pref as VPre, as they behave the same way. */ ++ for (unsigned int i = start; i < end; i++) ++ if (_hb_glyph_info_substituted (&info[i])) ++ { ++ info[i].use_category() = USE_VPre; ++ break; ++ } ++ } ++} ++ ++static inline bool ++is_halant (const hb_glyph_info_t &info) ++{ ++ return info.use_category() == USE_H && !_hb_glyph_info_ligated (&info); ++} ++ ++static void ++reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end) ++{ ++ syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F); ++ /* Only a few syllable types need reordering. */ ++ if (unlikely (!(FLAG_SAFE (syllable_type) & ++ (FLAG (virama_terminated_cluster) | ++ FLAG (consonant_cluster) | ++ FLAG (vowel_cluster) | ++ FLAG (broken_cluster) | ++ 0)))) ++ return; ++ ++ hb_glyph_info_t *info = buffer->info; ++ ++#define BASE_FLAGS (FLAG (USE_B) | FLAG (USE_GB) | FLAG (USE_IV)) ++ ++ /* Move things forward. */ ++ if (info[start].use_category() == USE_R && end - start > 1) ++ { ++ /* Got a repha. Reorder it to after first base, before first halant. */ ++ for (unsigned int i = start + 1; i < end; i++) ++ if ((FLAG_UNSAFE (info[i].use_category()) & (BASE_FLAGS)) || is_halant (info[i])) ++ { ++ /* If we hit a halant, move before it; otherwise it's a base: move to it's ++ * place, and shift things in between backward. */ ++ ++ if (is_halant (info[i])) ++ i--; ++ ++ buffer->merge_clusters (start, i + 1); ++ hb_glyph_info_t t = info[start]; ++ memmove (&info[start], &info[start + 1], (i - start) * sizeof (info[0])); ++ info[i] = t; ++ ++ break; ++ } ++ } ++ ++ /* Move things back. */ ++ unsigned int j = end; ++ for (unsigned int i = start; i < end; i++) ++ { ++ uint32_t flag = FLAG_UNSAFE (info[i].use_category()); ++ if ((flag & (BASE_FLAGS)) || is_halant (info[i])) ++ { ++ /* If we hit a halant, move after it; otherwise it's a base: move to it's ++ * place, and shift things in between backward. */ ++ if (is_halant (info[i])) ++ j = i + 1; ++ else ++ j = i; ++ } ++ else if (((flag) & (FLAG (USE_VPre) | FLAG (USE_VMPre))) && ++ /* Only move the first component of a MultipleSubst. */ ++ 0 == _hb_glyph_info_get_lig_comp (&info[i]) && ++ j < i) ++ { ++ buffer->merge_clusters (j, i + 1); ++ hb_glyph_info_t t = info[i]; ++ memmove (&info[j + 1], &info[j], (i - j) * sizeof (info[0])); ++ info[j] = t; ++ } ++ } ++} ++ ++static inline void ++insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, ++ hb_font_t *font, ++ hb_buffer_t *buffer) ++{ ++ /* Note: This loop is extra overhead, but should not be measurable. */ ++ bool has_broken_syllables = false; ++ unsigned int count = buffer->len; ++ hb_glyph_info_t *info = buffer->info; ++ for (unsigned int i = 0; i < count; i++) ++ if ((info[i].syllable() & 0x0F) == broken_cluster) ++ { ++ has_broken_syllables = true; ++ break; ++ } ++ if (likely (!has_broken_syllables)) ++ return; ++ ++ hb_glyph_info_t dottedcircle = {0}; ++ if (!font->get_glyph (0x25CCu, 0, &dottedcircle.codepoint)) ++ return; ++ dottedcircle.use_category() = hb_use_get_categories (0x25CC); ++ ++ buffer->clear_output (); ++ ++ buffer->idx = 0; ++ unsigned int last_syllable = 0; ++ while (buffer->idx < buffer->len && !buffer->in_error) ++ { ++ unsigned int syllable = buffer->cur().syllable(); ++ syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F); ++ if (unlikely (last_syllable != syllable && syllable_type == broken_cluster)) ++ { ++ last_syllable = syllable; ++ ++ hb_glyph_info_t ginfo = dottedcircle; ++ ginfo.cluster = buffer->cur().cluster; ++ ginfo.mask = buffer->cur().mask; ++ ginfo.syllable() = buffer->cur().syllable(); ++ /* TODO Set glyph_props? */ ++ ++ /* Insert dottedcircle after possible Repha. */ ++ while (buffer->idx < buffer->len && ++ last_syllable == buffer->cur().syllable() && ++ buffer->cur().use_category() == USE_R) ++ buffer->next_glyph (); ++ ++ buffer->output_info (ginfo); ++ } ++ else ++ buffer->next_glyph (); ++ } ++ ++ buffer->swap_buffers (); ++} ++ ++static void ++reorder (const hb_ot_shape_plan_t *plan, ++ hb_font_t *font, ++ hb_buffer_t *buffer) ++{ ++ insert_dotted_circles (plan, font, buffer); ++ ++ hb_glyph_info_t *info = buffer->info; ++ ++ foreach_syllable (buffer, start, end) ++ reorder_syllable (buffer, start, end); ++ ++ /* Zero syllables now... */ ++ unsigned int count = buffer->len; ++ for (unsigned int i = 0; i < count; i++) ++ info[i].syllable() = 0; ++ ++ HB_BUFFER_DEALLOCATE_VAR (buffer, use_category); ++} ++ ++static bool ++compose_use (const hb_ot_shape_normalize_context_t *c, ++ hb_codepoint_t a, ++ hb_codepoint_t b, ++ hb_codepoint_t *ab) ++{ ++ /* Avoid recomposing split matras. */ ++ if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (c->unicode->general_category (a))) ++ return false; ++ ++ return (bool)c->unicode->compose (a, b, ab); ++} ++ ++ ++const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use = ++{ ++ "use", ++ collect_features_use, ++ NULL, /* override_features */ ++ data_create_use, ++ data_destroy_use, ++ NULL, /* preprocess_text */ ++ NULL, /* postprocess_glyphs */ ++ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, ++ NULL, /* decompose */ ++ compose_use, ++ setup_masks_use, ++ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, ++ false, /* fallback_position */ ++}; +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-use-machine.hh gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.hh +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-use-machine.hh 1970-01-01 01:00:00.000000000 +0100 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.hh 2016-06-05 23:50:06.101773685 +0200 +@@ -0,0 +1,548 @@ ++ ++#line 1 "hb-ot-shape-complex-use-machine.rl" ++/* ++ * Copyright © 2015 Mozilla Foundation. ++ * Copyright © 2015 Google, Inc. ++ * ++ * This is part of HarfBuzz, a text shaping library. ++ * ++ * Permission is hereby granted, without written agreement and without ++ * license or royalty fees, to use, copy, modify, and distribute this ++ * software and its documentation for any purpose, provided that the ++ * above copyright notice and the following two paragraphs appear in ++ * all copies of this software. ++ * ++ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR ++ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ++ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN ++ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ++ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, ++ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ++ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ++ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO ++ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ++ * ++ * Mozilla Author(s): Jonathan Kew ++ * Google Author(s): Behdad Esfahbod ++ */ ++ ++#ifndef HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH ++#define HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH ++ ++#include "hb-private.hh" ++ ++ ++#line 38 "hb-ot-shape-complex-use-machine.hh" ++static const unsigned char _use_syllable_machine_trans_keys[] = { ++ 0u, 0u, 4u, 4u, 1u, 1u, 0u, 39u, 21u, 21u, 8u, 39u, 8u, 39u, 1u, 1u, ++ 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u, ++ 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, ++ 8u, 39u, 8u, 39u, 8u, 39u, 1u, 1u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, ++ 8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, ++ 8u, 39u, 12u, 21u, 12u, 13u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, ++ 8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, ++ 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 1u, 39u, 8u, 39u, 21u, 42u, 41u, 42u, ++ 42u, 42u, 0 ++}; ++ ++static const char _use_syllable_machine_key_spans[] = { ++ 0, 1, 1, 40, 1, 32, 32, 1, ++ 32, 32, 32, 19, 19, 19, 32, 32, ++ 32, 32, 32, 32, 32, 32, 32, 32, ++ 32, 32, 32, 1, 32, 32, 19, 19, ++ 19, 32, 32, 32, 32, 32, 32, 32, ++ 32, 10, 2, 32, 32, 32, 32, 19, ++ 19, 19, 32, 32, 32, 32, 32, 32, ++ 32, 32, 32, 32, 39, 32, 22, 2, ++ 1 ++}; ++ ++static const short _use_syllable_machine_index_offsets[] = { ++ 0, 0, 2, 4, 45, 47, 80, 113, ++ 115, 148, 181, 214, 234, 254, 274, 307, ++ 340, 373, 406, 439, 472, 505, 538, 571, ++ 604, 637, 670, 703, 705, 738, 771, 791, ++ 811, 831, 864, 897, 930, 963, 996, 1029, ++ 1062, 1095, 1106, 1109, 1142, 1175, 1208, 1241, ++ 1261, 1281, 1301, 1334, 1367, 1400, 1433, 1466, ++ 1499, 1532, 1565, 1598, 1631, 1671, 1704, 1727, ++ 1730 ++}; ++ ++static const char _use_syllable_machine_indicies[] = { ++ 1, 0, 3, 2, 4, 5, 6, ++ 4, 1, 5, 8, 8, 7, 8, 8, ++ 3, 9, 8, 8, 8, 4, 4, 10, ++ 11, 8, 8, 12, 13, 14, 15, 16, ++ 17, 18, 12, 19, 20, 21, 22, 23, ++ 24, 8, 25, 26, 27, 8, 29, 28, ++ 31, 30, 30, 32, 33, 30, 30, 30, ++ 30, 30, 30, 30, 30, 34, 35, 36, ++ 37, 38, 39, 40, 41, 35, 42, 34, ++ 43, 44, 45, 46, 30, 47, 48, 49, ++ 30, 31, 30, 30, 32, 33, 30, 30, ++ 30, 30, 30, 30, 30, 30, 50, 35, ++ 36, 37, 38, 39, 40, 41, 35, 42, ++ 43, 43, 44, 45, 46, 30, 47, 48, ++ 49, 30, 32, 51, 31, 30, 30, 32, ++ 33, 30, 30, 30, 30, 30, 30, 30, ++ 30, 30, 35, 36, 37, 38, 39, 40, ++ 41, 35, 42, 43, 43, 44, 45, 46, ++ 30, 47, 48, 49, 30, 31, 30, 30, ++ 30, 30, 30, 30, 30, 30, 30, 30, ++ 30, 30, 30, 35, 36, 37, 38, 39, ++ 30, 30, 30, 30, 30, 30, 44, 45, ++ 46, 30, 47, 48, 49, 30, 31, 30, ++ 30, 30, 30, 30, 30, 30, 30, 30, ++ 30, 30, 30, 30, 30, 36, 37, 38, ++ 39, 30, 30, 30, 30, 30, 30, 30, ++ 30, 30, 30, 47, 48, 49, 30, 31, ++ 30, 30, 30, 30, 30, 30, 30, 30, ++ 30, 30, 30, 30, 30, 30, 30, 37, ++ 38, 39, 30, 31, 30, 30, 30, 30, ++ 30, 30, 30, 30, 30, 30, 30, 30, ++ 30, 30, 30, 30, 38, 39, 30, 31, ++ 30, 30, 30, 30, 30, 30, 30, 30, ++ 30, 30, 30, 30, 30, 30, 30, 30, ++ 30, 39, 30, 31, 30, 30, 30, 30, ++ 30, 30, 30, 30, 30, 30, 30, 30, ++ 30, 30, 30, 37, 38, 39, 30, 30, ++ 30, 30, 30, 30, 30, 30, 30, 30, ++ 47, 48, 49, 30, 31, 30, 30, 30, ++ 30, 30, 30, 30, 30, 30, 30, 30, ++ 30, 30, 30, 30, 37, 38, 39, 30, ++ 30, 30, 30, 30, 30, 30, 30, 30, ++ 30, 30, 48, 49, 30, 31, 30, 30, ++ 30, 30, 30, 30, 30, 30, 30, 30, ++ 30, 30, 30, 30, 30, 37, 38, 39, ++ 30, 30, 30, 30, 30, 30, 30, 30, ++ 30, 30, 30, 30, 49, 30, 31, 30, ++ 30, 30, 30, 30, 30, 30, 30, 30, ++ 30, 30, 30, 30, 30, 36, 37, 38, ++ 39, 30, 30, 30, 30, 30, 30, 44, ++ 45, 46, 30, 47, 48, 49, 30, 31, ++ 30, 30, 30, 30, 30, 30, 30, 30, ++ 30, 30, 30, 30, 30, 30, 36, 37, ++ 38, 39, 30, 30, 30, 30, 30, 30, ++ 30, 45, 46, 30, 47, 48, 49, 30, ++ 31, 30, 30, 30, 30, 30, 30, 30, ++ 30, 30, 30, 30, 30, 30, 30, 36, ++ 37, 38, 39, 30, 30, 30, 30, 30, ++ 30, 30, 30, 46, 30, 47, 48, 49, ++ 30, 31, 30, 30, 30, 30, 30, 30, ++ 30, 30, 30, 30, 30, 30, 30, 35, ++ 36, 37, 38, 39, 30, 41, 35, 30, ++ 30, 30, 44, 45, 46, 30, 47, 48, ++ 49, 30, 31, 30, 30, 30, 30, 30, ++ 30, 30, 30, 30, 30, 30, 30, 30, ++ 35, 36, 37, 38, 39, 30, 30, 35, ++ 30, 30, 30, 44, 45, 46, 30, 47, ++ 48, 49, 30, 31, 30, 30, 30, 30, ++ 30, 30, 30, 30, 30, 30, 30, 30, ++ 30, 35, 36, 37, 38, 39, 40, 41, ++ 35, 30, 30, 30, 44, 45, 46, 30, ++ 47, 48, 49, 30, 31, 30, 30, 32, ++ 33, 30, 30, 30, 30, 30, 30, 30, ++ 30, 30, 35, 36, 37, 38, 39, 40, ++ 41, 35, 42, 30, 43, 44, 45, 46, ++ 30, 47, 48, 49, 30, 31, 30, 30, ++ 32, 33, 30, 30, 30, 30, 30, 30, ++ 30, 30, 30, 35, 36, 37, 38, 39, ++ 40, 41, 35, 42, 34, 43, 44, 45, ++ 46, 30, 47, 48, 49, 30, 53, 52, ++ 52, 54, 55, 52, 52, 52, 52, 52, ++ 52, 52, 52, 56, 52, 57, 58, 59, ++ 60, 61, 62, 57, 63, 56, 64, 52, ++ 52, 52, 52, 65, 66, 67, 52, 53, ++ 52, 52, 54, 55, 52, 52, 52, 52, ++ 52, 52, 52, 52, 68, 52, 57, 58, ++ 59, 60, 61, 62, 57, 63, 64, 64, ++ 52, 52, 52, 52, 65, 66, 67, 52, ++ 54, 51, 53, 52, 52, 54, 55, 52, ++ 52, 52, 52, 52, 52, 52, 52, 52, ++ 52, 57, 58, 59, 60, 61, 62, 57, ++ 63, 64, 64, 52, 52, 52, 52, 65, ++ 66, 67, 52, 53, 52, 52, 52, 52, ++ 52, 52, 52, 52, 52, 52, 52, 52, ++ 52, 52, 57, 58, 59, 60, 52, 52, ++ 52, 52, 52, 52, 52, 52, 52, 52, ++ 65, 66, 67, 52, 53, 52, 52, 52, ++ 52, 52, 52, 52, 52, 52, 52, 52, ++ 52, 52, 52, 52, 58, 59, 60, 52, ++ 53, 52, 52, 52, 52, 52, 52, 52, ++ 52, 52, 52, 52, 52, 52, 52, 52, ++ 52, 59, 60, 52, 53, 52, 52, 52, ++ 52, 52, 52, 52, 52, 52, 52, 52, ++ 52, 52, 52, 52, 52, 52, 60, 52, ++ 53, 52, 52, 52, 52, 52, 52, 52, ++ 52, 52, 52, 52, 52, 52, 52, 52, ++ 58, 59, 60, 52, 52, 52, 52, 52, ++ 52, 52, 52, 52, 52, 65, 66, 67, ++ 52, 53, 52, 52, 52, 52, 52, 52, ++ 52, 52, 52, 52, 52, 52, 52, 52, ++ 52, 58, 59, 60, 52, 52, 52, 52, ++ 52, 52, 52, 52, 52, 52, 52, 66, ++ 67, 52, 53, 52, 52, 52, 52, 52, ++ 52, 52, 52, 52, 52, 52, 52, 52, ++ 52, 52, 58, 59, 60, 52, 52, 52, ++ 52, 52, 52, 52, 52, 52, 52, 52, ++ 52, 67, 52, 53, 52, 52, 52, 52, ++ 52, 52, 52, 52, 52, 52, 52, 52, ++ 52, 52, 57, 58, 59, 60, 52, 62, ++ 57, 52, 52, 52, 52, 52, 52, 52, ++ 65, 66, 67, 52, 53, 52, 52, 52, ++ 52, 52, 52, 52, 52, 52, 52, 52, ++ 52, 52, 52, 57, 58, 59, 60, 52, ++ 52, 57, 52, 52, 52, 52, 52, 52, ++ 52, 65, 66, 67, 52, 53, 52, 52, ++ 52, 52, 52, 52, 52, 52, 52, 52, ++ 52, 52, 52, 52, 57, 58, 59, 60, ++ 61, 62, 57, 52, 52, 52, 52, 52, ++ 52, 52, 65, 66, 67, 52, 53, 52, ++ 52, 54, 55, 52, 52, 52, 52, 52, ++ 52, 52, 52, 52, 52, 57, 58, 59, ++ 60, 61, 62, 57, 63, 52, 64, 52, ++ 52, 52, 52, 65, 66, 67, 52, 53, ++ 52, 52, 54, 55, 52, 52, 52, 52, ++ 52, 52, 52, 52, 52, 52, 57, 58, ++ 59, 60, 61, 62, 57, 63, 56, 64, ++ 52, 52, 52, 52, 65, 66, 67, 52, ++ 70, 71, 69, 69, 69, 69, 69, 69, ++ 69, 72, 69, 70, 71, 69, 7, 73, ++ 73, 3, 9, 73, 73, 73, 73, 73, ++ 73, 73, 73, 74, 12, 13, 14, 15, ++ 16, 17, 18, 12, 19, 21, 21, 22, ++ 23, 24, 73, 25, 26, 27, 73, 7, ++ 73, 73, 3, 9, 73, 73, 73, 73, ++ 73, 73, 73, 73, 73, 12, 13, 14, ++ 15, 16, 17, 18, 12, 19, 21, 21, ++ 22, 23, 24, 73, 25, 26, 27, 73, ++ 7, 73, 73, 73, 73, 73, 73, 73, ++ 73, 73, 73, 73, 73, 73, 12, 13, ++ 14, 15, 16, 73, 73, 73, 73, 73, ++ 73, 22, 23, 24, 73, 25, 26, 27, ++ 73, 7, 73, 73, 73, 73, 73, 73, ++ 73, 73, 73, 73, 73, 73, 73, 73, ++ 13, 14, 15, 16, 73, 73, 73, 73, ++ 73, 73, 73, 73, 73, 73, 25, 26, ++ 27, 73, 7, 73, 73, 73, 73, 73, ++ 73, 73, 73, 73, 73, 73, 73, 73, ++ 73, 73, 14, 15, 16, 73, 7, 73, ++ 73, 73, 73, 73, 73, 73, 73, 73, ++ 73, 73, 73, 73, 73, 73, 73, 15, ++ 16, 73, 7, 73, 73, 73, 73, 73, ++ 73, 73, 73, 73, 73, 73, 73, 73, ++ 73, 73, 73, 73, 16, 73, 7, 73, ++ 73, 73, 73, 73, 73, 73, 73, 73, ++ 73, 73, 73, 73, 73, 73, 14, 15, ++ 16, 73, 73, 73, 73, 73, 73, 73, ++ 73, 73, 73, 25, 26, 27, 73, 7, ++ 73, 73, 73, 73, 73, 73, 73, 73, ++ 73, 73, 73, 73, 73, 73, 73, 14, ++ 15, 16, 73, 73, 73, 73, 73, 73, ++ 73, 73, 73, 73, 73, 26, 27, 73, ++ 7, 73, 73, 73, 73, 73, 73, 73, ++ 73, 73, 73, 73, 73, 73, 73, 73, ++ 14, 15, 16, 73, 73, 73, 73, 73, ++ 73, 73, 73, 73, 73, 73, 73, 27, ++ 73, 7, 73, 73, 73, 73, 73, 73, ++ 73, 73, 73, 73, 73, 73, 73, 73, ++ 13, 14, 15, 16, 73, 73, 73, 73, ++ 73, 73, 22, 23, 24, 73, 25, 26, ++ 27, 73, 7, 73, 73, 73, 73, 73, ++ 73, 73, 73, 73, 73, 73, 73, 73, ++ 73, 13, 14, 15, 16, 73, 73, 73, ++ 73, 73, 73, 73, 23, 24, 73, 25, ++ 26, 27, 73, 7, 73, 73, 73, 73, ++ 73, 73, 73, 73, 73, 73, 73, 73, ++ 73, 73, 13, 14, 15, 16, 73, 73, ++ 73, 73, 73, 73, 73, 73, 24, 73, ++ 25, 26, 27, 73, 7, 73, 73, 73, ++ 73, 73, 73, 73, 73, 73, 73, 73, ++ 73, 73, 12, 13, 14, 15, 16, 73, ++ 18, 12, 73, 73, 73, 22, 23, 24, ++ 73, 25, 26, 27, 73, 7, 73, 73, ++ 73, 73, 73, 73, 73, 73, 73, 73, ++ 73, 73, 73, 12, 13, 14, 15, 16, ++ 73, 73, 12, 73, 73, 73, 22, 23, ++ 24, 73, 25, 26, 27, 73, 7, 73, ++ 73, 73, 73, 73, 73, 73, 73, 73, ++ 73, 73, 73, 73, 12, 13, 14, 15, ++ 16, 17, 18, 12, 73, 73, 73, 22, ++ 23, 24, 73, 25, 26, 27, 73, 7, ++ 73, 73, 3, 9, 73, 73, 73, 73, ++ 73, 73, 73, 73, 73, 12, 13, 14, ++ 15, 16, 17, 18, 12, 19, 73, 21, ++ 22, 23, 24, 73, 25, 26, 27, 73, ++ 5, 6, 73, 73, 5, 73, 73, 7, ++ 73, 73, 3, 9, 73, 73, 73, 73, ++ 73, 73, 73, 73, 73, 12, 13, 14, ++ 15, 16, 17, 18, 12, 19, 20, 21, ++ 22, 23, 24, 73, 25, 26, 27, 73, ++ 7, 73, 73, 3, 9, 73, 73, 73, ++ 73, 73, 73, 73, 73, 73, 12, 13, ++ 14, 15, 16, 17, 18, 12, 19, 20, ++ 21, 22, 23, 24, 73, 25, 26, 27, ++ 73, 76, 75, 75, 75, 75, 75, 75, ++ 75, 75, 75, 75, 75, 75, 75, 75, ++ 75, 75, 75, 75, 75, 76, 77, 75, ++ 76, 77, 75, 77, 75, 0 ++}; ++ ++static const char _use_syllable_machine_trans_targs[] = { ++ 3, 41, 3, 43, 4, 5, 25, 3, ++ 0, 2, 60, 62, 45, 46, 47, 48, ++ 49, 56, 57, 58, 61, 59, 53, 54, ++ 55, 50, 51, 52, 3, 3, 3, 3, ++ 6, 7, 24, 9, 10, 11, 12, 13, ++ 20, 21, 22, 23, 17, 18, 19, 14, ++ 15, 16, 8, 3, 3, 3, 26, 27, ++ 40, 29, 30, 31, 32, 36, 37, 38, ++ 39, 33, 34, 35, 28, 3, 3, 1, ++ 42, 3, 44, 3, 63, 64 ++}; ++ ++static const char _use_syllable_machine_trans_actions[] = { ++ 1, 2, 3, 4, 0, 0, 0, 7, ++ 0, 0, 4, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 4, 4, 0, 0, ++ 0, 0, 0, 0, 8, 9, 10, 11, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 12, 13, 14, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 15, 16, 0, ++ 2, 17, 4, 18, 0, 0 ++}; ++ ++static const char _use_syllable_machine_to_state_actions[] = { ++ 0, 0, 0, 5, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0 ++}; ++ ++static const char _use_syllable_machine_from_state_actions[] = { ++ 0, 0, 0, 6, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0 ++}; ++ ++static const short _use_syllable_machine_eof_trans[] = { ++ 0, 1, 3, 0, 29, 31, 31, 52, ++ 31, 31, 31, 31, 31, 31, 31, 31, ++ 31, 31, 31, 31, 31, 31, 31, 31, ++ 31, 53, 53, 52, 53, 53, 53, 53, ++ 53, 53, 53, 53, 53, 53, 53, 53, ++ 53, 70, 70, 74, 74, 74, 74, 74, ++ 74, 74, 74, 74, 74, 74, 74, 74, ++ 74, 74, 74, 74, 74, 74, 76, 76, ++ 76 ++}; ++ ++static const int use_syllable_machine_start = 3; ++static const int use_syllable_machine_first_final = 3; ++static const int use_syllable_machine_error = 0; ++ ++static const int use_syllable_machine_en_main = 3; ++ ++ ++#line 38 "hb-ot-shape-complex-use-machine.rl" ++ ++ ++ ++#line 145 "hb-ot-shape-complex-use-machine.rl" ++ ++ ++#define found_syllable(syllable_type) \ ++ HB_STMT_START { \ ++ if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \ ++ for (unsigned int i = last; i < p+1; i++) \ ++ info[i].syllable() = (syllable_serial << 4) | syllable_type; \ ++ last = p+1; \ ++ syllable_serial++; \ ++ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ ++ } HB_STMT_END ++ ++static void ++find_syllables (hb_buffer_t *buffer) ++{ ++ unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED; ++ int cs; ++ hb_glyph_info_t *info = buffer->info; ++ ++#line 388 "hb-ot-shape-complex-use-machine.hh" ++ { ++ cs = use_syllable_machine_start; ++ ts = 0; ++ te = 0; ++ act = 0; ++ } ++ ++#line 166 "hb-ot-shape-complex-use-machine.rl" ++ ++ ++ p = 0; ++ pe = eof = buffer->len; ++ ++ unsigned int last = 0; ++ unsigned int syllable_serial = 1; ++ ++#line 405 "hb-ot-shape-complex-use-machine.hh" ++ { ++ int _slen; ++ int _trans; ++ const unsigned char *_keys; ++ const char *_inds; ++ if ( p == pe ) ++ goto _test_eof; ++ if ( cs == 0 ) ++ goto _out; ++_resume: ++ switch ( _use_syllable_machine_from_state_actions[cs] ) { ++ case 6: ++#line 1 "NONE" ++ {ts = p;} ++ break; ++#line 421 "hb-ot-shape-complex-use-machine.hh" ++ } ++ ++ _keys = _use_syllable_machine_trans_keys + (cs<<1); ++ _inds = _use_syllable_machine_indicies + _use_syllable_machine_index_offsets[cs]; ++ ++ _slen = _use_syllable_machine_key_spans[cs]; ++ _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].use_category()) && ++ ( info[p].use_category()) <= _keys[1] ? ++ ( info[p].use_category()) - _keys[0] : _slen ]; ++ ++_eof_trans: ++ cs = _use_syllable_machine_trans_targs[_trans]; ++ ++ if ( _use_syllable_machine_trans_actions[_trans] == 0 ) ++ goto _again; ++ ++ switch ( _use_syllable_machine_trans_actions[_trans] ) { ++ case 2: ++#line 1 "NONE" ++ {te = p+1;} ++ break; ++ case 9: ++#line 134 "hb-ot-shape-complex-use-machine.rl" ++ {te = p+1;{ found_syllable (independent_cluster); }} ++ break; ++ case 11: ++#line 136 "hb-ot-shape-complex-use-machine.rl" ++ {te = p+1;{ found_syllable (consonant_cluster); }} ++ break; ++ case 14: ++#line 137 "hb-ot-shape-complex-use-machine.rl" ++ {te = p+1;{ found_syllable (vowel_cluster); }} ++ break; ++ case 16: ++#line 138 "hb-ot-shape-complex-use-machine.rl" ++ {te = p+1;{ found_syllable (number_joiner_terminated_cluster); }} ++ break; ++ case 7: ++#line 141 "hb-ot-shape-complex-use-machine.rl" ++ {te = p+1;{ found_syllable (broken_cluster); }} ++ break; ++ case 8: ++#line 134 "hb-ot-shape-complex-use-machine.rl" ++ {te = p;p--;{ found_syllable (independent_cluster); }} ++ break; ++ case 12: ++#line 135 "hb-ot-shape-complex-use-machine.rl" ++ {te = p;p--;{ found_syllable (virama_terminated_cluster); }} ++ break; ++ case 10: ++#line 136 "hb-ot-shape-complex-use-machine.rl" ++ {te = p;p--;{ found_syllable (consonant_cluster); }} ++ break; ++ case 13: ++#line 137 "hb-ot-shape-complex-use-machine.rl" ++ {te = p;p--;{ found_syllable (vowel_cluster); }} ++ break; ++ case 15: ++#line 139 "hb-ot-shape-complex-use-machine.rl" ++ {te = p;p--;{ found_syllable (numeral_cluster); }} ++ break; ++ case 18: ++#line 140 "hb-ot-shape-complex-use-machine.rl" ++ {te = p;p--;{ found_syllable (symbol_cluster); }} ++ break; ++ case 17: ++#line 141 "hb-ot-shape-complex-use-machine.rl" ++ {te = p;p--;{ found_syllable (broken_cluster); }} ++ break; ++ case 1: ++#line 139 "hb-ot-shape-complex-use-machine.rl" ++ {{p = ((te))-1;}{ found_syllable (numeral_cluster); }} ++ break; ++ case 3: ++#line 1 "NONE" ++ { switch( act ) { ++ case 0: ++ {{cs = 0; goto _again;}} ++ break; ++ case 8: ++ {{p = ((te))-1;} found_syllable (broken_cluster); } ++ break; ++ } ++ } ++ break; ++ case 4: ++#line 1 "NONE" ++ {te = p+1;} ++#line 141 "hb-ot-shape-complex-use-machine.rl" ++ {act = 8;} ++ break; ++#line 513 "hb-ot-shape-complex-use-machine.hh" ++ } ++ ++_again: ++ switch ( _use_syllable_machine_to_state_actions[cs] ) { ++ case 5: ++#line 1 "NONE" ++ {ts = 0;} ++#line 1 "NONE" ++ {act = 0;} ++ break; ++#line 524 "hb-ot-shape-complex-use-machine.hh" ++ } ++ ++ if ( cs == 0 ) ++ goto _out; ++ if ( ++p != pe ) ++ goto _resume; ++ _test_eof: {} ++ if ( p == eof ) ++ { ++ if ( _use_syllable_machine_eof_trans[cs] > 0 ) { ++ _trans = _use_syllable_machine_eof_trans[cs] - 1; ++ goto _eof_trans; ++ } ++ } ++ ++ _out: {} ++ } ++ ++#line 175 "hb-ot-shape-complex-use-machine.rl" ++ ++} ++ ++#undef found_syllable ++ ++#endif /* HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH */ +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-use-machine.rl gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.rl +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-use-machine.rl 1970-01-01 01:00:00.000000000 +0100 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.rl 2016-06-05 23:50:07.357767129 +0200 +@@ -0,0 +1,180 @@ ++/* ++ * Copyright © 2015 Mozilla Foundation. ++ * Copyright © 2015 Google, Inc. ++ * ++ * This is part of HarfBuzz, a text shaping library. ++ * ++ * Permission is hereby granted, without written agreement and without ++ * license or royalty fees, to use, copy, modify, and distribute this ++ * software and its documentation for any purpose, provided that the ++ * above copyright notice and the following two paragraphs appear in ++ * all copies of this software. ++ * ++ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR ++ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ++ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN ++ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ++ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, ++ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ++ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ++ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO ++ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ++ * ++ * Mozilla Author(s): Jonathan Kew ++ * Google Author(s): Behdad Esfahbod ++ */ ++ ++#ifndef HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH ++#define HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH ++ ++#include "hb-private.hh" ++ ++%%{ ++ machine use_syllable_machine; ++ alphtype unsigned char; ++ write data; ++}%% ++ ++%%{ ++ ++# Same order as enum use_category_t. Not sure how to avoid duplication. ++ ++O = 0; # OTHER ++ ++B = 1; # BASE ++IV = 2; # BASE_VOWEL ++IND = 3; # BASE_IND ++N = 4; # BASE_NUM ++GB = 5; # BASE_OTHER ++CGJ = 6; # CGJ ++#F = 7; # CONS_FINAL ++FM = 8; # CONS_FINAL_MOD ++#M = 9; # CONS_MED ++#CM = 10; # CONS_MOD ++SUB = 11; # CONS_SUB ++H = 12; # HALANT ++ ++HN = 13; # HALANT_NUM ++ZWNJ = 14; # Zero width non-joiner ++ZWJ = 15; # Zero width joiner ++WJ = 16; # Word joiner ++Rsv = 17; # Reserved characters ++R = 18; # REPHA ++S = 19; # SYM ++#SM = 20; # SYM_MOD ++VS = 21; # VARIATION_SELECTOR ++#V = 36; # VOWEL ++#VM = 40; # VOWEL_MOD ++ ++FAbv = 24; # CONS_FINAL_ABOVE ++FBlw = 25; # CONS_FINAL_BELOW ++FPst = 26; # CONS_FINAL_POST ++MAbv = 27; # CONS_MED_ABOVE ++MBlw = 28; # CONS_MED_BELOW ++MPst = 29; # CONS_MED_POST ++MPre = 30; # CONS_MED_PRE ++CMAbv = 31; # CONS_MOD_ABOVE ++CMBlw = 32; # CONS_MOD_BELOW ++VAbv = 33; # VOWEL_ABOVE / VOWEL_ABOVE_BELOW / VOWEL_ABOVE_BELOW_POST / VOWEL_ABOVE_POST ++VBlw = 34; # VOWEL_BELOW / VOWEL_BELOW_POST ++VPst = 35; # VOWEL_POST UIPC = Right ++VPre = 22; # VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST ++VMAbv = 37; # VOWEL_MOD_ABOVE ++VMBlw = 38; # VOWEL_MOD_BELOW ++VMPst = 39; # VOWEL_MOD_POST ++VMPre = 23; # VOWEL_MOD_PRE ++SMAbv = 41; # SYM_MOD_ABOVE ++SMBlw = 42; # SYM_MOD_BELOW ++ ++ ++consonant_modifiers = CMAbv* CMBlw* ((H B | SUB) VS? CMAbv? CMBlw*)*; ++medial_consonants = MPre? MAbv? MBlw? MPst?; ++dependent_vowels = VPre* VAbv* VBlw* VPst*; ++vowel_modifiers = VMPre* VMAbv* VMBlw* VMPst*; ++final_consonants = FAbv* FBlw* FPst* FM?; ++ ++virama_terminated_cluster = ++ R? (B | GB | IV) VS? ++ consonant_modifiers ++ H ++; ++consonant_cluster = ++ R? (B | GB) VS? ++ consonant_modifiers ++ medial_consonants ++ dependent_vowels ++ vowel_modifiers ++ final_consonants ++; ++vowel_cluster = ++ R? (IV) VS? ++ consonant_modifiers ++ medial_consonants ++ vowel_modifiers ++ final_consonants ++; ++ ++broken_cluster = ++ R? ++ consonant_modifiers ++ medial_consonants ++ dependent_vowels ++ vowel_modifiers ++ final_consonants ++; ++ ++number_joiner_terminated_cluster = N VS? (HN N VS?)* H; ++numeral_cluster = N VS? (HN N VS?)*; ++symbol_cluster = S VS? SMAbv* SMBlw*; ++independent_cluster = (IND | O | Rsv | WJ) VS?; ++ ++main := |* ++ independent_cluster => { found_syllable (independent_cluster); }; ++ virama_terminated_cluster => { found_syllable (virama_terminated_cluster); }; ++ consonant_cluster => { found_syllable (consonant_cluster); }; ++ vowel_cluster => { found_syllable (vowel_cluster); }; ++ number_joiner_terminated_cluster => { found_syllable (number_joiner_terminated_cluster); }; ++ numeral_cluster => { found_syllable (numeral_cluster); }; ++ symbol_cluster => { found_syllable (symbol_cluster); }; ++ broken_cluster => { found_syllable (broken_cluster); }; ++*|; ++ ++ ++}%% ++ ++#define found_syllable(syllable_type) \ ++ HB_STMT_START { \ ++ if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \ ++ for (unsigned int i = last; i < p+1; i++) \ ++ info[i].syllable() = (syllable_serial << 4) | syllable_type; \ ++ last = p+1; \ ++ syllable_serial++; \ ++ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ ++ } HB_STMT_END ++ ++static void ++find_syllables (hb_buffer_t *buffer) ++{ ++ unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED; ++ int cs; ++ hb_glyph_info_t *info = buffer->info; ++ %%{ ++ write init; ++ getkey info[p].use_category(); ++ }%% ++ ++ p = 0; ++ pe = eof = buffer->len; ++ ++ unsigned int last = 0; ++ unsigned int syllable_serial = 1; ++ %%{ ++ write exec; ++ }%% ++} ++ ++#undef found_syllable ++ ++#endif /* HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH */ +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-use-private.hh gfx/harfbuzz/src/hb-ot-shape-complex-use-private.hh +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-use-private.hh 1970-01-01 01:00:00.000000000 +0100 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-use-private.hh 2016-06-05 23:50:08.571760803 +0200 +@@ -0,0 +1,97 @@ ++/* ++ * Copyright © 2015 Mozilla Foundation. ++ * Copyright © 2015 Google, Inc. ++ * ++ * This is part of HarfBuzz, a text shaping library. ++ * ++ * Permission is hereby granted, without written agreement and without ++ * license or royalty fees, to use, copy, modify, and distribute this ++ * software and its documentation for any purpose, provided that the ++ * above copyright notice and the following two paragraphs appear in ++ * all copies of this software. ++ * ++ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR ++ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ++ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN ++ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ++ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, ++ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ++ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ++ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO ++ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ++ * ++ * Mozilla Author(s): Jonathan Kew ++ * Google Author(s): Behdad Esfahbod ++ */ ++ ++#ifndef HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH ++#define HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH ++ ++#include "hb-private.hh" ++ ++ ++#include "hb-ot-shape-complex-private.hh" ++ ++ ++#define USE_TABLE_ELEMENT_TYPE uint8_t ++ ++/* Cateories used in the Universal Shaping Engine spec: ++ * https://www.microsoft.com/typography/OpenTypeDev/USE/intro.htm ++ */ ++/* Note: This enum is duplicated in the -machine.rl source file. ++ * Not sure how to avoid duplication. */ ++enum use_category_t { ++ USE_O = 0, /* OTHER */ ++ ++ USE_B = 1, /* BASE */ ++ USE_IV = 2, /* BASE_VOWEL */ ++ USE_IND = 3, /* BASE_IND */ ++ USE_N = 4, /* BASE_NUM */ ++ USE_GB = 5, /* BASE_OTHER */ ++ USE_CGJ = 6, /* CGJ */ ++// USE_F = 7, /* CONS_FINAL */ ++ USE_FM = 8, /* CONS_FINAL_MOD */ ++// USE_M = 9, /* CONS_MED */ ++// USE_CM = 10, /* CONS_MOD */ ++ USE_SUB = 11, /* CONS_SUB */ ++ USE_H = 12, /* HALANT */ ++ ++ USE_HN = 13, /* HALANT_NUM */ ++ USE_ZWNJ = 14, /* Zero width non-joiner */ ++ USE_ZWJ = 15, /* Zero width joiner */ ++ USE_WJ = 16, /* Word joiner */ ++ USE_Rsv = 17, /* Reserved characters */ ++ USE_R = 18, /* REPHA */ ++ USE_S = 19, /* SYM */ ++// USE_SM = 20, /* SYM_MOD */ ++ USE_VS = 21, /* VARIATION_SELECTOR */ ++// USE_V = 36, /* VOWEL */ ++// USE_VM = 40, /* VOWEL_MOD */ ++ ++ USE_FAbv = 24, /* CONS_FINAL_ABOVE */ ++ USE_FBlw = 25, /* CONS_FINAL_BELOW */ ++ USE_FPst = 26, /* CONS_FINAL_POST */ ++ USE_MAbv = 27, /* CONS_MED_ABOVE */ ++ USE_MBlw = 28, /* CONS_MED_BELOW */ ++ USE_MPst = 29, /* CONS_MED_POST */ ++ USE_MPre = 30, /* CONS_MED_PRE */ ++ USE_CMAbv = 31, /* CONS_MOD_ABOVE */ ++ USE_CMBlw = 32, /* CONS_MOD_BELOW */ ++ USE_VAbv = 33, /* VOWEL_ABOVE / VOWEL_ABOVE_BELOW / VOWEL_ABOVE_BELOW_POST / VOWEL_ABOVE_POST */ ++ USE_VBlw = 34, /* VOWEL_BELOW / VOWEL_BELOW_POST */ ++ USE_VPst = 35, /* VOWEL_POST UIPC = Right */ ++ USE_VPre = 22, /* VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST */ ++ USE_VMAbv = 37, /* VOWEL_MOD_ABOVE */ ++ USE_VMBlw = 38, /* VOWEL_MOD_BELOW */ ++ USE_VMPst = 39, /* VOWEL_MOD_POST */ ++ USE_VMPre = 23, /* VOWEL_MOD_PRE */ ++ USE_SMAbv = 41, /* SYM_MOD_ABOVE */ ++ USE_SMBlw = 42 /* SYM_MOD_BELOW */ ++}; ++ ++HB_INTERNAL USE_TABLE_ELEMENT_TYPE ++hb_use_get_categories (hb_codepoint_t u); ++ ++#endif /* HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH */ +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-complex-use-table.cc gfx/harfbuzz/src/hb-ot-shape-complex-use-table.cc +--- gfx/harfbuzz/src_old/hb-ot-shape-complex-use-table.cc 1970-01-01 01:00:00.000000000 +0100 ++++ gfx/harfbuzz/src/hb-ot-shape-complex-use-table.cc 2016-06-05 23:50:10.313751710 +0200 +@@ -0,0 +1,696 @@ ++/* == Start of generated table == */ ++/* ++ * The following table is generated by running: ++ * ++ * ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt ++ * ++ * on files with these headers: ++ * ++ * # IndicSyllabicCategory-8.0.0.txt ++ * # Date: 2015-05-12, 10:00:00 GMT [RP, KW, LI] ++ * # IndicPositionalCategory-8.0.0.txt ++ * # Date: 2015-05-12, 10:00:00 GMT [RP, KW, LI] ++ * # Blocks-8.0.0.txt ++ * # Date: 2014-11-10, 23:04:00 GMT [KW] ++ * UnicodeData.txt does not have a header. ++ */ ++ ++#include "hb-ot-shape-complex-use-private.hh" ++ ++#define B USE_B /* BASE */ ++#define CGJ USE_CGJ /* CGJ */ ++#define FM USE_FM /* CONS_FINAL_MOD */ ++#define GB USE_GB /* BASE_OTHER */ ++#define H USE_H /* HALANT */ ++#define HN USE_HN /* HALANT_NUM */ ++#define IND USE_IND /* BASE_IND */ ++#define IV USE_IV /* BASE_VOWEL */ ++#define N USE_N /* BASE_NUM */ ++#define O USE_O /* OTHER */ ++#define R USE_R /* REPHA */ ++#define Rsv USE_Rsv /* Reserved */ ++#define S USE_S /* SYM */ ++#define SUB USE_SUB /* CONS_SUB */ ++#define VS USE_VS /* VARIATION_SELECTOR */ ++#define WJ USE_WJ /* Word_Joiner */ ++#define ZWJ USE_ZWJ /* ZWJ */ ++#define ZWNJ USE_ZWNJ /* ZWNJ */ ++#define CMBlw USE_CMBlw ++#define CMAbv USE_CMAbv ++#define FBlw USE_FBlw ++#define FPst USE_FPst ++#define FAbv USE_FAbv ++#define MPre USE_MPre ++#define MBlw USE_MBlw ++#define MPst USE_MPst ++#define MAbv USE_MAbv ++#define SMBlw USE_SMBlw ++#define SMAbv USE_SMAbv ++#define VPre USE_VPre ++#define VBlw USE_VBlw ++#define VPst USE_VPst ++#define VAbv USE_VAbv ++#define VMPre USE_VMPre ++#define VMBlw USE_VMBlw ++#define VMPst USE_VMPst ++#define VMAbv USE_VMAbv ++ ++static const USE_TABLE_ELEMENT_TYPE use_table[] = { ++ ++ ++#define use_offset_0x0028u 0 ++ ++ ++ /* Basic Latin */ ++ O, O, O, O, O, GB, O, O, ++ /* 0030 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, ++ ++#define use_offset_0x00a0u 24 ++ ++ ++ /* Latin-1 Supplement */ ++ ++ /* 00A0 */ GB, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ /* 00B0 */ O, O, FM, FM, O, O, O, O, O, O, O, O, O, O, O, O, ++ /* 00C0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ /* 00D0 */ O, O, O, O, O, O, O, GB, ++ ++#define use_offset_0x0900u 80 ++ ++ ++ /* Devanagari */ ++ ++ /* 0900 */ VMAbv, VMAbv, VMAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, ++ /* 0910 */ IV, IV, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, ++ /* 0920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 0930 */ B, B, B, B, B, B, B, B, B, B, VAbv, VPst, CMBlw, B, VPst, VPre, ++ /* 0940 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VPst, VPst, VPst, VPst, H, VPre, VPst, ++ /* 0950 */ O, VMAbv, VMBlw, O, O, VAbv, VBlw, VBlw, B, B, B, B, B, B, B, B, ++ /* 0960 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, ++ /* 0970 */ O, O, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, B, B, ++ ++ /* Bengali */ ++ ++ /* 0980 */ O, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, O, IV, ++ /* 0990 */ IV, O, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B, ++ /* 09A0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, ++ /* 09B0 */ B, O, B, O, O, O, B, B, B, B, O, O, CMBlw, B, VPst, VPre, ++ /* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, IND, O, ++ /* 09D0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, B, B, O, B, ++ /* 09E0 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, ++ /* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Gurmukhi */ ++ ++ /* 0A00 */ O, VMAbv, VMAbv, VMPst, O, IV, IV, IV, IV, IV, IV, O, O, O, O, IV, ++ /* 0A10 */ IV, O, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B, ++ /* 0A20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, ++ /* 0A30 */ B, O, B, B, O, B, B, O, B, B, O, O, CMBlw, O, VPst, VPre, ++ /* 0A40 */ VPst, VBlw, VBlw, O, O, O, O, VAbv, VAbv, O, O, VAbv, VAbv, H, O, O, ++ /* 0A50 */ O, O, O, O, O, O, O, O, O, B, B, B, B, O, B, O, ++ /* 0A60 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B, ++ /* 0A70 */ VMAbv, CMAbv, GB, GB, O, MBlw, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Gujarati */ ++ ++ /* 0A80 */ O, VMAbv, VMAbv, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, IV, O, IV, ++ /* 0A90 */ IV, IV, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B, ++ /* 0AA0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, ++ /* 0AB0 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VPre, ++ /* 0AC0 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, O, VAbv, VAbv, VAbv, O, VPst, VPst, H, O, O, ++ /* 0AD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ /* 0AE0 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, ++ /* 0AF0 */ O, O, O, O, O, O, O, O, O, B, O, O, O, O, O, O, ++ ++ /* Oriya */ ++ ++ /* 0B00 */ O, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, O, IV, ++ /* 0B10 */ IV, O, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B, ++ /* 0B20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, ++ /* 0B30 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VAbv, ++ /* 0B40 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O, ++ /* 0B50 */ O, O, O, O, O, O, VAbv, VAbv, O, O, O, O, B, B, O, B, ++ /* 0B60 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, ++ /* 0B70 */ O, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Tamil */ ++ ++ /* 0B80 */ O, O, VMAbv, IND, O, IV, IV, IV, IV, IV, IV, O, O, O, IV, IV, ++ /* 0B90 */ IV, O, IV, IV, IV, B, O, O, O, B, B, O, B, O, B, B, ++ /* 0BA0 */ O, O, O, B, B, O, O, O, B, B, B, O, O, O, B, B, ++ /* 0BB0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, VPst, VPst, ++ /* 0BC0 */ VAbv, VPst, VPst, O, O, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, O, O, ++ /* 0BD0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, O, ++ /* 0BE0 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B, ++ /* 0BF0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Telugu */ ++ ++ /* 0C00 */ VMAbv, VMPst, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, IV, IV, ++ /* 0C10 */ IV, O, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, ++ /* 0C20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, ++ /* 0C30 */ B, B, B, B, B, B, B, B, B, B, O, O, O, B, VAbv, VAbv, ++ /* 0C40 */ VAbv, VPst, VPst, VPst, VPst, O, VAbv, VAbv, VAbv, O, VAbv, VAbv, VAbv, H, O, O, ++ /* 0C50 */ O, O, O, O, O, VAbv, VBlw, O, B, B, B, O, O, O, O, O, ++ /* 0C60 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, ++ /* 0C70 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Kannada */ ++ ++ /* 0C80 */ O, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, IV, IV, ++ /* 0C90 */ IV, O, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, ++ /* 0CA0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, ++ /* 0CB0 */ B, B, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VAbv, ++ /* 0CC0 */ VAbv, VPst, VPst, VPst, VPst, O, VAbv, VAbv, VAbv, O, VAbv, VAbv, VAbv, H, O, O, ++ /* 0CD0 */ O, O, O, O, O, VPst, VPst, O, O, O, O, O, O, O, B, O, ++ /* 0CE0 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, ++ /* 0CF0 */ O, R, R, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Malayalam */ ++ ++ /* 0D00 */ O, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, IV, IV, ++ /* 0D10 */ IV, O, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, ++ /* 0D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 0D30 */ B, B, B, B, B, B, B, B, B, B, B, O, O, B, VPst, VPst, ++ /* 0D40 */ VPst, VPst, VPst, VBlw, VBlw, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, R, O, ++ /* 0D50 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, IV, ++ /* 0D60 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, ++ /* 0D70 */ O, O, O, O, O, O, O, O, O, O, IND, IND, IND, IND, IND, IND, ++ ++ /* Sinhala */ ++ ++ /* 0D80 */ O, O, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, ++ /* 0D90 */ IV, IV, IV, IV, IV, IV, IV, O, O, O, B, B, B, B, B, B, ++ /* 0DA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 0DB0 */ B, B, O, B, B, B, B, B, B, B, B, B, O, B, O, O, ++ /* 0DC0 */ B, B, B, B, B, B, B, O, O, O, H, O, O, O, O, VPst, ++ /* 0DD0 */ VPst, VPst, VAbv, VAbv, VBlw, O, VBlw, O, VPst, VPre, VPre, VPre, VPre, VPre, VPre, VPst, ++ /* 0DE0 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B, ++ /* 0DF0 */ O, O, VPst, VPst, O, O, O, O, ++ ++#define use_offset_0x1000u 1352 ++ ++ ++ /* Myanmar */ ++ ++ /* 1000 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1020 */ B, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, VPst, VPst, VAbv, VAbv, VBlw, ++ /* 1030 */ VBlw, VPre, VAbv, VAbv, VAbv, VAbv, VMAbv, VMBlw, VMPst, H, VAbv, MPst, MPre, MBlw, MBlw, B, ++ /* 1040 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, GB, O, ++ /* 1050 */ B, B, IV, IV, IV, IV, VPst, VPst, VBlw, VBlw, B, B, B, B, MBlw, MBlw, ++ /* 1060 */ MBlw, B, VPst, VMPst, VMPst, B, B, VPst, VPst, VMPst, VMPst, VMPst, VMPst, VMPst, B, B, ++ /* 1070 */ B, VAbv, VAbv, VAbv, VAbv, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1080 */ B, B, MBlw, VPst, VPre, VAbv, VAbv, VMPst, VMPst, VMPst, VMPst, VMPst, VMPst, VMBlw, B, VMPst, ++ /* 1090 */ B, B, B, B, B, B, B, B, B, B, VMPst, VMPst, VPst, VAbv, O, O, ++ ++#define use_offset_0x1700u 1512 ++ ++ ++ /* Tagalog */ ++ ++ /* 1700 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, O, B, B, ++ /* 1710 */ B, B, VAbv, VBlw, VBlw, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Hanunoo */ ++ ++ /* 1720 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1730 */ B, B, VAbv, VBlw, VBlw, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Buhid */ ++ ++ /* 1740 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1750 */ B, B, VAbv, VBlw, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Tagbanwa */ ++ ++ /* 1760 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, O, B, B, ++ /* 1770 */ B, O, VAbv, VBlw, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Khmer */ ++ ++ /* 1780 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1790 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 17A0 */ B, B, B, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, ++ /* 17B0 */ IV, IV, IV, IV, O, O, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VPre, VPre, ++ /* 17C0 */ VPre, VPre, VPre, VPre, VPre, VPre, VMAbv, VMPst, VPst, VMAbv, VMAbv, FM, FAbv, CMAbv, FM, FM, ++ /* 17D0 */ FM, VAbv, H, FM, O, O, O, O, O, O, O, O, B, VAbv, O, O, ++ /* 17E0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, ++ ++#define use_offset_0x1900u 1752 ++ ++ ++ /* Limbu */ ++ ++ /* 1900 */ GB, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, ++ /* 1920 */ VAbv, VAbv, VBlw, VPst, VPst, VAbv, VAbv, VAbv, VAbv, SUB, SUB, SUB, O, O, O, O, ++ /* 1930 */ FPst, FPst, VMBlw, FPst, FPst, FPst, FPst, FPst, FPst, FBlw, VAbv, FM, O, O, O, O, ++ /* 1940 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B, ++ ++ /* Tai Le */ ++ ++ /* 1950 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1960 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, ++ /* 1970 */ B, B, B, B, B, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* New Tai Lue */ ++ ++ /* 1980 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 19A0 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, ++ /* 19B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 19C0 */ B, B, B, B, B, B, B, B, VMPst, VMPst, O, O, O, O, O, O, ++ /* 19D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, ++ /* 19E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ /* 19F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Buginese */ ++ ++ /* 1A00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1A10 */ B, B, B, B, B, B, B, VAbv, VBlw, VPre, VPst, VAbv, O, O, O, O, ++ ++ /* Tai Tham */ ++ ++ /* 1A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1A30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1A40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, IV, IV, IV, ++ /* 1A50 */ IV, IV, IV, B, B, MPre, MBlw, FPst, FAbv, FAbv, FAbv, FBlw, FBlw, FBlw, FBlw, O, ++ /* 1A60 */ H, VPst, VAbv, VPst, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VAbv, VBlw, VPst, VPre, VPre, ++ /* 1A70 */ VPre, VPre, VPre, VAbv, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, FM, FM, FM, O, O, FM, ++ /* 1A80 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, ++ /* 1A90 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, ++ ++#define use_offset_0x1b00u 2168 ++ ++ ++ /* Balinese */ ++ ++ /* 1B00 */ VMAbv, VMAbv, VMAbv, FAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, ++ /* 1B10 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1B30 */ B, B, B, B, CMAbv, VPst, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VPre, ++ /* 1B40 */ VPre, VPre, VAbv, VAbv, H, B, B, B, B, B, B, B, O, O, O, O, ++ /* 1B50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, ++ /* 1B60 */ O, O, O, O, O, O, O, O, O, O, O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv, ++ /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Sundanese */ ++ ++ /* 1B80 */ VMAbv, FAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, ++ /* 1B90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1BA0 */ B, SUB, SUB, SUB, VAbv, VBlw, VPre, VPst, VAbv, VAbv, VPst, H, SUB, SUB, B, B, ++ /* 1BB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ ++ /* Batak */ ++ ++ /* 1BC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1BD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1BE0 */ B, B, B, B, IV, IV, CMAbv, VPst, VAbv, VAbv, VPst, VPst, VPst, VAbv, VPst, VAbv, ++ /* 1BF0 */ FAbv, FAbv, VPst, VPst, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Lepcha */ ++ ++ /* 1C00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 1C20 */ B, B, B, B, SUB, SUB, VPst, VPre, VPre, VPre, VPst, VPst, VBlw, FAbv, FAbv, FAbv, ++ /* 1C30 */ FAbv, FAbv, FAbv, FAbv, VMPre, VMPre, FM, CMBlw, O, O, O, O, O, O, O, O, ++ /* 1C40 */ B, B, B, B, B, B, B, B, B, B, O, O, O, B, B, B, ++ ++#define use_offset_0x1cd0u 2504 ++ ++ ++ /* Vedic Extensions */ ++ ++ /* 1CD0 */ VMAbv, VMAbv, VMAbv, O, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMAbv, VMAbv, VMBlw, VMBlw, VMBlw, VMBlw, ++ /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, O, O, O, O, VMBlw, O, O, ++ /* 1CF0 */ O, O, VMPst, VMPst, VMAbv, O, O, O, VMAbv, VMAbv, O, O, O, O, O, O, ++ ++#define use_offset_0x2008u 2552 ++ ++ ++ /* General Punctuation */ ++ O, O, O, O, ZWNJ, ZWJ, O, O, ++ /* 2010 */ GB, GB, GB, GB, GB, O, O, O, ++ ++#define use_offset_0x2060u 2568 ++ ++ /* 2060 */ WJ, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Superscripts and Subscripts */ ++ ++ /* 2070 */ O, O, O, O, FM, O, O, O, O, O, O, O, O, O, O, O, ++ /* 2080 */ O, O, FM, FM, FM, O, O, O, ++ ++#define use_offset_0xa800u 2608 ++ ++ ++ /* Syloti Nagri */ ++ ++ /* A800 */ IV, IV, O, IV, IV, IV, VAbv, B, B, B, B, VMAbv, B, B, B, B, ++ /* A810 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* A820 */ B, B, B, VPst, VPst, VBlw, VAbv, VPst, O, O, O, O, O, O, O, O, ++ /* A830 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Phags-pa */ ++ ++ /* A840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* A850 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* A860 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* A870 */ B, B, B, B, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Saurashtra */ ++ ++ /* A880 */ VMPst, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, ++ /* A890 */ IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* A8A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* A8B0 */ B, B, B, B, FPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, ++ /* A8C0 */ VPst, VPst, VPst, VPst, H, O, O, O, O, O, O, O, O, O, O, O, ++ /* A8D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, ++ ++ /* Devanagari Extended */ ++ ++ /* A8E0 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, ++ /* A8F0 */ VMAbv, VMAbv, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Kayah Li */ ++ ++ /* A900 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* A910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* A920 */ B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VAbv, VMBlw, VMBlw, VMBlw, O, O, ++ ++ /* Rejang */ ++ ++ /* A930 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* A940 */ B, B, B, B, B, B, B, VBlw, VBlw, VBlw, VAbv, VBlw, VBlw, VBlw, VBlw, FAbv, ++ /* A950 */ FAbv, FAbv, FPst, VPst, O, O, O, O, O, O, O, O, O, O, O, O, ++ /* A960 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ /* A970 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Javanese */ ++ ++ /* A980 */ VMAbv, VMAbv, FAbv, VMPst, IV, IV, IV, IV, IV, B, B, B, IV, IV, IV, B, ++ /* A990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* A9A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* A9B0 */ B, B, B, CMAbv, VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VPre, VAbv, SUB, MPst, MPst, ++ /* A9C0 */ H, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ /* A9D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, ++ ++ /* Myanmar Extended-B */ ++ ++ /* A9E0 */ B, B, B, B, B, VAbv, O, B, B, B, B, B, B, B, B, B, ++ /* A9F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, ++ ++ /* Cham */ ++ ++ /* AA00 */ IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, ++ /* AA10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* AA20 */ B, B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VAbv, VPre, ++ /* AA30 */ VPre, VAbv, VBlw, MPst, MPre, MBlw, MBlw, O, O, O, O, O, O, O, O, O, ++ /* AA40 */ B, B, B, FAbv, B, B, B, B, B, B, B, B, FAbv, FPst, O, O, ++ /* AA50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, ++ ++ /* Myanmar Extended-A */ ++ ++ /* AA60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* AA70 */ O, B, B, B, O, O, O, O, O, O, B, VMPst, VMAbv, VMPst, B, B, ++ ++ /* Tai Viet */ ++ ++ /* AA80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* AA90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* AAA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* AAB0 */ VAbv, B, VAbv, VAbv, VBlw, B, B, VAbv, VAbv, B, B, B, B, B, VAbv, VMAbv, ++ /* AAC0 */ B, VMAbv, B, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ /* AAD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Meetei Mayek Extensions */ ++ ++ /* AAE0 */ IV, IV, B, B, B, B, B, B, B, B, B, VPre, VBlw, VAbv, VPre, VPst, ++ /* AAF0 */ O, O, O, O, O, VMPst, H, O, ++ ++#define use_offset_0xabc0u 3368 ++ ++ ++ /* Meetei Mayek */ ++ ++ /* ABC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, IV, IV, ++ /* ABD0 */ B, IV, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* ABE0 */ B, B, B, VPst, VPst, VAbv, VPst, VPst, VBlw, VPst, VPst, O, VMPst, VBlw, O, O, ++ /* ABF0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, ++ ++#define use_offset_0xfe00u 3432 ++ ++ ++ /* Variation Selectors */ ++ ++ /* FE00 */ VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, ++ ++#define use_offset_0x10a00u 3448 ++ ++ ++ /* Kharoshthi */ ++ ++ /* 10A00 */ B, VBlw, VBlw, VBlw, O, VAbv, VBlw, O, O, O, O, O, VBlw, VBlw, VMBlw, VMAbv, ++ /* 10A10 */ B, B, B, B, O, B, B, B, O, 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, O, O, O, O, CMAbv, CMBlw, CMBlw, O, O, O, O, H, ++ /* 10A40 */ B, B, B, B, B, B, B, B, ++ ++#define use_offset_0x11000u 3520 ++ ++ ++ /* Brahmi */ ++ ++ /* 11000 */ VMPst, VMAbv, VMPst, R, R, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, ++ /* 11010 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 11020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 11030 */ B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, ++ /* 11040 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, O, O, O, O, O, O, O, O, O, ++ /* 11050 */ O, O, N, N, N, N, N, N, N, N, N, N, N, N, N, N, ++ /* 11060 */ N, N, N, N, N, N, B, B, B, B, B, B, B, B, B, B, ++ /* 11070 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Kaithi */ ++ ++ /* 11080 */ VMAbv, VMAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B, B, ++ /* 11090 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 110A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 110B0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VPst, VPst, H, CMBlw, O, O, O, O, O, ++ ++#define use_offset_0x11100u 3712 ++ ++ ++ /* Chakma */ ++ ++ /* 11100 */ VMAbv, VMAbv, VMAbv, IV, IV, IV, IV, B, B, B, B, B, B, B, B, B, ++ /* 11110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 11120 */ B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VAbv, VAbv, ++ /* 11130 */ VAbv, VBlw, VBlw, H, VAbv, O, B, B, B, B, B, B, B, B, B, B, ++ /* 11140 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Mahajani */ ++ ++ /* 11150 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 11160 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 11170 */ B, B, B, CMBlw, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Sharada */ ++ ++ /* 11180 */ VMAbv, VMAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, ++ /* 11190 */ IV, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 111A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 111B0 */ B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, ++ /* 111C0 */ H, B, R, R, O, O, O, O, O, O, CMBlw, VAbv, VBlw, O, O, O, ++ /* 111D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, ++ ++ /* Sinhala Archaic Numbers */ ++ ++ /* 111E0 */ O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 111F0 */ B, B, B, B, B, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Khojki */ ++ ++ /* 11200 */ IV, IV, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, B, B, ++ /* 11210 */ B, B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 11220 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VBlw, ++ /* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv, ++ ++#define use_offset_0x11280u 4024 ++ ++ ++ /* Multani */ ++ ++ /* 11280 */ IV, IV, IV, IV, B, B, B, O, B, O, B, B, B, B, O, B, ++ /* 11290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, B, ++ /* 112A0 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O, ++ ++ /* Khudawadi */ ++ ++ /* 112B0 */ IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, ++ /* 112C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 112D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, ++ /* 112E0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, CMBlw, VBlw, O, O, O, O, O, ++ /* 112F0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, ++ ++ /* Grantha */ ++ ++ /* 11300 */ VMAbv, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, O, IV, ++ /* 11310 */ IV, O, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B, ++ /* 11320 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, ++ /* 11330 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VPst, ++ /* 11340 */ VAbv, VPst, VPst, VPst, VPst, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O, ++ /* 11350 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, O, ++ /* 11360 */ IV, IV, VPst, VPst, O, O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, ++ /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, ++ ++#define use_offset_0x11480u 4272 ++ ++ ++ /* Tirhuta */ ++ ++ /* 11480 */ O, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, ++ /* 11490 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 114A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 114B0 */ VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VPre, VAbv, VPre, VPre, VPst, VPre, VMAbv, ++ /* 114C0 */ VMAbv, VMPst, H, CMBlw, B, O, O, O, O, O, O, O, O, O, O, O, ++ /* 114D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, ++ ++#define use_offset_0x11580u 4368 ++ ++ ++ /* Siddham */ ++ ++ /* 11580 */ IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B, ++ /* 11590 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 115A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst, ++ /* 115B0 */ VPre, VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, VPre, VPre, VMAbv, VMAbv, VMPst, H, ++ /* 115C0 */ CMBlw, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ /* 115D0 */ O, O, O, O, O, O, O, O, IV, IV, IV, IV, VBlw, VBlw, O, O, ++ /* 115E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ /* 115F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Modi */ ++ ++ /* 11600 */ IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B, ++ /* 11610 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 11620 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 11630 */ VPst, VPst, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPst, VPst, VMAbv, VMPst, H, ++ /* 11640 */ VAbv, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ /* 11650 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, ++ /* 11660 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ /* 11670 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Takri */ ++ ++ /* 11680 */ IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, ++ /* 11690 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 116A0 */ B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMPst, VAbv, VPre, VPst, ++ /* 116B0 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, CMBlw, O, O, O, O, O, O, O, O, ++ /* 116C0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, ++ /* 116D0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ /* 116E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ /* 116F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, ++ ++ /* Ahom */ ++ ++ /* 11700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, ++ /* 11710 */ B, B, B, B, B, B, B, B, B, B, O, O, O, MBlw, MPre, MAbv, ++ /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, O, O, O, O, ++ /* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, ++ ++}; /* Table items: 4816; occupancy: 72% */ ++ ++USE_TABLE_ELEMENT_TYPE ++hb_use_get_categories (hb_codepoint_t u) ++{ ++ switch (u >> 12) ++ { ++ case 0x0u: ++ if (hb_in_range (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u]; ++ if (hb_in_range (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u]; ++ if (hb_in_range (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u]; ++ if (unlikely (u == 0x034Fu)) return CGJ; ++ break; ++ ++ case 0x1u: ++ if (hb_in_range (u, 0x1000u, 0x109Fu)) return use_table[u - 0x1000u + use_offset_0x1000u]; ++ if (hb_in_range (u, 0x1700u, 0x17EFu)) return use_table[u - 0x1700u + use_offset_0x1700u]; ++ if (hb_in_range (u, 0x1900u, 0x1A9Fu)) return use_table[u - 0x1900u + use_offset_0x1900u]; ++ if (hb_in_range (u, 0x1B00u, 0x1C4Fu)) return use_table[u - 0x1B00u + use_offset_0x1b00u]; ++ if (hb_in_range (u, 0x1CD0u, 0x1CFFu)) return use_table[u - 0x1CD0u + use_offset_0x1cd0u]; ++ break; ++ ++ case 0x2u: ++ if (hb_in_range (u, 0x2008u, 0x2017u)) return use_table[u - 0x2008u + use_offset_0x2008u]; ++ if (hb_in_range (u, 0x2060u, 0x2087u)) return use_table[u - 0x2060u + use_offset_0x2060u]; ++ if (unlikely (u == 0x25CCu)) return GB; ++ break; ++ ++ case 0xAu: ++ if (hb_in_range (u, 0xA800u, 0xAAF7u)) return use_table[u - 0xA800u + use_offset_0xa800u]; ++ if (hb_in_range (u, 0xABC0u, 0xABFFu)) return use_table[u - 0xABC0u + use_offset_0xabc0u]; ++ break; ++ ++ case 0xFu: ++ if (hb_in_range (u, 0xFE00u, 0xFE0Fu)) return use_table[u - 0xFE00u + use_offset_0xfe00u]; ++ break; ++ ++ case 0x10u: ++ if (hb_in_range (u, 0x10A00u, 0x10A47u)) return use_table[u - 0x10A00u + use_offset_0x10a00u]; ++ break; ++ ++ case 0x11u: ++ if (hb_in_range (u, 0x11000u, 0x110BFu)) return use_table[u - 0x11000u + use_offset_0x11000u]; ++ if (hb_in_range (u, 0x11100u, 0x11237u)) return use_table[u - 0x11100u + use_offset_0x11100u]; ++ if (hb_in_range (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u]; ++ if (hb_in_range (u, 0x11480u, 0x114DFu)) return use_table[u - 0x11480u + use_offset_0x11480u]; ++ if (hb_in_range (u, 0x11580u, 0x1173Fu)) return use_table[u - 0x11580u + use_offset_0x11580u]; ++ if (unlikely (u == 0x1107Fu)) return HN; ++ break; ++ ++ default: ++ break; ++ } ++ return USE_O; ++} ++ ++#undef B ++#undef CGJ ++#undef FM ++#undef GB ++#undef H ++#undef HN ++#undef IND ++#undef IV ++#undef N ++#undef O ++#undef R ++#undef Rsv ++#undef S ++#undef SUB ++#undef VS ++#undef WJ ++#undef ZWJ ++#undef ZWNJ ++#undef CMBlw ++#undef CMAbv ++#undef FBlw ++#undef FPst ++#undef FAbv ++#undef MPre ++#undef MBlw ++#undef MPst ++#undef MAbv ++#undef SMBlw ++#undef SMAbv ++#undef VPre ++#undef VBlw ++#undef VPst ++#undef VAbv ++#undef VMPre ++#undef VMBlw ++#undef VMPst ++#undef VMAbv ++ ++/* == End of generated table == */ +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-fallback.cc gfx/harfbuzz/src/hb-ot-shape-fallback.cc +--- gfx/harfbuzz/src_old/hb-ot-shape-fallback.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-fallback.cc 2016-06-05 23:50:14.550729671 +0200 +@@ -224,7 +224,7 @@ + pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width / 2 - mark_extents.x_bearing; + break; + } +- /* Fall through */ ++ HB_FALLTHROUGH; + + default: + case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW: +@@ -259,6 +259,7 @@ + case HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT: + /* Add gap, fall-through. */ + base_extents.height -= y_gap; ++ HB_FALLTHROUGH; + + case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT: + case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW: +@@ -279,6 +280,7 @@ + /* Add gap, fall-through. */ + base_extents.y_bearing += y_gap; + base_extents.height -= y_gap; ++ HB_FALLTHROUGH; + + case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE: + case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT: +@@ -418,13 +420,12 @@ + _hb_buffer_assert_gsubgpos_vars (buffer); + + unsigned int start = 0; +- unsigned int last_cluster = buffer->info[0].cluster; + unsigned int count = buffer->len; ++ hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 1; i < count; i++) +- if (buffer->info[i].cluster != last_cluster) { ++ if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))) { + position_cluster (plan, font, buffer, start, i); + start = i; +- last_cluster = buffer->info[i].cluster; + } + position_cluster (plan, font, buffer, start, count); + } +@@ -441,13 +442,15 @@ + OT::hb_apply_context_t c (1, font, buffer); + c.set_lookup_mask (plan->kern_mask); + c.set_lookup_props (OT::LookupFlag::IgnoreMarks); ++ OT::hb_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input; ++ skippy_iter.init (&c); + + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + hb_glyph_position_t *pos = buffer->pos; + for (unsigned int idx = 0; idx < count;) + { +- OT::hb_apply_context_t::skipping_forward_iterator_t skippy_iter (&c, idx, 1); ++ skippy_iter.reset (idx, 1); + if (!skippy_iter.next ()) + { + idx++; +@@ -481,3 +484,70 @@ + idx = skippy_iter.idx; + } + } ++ ++ ++/* Adjusts width of various spaces. */ ++void ++_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan, ++ hb_font_t *font, ++ hb_buffer_t *buffer) ++{ ++ if (!HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) ++ return; ++ ++ hb_glyph_info_t *info = buffer->info; ++ hb_glyph_position_t *pos = buffer->pos; ++ unsigned int count = buffer->len; ++ for (unsigned int i = 0; i < count; i++) ++ if (_hb_glyph_info_is_unicode_space (&info[i]) && !_hb_glyph_info_ligated (&info[i])) ++ { ++ hb_unicode_funcs_t::space_t space_type = _hb_glyph_info_get_unicode_space_fallback_type (&info[i]); ++ hb_codepoint_t glyph; ++ typedef hb_unicode_funcs_t t; ++ switch (space_type) ++ { ++ case t::NOT_SPACE: /* Shouldn't happen. */ ++ case t::SPACE: ++ break; ++ ++ case t::SPACE_EM: ++ case t::SPACE_EM_2: ++ case t::SPACE_EM_3: ++ case t::SPACE_EM_4: ++ case t::SPACE_EM_5: ++ case t::SPACE_EM_6: ++ case t::SPACE_EM_16: ++ pos[i].x_advance = (font->x_scale + ((int) space_type)/2) / (int) space_type; ++ break; ++ ++ case t::SPACE_4_EM_18: ++ pos[i].x_advance = font->x_scale * 4 / 18; ++ break; ++ ++ case t::SPACE_FIGURE: ++ for (char u = '0'; u <= '9'; u++) ++ if (font->get_glyph (u, 0, &glyph)) ++ { ++ pos[i].x_advance = font->get_glyph_h_advance (glyph); ++ break; ++ } ++ break; ++ ++ case t::SPACE_PUNCTUATION: ++ if (font->get_glyph ('.', 0, &glyph)) ++ pos[i].x_advance = font->get_glyph_h_advance (glyph); ++ else if (font->get_glyph (',', 0, &glyph)) ++ pos[i].x_advance = font->get_glyph_h_advance (glyph); ++ break; ++ ++ case t::SPACE_NARROW: ++ /* Half-space? ++ * Unicode doc http://www.unicode.org/charts/PDF/U2000.pdf says ~1/4 or 1/5 of EM. ++ * However, in my testing, many fonts have their regular space being about that ++ * size. To me, a percentage of the space width makes more sense. Half is as ++ * good as any. */ ++ pos[i].x_advance /= 2; ++ break; ++ } ++ } ++} +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-fallback-private.hh gfx/harfbuzz/src/hb-ot-shape-fallback-private.hh +--- gfx/harfbuzz/src_old/hb-ot-shape-fallback-private.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-fallback-private.hh 2016-06-05 23:50:13.114737132 +0200 +@@ -45,5 +45,9 @@ + hb_font_t *font, + hb_buffer_t *buffer); + ++HB_INTERNAL void _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan, ++ hb_font_t *font, ++ hb_buffer_t *buffer); ++ + + #endif /* HB_OT_SHAPE_FALLBACK_PRIVATE_HH */ +diff -uN gfx/harfbuzz/src_old/hb-ot-shape.h gfx/harfbuzz/src/hb-ot-shape.h +--- gfx/harfbuzz/src_old/hb-ot-shape.h 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape.h 2016-06-05 23:50:20.781697361 +0200 +@@ -36,14 +36,14 @@ + HB_BEGIN_DECLS + + /* TODO port to shape-plan / set. */ +-void ++HB_EXTERN void + hb_ot_shape_glyphs_closure (hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features, + hb_set_t *glyphs); + +-void ++HB_EXTERN void + hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan, + hb_tag_t table_tag, + hb_set_t *lookup_indexes /* OUT */); +diff -uN gfx/harfbuzz/src_old/hb-ot-shape-normalize.cc gfx/harfbuzz/src/hb-ot-shape-normalize.cc +--- gfx/harfbuzz/src_old/hb-ot-shape-normalize.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-shape-normalize.cc 2016-06-05 23:50:16.988717013 +0200 +@@ -62,24 +62,12 @@ + * with previous base, use that. This needs the itemizer to have this + * knowledge too. We need to provide assistance to the itemizer. + * +- * - When a font does not support a character but supports its decomposition, +- * well, use the decomposition (preferring the canonical decomposition, but +- * falling back to the compatibility decomposition if necessary). The +- * compatibility decomposition is really nice to have, for characters like +- * ellipsis, or various-sized space characters. ++ * - When a font does not support a character but supports its canonical ++ * decomposition, well, use the decomposition. + * + * - The complex shapers can customize the compose and decompose functions to + * offload some of their requirements to the normalizer. For example, the + * Indic shaper may want to disallow recomposing of two matras. +- * +- * - We try compatibility decomposition if decomposing through canonical +- * decomposition alone failed to find a sequence that the font supports. +- * We don't try compatibility decomposition recursively during the canonical +- * decomposition phase. This has minimal impact. There are only a handful +- * of Greek letter that have canonical decompositions that include characters +- * with compatibility decomposition. Those can be found using this command: +- * +- * egrep "`echo -n ';('; grep ';<' UnicodeData.txt | cut -d';' -f1 | tr '\n' '|'; echo ') '`" UnicodeData.txt + */ + + static bool +@@ -88,7 +76,7 @@ + hb_codepoint_t *a, + hb_codepoint_t *b) + { +- return c->unicode->decompose (ab, a, b); ++ return (bool) c->unicode->decompose (ab, a, b); + } + + static bool +@@ -97,7 +85,7 @@ + hb_codepoint_t b, + hb_codepoint_t *ab) + { +- return c->unicode->compose (a, b, ab); ++ return (bool) c->unicode->compose (a, b, ab); + } + + static inline void +@@ -110,8 +98,8 @@ + output_char (hb_buffer_t *buffer, hb_codepoint_t unichar, hb_codepoint_t glyph) + { + buffer->cur().glyph_index() = glyph; +- buffer->output_glyph (unichar); +- _hb_glyph_info_set_unicode_props (&buffer->prev(), buffer->unicode); ++ buffer->output_glyph (unichar); /* This is very confusing indeed. */ ++ _hb_glyph_info_set_unicode_props (&buffer->prev(), buffer); + } + + static inline void +@@ -139,7 +127,7 @@ + (b && !font->get_glyph (b, 0, &b_glyph))) + return 0; + +- bool has_a = font->get_glyph (a, 0, &a_glyph); ++ bool has_a = (bool) font->get_glyph (a, 0, &a_glyph); + if (shortest && has_a) { + /* Output a and b */ + output_char (buffer, a, a_glyph); +@@ -171,45 +159,57 @@ + return 0; + } + +-/* Returns 0 if didn't decompose, number of resulting characters otherwise. */ +-static inline unsigned int +-decompose_compatibility (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t u) +-{ +- unsigned int len, i; +- hb_codepoint_t decomposed[HB_UNICODE_MAX_DECOMPOSITION_LEN]; +- hb_codepoint_t glyphs[HB_UNICODE_MAX_DECOMPOSITION_LEN]; +- +- len = c->buffer->unicode->decompose_compatibility (u, decomposed); +- if (!len) +- return 0; +- +- for (i = 0; i < len; i++) +- if (!c->font->get_glyph (decomposed[i], 0, &glyphs[i])) +- return 0; +- +- for (i = 0; i < len; i++) +- output_char (c->buffer, decomposed[i], glyphs[i]); +- +- return len; +-} +- + static inline void + decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shortest) + { + hb_buffer_t * const buffer = c->buffer; ++ hb_codepoint_t u = buffer->cur().codepoint; + hb_codepoint_t glyph; + +- /* Kind of a cute waterfall here... */ +- if (shortest && c->font->get_glyph (buffer->cur().codepoint, 0, &glyph)) ++ if (shortest && c->font->get_glyph (u, 0, &glyph)) ++ { + next_char (buffer, glyph); +- else if (decompose (c, shortest, buffer->cur().codepoint)) ++ return; ++ } ++ ++ if (decompose (c, shortest, u)) ++ { + skip_char (buffer); +- else if (!shortest && c->font->get_glyph (buffer->cur().codepoint, 0, &glyph)) ++ return; ++ } ++ ++ if (!shortest && c->font->get_glyph (u, 0, &glyph)) ++ { + next_char (buffer, glyph); +- else if (decompose_compatibility (c, buffer->cur().codepoint)) +- skip_char (buffer); +- else +- next_char (buffer, glyph); /* glyph is initialized in earlier branches. */ ++ return; ++ } ++ ++ if (_hb_glyph_info_is_unicode_space (&buffer->cur())) ++ { ++ hb_codepoint_t space_glyph; ++ hb_unicode_funcs_t::space_t space_type = buffer->unicode->space_fallback_type (u); ++ if (space_type != hb_unicode_funcs_t::NOT_SPACE && c->font->get_glyph (0x0020u, 0, &space_glyph)) ++ { ++ _hb_glyph_info_set_unicode_space_fallback_type (&buffer->cur(), space_type); ++ next_char (buffer, space_glyph); ++ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK; ++ return; ++ } ++ } ++ ++ if (u == 0x2011u) ++ { ++ /* U+2011 is the only sensible character that is a no-break version of another character ++ * and not a space. The space ones are handled already. Handle this lone one. */ ++ hb_codepoint_t other_glyph; ++ if (c->font->get_glyph (0x2010u, 0, &other_glyph)) ++ { ++ next_char (buffer, other_glyph); ++ return; ++ } ++ } ++ ++ next_char (buffer, glyph); /* glyph is initialized in earlier branches. */ + } + + static inline void +@@ -218,7 +218,7 @@ + /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */ + hb_buffer_t * const buffer = c->buffer; + hb_font_t * const font = c->font; +- for (; buffer->idx < end - 1;) { ++ for (; buffer->idx < end - 1 && !buffer->in_error;) { + if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) { + /* The next two lines are some ugly lines... But work. */ + if (font->get_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index())) +@@ -254,13 +254,13 @@ + decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit) + { + hb_buffer_t * const buffer = c->buffer; +- for (unsigned int i = buffer->idx; i < end; i++) ++ for (unsigned int i = buffer->idx; i < end && !buffer->in_error; i++) + if (unlikely (buffer->unicode->is_variation_selector (buffer->info[i].codepoint))) { + handle_variation_selector_cluster (c, end, short_circuit); + return; + } + +- while (buffer->idx < end) ++ while (buffer->idx < end && !buffer->in_error) + decompose_current_character (c, short_circuit); + } + +@@ -289,6 +289,8 @@ + hb_buffer_t *buffer, + hb_font_t *font) + { ++ if (unlikely (!buffer->len)) return; ++ + _hb_buffer_assert_unicode_vars (buffer); + + hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference; +@@ -318,11 +320,11 @@ + + buffer->clear_output (); + count = buffer->len; +- for (buffer->idx = 0; buffer->idx < count;) ++ for (buffer->idx = 0; buffer->idx < count && !buffer->in_error;) + { + unsigned int end; + for (end = buffer->idx + 1; end < count; end++) +- if (buffer->cur().cluster != buffer->info[end].cluster) ++ if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end])))) + break; + + decompose_cluster (&c, end, might_short_circuit, always_short_circuit); +@@ -343,15 +345,13 @@ + if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0) + break; + +- /* We are going to do a bubble-sort. Only do this if the +- * sequence is short. Doing it on long sequences can result +- * in an O(n^2) DoS. */ ++ /* We are going to do a O(n^2). Only do this if the sequence is short. */ + if (end - i > 10) { + i = end; + continue; + } + +- hb_bubble_sort (buffer->info + i, end - i, compare_combining_class); ++ buffer->sort (i, end, compare_combining_class); + + i = end; + } +@@ -370,7 +370,7 @@ + count = buffer->len; + unsigned int starter = 0; + buffer->next_glyph (); +- while (buffer->idx < count) ++ while (buffer->idx < count && !buffer->in_error) + { + hb_codepoint_t composed, glyph; + if (/* We don't try to compose a non-mark character with it's preceding starter. +@@ -399,7 +399,7 @@ + /* Modify starter and carry on. */ + buffer->out_info[starter].codepoint = composed; + buffer->out_info[starter].glyph_index() = glyph; +- _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer->unicode); ++ _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer); + + continue; + } +diff -uN gfx/harfbuzz/src_old/hb-ot-tag.cc gfx/harfbuzz/src/hb-ot-tag.cc +--- gfx/harfbuzz/src_old/hb-ot-tag.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-tag.cc 2016-06-05 23:50:22.342689280 +0200 +@@ -175,6 +175,11 @@ + * + * Some items still missing. Those are commented out at the end. + * Keep sorted for bsearch. ++ * ++ * Updated as of 2015-05-06: OT1.7 on MS website has some newer ++ * items that we don't have here, eg. Zazaki. This is the new ++ * items in OpenType 1.7 (red items), most of which we have: ++ * http://www.microsoft.com/typography/otspec170/languagetags.htm + */ + + static const LangTag ot_languages[] = { +@@ -217,9 +222,9 @@ + {"bci", HB_TAG('B','A','U',' ')}, /* Baoulé */ + {"bcl", HB_TAG('B','I','K',' ')}, /* Central Bikol */ + {"bcq", HB_TAG('B','C','H',' ')}, /* Bench */ +- {"be", HB_TAG('B','E','L',' ')}, /* Belarusian */ ++ {"be", HB_TAG('B','E','L',' ')}, /* Belarusian */ + {"bem", HB_TAG('B','E','M',' ')}, /* Bemba (Zambia) */ +- {"ber", HB_TAG('B','E','R',' ')}, /* Berber [family] */ ++ {"ber", HB_TAG('B','E','R',' ')}, /* Berber [family] */ + {"bfq", HB_TAG('B','A','D',' ')}, /* Badaga */ + {"bft", HB_TAG('B','L','T',' ')}, /* Balti */ + {"bfy", HB_TAG('B','A','G',' ')}, /* Baghelkhandi */ +@@ -346,11 +351,10 @@ + {"gv", HB_TAG('M','N','X',' ')}, /* Manx */ + {"ha", HB_TAG('H','A','U',' ')}, /* Hausa */ + {"har", HB_TAG('H','R','I',' ')}, /* Harari */ +- {"haw", HB_TAG('H','A','W',' ')}, /* Hawaiian */ +- {"hay", HB_TAG('H','A','Y',' ')}, /* Haya */ +- {"haz", HB_TAG('H','A','Z',' ')}, /* Hazaragi */ ++ {"haw", HB_TAG('H','A','W',' ')}, /* Hawaiian */ ++ {"hay", HB_TAG('H','A','Y',' ')}, /* Haya */ ++ {"haz", HB_TAG('H','A','Z',' ')}, /* Hazaragi */ + {"he", HB_TAG('I','W','R',' ')}, /* Hebrew */ +- {"hz", HB_TAG('H','E','R',' ')}, /* Herero */ + {"hi", HB_TAG('H','I','N',' ')}, /* Hindi */ + {"hil", HB_TAG('H','I','L',' ')}, /* Hiligaynon */ + {"hnd", HB_TAG('H','N','D',' ')}, /* [Southern] Hindko */ +@@ -542,6 +546,7 @@ + {"nr", HB_TAG('N','D','B',' ')}, /* [South] Ndebele */ + {"nsk", HB_TAG('N','A','S',' ')}, /* Naskapi */ + {"nso", HB_TAG('S','O','T',' ')}, /* [Northern] Sotho */ ++ {"nv", HB_TAG('N','A','V',' ')}, /* Navajo */ + {"ny", HB_TAG('C','H','I',' ')}, /* Chewa/Chichwa/Nyanja */ + {"nym", HB_TAG('N','Y','M',' ')}, /* Nyamwezi */ + {"nyn", HB_TAG('N','K','L',' ')}, /* Nyankole */ +@@ -595,8 +600,8 @@ + {"sah", HB_TAG('Y','A','K',' ')}, /* Yakut */ + {"sas", HB_TAG('S','A','S',' ')}, /* Sasak */ + {"sat", HB_TAG('S','A','T',' ')}, /* Santali */ +- {"sck", HB_TAG('S','A','D',' ')}, /* Sadri */ + {"sc", HB_TAG('S','R','D',' ')}, /* Sardinian [macrolanguage] */ ++ {"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','L','A',' ')}, /* [North] Slavey */ +@@ -684,8 +689,8 @@ + {"uzs", HB_TAG('U','Z','B',' ')}, /* Southern Uzbek */ + {"ve", HB_TAG('V','E','N',' ')}, /* Venda */ + {"vec", HB_TAG('V','E','C',' ')}, /* Venetian */ +- {"vls", HB_TAG('F','L','E',' ')}, /* Vlaams */ + {"vi", HB_TAG('V','I','T',' ')}, /* Vietnamese */ ++ {"vls", HB_TAG('F','L','E',' ')}, /* Vlaams */ + {"vmw", HB_TAG('M','A','K',' ')}, /* Makhuwa */ + {"vo", HB_TAG('V','O','L',' ')}, /* Volapük */ + {"vro", HB_TAG('V','R','O',' ')}, /* Võro */ +@@ -694,9 +699,9 @@ + {"wbm", HB_TAG('W','A',' ',' ')}, /* Wa */ + {"wbr", HB_TAG('W','A','G',' ')}, /* Wagdi */ + {"wle", HB_TAG('S','I','G',' ')}, /* Wolane */ ++ {"wo", HB_TAG('W','L','F',' ')}, /* Wolof */ + {"wry", HB_TAG('M','A','W',' ')}, /* Merwari */ + {"wtm", HB_TAG('W','T','M',' ')}, /* Mewati */ +- {"wo", HB_TAG('W','L','F',' ')}, /* Wolof */ + {"xal", HB_TAG('K','L','M',' ')}, /* Kalmyk */ + {"xh", HB_TAG('X','H','S',' ')}, /* Xhosa */ + {"xog", HB_TAG('X','O','G',' ')}, /* Soga */ +@@ -727,7 +732,6 @@ + /*{"fuf?", HB_TAG('F','T','A',' ')},*/ /* Futa */ + /*{"ar-Syrc?", HB_TAG('G','A','R',' ')},*/ /* Garshuni */ + /*{"cfm/rnl?", HB_TAG('H','A','L',' ')},*/ /* Halam */ +-/*{"fonipa", HB_TAG('I','P','P','H')},*/ /* Phonetic transcription—IPA conventions */ + /*{"ga-Latg?/Latg?", HB_TAG('I','R','T',' ')},*/ /* Irish Traditional */ + /*{"krc", HB_TAG('K','A','R',' ')},*/ /* Karachay */ + /*{"alw?/ktb?", HB_TAG('K','E','B',' ')},*/ /* Kebena */ +@@ -826,6 +830,14 @@ + } + } + ++ /* ++ * The International Phonetic Alphabet is a variant tag in BCP-47, ++ * which can be applied to any language. ++ */ ++ if (strstr (lang_str, "-fonipa")) { ++ return HB_TAG('I','P','P','H'); /* Phonetic transcription—IPA conventions */ ++ } ++ + /* Find a language matching in the first component */ + { + const LangTag *lang_tag; +@@ -864,6 +876,15 @@ + return HB_OT_TAG_DEFAULT_LANGUAGE; + } + ++/** ++ * hb_ot_tag_to_language: ++ * ++ * ++ * ++ * Return value: (transfer none): ++ * ++ * Since: 0.9.2 ++ **/ + hb_language_t + hb_ot_tag_to_language (hb_tag_t tag) + { +@@ -886,6 +907,12 @@ + } + } + ++ /* struct LangTag has only room for 3-letter language tags. */ ++ switch (tag) { ++ case HB_TAG('I','P','P','H'): /* Phonetic transcription—IPA conventions */ ++ return hb_language_from_string ("und-fonipa", -1); ++ } ++ + /* Else return a custom language in the form of "x-hbotABCD" */ + { + unsigned char buf[11] = "x-hbot"; +@@ -900,4 +927,27 @@ + } + } + ++static inline void ++test_langs_sorted (void) ++{ ++ for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages); i++) ++ { ++ int c = lang_compare_first_component (ot_languages[i-1].language, ot_languages[i].language); ++ 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); ++ abort(); ++ } ++ } ++} ++ ++#ifdef MAIN ++int ++main (void) ++{ ++ test_langs_sorted (); ++ return 0; ++} + ++#endif +diff -uN gfx/harfbuzz/src_old/hb-ot-tag.h gfx/harfbuzz/src/hb-ot-tag.h +--- gfx/harfbuzz/src_old/hb-ot-tag.h 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ot-tag.h 2016-06-05 23:50:23.562682979 +0200 +@@ -39,18 +39,18 @@ + #define HB_OT_TAG_DEFAULT_SCRIPT HB_TAG ('D', 'F', 'L', 'T') + #define HB_OT_TAG_DEFAULT_LANGUAGE HB_TAG ('d', 'f', 'l', 't') + +-void ++HB_EXTERN void + hb_ot_tags_from_script (hb_script_t script, + hb_tag_t *script_tag_1, + hb_tag_t *script_tag_2); + +-hb_script_t ++HB_EXTERN hb_script_t + hb_ot_tag_to_script (hb_tag_t tag); + +-hb_tag_t ++HB_EXTERN hb_tag_t + hb_ot_tag_from_language (hb_language_t language); + +-hb_language_t ++HB_EXTERN hb_language_t + hb_ot_tag_to_language (hb_tag_t tag); + + +diff -uN gfx/harfbuzz/src_old/hb-private.hh gfx/harfbuzz/src/hb-private.hh +--- gfx/harfbuzz/src_old/hb-private.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-private.hh 2016-06-05 23:50:26.191669403 +0200 +@@ -54,6 +54,23 @@ + #include <stdarg.h> + + ++/* Compile-time custom allocator support. */ ++ ++#if defined(hb_malloc_impl) \ ++ && defined(hb_calloc_impl) \ ++ && defined(hb_realloc_impl) \ ++ && defined(hb_free_impl) ++extern "C" void* hb_malloc_impl(size_t size); ++extern "C" void* hb_calloc_impl(size_t nmemb, size_t size); ++extern "C" void* hb_realloc_impl(void *ptr, size_t size); ++extern "C" void hb_free_impl(void *ptr); ++#define malloc hb_malloc_impl ++#define calloc hb_calloc_impl ++#define realloc hb_realloc_impl ++#define free hb_free_impl ++#endif ++ ++ + /* Compiler attributes */ + + +@@ -94,22 +111,6 @@ + # endif + #endif + +-#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER) +-#define snprintf _snprintf +-/* Windows CE only has _strdup, while rest of Windows has both. */ +-#define strdup _strdup +-#endif +- +-#ifdef _MSC_VER +-#undef inline +-#define inline __inline +-#endif +- +-#ifdef __STRICT_ANSI__ +-#undef inline +-#define inline __inline__ +-#endif +- + #if __GNUC__ >= 3 + #define HB_FUNC __PRETTY_FUNCTION__ + #elif defined(_MSC_VER) +@@ -118,6 +119,36 @@ + #define HB_FUNC __func__ + #endif + ++/* ++ * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411 ++ * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch ++ * cases that fall through without a break or return statement. HB_FALLTHROUGH ++ * is only needed on cases that have code: ++ * ++ * switch (foo) { ++ * case 1: // These cases have no code. No fallthrough annotations are needed. ++ * case 2: ++ * case 3: ++ * foo = 4; // This case has code, so a fallthrough annotation is needed: ++ * HB_FALLTHROUGH; ++ * default: ++ * return foo; ++ * } ++ */ ++#if defined(__clang__) && __cplusplus >= 201103L ++ /* clang's fallthrough annotations are only available starting in C++11. */ ++# define HB_FALLTHROUGH [[clang::fallthrough]] ++#elif defined(_MSC_VER) ++ /* ++ * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis): ++ * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx ++ */ ++# include <sal.h> ++# define HB_FALLTHROUGH __fallthrough ++#else ++# define HB_FALLTHROUGH /* FALLTHROUGH */ ++#endif ++ + #if defined(_WIN32) || defined(__CYGWIN__) + /* We need Windows Vista for both Uniscribe backend and for + * MemoryBarrier. We don't support compiling on Windows XP, +@@ -134,14 +165,24 @@ + # ifndef STRICT + # define STRICT 1 + # endif +-#endif + +-#ifdef _WIN32_WCE +-/* Some things not defined on Windows CE. */ +-#define MemoryBarrier() +-#define getenv(Name) NULL +-#define setlocale(Category, Locale) "C" ++# if defined(_WIN32_WCE) ++ /* Some things not defined on Windows CE. */ ++# define strdup _strdup ++# define getenv(Name) NULL ++# if _WIN32_WCE < 0x800 ++# define setlocale(Category, Locale) "C" + static int errno = 0; /* Use something better? */ ++# endif ++# elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) ++# define getenv(Name) NULL ++# endif ++# if defined(_MSC_VER) && _MSC_VER < 1900 ++# define snprintf _snprintf ++# elif defined(_MSC_VER) && _MSC_VER >= 1900 ++# /* Covers VC++ Error for strdup being a deprecated POSIX name and to instead use _strdup instead */ ++# define strdup _strdup ++# endif + #endif + + #if HAVE_ATEXIT +@@ -202,8 +243,9 @@ + #define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond)) + #define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond)) + +-#define ASSERT_STATIC_EXPR(_cond)((void) sizeof (char[(_cond) ? 1 : -1])) +-#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * sizeof (char[(_cond) ? 1 : -1])) ++template <unsigned int cond> class hb_assert_constant_t {}; ++ ++#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>)) + + #define _PASTE1(a,b) a##b + #define PASTE(a,b) _PASTE1(a,b) +@@ -256,8 +298,8 @@ + + /* Void! */ + struct _hb_void_t {}; +-typedef const _hb_void_t &hb_void_t; +-#define HB_VOID (* (const _hb_void_t *) NULL) ++typedef const _hb_void_t *hb_void_t; ++#define HB_VOID ((const _hb_void_t *) NULL) + + /* Return the number of 1 bits in mask. */ + static inline HB_CONST_FUNC unsigned int +@@ -583,6 +625,30 @@ + #define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT)) + #define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0)) + ++static inline void ++_hb_print_func (const char *func) ++{ ++ if (func) ++ { ++ unsigned int func_len = strlen (func); ++ /* Skip "static" */ ++ if (0 == strncmp (func, "static ", 7)) ++ func += 7; ++ /* Skip "typename" */ ++ if (0 == strncmp (func, "typename ", 9)) ++ func += 9; ++ /* Skip return type */ ++ const char *space = strchr (func, ' '); ++ if (space) ++ func = space + 1; ++ /* Skip parameter list */ ++ const char *paren = strchr (func, '('); ++ if (paren) ++ func_len = paren - func; ++ fprintf (stderr, "%.*s", func_len, func); ++ } ++} ++ + template <int max_level> static inline void + _hb_debug_msg_va (const char *what, + const void *obj, +@@ -628,27 +694,13 @@ + } else + fprintf (stderr, " " VRBAR LBAR); + +- if (func) +- { +- unsigned int func_len = strlen (func); +-#ifndef HB_DEBUG_VERBOSE +- /* Skip "typename" */ +- if (0 == strncmp (func, "typename ", 9)) +- func += 9; +- /* Skip return type */ +- const char *space = strchr (func, ' '); +- if (space) +- func = space + 1; +- /* Skip parameter list */ +- const char *paren = strchr (func, '('); +- if (paren) +- func_len = paren - func; +-#endif +- fprintf (stderr, "%.*s: ", func_len, func); +- } ++ _hb_print_func (func); + + if (message) ++ { ++ fprintf (stderr, ": "); + vfprintf (stderr, message, ap); ++ } + + fprintf (stderr, "\n"); + } +@@ -738,7 +790,7 @@ + static inline void _hb_warn_no_return (bool returned) + { + if (unlikely (!returned)) { +- fprintf (stderr, "OUCH, returned with no call to TRACE_RETURN. This is a bug, please report.\n"); ++ fprintf (stderr, "OUCH, returned with no call to return_trace(). This is a bug, please report.\n"); + } + } + template <> +@@ -773,7 +825,7 @@ + inline ret_t ret (ret_t v, unsigned int line = 0) + { + if (unlikely (returned)) { +- fprintf (stderr, "OUCH, double calls to TRACE_RETURN. This is a bug, please report.\n"); ++ fprintf (stderr, "OUCH, double calls to return_trace(). This is a bug, please report.\n"); + return v; + } + +@@ -804,7 +856,7 @@ + inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; } + }; + +-#define TRACE_RETURN(RET) trace.ret (RET, __LINE__) ++#define return_trace(RET) return trace.ret (RET, __LINE__) + + /* Misc */ + +@@ -820,7 +872,7 @@ + /* The sizeof() is here to force template instantiation. + * I'm sure there are better ways to do this but can't think of + * one right now. Declaring a variable won't work as HB_UNUSED +- * is unsable on some platforms and unused types are less likely ++ * is unusable on some platforms and unused types are less likely + * to generate a warning than unused variables. */ + ASSERT_STATIC (sizeof (hb_assert_unsigned_t<T>) >= 0); + +@@ -842,51 +894,68 @@ + } + + ++/* Enable bitwise ops on enums marked as flags_t */ ++/* To my surprise, looks like the function resolver is happy to silently cast ++ * one enum to another... So this doesn't provide the type-checking that I ++ * originally had in mind... :(. ++ * ++ * For MSVC warnings, see: https://github.com/behdad/harfbuzz/pull/163 ++ */ ++#ifdef _MSC_VER ++# pragma warning(disable:4200) ++# pragma warning(disable:4800) ++#endif ++#define HB_MARK_AS_FLAG_T(T) \ ++ extern "C++" { \ ++ static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \ ++ static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \ ++ static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \ ++ static inline T operator ~ (T r) { return T (~(unsigned int) r); } \ ++ static inline T& operator |= (T &l, T r) { l = l | r; return l; } \ ++ static inline T& operator &= (T& l, T r) { l = l & r; return l; } \ ++ static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \ ++ } ++ ++ + /* Useful for set-operations on small enums. + * For example, for testing "x ∈ {x1, x2, x3}" use: +- * (FLAG(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3))) ++ * (FLAG_SAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3))) + */ +-#define FLAG(x) (1<<(x)) ++#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((x) < 32) + (1U << (x))) ++#define FLAG_SAFE(x) (1U << (x)) ++#define FLAG_UNSAFE(x) ((x) < 32 ? FLAG_SAFE(x) : 0) + #define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x)) + + + template <typename T, typename T2> static inline void +-hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2) ++hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2) + { +- if (unlikely (!len)) +- return; +- +- unsigned int k = len - 1; +- do { +- unsigned int new_k = 0; +- +- for (unsigned int j = 0; j < k; j++) +- if (compar (&array[j], &array[j+1]) > 0) +- { +- { +- T t; +- t = array[j]; +- array[j] = array[j + 1]; +- array[j + 1] = t; +- } +- if (array2) +- { +- T2 t; +- t = array2[j]; +- array2[j] = array2[j + 1]; +- array2[j + 1] = t; +- } +- +- new_k = j; +- } +- k = new_k; +- } while (k); ++ for (unsigned int i = 1; i < len; i++) ++ { ++ unsigned int j = i; ++ while (j && compar (&array[j - 1], &array[i]) > 0) ++ j--; ++ if (i == j) ++ continue; ++ /* Move item i to occupy place for item j, shift what's in between. */ ++ { ++ T t = array[i]; ++ memmove (&array[j + 1], &array[j], (i - j) * sizeof (T)); ++ array[j] = t; ++ } ++ if (array2) ++ { ++ T2 t = array2[i]; ++ memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2)); ++ array2[j] = t; ++ } ++ } + } + + template <typename T> static inline void +-hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *)) ++hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *)) + { +- hb_bubble_sort (array, len, compar, (int *) NULL); ++ hb_stable_sort (array, len, compar, (int *) NULL); + } + + static inline hb_bool_t +@@ -936,5 +1005,7 @@ + return _hb_options.opts; + } + ++/* Size signifying variable-sized array */ ++#define VAR 1 + + #endif /* HB_PRIVATE_HH */ +diff -uN gfx/harfbuzz/src_old/hb-set.cc gfx/harfbuzz/src/hb-set.cc +--- gfx/harfbuzz/src_old/hb-set.cc 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-set.cc 2016-06-05 23:50:28.650656740 +0200 +@@ -35,7 +35,7 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_set_t * + hb_set_create (void) +@@ -55,7 +55,7 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_set_t * + hb_set_get_empty (void) +@@ -76,7 +76,7 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_set_t * + hb_set_reference (hb_set_t *set) +@@ -88,7 +88,7 @@ + * hb_set_destroy: (skip) + * @set: a set. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_set_destroy (hb_set_t *set) +@@ -110,7 +110,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_set_set_user_data (hb_set_t *set, +@@ -129,7 +129,7 @@ + * + * Return value: (transfer none): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void * + hb_set_get_user_data (hb_set_t *set, +@@ -147,7 +147,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_set_allocation_successful (const hb_set_t *set HB_UNUSED) +@@ -161,7 +161,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_set_clear (hb_set_t *set) +@@ -177,7 +177,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + hb_bool_t + hb_set_is_empty (const hb_set_t *set) +@@ -194,7 +194,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_set_has (const hb_set_t *set, +@@ -210,7 +210,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_set_add (hb_set_t *set, +@@ -227,7 +227,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + void + hb_set_add_range (hb_set_t *set, +@@ -244,7 +244,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_set_del (hb_set_t *set, +@@ -261,7 +261,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + void + hb_set_del_range (hb_set_t *set, +@@ -280,7 +280,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + hb_bool_t + hb_set_is_equal (const hb_set_t *set, +@@ -296,7 +296,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_set_set (hb_set_t *set, +@@ -312,7 +312,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_set_union (hb_set_t *set, +@@ -328,7 +328,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_set_intersect (hb_set_t *set, +@@ -344,7 +344,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_set_subtract (hb_set_t *set, +@@ -360,7 +360,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_set_symmetric_difference (hb_set_t *set, +@@ -375,7 +375,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.10 + **/ + void + hb_set_invert (hb_set_t *set) +@@ -391,7 +391,7 @@ + * + * Return value: set population. + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + unsigned int + hb_set_get_population (const hb_set_t *set) +@@ -407,7 +407,7 @@ + * + * Return value: minimum of the set, or %HB_SET_VALUE_INVALID if set is empty. + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + hb_codepoint_t + hb_set_get_min (const hb_set_t *set) +@@ -423,7 +423,7 @@ + * + * Return value: minimum of the set, or %HB_SET_VALUE_INVALID if set is empty. + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + hb_codepoint_t + hb_set_get_max (const hb_set_t *set) +@@ -440,7 +440,7 @@ + * + * Return value: whether there was a next value. + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_set_next (const hb_set_t *set, +@@ -460,7 +460,7 @@ + * + * Return value: whether there was a next range. + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + hb_bool_t + hb_set_next_range (const hb_set_t *set, +diff -uN gfx/harfbuzz/src_old/hb-set.h gfx/harfbuzz/src/hb-set.h +--- gfx/harfbuzz/src_old/hb-set.h 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-set.h 2016-06-05 23:50:29.745651091 +0200 +@@ -36,114 +36,117 @@ + HB_BEGIN_DECLS + + ++/* ++ * Since: 0.9.21 ++ */ + #define HB_SET_VALUE_INVALID ((hb_codepoint_t) -1) + + typedef struct hb_set_t hb_set_t; + + +-hb_set_t * ++HB_EXTERN hb_set_t * + hb_set_create (void); + +-hb_set_t * ++HB_EXTERN hb_set_t * + hb_set_get_empty (void); + +-hb_set_t * ++HB_EXTERN hb_set_t * + hb_set_reference (hb_set_t *set); + +-void ++HB_EXTERN void + hb_set_destroy (hb_set_t *set); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_set_set_user_data (hb_set_t *set, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace); + +-void * ++HB_EXTERN void * + hb_set_get_user_data (hb_set_t *set, + hb_user_data_key_t *key); + + + /* Returns false if allocation has failed before */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_set_allocation_successful (const hb_set_t *set); + +-void ++HB_EXTERN void + hb_set_clear (hb_set_t *set); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_set_is_empty (const hb_set_t *set); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_set_has (const hb_set_t *set, + hb_codepoint_t codepoint); + + /* Right now limited to 16-bit integers. Eventually will do full codepoint range, sans -1 + * which we will use as a sentinel. */ +-void ++HB_EXTERN void + hb_set_add (hb_set_t *set, + hb_codepoint_t codepoint); + +-void ++HB_EXTERN void + hb_set_add_range (hb_set_t *set, + hb_codepoint_t first, + hb_codepoint_t last); + +-void ++HB_EXTERN void + hb_set_del (hb_set_t *set, + hb_codepoint_t codepoint); + +-void ++HB_EXTERN void + hb_set_del_range (hb_set_t *set, + hb_codepoint_t first, + hb_codepoint_t last); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_set_is_equal (const hb_set_t *set, + const hb_set_t *other); + +-void ++HB_EXTERN void + hb_set_set (hb_set_t *set, + const hb_set_t *other); + +-void ++HB_EXTERN void + hb_set_union (hb_set_t *set, + const hb_set_t *other); + +-void ++HB_EXTERN void + hb_set_intersect (hb_set_t *set, + const hb_set_t *other); + +-void ++HB_EXTERN void + hb_set_subtract (hb_set_t *set, + const hb_set_t *other); + +-void ++HB_EXTERN void + hb_set_symmetric_difference (hb_set_t *set, + const hb_set_t *other); + +-void ++HB_EXTERN void + hb_set_invert (hb_set_t *set); + +-unsigned int ++HB_EXTERN unsigned int + hb_set_get_population (const hb_set_t *set); + + /* Returns -1 if set empty. */ +-hb_codepoint_t ++HB_EXTERN hb_codepoint_t + hb_set_get_min (const hb_set_t *set); + + /* Returns -1 if set empty. */ +-hb_codepoint_t ++HB_EXTERN hb_codepoint_t + hb_set_get_max (const hb_set_t *set); + + /* Pass -1 in to get started. */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_set_next (const hb_set_t *set, + hb_codepoint_t *codepoint); + + /* Pass -1 for first and last to get started. */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_set_next_range (const hb_set_t *set, + hb_codepoint_t *first, + hb_codepoint_t *last); +diff -uN gfx/harfbuzz/src_old/hb-set-private.hh gfx/harfbuzz/src/hb-set-private.hh +--- gfx/harfbuzz/src_old/hb-set-private.hh 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-set-private.hh 2016-06-05 23:50:27.437662982 +0200 +@@ -36,7 +36,15 @@ + * "approximate member query". Conceptually these are like Bloom + * Filter and Quotient Filter, however, much smaller, faster, and + * designed to fit the requirements of our uses for glyph coverage +- * queries. As a result, our filters have much higher. ++ * queries. ++ * ++ * Our filters are highly accurate if the lookup covers fairly local ++ * set of glyphs, but fully flooded and ineffective if coverage is ++ * all over the place. ++ * ++ * The frozen-set can be used instead of a digest, to trade more ++ * memory for 100% accuracy, but in practice, that doesn't look like ++ * an attractive trade-off. + */ + + template <typename mask_t, unsigned int shift> +@@ -145,6 +153,8 @@ + + struct hb_set_t + { ++ friend struct hb_frozen_set_t; ++ + hb_object_header_t header; + ASSERT_POD (); + bool in_error; +@@ -326,7 +336,7 @@ + static const hb_codepoint_t INVALID = HB_SET_VALUE_INVALID; + + elt_t &elt (hb_codepoint_t g) { return elts[g >> SHIFT]; } +- elt_t elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; } ++ elt_t const &elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; } + elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); } + + elt_t elts[ELTS]; /* XXX 8kb */ +@@ -335,6 +345,58 @@ + ASSERT_STATIC (sizeof (elt_t) * 8 * ELTS > MAX_G); + }; + ++struct hb_frozen_set_t ++{ ++ static const unsigned int SHIFT = hb_set_t::SHIFT; ++ static const unsigned int BITS = hb_set_t::BITS; ++ static const unsigned int MASK = hb_set_t::MASK; ++ typedef hb_set_t::elt_t elt_t; ++ ++ inline void init (const hb_set_t &set) ++ { ++ start = count = 0; ++ elts = NULL; ++ ++ unsigned int max = set.get_max (); ++ if (max == set.INVALID) ++ return; ++ unsigned int min = set.get_min (); ++ const elt_t &min_elt = set.elt (min); ++ ++ start = min & ~MASK; ++ count = max - start + 1; ++ unsigned int num_elts = (count + BITS - 1) / BITS; ++ unsigned int elts_size = num_elts * sizeof (elt_t); ++ elts = (elt_t *) malloc (elts_size); ++ if (unlikely (!elts)) ++ { ++ start = count = 0; ++ return; ++ } ++ memcpy (elts, &min_elt, elts_size); ++ } ++ ++ inline void fini (void) ++ { ++ if (elts) ++ free (elts); ++ } ++ ++ inline bool has (hb_codepoint_t g) const ++ { ++ /* hb_codepoint_t is unsigned. */ ++ g -= start; ++ if (unlikely (g > count)) return false; ++ return !!(elt (g) & mask (g)); ++ } ++ ++ elt_t const &elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; } ++ elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); } ++ ++ private: ++ hb_codepoint_t start, count; ++ elt_t *elts; ++}; + + + #endif /* HB_SET_PRIVATE_HH */ +diff -uN gfx/harfbuzz/src_old/hb-shape.cc gfx/harfbuzz/src/hb-shape.cc +--- gfx/harfbuzz/src_old/hb-shape.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-shape.cc 2016-06-05 23:50:35.179623187 +0200 +@@ -33,6 +33,17 @@ + #include "hb-buffer-private.hh" + #include "hb-font-private.hh" + ++/** ++ * SECTION:hb-shape ++ * @title: Shaping ++ * @short_description: Conversion of text strings into positioned glyphs ++ * @include: hb.h ++ * ++ * Shaping is the central operation of HarfBuzz. Shaping operates on buffers, ++ * which are sequences of Unicode characters that use the same font and have ++ * the same text direction, script and language. After shaping the buffer ++ * contains the output glyphs and their positions. ++ **/ + + static bool + parse_space (const char **pp, const char *end) +@@ -198,15 +209,18 @@ + + /** + * hb_feature_from_string: +- * @str: (array length=len): +- * @len: +- * @feature: (out) (allow-none): ++ * @str: (array length=len) (element-type uint8_t): a string to parse ++ * @len: length of @str, or -1 if string is %NULL terminated ++ * @feature: (out): the #hb_feature_t to initialize with the parsed values ++ * ++ * Parses a string into a #hb_feature_t. + * +- * ++ * TODO: document the syntax here. + * +- * Return value: ++ * Return value: ++ * %true if @str is successfully parsed, %false otherwise. + * +- * Since: 1.0 ++ * Since: 0.9.5 + **/ + hb_bool_t + hb_feature_from_string (const char *str, int len, +@@ -231,13 +245,15 @@ + + /** + * hb_feature_to_string: +- * @feature: +- * @buf: (array length=size): +- * @size: ++ * @feature: an #hb_feature_t to convert ++ * @buf: (array length=size) (out): output string ++ * @size: the allocated size of @buf ++ * ++ * Converts a #hb_feature_t into a %NULL-terminated string in the format ++ * understood by hb_feature_from_string(). The client in responsible for ++ * allocating big enough size for @buf, 128 bytes is more than enough. + * +- * +- * +- * Since: 1.0 ++ * Since: 0.9.5 + **/ + void + hb_feature_to_string (hb_feature_t *feature, +@@ -279,20 +295,23 @@ + + static const char **static_shaper_list; + +-static inline ++#ifdef HB_USE_ATEXIT ++static + void free_static_shaper_list (void) + { + free (static_shaper_list); + } ++#endif + + /** + * hb_shape_list_shapers: + * +- * ++ * Retrieves the list of shapers supported by HarfBuzz. + * +- * Return value: (transfer none): ++ * Return value: (transfer none) (array zero-terminated=1): an array of ++ * constant strings + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + const char ** + hb_shape_list_shapers (void) +@@ -331,17 +350,21 @@ + + /** + * hb_shape_full: +- * @font: a font. +- * @buffer: a buffer. +- * @features: (array length=num_features): +- * @num_features: +- * @shaper_list: (array zero-terminated=1): +- * +- * ++ * @font: an #hb_font_t to use for shaping ++ * @buffer: an #hb_buffer_t to shape ++ * @features: (array length=num_features) (allow-none): an array of user ++ * specified #hb_feature_t or %NULL ++ * @num_features: the length of @features array ++ * @shaper_list: (array zero-terminated=1) (allow-none): a %NULL-terminated ++ * array of shapers to use or %NULL ++ * ++ * See hb_shape() for details. If @shaper_list is not %NULL, the specified ++ * shapers will be used in the given order, otherwise the default shapers list ++ * will be used. + * +- * Return value: ++ * Return value: %FALSE if all shapers failed, %TRUE otherwise + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_shape_full (hb_font_t *font, +@@ -350,11 +373,6 @@ + unsigned int num_features, + const char * const *shaper_list) + { +- if (unlikely (!buffer->len)) +- return true; +- +- assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE); +- + hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list); + hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features); + hb_shape_plan_destroy (shape_plan); +@@ -366,14 +384,19 @@ + + /** + * hb_shape: +- * @font: a font. +- * @buffer: a buffer. +- * @features: (array length=num_features): +- * @num_features: ++ * @font: an #hb_font_t to use for shaping ++ * @buffer: an #hb_buffer_t to shape ++ * @features: (array length=num_features) (allow-none): an array of user ++ * specified #hb_feature_t or %NULL ++ * @num_features: the length of @features array ++ * ++ * Shapes @buffer using @font turning its Unicode characters content to ++ * positioned glyphs. If @features is not %NULL, it will be used to control the ++ * features applied during shaping. + * +- * ++ * Return value: %FALSE if all shapers failed, %TRUE otherwise + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_shape (hb_font_t *font, +diff -uN gfx/harfbuzz/src_old/hb-shape.h gfx/harfbuzz/src/hb-shape.h +--- gfx/harfbuzz/src_old/hb-shape.h 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-shape.h 2016-06-05 23:50:36.664615573 +0200 +@@ -47,32 +47,29 @@ + unsigned int end; + } hb_feature_t; + +-/* len=-1 means str is NUL-terminated */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_feature_from_string (const char *str, int len, + hb_feature_t *feature); + +-/* Something like 128 bytes is more than enough. +- * nul-terminates. */ +-void ++HB_EXTERN void + hb_feature_to_string (hb_feature_t *feature, + char *buf, unsigned int size); + + +-void ++HB_EXTERN void + hb_shape (hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_shape_full (hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features, + const char * const *shaper_list); + +-const char ** ++HB_EXTERN const char ** + hb_shape_list_shapers (void); + + +diff -uN gfx/harfbuzz/src_old/hb-shape-plan.cc gfx/harfbuzz/src/hb-shape-plan.cc +--- gfx/harfbuzz/src_old/hb-shape-plan.cc 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-shape-plan.cc 2016-06-05 23:50:32.402637444 +0200 +@@ -106,7 +106,7 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + hb_shape_plan_t * + hb_shape_plan_create (hb_face_t *face, +@@ -126,9 +126,9 @@ + + if (unlikely (!face)) + face = hb_face_get_empty (); +- if (unlikely (!props || hb_object_is_inert (face))) ++ if (unlikely (!props)) + return hb_shape_plan_get_empty (); +- if (num_user_features && !(features = (hb_feature_t *) malloc (num_user_features * sizeof (hb_feature_t)))) ++ if (num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t)))) + return hb_shape_plan_get_empty (); + if (!(shape_plan = hb_object_create<hb_shape_plan_t> ())) { + free (features); +@@ -158,7 +158,7 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + hb_shape_plan_t * + hb_shape_plan_get_empty (void) +@@ -194,7 +194,7 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + hb_shape_plan_t * + hb_shape_plan_reference (hb_shape_plan_t *shape_plan) +@@ -208,7 +208,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + void + hb_shape_plan_destroy (hb_shape_plan_t *shape_plan) +@@ -236,7 +236,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + hb_bool_t + hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan, +@@ -257,7 +257,7 @@ + * + * Return value: (transfer none): + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + void * + hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan, +@@ -279,7 +279,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + hb_bool_t + hb_shape_plan_execute (hb_shape_plan_t *shape_plan, +@@ -293,9 +293,13 @@ + num_features, + shape_plan->shaper_func); + +- if (unlikely (hb_object_is_inert (shape_plan) || +- hb_object_is_inert (font) || +- hb_object_is_inert (buffer))) ++ if (unlikely (!buffer->len)) ++ return true; ++ ++ assert (!hb_object_is_inert (buffer)); ++ assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE); ++ ++ if (unlikely (hb_object_is_inert (shape_plan))) + return false; + + assert (shape_plan->face_unsafe == font->face); +@@ -396,7 +400,7 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + hb_shape_plan_t * + hb_shape_plan_create_cached (hb_face_t *face, +@@ -453,6 +457,10 @@ + + hb_shape_plan_t *shape_plan = hb_shape_plan_create (face, props, user_features, num_user_features, shaper_list); + ++ /* Don't add to the cache if face is inert. */ ++ if (unlikely (hb_object_is_inert (face))) ++ return shape_plan; ++ + /* Don't add the plan to the cache if there were user features with non-global ranges */ + + if (hb_non_global_user_features_present (user_features, num_user_features)) +@@ -483,7 +491,7 @@ + * + * Return value: (transfer none): + * +- * Since: 1.0 ++ * Since: 0.9.7 + **/ + const char * + hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan) +diff -uN gfx/harfbuzz/src_old/hb-shape-plan.h gfx/harfbuzz/src/hb-shape-plan.h +--- gfx/harfbuzz/src_old/hb-shape-plan.h 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-shape-plan.h 2016-06-05 23:50:33.950629490 +0200 +@@ -38,49 +38,49 @@ + + typedef struct hb_shape_plan_t hb_shape_plan_t; + +-hb_shape_plan_t * ++HB_EXTERN hb_shape_plan_t * + hb_shape_plan_create (hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const char * const *shaper_list); + +-hb_shape_plan_t * ++HB_EXTERN hb_shape_plan_t * + hb_shape_plan_create_cached (hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const char * const *shaper_list); + +-hb_shape_plan_t * ++HB_EXTERN hb_shape_plan_t * + hb_shape_plan_get_empty (void); + +-hb_shape_plan_t * ++HB_EXTERN hb_shape_plan_t * + hb_shape_plan_reference (hb_shape_plan_t *shape_plan); + +-void ++HB_EXTERN void + hb_shape_plan_destroy (hb_shape_plan_t *shape_plan); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace); + +-void * ++HB_EXTERN void * + hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan, + hb_user_data_key_t *key); + + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_shape_plan_execute (hb_shape_plan_t *shape_plan, + hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features); + +-const char * ++HB_EXTERN const char * + hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan); + + +diff -uN gfx/harfbuzz/src_old/hb-shaper.cc gfx/harfbuzz/src/hb-shaper.cc +--- gfx/harfbuzz/src_old/hb-shaper.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-shaper.cc 2016-06-05 23:50:41.554590551 +0200 +@@ -40,12 +40,14 @@ + + static const hb_shaper_pair_t *static_shapers; + +-static inline ++#ifdef HB_USE_ATEXIT ++static + void free_static_shapers (void) + { + if (unlikely (static_shapers != all_shapers)) + free ((void *) static_shapers); + } ++#endif + + const hb_shaper_pair_t * + _hb_shapers_get (void) +@@ -62,7 +64,7 @@ + } + + /* Not found; allocate one. */ +- shapers = (hb_shaper_pair_t *) malloc (sizeof (all_shapers)); ++ shapers = (hb_shaper_pair_t *) calloc (1, sizeof (all_shapers)); + if (unlikely (!shapers)) { + (void) hb_atomic_ptr_cmpexch (&static_shapers, NULL, &all_shapers[0]); + return (const hb_shaper_pair_t *) all_shapers; +diff -uN gfx/harfbuzz/src_old/hb-shaper-list.hh gfx/harfbuzz/src/hb-shaper-list.hh +--- gfx/harfbuzz/src_old/hb-shaper-list.hh 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-shaper-list.hh 2016-06-05 23:50:39.106603073 +0200 +@@ -46,6 +46,9 @@ + #ifdef HAVE_UNISCRIBE + HB_SHAPER_IMPLEMENT (uniscribe) + #endif ++#ifdef HAVE_DIRECTWRITE ++HB_SHAPER_IMPLEMENT (directwrite) ++#endif + #ifdef HAVE_CORETEXT + HB_SHAPER_IMPLEMENT (coretext) + #endif +diff -uN gfx/harfbuzz/src_old/hb-shaper-private.hh gfx/harfbuzz/src/hb-shaper-private.hh +--- gfx/harfbuzz/src_old/hb-shaper-private.hh 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-shaper-private.hh 2016-06-05 23:50:40.352596696 +0200 +@@ -79,10 +79,9 @@ + HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *data) + + #define HB_SHAPER_DATA_DESTROY(shaper, object) \ +- if (object->shaper_data.shaper && \ +- object->shaper_data.shaper != HB_SHAPER_DATA_INVALID && \ +- object->shaper_data.shaper != HB_SHAPER_DATA_SUCCEEDED) \ +- HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA (shaper, object)); ++ if (HB_SHAPER_DATA_TYPE (shaper, object) *data = HB_SHAPER_DATA (shaper, object)) \ ++ if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) \ ++ HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); + + #define HB_SHAPER_DATA_ENSURE_DECLARE(shaper, object) \ + static inline bool \ +diff -uN gfx/harfbuzz/src_old/hb-ucdn.cc gfx/harfbuzz/src/hb-ucdn.cc +--- gfx/harfbuzz/src_old/hb-ucdn.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-ucdn.cc 2016-06-05 23:50:42.748584458 +0200 +@@ -148,6 +148,12 @@ + HB_SCRIPT_SIDDHAM, + HB_SCRIPT_TIRHUTA, + HB_SCRIPT_WARANG_CITI, ++ HB_SCRIPT_AHOM, ++ HB_SCRIPT_ANATOLIAN_HIEROGLYPHS, ++ HB_SCRIPT_HATRAN, ++ HB_SCRIPT_MULTANI, ++ HB_SCRIPT_OLD_HUNGARIAN, ++ HB_SCRIPT_SIGNWRITING, + }; + + static hb_unicode_combining_class_t +diff -uN gfx/harfbuzz/src_old/hb-unicode.cc gfx/harfbuzz/src/hb-unicode.cc +--- gfx/harfbuzz/src_old/hb-unicode.cc 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-unicode.cc 2016-06-05 23:50:45.673569556 +0200 +@@ -146,24 +146,19 @@ + } + + #if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL) +-#ifdef _MSC_VER +-#pragma message("Could not find any Unicode functions implementation, you have to provide your own") +-#pragma message("To suppress this warnings, define HB_NO_UNICODE_FUNCS") +-#else +-#warning "Could not find any Unicode functions implementation, you have to provide your own" +-#warning "To suppress this warning, define HB_NO_UNICODE_FUNCS" +-#endif ++#error "Could not find any Unicode functions implementation, you have to provide your own" ++#error "Consider building hb-ucdn.c. If you absolutely want to build without any, check the code." + #endif + + /** + * hb_unicode_funcs_create: (Xconstructor) +- * @parent: (allow-none): ++ * @parent: (nullable): + * + * + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_unicode_funcs_t * + hb_unicode_funcs_create (hb_unicode_funcs_t *parent) +@@ -209,7 +204,7 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_unicode_funcs_t * + hb_unicode_funcs_get_empty (void) +@@ -225,7 +220,7 @@ + * + * Return value: (transfer full): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_unicode_funcs_t * + hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs) +@@ -239,7 +234,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs) +@@ -268,7 +263,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs, +@@ -289,7 +284,7 @@ + * + * Return value: (transfer none): + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void * + hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs, +@@ -305,7 +300,7 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + void + hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs) +@@ -324,7 +319,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs) +@@ -340,7 +335,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_unicode_funcs_t * + hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs) +@@ -400,7 +395,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_unicode_compose (hb_unicode_funcs_t *ufuncs, +@@ -422,7 +417,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + hb_bool_t + hb_unicode_decompose (hb_unicode_funcs_t *ufuncs, +@@ -443,7 +438,7 @@ + * + * Return value: + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ + unsigned int + hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs, +diff -uN gfx/harfbuzz/src_old/hb-unicode.h gfx/harfbuzz/src/hb-unicode.h +--- gfx/harfbuzz/src_old/hb-unicode.h 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-unicode.h 2016-06-05 23:50:47.101562269 +0200 +@@ -174,23 +174,23 @@ + /* + * just give me the best implementation you've got there. + */ +-hb_unicode_funcs_t * ++HB_EXTERN hb_unicode_funcs_t * + hb_unicode_funcs_get_default (void); + + +-hb_unicode_funcs_t * ++HB_EXTERN hb_unicode_funcs_t * + hb_unicode_funcs_create (hb_unicode_funcs_t *parent); + +-hb_unicode_funcs_t * ++HB_EXTERN hb_unicode_funcs_t * + hb_unicode_funcs_get_empty (void); + +-hb_unicode_funcs_t * ++HB_EXTERN hb_unicode_funcs_t * + hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs); + +-void ++HB_EXTERN void + hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs, + hb_user_data_key_t *key, + void * data, +@@ -198,18 +198,18 @@ + hb_bool_t replace); + + +-void * ++HB_EXTERN void * + hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs, + hb_user_data_key_t *key); + + +-void ++HB_EXTERN void + hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs); + +-hb_unicode_funcs_t * ++HB_EXTERN hb_unicode_funcs_t * + hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs); + + +@@ -283,9 +283,9 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_combining_class_func_t func, + void *user_data, hb_destroy_func_t destroy); +@@ -299,9 +299,9 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_eastasian_width_func_t func, + void *user_data, hb_destroy_func_t destroy); +@@ -315,9 +315,9 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_general_category_func_t func, + void *user_data, hb_destroy_func_t destroy); +@@ -331,9 +331,9 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_mirroring_func_t func, + void *user_data, hb_destroy_func_t destroy); +@@ -347,9 +347,9 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_script_func_t func, + void *user_data, hb_destroy_func_t destroy); +@@ -363,9 +363,9 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_compose_func_t func, + void *user_data, hb_destroy_func_t destroy); +@@ -379,9 +379,9 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_unicode_funcs_set_decompose_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_decompose_func_t func, + void *user_data, hb_destroy_func_t destroy); +@@ -395,47 +395,88 @@ + * + * + * +- * Since: 1.0 ++ * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_decompose_compatibility_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /* accessors */ + +-hb_unicode_combining_class_t ++/** ++ * hb_unicode_combining_class: ++ * ++ * Since: 0.9.2 ++ **/ ++HB_EXTERN hb_unicode_combining_class_t + hb_unicode_combining_class (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t unicode); + +-unsigned int ++/** ++ * hb_unicode_eastasian_width: ++ * ++ * Since: 0.9.2 ++ **/ ++HB_EXTERN unsigned int + hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t unicode); + +-hb_unicode_general_category_t ++/** ++ * hb_unicode_general_category: ++ * ++ * Since: 0.9.2 ++ **/ ++HB_EXTERN hb_unicode_general_category_t + hb_unicode_general_category (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t unicode); + +-hb_codepoint_t ++/** ++ * hb_unicode_mirroring: ++ * ++ * Since: 0.9.2 ++ **/ ++HB_EXTERN hb_codepoint_t + hb_unicode_mirroring (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t unicode); + +-hb_script_t ++/** ++ * hb_unicode_script: ++ * ++ * Since: 0.9.2 ++ **/ ++HB_EXTERN hb_script_t + hb_unicode_script (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t unicode); + +-hb_bool_t ++/** ++ * hb_unicode_compose: ++ * ++ * Since: 0.9.2 ++ **/ ++HB_EXTERN hb_bool_t + hb_unicode_compose (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t a, + hb_codepoint_t b, + hb_codepoint_t *ab); +-hb_bool_t ++ ++/** ++ * hb_unicode_decompose: ++ * ++ * Since: 0.9.2 ++ **/ ++HB_EXTERN hb_bool_t + hb_unicode_decompose (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t ab, + hb_codepoint_t *a, + hb_codepoint_t *b); + +-unsigned int ++/** ++ * hb_unicode_decompose_compatibility: ++ * ++ * Since: 0.9.2 ++ **/ ++HB_EXTERN unsigned int + hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t u, + hb_codepoint_t *decomposed); +diff -uN gfx/harfbuzz/src_old/hb-unicode-private.hh gfx/harfbuzz/src/hb-unicode-private.hh +--- gfx/harfbuzz/src_old/hb-unicode-private.hh 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-unicode-private.hh 2016-06-05 23:50:44.271576710 +0200 +@@ -199,6 +199,50 @@ + } + } + ++ /* Space estimates based on: ++ * http://www.unicode.org/charts/PDF/U2000.pdf ++ * https://www.microsoft.com/typography/developers/fdsspec/spaces.aspx ++ */ ++ enum space_t { ++ NOT_SPACE = 0, ++ SPACE_EM = 1, ++ SPACE_EM_2 = 2, ++ SPACE_EM_3 = 3, ++ SPACE_EM_4 = 4, ++ SPACE_EM_5 = 5, ++ SPACE_EM_6 = 6, ++ SPACE_EM_16 = 16, ++ SPACE_4_EM_18, /* 4/18th of an EM! */ ++ SPACE, ++ SPACE_FIGURE, ++ SPACE_PUNCTUATION, ++ SPACE_NARROW, ++ }; ++ static inline space_t ++ space_fallback_type (hb_codepoint_t u) ++ { ++ switch (u) ++ { ++ /* All GC=Zs chars that can use a fallback. */ ++ default: return NOT_SPACE; /* Shouldn't happen. */ ++ case 0x0020u: return SPACE; /* U+0020 SPACE */ ++ case 0x00A0u: return SPACE; /* U+00A0 NO-BREAK SPACE */ ++ case 0x2000u: return SPACE_EM_2; /* U+2000 EN QUAD */ ++ case 0x2001u: return SPACE_EM; /* U+2001 EM QUAD */ ++ case 0x2002u: return SPACE_EM_2; /* U+2002 EN SPACE */ ++ case 0x2003u: return SPACE_EM; /* U+2003 EM SPACE */ ++ case 0x2004u: return SPACE_EM_3; /* U+2004 THREE-PER-EM SPACE */ ++ case 0x2005u: return SPACE_EM_4; /* U+2005 FOUR-PER-EM SPACE */ ++ case 0x2006u: return SPACE_EM_6; /* U+2006 SIX-PER-EM SPACE */ ++ case 0x2007u: return SPACE_FIGURE; /* U+2007 FIGURE SPACE */ ++ case 0x2008u: return SPACE_PUNCTUATION; /* U+2008 PUNCTUATION SPACE */ ++ case 0x2009u: return SPACE_EM_5; /* U+2009 THIN SPACE */ ++ case 0x200Au: return SPACE_EM_16; /* U+200A HAIR SPACE */ ++ case 0x202Fu: return SPACE_NARROW; /* U+202F NARROW NO-BREAK SPACE */ ++ case 0x205Fu: return SPACE_4_EM_18; /* U+205F MEDIUM MATHEMATICAL SPACE */ ++ case 0x3000u: return SPACE_EM; /* U+3000 IDEOGRAPHIC SPACE */ ++ } ++ } + + struct { + #define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_func_t name; +@@ -308,10 +352,14 @@ + /* Misc */ + + #define HB_UNICODE_GENERAL_CATEGORY_IS_MARK(gen_cat) \ +- (FLAG (gen_cat) & \ ++ (FLAG_SAFE (gen_cat) & \ + (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \ + FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \ + FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK))) + ++#define HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK(gen_cat) \ ++ (FLAG_SAFE (gen_cat) & \ ++ (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \ ++ FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK))) + + #endif /* HB_UNICODE_PRIVATE_HH */ +diff -uN gfx/harfbuzz/src_old/hb-uniscribe.cc gfx/harfbuzz/src/hb-uniscribe.cc +--- gfx/harfbuzz/src_old/hb-uniscribe.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-uniscribe.cc 2016-06-05 23:50:48.566554822 +0200 +@@ -486,14 +486,16 @@ + LOGFONTW log_font; + HFONT hfont; + SCRIPT_CACHE script_cache; ++ double x_mult, y_mult; /* From LOGFONT space to HB space. */ + }; + + static bool + populate_log_font (LOGFONTW *lf, +- hb_font_t *font) ++ hb_font_t *font, ++ unsigned int font_size) + { + memset (lf, 0, sizeof (*lf)); +- lf->lfHeight = -font->y_scale; ++ lf->lfHeight = -font_size; + lf->lfCharSet = DEFAULT_CHARSET; + + hb_face_t *face = font->face; +@@ -513,9 +515,19 @@ + if (unlikely (!data)) + return NULL; + ++ int font_size = font->face->get_upem (); /* Default... */ ++ /* No idea if the following is even a good idea. */ ++ if (font->y_ppem) ++ font_size = font->y_ppem; ++ ++ if (font_size < 0) ++ font_size = -font_size; ++ data->x_mult = (double) font->x_scale / font_size; ++ data->y_mult = (double) font->y_scale / font_size; ++ + data->hdc = GetDC (NULL); + +- if (unlikely (!populate_log_font (&data->log_font, font))) { ++ if (unlikely (!populate_log_font (&data->log_font, font, font_size))) { + DEBUG_MSG (UNISCRIBE, font, "Font populate_log_font() failed"); + _hb_uniscribe_shaper_font_data_destroy (data); + return NULL; +@@ -907,7 +919,7 @@ + + if (unlikely (items[i].a.fNoGlyphIndex)) + FAIL ("ScriptShapeOpenType() set fNoGlyphIndex"); +- if (unlikely (hr == E_OUTOFMEMORY)) ++ if (unlikely (hr == E_OUTOFMEMORY || hr == E_NOT_SUFFICIENT_BUFFER)) + { + if (unlikely (!buffer->ensure (buffer->allocated * 2))) + FAIL ("Buffer resize failed"); +@@ -994,21 +1006,22 @@ + + /* The rest is crap. Let's store position info there for now. */ + info->mask = advances[i]; +- info->var1.u32 = offsets[i].du; +- info->var2.u32 = offsets[i].dv; ++ info->var1.i32 = offsets[i].du; ++ info->var2.i32 = offsets[i].dv; + } + + /* Set glyph positions */ + buffer->clear_positions (); ++ double x_mult = font_data->x_mult, y_mult = font_data->y_mult; + for (unsigned int i = 0; i < glyphs_len; i++) + { + hb_glyph_info_t *info = &buffer->info[i]; + hb_glyph_position_t *pos = &buffer->pos[i]; + + /* TODO vertical */ +- pos->x_advance = info->mask; +- pos->x_offset = backward ? -info->var1.u32 : info->var1.u32; +- pos->y_offset = info->var2.u32; ++ pos->x_advance = x_mult * (int32_t) info->mask; ++ pos->x_offset = x_mult * (backward ? -info->var1.i32 : info->var1.i32); ++ pos->y_offset = y_mult * info->var2.i32; + } + + if (backward) +diff -uN gfx/harfbuzz/src_old/hb-uniscribe.h gfx/harfbuzz/src/hb-uniscribe.h +--- gfx/harfbuzz/src_old/hb-uniscribe.h 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-uniscribe.h 2016-06-05 23:50:49.730548897 +0200 +@@ -34,10 +34,10 @@ + HB_BEGIN_DECLS + + +-LOGFONTW * ++HB_EXTERN LOGFONTW * + hb_uniscribe_font_get_logfontw (hb_font_t *font); + +-HFONT ++HB_EXTERN HFONT + hb_uniscribe_font_get_hfont (hb_font_t *font); + + +diff -uN gfx/harfbuzz/src_old/hb-utf-private.hh gfx/harfbuzz/src/hb-utf-private.hh +--- gfx/harfbuzz/src_old/hb-utf-private.hh 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-utf-private.hh 2016-06-05 23:50:51.027542307 +0200 +@@ -29,14 +29,11 @@ + + #include "hb-private.hh" + +-template <typename T, bool validate=true> struct hb_utf_t; + +- +-/* UTF-8 */ +- +-template <> +-struct hb_utf_t<uint8_t, true> ++struct hb_utf8_t + { ++ typedef uint8_t codepoint_t; ++ + static inline const uint8_t * + next (const uint8_t *text, + const uint8_t *end, +@@ -131,11 +128,10 @@ + }; + + +-/* UTF-16 */ +- +-template <> +-struct hb_utf_t<uint16_t, true> ++struct hb_utf16_t + { ++ typedef uint16_t codepoint_t; ++ + static inline const uint16_t * + next (const uint16_t *text, + const uint16_t *end, +@@ -150,11 +146,11 @@ + return text; + } + +- if (likely (hb_in_range (c, 0xD800u, 0xDBFFu))) ++ if (likely (c <= 0xDBFFu && text < end)) + { + /* High-surrogate in c */ +- hb_codepoint_t l; +- if (text < end && ((l = *text), likely (hb_in_range (l, 0xDC00u, 0xDFFFu)))) ++ hb_codepoint_t l = *text; ++ if (likely (hb_in_range (l, 0xDC00u, 0xDFFFu))) + { + /* Low-surrogate in l */ + *unicode = (c << 10) + l - ((0xD800u << 10) - 0x10000u + 0xDC00u); +@@ -174,8 +170,7 @@ + hb_codepoint_t *unicode, + hb_codepoint_t replacement) + { +- const uint16_t *end = text--; +- hb_codepoint_t c = *text; ++ hb_codepoint_t c = *--text; + + if (likely (!hb_in_range (c, 0xD800u, 0xDFFFu))) + { +@@ -183,14 +178,22 @@ + return text; + } + +- if (likely (start < text && hb_in_range (c, 0xDC00u, 0xDFFFu))) +- text--; +- +- if (likely (next (text, end, unicode, replacement) == end)) +- return text; ++ if (likely (c >= 0xDC00u && start < text)) ++ { ++ /* Low-surrogate in c */ ++ hb_codepoint_t h = text[-1]; ++ if (likely (hb_in_range (h, 0xD800u, 0xDBFFu))) ++ { ++ /* High-surrogate in h */ ++ *unicode = (h << 10) + c - ((0xD800u << 10) - 0x10000u + 0xDC00u); ++ text--; ++ return text; ++ } ++ } + ++ /* Lonely / out-of-order surrogate. */ + *unicode = replacement; +- return end - 1; ++ return text; + } + + +@@ -204,25 +207,20 @@ + }; + + +-/* UTF-32 */ +- +-template <bool validate> +-struct hb_utf_t<uint32_t, validate> ++template <bool validate=true> ++struct hb_utf32_t + { ++ typedef uint32_t codepoint_t; ++ + static inline const uint32_t * + next (const uint32_t *text, + const uint32_t *end HB_UNUSED, + hb_codepoint_t *unicode, + hb_codepoint_t replacement) + { +- hb_codepoint_t c = *text++; +- if (validate && unlikely (c > 0x10FFFFu || hb_in_range (c, 0xD800u, 0xDFFFu))) +- goto error; +- *unicode = c; +- return text; +- +- error: +- *unicode = replacement; ++ hb_codepoint_t c = *unicode = *text++; ++ if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu))) ++ *unicode = replacement; + return text; + } + +@@ -232,8 +230,10 @@ + hb_codepoint_t *unicode, + hb_codepoint_t replacement) + { +- next (text - 1, text, unicode, replacement); +- return text - 1; ++ hb_codepoint_t c = *unicode = *--text; ++ if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu))) ++ *unicode = replacement; ++ return text; + } + + static inline unsigned int +@@ -246,4 +246,37 @@ + }; + + ++struct hb_latin1_t ++{ ++ typedef uint8_t codepoint_t; ++ ++ static inline const uint8_t * ++ next (const uint8_t *text, ++ const uint8_t *end HB_UNUSED, ++ hb_codepoint_t *unicode, ++ hb_codepoint_t replacement HB_UNUSED) ++ { ++ *unicode = *text++; ++ return text; ++ } ++ ++ static inline const uint8_t * ++ prev (const uint8_t *text, ++ const uint8_t *start HB_UNUSED, ++ hb_codepoint_t *unicode, ++ hb_codepoint_t replacement) ++ { ++ *unicode = *--text; ++ return text; ++ } ++ ++ static inline unsigned int ++ strlen (const uint8_t *text) ++ { ++ unsigned int l = 0; ++ while (*text++) l++; ++ return l; ++ } ++}; ++ + #endif /* HB_UTF_PRIVATE_HH */ +diff -uN gfx/harfbuzz/src_old/hb-version.h gfx/harfbuzz/src/hb-version.h +--- gfx/harfbuzz/src_old/hb-version.h 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-version.h 2016-06-05 23:50:52.292535893 +0200 +@@ -36,26 +36,26 @@ + HB_BEGIN_DECLS + + +-#define HB_VERSION_MAJOR 0 +-#define HB_VERSION_MINOR 9 +-#define HB_VERSION_MICRO 37 ++#define HB_VERSION_MAJOR 1 ++#define HB_VERSION_MINOR 1 ++#define HB_VERSION_MICRO 3 + +-#define HB_VERSION_STRING "0.9.37" ++#define HB_VERSION_STRING "1.1.3" + + #define HB_VERSION_ATLEAST(major,minor,micro) \ + ((major)*10000+(minor)*100+(micro) <= \ + HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO) + + +-void ++HB_EXTERN void + hb_version (unsigned int *major, + unsigned int *minor, + unsigned int *micro); + +-const char * ++HB_EXTERN const char * + hb_version_string (void); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_version_atleast (unsigned int major, + unsigned int minor, + unsigned int micro); +diff -uN gfx/harfbuzz/src_old/hb-version.h.in gfx/harfbuzz/src/hb-version.h.in +--- gfx/harfbuzz/src_old/hb-version.h.in 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/hb-version.h.in 2016-06-05 23:50:53.575529376 +0200 +@@ -47,15 +47,15 @@ + HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO) + + +-void ++HB_EXTERN void + hb_version (unsigned int *major, + unsigned int *minor, + unsigned int *micro); + +-const char * ++HB_EXTERN const char * + hb_version_string (void); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_version_atleast (unsigned int major, + unsigned int minor, + unsigned int micro); +diff -uN gfx/harfbuzz/src_old/hb-warning.cc gfx/harfbuzz/src/hb-warning.cc +--- gfx/harfbuzz/src_old/hb-warning.cc 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/hb-warning.cc 2016-06-05 23:50:54.795523196 +0200 +@@ -29,27 +29,11 @@ + + + #if defined(HB_ATOMIC_INT_NIL) +-#ifdef _MSC_VER +-#pragma message("Could not find any system to define atomic_int macros, library may NOT be thread-safe") +-#else +-#warning "Could not find any system to define atomic_int macros, library may NOT be thread-safe" +-#endif ++#error "Could not find any system to define atomic_int macros, library WILL NOT be thread-safe" ++#error "Check hb-atomic-private.hh for possible resolutions." + #endif + + #if defined(HB_MUTEX_IMPL_NIL) +-#ifdef _MSC_VER +-#pragma message("Could not find any system to define mutex macros, library may NOT be thread-safe") +-#else +-#warning "Could not find any system to define mutex macros, library may NOT be thread-safe" +-#endif +-#endif +- +-#if defined(HB_ATOMIC_INT_NIL) || defined(HB_MUTEX_IMPL_NIL) +-#ifdef _MSC_VER +-#pragma message("To suppress these warnings, define HB_NO_MT") +-#else +-#warning "To suppress these warnings, define HB_NO_MT" ++#error "Could not find any system to define mutex macros, library WILL NOT be thread-safe" ++#error "Check hb-mutex-private.hh for possible resolutions." + #endif +-#endif +- +- +diff -uN gfx/harfbuzz/src_old/Makefile.am gfx/harfbuzz/src/Makefile.am +--- gfx/harfbuzz/src_old/Makefile.am 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/Makefile.am 2016-06-05 23:47:56.984478616 +0200 +@@ -13,10 +13,16 @@ + # The following warning options are useful for debugging: -Wpadded + #AM_CXXFLAGS = + ++# Convenience targets: ++lib: $(BUILT_SOURCES) libharfbuzz.la ++fuzzing: $(BUILT_SOURCES) libharfbuzz-fuzzing.la ++ + lib_LTLIBRARIES = libharfbuzz.la + + HBCFLAGS = + HBLIBS = ++HBNONPCLIBS = ++HBDEPS = + HBSOURCES = \ + hb-atomic-private.hh \ + hb-blob.cc \ +@@ -36,11 +42,13 @@ + hb-open-file-private.hh \ + hb-open-type-private.hh \ + hb-ot-cmap-table.hh \ ++ hb-ot-glyf-table.hh \ + hb-ot-head-table.hh \ + hb-ot-hhea-table.hh \ + hb-ot-hmtx-table.hh \ + hb-ot-maxp-table.hh \ + hb-ot-name-table.hh \ ++ hb-ot-os2-table.hh \ + hb-ot-tag.cc \ + hb-private.hh \ + hb-set-private.hh \ +@@ -90,6 +98,7 @@ + hb-ot-shape.cc \ + hb-ot-shape-complex-arabic.cc \ + hb-ot-shape-complex-arabic-fallback.hh \ ++ hb-ot-shape-complex-arabic-private.hh \ + hb-ot-shape-complex-arabic-table.hh \ + hb-ot-shape-complex-arabic-win1256.hh \ + hb-ot-shape-complex-default.cc \ +@@ -101,10 +110,12 @@ + hb-ot-shape-complex-indic-table.cc \ + hb-ot-shape-complex-myanmar.cc \ + hb-ot-shape-complex-myanmar-machine.hh \ +- hb-ot-shape-complex-sea.cc \ +- hb-ot-shape-complex-sea-machine.hh \ + hb-ot-shape-complex-thai.cc \ + hb-ot-shape-complex-tibetan.cc \ ++ hb-ot-shape-complex-use.cc \ ++ hb-ot-shape-complex-use-machine.hh \ ++ hb-ot-shape-complex-use-private.hh \ ++ hb-ot-shape-complex-use-table.cc \ + hb-ot-shape-complex-private.hh \ + hb-ot-shape-normalize-private.hh \ + hb-ot-shape-normalize.cc \ +@@ -127,12 +138,13 @@ + + if HAVE_PTHREAD + HBCFLAGS += $(PTHREAD_CFLAGS) +-HBLIBS += $(PTHREAD_LIBS) ++HBNONPCLIBS += $(PTHREAD_LIBS) + endif + + if HAVE_GLIB + HBCFLAGS += $(GLIB_CFLAGS) + HBLIBS += $(GLIB_LIBS) ++HBDEPS += $(GLIB_DEPS) + HBSOURCES += hb-glib.cc + HBHEADERS += hb-glib.h + endif +@@ -140,6 +152,12 @@ + if HAVE_FREETYPE + HBCFLAGS += $(FREETYPE_CFLAGS) + HBLIBS += $(FREETYPE_LIBS) ++# XXX ++# The following creates a recursive dependency on FreeType if FreeType is ++# built with HarfBuzz support enabled. Newer pkg-config handles that just ++# fine but pkg-config 0.26 as shipped in Ubuntu 14.04 crashes. Remove ++# in a year or two, or otherwise work around it... ++#HBDEPS += $(FREETYPE_DEPS) + HBSOURCES += hb-ft.cc + HBHEADERS += hb-ft.h + endif +@@ -147,20 +165,21 @@ + if HAVE_GRAPHITE2 + HBCFLAGS += $(GRAPHITE2_CFLAGS) + HBLIBS += $(GRAPHITE2_LIBS) ++HBDEPS += $(GRAPHITE2_DEPS) + HBSOURCES += hb-graphite2.cc + HBHEADERS += hb-graphite2.h + endif + + if HAVE_UNISCRIBE + HBCFLAGS += $(UNISCRIBE_CFLAGS) +-HBLIBS += $(UNISCRIBE_LIBS) ++HBNONPCLIBS += $(UNISCRIBE_LIBS) + HBSOURCES += hb-uniscribe.cc + HBHEADERS += hb-uniscribe.h + endif + + if HAVE_CORETEXT + HBCFLAGS += $(CORETEXT_CFLAGS) +-HBLIBS += $(CORETEXT_LIBS) ++HBNONPCLIBS += $(CORETEXT_LIBS) + HBSOURCES += hb-coretext.cc + HBHEADERS += hb-coretext.h + endif +@@ -176,6 +195,8 @@ + + # Put the library together + ++HBLIBS += $(HBNONPCLIBS) ++ + if OS_WIN32 + export_symbols = -export-symbols harfbuzz.def + harfbuzz_def_dependency = harfbuzz.def +@@ -200,6 +221,22 @@ + pkgconfig_DATA = harfbuzz.pc + EXTRA_DIST += harfbuzz.pc.in + ++FUZZING_CPPFLAGS= \ ++ -DHB_MAX_NESTING_LEVEL=3 \ ++ -DHB_SANITIZE_MAX_EDITS=3 \ ++ -DHB_BUFFER_MAX_EXPANSION_FACTOR=3 \ ++ -DHB_BUFFER_MAX_LEN_MIN=8 \ ++ -DHB_BUFFER_MAX_LEN_DEFAULT=128 \ ++ $(NULL) ++EXTRA_LTLIBRARIES = libharfbuzz-fuzzing.la ++libharfbuzz_fuzzing_la_LINK = $(libharfbuzz_la_LINK) ++libharfbuzz_fuzzing_la_SOURCES = $(libharfbuzz_la_SOURCES) ++libharfbuzz_fuzzing_la_CPPFLAGS = $(libharfbuzz_la_CPPFLAGS) $(FUZZING_CPPFLAGS) ++libharfbuzz_fuzzing_la_LDFLAGS = $(libharfbuzz_la_LDFLAGS) ++libharfbuzz_fuzzing_la_LIBADD = $(libharfbuzz_la_LIBADD) ++EXTRA_libharfbuzz_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_la_DEPENDENCIES) ++CLEANFILES += libharfbuzz-fuzzing.la ++ + if HAVE_ICU + lib_LTLIBRARIES += libharfbuzz-icu.la + libharfbuzz_icu_la_SOURCES = hb-icu.cc +@@ -250,6 +287,8 @@ + -e 's@%exec_prefix%@$(exec_prefix)@g' \ + -e 's@%libdir%@$(libdir)@g' \ + -e 's@%includedir%@$(includedir)@g' \ ++ -e 's@%libs_private%@$(HBNONPCLIBS)@g' \ ++ -e 's@%requires_private%@$(HBDEPS)@g' \ + -e 's@%VERSION%@$(VERSION)@g' \ + "$<" > "$@" \ + || ($(RM) "$@"; false) +@@ -264,7 +303,7 @@ + $(EGREP) '^hb_.* \(' | \ + sed -e 's/ (.*//' | \ + LANG=C sort; \ +- echo LIBRARY libharfbuzz-$(HB_VERSION_MAJOR).dll; \ ++ echo LIBRARY libharfbuzz-0.dll; \ + ) >"$@" + @ ! grep -q hb_ERROR "$@" \ + || ($(RM) "$@"; false) +@@ -273,29 +312,34 @@ + GENERATORS = \ + gen-arabic-table.py \ + gen-indic-table.py \ ++ gen-use-table.py \ + $(NULL) + EXTRA_DIST += $(GENERATORS) + +-unicode-tables: arabic-table indic-table +- +-indic-table: gen-indic-table.py IndicSyllabicCategory.txt IndicMatraCategory.txt Blocks.txt +- $(AM_V_GEN) $(builddir)/$^ > hb-ot-shape-complex-indic-table.cc \ +- || ($(RM) hb-ot-shape-complex-indic-table.cc; false) ++unicode-tables: arabic-table indic-table use-table + + arabic-table: gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt + $(AM_V_GEN) $(builddir)/$^ > hb-ot-shape-complex-arabic-table.hh \ + || ($(RM) hb-ot-shape-complex-arabic-table.hh; false) + ++indic-table: gen-indic-table.py IndicSyllabicCategory-7.0.0.txt IndicMatraCategory-7.0.0.txt Blocks.txt ++ $(AM_V_GEN) $(builddir)/$^ > hb-ot-shape-complex-indic-table.cc \ ++ || ($(RM) hb-ot-shape-complex-indic-table.cc; false) ++ ++use-table: gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt ++ $(AM_V_GEN) $(builddir)/$^ > hb-ot-shape-complex-use-table.cc \ ++ || ($(RM) hb-ot-shape-complex-use-table.cc; false) ++ + built-sources: $(BUILT_SOURCES) + +-.PHONY: unicode-tables arabic-table indic-table built-sources ++.PHONY: unicode-tables arabic-table indic-table use-table built-sources + + RAGEL_GENERATED = \ + $(srcdir)/hb-buffer-deserialize-json.hh \ + $(srcdir)/hb-buffer-deserialize-text.hh \ + $(srcdir)/hb-ot-shape-complex-indic-machine.hh \ + $(srcdir)/hb-ot-shape-complex-myanmar-machine.hh \ +- $(srcdir)/hb-ot-shape-complex-sea-machine.hh \ ++ $(srcdir)/hb-ot-shape-complex-use-machine.hh \ + $(NULL) + BUILT_SOURCES += $(RAGEL_GENERATED) + EXTRA_DIST += \ +@@ -303,7 +347,7 @@ + hb-buffer-deserialize-text.rl \ + hb-ot-shape-complex-indic-machine.rl \ + hb-ot-shape-complex-myanmar-machine.rl \ +- hb-ot-shape-complex-sea-machine.rl \ ++ hb-ot-shape-complex-use-machine.rl \ + $(NULL) + MAINTAINERCLEANFILES += $(RAGEL_GENERATED) + $(srcdir)/%.hh: $(srcdir)/%.rl +@@ -349,7 +393,14 @@ + check-symbols.sh \ + $(NULL) + +-TESTS = $(dist_check_SCRIPTS) ++check_PROGRAMS = \ ++ test-ot-tag \ ++ $(NULL) ++test_ot_tag_SOURCES = hb-ot-tag.cc ++test_ot_tag_CPPFLAGS = $(HBCFLAGS) -DMAIN ++test_ot_tag_LDADD = libharfbuzz.la $(HBLIBS) ++ ++TESTS = $(dist_check_SCRIPTS) $(check_PROGRAMS) + TESTS_ENVIRONMENT = \ + srcdir="$(srcdir)" \ + MAKE="$(MAKE) $(AM_MAKEFLAGS)" \ +@@ -360,7 +411,7 @@ + if HAVE_INTROSPECTION + + -include $(INTROSPECTION_MAKEFILE) +-INTROSPECTION_GIRS = HarfBuzz-$(HB_VERSION_MAJOR).0.gir # What does the 0 mean anyway?! ++INTROSPECTION_GIRS = HarfBuzz-0.0.gir # What does the 0 mean anyway?! + INTROSPECTION_SCANNER_ARGS = -I$(srcdir) -n hb --identifier-prefix=hb_ --warn-all + INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir) + INTROSPECTION_SCANNER_ENV = CC="$(CC)" +@@ -376,6 +427,7 @@ + -DHB_OT_H_IN \ + -DHB_GOBJECT_H \ + -DHB_GOBJECT_H_IN \ ++ -DHB_EXTERN= \ + $(NULL) + HarfBuzz_0_0_gir_LIBS = \ + libharfbuzz.la \ +diff -uN gfx/harfbuzz/src_old/Makefile.in gfx/harfbuzz/src/Makefile.in +--- gfx/harfbuzz/src_old/Makefile.in 2016-05-10 22:26:55.000000000 +0200 ++++ gfx/harfbuzz/src/Makefile.in 1970-01-01 01:00:00.000000000 +0100 +@@ -1,31 +0,0 @@ +-# +-# Copyright (C) 2010 Mozilla Foundation +-# +-# This is used to integrate the HarfBuzz library with the GNU build. +-# +-# Permission is hereby granted, without written agreement and without +-# license or royalty fees, to use, copy, modify, and distribute this +-# software and its documentation for any purpose, provided that the +-# above copyright notice and the following two paragraphs appear in +-# all copies of this software. +-# +-# IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR +-# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +-# ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN +-# IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +-# DAMAGE. +-# +-# THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, +-# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +-# FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +-# ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO +-# PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +-# +-# GNU author(s): Jonathan Kew +-# +- +-include $(topsrcdir)/config/rules.mk +- +-# Cancel the effect of the -DDEBUG macro if present, +-# because harfbuzz uses that name for its own purposes +-COMPILE_CXXFLAGS += -UDEBUG +diff -uN gfx/harfbuzz/src_old/moz.build gfx/harfbuzz/src/moz.build +--- gfx/harfbuzz/src_old/moz.build 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/moz.build 2016-06-05 23:50:58.630503774 +0200 +@@ -29,7 +29,7 @@ + 'hb-common.cc', # error: use of undeclared identifier 'strdup' + 'hb-ot-shape-complex-hangul.cc', # error: redefinition of enumerator 'NONE' + 'hb-ot-shape-complex-indic.cc', # error: redefinition of enumerator 'INIT' +- 'hb-ot-shape-complex-sea.cc', # error: redefinition of 'basic_features' ++ 'hb-ot-shape-complex-use.cc', # error: redefinition of 'basic_features' + 'hb-ot-shape.cc', # error: functions that differ only in their return type cannot be overloaded + 'hb-shape-plan.cc', # error: redefinition of 'hb_ot_shaper_face_data_ensure' + ] +@@ -48,6 +48,7 @@ + 'hb-ot-shape-complex-myanmar.cc', + 'hb-ot-shape-complex-thai.cc', + 'hb-ot-shape-complex-tibetan.cc', ++ 'hb-ot-shape-complex-use-table.cc', + 'hb-ot-shape-fallback.cc', + 'hb-ot-shape-normalize.cc', + 'hb-ot-tag.cc', +@@ -58,7 +59,8 @@ + 'hb-warning.cc', + ] + +-MSVC_ENABLE_PGO = True ++# We allow warnings for third-party code that can be updated from upstream. ++FAIL_ON_WARNINGS = True + + FINAL_LIBRARY = 'gkmedias' + +@@ -67,3 +69,6 @@ + DEFINES['HAVE_OT'] = 1 + DEFINES['HB_NO_MT'] = True + DEFINES['HB_NO_UNICODE_FUNCS'] = True ++# Cancel the effect of the -DDEBUG macro if present, ++# because harfbuzz uses that name for its own purposes ++DEFINES['DEBUG'] = False +diff -uN gfx/harfbuzz/src_old/sample.py gfx/harfbuzz/src/sample.py +--- gfx/harfbuzz/src_old/sample.py 1970-01-01 01:00:00.000000000 +0100 ++++ gfx/harfbuzz/src/sample.py 2016-06-05 23:50:59.856497586 +0200 +@@ -0,0 +1,58 @@ ++#!/usr/bin/python ++# -*- coding: utf-8 -*- ++ ++from __future__ import print_function ++import sys ++from gi.repository import HarfBuzz as hb ++from gi.repository import GLib ++ ++# Python 2/3 compatibility ++try: ++ unicode ++except NameError: ++ unicode = str ++ ++def tounicode(s, encoding='utf-8'): ++ if not isinstance(s, unicode): ++ return s.decode(encoding) ++ else: ++ return s ++ ++fontdata = open (sys.argv[1], 'rb').read () ++text = tounicode(sys.argv[2]) ++# Need to create GLib.Bytes explicitly until this bug is fixed: ++# https://bugzilla.gnome.org/show_bug.cgi?id=729541 ++blob = hb.glib_blob_create (GLib.Bytes.new (fontdata)) ++face = hb.face_create (blob, 0) ++del blob ++font = hb.font_create (face) ++upem = hb.face_get_upem (face) ++del face ++hb.font_set_scale (font, upem, upem) ++#hb.ft_font_set_funcs (font) ++hb.ot_font_set_funcs (font) ++ ++buf = hb.buffer_create () ++class Debugger(object): ++ def message (self, buf, font, msg, data, _x_what_is_this): ++ print(msg) ++ return True ++debugger = Debugger() ++hb.buffer_set_message_func (buf, debugger.message, 1, 0) ++hb.buffer_add_utf8 (buf, text.encode('utf-8'), 0, -1) ++hb.buffer_guess_segment_properties (buf) ++ ++hb.shape (font, buf, []) ++del font ++ ++infos = hb.buffer_get_glyph_infos (buf) ++positions = hb.buffer_get_glyph_positions (buf) ++ ++for info,pos in zip(infos, positions): ++ gid = info.codepoint ++ cluster = info.cluster ++ x_advance = pos.x_advance ++ x_offset = pos.x_offset ++ y_offset = pos.y_offset ++ ++ print("gid%d=%d@%d,%d+%d" % (gid, cluster, x_advance, x_offset, y_offset)) +diff -uN gfx/harfbuzz/src_old/test.cc gfx/harfbuzz/src/test.cc +--- gfx/harfbuzz/src_old/test.cc 2016-05-10 22:26:56.000000000 +0200 ++++ gfx/harfbuzz/src/test.cc 2016-06-05 23:51:04.705473120 +0200 +@@ -120,7 +120,7 @@ + info->cluster, + info->codepoint, + pos->x_offset, +- pos->x_offset, ++ pos->y_offset, + pos->x_advance, + pos->y_advance); + |