summaryrefslogtreecommitdiff
path: root/pcr
diff options
context:
space:
mode:
Diffstat (limited to 'pcr')
-rw-r--r--pcr/icedove-hardening/PKGBUILD206
-rw-r--r--pcr/icedove-hardening/changing-the-default-search-engine.patch40
-rw-r--r--pcr/icedove-hardening/firefox-gcc-6.0.patch26
-rw-r--r--pcr/icedove-hardening/fix-missing-files.patch38
-rw-r--r--pcr/icedove-hardening/icedove.desktop173
-rw-r--r--pcr/icedove-hardening/icedove.install36
-rw-r--r--pcr/icedove-hardening/mozconfig39
-rw-r--r--pcr/icedove-hardening/mozilla-1228540-1.patch84
-rw-r--r--pcr/icedove-hardening/mozilla-1228540.patch6032
-rw-r--r--pcr/icedove-hardening/mozilla-1253216.patch12
-rw-r--r--pcr/icedove-hardening/no-neon.patch96
-rw-r--r--pcr/icedove-hardening/vendor.js231
-rw-r--r--pcr/iceweasel-hardening/PKGBUILD213
-rw-r--r--pcr/iceweasel-hardening/drm-free.pngbin0 -> 3213 bytes
-rw-r--r--pcr/iceweasel-hardening/enable-object-directory-paths.patch13
-rw-r--r--pcr/iceweasel-hardening/gnu_headshadow.pngbin0 -> 6785 bytes
-rw-r--r--pcr/iceweasel-hardening/iceweasel-install-dir.patch13
-rw-r--r--pcr/iceweasel-hardening/iceweasel.desktop310
-rw-r--r--pcr/iceweasel-hardening/iceweasel.install31
-rw-r--r--pcr/iceweasel-hardening/libre.patch338
-rw-r--r--pcr/iceweasel-hardening/mozconfig46
-rw-r--r--pcr/iceweasel-hardening/mozilla-1253216.patch12
-rw-r--r--pcr/iceweasel-hardening/mozilla-build-arm.patch24
-rw-r--r--pcr/iceweasel-hardening/remove-default-and-shell-icons-in-packaging-manifest.patch34
-rw-r--r--pcr/iceweasel-hardening/vendor.js351
25 files changed, 8398 insertions, 0 deletions
diff --git a/pcr/icedove-hardening/PKGBUILD b/pcr/icedove-hardening/PKGBUILD
new file mode 100644
index 000000000..6ce8d46eb
--- /dev/null
+++ b/pcr/icedove-hardening/PKGBUILD
@@ -0,0 +1,206 @@
+# Maintainer: André Silva <emulatorman@parabola.nu>
+# Contributor: Márcio Silva <coadde@parabola.nu>
+# Contributor: Luke R. <g4jc@openmailbox.org>
+# Contributor: Isaac David <isacdaavid@isacdaavid.info>
+
+# We're getting this from Debian Sid
+_debname=icedove
+_debver=45.4.0
+_debrel=deb1
+_debrepo=http://ftp.debian.org/debian/pool/main/
+debfile() { echo $@|sed -r 's@(.).*@\1/&/&@'; }
+
+_pkgname=thunderbird
+pkgname=icedove-hardening
+epoch=1
+pkgver=$_debver.$_debrel
+pkgrel=1
+
+pkgdesc="A libre version of Debian Icedove, the standalone mail and news reader based on Mozilla Thunderbird, with several patches that were introduced to strengthen and protect the end user from security threats and without support for unsafe and dangerous for privacy protocols"
+arch=(i686 x86_64 armv7h)
+license=(MPL GPL LGPL)
+depends=(alsa-lib dbus-glib gtk2 hunspell icu=57.1 libevent libvpx=1.6.0 libxt mime-types mozilla-common nss sqlite startup-notification ttf-font)
+makedepends=(autoconf2.13 diffutils gconf imake inetutils libpulse mesa mozilla-searchplugins pkg-config python2 quilt unzip yasm zip)
+options=(!emptydirs !makeflags)
+optdepends=('libcanberra: for sound support')
+url="https://wiki.parabola.nu/${pkgname%-*}"
+replaces=("${pkgname%-*}-libre" "$_pkgname")
+conflicts=("${pkgname%-*}-libre" "$_pkgname" "${pkgname%-*}")
+provides=("$_pkgname" "${pkgname%-*}")
+install=${pkgname%-*}.install
+source=("$_debrepo/`debfile $_debname`_$_debver.orig.tar.xz"
+ "$_debrepo/`debfile $_debname`_$_debver-${_debrel#deb}.debian.tar.xz"
+ mozconfig
+ ${pkgname%-*}.desktop
+ changing-the-default-search-engine.patch
+ firefox-gcc-6.0.patch mozilla-1228540.patch mozilla-1228540-1.patch
+ vendor.js
+ fix-missing-files.patch
+ no-neon.patch
+ mozilla-1253216.patch)
+sha256sums=('00ff0dcd4bddd053b5285c78cd687876cfab9455c2eb1e670746eb4bedaac38f'
+ 'b4d1b193aee7481249ef5e638bf583b69c1785dd530a9ecd098a84f42dfdf09d'
+ 'aaca37bcca176d1b8ebe7c18d3fb0c61e3d21769fbf8e994a189eb3263257d3d'
+ '0b0d25067c64c6b829c84e5259ffca978e3971f85acc8483f47bdbed5b0b5b6a'
+ 'e1f72c44e31f191271207fc874dcfbf3d504b6b42dc1bb063ba8c7c9ee032130'
+ '4d1e1ddabc9e975ed39f49e134559a29e01cd49439e358233f1ede43bf5a52bf'
+ '3a3e84c702ee31450a3e84698441aceb11cf44e64c9fedcaddb8cb50db759417'
+ 'd1ccbaf0973615c57f7893355e5cd3a89efb4e91071d0ec376e429b50cf6ed19'
+ '173c929176262c0ad27984d68d61918d51d27bbc538ccbe9e6d19727d1f9de4d'
+ '294a2cc7b0477ad285af10ac2a04b767cabec07f03b23da23014bda71caea510'
+ '59f40d8b2480aa67bf76f4f119826b6828a6a59cc040caf1ab5a6e19eef44c6e'
+ '1e7ef08acd46aeacc8cd8b2c89012983fb2c8c18648e0f3e9371b0c76caedbde')
+
+prepare() {
+ cd "$srcdir/$_pkgname-$_debver"
+ mv "$srcdir/debian" .
+
+ export QUILT_PATCHES=debian/patches
+ export QUILT_REFRESH_ARGS='-p ab --no-timestamps --no-index'
+ export QUILT_DIFF_ARGS='--no-timestamps'
+
+ # Prepare branding for the Icedove packages
+ mkdir -v mail/branding/${pkgname%-*}
+
+ # Copy needed icons
+ cp -va debian/${pkgname%-*}-branding/* mail/branding/${pkgname%-*}
+ for i in 16 22 24 32 48 256; do
+ install -Dm644 debian/app-icons/${pkgname%-*}$i.png \
+ mail/branding/${pkgname%-*}/mailicon$i.png
+ done
+ for i in 48 64; do
+ install -Dm644 debian/app-icons/${pkgname%-*}$i.png \
+ mail/branding/${pkgname%-*}/content/icon$i.png
+ done
+ cp -av debian/preview.png mail/themes/linux/mail/preview.png
+
+ # Useless since we are doing it ourselves
+ rm -rv debian/patches/icedove-l10n || true
+ rm -rv debian/patches/iceowl-l10n || true
+ rm -v debian/patches/debian-hacks/changing-the-default-search-engine.patch || true
+
+ quilt push -av
+
+ # Fix missing files
+ patch -Np1 -i "$srcdir/fix-missing-files.patch"
+
+ # Remove url-classifier from package-manifest.in to build and disable Phishing Protection
+ sed -i '\|Phishing Protection|d
+ \|UrlClassifier|d
+ \|URLClassifier|d
+ \|url-classifier|d
+ ' mail/installer/package-manifest.in
+
+ # Fix branding
+ sed -i 's|Icedove Mail/News|Icedove|
+ ' mail/branding/icedove/locales/en-US/brand.{dtd,properties}
+
+ # Replace common URLs
+ sed -i '\|extensions[.]getAddons[.]get[.]url| s|https://services[.]addons[.]mozilla[.]org.\+["][)][;]|https://directory.fsf.org/wiki/Icedove");|g;
+ \|extensions[.]getAddons[.]search[.]browseURL| s|https://addons[.]mozilla[.]org.\+["][)][;]|https://directory.fsf.org/wiki/Icedove");|g;
+ \|extensions[.]getAddons[.]search[.]url| s|https://services[.]addons[.]mozilla[.]org.\+["][)][;]|https://directory.fsf.org/wiki/Icedove");|g;
+ \|extensions[.]webservice[.]discoverURL| s|https://services[.]addons[.]mozilla[.]org.\+["][)][;]|https://directory.fsf.org/wiki/Icedove");|g;
+ ' mail/app/profile/all-thunderbird.js
+
+ # Remove support for unsafe and dangerous for privacy protocols
+ sed -i '\|facebook|d
+ \|gtalk|d
+ \|odnoklassniki|d
+ \|twitter|d
+ \|yahoo|d
+ ' chat/moz.build
+ sed -i '\|facebook[.]js|d
+ \|facebook[.]manifest|d
+ \|gtalk[.]js|d
+ \|gtalk[.]manifest|d
+ \|twitter[.]js|d
+ \|twitter[.]manifest|d
+ \|yahoo[.]js|d
+ \|yahoo[.]manifest|d
+ ' mail/installer/package-manifest.in
+ rm -rv chat/protocols/{facebook,gtalk,twitter,yahoo}
+
+ # Required for GCC 6
+ patch -d mozilla -Np1 < ../firefox-gcc-6.0.patch
+ patch -d mozilla -Np1 < ../mozilla-1228540.patch
+ patch -d mozilla -Np1 < ../mozilla-1228540-1.patch
+
+ cp -v "$srcdir/mozconfig" .mozconfig
+
+ mkdir "$srcdir/path"
+ ln -s /usr/bin/python2 "$srcdir/path/python"
+
+ # Change the default search engine using our system-provided searchplugins
+ patch -Np1 -i "$srcdir/changing-the-default-search-engine.patch"
+
+ # Load our searchplugins
+ rm -rv mail/locales/en-US/searchplugins
+ cp -av /usr/lib/mozilla/searchplugins mail/locales/en-US
+
+ # ARM-specific changes:
+ if [[ "$CARCH" == arm* ]]; then
+ patch -Np0 -i ../no-neon.patch
+ patch -p2 -d mozilla < ../mozilla-1253216.patch
+ sed -i '/ac_add_options --enable-gold/d' .mozconfig
+ cat >> .mozconfig <<- EOF
+ ac_add_options --disable-elf-hack
+ ac_add_options --disable-neon
+ ac_add_options --disable-ion
+ ac_add_options --disable-webrtc
+ ac_add_options --disable-debug
+ ac_add_options --disable-debug-symbols
+ EOF
+ fi
+}
+
+build() {
+ cd "$srcdir/$_pkgname-$_debver"
+
+ # _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"
+
+ export PATH="$srcdir/path:$PATH"
+
+ make -f client.mk build
+}
+
+package() {
+ cd "$srcdir/$_pkgname-$_debver"
+ make -f client.mk DESTDIR="$pkgdir" INSTALL_SDK= install
+
+ install -Dm644 ../vendor.js "$pkgdir/usr/lib/${pkgname%-*}/defaults/preferences/vendor.js"
+
+ # Install Icedove menu icon
+ install -Dm644 debian/${pkgname%-*}.xpm "$pkgdir/usr/share/pixmaps/${pkgname%-*}.xpm"
+
+ # Install Icedove icons
+ brandingdir=debian/app-icons
+ icondir="$pkgdir/usr/share/icons/hicolor"
+ for i in 16 22 24 32 48 64 128 256; do
+ install -Dm644 "$brandingdir/${pkgname%-*}$i.png" \
+ "$icondir/${i}x${i}/apps/${pkgname%-*}.png"
+ done
+ install -Dm644 "$brandingdir/${pkgname}big.svg" \
+ "$icondir/scalable/apps/${pkgname%-*}.svg"
+
+ # Install Icedove desktop
+ install -d "$pkgdir/usr/share/applications"
+ install -m644 "$srcdir/${pkgname%-*}.desktop" \
+ "$pkgdir/usr/share/applications"
+
+ # Use system-provided dictionaries
+ rm -rf "$pkgdir/usr/lib/${pkgname%-*}/"{dictionaries,hyphenation}
+ ln -s /usr/share/hunspell "$pkgdir/usr/lib/${pkgname%-*}/dictionaries"
+ ln -s /usr/share/hyphen "$pkgdir/usr/lib/${pkgname%-*}/hyphenation"
+
+ # Replace duplicate binary with symlink
+ # https://bugzilla.mozilla.org/show_bug.cgi?id=658850
+ ln -sf ${pkgname%-*} "$pkgdir/usr/lib/${pkgname%-*}/${pkgname%-*}-bin"
+}
diff --git a/pcr/icedove-hardening/changing-the-default-search-engine.patch b/pcr/icedove-hardening/changing-the-default-search-engine.patch
new file mode 100644
index 000000000..37df3e851
--- /dev/null
+++ b/pcr/icedove-hardening/changing-the-default-search-engine.patch
@@ -0,0 +1,40 @@
+diff --git a/mail/locales/en-US/chrome/messenger-region/region.properties b/mail/locales/en-US/chrome/messenger-region/region.properties
+index fcc870d..f810450 100644
+--- a/mail/locales/en-US/chrome/messenger-region/region.properties
++++ b/mail/locales/en-US/chrome/messenger-region/region.properties
+@@ -3,12 +3,12 @@
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+ # Default search engine
+-browser.search.defaultenginename=Bing
++browser.search.defaultenginename=searx
+
+ # Search engine order (order displayed in the search bar dropdown)s
+-browser.search.order.1=Bing
+-browser.search.order.2=Yahoo
+-browser.search.order.3=
++browser.search.order.1=searx
++browser.search.order.2=DuckDuckGo HTML
++browser.search.order.3=DuckDuckGo Lite
+
+ # To make mapit buttons to disappear in the addressbook, specify empty string. For example:
+ # mail.addr_book.mapit_url.format=
+@@ -23,14 +23,12 @@ browser.search.order.3=
+ # @ZI == zip code
+ # @CO == country
+ # Default map service:
+-mail.addr_book.mapit_url.format=http://maps.google.com/maps?q=@A1%20@A2%20@CI%20@ST%20@ZI%20@CO
++mail.addr_book.mapit_url.format=http://nominatim.openstreetmap.org/search.php?polygon=1&q=@A1%2C@A2%2C@CI%2C@ST%2C@ZI%2C@CO
+ # List of available map services (up to 5 can be defined here):
+-mail.addr_book.mapit_url.1.name=Google Maps
+-mail.addr_book.mapit_url.1.format=http://maps.google.com/maps?q=@A1%20@A2%20@CI%20@ST%20@ZI%20@CO
+-mail.addr_book.mapit_url.2.name=OpenStreetMap
+-mail.addr_book.mapit_url.2.format=http://nominatim.openstreetmap.org/search.php?polygon=1&q=@A1%2C@A2%2C@CI%2C@ST%2C@ZI%2C@CO
++mail.addr_book.mapit_url.1.name=OpenStreetMap
++mail.addr_book.mapit_url.1.format=http://nominatim.openstreetmap.org/search.php?polygon=1&q=@A1%2C@A2%2C@CI%2C@ST%2C@ZI%2C@CO
+
+-mailnews.messageid_browser.url=http://groups.google.com/search?as_umsgid=%mid
++mailnews.messageid_browser.url=
+
+ # Recognize non-standard versions of "Re:" in subjects from localized versions of MS Outlook et al.
+ # Specify a comma-separated list without spaces. For example: mailnews.localizedRe=AW,SV
diff --git a/pcr/icedove-hardening/firefox-gcc-6.0.patch b/pcr/icedove-hardening/firefox-gcc-6.0.patch
new file mode 100644
index 000000000..0a74d3616
--- /dev/null
+++ b/pcr/icedove-hardening/firefox-gcc-6.0.patch
@@ -0,0 +1,26 @@
+diff -up firefox-44.0/nsprpub/config/make-system-wrappers.pl.back firefox-44.0/nsprpub/config/make-system-wrappers.pl
+--- firefox-44.0/nsprpub/config/make-system-wrappers.pl.back 2016-01-24 00:23:49.000000000 +0100
++++ firefox-44.0/nsprpub/config/make-system-wrappers.pl 2016-02-02 14:58:45.064112655 +0100
+@@ -19,7 +19,9 @@ while (<STDIN>) {
+ open OUT, ">$output_dir/$_";
+ print OUT "#pragma GCC system_header\n"; # suppress include_next warning
+ print OUT "#pragma GCC visibility push(default)\n";
++ print OUT "#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS\n";
+ print OUT "#include_next \<$_\>\n";
++ print OUT "#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS\n";
+ print OUT "#pragma GCC visibility pop\n";
+ close OUT;
+ }
+diff -up firefox-44.0/mozglue/build/arm.cpp.old firefox-44.0/mozglue/build/arm.cpp
+--- firefox-44.0/mozglue/build/arm.cpp.old 2016-02-03 10:07:29.879526500 +0100
++++ firefox-44.0/mozglue/build/arm.cpp 2016-02-03 10:08:11.062697517 +0100
+@@ -104,7 +104,9 @@ check_neon(void)
+
+ # elif defined(__linux__) || defined(ANDROID)
+ # include <stdio.h>
++#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS
+ # include <stdlib.h>
++#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS
+ # include <string.h>
+
+ enum{
diff --git a/pcr/icedove-hardening/fix-missing-files.patch b/pcr/icedove-hardening/fix-missing-files.patch
new file mode 100644
index 000000000..04cf3d35e
--- /dev/null
+++ b/pcr/icedove-hardening/fix-missing-files.patch
@@ -0,0 +1,38 @@
+diff --git a/mailnews/base/test/unit/xpcshell.ini b/mailnews/base/test/unit/xpcshell.ini
+index 9644fdf..f098fad 100644
+--- a/mailnews/base/test/unit/xpcshell.ini
++++ b/mailnews/base/test/unit/xpcshell.ini
+@@ -19,7 +19,6 @@ support-files = nodelist_test.xml data/*
+ [test_bug471682.js]
+ [test_bug514945.js]
+ [test_compactFailure.js]
+-[test_compactColumnSave.js]
+ [test_copyChaining.js]
+ [test_copyThenMoveManual.js]
+ [test_copyToInvalidDB.js]
+diff --git a/mozilla/intl/uconv/tests/moz.build b/mozilla/intl/uconv/tests/moz.build
+index 4223d2e..fae03f4 100644
+--- a/mozilla/intl/uconv/tests/moz.build
++++ b/mozilla/intl/uconv/tests/moz.build
+@@ -4,8 +4,6 @@
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+-XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
+-
+ # Tests disabled because they dont work in libxul builds.
+ #MOZILLA_INTERNAL_API = True
+ #
+diff --git a/mozilla/parser/xml/moz.build b/mozilla/parser/xml/moz.build
+index 484f6d1..d072795 100644
+--- a/mozilla/parser/xml/moz.build
++++ b/mozilla/parser/xml/moz.build
+@@ -4,8 +4,6 @@
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+-TEST_DIRS += ['test']
+-
+ XPIDL_SOURCES += [
+ 'nsIMozSAXXMLDeclarationHandler.idl',
+ 'nsISAXAttributes.idl',
diff --git a/pcr/icedove-hardening/icedove.desktop b/pcr/icedove-hardening/icedove.desktop
new file mode 100644
index 000000000..1ba43e0b3
--- /dev/null
+++ b/pcr/icedove-hardening/icedove.desktop
@@ -0,0 +1,173 @@
+[Desktop Entry]
+Name=Icedove
+Comment=Send and receive mail with Icedove
+Comment[ast]=Lleer y escribir corréu electrónicu
+Comment[ca]=Llegiu i escriviu correu
+Comment[cs]=Čtení a psaní pošty
+Comment[da]=Skriv/læs e-post/nyhedsgruppe med Icedove
+Comment[de]=E-Mails und Nachrichten mit Icedove lesen und schreiben
+Comment[el]=Διαβάστε και γράψτε γράμματα με το Icedove
+Comment[es]=Lea y escriba correos y noticias con Icedove
+Comment[fi]=Lue ja kirjoita sähköposteja
+Comment[fr]=Lire et écrire des courriels
+Comment[gl]=Lea e escriba correo electrónico
+Comment[he]=קריאה/כתיבה של דוא״ל/חדשות באמצעות Icedove
+Comment[hr]=Čitajte/šaljite e-poštu s Icedove
+Comment[hu]=Levelek írása és olvasása a Icedove
+Comment[it]=Per leggere e scrivere email
+Comment[ja]=メールの読み書き
+Comment[ko]=Icedove 메일/뉴스 읽기 및 쓰기 클라이언트
+Comment[nl]=E-mail/nieuws lezen en schrijven met Icedove
+Comment[pl]=Czytanie i wysyłanie e-maili
+Comment[pt_BR]=Leia e escreva suas mensagens
+Comment[ru]=Читайте и пишите письма
+Comment[sk]=Čítajte a píšte poštu pomocou programu Icedove
+Comment[sv]=Läs och skriv e-post
+Comment[ug]=ئېلخەت ۋە خەۋەرلەرنى Icedove دا كۆرۈش ۋە يېزىش
+Comment[uk]=Читання та написання листів
+Comment[vi]=Đọc và soạn thư điện tử
+Comment[zh_CN]=阅读邮件或新闻
+Comment[zh_TW]=以 Icedove 讀寫郵件或新聞
+GenericName=Mail Client
+GenericName[ast]=Client de correu
+GenericName[ca]=Client de correu
+GenericName[cs]=Poštovní klient
+GenericName[da]=E-postklient
+GenericName[de]=E-Mail-Anwendung
+GenericName[el]=Λογισμικό αλληλογραφίας
+GenericName[es]=Cliente de correo
+GenericName[fi]=Sähköpostiohjelma
+GenericName[fr]=Client de messagerie
+GenericName[gl]=Cliente de correo electrónico
+GenericName[he]=לקוח דוא״ל
+GenericName[hr]=Klijent e-pošte
+GenericName[hu]=Levelezőkliens
+GenericName[it]=Client email
+GenericName[ja]=電子メールクライアント
+GenericName[ko]=메일 클라이언트
+GenericName[nl]=E-mailprogramma
+GenericName[pl]=Klient poczty
+GenericName[pt_BR]=Cliente de E-mail
+GenericName[ru]=Почтовый клиент
+GenericName[sk]=Poštový klient
+GenericName[ug]=ئېلخەت دېتالى
+GenericName[uk]=Поштова програма
+GenericName[vi]=Phần mềm khách quản lý thư điện tử
+GenericName[zh_CN]=邮件新闻客户端
+GenericName[zh_TW]=郵件用戶端
+Exec=icedove %u
+Terminal=false
+Type=Application
+Icon=icedove
+Categories=Network;Email;
+MimeType=message/rfc822;x-scheme-handler/mailto;application/x-xpinstall;
+StartupNotify=true
+Actions=ComposeMessage;OpenAddressBook;
+
+[Desktop Action ComposeMessage]
+Name=Write new message
+Name[ar]=اكتب رسالة جديدة
+Name[ast]=Redactar mensaxe nuevu
+Name[be]=Напісаць новы ліст
+Name[bg]=Съставяне на ново съобщение
+Name[br]=Skrivañ ur gemennadenn nevez
+Name[ca]=Escriu un missatge nou
+Name[cs]=Napsat novou zprávu
+Name[da]=Skriv en ny meddelelse
+Name[de]=Neue Nachricht verfassen
+Name[el]=Σύνταξη νέου μηνύματος
+Name[es_AR]=Escribir un nuevo mensaje
+Name[es_ES]=Redactar nuevo mensaje
+Name[et]=Kirjuta uus kiri
+Name[eu]=Idatzi mezu berria
+Name[fi]=Kirjoita uusi viesti
+Name[fr]=Rédiger un nouveau message
+Name[fy_NL]=Skriuw in nij berjocht
+Name[ga_IE]=Scríobh teachtaireacht nua
+Name[gd]=Sgrìobh teachdaireachd ùr
+Name[gl]=Escribir unha nova mensaxe
+Name[he]=כתיבת הודעה חדשה
+Name[hr]=Piši novu poruku
+Name[hu]=Új üzenet írása
+Name[hy_AM]=Գրել նոր նամակ
+Name[is]=SKrifa nýjan póst
+Name[it]=Scrivi nuovo messaggio
+Name[ja]=新しいメッセージを作成する
+Name[ko]=새 메시지 작성
+Name[lt]=Rašyti naują laišką
+Name[nb_NO]=Skriv ny melding
+Name[nl]=Nieuw bericht aanmaken
+Name[nn_NO]=Skriv ny melding
+Name[pl]=Nowa wiadomość
+Name[pt_BR]=Nova mensagem
+Name[pt_PT]=Escrever nova mensagem
+Name[rm]=Scriver in nov messadi
+Name[ro]=Scrie un mesaj nou
+Name[ru]=Создать новое сообщение
+Name[si]=නව ලිපියක් ලියන්න
+Name[sk]=Nová e-mailová správa
+Name[sl]=Sestavi novo sporočilo
+Name[sq]=Shkruani mesazh të ri
+Name[sr]=Писање нове поруке
+Name[sv_SE]=Skriv ett nytt meddelande
+Name[ta_LK]=புதிய செய்தியை எழுதுக
+Name[tr]=Yeni ileti yaz
+Name[uk]=Написати нового листа
+Name[vi]=Viết thư mới
+Name[zh_CN]=编写新消息
+Name[zh_TW]=寫一封新訊息
+Exec=icedove -compose
+
+[Desktop Action OpenAddressBook]
+Name=Open address book
+Name[ar]=افتح دفتر العناوين
+Name[ast]=Abrir llibreta de direiciones
+Name[be]=Адкрыць адрасную кнігу
+Name[bg]=Отваряне на адресник
+Name[br]=Digeriñ ur c'harned chomlec'hioù
+Name[ca]=Obre la llibreta d'adreces
+Name[cs]=Otevřít Adresář
+Name[da]=Åbn adressebog
+Name[de]=Adressbuch öffnen
+Name[el]=Άνοιγμα ευρετηρίου διευθύνσεων
+Name[es_AR]=Abrir libreta de direcciones
+Name[es_ES]=Abrir libreta de direcciones
+Name[et]=Ava aadressiraamat
+Name[eu]=Ireki helbide-liburua
+Name[fi]=Avaa osoitekirja
+Name[fr]=Ouvrir un carnet d'adresses
+Name[fy_NL]=Iepenje adresboek
+Name[ga_IE]=Oscail leabhar seoltaí
+Name[gd]=Fosgail leabhar-sheòlaidhean
+Name[gl]=Abrir a axenda de enderezos
+Name[he]=פתיחת ספר כתובות
+Name[hr]=Otvori adresar
+Name[hu]=Címjegyzék megnyitása
+Name[hy_AM]=Բացել Հասցեագիրքը
+Name[is]=Opna nafnaskrá
+Name[it]=Apri rubrica
+Name[ja]=アドレス帳を開く
+Name[ko]=주소록 열기
+Name[lt]=Atverti adresų knygą
+Name[nb_NO]=Åpne adressebok
+Name[nl]=Adresboek openen
+Name[nn_NO]=Opne adressebok
+Name[pl]=Książka adresowa
+Name[pt_BR]=Catálogo de endereços
+Name[pt_PT]=Abrir livro de endereços
+Name[rm]=Avrir il cudeschet d'adressas
+Name[ro]=Deschide agenda de contacte
+Name[ru]=Открыть адресную книгу
+Name[si]=ලිපින පොත විවෘත කරන්න
+Name[sk]=Otvoriť adresár
+Name[sl]=Odpri adressar
+Name[sq]=Hapni libër adresash
+Name[sr]=Отвори адресар
+Name[sv_SE]=Öppna adressboken
+Name[ta_LK]=முகவரி பத்தகத்தை திறக்க
+Name[tr]=Adres defterini aç
+Name[uk]=Відкрити адресну книгу
+Name[vi]=Mở sổ địa chỉ
+Name[zh_CN]=打开通讯录
+Name[zh_TW]=開啟通訊錄
+Exec=icedove -addressbook
diff --git a/pcr/icedove-hardening/icedove.install b/pcr/icedove-hardening/icedove.install
new file mode 100644
index 000000000..af5f896b5
--- /dev/null
+++ b/pcr/icedove-hardening/icedove.install
@@ -0,0 +1,36 @@
+notice() {
+ cat <<EOM
+ == IMPORTANT NOTICE ==
+
+ This package contains several patches that were introduced
+ to strengthen and protect the end user from security threats.
+
+ For users who wish to opt-out of security, you may override options in
+ about:config using a user.js file in your ~/.icedove's profile folder.
+
+ Some user.js examples:
+ user_pref("mailnews.display.prefer_plaintext", false); # Enables possible HTML leaks
+ user_pref("purple.logging.log_chats", true); # Enables chat logging
+
+ Further reading:
+ * https://lists.parabola.nu/pipermail/dev/2016-October/004522.html
+ * http://kb.mozillazine.org/About:config
+ * http://kb.mozillazine.org/User.js_file
+
+EOM
+}
+
+post_install() {
+ update-desktop-database -q
+ gtk-update-icon-cache -q -t -f usr/share/icons/hicolor
+ notice
+}
+
+post_upgrade() {
+ post_install
+}
+
+post_remove() {
+ update-desktop-database -q
+ gtk-update-icon-cache -q -t -f usr/share/icons/hicolor
+}
diff --git a/pcr/icedove-hardening/mozconfig b/pcr/icedove-hardening/mozconfig
new file mode 100644
index 000000000..972b9ac0d
--- /dev/null
+++ b/pcr/icedove-hardening/mozconfig
@@ -0,0 +1,39 @@
+ac_add_options --enable-application=mail
+
+ac_add_options --prefix=/usr
+ac_add_options --libdir=/usr/lib
+ac_add_options --enable-release
+ac_add_options --enable-gold
+ac_add_options --enable-pie
+
+# Icedove
+ac_add_options --with-branding=mail/branding/icedove
+
+# System libraries
+ac_add_options --with-system-nspr
+ac_add_options --with-system-nss
+ac_add_options --with-system-icu
+ac_add_options --with-system-jpeg
+ac_add_options --with-system-zlib
+ac_add_options --with-system-bz2
+ac_add_options --with-system-libevent
+ac_add_options --with-system-libvpx
+ac_add_options --enable-system-hunspell
+ac_add_options --enable-system-sqlite
+ac_add_options --enable-system-ffi
+ac_add_options --enable-system-pixman
+
+# Features
+ac_add_options --enable-startup-notification
+ac_add_options --disable-gstreamer
+ac_add_options --disable-updater
+ac_add_options --disable-crashreporter
+
+STRIP_FLAGS="--strip-debug"
+
+# Parabola features
+ac_add_options --disable-official-branding
+ac_add_options --disable-safe-browsing
+ac_add_options --disable-url-classifier
+
+# vim:set ft=sh:
diff --git a/pcr/icedove-hardening/mozilla-1228540-1.patch b/pcr/icedove-hardening/mozilla-1228540-1.patch
new file mode 100644
index 000000000..be6ffc316
--- /dev/null
+++ b/pcr/icedove-hardening/mozilla-1228540-1.patch
@@ -0,0 +1,84 @@
+# HG changeset patch
+# User Jonathan Kew <jkew@mozilla.com>
+# Date 1452675061 0
+# Wed Jan 13 08:51:01 2016 +0000
+# Node ID cf699e95e98829b465b64a7e0281d95ec851ce8c
+# Parent 3c9f357598e86c2f593e9895d5725bf3498f8f5a
+Bug 1228540 - pt 2 - Remove our HBGetGlyphHOrigin callback, as the default behavior is sufficient.
+
+diff --git a/gfx/thebes/gfxHarfBuzzShaper.cpp b/gfx/thebes/gfxHarfBuzzShaper.cpp
+--- a/gfx/thebes/gfxHarfBuzzShaper.cpp
++++ b/gfx/thebes/gfxHarfBuzzShaper.cpp
+@@ -349,27 +349,16 @@ gfxHarfBuzzShaper::HBGetGlyphVAdvance(hb
+ static_cast<const gfxHarfBuzzShaper::FontCallbackData*>(font_data);
+ // Currently, we don't offer gfxFont subclasses a method to override this
+ // and provide hinted platform-specific vertical advances (analogous to the
+ // GetGlyphWidth method for horizontal advances). If that proves necessary,
+ // we'll add a new gfxFont method and call it from here.
+ return fcd->mShaper->GetGlyphVAdvance(glyph);
+ }
+
+-/* static */
+-hb_bool_t
+-gfxHarfBuzzShaper::HBGetGlyphHOrigin(hb_font_t *font, void *font_data,
+- hb_codepoint_t glyph,
+- hb_position_t *x, hb_position_t *y,
+- void *user_data)
+-{
+- // We work in horizontal coordinates, so no origin adjustment needed here.
+- return true;
+-}
+-
+ struct VORG {
+ AutoSwap_PRUint16 majorVersion;
+ AutoSwap_PRUint16 minorVersion;
+ AutoSwap_PRInt16 defaultVertOriginY;
+ AutoSwap_PRUint16 numVertOriginYMetrics;
+ };
+
+ struct VORGrec {
+@@ -1262,19 +1251,16 @@ gfxHarfBuzzShaper::Initialize()
+ hb_font_funcs_set_glyph_func(sHBFontFuncs, HBGetGlyph,
+ nullptr, nullptr);
+ hb_font_funcs_set_glyph_h_advance_func(sHBFontFuncs,
+ HBGetGlyphHAdvance,
+ nullptr, nullptr);
+ hb_font_funcs_set_glyph_v_advance_func(sHBFontFuncs,
+ HBGetGlyphVAdvance,
+ nullptr, nullptr);
+- hb_font_funcs_set_glyph_h_origin_func(sHBFontFuncs,
+- HBGetGlyphHOrigin,
+- nullptr, nullptr);
+ hb_font_funcs_set_glyph_v_origin_func(sHBFontFuncs,
+ HBGetGlyphVOrigin,
+ nullptr, nullptr);
+ hb_font_funcs_set_glyph_extents_func(sHBFontFuncs,
+ HBGetGlyphExtents,
+ nullptr, nullptr);
+ hb_font_funcs_set_glyph_contour_point_func(sHBFontFuncs,
+ HBGetContourPoint,
+diff --git a/gfx/thebes/gfxHarfBuzzShaper.h b/gfx/thebes/gfxHarfBuzzShaper.h
+--- a/gfx/thebes/gfxHarfBuzzShaper.h
++++ b/gfx/thebes/gfxHarfBuzzShaper.h
+@@ -56,21 +56,16 @@ public:
+ hb_codepoint_t glyph, void *user_data);
+
+ // get harfbuzz vertical advance in 16.16 fixed point format.
+ static hb_position_t
+ HBGetGlyphVAdvance(hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph, void *user_data);
+
+ static hb_bool_t
+- HBGetGlyphHOrigin(hb_font_t *font, void *font_data,
+- hb_codepoint_t glyph,
+- hb_position_t *x, hb_position_t *y,
+- void *user_data);
+- static hb_bool_t
+ HBGetGlyphVOrigin(hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ hb_position_t *x, hb_position_t *y,
+ void *user_data);
+
+ hb_position_t GetHKerning(uint16_t aFirstGlyph,
+ uint16_t aSecondGlyph) const;
+
diff --git a/pcr/icedove-hardening/mozilla-1228540.patch b/pcr/icedove-hardening/mozilla-1228540.patch
new file mode 100644
index 000000000..9f6c46077
--- /dev/null
+++ b/pcr/icedove-hardening/mozilla-1228540.patch
@@ -0,0 +1,6032 @@
+diff -u -r mozilla/gfx/harfbuzz/src/check-header-guards.sh mozilla-1228540/gfx/harfbuzz/src/check-header-guards.sh
+--- mozilla/gfx/harfbuzz/src/check-header-guards.sh 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/check-header-guards.sh 2016-07-09 23:52:22.089763061 +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 -u -r mozilla/gfx/harfbuzz/src/gen-indic-table.py mozilla-1228540/gfx/harfbuzz/src/gen-indic-table.py
+--- mozilla/gfx/harfbuzz/src/gen-indic-table.py 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/gen-indic-table.py 2016-07-09 23:52:22.089763061 +0200
+@@ -91,6 +91,7 @@
+ "Visarga": 'Vs',
+ "Vowel": 'Vo',
+ "Vowel_Dependent": 'M',
++ "Consonant_Prefixed": 'CPrf',
+ "Other": 'x',
+ },{
+ "Not_Applicable": 'x',
+diff -u -r mozilla/gfx/harfbuzz/src/hb-atomic-private.hh mozilla-1228540/gfx/harfbuzz/src/hb-atomic-private.hh
+--- mozilla/gfx/harfbuzz/src/hb-atomic-private.hh 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-atomic-private.hh 2016-07-09 23:52:22.089763061 +0200
+@@ -119,6 +119,31 @@
+ #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;
++}
++
++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. */
+diff -u -r mozilla/gfx/harfbuzz/src/hb-blob.h mozilla-1228540/gfx/harfbuzz/src/hb-blob.h
+--- mozilla/gfx/harfbuzz/src/hb-blob.h 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-blob.h 2016-07-09 23:52:22.089763061 +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 -u -r mozilla/gfx/harfbuzz/src/hb-buffer.cc mozilla-1228540/gfx/harfbuzz/src/hb-buffer.cc
+--- mozilla/gfx/harfbuzz/src/hb-buffer.cc 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-buffer.cc 2016-07-09 23:52:22.089763061 +0200
+@@ -35,8 +35,26 @@
+ #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
+@@ -52,6 +70,14 @@
+ }
+
+ /**
++ * 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
+@@ -324,9 +350,7 @@
+ unsigned int num_out,
+ const uint32_t *glyph_data)
+ {
+- if (unlikely (!make_room_for (num_in, num_out)))
+- goto done;
+- {
++ if (unlikely (!make_room_for (num_in, num_out))) return;
+
+ merge_clusters (idx, idx + num_in);
+
+@@ -339,50 +363,39 @@
+ pinfo++;
+ }
+
+- out_len += num_out;
+- }
+-done:
+ idx += num_in;
++ out_len += num_out;
+ }
+
+ void
+ hb_buffer_t::output_glyph (hb_codepoint_t glyph_index)
+ {
+- if (unlikely (!make_room_for (0, 1)))
+- goto done;
++ if (unlikely (!make_room_for (0, 1))) return;
+
+ out_info[out_len] = info[idx];
+ out_info[out_len].codepoint = glyph_index;
+
+ out_len++;
+-done:
+- ;
+ }
+
+ void
+ hb_buffer_t::output_info (const hb_glyph_info_t &glyph_info)
+ {
+- if (unlikely (!make_room_for (0, 1)))
+- goto done;
++ if (unlikely (!make_room_for (0, 1))) return;
+
+ out_info[out_len] = glyph_info;
+
+ out_len++;
+-done:
+- ;
+ }
+
+ void
+ hb_buffer_t::copy_glyph (void)
+ {
+- if (unlikely (!make_room_for (0, 1)))
+- goto done;
++ if (unlikely (!make_room_for (0, 1))) return;
+
+ out_info[out_len] = info[idx];
+
+ out_len++;
+-done:
+- ;
+ }
+
+ bool
+@@ -400,7 +413,7 @@
+ if (out_len < i)
+ {
+ unsigned int count = i - out_len;
+- if (unlikely (!make_room_for (count, count))) return false; // XXX verify bailout
++ if (unlikely (!make_room_for (count, count))) return false;
+
+ memmove (out_info + out_len, info + idx, count * sizeof (out_info[0]));
+ idx += count;
+@@ -427,15 +440,13 @@
+ hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index)
+ {
+ if (unlikely (out_info != info || out_len != idx)) {
+- if (unlikely (!make_room_for (1, 1)))
+- goto out;
++ if (unlikely (!make_room_for (1, 1))) return;
+ out_info[out_len] = info[idx];
+ }
+ out_info[out_len].codepoint = glyph_index;
+
+- out_len++;
+-out:
+ idx++;
++ out_len++;
+ }
+
+
+@@ -721,9 +732,14 @@
+ /**
+ * 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: 0.9.2
+ **/
+@@ -778,11 +794,13 @@
+
+ /**
+ * 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: 0.9.2
+ **/
+@@ -794,9 +812,11 @@
+
+ /**
+ * 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: 0.9.2
+ **/
+@@ -809,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:
+@@ -839,7 +861,7 @@
+
+ /**
+ * hb_buffer_get_user_data: (skip)
+- * @buffer: a buffer.
++ * @buffer: an #hb_buffer_t.
+ * @key:
+ *
+ *
+@@ -858,10 +880,11 @@
+
+ /**
+ * 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: 0.9.5
+ **/
+@@ -874,11 +897,12 @@
+
+ /**
+ * 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: 0.9.5
+ **/
+@@ -891,7 +915,7 @@
+
+ /**
+ * hb_buffer_set_unicode_funcs:
+- * @buffer: a buffer.
++ * @buffer: an #hb_buffer_t.
+ * @unicode_funcs:
+ *
+ *
+@@ -916,7 +940,7 @@
+
+ /**
+ * hb_buffer_get_unicode_funcs:
+- * @buffer: a buffer.
++ * @buffer: an #hb_buffer_t.
+ *
+ *
+ *
+@@ -932,10 +956,16 @@
+
+ /**
+ * 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: 0.9.2
+ **/
+@@ -952,11 +982,12 @@
+
+ /**
+ * 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: 0.9.2
+ **/
+@@ -968,10 +999,18 @@
+
+ /**
+ * 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.
++ *
++ * 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
+ **/
+@@ -987,11 +1026,12 @@
+
+ /**
+ * 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: 0.9.2
+ **/
+@@ -1003,10 +1043,18 @@
+
+ /**
+ * 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: 0.9.2
+ **/
+@@ -1022,11 +1070,12 @@
+
+ /**
+ * hb_buffer_get_language:
+- * @buffer: a buffer.
++ * @buffer: an #hb_buffer_t.
+ *
+- *
++ * See hb_buffer_set_language().
+ *
+ * Return value: (transfer none):
++ * The #hb_language_t of the buffer. Must not be freed by the caller.
+ *
+ * Since: 0.9.2
+ **/
+@@ -1038,10 +1087,12 @@
+
+ /**
+ * 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: 0.9.7
+ **/
+@@ -1057,10 +1108,10 @@
+
+ /**
+ * hb_buffer_get_segment_properties:
+- * @buffer: a buffer.
+- * @props: (out):
++ * @buffer: an #hb_buffer_t.
++ * @props: (out): the output #hb_segment_properties_t.
+ *
+- *
++ * Sets @props to the #hb_segment_properties_t of @buffer.
+ *
+ * Since: 0.9.7
+ **/
+@@ -1074,10 +1125,10 @@
+
+ /**
+ * 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: 0.9.7
+ **/
+@@ -1093,11 +1144,12 @@
+
+ /**
+ * hb_buffer_get_flags:
+- * @buffer: a buffer.
++ * @buffer: an #hb_buffer_t.
+ *
+- *
++ * See hb_buffer_set_flags().
+ *
+ * Return value:
++ * The @buffer flags.
+ *
+ * Since: 0.9.7
+ **/
+@@ -1109,7 +1161,7 @@
+
+ /**
+ * hb_buffer_set_cluster_level:
+- * @buffer: a buffer.
++ * @buffer: an #hb_buffer_t.
+ * @cluster_level:
+ *
+ *
+@@ -1128,7 +1180,7 @@
+
+ /**
+ * hb_buffer_get_cluster_level:
+- * @buffer: a buffer.
++ * @buffer: an #hb_buffer_t.
+ *
+ *
+ *
+@@ -1145,10 +1197,13 @@
+
+ /**
+ * 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.
++ *
++ * Default is %HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT.
+ *
+ * Since: 0.9.31
+ **/
+@@ -1164,11 +1219,12 @@
+
+ /**
+ * 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: 0.9.31
+ **/
+@@ -1181,9 +1237,10 @@
+
+ /**
+ * 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: 0.9.2
+ **/
+@@ -1195,9 +1252,10 @@
+
+ /**
+ * 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: 0.9.11
+ **/
+@@ -1209,12 +1267,13 @@
+
+ /**
+ * 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: 0.9.2
+ **/
+@@ -1226,11 +1285,12 @@
+
+ /**
+ * 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: 0.9.2
+ **/
+@@ -1242,11 +1302,18 @@
+
+ /**
+ * 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: 0.9.7
+ **/
+@@ -1261,12 +1328,14 @@
+
+ /**
+ * 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: 0.9.2
+ **/
+@@ -1301,11 +1370,13 @@
+
+ /**
+ * 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: 0.9.2
+ **/
+@@ -1317,13 +1388,15 @@
+
+ /**
+ * 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: 0.9.2
+ **/
+@@ -1339,13 +1412,15 @@
+
+ /**
+ * 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: 0.9.2
+ **/
+@@ -1364,7 +1439,7 @@
+
+ /**
+ * hb_buffer_reverse:
+- * @buffer: a buffer.
++ * @buffer: an #hb_buffer_t.
+ *
+ * Reverses buffer contents.
+ *
+@@ -1378,7 +1453,7 @@
+
+ /**
+ * hb_buffer_reverse_range:
+- * @buffer: a buffer.
++ * @buffer: an #hb_buffer_t.
+ * @start: start index.
+ * @end: end index.
+ *
+@@ -1395,7 +1470,7 @@
+
+ /**
+ * 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
+@@ -1411,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
+@@ -1510,13 +1585,18 @@
+
+ /**
+ * hb_buffer_add_utf8:
+- * @buffer: a buffer.
+- * @text: (array length=text_length) (element-type uint8_t):
+- * @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().
++ *
++ * Replaces invalid UTF-8 characters with the @buffer replacement code point,
++ * see hb_buffer_set_replacement_codepoint().
+ *
+ * Since: 0.9.2
+ **/
+@@ -1532,13 +1612,17 @@
+
+ /**
+ * 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().
++ *
++ * Replaces invalid UTF-16 characters with the @buffer replacement code point,
++ * see hb_buffer_set_replacement_codepoint().
+ *
+ * Since: 0.9.2
+ **/
+@@ -1554,13 +1638,17 @@
+
+ /**
+ * 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().
++ *
++ * Replaces invalid UTF-32 characters with the @buffer replacement code point,
++ * see hb_buffer_set_replacement_codepoint().
+ *
+ * Since: 0.9.2
+ **/
+@@ -1576,13 +1664,18 @@
+
+ /**
+ * hb_buffer_add_latin1:
+- * @buffer: a buffer.
+- * @text: (array length=text_length) (element-type uint8_t):
+- * @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).
+ *
+- *
++ * 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
+ **/
+@@ -1598,13 +1691,25 @@
+
+ /**
+ * 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: 0.9.31
+ **/
+@@ -1676,9 +1781,12 @@
+
+ /**
+ * 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.
++ *
++ * <note>This has nothing to do with Unicode normalization.</note>
+ *
+ * Since: 0.9.2
+ **/
+@@ -1724,3 +1832,45 @@
+ }
+ }
+ }
++
++/*
++ * 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 -u -r mozilla/gfx/harfbuzz/src/hb-buffer.h mozilla-1228540/gfx/harfbuzz/src/hb-buffer.h
+--- mozilla/gfx/harfbuzz/src/hb-buffer.h 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-buffer.h 2016-07-09 23:52:22.089763061 +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,101 +122,125 @@
+ 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 >*/
+@@ -181,11 +250,11 @@
+ 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);
+
+ /*
+@@ -198,93 +267,92 @@
+ HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES
+ } hb_buffer_cluster_level_t;
+
+-void
++HB_EXTERN void
+ hb_buffer_set_cluster_level (hb_buffer_t *buffer,
+ hb_buffer_cluster_level_t cluster_level);
+
+-hb_buffer_cluster_level_t
++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);
+
+-void
++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);
+
+-/* Allows only access to first 256 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);
+
+-/* Like add_utf32 but does NOT check for invalid Unicode codepoints. */
+-void
++HB_EXTERN void
+ hb_buffer_add_codepoints (hb_buffer_t *buffer,
+ const hb_codepoint_t *text,
+ int text_length,
+@@ -292,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);
+
+
+@@ -325,7 +386,16 @@
+ * 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 >*/
+@@ -336,43 +406,67 @@
+ 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 -u -r mozilla/gfx/harfbuzz/src/hb-buffer-private.hh mozilla-1228540/gfx/harfbuzz/src/hb-buffer-private.hh
+--- mozilla/gfx/harfbuzz/src/hb-buffer-private.hh 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-buffer-private.hh 2016-07-09 23:52:22.089763061 +0200
+@@ -124,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 */
+
+@@ -174,13 +179,12 @@
+ if (have_output)
+ {
+ if (unlikely (out_info != info || out_len != idx)) {
+- if (unlikely (!make_room_for (1, 1)))
+- goto done;
++ if (unlikely (!make_room_for (1, 1))) return;
+ out_info[out_len] = info[idx];
+ }
+ out_len++;
+ }
+- done:
++
+ idx++;
+ }
+
+@@ -234,6 +238,19 @@
+ 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 -u -r mozilla/gfx/harfbuzz/src/hb-buffer-serialize.cc mozilla-1228540/gfx/harfbuzz/src/hb-buffer-serialize.cc
+--- mozilla/gfx/harfbuzz/src/hb-buffer-serialize.cc 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-buffer-serialize.cc 2016-07-09 23:52:22.089763061 +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: 0.9.2
++ * 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: 0.9.2
++ * 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: 0.9.2
++ * Since: 0.9.7
+ **/
+ const char *
+ hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format)
+@@ -242,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
++ * `&lt;x_bearing,y_bearing,width,height&gt;`
+ *
+- *
++ * ## json
++ * TODO.
+ *
+ * Return value:
++ * The number of serialized items.
+ *
+- * Since: 0.9.2
++ * Since: 0.9.7
+ **/
+ unsigned int
+ hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
+@@ -267,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)
+ {
+@@ -282,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;
+
+@@ -355,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):
+@@ -366,7 +402,7 @@
+ *
+ * Return value:
+ *
+- * Since: 0.9.2
++ * Since: 0.9.7
+ **/
+ hb_bool_t
+ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
+diff -u -r mozilla/gfx/harfbuzz/src/hb-common.cc mozilla-1228540/gfx/harfbuzz/src/hb-common.cc
+--- mozilla/gfx/harfbuzz/src/hb-common.cc 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-common.cc 2016-07-09 23:52:22.089763061 +0200
+@@ -281,12 +281,15 @@
+
+ /**
+ * hb_language_from_string:
+- * @str: (array length=len) (element-type uint8_t):
+- * @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: (transfer none):
++ * The #hb_language_t corresponding to the ISO 639 language code.
+ *
+ * Since: 0.9.2
+ **/
+@@ -314,11 +317,13 @@
+
+ /**
+ * 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: 0.9.2
+ **/
+@@ -357,11 +362,12 @@
+
+ /**
+ * 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: 0.9.2
+ **/
+@@ -401,28 +407,33 @@
+
+ /**
+ * hb_script_from_string:
+- * @s: (array length=len) (element-type uint8_t):
+- * @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: 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: 0.9.2
+ **/
+@@ -521,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;
+ }
+diff -u -r mozilla/gfx/harfbuzz/src/hb-common.h mozilla-1228540/gfx/harfbuzz/src/hb-common.h
+--- mozilla/gfx/harfbuzz/src/hb-common.h 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-common.h 2016-07-09 23:52:22.089763061 +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);
+
+
+@@ -324,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 -u -r mozilla/gfx/harfbuzz/src/hb-coretext.cc mozilla-1228540/gfx/harfbuzz/src/hb-coretext.cc
+--- mozilla/gfx/harfbuzz/src/hb-coretext.cc 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-coretext.cc 2016-07-09 23:52:22.089763061 +0200
+@@ -176,6 +176,43 @@
+ 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);
++ return NULL;
++ }
++
+ return data;
+ }
+
+@@ -693,7 +730,6 @@
+ scratch += old_scratch_used;
+ scratch_size -= old_scratch_used;
+ }
+-retry:
+ {
+ string_ref = CFStringCreateWithCharactersNoCopy (NULL,
+ pchars, chars_len,
+@@ -848,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
+ */
+@@ -1129,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 -u -r mozilla/gfx/harfbuzz/src/hb-coretext.h mozilla-1228540/gfx/harfbuzz/src/hb-coretext.h
+--- mozilla/gfx/harfbuzz/src/hb-coretext.h 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-coretext.h 2016-07-09 23:52:22.089763061 +0200
+@@ -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);
+
+
+Only in mozilla-1228540/gfx/harfbuzz/src: hb-directwrite.cc
+Only in mozilla-1228540/gfx/harfbuzz/src: hb-directwrite.h
+diff -u -r mozilla/gfx/harfbuzz/src/hb-face.h mozilla-1228540/gfx/harfbuzz/src/hb-face.h
+--- mozilla/gfx/harfbuzz/src/hb-face.h 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-face.h 2016-07-09 23:52:22.093096381 +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 -u -r mozilla/gfx/harfbuzz/src/hb-fallback-shape.cc mozilla-1228540/gfx/harfbuzz/src/hb-fallback-shape.cc
+--- mozilla/gfx/harfbuzz/src/hb-fallback-shape.cc 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-fallback-shape.cc 2016-07-09 23:52:22.093096381 +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 -u -r mozilla/gfx/harfbuzz/src/hb-font.cc mozilla-1228540/gfx/harfbuzz/src/hb-font.cc
+--- mozilla/gfx/harfbuzz/src/hb-font.cc 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-font.cc 2016-07-09 23:52:22.093096381 +0200
+@@ -45,6 +45,54 @@
+ */
+
+ static hb_bool_t
++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,
+@@ -109,7 +157,7 @@
+ void *user_data HB_UNUSED)
+ {
+ *x = *y = 0;
+- return false;
++ return true;
+ }
+ static hb_bool_t
+ hb_font_get_glyph_h_origin_parent (hb_font_t *font,
+@@ -280,7 +328,6 @@
+ return font->parent->get_glyph_from_name (name, len, glyph);
+ }
+
+-
+ static const hb_font_funcs_t _hb_font_funcs_nil = {
+ HB_OBJECT_HEADER_STATIC,
+
+@@ -522,6 +569,42 @@
+ /* 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:
+@@ -746,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:
+diff -u -r mozilla/gfx/harfbuzz/src/hb-font.h mozilla-1228540/gfx/harfbuzz/src/hb-font.h
+--- mozilla/gfx/harfbuzz/src/hb-font.h 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-font.h 2016-07-09 23:52:22.093096381 +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,19 +66,37 @@
+ 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
+@@ -89,9 +107,15 @@
+ 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,
+@@ -141,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):
+@@ -151,7 +207,7 @@
+ *
+ * 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);
+@@ -167,7 +223,7 @@
+ *
+ * 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);
+@@ -183,7 +239,7 @@
+ *
+ * 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);
+@@ -199,7 +255,7 @@
+ *
+ * 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);
+@@ -215,7 +271,7 @@
+ *
+ * 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);
+@@ -231,7 +287,7 @@
+ *
+ * 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);
+@@ -247,7 +303,7 @@
+ *
+ * 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);
+@@ -263,7 +319,7 @@
+ *
+ * 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);
+@@ -279,7 +335,7 @@
+ *
+ * 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);
+@@ -295,7 +351,7 @@
+ *
+ * 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);
+@@ -311,57 +367,63 @@
+ *
+ * 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);
+@@ -369,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);
+@@ -426,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,
+@@ -449,46 +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);
+
+-void
++HB_EXTERN void
+ hb_font_set_parent (hb_font_t *font,
+ hb_font_t *parent);
+
+-hb_font_t *
++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);
+@@ -496,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 -u -r mozilla/gfx/harfbuzz/src/hb-font-private.hh mozilla-1228540/gfx/harfbuzz/src/hb-font-private.hh
+--- mozilla/gfx/harfbuzz/src/hb-font-private.hh 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-font-private.hh 2016-07-09 23:52:22.093096381 +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) \
+@@ -160,7 +162,22 @@
+ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+ #undef HB_FONT_FUNC_IMPLEMENT
+
+- inline hb_bool_t has_glyph (hb_codepoint_t unicode)
++ 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);
+@@ -265,6 +282,26 @@
+
+ /* 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)
+@@ -284,7 +321,7 @@
+ {
+ *x = get_glyph_h_advance (glyph) / 2;
+
+- /* TODO use font_metrics.ascent */
++ /* TODO use font_extents.ascender */
+ *y = y_scale;
+ }
+
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ft.cc mozilla-1228540/gfx/harfbuzz/src/hb-ft.cc
+--- mozilla/gfx/harfbuzz/src/hb-ft.cc 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ft.cc 2016-07-09 23:52:22.093096381 +0200
+@@ -366,6 +366,25 @@
+ 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;
+
+@@ -387,6 +406,8 @@
+ {
+ 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);
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ft.h mozilla-1228540/gfx/harfbuzz/src/hb-ft.h
+--- mozilla/gfx/harfbuzz/src/hb-ft.h 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ft.h 2016-07-09 23:52:22.093096381 +0200
+@@ -59,7 +59,7 @@
+ * probably should use (the more recent) hb_ft_face_create_referenced()
+ * instead.
+ */
+-hb_face_t *
++HB_EXTERN hb_face_t *
+ hb_ft_face_create (FT_Face ft_face,
+ hb_destroy_func_t destroy);
+
+@@ -71,7 +71,7 @@
+ * Client is still responsible for making sure that ft-face is destroyed
+ * after hb-face is.
+ */
+-hb_face_t *
++HB_EXTERN hb_face_t *
+ hb_ft_face_create_cached (FT_Face ft_face);
+
+ /* This version is like hb_ft_face_create(), except that it calls
+@@ -81,7 +81,7 @@
+ * This is the most convenient version to use. Use it unless you have
+ * very good reasons not to.
+ */
+-hb_face_t *
++HB_EXTERN hb_face_t *
+ hb_ft_face_create_referenced (FT_Face ft_face);
+
+
+@@ -98,26 +98,26 @@
+
+ /* See notes on hb_ft_face_create(). Same issues re lifecycle-management
+ * apply here. Use hb_ft_font_create_referenced() if you can. */
+-hb_font_t *
++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_font_t *
++HB_EXTERN hb_font_t *
+ hb_ft_font_create_referenced (FT_Face ft_face);
+
+-FT_Face
++HB_EXTERN FT_Face
+ hb_ft_font_get_face (hb_font_t *font);
+
+-void
++HB_EXTERN void
+ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags);
+
+-int
++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);
+
+
+diff -u -r mozilla/gfx/harfbuzz/src/hb-glib.cc mozilla-1228540/gfx/harfbuzz/src/hb-glib.cc
+--- mozilla/gfx/harfbuzz/src/hb-glib.cc 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-glib.cc 2016-07-09 23:52:22.093096381 +0200
+@@ -383,6 +383,8 @@
+ }
+
+ /**
++ * hb_glib_blob_create:
++ *
+ * Since: 0.9.38
+ **/
+ hb_blob_t *
+diff -u -r mozilla/gfx/harfbuzz/src/hb-glib.h mozilla-1228540/gfx/harfbuzz/src/hb-glib.h
+--- mozilla/gfx/harfbuzz/src/hb-glib.h 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-glib.h 2016-07-09 23:52:22.093096381 +0200
+@@ -36,17 +36,17 @@
+ 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_blob_t *
++HB_EXTERN hb_blob_t *
+ hb_glib_blob_create (GBytes *gbytes);
+
+
+diff -u -r mozilla/gfx/harfbuzz/src/hb-gobject-enums.h.tmpl mozilla-1228540/gfx/harfbuzz/src/hb-gobject-enums.h.tmpl
+--- mozilla/gfx/harfbuzz/src/hb-gobject-enums.h.tmpl 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-gobject-enums.h.tmpl 2016-07-09 23:52:22.093096381 +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 -u -r mozilla/gfx/harfbuzz/src/hb-gobject-structs.h mozilla-1228540/gfx/harfbuzz/src/hb-gobject-structs.h
+--- mozilla/gfx/harfbuzz/src/hb-gobject-structs.h 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-gobject-structs.h 2016-07-09 23:52:22.093096381 +0200
+@@ -43,60 +43,60 @@
+ /**
+ * Since: 0.9.2
+ **/
+-GType hb_gobject_blob_get_type (void);
++HB_EXTERN GType hb_gobject_blob_get_type (void);
+ #define HB_GOBJECT_TYPE_BLOB (hb_gobject_blob_get_type ())
+
+ /**
+ * Since: 0.9.2
+ **/
+-GType hb_gobject_buffer_get_type (void);
++HB_EXTERN GType hb_gobject_buffer_get_type (void);
+ #define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ())
+
+ /**
+ * Since: 0.9.2
+ **/
+-GType hb_gobject_face_get_type (void);
++HB_EXTERN GType hb_gobject_face_get_type (void);
+ #define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ())
+
+ /**
+ * Since: 0.9.2
+ **/
+-GType hb_gobject_font_get_type (void);
++HB_EXTERN GType hb_gobject_font_get_type (void);
+ #define HB_GOBJECT_TYPE_FONT (hb_gobject_font_get_type ())
+
+ /**
+ * Since: 0.9.2
+ **/
+-GType hb_gobject_font_funcs_get_type (void);
++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 ())
+
+ /**
+ * Since: 0.9.2
+ **/
+-GType hb_gobject_unicode_funcs_get_type (void);
++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 ())
+
+
+diff -u -r mozilla/gfx/harfbuzz/src/hb-graphite2.cc mozilla-1228540/gfx/harfbuzz/src/hb-graphite2.cc
+--- mozilla/gfx/harfbuzz/src/hb-graphite2.cc 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-graphite2.cc 2016-07-09 23:52:22.093096381 +0200
+@@ -351,6 +351,7 @@
+ }
+ buffer->len = glyph_count;
+
++ float yscale = font->y_scale / font->x_scale;
+ /* Positioning. */
+ if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
+ {
+@@ -359,9 +360,9 @@
+ 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->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);
++ pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale;
+ curradvx += pPos->x_advance;
+ curradvy += pPos->y_advance;
+ }
+@@ -387,17 +388,17 @@
+ 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);
++ 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);
++ 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) - curradvy;
++ pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy;
+ }
+ hb_buffer_reverse_clusters (buffer);
+ }
+diff -u -r mozilla/gfx/harfbuzz/src/hb-graphite2.h mozilla-1228540/gfx/harfbuzz/src/hb-graphite2.h
+--- mozilla/gfx/harfbuzz/src/hb-graphite2.h 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-graphite2.h 2016-07-09 23:52:22.093096381 +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 -u -r mozilla/gfx/harfbuzz/src/hb.h mozilla-1228540/gfx/harfbuzz/src/hb.h
+--- mozilla/gfx/harfbuzz/src/hb.h 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb.h 2016-07-09 23:52:22.096429701 +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 -u -r mozilla/gfx/harfbuzz/src/hb-icu.h mozilla-1228540/gfx/harfbuzz/src/hb-icu.h
+--- mozilla/gfx/harfbuzz/src/hb-icu.h 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-icu.h 2016-07-09 23:52:22.093096381 +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 -u -r mozilla/gfx/harfbuzz/src/hb-open-type-private.hh mozilla-1228540/gfx/harfbuzz/src/hb-open-type-private.hh
+--- mozilla/gfx/harfbuzz/src/hb-open-type-private.hh 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-open-type-private.hh 2016-07-09 23:54:00.822696030 +0200
+@@ -182,7 +182,7 @@
+
+ /* This limits sanitizing time on really broken fonts. */
+ #ifndef HB_SANITIZE_MAX_EDITS
+-#define HB_SANITIZE_MAX_EDITS 8
++#define HB_SANITIZE_MAX_EDITS 32
+ #endif
+
+ struct hb_sanitize_context_t :
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-font.cc mozilla-1228540/gfx/harfbuzz/src/hb-ot-font.cc
+--- mozilla/gfx/harfbuzz/src/hb-ot-font.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-font.cc 2016-07-09 23:52:22.093096381 +0200
+@@ -35,6 +35,7 @@
+ #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
+@@ -42,17 +43,45 @@
+ 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)
++ hb_tag_t _hea_tag,
++ hb_tag_t _mtx_tag,
++ hb_tag_t os2_tag)
+ {
+ 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));
+@@ -252,8 +281,8 @@
+ return NULL;
+
+ ot_font->cmap.init (face);
+- ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx);
+- ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx); /* 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;
+@@ -320,6 +349,31 @@
+ return ret;
+ }
+
++static hb_bool_t
++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)
++{
++ 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_font_v_extents (hb_font_t *font HB_UNUSED,
++ void *font_data,
++ hb_font_extents_t *metrics,
++ void *user_data HB_UNUSED)
++{
++ 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_font_funcs_t *static_ot_funcs = NULL;
+
+@@ -341,6 +395,8 @@
+ {
+ funcs = hb_font_funcs_create ();
+
++ 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);
+@@ -370,6 +426,8 @@
+
+
+ /**
++ * hb_ot_font_set_funcs:
++ *
+ * Since: 0.9.28
+ **/
+ void
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-font.h mozilla-1228540/gfx/harfbuzz/src/hb-ot-font.h
+--- mozilla/gfx/harfbuzz/src/hb-ot-font.h 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-font.h 2016-07-09 23:52:22.093096381 +0200
+@@ -36,7 +36,7 @@
+ HB_BEGIN_DECLS
+
+
+-void
++HB_EXTERN void
+ hb_ot_font_set_funcs (hb_font_t *font);
+
+
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-head-table.hh mozilla-1228540/gfx/harfbuzz/src/hb-ot-head-table.hh
+--- mozilla/gfx/harfbuzz/src/hb-ot-head-table.hh 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-head-table.hh 2016-07-09 23:52:22.093096381 +0200
+@@ -55,7 +55,9 @@
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+- return_trace (c->check_struct (this) && likely (version.major == 1));
++ return_trace (c->check_struct (this) &&
++ version.major == 1 &&
++ magicNumber == 0x5F0F3CF5u);
+ }
+
+ protected:
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-layout.cc mozilla-1228540/gfx/harfbuzz/src/hb-ot-layout.cc
+--- mozilla/gfx/harfbuzz/src/hb-ot-layout.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-layout.cc 2016-07-09 23:52:22.093096381 +0200
+@@ -130,6 +130,8 @@
+ }
+
+ /**
++ * hb_ot_layout_get_glyph_class:
++ *
+ * Since: 0.9.7
+ **/
+ hb_ot_layout_glyph_class_t
+@@ -140,6 +142,8 @@
+ }
+
+ /**
++ * hb_ot_layout_get_glyphs_in_class:
++ *
+ * Since: 0.9.7
+ **/
+ void
+@@ -365,6 +369,8 @@
+ }
+
+ /**
++ * hb_ot_layout_language_get_required_feature:
++ *
+ * Since: 0.9.30
+ **/
+ hb_bool_t
+@@ -452,6 +458,8 @@
+ }
+
+ /**
++ * hb_ot_layout_feature_get_lookups:
++ *
+ * Since: 0.9.7
+ **/
+ unsigned int
+@@ -469,6 +477,8 @@
+ }
+
+ /**
++ * hb_ot_layout_table_get_lookup_count:
++ *
+ * Since: 0.9.22
+ **/
+ unsigned int
+@@ -629,6 +639,8 @@
+ }
+
+ /**
++ * hb_ot_layout_collect_lookups:
++ *
+ * Since: 0.9.8
+ **/
+ void
+@@ -673,6 +685,8 @@
+ }
+
+ /**
++ * hb_ot_layout_lookup_collect_glyphs:
++ *
+ * Since: 0.9.7
+ **/
+ void
+@@ -721,6 +735,8 @@
+ }
+
+ /**
++ * hb_ot_layout_lookup_would_substitute:
++ *
+ * Since: 0.9.7
+ **/
+ hb_bool_t
+@@ -742,7 +758,7 @@
+ 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);
+
+@@ -762,6 +778,8 @@
+ }
+
+ /**
++ * hb_ot_layout_lookup_substitute_closure:
++ *
+ * Since: 0.9.7
+ **/
+ void
+@@ -799,6 +817,8 @@
+ }
+
+ /**
++ * hb_ot_layout_get_size_params:
++ *
+ * Since: 0.9.10
+ **/
+ hb_bool_t
+@@ -1008,25 +1028,15 @@
+ const stage_map_t *stage = &stages[table_index][stage_index];
+ for (; i < stage->last_lookup; i++)
+ {
+-#if 0
+- char buf[4096];
+- hb_buffer_serialize_glyphs (buffer, 0, buffer->len,
+- buf, sizeof (buf), NULL,
+- font,
+- HB_BUFFER_SERIALIZE_FORMAT_TEXT,
+- Proxy::table_index == 0 ?
+- HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS :
+- HB_BUFFER_SERIALIZE_FLAG_DEFAULT);
+- printf ("buf: [%s]\n", buf);
+-#endif
+-
+ 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 -u -r mozilla/gfx/harfbuzz/src/hb-ot-layout-common-private.hh mozilla-1228540/gfx/harfbuzz/src/hb-ot-layout-common-private.hh
+--- mozilla/gfx/harfbuzz/src/hb-ot-layout-common-private.hh 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-layout-common-private.hh 2016-07-09 23:52:22.093096381 +0200
+@@ -545,6 +545,9 @@
+ c->try_set (&featureParams, new_offset) &&
+ !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
+ return_trace (false);
++
++ if (c->edit_count > 1)
++ c->edit_count--; /* This was a "legitimate" edit; don't contribute to error count. */
+ }
+
+ return_trace (true);
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh mozilla-1228540/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
+--- mozilla/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh 2016-07-09 23:52:22.093096381 +0200
+@@ -742,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;
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh mozilla-1228540/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh
+--- mozilla/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh 2016-07-09 23:52:22.093096381 +0200
+@@ -845,9 +845,12 @@
+ 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 ();
+ }
+@@ -864,8 +867,11 @@
+ /* 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;
+@@ -971,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 ();
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-layout.h mozilla-1228540/gfx/harfbuzz/src/hb-ot-layout.h
+--- mozilla/gfx/harfbuzz/src/hb-ot-layout.h 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-layout.h 2016-07-09 23:52:22.093096381 +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 -u -r mozilla/gfx/harfbuzz/src/hb-ot-layout-private.hh mozilla-1228540/gfx/harfbuzz/src/hb-ot-layout-private.hh
+--- mozilla/gfx/harfbuzz/src/hb-ot-layout-private.hh 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-layout-private.hh 2016-07-09 23:52:22.093096381 +0200
+@@ -517,11 +517,9 @@
+ }
+
+ static inline void
+-_hb_glyph_info_clear_substituted_and_ligated_and_multiplied (hb_glyph_info_t *info)
++_hb_glyph_info_clear_substituted (hb_glyph_info_t *info)
+ {
+- info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
+- HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
+- HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
++ info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
+ }
+
+
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-map.cc mozilla-1228540/gfx/harfbuzz/src/hb-ot-map.cc
+--- mozilla/gfx/harfbuzz/src/hb-ot-map.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-map.cc 2016-07-09 23:52:22.093096381 +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]);
+ }
+ }
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-map-private.hh mozilla-1228540/gfx/harfbuzz/src/hb-ot-map-private.hh
+--- mozilla/gfx/harfbuzz/src/hb-ot-map-private.hh 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-map-private.hh 2016-07-09 23:52:22.093096381 +0200
+@@ -203,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 {
+Only in mozilla-1228540/gfx/harfbuzz/src: hb-ot-os2-table.hh
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-shape.cc mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape.cc
+--- mozilla/gfx/harfbuzz/src/hb-ot-shape.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape.cc 2016-07-09 23:52:22.096429701 +0200
+@@ -662,6 +662,7 @@
+ {
+ 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,
+@@ -671,12 +672,12 @@
+ else
+ {
+ for (unsigned int i = 0; i < count; i++)
++ {
+ pos[i].y_advance = c->font->get_glyph_v_advance (info[i].codepoint);
+- if (c->font->has_glyph_v_origin_func ())
+- for (unsigned int i = 0; i < count; i++)
+- c->font->subtract_glyph_v_origin (info[i].codepoint,
+- &pos[i].x_offset,
+- &pos[i].y_offset);
++ 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);
+@@ -687,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
+@@ -726,6 +727,7 @@
+
+ /* Change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
+
++ /* 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,
+@@ -734,6 +736,7 @@
+
+ c->plan->position (c->font, c->buffer);
+
++ /* 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,
+@@ -852,6 +855,8 @@
+
+
+ /**
++ * hb_ot_shape_plan_collect_lookups:
++ *
+ * Since: 0.9.7
+ **/
+ void
+@@ -885,6 +890,8 @@
+
+
+ /**
++ * hb_ot_shape_glyphs_closure:
++ *
+ * Since: 0.9.2
+ **/
+ void
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc
+--- mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc 2016-07-09 23:52:22.093096381 +0200
+@@ -223,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
+@@ -233,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'));
+ }
+@@ -463,10 +463,6 @@
+ * Second pass applies the stretch, copying things to the end of buffer.
+ */
+
+- /* 30 = 2048 / 70.
+- * https://www.microsoft.com/typography/cursivescriptguidelines.mspx */
+- hb_position_t overlap = font->x_scale / 30;
+- DEBUG_MSG (ARABIC, NULL, "overlap for stretching is %d", overlap);
+ 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;
+@@ -504,18 +500,15 @@
+ hb_in_range<unsigned> (info[i - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING))
+ {
+ i--;
+- hb_glyph_extents_t extents;
+- if (!font->get_glyph_extents (info[i].codepoint, &extents))
+- extents.width = 0;
+- extents.width -= overlap;
++ hb_position_t width = font->get_glyph_h_advance (info[i].codepoint);
+ if (info[i].arabic_shaping_action() == STCH_FIXED)
+ {
+- w_fixed += extents.width;
++ w_fixed += width;
+ n_fixed++;
+ }
+ else
+ {
+- w_repeating += extents.width;
++ w_repeating += width;
+ n_repeating++;
+ }
+ }
+@@ -540,9 +533,20 @@
+ /* Number of additional times to repeat each repeating tile. */
+ int n_copies = 0;
+
+- hb_position_t w_remaining = w_total - w_fixed - overlap;
++ 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 / 4) / (sign * w_repeating) - 1;
++ 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)
+ {
+@@ -551,13 +555,10 @@
+ }
+ else
+ {
+- hb_position_t x_offset = -overlap;
++ hb_position_t x_offset = 0;
+ for (unsigned int k = end; k > start; k--)
+ {
+- hb_glyph_extents_t extents;
+- if (!font->get_glyph_extents (info[k - 1].codepoint, &extents))
+- extents.width = 0;
+- extents.width -= overlap;
++ 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)
+@@ -567,7 +568,9 @@
+ repeat, info[k - 1].codepoint, j);
+ for (unsigned int n = 0; n < repeat; n++)
+ {
+- x_offset -= extents.width;
++ x_offset -= width;
++ if (n > 0)
++ x_offset += extra_repeat_overlap;
+ pos[k - 1].x_offset = x_offset;
+ /* Append copy. */
+ --j;
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc
+--- mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc 2016-07-09 23:52:22.093096381 +0200
+@@ -40,6 +40,6 @@
+ 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 -u -r mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
+--- mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc 2016-07-09 23:52:22.093096381 +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)
+ {
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc
+--- mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc 2016-07-09 23:52:22.096429701 +0200
+@@ -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;
+@@ -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);
+@@ -1348,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--;
+@@ -1806,7 +1813,7 @@
+ }
+ }
+
+- return c->unicode->decompose (ab, a, b);
++ return (bool) c->unicode->decompose (ab, a, b);
+ }
+
+ static bool
+@@ -1822,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);
+ }
+
+
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh
+--- mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh 2016-07-09 23:52:22.093096381 +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,
+@@ -162,17 +166,23 @@
+ };
+
+ #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 -u -r mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
+--- mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc 2016-07-09 23:52:22.096429701 +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)
+@@ -862,7 +910,7 @@
+ {
+ case 0x0u:
+ if (hb_in_range (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
+- if (hb_in_range (u, 0x00D0u, 0x00D7u)) return indic_table[u - 0x00D0u + indic_offset_0x00d0u];
++ 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;
+@@ -872,11 +920,12 @@
+ 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, 0x1CF7u)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
++ if (hb_in_range (u, 0x1CD0u, 0x1CFFu)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
+ break;
+
+ case 0x2u:
+ 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;
+
+@@ -892,10 +941,9 @@
+ case 0x11u:
+ 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, 0x112B0u, 0x11377u)) return indic_table[u - 0x112B0u + indic_offset_0x112b0u];
++ 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, 0x115C7u)) return indic_table[u - 0x11580u + indic_offset_0x11580u];
+- if (hb_in_range (u, 0x11600u, 0x116CFu)) return indic_table[u - 0x11600u + indic_offset_0x11600u];
++ 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 -u -r mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
+--- mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc 2016-07-09 23:52:22.096429701 +0200
+@@ -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;
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh
+--- mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh 2016-07-09 23:52:22.096429701 +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
+ };
+
+
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc
+--- mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc 2016-07-09 23:52:22.096429701 +0200
+@@ -377,6 +377,6 @@
+ 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 -u -r mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc
+--- mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc 2016-07-09 23:52:22.096429701 +0200
+@@ -57,6 +57,6 @@
+ 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 -u -r mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc
+--- mozilla/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc 2016-07-09 23:52:22.096429701 +0200
+@@ -285,6 +285,9 @@
+ 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;
+@@ -360,7 +363,7 @@
+ 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_and_ligated_and_multiplied (&info[i]);
++ _hb_glyph_info_clear_substituted (&info[i]);
+ }
+
+ static void
+@@ -405,6 +408,12 @@
+ }
+ }
+
++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)
+ {
+@@ -420,7 +429,6 @@
+
+ hb_glyph_info_t *info = buffer->info;
+
+-#define HALANT_FLAGS FLAG(USE_H)
+ #define BASE_FLAGS (FLAG (USE_B) | FLAG (USE_GB) | FLAG (USE_IV))
+
+ /* Move things forward. */
+@@ -428,12 +436,12 @@
+ {
+ /* 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()) & (HALANT_FLAGS | BASE_FLAGS))
++ 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 (info[i].use_category() == USE_H)
++ if (is_halant (info[i]))
+ i--;
+
+ buffer->merge_clusters (start, i + 1);
+@@ -450,11 +458,11 @@
+ for (unsigned int i = start; i < end; i++)
+ {
+ uint32_t flag = FLAG_UNSAFE (info[i].use_category());
+- if (flag & (HALANT_FLAGS | BASE_FLAGS))
++ if ((flag & (BASE_FLAGS)) || is_halant (info[i]))
+ {
+- /* If we hit a halant, move before it; otherwise it's a base: move to it's
++ /* 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 (info[i].use_category() == USE_H)
++ if (is_halant (info[i]))
+ j = i + 1;
+ else
+ j = i;
+@@ -558,7 +566,7 @@
+ if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (c->unicode->general_category (a)))
+ return false;
+
+- return c->unicode->compose (a, b, ab);
++ return (bool)c->unicode->compose (a, b, ab);
+ }
+
+
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-shape.h mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape.h
+--- mozilla/gfx/harfbuzz/src/hb-ot-shape.h 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape.h 2016-07-09 23:52:22.096429701 +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 -u -r mozilla/gfx/harfbuzz/src/hb-ot-shape-normalize.cc mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-normalize.cc
+--- mozilla/gfx/harfbuzz/src/hb-ot-shape-normalize.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-shape-normalize.cc 2016-07-09 23:52:22.096429701 +0200
+@@ -76,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
+@@ -85,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
+@@ -127,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);
+diff -u -r mozilla/gfx/harfbuzz/src/hb-ot-tag.cc mozilla-1228540/gfx/harfbuzz/src/hb-ot-tag.cc
+--- mozilla/gfx/harfbuzz/src/hb-ot-tag.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-tag.cc 2016-07-09 23:52:22.096429701 +0200
+@@ -355,7 +355,6 @@
+ {"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 */
+@@ -601,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 */
+@@ -690,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 */
+@@ -700,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 */
+@@ -928,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 -u -r mozilla/gfx/harfbuzz/src/hb-ot-tag.h mozilla-1228540/gfx/harfbuzz/src/hb-ot-tag.h
+--- mozilla/gfx/harfbuzz/src/hb-ot-tag.h 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-ot-tag.h 2016-07-09 23:52:22.096429701 +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 -u -r mozilla/gfx/harfbuzz/src/hb-private.hh mozilla-1228540/gfx/harfbuzz/src/hb-private.hh
+--- mozilla/gfx/harfbuzz/src/hb-private.hh 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-private.hh 2016-07-09 23:52:22.096429701 +0200
+@@ -53,9 +53,6 @@
+ #include <errno.h>
+ #include <stdarg.h>
+
+-#ifdef _MSC_VER
+-#include <windows.h> /* ensure DEFINE_ENUM_FLAG_OPERATORS is defined */
+-#endif
+
+ /* Compile-time custom allocator support. */
+
+@@ -182,6 +179,9 @@
+ # 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
+
+@@ -899,27 +899,22 @@
+ * one enum to another... So this doesn't provide the type-checking that I
+ * originally had in mind... :(.
+ *
+- * On MSVC use DEFINE_ENUM_FLAG_OPERATORS. See:
+- * https://github.com/behdad/harfbuzz/pull/163
++ * For MSVC warnings, see: https://github.com/behdad/harfbuzz/pull/163
+ */
+ #ifdef _MSC_VER
+ # pragma warning(disable:4200)
+ # pragma warning(disable:4800)
+-# define HB_MARK_AS_FLAG_T(flags_t) DEFINE_ENUM_FLAG_OPERATORS (##flags_t##);
+-#else
+-# define HB_MARK_AS_FLAG_T(flags_t) template <> class hb_mark_as_flags_t<flags_t> {};
+-template <class T> class hb_mark_as_flags_t;
+-template <class T> static inline T operator | (T l, T r)
+-{ hb_mark_as_flags_t<T> unused HB_UNUSED; return T ((unsigned int) l | (unsigned int) r); }
+-template <class T> static inline T operator & (T l, T r)
+-{ hb_mark_as_flags_t<T> unused HB_UNUSED; return T ((unsigned int) l & (unsigned int) r); }
+-template <class T> static inline T operator ~ (T r)
+-{ hb_mark_as_flags_t<T> unused HB_UNUSED; return T (~(unsigned int) r); }
+-template <class T> static inline T& operator |= (T &l, T r)
+-{ hb_mark_as_flags_t<T> unused HB_UNUSED; l = l | r; return l; }
+-template <class T> static inline T& operator &= (T& l, T r)
+-{ hb_mark_as_flags_t<T> unused HB_UNUSED; l = l & r; return l; }
+ #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.
+diff -u -r mozilla/gfx/harfbuzz/src/hb-set.h mozilla-1228540/gfx/harfbuzz/src/hb-set.h
+--- mozilla/gfx/harfbuzz/src/hb-set.h 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-set.h 2016-07-09 23:52:22.096429701 +0200
+@@ -44,109 +44,109 @@
+ 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 -u -r mozilla/gfx/harfbuzz/src/hb-shape.cc mozilla-1228540/gfx/harfbuzz/src/hb-shape.cc
+--- mozilla/gfx/harfbuzz/src/hb-shape.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-shape.cc 2016-07-09 23:52:22.096429701 +0200
+@@ -210,13 +210,15 @@
+ /**
+ * hb_feature_from_string:
+ * @str: (array length=len) (element-type uint8_t): a string to parse
+- * @len: length of @str, or -1 if string is nul-terminated
++ * @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. If @len is -1 then @str is
+- * %NULL-terminated.
++ * Parses a string into a #hb_feature_t.
+ *
+- * Return value: %TRUE if @str is successfully parsed, %FALSE otherwise
++ * TODO: document the syntax here.
++ *
++ * Return value:
++ * %true if @str is successfully parsed, %false otherwise.
+ *
+ * Since: 0.9.5
+ **/
+diff -u -r mozilla/gfx/harfbuzz/src/hb-shape.h mozilla-1228540/gfx/harfbuzz/src/hb-shape.h
+--- mozilla/gfx/harfbuzz/src/hb-shape.h 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-shape.h 2016-07-09 23:52:22.096429701 +0200
+@@ -47,29 +47,29 @@
+ unsigned int end;
+ } hb_feature_t;
+
+-hb_bool_t
++HB_EXTERN hb_bool_t
+ hb_feature_from_string (const char *str, int len,
+ hb_feature_t *feature);
+
+-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 -u -r mozilla/gfx/harfbuzz/src/hb-shape-plan.h mozilla-1228540/gfx/harfbuzz/src/hb-shape-plan.h
+--- mozilla/gfx/harfbuzz/src/hb-shape-plan.h 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-shape-plan.h 2016-07-09 23:52:22.096429701 +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 -u -r mozilla/gfx/harfbuzz/src/hb-shaper-list.hh mozilla-1228540/gfx/harfbuzz/src/hb-shaper-list.hh
+--- mozilla/gfx/harfbuzz/src/hb-shaper-list.hh 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-shaper-list.hh 2016-07-09 23:52:22.096429701 +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 -u -r mozilla/gfx/harfbuzz/src/hb-unicode.h mozilla-1228540/gfx/harfbuzz/src/hb-unicode.h
+--- mozilla/gfx/harfbuzz/src/hb-unicode.h 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-unicode.h 2016-07-09 23:52:22.096429701 +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);
+
+
+@@ -285,7 +285,7 @@
+ *
+ * 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);
+@@ -301,7 +301,7 @@
+ *
+ * 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);
+@@ -317,7 +317,7 @@
+ *
+ * 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);
+@@ -333,7 +333,7 @@
+ *
+ * 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);
+@@ -349,7 +349,7 @@
+ *
+ * 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);
+@@ -365,7 +365,7 @@
+ *
+ * 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);
+@@ -381,7 +381,7 @@
+ *
+ * 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);
+@@ -397,7 +397,7 @@
+ *
+ * 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);
+@@ -405,62 +405,78 @@
+ /* accessors */
+
+ /**
++ * hb_unicode_combining_class:
++ *
+ * Since: 0.9.2
+ **/
+-hb_unicode_combining_class_t
++HB_EXTERN hb_unicode_combining_class_t
+ hb_unicode_combining_class (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode);
+
+ /**
++ * hb_unicode_eastasian_width:
++ *
+ * Since: 0.9.2
+ **/
+-unsigned int
++HB_EXTERN unsigned int
+ hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode);
+
+ /**
++ * hb_unicode_general_category:
++ *
+ * Since: 0.9.2
+ **/
+-hb_unicode_general_category_t
++HB_EXTERN hb_unicode_general_category_t
+ hb_unicode_general_category (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode);
+
+ /**
++ * hb_unicode_mirroring:
++ *
+ * Since: 0.9.2
+ **/
+-hb_codepoint_t
++HB_EXTERN hb_codepoint_t
+ hb_unicode_mirroring (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode);
+
+ /**
++ * hb_unicode_script:
++ *
+ * Since: 0.9.2
+ **/
+-hb_script_t
++HB_EXTERN hb_script_t
+ hb_unicode_script (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode);
+
+ /**
++ * hb_unicode_compose:
++ *
+ * Since: 0.9.2
+ **/
+-hb_bool_t
++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_unicode_decompose:
++ *
+ * Since: 0.9.2
+ **/
+-hb_bool_t
++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);
+
+ /**
++ * hb_unicode_decompose_compatibility:
++ *
+ * Since: 0.9.2
+ **/
+-unsigned int
++HB_EXTERN unsigned int
+ hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t u,
+ hb_codepoint_t *decomposed);
+diff -u -r mozilla/gfx/harfbuzz/src/hb-uniscribe.cc mozilla-1228540/gfx/harfbuzz/src/hb-uniscribe.cc
+--- mozilla/gfx/harfbuzz/src/hb-uniscribe.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-uniscribe.cc 2016-07-09 23:52:22.096429701 +0200
+@@ -919,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");
+@@ -1019,7 +1019,7 @@
+ hb_glyph_position_t *pos = &buffer->pos[i];
+
+ /* TODO vertical */
+- pos->x_advance = x_mult * info->mask;
++ 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;
+ }
+diff -u -r mozilla/gfx/harfbuzz/src/hb-uniscribe.h mozilla-1228540/gfx/harfbuzz/src/hb-uniscribe.h
+--- mozilla/gfx/harfbuzz/src/hb-uniscribe.h 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-uniscribe.h 2016-07-09 23:52:22.096429701 +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 -u -r mozilla/gfx/harfbuzz/src/hb-version.h mozilla-1228540/gfx/harfbuzz/src/hb-version.h
+--- mozilla/gfx/harfbuzz/src/hb-version.h 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-version.h 2016-07-09 23:52:22.096429701 +0200
+@@ -38,24 +38,24 @@
+
+ #define HB_VERSION_MAJOR 1
+ #define HB_VERSION_MINOR 1
+-#define HB_VERSION_MICRO 0
++#define HB_VERSION_MICRO 3
+
+-#define HB_VERSION_STRING "1.1.0"
++#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 -u -r mozilla/gfx/harfbuzz/src/hb-version.h.in mozilla-1228540/gfx/harfbuzz/src/hb-version.h.in
+--- mozilla/gfx/harfbuzz/src/hb-version.h.in 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/hb-version.h.in 2016-07-09 23:52:22.096429701 +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 -u -r mozilla/gfx/harfbuzz/src/Makefile.am mozilla-1228540/gfx/harfbuzz/src/Makefile.am
+--- mozilla/gfx/harfbuzz/src/Makefile.am 2016-06-30 16:10:42.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/Makefile.am 2016-07-09 23:52:22.089763061 +0200
+@@ -48,6 +48,7 @@
+ 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 \
+@@ -392,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)" \
+@@ -419,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 -u -r mozilla/gfx/harfbuzz/src/sample.py mozilla-1228540/gfx/harfbuzz/src/sample.py
+--- mozilla/gfx/harfbuzz/src/sample.py 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/sample.py 2016-07-09 23:52:22.096429701 +0200
+@@ -33,6 +33,12 @@
+ 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)
+
+diff -u -r mozilla/gfx/harfbuzz/src/test.cc mozilla-1228540/gfx/harfbuzz/src/test.cc
+--- mozilla/gfx/harfbuzz/src/test.cc 2016-06-30 16:10:43.000000000 +0200
++++ mozilla-1228540/gfx/harfbuzz/src/test.cc 2016-07-09 23:52:22.096429701 +0200
+@@ -120,7 +120,7 @@
+ info->cluster,
+ info->codepoint,
+ pos->x_offset,
+- pos->x_offset,
++ pos->y_offset,
+ pos->x_advance,
+ pos->y_advance);
+
diff --git a/pcr/icedove-hardening/mozilla-1253216.patch b/pcr/icedove-hardening/mozilla-1253216.patch
new file mode 100644
index 000000000..6de072054
--- /dev/null
+++ b/pcr/icedove-hardening/mozilla-1253216.patch
@@ -0,0 +1,12 @@
+diff -up firefox-45.0/firefox-45.0/js/src/jit/AtomicOperations.h.old firefox-45.0/firefox-45.0/js/src/jit/AtomicOperations.h
+--- firefox-45.0/firefox-45.0/js/src/jit/AtomicOperations.h.old 2016-03-01 09:45:01.000000000 +0100
++++ firefox-45.0/firefox-45.0/js/src/jit/AtomicOperations.h 2016-03-03 13:13:34.915015391 +0100
+@@ -305,7 +305,7 @@ AtomicOperations::isLockfree(int32_t siz
+ || defined(__ppc__) || defined(__PPC__)
+ # include "jit/none/AtomicOperations-ppc.h"
+ #elif defined(JS_CODEGEN_NONE)
+-# include "jit/none/AtomicOperations-none.h"
++# include "jit/none/AtomicOperations-ppc.h"
+ #elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+ # include "jit/x86-shared/AtomicOperations-x86-shared.h"
+ #else
diff --git a/pcr/icedove-hardening/no-neon.patch b/pcr/icedove-hardening/no-neon.patch
new file mode 100644
index 000000000..af8bf198d
--- /dev/null
+++ b/pcr/icedove-hardening/no-neon.patch
@@ -0,0 +1,96 @@
+--- mozilla/configure.orig 2016-04-19 12:42:57.280811615 -0600
++++ mozilla/configure 2016-04-19 12:44:20.697690476 -0600
+@@ -7389,14 +7389,7 @@
+ rm -f conftest*
+ echo "$ac_t"""$result"" 1>&6
+ if test "$result" = "yes"; then
+- cat >> confdefs.pytmp <<\EOF
+- (''' HAVE_ARM_SIMD ''', ' 1 ')
+-EOF
+-cat >> confdefs.h <<\EOF
+-#define HAVE_ARM_SIMD 1
+-EOF
+-
+- HAVE_ARM_SIMD=1
++ HAVE_ARM_SIMD=
+ fi
+
+ echo $ac_n "checking ARM version support in compiler""... $ac_c" 1>&6
+@@ -7428,27 +7421,13 @@
+ rm -f conftest*
+ echo "$ac_t"""$result"" 1>&6
+ if test "$result" = "yes"; then
+- cat >> confdefs.pytmp <<\EOF
+- (''' HAVE_ARM_NEON ''', ' 1 ')
+-EOF
+-cat >> confdefs.h <<\EOF
+-#define HAVE_ARM_NEON 1
+-EOF
+-
+- HAVE_ARM_NEON=1
++ HAVE_ARM_NEON=
+
+ if test -n "$ARM_ARCH"; then
+ if test "$ARM_ARCH" -lt 7; then
+ BUILD_ARM_NEON=
+ else
+- cat >> confdefs.pytmp <<\EOF
+- (''' BUILD_ARM_NEON ''', ' 1 ')
+-EOF
+-cat >> confdefs.h <<\EOF
+-#define BUILD_ARM_NEON 1
+-EOF
+-
+- BUILD_ARM_NEON=1
++ BUILD_ARM_NEON=
+ fi
+ fi
+ fi
+--- mozilla/js/src/configure.orig 2016-04-07 15:33:39.000000000 -0600
++++ mozilla/js/src/configure 2016-04-19 12:44:20.697690476 -0600
+@@ -6578,14 +6578,7 @@
+ rm -f conftest*
+ echo "$ac_t"""$result"" 1>&6
+ if test "$result" = "yes"; then
+- cat >> confdefs.pytmp <<\EOF
+- (''' HAVE_ARM_SIMD ''', ' 1 ')
+-EOF
+-cat >> confdefs.h <<\EOF
+-#define HAVE_ARM_SIMD 1
+-EOF
+-
+- HAVE_ARM_SIMD=1
++ HAVE_ARM_SIMD=
+ fi
+
+ echo $ac_n "checking ARM version support in compiler""... $ac_c" 1>&6
+@@ -6617,27 +6610,13 @@
+ rm -f conftest*
+ echo "$ac_t"""$result"" 1>&6
+ if test "$result" = "yes"; then
+- cat >> confdefs.pytmp <<\EOF
+- (''' HAVE_ARM_NEON ''', ' 1 ')
+-EOF
+-cat >> confdefs.h <<\EOF
+-#define HAVE_ARM_NEON 1
+-EOF
+-
+- HAVE_ARM_NEON=1
++ HAVE_ARM_NEON=
+
+ if test -n "$ARM_ARCH"; then
+ if test "$ARM_ARCH" -lt 7; then
+ BUILD_ARM_NEON=
+ else
+- cat >> confdefs.pytmp <<\EOF
+- (''' BUILD_ARM_NEON ''', ' 1 ')
+-EOF
+-cat >> confdefs.h <<\EOF
+-#define BUILD_ARM_NEON 1
+-EOF
+-
+- BUILD_ARM_NEON=1
++ BUILD_ARM_NEON=
+ fi
+ fi
+ fi
diff --git a/pcr/icedove-hardening/vendor.js b/pcr/icedove-hardening/vendor.js
new file mode 100644
index 000000000..e65c501d7
--- /dev/null
+++ b/pcr/icedove-hardening/vendor.js
@@ -0,0 +1,231 @@
+pref("app.update.auto", false);
+pref("app.update.enabled", false);
+pref("app.update.url", "about:blank");
+pref("beacon.enabled", false);
+pref("breakpad.reportURL", "about:blank");
+pref("browser.cache.disk.enable", false);
+pref("browser.cache.offline.enable", false);
+pref("browser.fixup.alternate.enabled", false);
+pref("browser.formfill.enable", false);
+pref("browser.link.open_newwindow.restriction", 0); // Bug 9881: Open popups in new tabs (to avoid fullscreen popups)
+pref("browser.display.use_document_fonts", 0); // Prevent font fingerprinting
+pref("browser.download.manager.addToRecentDocs", false);
+pref("browser.download.manager.retention", 1);
+pref("browser.download.manager.scanWhenDone", false); // prevents AV remote reporting of downloads
+pref("browser.download.useDownloadDir", false);
+pref("browser.safebrowsing.appRepURL", "about:blank");
+pref("browser.safebrowsing.enabled", false);
+pref("browser.safebrowsing.malware.enabled", false);
+pref("browser.safebrowsing.provider.mozilla.gethashURL", "about:blank");
+pref("browser.safebrowsing.provider.mozilla.updateURL", "about:blank");
+pref("browser.search.suggest.enabled", false);
+pref("browser.search.geoip.url", "about:blank");
+pref("browser.send_pings", false);
+pref("browser.formfill.enable", false);
+pref("browser.urlbar.autocomplete.enabled", false);
+pref("mail.shell.checkDefaultClient", false);
+pref("calendar.useragent.extra", ""); // Wipe useragent string.
+pref("camera.control.face_detection.enabled", false);
+pref("captivedetect.canonicalURL", "about:blank");
+pref("datareporting.healthreport.service.enabled", false); // Yes, all three of these must be set
+pref("datareporting.healthreport.uploadEnabled", false);
+pref("datareporting.policy.dataSubmissionEnabled", false);
+pref("datareporting.healthreport.about.reportUrl", "data:text/plain,");
+pref("device.sensors.enabled", false);
+pref("devtools.debugger.remote-enabled", false); // https://developer.mozilla.org/docs/Tools/Remote_Debugging/Debugging_Firefox_Desktop#Enable_remote_debugging
+pref("devtools.devices.url", "about:blank");
+pref("devtools.gcli.imgurUploadURL", "about:blank");
+pref("devtools.gcli.jquerySrc", "about:blank");
+pref("devtools.gcli.lodashSrc", "about:blank");
+pref("devtools.gcli.underscoreSrc", "about:blank");
+pref("devtools.remote.wifi.scan", false); // http://forum.top-hat-sec.com/index.php?topic=4951.5;wap2
+pref("devtools.remote.wifi.visible", false);
+pref("dom.battery.enabled", false); // fingerprinting due to differing OS implementations
+pref("dom.enable_performance", false);
+pref("dom.enable_user_timing", false);
+pref("dom.event.highrestimestamp.enabled", false);
+pref("dom.event.clipboardevents.enabled",false);
+pref("dom.gamepad.enabled", false); // bugs.torproject.org/13023
+pref("dom.indexedDB.enabled", false);
+pref("dom.ipc.plugins.flash.subprocess.crashreporter.enabled", false);
+pref("dom.mozApps.signed_apps_installable_from", "about:blank");
+pref("dom.netinfo.enabled", false); // Network Information API provides general information about the system's connection type (WiFi, cellular, etc.)
+pref("dom.network.enabled",false); // fingerprinting due to differing OS implementations
+pref("dom.push.enabled", false);
+pref("dom.storage.enabled", false);
+pref("dom.telephony.enabled", false); // https://wiki.mozilla.org/WebAPI/Security/WebTelephony
+pref("dom.vibrator.enabled", false);
+pref("dom.vr.enabled", false);
+pref("dom.workers.sharedWorkers.enabled", false); // See https://bugs.torproject.org/15562
+pref("dom.idle-observers-api.enabled", false); // disable idle observation
+// Don't disable our bundled extensions in the application directory
+pref("extensions.autoDisableScopes", 11);
+pref("extensions.shownSelectionUI", true);
+pref("extensions.blocklist.detailsURL", "about:blank");
+pref("extensions.blocklist.enabled", false); // https://trac.torproject.org/projects/tor/ticket/6734
+pref("extensions.blocklist.itemURL", "about:blank");
+pref("extensions.blocklist.url", "about:blank");
+pref("extensions.bootstrappedAddons", "{}");
+pref("extensions.databaseSchema", 3);
+pref("extensions.enabledScopes", 1);
+pref("extensions.getAddons.cache.enabled", false); // https://blog.mozilla.org/addons/how-to-opt-out-of-add-on-metadata-updates/
+pref("extensions.getAddons.get.url", "about:blank");
+pref("extensions.getAddons.getWithPerformance.url", "about:blank");
+pref("extensions.getAddons.link.url", "https://directory.fsf.org/wiki/Icedove");
+pref("extensions.getAddons.recommended.url", "about:blank");
+pref("extensions.getAddons.search.browseURL", "https://directory.fsf.org/wiki/Icedove");
+pref("extensions.getAddons.search.url", "https://directory.fsf.org/wiki/Icedove");
+pref("extensions.webservice.discoverURL", "https://directory.fsf.org/wiki/Icedove");
+pref("extensions.pendingOperations", false);
+pref("extensions.update.autoUpdateDefault", false);
+pref("extensions.update.background.url", "about:blank");
+pref("extensions.update.enabled", false); // Users can run their own updates on addons, fingerprints installed addons.
+pref("extensions.enigmail.addHeaders", false);
+pref("extensions.engimail.useDefaultComment", true);
+pref("extensions.enigmail.agentAdditionalParam", "--no-emit-version --no-comments --display-charset utf-8 --keyserver-options http-proxy=socks5h://127.0.0.1:9050");
+pref("extensions.enigmail.mimeHashAlgorithm", 5);
+pref("general.useragent.override", "");
+pref("geo.enabled", false);
+pref("gfx.downloadable_fonts.fallback_delay", -1);
+pref("javascript.enabled", false); // We don't need to run JS in an e-mail client. Use a browser..
+pref("javascript.options.asmjs", false); // Multiple security advisories, low level js
+pref("keyword.enabled", false);
+pref("layers.acceleration.disabled", true);
+pref("layout.css.visited_links_enabled", false);
+pref("lightweightThemes.update.enabled", false); // We can update our themes manually, may fingerprint the user.
+pref("mail.instrumentation.askUser", false);
+pref("mail.instrumentation.postUrl", "about:blank");
+pref("mail.instrumentation.userOptedIn", false);
+pref("mailnews.start_page.enabled", false); // http://anonymous-proxy-servers.net/en/help/thunderbird.html
+pref("mailnews.start_page.override_url", "http://wiki.debian.org/Icedove/WhatsNew45");
+pref("mailnews.send_default_charset", "UTF-8");
+pref("mailnews.send_plaintext_flowed", false);
+pref("mailnews.display.prefer_plaintext", true);
+pref("mailnews.display.disallow_mime_handlers", 3); // http://www.bucksch.org/1/projects/mozilla/108153/
+pref("mailnews.display.html_as", 1); // Convert HTML to text and then back again.
+pref("mailnews.reply_header_type", 1);
+pref("mailnews.reply_header_authorwrote", "%s"); // https://lists.torproject.org/pipermail/tor-talk/2012-May/024395.html
+pref("mailnews.reply_header_authorwrotesingle", "#1");
+pref("mailnews.headers.showSender", true);
+pref("mailnews.message_display.allow_plugins", false); // Disable plugin support.
+pref("mailnews.migration.header_addons_url", "");
+pref("mailnews.messageid_browser.url", "");
+pref("mailnews.display.original_date", false); // Don't convert to our local date. This may matter in a reply, etc.
+pref("mail.cloud_files.enabled", false); // Disable "Cloud" advertisements
+pref("mail.cloud_files.inserted_urls.footer.link", "");
+pref("mail.smtpserver.default.hello_argument", "[127.0.0.1]"); // Prevent hostname leaks.
+//pref("mail.provider.enabled", false); // Disable Thunderbird's 'Get new account' wizard.
+pref("mail.inline_attachments", false); // Disable inline attachments.
+pref("mail.addr_book.mapit_url.format", "");
+pref("mail.addr_book.mapit_url.1.format", ""); // Pushes addressbook info to GoogleMaps without HTTPS unless changed or disabled http://www-archive.mozilla.org/mailnews/arch/addrbook/hiddenprefs.html
+pref("mail.addr_book.mapit_url.2.format", "");
+pref("mail.server.default.use_idle", false); // Do not IDLE (disable push mail).
+pref("media.autoplay.enabled", false);
+pref("media.cache_size", 0);
+pref("media.getusermedia.screensharing.allowed_domains", ""); // We really don't want to be promoting Cisco and Cloudflare in a whitelist here.
+pref("media.getusermedia.screensharing.enabled", false);
+pref("media.gmp-manager.url", "about:blank"); // Disable Gecko media plugins: https://wiki.mozilla.org/GeckoMediaPlugins
+pref("media.gmp-manager.url.override", "data:text/plain,");
+pref("media.navigator.enabled", false);
+pref("media.peerconnection.enabled", false); // Disable WebRTC interfaces
+pref("media.peerconnection.ice.default_address_only", true);
+pref("media.video_stats.enabled", false);
+pref("media.webspeech.recognition.enable", false);
+pref("media.track.enabled", false);
+pref("network.allow-experiments", false);
+pref("network.captive-portal-service.enabled", false);
+pref("network.cookie.cookieBehavior", 1);
+pref("network.cookie.lifetimePolicy", 2); // http://kb.mozillazine.org/Network.cookie.lifetimePolicy
+pref("network.dns.disablePrefetch", true);
+pref("network.http.altsvc.enabled", false);
+pref("network.http.altsvc.oe", false); // https://trac.torproject.org/projects/tor/ticket/16673
+pref("network.http.connection-retry-timeout", 0);
+pref("network.http.max-persistent-connections-per-proxy", 256);
+pref("network.http.pipelining", true);
+pref("network.http.pipelining.aggressive", true);
+pref("network.http.pipelining.max-optimistic-requests", 3);
+pref("network.http.pipelining.maxrequests", 10);
+pref("network.http.pipelining.maxrequests", 12);
+pref("network.http.pipelining.read-timeout", 60000);
+pref("network.http.pipelining.reschedule-timeout", 15000);
+pref("network.http.pipelining.ssl", true);
+pref("network.http.proxy.pipelining", true);
+pref("network.http.referer.spoofSource", true);
+pref("network.http.sendRefererHeader", 2);
+pref("network.http.sendSecureXSiteReferrer", false);
+pref("network.http.spdy.enabled", false); // Stores state and may have keepalive issues (both fixable)
+pref("network.http.spdy.enabled.v2", false); // Seems redundant, but just in case
+pref("network.http.spdy.enabled.v3", false); // Seems redundant, but just in case
+pref("network.http.speculative-parallel-limit", 0);
+pref("network.jar.block-remote-files", true); // https://bugzilla.mozilla.org/show_bug.cgi?id=1173171
+pref("network.jar.open-unsafe-types", false);
+pref("network.manage-offline-status", false); // https://trac.torproject.org/projects/tor/ticket/18945
+pref("network.prefetch-next", false);
+pref("network.protocol-handler.warn-external.http", true);
+pref("network.protocol-handler.warn-external.https", true);
+pref("network.protocol-handler.warn-external.ftp", true);
+pref("network.protocol-handler.warn-external.file", true);
+pref("network.protocol-handler.warn-external-default", true);
+pref("network.protocol-handler.external-default", false);
+pref("network.protocol-handler.external.mailto", false);
+pref("network.protocol-handler.external.news", false);
+pref("network.protocol-handler.external.nntp", false);
+pref("network.protocol-handler.external.snews", false);
+pref("network.protocol-handler.warn-external.mailto", true);
+pref("network.protocol-handler.warn-external.news", true);
+pref("network.protocol-handler.warn-external.nntp", true);
+pref("network.protocol-handler.warn-external.snews", true);
+pref("network.proxy.no_proxies_on", ""); // For fingerprinting and local service vulns (#10419)
+pref("network.proxy.socks", "127.0.0.1");
+pref("network.proxy.socks_port", 9050);
+pref("network.proxy.socks_remote_dns", true);
+pref("network.proxy.type", 0);
+pref("network.security.ports.banned", "9050,9051,9150,9151");
+pref("network.websocket.max-connections", 0);
+pref("network.websocket.enabled", false);
+pref("pfs.datasource.url", "about:blank");
+pref("plugins.click_to_play", true);
+pref("plugins.crash.supportUrl", "about:blank");
+pref("privacy.trackingprotection.enabled", true);
+pref("purple.logging.log_chats", false); // Disable messenger logging and auto-start
+pref("purple.logging.log_ims", false);
+pref("purple.logging.log_system", false);
+pref("purple.conversations.im.send_typing", false);
+pref("messenger.startup.action", 0);
+pref("messenger.conversations.autoAcceptChatInvitations", 0); // Ignore invitations; do not automatically accept them.
+pref("rss.display.prefer_plaintext", true);
+pref("rss.display.disallow_mime_handlers", 3);
+pref("rss.display.html_as", 1);
+pref("security.OCSP.enabled", 0);
+pref("security.OCSP.require", false);
+//pref("security.ask_for_password", 0);
+pref("security.cert_pinning.enforcement_level", 2); // https://trac.torproject.org/projects/tor/ticket/16206
+pref("security.enable_tls_session_tickets", false);
+pref("security.mixed_content.block_active_content", true); // Note: Can be disabled for user experience. https://bugzilla.mozilla.org/show_bug.cgi?id=878890
+pref("security.nocertdb", false);
+pref("security.ssl.disable_session_identifiers", true);
+pref("security.ssl.enable_false_start", true);
+pref("security.ssl.require_safe_negotiation", true);
+pref("security.ssl.treat_unsafe_negotiation_as_broken", true);
+pref("security.ssl3.rsa_seed_sha", true);
+pref("security.tls.insecure_fallback_hosts.use_static_list", false);
+pref("security.tls.unrestricted_rc4_fallback", false);
+pref("security.tls.version.max", 3);
+pref("security.tls.version.min", 1);
+pref("security.warn_entering_weak", true);
+pref("security.warn_submit_insecure", true);
+pref("signon.autofillForms", false); // disable cross-site form exposure from password manager - http://kb.mozillazine.org/Signon.autofillForms
+pref("social.directories", "");
+pref("social.enabled", false);
+pref("social.remote-install.enabled", false); // Disable Social API for content
+pref("social.shareDirectory", "");
+pref("social.toast-notifications.enabled", false);
+pref("social.whitelist", "");
+pref("toolkit.telemetry.enabled", false);
+pref("toolkit.telemetry.server", "about:blank");
+pref("ui.key.menuAccessKeyFocuses", false);
+pref("webgl.disable-extensions", true);
+pref("webgl.disabled", true);
+pref("webgl.min_capability_mode", true);
+pref("xpinstall.signatures.required", true); // Requires AMO signing key for addons
+pref("xpinstall.whitelist.add", "");
diff --git a/pcr/iceweasel-hardening/PKGBUILD b/pcr/iceweasel-hardening/PKGBUILD
new file mode 100644
index 000000000..790b18177
--- /dev/null
+++ b/pcr/iceweasel-hardening/PKGBUILD
@@ -0,0 +1,213 @@
+# Maintainer: André Silva <emulatorman@parabola.nu>
+# Contributor: Márcio Silva <coadde@parabola.nu>
+# Contributor (ConnochaetOS): Henry Jensen <hjensen@connochaetos.org>
+# Contributor: Luke Shumaker <lukeshu@sbcglobal.net>
+# Contributor: fauno <fauno@kiwwwi.com.ar>
+# Contributor: vando <facundo@esdebian.org>
+# Contributor (Arch): Jakub Schmidtke <sjakub@gmail.com>
+# Contributor: Figue <ffigue at gmail>
+# Contributor: taro-k <taro-k@movasense_com>
+# Contributor: Michał Masłowski <mtjm@mtjm.eu>
+# Contributor: Luke R. <g4jc@openmailbox.org>
+# Contributor: Isaac David <isacdaavid@isacdaavid.info>
+# Thank you very much to the older contributors:
+# Contributor: evr <evanroman at gmail>
+# Contributor: Muhammad 'MJ' Jassim <UnbreakableMJ@gmail.com>
+
+_pgo=false
+
+# We're getting this from Debian Sid
+_debname=firefox
+_brandingver=49.0
+_brandingrel=1
+_debver=49.0
+_debrel=deb4
+_debrepo=http://ftp.debian.org/debian/pool/main/
+_parabolarepo=https://repo.parabola.nu/other/iceweasel
+debfile() { echo $@|sed -r 's@(.).*@\1/&/&@'; }
+
+_pkgname=firefox
+pkgname=iceweasel-hardening
+epoch=1
+pkgver=$_debver.$_debrel
+pkgrel=1
+pkgdesc="A libre version of Debian Iceweasel, the standalone web browser based on Mozilla Firefox, with several patches that were introduced to strengthen and protect the end user from security threats"
+arch=(i686 x86_64 armv7h)
+license=(MPL GPL LGPL)
+depends=(alsa-lib dbus-glib ffmpeg gtk2 gtk3 hunspell icu=57.1 libevent libvpx=1.6.0 libxt mime-types mozilla-common nss sqlite startup-notification ttf-font)
+makedepends=(autoconf2.13 diffutils gconf imagemagick imake inetutils libidl2 libpulse librsvg-stable libxslt mesa mozilla-searchplugins pkg-config python2 quilt unzip yasm zip)
+makedepends_i686=(rust)
+makedepends_x86_64=("${makedepends_i686[@]}")
+options=(!emptydirs !makeflags debug)
+if $_pgo; then
+ makedepends+=(xorg-server-xvfb)
+ options+=(!ccache)
+fi
+optdepends=('networkmanager: Location detection via available WiFi networks'
+ 'libnotify: Notification integration'
+ 'upower: Battery API')
+url="https://wiki.parabola.nu/${pkgname%-*}"
+replaces=("${pkgname%-*}-libre" "$_pkgname")
+conflicts=("${pkgname%-*}-libre" "${pkgname%-*}")
+provides=("${pkgname%-*}")
+install=${pkgname%-*}.install
+source=("$_debrepo/`debfile $_debname`_$_debver.orig.tar.xz"
+ "$_debrepo/`debfile $_debname`_$_debver-${_debrel#deb}.debian.tar.xz"
+ "$_parabolarepo/${pkgname}_$_brandingver-$_brandingrel.branding.tar.xz"
+ "$_parabolarepo/${pkgname}_$_brandingver-$_brandingrel.branding.tar.xz.sig"
+ mozconfig
+ libre.patch
+ remove-default-and-shell-icons-in-packaging-manifest.patch
+ gnu_headshadow.png
+ drm-free.png
+ ${pkgname%-*}.desktop
+ ${pkgname%-*}-install-dir.patch
+ vendor.js
+ enable-object-directory-paths.patch
+ mozilla-1253216.patch
+ mozilla-build-arm.patch)
+sha256sums=('2f463afd3c74eb9477f58525214f06498357ff90f01b45fb2675fc77c57bcffe'
+ '8e4051a587e380849226fa0de89a02468c45133a758665dc2a7064a248f138a8'
+ 'c0fd88e37187298a7658919cf2e4b6d024425b781d6aff5bdba49dc991f379d3'
+ 'SKIP'
+ '8212fd5e341a251c97871c0f114f6332c78326f707f9d20eddc8d644e0c5c988'
+ '013af398e97da9e855a143582816bf819e0d9d8d2b0e323d6b832f3df1157fdd'
+ '32f1fe3ad4f80d0ae419064db2abe49b97cd7cb18c35d68be1a2befb60172a2a'
+ '93e3001ce152e1d142619e215a9ef07dd429943b99d21726c25da9ceb31e31cd'
+ '56eba484179c7f498076f8dc603d8795e99dce8c6ea1da9736318c59d666bff6'
+ '87034dbb640f70454b27d1695a6f03b6fd1ab81c82eb4d8c771db925ae03d408'
+ '3aea6676f1e53a09673b6ae219d281fc28054beb6002b09973611c02f827651d'
+ 'aec1e2c3a1f5626c39d5d71000a45033de5b67b5fb9cb437a45f16ee5c5d2dc3'
+ 'e260e555b261aabab1e48786dd514eeea056e4402af7cfd4dfd1d32858441484'
+ 'fbb6011501a74a8ea6d01c041870fcefb7ef2859c134aedc676e5f6452833f65'
+ '56eecee8162c138c442773d66483886f1242c8dd2b16eed5711ae5e63d9b0e3a')
+validpgpkeys=(
+ 'C92BAA713B8D53D3CAE63FC9E6974752F9704456' # André Silva
+ '684D54A189305A9CC95446D36B888913DDB59515' # Márcio Silva
+)
+
+prepare() {
+ cd "$srcdir/$_pkgname-$_debver"
+ mv "$srcdir/debian" .
+ mv "$srcdir/${pkgname%-*}-$_brandingver/branding" debian
+ mv "$srcdir/${pkgname%-*}-$_brandingver/patches/iceweasel-branding" debian/patches
+ cat "$srcdir/${pkgname%-*}-$_brandingver/patches/series" >> debian/patches/series
+
+ export QUILT_PATCHES=debian/patches
+ export QUILT_REFRESH_ARGS='-p ab --no-timestamps --no-index'
+ export QUILT_DIFF_ARGS='--no-timestamps'
+
+ quilt push -av
+
+ # Put gnu_headshadow.png and drm-free.png in the source code
+ install -m644 "$srcdir/"{gnu_headshadow,drm-free}.png \
+ browser/base/content/abouthome
+
+ # Useless since we are doing it ourselves
+ patch -Np1 -i "$srcdir/remove-default-and-shell-icons-in-packaging-manifest.patch"
+
+ # Enable object directory paths for Iceweasel rebranding
+ patch -Np1 -i "$srcdir/enable-object-directory-paths.patch"
+
+ # Install to /usr/lib/${pkgname%-*}
+ patch -Np1 -i "$srcdir/${pkgname%-*}-install-dir.patch"
+
+ # Patch and remove anything that's left
+ patch -Np1 -i "$srcdir/libre.patch"
+ sed -i 's|Adobe Flash|SWF Player|g;
+ ' browser/base/content/pageinfo/permissions.js \
+ browser/base/content/browser-plugins.js
+ sed -i '\|["]displayName["][:] ["]Flash["]| s|Flash|SWF Player|
+ \|["]displayName["][:] ["]Shockwave["]| s|Shockwave|DCR Player|
+ \|["]displayName["][:] ["]QuickTime["]| s|QuickTime|MOV Player|
+ \|installLinux| s|true|false|
+ ' browser/base/content/browser-plugins.js
+
+ # Load our build config, disable SafeSearch
+ cp "$srcdir/mozconfig" .mozconfig
+
+ mkdir "$srcdir/path"
+ ln -s /usr/bin/python2 "$srcdir/path/python"
+
+ # Load our searchplugins
+ rm -rv browser/locales/en-US/searchplugins
+ cp -av /usr/lib/mozilla/searchplugins browser/locales/en-US
+
+ # Disable various components at the source level
+ sed -i 's|[;]1|;0|' toolkit/components/telemetry/TelemetryStartup.manifest || die "failed break telemetry startup"
+ sed -i 's|[;]1|;0|' browser/experiments/Experiments.manifest || die "failed to break ExperimentsService"
+ sed -i '/pocket/d' browser/extensions/moz.build || die "failed to wipe pocket"
+
+ # ARM-specific changes:
+ if [[ "$CARCH" == arm* ]]; then
+ sed -i '/ac_add_options --enable-rust/d' .mozconfig
+ echo "ac_add_options --disable-ion" >> .mozconfig
+ echo "ac_add_options --disable-elf-hack" >> .mozconfig
+ echo "ac_add_options --disable-webrtc" >> .mozconfig
+
+ # Disable gold linker, reduce memory consumption at link time
+ sed -i '/ac_add_options --enable-gold/d' .mozconfig
+ LDFLAGS+=" -Wl,--no-keep-memory -Wl,--reduce-memory-overheads"
+ echo "ac_add_options --disable-tests" >> .mozconfig
+ echo "ac_add_options --disable-debug" >> .mozconfig
+
+ patch -p1 -i ../mozilla-1253216.patch
+ patch -p1 -i ../mozilla-build-arm.patch
+ fi
+}
+
+build() {
+ cd "$srcdir/$_pkgname-$_debver"
+
+ # _FORTIFY_SOURCE causes configure failures
+ CPPFLAGS+=" -O2"
+
+ # Hardening
+ LDFLAGS+=" -Wl,-z,now"
+
+ # GCC 6
+ CXXFLAGS+=" -fno-delete-null-pointer-checks -fno-schedule-insns2"
+
+ export PATH="$srcdir/path:$PATH"
+
+ if $_pgo; then
+ # Do PGO
+ xvfb-run -a -s "-extension GLX -screen 0 1280x1024x24" \
+ make -f client.mk build MOZ_PGO=1
+ else
+ make -f client.mk build
+ fi
+}
+
+package() {
+ cd "$srcdir/$_pkgname-$_debver"
+ make -f client.mk DESTDIR="$pkgdir" INSTALL_SDK= install
+
+ install -Dm644 ../vendor.js "$pkgdir/usr/lib/${pkgname%-*}/browser/defaults/preferences/vendor.js"
+
+ _brandingdir=debian/branding
+ brandingdir=moz-objdir/$_brandingdir
+ icondir="$pkgdir/usr/share/icons/hicolor"
+ for i in 16 22 24 32 48 64 128 192 256 384; do
+ rsvg-convert -w $i -h $i "$_brandingdir/${pkgname}_icon.svg" \
+ -o "$brandingdir/default$i.png"
+ install -Dm644 "$brandingdir/default$i.png" \
+ "$icondir/${i}x${i}/apps/${pkgname%-*}.png"
+ done
+
+ install -Dm644 "$_brandingdir/${pkgname}_icon.svg" \
+ "$icondir/scalable/apps/${pkgname%-*}.svg"
+
+ install -d "$pkgdir/usr/share/applications"
+ install -m644 "$srcdir/${pkgname%-*}.desktop" \
+ "$pkgdir/usr/share/applications"
+
+ # Use system-provided dictionaries
+ rm -rf "$pkgdir/usr/lib/${pkgname%-*}/"{dictionaries,hyphenation}
+ ln -s /usr/share/hunspell "$pkgdir/usr/lib/${pkgname%-*}/dictionaries"
+ ln -s /usr/share/hyphen "$pkgdir/usr/lib/${pkgname%-*}/hyphenation"
+
+ # Replace duplicate binary with symlink
+ # https://bugzilla.mozilla.org/show_bug.cgi?id=658850
+ ln -sf ${pkgname%-*} "$pkgdir/usr/lib/${pkgname%-*}/${pkgname%-*}-bin"
+}
diff --git a/pcr/iceweasel-hardening/drm-free.png b/pcr/iceweasel-hardening/drm-free.png
new file mode 100644
index 000000000..e30994e67
--- /dev/null
+++ b/pcr/iceweasel-hardening/drm-free.png
Binary files differ
diff --git a/pcr/iceweasel-hardening/enable-object-directory-paths.patch b/pcr/iceweasel-hardening/enable-object-directory-paths.patch
new file mode 100644
index 000000000..bc938c66e
--- /dev/null
+++ b/pcr/iceweasel-hardening/enable-object-directory-paths.patch
@@ -0,0 +1,13 @@
+diff --git a/python/mozbuild/mozbuild/frontend/context.py b/python/mozbuild/mozbuild/frontend/context.py
+index 41ae8ae..dcc3263 100644
+--- a/python/mozbuild/mozbuild/frontend/context.py
++++ b/python/mozbuild/mozbuild/frontend/context.py
+@@ -408,8 +408,6 @@ class Path(ContextDerivedValue, unicode):
+ class SourcePath(Path):
+ """Like Path, but limited to paths in the source directory."""
+ def __init__(self, context, value):
+- if value.startswith('!'):
+- raise ValueError('Object directory paths are not allowed')
+ if value.startswith('%'):
+ raise ValueError('Filesystem absolute paths are not allowed')
+ super(SourcePath, self).__init__(context, value)
diff --git a/pcr/iceweasel-hardening/gnu_headshadow.png b/pcr/iceweasel-hardening/gnu_headshadow.png
new file mode 100644
index 000000000..e0f73a3bf
--- /dev/null
+++ b/pcr/iceweasel-hardening/gnu_headshadow.png
Binary files differ
diff --git a/pcr/iceweasel-hardening/iceweasel-install-dir.patch b/pcr/iceweasel-hardening/iceweasel-install-dir.patch
new file mode 100644
index 000000000..af113fa85
--- /dev/null
+++ b/pcr/iceweasel-hardening/iceweasel-install-dir.patch
@@ -0,0 +1,13 @@
+diff --git a/config/baseconfig.mk b/config/baseconfig.mk
+index 7ca8e35..6e92846 100644
+--- a/config/baseconfig.mk
++++ b/config/baseconfig.mk
+@@ -5,7 +5,7 @@
+ MOZ_APP_BASE_VERSION = $(firstword $(subst ., ,$(MOZ_APP_VERSION))).$(word 2,$(subst ., ,$(MOZ_APP_VERSION)))
+ includedir := $(includedir)/$(MOZ_APP_NAME)-$(MOZ_APP_BASE_VERSION)
+ idldir = $(datadir)/idl/$(MOZ_APP_NAME)-$(MOZ_APP_BASE_VERSION)
+-installdir = $(libdir)/$(MOZ_APP_NAME)-$(MOZ_APP_BASE_VERSION)
++installdir = $(libdir)/$(MOZ_APP_NAME)
+ sdkdir = $(libdir)/$(MOZ_APP_NAME)-devel-$(MOZ_APP_BASE_VERSION)
+ ifndef TOP_DIST
+ TOP_DIST = dist
diff --git a/pcr/iceweasel-hardening/iceweasel.desktop b/pcr/iceweasel-hardening/iceweasel.desktop
new file mode 100644
index 000000000..028aeffde
--- /dev/null
+++ b/pcr/iceweasel-hardening/iceweasel.desktop
@@ -0,0 +1,310 @@
+[Desktop Entry]
+Version=1.0
+Name=Iceweasel
+GenericName=Web Browser
+GenericName[ar]=متصفح ويب
+GenericName[ast]=Restolador Web
+GenericName[bn]=ওয়েব ব্রাউজার
+GenericName[ca]=Navegador web
+GenericName[cs]=Webový prohlížeč
+GenericName[da]=Webbrowser
+GenericName[de]=Webbrowser
+GenericName[el]=Περιηγητής διαδικτύου
+GenericName[es]=Navegador web
+GenericName[et]=Veebibrauser
+GenericName[fa]=مرورگر اینترنتی
+GenericName[fi]=WWW-selain
+GenericName[fr]=Navigateur Web
+GenericName[gl]=Navegador Web
+GenericName[he]=דפדפן אינטרנט
+GenericName[hr]=Web preglednik
+GenericName[hu]=Webböngésző
+GenericName[it]=Browser Web
+GenericName[ja]=ウェブ・ブラウザ
+GenericName[ko]=웹 브라우저
+GenericName[ku]=Geroka torê
+GenericName[lt]=Interneto naršyklė
+GenericName[nb]=Nettleser
+GenericName[nl]=Webbrowser
+GenericName[nn]=Nettlesar
+GenericName[no]=Nettleser
+GenericName[pl]=Przeglądarka WWW
+GenericName[pt]=Navegador Web
+GenericName[pt_BR]=Navegador Web
+GenericName[ro]=Navigator Internet
+GenericName[ru]=Веб-браузер
+GenericName[sk]=Internetový prehliadač
+GenericName[sl]=Spletni brskalnik
+GenericName[sv]=Webbläsare
+GenericName[tr]=Web Tarayıcı
+GenericName[ug]=توركۆرگۈ
+GenericName[uk]=Веб-браузер
+GenericName[vi]=Trình duyệt Web
+GenericName[zh_CN]=网络浏览器
+GenericName[zh_TW]=網路瀏覽器
+Comment=Browse the Web
+Comment[ar]=تصفح الشبكة العنكبوتية العالمية
+Comment[ast]=Restola pela Rede
+Comment[bn]=ইন্টারনেট ব্রাউজ করুন
+Comment[ca]=Navegueu per el web
+Comment[cs]=Prohlížení stránek World Wide Webu
+Comment[da]=Surf på internettet
+Comment[de]=Im Internet surfen
+Comment[el]=Μπορείτε να περιηγηθείτε στο διαδίκτυο (Web)
+Comment[es]=Navegue por la web
+Comment[et]=Lehitse veebi
+Comment[fa]=صفحات شبکه جهانی اینترنت را مرور نمایید
+Comment[fi]=Selaa Internetin WWW-sivuja
+Comment[fr]=Naviguer sur le Web
+Comment[gl]=Navegar pola rede
+Comment[he]=גלישה ברחבי האינטרנט
+Comment[hr]=Pretražite web
+Comment[hu]=A világháló böngészése
+Comment[it]=Esplora il web
+Comment[ja]=ウェブを閲覧します
+Comment[ko]=웹을 돌아 다닙니다
+Comment[ku]=Li torê bigere
+Comment[lt]=Naršykite internete
+Comment[nb]=Surf på nettet
+Comment[nl]=Verken het internet
+Comment[nn]=Surf på nettet
+Comment[no]=Surf på nettet
+Comment[pl]=Przeglądanie stron WWW
+Comment[pt]=Navegue na Internet
+Comment[pt_BR]=Navegue na Internet
+Comment[ro]=Navigați pe Internet
+Comment[ru]=Доступ в Интернет
+Comment[sk]=Prehliadanie internetu
+Comment[sl]=Brskajte po spletu
+Comment[sv]=Surfa på webben
+Comment[tr]=İnternet'te Gezinin
+Comment[ug]=دۇنيادىكى توربەتلەرنى كۆرگىلى بولىدۇ
+Comment[uk]=Перегляд сторінок Інтернету
+Comment[vi]=Để duyệt các trang web
+Comment[zh_CN]=浏览互联网
+Comment[zh_TW]=瀏覽網際網路
+Exec=iceweasel %u
+Icon=iceweasel
+Terminal=false
+Type=Application
+MimeType=text/html;text/xml;application/xhtml+xml;application/vnd.mozilla.xul+xml;text/mml;x-scheme-handler/http;x-scheme-handler/https;
+StartupNotify=true
+Categories=Network;WebBrowser;
+Keywords=web;browser;internet;
+Actions=new-window;new-private-window;
+
+[Desktop Action new-window]
+Name=New Window
+Name[ach]=Dirica manyen
+Name[af]=Nuwe venster
+Name[an]=Nueva finestra
+Name[ar]=نافذة جديدة
+Name[as]=নতুন উইন্ডো
+Name[ast]=Ventana nueva
+Name[az]=Yeni Pəncərə
+Name[be]=Новае акно
+Name[bg]=Нов прозорец
+Name[bn_BD]=নতুন উইন্ডো (N)
+Name[bn_IN]=নতুন উইন্ডো
+Name[br]=Prenestr nevez
+Name[brx]=गोदान उइन्ड'(N)
+Name[bs]=Novi prozor
+Name[ca]=Finestra nova
+Name[cak]=K'ak'a' tzuwäch
+Name[cs]=Nové okno
+Name[cy]=Ffenestr Newydd
+Name[da]=Nyt vindue
+Name[de]=Neues Fenster
+Name[dsb]=Nowe wokno
+Name[el]=Νέο παράθυρο
+Name[en_GB]=New Window
+Name[en_US]=New Window
+Name[en_ZA]=New Window
+Name[eo]=Nova fenestro
+Name[es_AR]=Nueva ventana
+Name[es_CL]=Nueva ventana
+Name[es_ES]=Nueva ventana
+Name[es_MX]=Nueva ventana
+Name[et]=Uus aken
+Name[eu]=Leiho berria
+Name[fa]=پنجره جدید
+Name[ff]=Henorde Hesere
+Name[fi]=Uusi ikkuna
+Name[fr]=Nouvelle fenêtre
+Name[fy_NL]=Nij finster
+Name[ga_IE]=Fuinneog Nua
+Name[gd]=Uinneag ùr
+Name[gl]=Nova xanela
+Name[gn]=Ovetã pyahu
+Name[gu_IN]=નવી વિન્ડો
+Name[he]=חלון חדש
+Name[hi_IN]=नया विंडो
+Name[hr]=Novi prozor
+Name[hsb]=Nowe wokno
+Name[hu]=Új ablak
+Name[hy_AM]=Նոր Պատուհան
+Name[id]=Jendela Baru
+Name[is]=Nýr gluggi
+Name[it]=Nuova finestra
+Name[ja]=新しいウィンドウ
+Name[ja_JP-mac]=新規ウインドウ
+Name[ka]=ახალი ფანჯარა
+Name[kk]=Жаңа терезе
+Name[km]=បង្អួចថ្មី
+Name[kn]=ಹೊಸ ಕಿಟಕಿ
+Name[ko]=새 창
+Name[kok]=नवें जनेल
+Name[ks]=نئئ وِنڈو
+Name[lij]=Neuvo barcon
+Name[lo]=ຫນ້າຕ່າງໃຫມ່
+Name[lt]=Naujas langas
+Name[ltg]=Jauns lūgs
+Name[lv]=Jauns logs
+Name[mai]=नव विंडो
+Name[mk]=Нов прозорец
+Name[ml]=പുതിയ ജാലകം
+Name[mr]=नवीन पटल
+Name[ms]=Tetingkap Baru
+Name[my]=ဝင်းဒိုးအသစ်
+Name[nb_NO]=Nytt vindu
+Name[ne_NP]=नयाँ सञ्झ्याल
+Name[nl]=Nieuw venster
+Name[nn_NO]=Nytt vindauge
+Name[or]=ନୂତନ ୱିଣ୍ଡୋ
+Name[pa_IN]=ਨਵੀਂ ਵਿੰਡੋ
+Name[pl]=Nowe okno
+Name[pt_BR]=Nova janela
+Name[pt_PT]=Nova janela
+Name[rm]=Nova fanestra
+Name[ro]=Fereastră nouă
+Name[ru]=Новое окно
+Name[sat]=नावा विंडो (N)
+Name[si]=නව කවුළුවක්
+Name[sk]=Nové okno
+Name[sl]=Novo okno
+Name[son]=Zanfun taaga
+Name[sq]=Dritare e Re
+Name[sr]=Нови прозор
+Name[sv_SE]=Nytt fönster
+Name[ta]=புதிய சாளரம்
+Name[te]=కొత్త విండో
+Name[th]=หน้าต่างใหม่
+Name[tr]=Yeni pencere
+Name[tsz]=Eraatarakua jimpani
+Name[uk]=Нове вікно
+Name[ur]=نیا دریچہ
+Name[uz]=Yangi oyna
+Name[vi]=Cửa sổ mới
+Name[wo]=Palanteer bu bees
+Name[xh]=Ifestile entsha
+Name[zh_CN]=新建窗口
+Name[zh_TW]=開新視窗
+Exec=iceweasel --new-window %u
+
+[Desktop Action new-private-window]
+Name=New Private Window
+Name[ach]=Dirica manyen me mung
+Name[af]=Nuwe privaatvenster
+Name[an]=Nueva finestra privada
+Name[ar]=نافذة خاصة جديدة
+Name[as]=নতুন ব্যক্তিগত উইন্ডো
+Name[ast]=Ventana privada nueva
+Name[az]=Yeni Məxfi Pəncərə
+Name[be]=Новае акно адасаблення
+Name[bg]=Нов прозорец за поверително сърфиране
+Name[bn_BD]=নতুন ব্যক্তিগত উইন্ডো
+Name[bn_IN]=নতুন ব্যক্তিগত উইন্ডো
+Name[br]=Prenestr merdeiñ prevez nevez
+Name[brx]=गोदान प्राइभेट उइन्ड'
+Name[bs]=Novi privatni prozor
+Name[ca]=Finestra privada nova
+Name[cak]=K'ak'a' ichinan tzuwäch
+Name[cs]=Nové anonymní okno
+Name[cy]=Ffenestr Breifat Newydd
+Name[da]=Nyt privat vindue
+Name[de]=Neues privates Fenster
+Name[dsb]=Nowe priwatne wokno
+Name[el]=Νέο παράθυρο ιδιωτικής περιήγησης
+Name[en_GB]=New Private Window
+Name[en_US]=New Private Window
+Name[en_ZA]=New Private Window
+Name[eo]=Nova privata fenestro
+Name[es_AR]=Nueva ventana privada
+Name[es_CL]=Nueva ventana privada
+Name[es_ES]=Nueva ventana privada
+Name[es_MX]=Nueva ventana privada
+Name[et]=Uus privaatne aken
+Name[eu]=Leiho pribatu berria
+Name[fa]=پنجره ناشناس جدید
+Name[ff]=Henorde Suturo Hesere
+Name[fi]=Uusi yksityinen ikkuna
+Name[fr]=Nouvelle fenêtre de navigation privée
+Name[fy_NL]=Nij priveefinster
+Name[ga_IE]=Fuinneog Nua Phríobháideach
+Name[gd]=Uinneag phrìobhaideach ùr
+Name[gl]=Nova xanela privada
+Name[gn]=Ovetã ñemi pyahu
+Name[gu_IN]=નવી ખાનગી વિન્ડો
+Name[he]=חלון פרטי חדש
+Name[hi_IN]=नयी निजी विंडो
+Name[hr]=Novi privatni prozor
+Name[hsb]=Nowe priwatne wokno
+Name[hu]=Új privát ablak
+Name[hy_AM]=Սկսել Գաղտնի դիտարկում
+Name[id]=Jendela Mode Pribadi Baru
+Name[is]=Nýr huliðsgluggi
+Name[it]=Nuova finestra anonima
+Name[ja]=新しいプライベートウィンドウ
+Name[ja_JP-mac]=新規プライベートウインドウ
+Name[ka]=ახალი პირადი ფანჯარა
+Name[kk]=Жаңа жекелік терезе
+Name[km]=បង្អួចឯកជនថ្មី
+Name[kn]=ಹೊಸ ಖಾಸಗಿ ಕಿಟಕಿ
+Name[ko]=새 사생활 보호 모드
+Name[kok]=नवो खाजगी विंडो
+Name[ks]=نْو پرایوٹ وینڈو
+Name[lij]=Nêuvo barcón privòu
+Name[lo]=ເປີດຫນ້າຕ່າງສວນຕົວຂື້ນມາໃຫມ່
+Name[lt]=Naujas privataus naršymo langas
+Name[ltg]=Jauns privatais lūgs
+Name[lv]=Jauns privātais logs
+Name[mai]=नया निज विंडो (W)
+Name[mk]=Нов приватен прозорец
+Name[ml]=പുതിയ സ്വകാര്യ ജാലകം
+Name[mr]=नवीन वैयक्तिक पटल
+Name[ms]=Tetingkap Persendirian Baharu
+Name[my]=New Private Window
+Name[nb_NO]=Nytt privat vindu
+Name[ne_NP]=नयाँ निजी सञ्झ्याल
+Name[nl]=Nieuw privévenster
+Name[nn_NO]=Nytt privat vindauge
+Name[or]=ନୂତନ ବ୍ୟକ୍ତିଗତ ୱିଣ୍ଡୋ
+Name[pa_IN]=ਨਵੀਂ ਪ੍ਰਾਈਵੇਟ ਵਿੰਡੋ
+Name[pl]=Nowe okno prywatne
+Name[pt_BR]=Nova janela privativa
+Name[pt_PT]=Nova janela privada
+Name[rm]=Nova fanestra privata
+Name[ro]=Fereastră privată nouă
+Name[ru]=Новое приватное окно
+Name[sat]=नावा निजेराक् विंडो (W )
+Name[si]=නව පුද්ගලික කවුළුව (W)
+Name[sk]=Nové okno v režime Súkromné prehliadanie
+Name[sl]=Novo zasebno okno
+Name[son]=Sutura zanfun taaga
+Name[sq]=Dritare e Re Private
+Name[sr]=Нови приватан прозор
+Name[sv_SE]=Nytt privat fönster
+Name[ta]=புதிய தனிப்பட்ட சாளரம்
+Name[te]=కొత్త ఆంతరంగిక విండో
+Name[th]=หน้าต่างส่วนตัวใหม่
+Name[tr]=Yeni gizli pencere
+Name[tsz]=Juchiiti eraatarakua jimpani
+Name[uk]=Приватне вікно
+Name[ur]=نیا نجی دریچہ
+Name[uz]=Yangi maxfiy oyna
+Name[vi]=Cửa sổ riêng tư mới
+Name[wo]=Panlanteeru biir bu bees
+Name[xh]=Ifestile yangasese entsha
+Name[zh_CN]=新建隐私浏览窗口
+Name[zh_TW]=新增隱私視窗
+Exec=iceweasel --private-window %u
diff --git a/pcr/iceweasel-hardening/iceweasel.install b/pcr/iceweasel-hardening/iceweasel.install
new file mode 100644
index 000000000..574e0d3db
--- /dev/null
+++ b/pcr/iceweasel-hardening/iceweasel.install
@@ -0,0 +1,31 @@
+notice() {
+ cat <<EOM
+ == IMPORTANT NOTICE ==
+
+ This package contains several patches that were introduced
+ to strengthen and protect the end user from security threats.
+
+ For users who wish to opt-out of security, you may override options in
+ about:config using a user.js file in your ~/.mozilla's profile folder.
+
+ Some user.js examples:
+ user_pref("dom.storage.enabled", true); # Enables DOM tracking
+ user_pref("network.websocket.max-connections", "5"); # Enables WebSocket IP Leak
+
+ Further reading:
+ * https://lists.parabola.nu/pipermail/dev/2016-October/004522.html
+ * http://kb.mozillazine.org/About:config
+ * http://kb.mozillazine.org/User.js_file
+
+EOM
+}
+
+post_install() {
+ notice
+}
+
+post_upgrade() {
+ post_install
+}
+
+# vim:set ts=2 sw=2 et:
diff --git a/pcr/iceweasel-hardening/libre.patch b/pcr/iceweasel-hardening/libre.patch
new file mode 100644
index 000000000..a434fef2f
--- /dev/null
+++ b/pcr/iceweasel-hardening/libre.patch
@@ -0,0 +1,338 @@
+diff --git a/browser/base/content/abouthome/aboutHome.css b/browser/base/content/abouthome/aboutHome.css
+index c1ef3a4..48e1a16 100644
+--- a/browser/base/content/abouthome/aboutHome.css
++++ b/browser/base/content/abouthome/aboutHome.css
+@@ -343,26 +343,46 @@ body[narrow] #restorePreviousSession::before {
+ width: 32px;
+ }
+
+-#aboutMozilla {
++#aboutGNU {
+ display: block;
+- position: relative; /* pin wordmark to edge of document, not of viewport */
+ -moz-box-ordinal-group: 0;
+ opacity: .5;
+ transition: opacity 150ms;
+ }
+
+-#aboutMozilla:hover {
++#aboutGNU:hover {
+ opacity: 1;
+ }
+
+-#aboutMozilla::before {
+- content: url("chrome://browser/content/abouthome/mozilla.png");
++#aboutGNU::before {
++ content: url("chrome://browser/content/abouthome/gnu_headshadow.png");
+ display: block;
+ position: absolute;
+ top: 12px;
+ right: 12px;
+- width: 69px;
+- height: 19px;
++ width: 200px;
++ height: 110px;
++}
++
++#aboutDRMfree {
++ display: block;
++ -moz-box-ordinal-group: 0;
++ opacity: .5;
++ transition: opacity 150ms;
++}
++
++#aboutDRMfree:hover {
++ opacity: 1;
++}
++
++#aboutDRMfree::before {
++ content: url("chrome://browser/content/abouthome/drm-free.png");
++ display: block;
++ position: absolute;
++ top: 12px;
++ left: 12px;
++ width: 120px;
++ height: 120px;
+ }
+
+ /* [HiDPI]
+@@ -435,9 +455,5 @@ body[narrow] #restorePreviousSession::before {
+ transform: scale(-0.5, 0.5) translateX(24px);
+ transform-origin: top center;
+ }
+-
+- #aboutMozilla::before {
+- content: url("chrome://browser/content/abouthome/mozilla@2x.png");
+- }
+ }
+
+diff --git a/browser/base/content/abouthome/aboutHome.js b/browser/base/content/abouthome/aboutHome.js
+index 8943165..cd2efd8 100644
+--- a/browser/base/content/abouthome/aboutHome.js
++++ b/browser/base/content/abouthome/aboutHome.js
+@@ -9,17 +9,13 @@
+ // * add a <span/> for it in aboutHome.xhtml
+ // * add an entry here in the proper ordering (based on spans)
+ // The <a/> part of the snippet will be linked to the corresponding url.
+-const DEFAULT_SNIPPETS_URLS = [
+- "https://www.mozilla.org/firefox/features/?utm_source=snippet&utm_medium=snippet&utm_campaign=default+feature+snippet"
+-, "https://addons.mozilla.org/firefox/?utm_source=snippet&utm_medium=snippet&utm_campaign=addons"
+-];
++const DEFAULT_SNIPPETS_URLS = [ "" ];
+
+-const SNIPPETS_UPDATE_INTERVAL_MS = 14400000; // 4 hours.
++const SNIPPETS_UPDATE_INTERVAL_MS = 86400000; // 1 Day.
+
+ // IndexedDB storage constants.
+ const DATABASE_NAME = "abouthome";
+ const DATABASE_VERSION = 1;
+-const DATABASE_STORAGE = "persistent";
+ const SNIPPETS_OBJECTSTORE_NAME = "snippets";
+ var searchText;
+
+diff --git a/browser/base/content/abouthome/aboutHome.xhtml b/browser/base/content/abouthome/aboutHome.xhtml
+index 655f64b..6dd78e5 100644
+--- a/browser/base/content/abouthome/aboutHome.xhtml
++++ b/browser/base/content/abouthome/aboutHome.xhtml
+@@ -49,10 +49,6 @@
+ </div>
+
+ <div id="snippetContainer">
+- <div id="defaultSnippets" hidden="true">
+- <span id="defaultSnippet1">&abouthome.defaultSnippet1.v1;</span>
+- <span id="defaultSnippet2">&abouthome.defaultSnippet2.v1;</span>
+- </div>
+ <span id="rightsSnippet" hidden="true">&abouthome.rightsSnippet;</span>
+ <div id="snippets"/>
+ </div>
+@@ -74,7 +70,7 @@
+ <button class="launchButton" id="restorePreviousSession">&historyRestoreLastSession.label;</button>
+ </div>
+
+- <a id="aboutMozilla" href="https://www.mozilla.org/about/?utm_source=about-home&amp;utm_medium=Referral"
+- aria-label="&abouthome.aboutMozilla.label;"/>
++ <a id="aboutGNU" href="https://www.gnu.org"></a>
++ <a id="aboutDRMfree" href="https://www.defectivebydesign.org/drm-free"></a>
+ </body>
+ </html>
+diff --git a/browser/base/jar.mn b/browser/base/jar.mn
+index c9a70fc..ab0f1dd 100644
+--- a/browser/base/jar.mn
++++ b/browser/base/jar.mn
+@@ -32,7 +32,8 @@ browser.jar:
+ content/browser/abouthome/settings.png (content/abouthome/settings.png)
+ content/browser/abouthome/restore.png (content/abouthome/restore.png)
+ content/browser/abouthome/restore-large.png (content/abouthome/restore-large.png)
+- content/browser/abouthome/mozilla.png (content/abouthome/mozilla.png)
++ content/browser/abouthome/gnu_headshadow.png (content/abouthome/gnu_headshadow.png)
++ content/browser/abouthome/drm-free.png (content/abouthome/drm-free.png)
+ content/browser/abouthome/snippet1@2x.png (content/abouthome/snippet1@2x.png)
+ content/browser/abouthome/snippet2@2x.png (content/abouthome/snippet2@2x.png)
+ content/browser/abouthome/downloads@2x.png (content/abouthome/downloads@2x.png)
+@@ -43,7 +44,6 @@ browser.jar:
+ content/browser/abouthome/settings@2x.png (content/abouthome/settings@2x.png)
+ content/browser/abouthome/restore@2x.png (content/abouthome/restore@2x.png)
+ content/browser/abouthome/restore-large@2x.png (content/abouthome/restore-large@2x.png)
+- content/browser/abouthome/mozilla@2x.png (content/abouthome/mozilla@2x.png)
+
+ content/browser/aboutNetError.xhtml (content/aboutNetError.xhtml)
+
+diff --git a/browser/locales/en-US/chrome/browser/aboutHome.dtd b/browser/locales/en-US/chrome/browser/aboutHome.dtd
+index 7e3b57a..6edc89d 100644
+--- a/browser/locales/en-US/chrome/browser/aboutHome.dtd
++++ b/browser/locales/en-US/chrome/browser/aboutHome.dtd
+@@ -11,14 +11,6 @@
+
+ <!ENTITY abouthome.pageTitle "&brandFullName; Start Page">
+
+-<!-- LOCALIZATION NOTE (abouthome.defaultSnippet1.v1):
+- text in <a/> will be linked to the Firefox features page on mozilla.com
+--->
+-<!ENTITY abouthome.defaultSnippet1.v1 "Thanks for choosing Firefox! To get the most out of your browser, learn more about the <a>latest features</a>.">
+-<!-- LOCALIZATION NOTE (abouthome.defaultSnippet2.v1):
+- text in <a/> will be linked to the featured add-ons on addons.mozilla.org
+--->
+-<!ENTITY abouthome.defaultSnippet2.v1 "It’s easy to customize your Firefox exactly the way you want it. <a>Choose from thousands of add-ons</a>.">
+ <!-- LOCALIZATION NOTE (abouthome.rightsSnippet): text in <a/> will be linked to about:rights -->
+ <!ENTITY abouthome.rightsSnippet "&brandFullName; is free and open source software from the non-profit Mozilla Foundation. <a>Know your rights…</a>">
+
+diff --git a/browser/locales/en-US/chrome/browser-region/region.properties b/browser/locales/en-US/chrome/browser-region/region.properties
+index e078ed5..ce2c5ed 100644
+--- a/browser/locales/en-US/chrome/browser-region/region.properties
++++ b/browser/locales/en-US/chrome/browser-region/region.properties
+@@ -3,17 +3,12 @@
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+ # Default search engine
+-browser.search.defaultenginename=Google
++browser.search.defaultenginename=searx
+
+ # Search engine order (order displayed in the search bar dropdown)s
+-browser.search.order.1=Google
+-browser.search.order.2=Yahoo
+-browser.search.order.3=Bing
+-
+-# This is the default set of web based feed handlers shown in the reader
+-# selection UI
+-browser.contentHandlers.types.0.title=My Yahoo!
+-browser.contentHandlers.types.0.uri=https://add.my.yahoo.com/rss?url=%s
++browser.search.order.1=searx
++browser.search.order.2=DuckDuckGo HTML
++browser.search.order.3=DuckDuckGo Lite
+
+ # increment this number when anything gets changed in the list below. This will
+ # cause Firefox to re-read these prefs and inject any new handlers into the
+@@ -22,20 +17,10 @@ browser.contentHandlers.types.0.uri=https://add.my.yahoo.com/rss?url=%s
+ # don't make any spelling errors here.
+ gecko.handlerService.defaultHandlersVersion=4
+
+-# The default set of protocol handlers for webcal:
+-gecko.handlerService.schemes.webcal.0.name=30 Boxes
+-gecko.handlerService.schemes.webcal.0.uriTemplate=https://30boxes.com/external/widget?refer=ff&url=%s
+-
+-# The default set of protocol handlers for mailto:
+-gecko.handlerService.schemes.mailto.0.name=Yahoo! Mail
+-gecko.handlerService.schemes.mailto.0.uriTemplate=https://compose.mail.yahoo.com/?To=%s
+-gecko.handlerService.schemes.mailto.1.name=Gmail
+-gecko.handlerService.schemes.mailto.1.uriTemplate=https://mail.google.com/mail/?extsrc=mailto&url=%s
+-
+ # The default set of protocol handlers for irc:
+-gecko.handlerService.schemes.irc.0.name=Mibbit
+-gecko.handlerService.schemes.irc.0.uriTemplate=https://www.mibbit.com/?url=%s
++gecko.handlerService.schemes.irc.0.name=Freenode Web IRC
++gecko.handlerService.schemes.irc.0.uriTemplate=https://webchat.freenode.net
+
+ # The default set of protocol handlers for ircs:
+-gecko.handlerService.schemes.ircs.0.name=Mibbit
+-gecko.handlerService.schemes.ircs.0.uriTemplate=https://www.mibbit.com/?url=%s
++gecko.handlerService.schemes.ircs.0.name=Freenode Web IRC
++gecko.handlerService.schemes.ircs.0.uriTemplate=https://webchat.freenode.net
+diff --git a/browser/locales/generic/profile/bookmarks.html.in b/browser/locales/generic/profile/bookmarks.html.in
+index cba600e..cd4e711 100644
+--- a/browser/locales/generic/profile/bookmarks.html.in
++++ b/browser/locales/generic/profile/bookmarks.html.in
+@@ -20,13 +20,20 @@
+ <DT><H3 PERSONAL_TOOLBAR_FOLDER="true" ID="rdf:#$FvPhC3">@bookmarks_toolbarfolder@</H3>
+ <DD>@bookmarks_toolbarfolder_description@
+ <DL><p>
+- <DT><A HREF="https://www.mozilla.org/@AB_CD@/firefox/central/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAz5JREFUeNpcU0toXFUY/s49596588ikySSmM8rk0UkJEirVTVEjYk1NUdRFFgouXZQI2k2hUCjdiYIuCi4Kuig0DbqQYgU3Yi0iFRuRCBMwaZvMZDTNY95z3/fM8b8jldpzOeeee/i/737n+/+f4ZExf730rkiaZ9NJMx/nmk5HypMqqLr+ZuD4F67N5ZYejmfRsnvhyKsLhSs3zP70SubgYKHSdFENu+gXAprQIGnvBi5ez0m1b6u7M399+PTx+UvtCKtFi2F6195qXK2byir88esy5ksfYND5DhuhRCtUKBNB0Q7w5Z8ee2GgWdjOn250fn5v5j8F5dOHlZD0kWRgAwp3hrKY0S9BJWKIcQ5PShhNG4+1bHx+IocT+RXcrRSDMfFNRvvt3Oyp/icIrRhUl9hoO4kt3F55Bxf3LkLV20jWOohbDjzXxyc/lMH0cRSyCd1xq+dFhu986t7T0CUwIzB8EkW3O5ibhj44ib7NJhiBKRoB/aS4ZWHjbxtjGQYP7nGRTjim1SaQqYiAVAREpHG8vzWJn+6PQ6CF0HPR7nQQczpYeEWHyWMUkwU8MSECGwgJxAWp9xWKNzkuH3oet+JDlIE9Momedh1G4CN0bfhVG9nsS0BQQthJx0V7j3elq7ihqV5ezQTwZmodP9ZGkU/bOPr4Nr53xtDYsaD7Dg4nNqFaH5OCYSSdGhf7daNmuv6wEKqXk/yExKGBHSznFsH6FFpKQ/JAA0ulUejWLt44lkHXsqDaX6C6Nl4Rnq8vK8s/KThDMlJhkI91YOO+iR3XwEelCdTCBLSgijNzd6DLNfhlHfZ6FtWiWBQpq/V2LdSrrNPljBQkoOjuCiPxAMutOIbkPqYSEqeequGZaTLzdhZhS0PlnlB9bvhtr5CuHj3y2Qj8hVQ/kEopxONEEsO/0yATDYXYAdWrE69JEElXq7Hyk0tro+xBU1yZmr4xrIcvptIRCZlJJAYBmRGRkD08aivA7VDvWPqt564Xn41w/AHB1/u7l1/uGxGU8mNcgodUNDIq0JDeLnpzc1uo1Qr76rWbqyf/142PjsXJqdkmN2YDnQ9oGkJNU+t57q7qUv4y9/t64+HYfwQYAN7OczrzUDvGAAAAAElFTkSuQmCC" ID="rdf:#$GvPhC3">@getting_started@</A>
++ <DT><A HREF="https://www.parabola.nu/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABL0lEQVQ4jWNgoCcoq16VU1GzygnEBtEVDWuV8GooKFuhWVG3uiM3d5UokG4qr1szAaa5vGbVt4ralacwNDU0rGIrr10VBVG0+lxhwyqVsqqVtRW1q6eD5IvL19oB2V+B+D9QzQu4xtDQVZylVavygRKHqurWOlbUrknKK12qWlCwWLK8elUFA8N/xvLy5VYVtas+gzWDDVi9E2QjT1XdcufymjWpQJt1cXmnvHwVP1DzR7hmIC6vW+kOtpnYQKysW30arrlm9RVi9cFBRfXKJTADympWJZNsQFnN6rUQA1adAQU2SZqBXmUGBtozUDiU1qxQJtl2oCY3kO2l1avCSdYMAsBAWwyM2plkaS4p6eYGOv1YQ0MDB1kGlFWuDChuWKZBlmYQqK5eJU22ZkIAAEIlnQZQkzITAAAAAElFTkSuQmCC">Parabola GNU/Linux-libre</A>
+ </DL><p>
+- <DT><H3 ID="rdf:#$ZvPhC3">@firefox_heading@</H3>
++ <DT><H3 ID="rdf:#$YvPhC3">Parabola GNU/Linux-libre</H3>
+ <DL><p>
+- <DT><A HREF="https://www.mozilla.org/@AB_CD@/firefox/help/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwMDAsTBZbkNwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABNElEQVQ4y8WSsU0DURBE3yyWIaAJaqAAN4DPSL6AlIACKIEOyJEgRsIgOOkiInJqgAKowNg7BHdn7MOksNl+zZ//dvbDf5cAiklp22BdVtXdeTEpDYDB9m1VzU6OJuVp2NdEQCaI96fH2YHG4+mDduKYNMYINTcjcGbXzQVDEAphG0k48zUsajIbnAiMIXThpW8EICE0RAK4dvoKg9NIcTiQ589otyHOZLnwqK5nLwBFUZ4igc3iM0d1ff8CMC6mZ6Ihiaqq3gi1aUAnArD00SW1fq5OLBg0ymYmSZsR2/t4e/rGyCLW0sbp3oq+yTYqVgytQWui2FS7XYF7GFprY921T4CNQt8zr47dNzCkIX7y/jBtH+v+RGMQrc828W8pApnZbmEVQp/Ae7BlOy2ttib81/UFc+WRWEbjckIAAAAASUVORK5CYII=" ID="rdf:#$22iCK1">@firefox_help@</A>
+- <DT><A HREF="https://www.mozilla.org/@AB_CD@/firefox/customize/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwMDAsTBZbkNwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABNElEQVQ4y8WSsU0DURBE3yyWIaAJaqAAN4DPSL6AlIACKIEOyJEgRsIgOOkiInJqgAKowNg7BHdn7MOksNl+zZ//dvbDf5cAiklp22BdVtXdeTEpDYDB9m1VzU6OJuVp2NdEQCaI96fH2YHG4+mDduKYNMYINTcjcGbXzQVDEAphG0k48zUsajIbnAiMIXThpW8EICE0RAK4dvoKg9NIcTiQ589otyHOZLnwqK5nLwBFUZ4igc3iM0d1ff8CMC6mZ6Ihiaqq3gi1aUAnArD00SW1fq5OLBg0ymYmSZsR2/t4e/rGyCLW0sbp3oq+yTYqVgytQWui2FS7XYF7GFprY921T4CNQt8zr47dNzCkIX7y/jBtH+v+RGMQrc828W8pApnZbmEVQp/Ae7BlOy2ttib81/UFc+WRWEbjckIAAAAASUVORK5CYII=" ID="rdf:#$32iCK1">@firefox_customize@</A>
+- <DT><A HREF="https://www.mozilla.org/@AB_CD@/contribute/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwMDAsTBZbkNwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABNElEQVQ4y8WSsU0DURBE3yyWIaAJaqAAN4DPSL6AlIACKIEOyJEgRsIgOOkiInJqgAKowNg7BHdn7MOksNl+zZ//dvbDf5cAiklp22BdVtXdeTEpDYDB9m1VzU6OJuVp2NdEQCaI96fH2YHG4+mDduKYNMYINTcjcGbXzQVDEAphG0k48zUsajIbnAiMIXThpW8EICE0RAK4dvoKg9NIcTiQ589otyHOZLnwqK5nLwBFUZ4igc3iM0d1ff8CMC6mZ6Ihiaqq3gi1aUAnArD00SW1fq5OLBg0ymYmSZsR2/t4e/rGyCLW0sbp3oq+yTYqVgytQWui2FS7XYF7GFprY921T4CNQt8zr47dNzCkIX7y/jBtH+v+RGMQrc828W8pApnZbmEVQp/Ae7BlOy2ttib81/UFc+WRWEbjckIAAAAASUVORK5CYII=" ID="rdf:#$42iCK1">@firefox_community@</A>
+- <DT><A HREF="https://www.mozilla.org/@AB_CD@/about/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwMDAsTBZbkNwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABNElEQVQ4y8WSsU0DURBE3yyWIaAJaqAAN4DPSL6AlIACKIEOyJEgRsIgOOkiInJqgAKowNg7BHdn7MOksNl+zZ//dvbDf5cAiklp22BdVtXdeTEpDYDB9m1VzU6OJuVp2NdEQCaI96fH2YHG4+mDduKYNMYINTcjcGbXzQVDEAphG0k48zUsajIbnAiMIXThpW8EICE0RAK4dvoKg9NIcTiQ589otyHOZLnwqK5nLwBFUZ4igc3iM0d1ff8CMC6mZ6Ihiaqq3gi1aUAnArD00SW1fq5OLBg0ymYmSZsR2/t4e/rGyCLW0sbp3oq+yTYqVgytQWui2FS7XYF7GFprY921T4CNQt8zr47dNzCkIX7y/jBtH+v+RGMQrc828W8pApnZbmEVQp/Ae7BlOy2ttib81/UFc+WRWEbjckIAAAAASUVORK5CYII=" ID="rdf:#$52iCK1">@firefox_about@</A>
++ <DT><A HREF="https://www.parabola.nu/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABL0lEQVQ4jWNgoCcoq16VU1GzygnEBtEVDWuV8GooKFuhWVG3uiM3d5UokG4qr1szAaa5vGbVt4ralacwNDU0rGIrr10VBVG0+lxhwyqVsqqVtRW1q6eD5IvL19oB2V+B+D9QzQu4xtDQVZylVavygRKHqurWOlbUrknKK12qWlCwWLK8elUFA8N/xvLy5VYVtas+gzWDDVi9E2QjT1XdcufymjWpQJt1cXmnvHwVP1DzR7hmIC6vW+kOtpnYQKysW30arrlm9RVi9cFBRfXKJTADympWJZNsQFnN6rUQA1adAQU2SZqBXmUGBtozUDiU1qxQJtl2oCY3kO2l1avCSdYMAsBAWwyM2plkaS4p6eYGOv1YQ0MDB1kGlFWuDChuWKZBlmYQqK5eJU22ZkIAAEIlnQZQkzITAAAAAElFTkSuQmCC">Parabola GNU/Linux-libre</A>
++ <DT><A HREF="https://www.parabola.nu/packages/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABL0lEQVQ4jWNgoCcoq16VU1GzygnEBtEVDWuV8GooKFuhWVG3uiM3d5UokG4qr1szAaa5vGbVt4ralacwNDU0rGIrr10VBVG0+lxhwyqVsqqVtRW1q6eD5IvL19oB2V+B+D9QzQu4xtDQVZylVavygRKHqurWOlbUrknKK12qWlCwWLK8elUFA8N/xvLy5VYVtas+gzWDDVi9E2QjT1XdcufymjWpQJt1cXmnvHwVP1DzR7hmIC6vW+kOtpnYQKysW30arrlm9RVi9cFBRfXKJTADympWJZNsQFnN6rUQA1adAQU2SZqBXmUGBtozUDiU1qxQJtl2oCY3kO2l1avCSdYMAsBAWwyM2plkaS4p6eYGOv1YQ0MDB1kGlFWuDChuWKZBlmYQqK5eJU22ZkIAAEIlnQZQkzITAAAAAElFTkSuQmCC">Parabola GNU/Linux-libre Packages</A>
++ <DT><A HREF="https://wiki.parabola.nu/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABL0lEQVQ4jWNgoCcoq16VU1GzygnEBtEVDWuV8GooKFuhWVG3uiM3d5UokG4qr1szAaa5vGbVt4ralacwNDU0rGIrr10VBVG0+lxhwyqVsqqVtRW1q6eD5IvL19oB2V+B+D9QzQu4xtDQVZylVavygRKHqurWOlbUrknKK12qWlCwWLK8elUFA8N/xvLy5VYVtas+gzWDDVi9E2QjT1XdcufymjWpQJt1cXmnvHwVP1DzR7hmIC6vW+kOtpnYQKysW30arrlm9RVi9cFBRfXKJTADympWJZNsQFnN6rUQA1adAQU2SZqBXmUGBtozUDiU1qxQJtl2oCY3kO2l1avCSdYMAsBAWwyM2plkaS4p6eYGOv1YQ0MDB1kGlFWuDChuWKZBlmYQqK5eJU22ZkIAAEIlnQZQkzITAAAAAElFTkSuQmCC">Parabola GNU/Linux-libre Wiki</A>
++ <DT><A HREF="https://labs.parabola.nu/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABL0lEQVQ4jWNgoCcoq16VU1GzygnEBtEVDWuV8GooKFuhWVG3uiM3d5UokG4qr1szAaa5vGbVt4ralacwNDU0rGIrr10VBVG0+lxhwyqVsqqVtRW1q6eD5IvL19oB2V+B+D9QzQu4xtDQVZylVavygRKHqurWOlbUrknKK12qWlCwWLK8elUFA8N/xvLy5VYVtas+gzWDDVi9E2QjT1XdcufymjWpQJt1cXmnvHwVP1DzR7hmIC6vW+kOtpnYQKysW30arrlm9RVi9cFBRfXKJTADympWJZNsQFnN6rUQA1adAQU2SZqBXmUGBtozUDiU1qxQJtl2oCY3kO2l1avCSdYMAsBAWwyM2plkaS4p6eYGOv1YQ0MDB1kGlFWuDChuWKZBlmYQqK5eJU22ZkIAAEIlnQZQkzITAAAAAElFTkSuQmCC">Parabola GNU/Linux-libre Labs</A>
++ </DL><p>
++ <DT><H3 ID="rdf:#$ZvPhC3">Free Software Foundation</H3>
++ <DL><p>
++ <DT><A HREF="https://www.fsf.org/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAADG0lEQVQoFQEQA+/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQECAAAAAAAAAAAAAAAAAAAA2qOp7tTXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAP///wAAAAAAAOCyt7pUXQcSEgcQDwAAAP///wAAAAAAAAD//x9NSDqNhQEBAQQAAAAAAAAAAAAAAAAQJiQGDQ0aPToZPjoAAQEAAAAAAAAAAAABAQEpZV4AAAAAAAAAAAAA////////////////pSIv05KZ////////////////////////////////AAAAAQAAAP///6krNwAAAAAAAPHc3ggSEQcSEQAAAAAAAAAAABY3NEGelQAAAAAAAAEBAQEAAAD///+YARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGDg1g690CBgYAAAABAQEEAAAAAAAAS7etAAAAAAAAwGVtHklFIlJOAAAAAAAAAAAAAAAA+/X2BwYGAAAAAAAABAAAAAAAAB1IQwAAAAAAAAYNDBAmJB1IQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAgL//v4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAQEB//7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAECAv/+/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////////////////cqK3qzM////////////////////////////////8AAAABAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGuLjDf9F8oBAAAAAElFTkSuQmCC">Free Software Foundation</A>
++ <DT><A HREF="https://www.gnu.org/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAAGFBMVEVFRUV+fn6mpqa/v7/Ozs7Y2Njg4OD8/Pwuhn+TAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAALEQAACxEBf2RfkQAAAAd0SU1FB9MBDhQ6Gd8s57cAAAEVSURBVBgZBcGxVtpgGADQL9gHSBzqSognzMixmcWWzB6pmRHhnyvku6/fewMAIPD3TwHmQxHs6vr+A16bphNum/vV0x429201hcPjAGBTDZGnR/Kw1U181+u4HXvOdSxjUcztz8jjg1xGVBG9XPYxt4PviKiaWLg168iXtbrq+mPT1utjNcR1U73deRnL43M2sRgj3+oYs8uL3rLphPd2QWmHbMu/VS/cnk6UdtSW657g9yBlcZ0UAkUWzPvyRaAYmfd+HT4IZtvC59ibEJxXiqJjQpBpNEufBYE0McoOAunGhRMEFIPc7h4goJigQEBxk8u7AgEpL3IEAUZfcgAByGFXQACm5+4MAuB19QMEgI8CAgDgP4rivVgoKP6ZAAAAAElFTkSuQmCC">The GNU Operating System and the Free Software Movement</A>
++ <DT><A HREF="https://libreplanet.org/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACfElEQVQ4jZXTS0hUcRTH8f+9M3fGd0gRRq1a2bZdBAotWtS6TQtB6IHgKzRy0UKqjRaRCAq+R21MDMsUR83JR5fJxhmaK2lzsWAWw+ToEHJxgnFm7reFIgza66z/58P/dzhHcESZpsluIsFPwyCVSmGa5lHPEEIIkdGYTqPPvqUlP4fK8nJ2DINYNEq71YJ3fv4QlAGkUynaj+VRdfUK7580M52rEN/ZYWNjg2GrjEMSPFXsmOn0YcA0TZ4V5tNZUkJTTTWfJiZIJhJ8U1VczwcZs0o4JUHzufM0ZGcf/OQASCaTxGIxDMNA00P8iEbpuXyJ8Tw77+wWJhWZQYuVbiHoFIKwpmUC4XCYzc1NDMMgHo9z8+IFvl6/xsf7D9ArbjOpyAxLEt1C0CUErfvJDwBd14lEImxvb/N9fR1fgY3egmyWsq0sO/poUyw4pb3mLiFolyRM09wDEokEfr+fUChEJBJh4HgBS7kKn92zLIy9ZriqklFZwiEEHfsRRp1O0un0HpDa3cU9M8PKygp3Tp5AzbKgZlmYt1uYtkn02q0MyYKmnBxWNI27Nhtut5tkMrkHmKZJbWkpqqryQpFxKTJTisyEVeaVRWJIlqgpLuZRWRkejwe/34/P58ucwZvWVhYXF5l2uejIzeHGqbM4ZYmB/dy1hUV8mJpibm4On8/H1tbW4T1YXV3F6/WysLDA5Pg4nfsDe5yfz8OiIjweD5qmEQwGf7/KwWCQtbU1NE2jRZbpEoI2SWKqr49lVUXX9T/fAkAgEKC/e5SW6mo6hKD+zGn6e0bw+/x/PyaA9S/rvOwfobGukfpbddyraMDR7iCwHPg34H9KCCF+Abts3KCj/p6aAAAAAElFTkSuQmCC">LibrePlanet</A>
++ <DT><A HREF="https://www.h-node.org/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABgElEQVQ4jaXRz2uSARzHcb0vlRGEzTVWISU1BVkFYTIyjNK1pKcxHA+yhWMWIamHYikFgpoLIi9jwegi3QbL9SzdLmMbM9J+DkJBgm5RDvEPeHeQHOyQz0OH9+V7ePGBr0pqpPmfVPsP8a0AR4MnMEwf48x9K0s/E8oAY9iEMOvD+8yP2qVjrhhRBnSN61n5sIpULqC+pGHh8wNlgEY8jPQXcGh4VXukDND5evYAl46odIuXtYdKAANSudAChO52/XeMZMohecCbcoGdH99Y+7LO72adT9+/4nh8nYOjBl7/SsoB8gBkpHk8T0S2K++pN3fRin3cfnFDHvCuWkI9rEMvHGEo5gbAHnXhnLF1BpZLeRaLOVT2A8Q3A5wMngXgWtKLxX9KPqC+rCWQvYkpeK4NWKcGOgO50ts2MJJ0cPreeQDciTHMchZYIhcwh2wcuqjn+ccwGm9v6wsTxxn0dVgQXZ7Ek3Agpq6QrcaQGmmebtxFSDkRU1fJVmL/BpT2ByV/3eDMhinRAAAAAElFTkSuQmCC">h-node</A>
+ </DL><p>
+ </DL><p>
+diff --git a/devtools/client/locales/en-US/connection-screen.dtd b/devtools/client/locales/en-US/connection-screen.dtd
+index 674a408..d27e97f 100644
+--- a/devtools/client/locales/en-US/connection-screen.dtd
++++ b/devtools/client/locales/en-US/connection-screen.dtd
+@@ -24,7 +24,7 @@
+ <!-- LOCALIZATION NOTE (remoteHelp, remoteDocumentation, remoteHelpSuffix):
+ these strings will be concatenated in a single label, remoteDocumentation will
+ be used as text for a link to MDN. -->
+-<!ENTITY remoteHelp "Firefox Developer Tools can debug remote devices (Firefox for Android and Firefox OS, for example). Make sure that you have turned on the ‘Remote debugging’ option in the remote device. For more, see the ">
++<!ENTITY remoteHelp "Iceweasel Developer Tools can debug remote devices. Make sure that you have turned on the ‘Remote debugging’ option in the remote device. For more, see the ">
+ <!ENTITY remoteDocumentation "documentation">
+ <!ENTITY remoteHelpSuffix ".">
+
+diff --git a/devtools/client/locales/en-US/sourceeditor.properties b/devtools/client/locales/en-US/sourceeditor.properties
+index 01447e3..0bc043e 100644
+--- a/devtools/client/locales/en-US/sourceeditor.properties
++++ b/devtools/client/locales/en-US/sourceeditor.properties
+@@ -4,7 +4,7 @@
+
+ # LOCALIZATION NOTE These strings are used inside the Source Editor component.
+ # This component is used whenever source code is displayed for the purpose of
+-# being edited, inside the Firefox developer tools - current examples are the
++# being edited, inside the Iceweasel developer tools - current examples are the
+ # Scratchpad and the Style Editor tools.
+
+ # LOCALIZATION NOTE The correct localization of this file might be to keep it
+diff --git a/devtools/client/locales/en-US/toolbox.dtd b/devtools/client/locales/en-US/toolbox.dtd
+index 53385de..fb9a95a 100644
+--- a/devtools/client/locales/en-US/toolbox.dtd
++++ b/devtools/client/locales/en-US/toolbox.dtd
+@@ -117,7 +117,7 @@ values from browser.dtd. -->
+ - checkbox that toggles remote debugging, i.e. devtools.debugger.remote-enabled
+ - boolean preference in about:config, in the options panel. -->
+ <!ENTITY options.enableRemote.label3 "Enable remote debugging">
+-<!ENTITY options.enableRemote.tooltip "Turning this option on will allow the developer tools to debug remote Firefox instance like Firefox OS">
++<!ENTITY options.enableRemote.tooltip "Turning this option on will allow the developer tools to debug remote Iceweasel instance like Iceweasel OS">
+
+ <!-- LOCALIZATION NOTE (options.enableWorkers.label): This is the label for the
+ - checkbox that toggles worker debugging, i.e. devtools.debugger.workers
+@@ -146,7 +146,7 @@ values from browser.dtd. -->
+ <!-- LOCALIZATION NOTE (options.selectDefaultTools.label): This is the label for
+ - the heading of group of checkboxes corresponding to the default developer
+ - tools. -->
+-<!ENTITY options.selectDefaultTools.label "Default Firefox Developer Tools">
++<!ENTITY options.selectDefaultTools.label "Default Iceweasel Developer Tools">
+
+ <!-- LOCALIZATION NOTE (options.selectAdditionalTools.label): This is the label for
+ - the heading of group of checkboxes corresponding to the developer tools
+diff --git a/devtools/client/locales/en-US/webide.dtd b/devtools/client/locales/en-US/webide.dtd
+index 5e1a80c..8f375da 100644
+--- a/devtools/client/locales/en-US/webide.dtd
++++ b/devtools/client/locales/en-US/webide.dtd
+@@ -2,7 +2,7 @@
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+-<!ENTITY windowTitle "Firefox WebIDE">
++<!ENTITY windowTitle "Iceweasel WebIDE">
+
+ <!ENTITY projectMenu_label "Project">
+ <!ENTITY projectMenu_accesskey "P">
+@@ -59,7 +59,7 @@
+ <!ENTITY projectButton_label "Open App">
+ <!ENTITY runtimeButton_label "Select Runtime">
+
+-<!-- We try to repicate Firefox' bindings: -->
++<!-- We try to repicate Iceweasel' bindings: -->
+ <!-- quit app -->
+ <!ENTITY key_quit "W">
+ <!-- open menu -->
+diff --git a/devtools/client/locales/en-US/webide.properties b/devtools/client/locales/en-US/webide.properties
+index 2368ad7..05e39c7 100644
+--- a/devtools/client/locales/en-US/webide.properties
++++ b/devtools/client/locales/en-US/webide.properties
+@@ -2,8 +2,8 @@
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+-title_noApp=Firefox WebIDE
+-title_app=Firefox WebIDE: %S
++title_noApp=Iceweasel WebIDE
++title_app=Iceweasel WebIDE: %S
+
+ runtimeButton_label=Select Runtime
+ projectButton_label=Open App
+@@ -54,10 +54,10 @@ error_runtimeVersionTooRecent=The connected runtime has a more recent build date
+ addons_stable=stable
+ addons_unstable=unstable
+ # LOCALIZATION NOTE (addons_simulator_label): This label is shown as the name of
+-# a given simulator version in the "Manage Simulators" pane. %1$S: Firefox OS
++# a given simulator version in the "Manage Simulators" pane. %1$S: Iceweasel OS
+ # version in the simulator, ex. 1.3. %2$S: Simulator stability label, ex.
+ # "stable" or "unstable".
+-addons_simulator_label=Firefox OS %1$S Simulator (%2$S)
++addons_simulator_label=Iceweasel OS %1$S Simulator (%2$S)
+ addons_install_button=install
+ addons_uninstall_button=uninstall
+ addons_adb_label=ADB Helper Add-on
diff --git a/pcr/iceweasel-hardening/mozconfig b/pcr/iceweasel-hardening/mozconfig
new file mode 100644
index 000000000..7349e3ccd
--- /dev/null
+++ b/pcr/iceweasel-hardening/mozconfig
@@ -0,0 +1,46 @@
+ac_add_options --enable-application=browser
+
+ac_add_options --prefix=/usr
+ac_add_options --enable-release
+ac_add_options --enable-gold
+ac_add_options --enable-pie
+ac_add_options --enable-rust
+
+# Release Iceweasel branding
+ac_add_options --disable-official-branding
+ac_add_options --with-branding=debian/branding
+ac_add_options --enable-update-channel=release
+MOZ_ADDON_SIGNING=1
+MOZ_REQUIRE_SIGNING=1
+
+# System libraries
+ac_add_options --with-system-nspr
+ac_add_options --with-system-nss
+ac_add_options --with-system-icu
+ac_add_options --with-system-jpeg
+ac_add_options --with-system-zlib
+ac_add_options --with-system-bz2
+ac_add_options --with-system-libevent
+ac_add_options --with-system-libvpx
+ac_add_options --enable-system-hunspell
+ac_add_options --enable-system-sqlite
+ac_add_options --enable-system-ffi
+ac_add_options --enable-system-pixman
+
+# Features
+ac_add_options --enable-startup-notification
+ac_add_options --disable-updater
+ac_add_options --disable-crashreporter
+
+STRIP_FLAGS="--strip-debug"
+
+# Parabola features
+ac_add_options --disable-safe-browsing
+ac_add_options --disable-url-classifier
+ac_add_options --disable-eme
+ac_add_options --disable-gamepad
+
+# Other
+mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/moz-objdir
+
+# vim:set ft=sh:
diff --git a/pcr/iceweasel-hardening/mozilla-1253216.patch b/pcr/iceweasel-hardening/mozilla-1253216.patch
new file mode 100644
index 000000000..c9252da5f
--- /dev/null
+++ b/pcr/iceweasel-hardening/mozilla-1253216.patch
@@ -0,0 +1,12 @@
+diff -up firefox-48.0/js/src/jit/AtomicOperations.h.old firefox-48.0/js/src/jit/AtomicOperations.h
+--- firefox-48.0/js/src/jit/AtomicOperations.h.old 2016-07-27 09:42:43.148175449 +0200
++++ firefox-48.0/js/src/jit/AtomicOperations.h 2016-07-27 09:41:13.000000000 +0200
+@@ -340,7 +340,7 @@ AtomicOperations::isLockfree(int32_t siz
+ # elif defined(__aarch64__)
+ # include "jit/arm64/AtomicOperations-arm64.h"
+ # else
+-# include "jit/none/AtomicOperations-none.h" // These MOZ_CRASH() always
++# include "jit/none/AtomicOperations-ppc.h"
+ # endif
+ #elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+ # include "jit/x86-shared/AtomicOperations-x86-shared.h"
diff --git a/pcr/iceweasel-hardening/mozilla-build-arm.patch b/pcr/iceweasel-hardening/mozilla-build-arm.patch
new file mode 100644
index 000000000..774147bbb
--- /dev/null
+++ b/pcr/iceweasel-hardening/mozilla-build-arm.patch
@@ -0,0 +1,24 @@
+diff -up firefox-46.0/media/webrtc/trunk/webrtc/build/common.gypi.arm firefox-46.0/media/webrtc/trunk/webrtc/build/common.gypi
+--- firefox-46.0/media/webrtc/trunk/webrtc/build/common.gypi.arm 2016-04-25 12:03:12.486027089 +0200
++++ firefox-46.0/media/webrtc/trunk/webrtc/build/common.gypi 2016-04-25 12:05:55.714644873 +0200
+@@ -312,20 +312,6 @@
+ 'defines': [
+ 'WEBRTC_ARCH_ARM',
+ ],
+- 'conditions': [
+- ['arm_version>=7', {
+- 'defines': ['WEBRTC_ARCH_ARM_V7',
+- 'WEBRTC_BUILD_NEON_LIBS'],
+- 'conditions': [
+- ['arm_neon==1', {
+- 'defines': ['WEBRTC_ARCH_ARM_NEON',],
+- }],
+- ['arm_neon==0 and arm_neon_optional==1', {
+- 'defines': ['WEBRTC_DETECT_ARM_NEON',],
+- }],
+- ],
+- }],
+- ],
+ }],
+ ['os_bsd==1', {
+ 'defines': [
diff --git a/pcr/iceweasel-hardening/remove-default-and-shell-icons-in-packaging-manifest.patch b/pcr/iceweasel-hardening/remove-default-and-shell-icons-in-packaging-manifest.patch
new file mode 100644
index 000000000..6bc67b30a
--- /dev/null
+++ b/pcr/iceweasel-hardening/remove-default-and-shell-icons-in-packaging-manifest.patch
@@ -0,0 +1,34 @@
+diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
+index cffcff1..85d28cc 100644
+--- a/browser/installer/package-manifest.in
++++ b/browser/installer/package-manifest.in
+@@ -653,11 +653,6 @@
+ @RESPATH@/chrome/toolkit.manifest
+ @RESPATH@/chrome/recording.manifest
+ @RESPATH@/chrome/recording/*
+-#ifdef MOZ_GTK
+-@RESPATH@/browser/chrome/icons/default/default16.png
+-@RESPATH@/browser/chrome/icons/default/default32.png
+-@RESPATH@/browser/chrome/icons/default/default48.png
+-#endif
+ @RESPATH@/browser/features/*
+
+ ; [Webide Files]
+@@ -670,17 +665,10 @@
+ @RESPATH@/browser/chrome/devtools.manifest
+ @RESPATH@/browser/@PREF_DIR@/devtools.js
+
+-; shell icons
+-#ifdef XP_UNIX
+-#ifndef XP_MACOSX
+-; shell icons
+-@RESPATH@/browser/icons/*.png
+ #ifdef MOZ_UPDATER
+ ; updater icon
+ @RESPATH@/icons/updater.png
+ #endif
+-#endif
+-#endif
+
+ ; [Default Preferences]
+ ; All the pref files must be part of base to prevent migration bugs
diff --git a/pcr/iceweasel-hardening/vendor.js b/pcr/iceweasel-hardening/vendor.js
new file mode 100644
index 000000000..84489482b
--- /dev/null
+++ b/pcr/iceweasel-hardening/vendor.js
@@ -0,0 +1,351 @@
+pref("extensions.getAddons.search.url", "https://directory.fsf.org/wiki/GNU_IceCat");
+pref("extensions.getAddons.link.url", "https://directory.fsf.org/wiki/GNU_IceCat");
+pref("extensions.getAddons.search.browseURL", "https://directory.fsf.org/wiki/GNU_IceCat");
+pref("accessibility.blockautorefresh", true);
+pref("browser.meta_refresh_when_inactive.disabled", true);
+pref("extensions.webservice.discoverURL", "https://directory.fsf.org/wiki/GNU_IceCat");
+pref("app.faqURL", "https://libreplanet.org/wiki/Group:IceCat/FAQ");
+pref("app.update.auto", false);
+pref("app.update.checkInstallTime", false);
+pref("app.update.enabled", false);
+pref("app.update.staging.enabled", false);
+pref("app.update.url", "about:blank");
+pref("beacon.enabled", false);
+pref("breakpad.reportURL", "about:blank");
+pref("browser.EULA.override", true);
+pref("browser.aboutHomeSnippets.updateUrl", "about:blank");
+pref("browser.apps.URL", "about:blank");
+pref("browser.cache.disk.enable", false);
+pref("browser.cache.offline.enable", false);
+pref("browser.casting.enabled", false);
+pref("browser.search.order.US.1", "");
+pref("browser.search.order.US.2", "");
+pref("browser.search.order.US.3", "");
+pref("gecko.handlerService.schemes.mailto.0.name", "");
+pref("browser.disableResetPrompt", true);
+pref("browser.display.max_font_attempts",10);
+pref("browser.display.max_font_count",10);
+pref("browser.display.use_document_fonts", 0); // Prevent font fingerprinting
+pref("browser.download.manager.addToRecentDocs", false);
+pref("browser.download.manager.retention", 1);
+pref("browser.download.manager.scanWhenDone", false); // prevents AV remote reporting of downloads
+pref("browser.download.useDownloadDir", false);
+pref("browser.eme.ui.enabled", false);
+pref("browser.fixup.alternate.enabled", false);
+pref("browser.formfill.enable", false);
+pref("browser.history.allowPopState", false); // HTML5 privacy https://bugzilla.mozilla.org/show_bug.cgi?id=500328
+pref("browser.history.allowPushState", false);
+pref("browser.history.allowReplaceState", false);
+pref("browser.link.open_newwindow.restriction", 0); // Bug 9881: Open popups in new tabs (to avoid fullscreen popups)
+pref("browser.newtab.preload", false);
+pref("browser.newtabpage.directory.ping", "about:blank");
+pref("browser.newtabpage.directory.source", "about:blank");
+pref("browser.newtabpage.enabled", false);
+pref("browser.newtabpage.enhanced", false);
+pref("browser.newtabpage.introShown", true);
+pref("browser.pocket.api", "about:blank");
+pref("browser.pocket.enabled", false);
+pref("browser.pocket.enabledLocales", "about:blank");
+pref("browser.pocket.oAuthConsumerKey", "about:blank");
+pref("browser.pocket.site", "about:blank");
+pref("browser.pocket.useLocaleList", false);
+pref("browser.preferences.inContent",false);
+//pref("browser.privatebrowsing.autostart", true);
+pref("browser.rights.3.shown", true);
+pref("browser.safebrowsing.appRepURL", "about:blank");
+pref("browser.safebrowsing.enabled", false);
+pref("browser.safebrowsing.malware.enabled", false);
+pref("browser.safebrowsing.provider.mozilla.gethashURL", "about:blank");
+pref("browser.safebrowsing.provider.mozilla.updateURL", "about:blank");
+pref("browser.safebrowsing.downloads.remote.block_dangerous", false);
+pref("browser.safebrowsing.downloads.remote.block_dangerous_host", false);
+pref("browser.safebrowsing.downloads.remote.block_potentially_unwanted", false);
+pref("browser.safebrowsing.downloads.remote.block_uncommon", false);
+pref("browser.safebrowsing.downloads.remote.enabled", false);
+pref("browser.safebrowsing.downloads.remote.url", "");
+pref("browser.safebrowsing.provider.google.gethashURL", "");
+pref("browser.safebrowsing.provider.google.updateURL", "");
+pref("browser.safebrowsing.provider.google.lists", "");
+pref("browser.search.geoSpecificDefaults.url", "about:blank");
+pref("browser.search.geoSpecificDefaults", false);
+pref("browser.search.geoip.url", "about:blank");
+pref("browser.search.suggest.enabled", false);
+pref("browser.search.update", false);
+pref("browser.selfsupport.url", "about:blank");
+pref("browser.send_pings", false);
+pref("browser.sessionstore.privacy_level", 2);
+pref("browser.shell.checkDefaultBrowser", false);
+pref("browser.slowStartup.maxSamples", 0);
+pref("browser.slowStartup.notificationDisabled", true);
+pref("browser.slowStartup.samples", 0);
+pref("browser.snippets.enabled", false);
+pref("browser.snippets.geoUrl", "about:blank");
+pref("browser.snippets.statsUrl", "about:blank");
+pref("browser.snippets.syncPromo.enabled", false);
+pref("browser.snippets.updateUrl", "about:blank");
+pref("browser.startup.homepage_override.buildID", "20100101");
+pref("browser.startup.homepage_override.mstone", "9001.0.0");
+pref("browser.syncPromoViewsLeftMap", "{\"addons\":0, \"passwords\":0, \"bookmarks\":0}"); // Don't promote sync
+pref("browser.newtabpage.remote", false);
+pref("browser.tabs.crashReporting.sendReport", false);
+pref("browser.tabs.remote.desktopbehavior", false);
+pref("browser.toolbarbuttons.introduced.pocket-button", true);
+pref("browser.uitour.enabled", false); // https://trac.torproject.org/projects/tor/ticket/19047
+pref("browser.urlbar.maxRichResults", 0);
+pref("browser.webapps.checkForUpdates", 0);
+pref("browser.webapps.updateCheckUrl", "about:blank");
+pref("browser.zoom.siteSpecific", false);
+pref("camera.control.autofocus_moving_callback.enabled", false);
+pref("camera.control.face_detection.enabled", false);
+pref("captivedetect.canonicalURL", "about:blank");
+pref("datareporting.healthreport.about.reportUrl", "about:blank");
+pref("datareporting.healthreport.documentServerURI", "about:blank");
+pref("datareporting.healthreport.service.enabled", false); // Yes, all three of these must be set
+pref("datareporting.healthreport.uploadEnabled", false);
+pref("datareporting.policy.dataSubmissionEnabled", false);
+pref("datareporting.policy.dataSubmissionPolicyVersion", 2);
+pref("datareporting.policy.firstRunTime", 0);
+pref("device.sensors.enabled", false);
+pref("devtools.debugger.remote-enabled", false); // https://developer.mozilla.org/docs/Tools/Remote_Debugging/Debugging_Firefox_Desktop#Enable_remote_debugging
+pref("devtools.devices.url", "about:blank");
+pref("devtools.gcli.imgurUploadURL", "about:blank");
+pref("devtools.gcli.jquerySrc", "about:blank");
+pref("devtools.gcli.lodashSrc", "about:blank");
+pref("devtools.gcli.underscoreSrc", "about:blank");
+pref("devtools.remote.wifi.scan", false); // http://forum.top-hat-sec.com/index.php?topic=4951.5;wap2
+pref("devtools.remote.wifi.visible", false);
+pref("devtools.webide.adaptersAddonURL", "about:blank");
+pref("devtools.webide.adbAddonURL", "about:blank");
+pref("devtools.webide.addonsURL", "about:blank");
+pref("devtools.webide.enabled", false); //https://trac.torproject.org/projects/tor/ticket/16222
+pref("devtools.webide.simulatorAddonsURL", "about:blank");
+pref("devtools.webide.templatesURL", "about:blank");
+pref("dom.battery.enabled", false); // fingerprinting due to differing OS implementations
+pref("dom.enable_performance", false);
+pref("dom.event.clipboardevents.enabled",false);
+pref("dom.gamepad.enabled", false); // bugs.torproject.org/13023
+pref("dom.indexedDB.enabled", false);
+pref("dom.enable_user_timing", false);
+pref("dom.event.highrestimestamp.enabled", false);
+pref("dom.ipc.plugins.flash.subprocess.crashreporter.enabled", false);
+pref("dom.mozApps.signed_apps_installable_from", "about:blank");
+pref("dom.netinfo.enabled", false); // Network Information API provides general information about the system's connection type (WiFi, cellular, etc.)
+pref("dom.network.enabled",false); // fingerprinting due to differing OS implementations
+pref("dom.push.enabled", false);
+pref("dom.push.serverURL", "");
+pref("dom.presentation.discovery.enabled", false);
+pref("dom.presentation.discoverable", false);
+pref("dom.storage.enabled", false);
+pref("dom.telephony.enabled", false); // https://wiki.mozilla.org/WebAPI/Security/WebTelephony
+pref("dom.vibrator.enabled", false);
+pref("dom.vr.enabled", false);
+pref("dom.vr.cardboard.enabled", false);
+pref("dom.vr.oculus.enabled", false);
+pref("dom.vr.oculus050.enabled", false);
+pref("dom.vr.poseprediction.enabled", false);
+pref("dom.vr.add-test-devices", 0);
+pref("dom.workers.sharedWorkers.enabled", false); // See https://bugs.torproject.org/15562
+pref("dom.idle-observers-api.enabled", false); // disable idle observation
+pref("experiments.enabled", false);
+pref("experiments.manifest.uri", "about:blank");
+pref("extensions.blocklist.detailsURL", "about:blank");
+pref("extensions.blocklist.enabled", false);
+pref("extensions.blocklist.itemURL", "about:blank");
+pref("extensions.blocklist.url", "about:blank");
+pref("extensions.bootstrappedAddons", "{}");
+pref("extensions.databaseSchema", 3);
+pref("extensions.enabledScopes", 1);
+// Don't disable our bundled extensions in the application directory
+pref("extensions.autoDisableScopes", 11);
+pref("extensions.shownSelectionUI", true);
+pref("extensions.getAddons.cache.enabled", false); // https://blog.mozilla.org/addons/how-to-opt-out-of-add-on-metadata-updates/
+pref("extensions.getAddons.get.url", "about:blank");
+pref("extensions.getAddons.getWithPerformance.url", "about:blank");
+pref("extensions.getAddons.recommended.url", "about:blank");
+pref("extensions.pendingOperations", false);
+pref("extensions.pocket.api", "about:blank");
+pref("extensions.pocket.enabled", false);
+pref("extensions.shownSelectionUI", true);
+pref("extensions.ui.lastCategory", "addons://list/extension");
+pref("extensions.update.autoUpdateDefault", false);
+pref("extensions.update.enabled", false); // Fingerprints all installed addons, best to let the user decide when to run updates manually.
+pref("extensions.update.background.url", ""); // User can still update manually, but we disable background updates.
+pref("extensions.systemAddon.update.url", ""); // The system add-ons infrastructure that's used to ship Hello and Pocket in Firefox
+pref("font.default.x-western", "sans-serif");
+pref("general.appname.override", "Netscape");
+pref("general.appversion.override", "5.0 (Windows)");
+pref("general.buildID.override", "20100101");
+pref("general.oscpu.override", "Windows NT 6.1");
+pref("general.platform.override", "Win32");
+pref("general.productSub.override", "20100101");
+pref("general.useragent.compatMode.firefox", true);
+pref("general.useragent.override", "Mozilla/5.0 (Windows NT 6.1; rv:49.0) Gecko/20100101 Firefox/49.0");
+pref("general.useragent.vendor", "");
+pref("general.useragent.vendorSub", "");
+pref("general.warnOnAboutConfig", false);
+pref("geo.enabled", false);
+pref("geo.wifi.uri", "about:blank");
+pref("gfx.direct2d.disabled", true);
+pref("gfx.downloadable_fonts.fallback_delay", -1);
+pref("gfx.font_rendering.opentype_svg.enabled", false); // https://wiki.mozilla.org/SVGOpenTypeFonts - iSEC Partners Report recommends to disable this
+pref("healthreport.uploadEnabled", false);
+pref("identity.fxaccounts.auth.uri", "about:blank");
+pref("intl.charset.default", "windows-1252");
+pref("intl.locale.matchOS", true);
+pref("javascript.options.asmjs", false); // Multiple security advisories, low level js
+pref("javascript.options.wasm", false); // https://hacks.mozilla.org/2016/03/a-webassembly-milestone/
+pref("javascript.use_us_english_locale", true);
+pref("javascript.options.typeinference", false);
+pref("javascript.options.baselinejit.content", false);
+pref("javascript.options.ion.content", false); // https://trac.torproject.org/projects/tor/ticket/9387#comment:43
+pref("keyword.enabled", false);
+pref("layers.acceleration.disabled", true);
+pref("layout.css.visited_links_enabled", false);
+pref("lightweightThemes.update.enabled", false); // We can update our themes manually, may fingerprint the user.
+pref("loop.copy.throttler", "about:blank");
+pref("loop.enabled",false); //Disable Firefox Hello
+pref("loop.facebook.appId", "about:blank");
+pref("loop.facebook.enabled", false);
+pref("loop.facebook.fallbackUrl", "about:blank");
+pref("loop.facebook.shareUrl", "about:blank");
+pref("loop.feedback.baseUrl", "about:blank");
+pref("loop.feedback.formURL", "about:blank");
+pref("loop.feedback.manualFormURL", "about:blank");
+pref("loop.gettingStarted.url", "about:blank");
+pref("loop.learnMoreUrl", "about:blank");
+pref("loop.legal.ToS_url", "about:blank");
+pref("loop.legal.privacy_url", "about:blank");
+pref("loop.linkClicker.url", "about:blank");
+pref("loop.oauth.google.redirect_uri", "about:blank");
+pref("loop.oauth.google.scope", "about:blank");
+pref("loop.remote.autostart", false);
+pref("loop.server", "about:blank");
+pref("loop.soft_start_hostname", "about:blank");
+pref("loop.support_url", "about:blank");
+pref("loop.throttled2",false);
+pref("mathml.disabled", true); // https://www.torproject.org/projects/torbrowser/design
+pref("media.audio_data.enabled", false);
+pref("media.autoplay.enabled", false);
+pref("media.cache_size", 0);
+pref("media.eme.apiVisible", false); // Disable Freedom Violating DRM Feature
+pref("media.eme.enabled", false);
+pref("media.getusermedia.screensharing.allowed_domains", ""); // We really don't want to be promoting Cisco and Cloudflare in a whitelist here.
+pref("media.getusermedia.screensharing.enabled", false);
+pref("media.gmp-eme-adobe.enabled", false);
+pref("media.gmp-gmpopenh264.enabled", false);
+pref("media.gmp-manager.url", "about:blank"); // Disable Gecko media plugins: https://wiki.mozilla.org/GeckoMediaPlugins
+pref("media.gmp-manager.url.override", "data:text/plain");
+pref("media.gmp-provider.enabled", false);
+pref("media.gmp.trial-create.enabled", false);
+pref("media.navigator.enabled", false);
+pref("media.peerconnection.enabled", false); // Disable WebRTC interfaces
+pref("media.peerconnection.ice.default_address_only", true);
+pref("media.video_stats.enabled", false);
+pref("media.webspeech.recognition.enable", false);
+pref("media.webspeech.synth.enabled", false);
+pref("network.allow-experiments", false);
+pref("network.http.altsvc.enabled", false);
+pref("network.http.altsvc.oe", false); // https://trac.torproject.org/projects/tor/ticket/16673
+pref("network.dns.disablePrefetch", true);
+pref("network.http.connection-retry-timeout", 0);
+pref("network.http.max-persistent-connections-per-proxy", 256);
+pref("network.http.pipelining", true);
+pref("network.http.pipelining.aggressive", true);
+pref("network.http.pipelining.max-optimistic-requests", 3);
+pref("network.http.pipelining.maxrequests", 10);
+pref("network.http.pipelining.maxrequests", 12);
+pref("network.http.pipelining.read-timeout", 60000);
+pref("network.http.pipelining.reschedule-timeout", 15000);
+pref("network.http.pipelining.ssl", true);
+pref("network.http.proxy.pipelining", true);
+pref("network.http.speculative-parallel-limit", 0);
+pref("network.jar.block-remote-files", true); // https://bugzilla.mozilla.org/show_bug.cgi?id=1173171
+pref("network.jar.open-unsafe-types", false);
+pref("network.manage-offline-status", false); // https://trac.torproject.org/projects/tor/ticket/18945
+pref("network.predictor.enabled", false); // https://trac.torproject.org/projects/tor/ticket/16625
+pref("network.prefetch-next", false);
+pref("network.protocol-handler.external-default", false);
+pref("network.protocol-handler.external.mailto", false);
+pref("network.protocol-handler.external.news", false);
+pref("network.protocol-handler.external.nntp", false);
+pref("network.protocol-handler.external.snews", false);
+pref("network.protocol-handler.warn-external.mailto", true);
+pref("network.protocol-handler.warn-external.news", true);
+pref("network.protocol-handler.warn-external.nntp", true);
+pref("network.protocol-handler.warn-external.snews", true);
+pref("network.proxy.no_proxies_on", ""); // For fingerprinting and local service vulns (#10419)
+pref("network.proxy.socks", "127.0.0.1");
+pref("network.proxy.socks_port", 9050);
+pref("network.proxy.socks_remote_dns", true);
+pref("network.proxy.type", 0); // Setup for TOR for default proxy, but do not enable by default.
+pref("network.security.ports.banned", "9050,9051,9150,9151");
+pref("network.websocket.max-connections", 0);
+//pref("nglayout.initialpaint.delay", 0); http://www.mozdev.org/pipermail/fasterfox/2006-January/000509.html
+pref("noscript.forbidMedia", true);
+pref("offline-apps.allow_by_default", false); // https://support.mozilla.org/en-US/questions/1014708
+pref("pdfjs.disabled", true); // https://www.exploit-db.com/exploits/37958/
+pref("permissions.memory_only", true);
+pref("pfs.datasource.url", "about:blank"); // Fingerprints the user, not HTTPS. Remove it.
+pref("pfs.filehint.url", "about:blank");
+pref("plugin.disable", true); // Disable to search plugins on first start
+pref("plugin.expose_full_path", false);
+pref("plugin.state.flash", 0);
+pref("plugin.state.libgnome-shell-browser-plugin", 0); // disable Gnome Shell Integration
+pref("plugins.click_to_play", true);
+pref("plugins.enumerable_names", "about:blank");
+pref("plugins.hideMissingPluginsNotification", true);
+pref("plugins.hide_infobar_for_missing_plugin", true);
+pref("plugins.hide_infobar_for_outdated_plugin", true);
+pref("plugins.notifyMissingFlash", false);
+pref("privacy.announcements.enabled", false);
+pref("privacy.donottrackheader.enabled", false); // http://www.howtogeek.com/126705/why-enabling-do-not-track-doesnt-stop-you-from-being-tracked/
+pref("privacy.donottrackheader.value", 1);
+pref("privacy.thirdparty.isolate", 2); // Always enforce third party isolation
+pref("privacy.trackingprotection.enabled", true);
+pref("privacy.trackingprotection.pbmode.enabled", true);
+pref("security.OCSP.enabled", 0); // https://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol#Privacy_concerns
+pref("security.OCSP.require", false);
+pref("security.ask_for_password", 0);
+pref("security.cert_pinning.enforcement_level", 2); // https://trac.torproject.org/projects/tor/ticket/16206
+pref("security.enable_tls_session_tickets", false);
+pref("security.mixed_content.block_active_content", true); // Note: Can be disabled for user experience. https://bugzilla.mozilla.org/show_bug.cgi?id=878890
+pref("security.nocertdb", false);
+pref("security.ssl.errorReporting.url", "");
+pref("security.ssl.errorReporting.enabled", false);
+pref("security.ssl.disable_session_identifiers", true);
+pref("security.ssl.enable_false_start", true);
+pref("security.ssl.require_safe_negotiation", true);
+pref("security.ssl.treat_unsafe_negotiation_as_broken", true);
+pref("security.ssl3.rsa_seed_sha", true);
+pref("security.tls.insecure_fallback_hosts.use_static_list", false);
+pref("security.tls.unrestricted_rc4_fallback", false);
+pref("security.tls.version.max", 3);
+pref("security.tls.version.min", 1);
+pref("services.kinto.base", "");
+pref("services.sync.engine.addons", false);
+pref("services.sync.engine.prefs", false); // Never sync prefs, addons, or tabs with other browsers
+pref("services.sync.engine.tabs", false);
+pref("services.sync.prefs.sync.addons.ignoreUserEnabledChanges", false);
+pref("services.sync.prefs.sync.extensions.update.enabled", false);
+pref("services.sync.serverURL", "about:blank");
+pref("services.sync.jpake.serverURL", "about:blank");
+pref("signon.autofillForms", false); // disable cross-site form exposure from password manager - http://kb.mozillazine.org/Signon.autofillForms
+pref("signon.rememberSignons", false);
+pref("social.directories", "");
+pref("social.enabled", false);
+pref("social.remote-install.enabled", false);
+pref("social.shareDirectory", "");
+pref("social.toast-notifications.enabled", false);
+pref("social.whitelist", "");
+pref("startup.homepage_override_url", "");
+pref("startup.homepage_welcome_url", "");
+pref("svg.in-content.enabled", true);
+pref("toolkit.telemetry.enabled", false);
+pref("toolkit.telemetry.server", "about:blank");
+pref("toolkit.telemetry.archive.enabled", false);
+pref("ui.key.menuAccessKeyFocuses", false); // Disable "alt" as a shortcut key to open full menu bar. Conflicts with "alt" as a modifier
+pref("webgl.disable-extensions", true);
+pref("webgl.disabled", true);
+pref("webgl.min_capability_mode", true);
+pref("xpinstall.signatures.required", true); // Requires AMO signing key for addons
+pref("xpinstall.whitelist.add", "");