Bug 1313097 - update harfbuzz to upstream release 1.3.3. r=jfkthame
authorFrédéric Wang <fred.wang@free.fr>
Wed, 26 Oct 2016 11:53:00 +0200
changeset 319825 ea39ecf49414c920b402938cd1ddef62dbb18c01
parent 319824 7b9c260074e76d3501c4bff39137cf382753e9d0
child 319826 ee15d36745a84ba995d4e349eca3a10690c571ec
push id30880
push userphilringnalda@gmail.com
push dateFri, 28 Oct 2016 02:22:06 +0000
treeherdermozilla-central@944cb0fd0552 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1313097
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1313097 - update harfbuzz to upstream release 1.3.3. r=jfkthame
gfx/harfbuzz/Makefile.am
gfx/harfbuzz/README
gfx/harfbuzz/README-mozilla
gfx/harfbuzz/TODO
gfx/harfbuzz/autogen.sh
gfx/harfbuzz/configure.ac
gfx/harfbuzz/git.mk
gfx/harfbuzz/harfbuzz.doap
gfx/harfbuzz/harfbuzz.pc.in
gfx/harfbuzz/src/check-symbols.sh
gfx/harfbuzz/src/harfbuzz-icu.pc
gfx/harfbuzz/src/harfbuzz.pc
gfx/harfbuzz/src/hb-coretext.cc
gfx/harfbuzz/src/hb-directwrite.cc
gfx/harfbuzz/src/hb-font-private.hh
gfx/harfbuzz/src/hb-glib.cc
gfx/harfbuzz/src/hb-glib.h
gfx/harfbuzz/src/hb-gobject-structs.cc
gfx/harfbuzz/src/hb-ot-layout-math-table.hh
gfx/harfbuzz/src/hb-ot-layout-private.hh
gfx/harfbuzz/src/hb-ot-layout.cc
gfx/harfbuzz/src/hb-ot-math.h
gfx/harfbuzz/src/hb-ot.h
gfx/harfbuzz/src/hb-shape-plan.cc
gfx/harfbuzz/src/hb-version.h
gfx/harfbuzz/src/moz.build
--- a/gfx/harfbuzz/Makefile.am
+++ b/gfx/harfbuzz/Makefile.am
@@ -1,68 +1,72 @@
 # Process this file with automake to produce Makefile.in
 
 NULL =
 
-SUBDIRS = src util test
+ACLOCAL_AMFLAGS = -I m4
 
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = harfbuzz.pc
+SUBDIRS = src util test docs win32
 
 EXTRA_DIST = \
 	autogen.sh \
 	harfbuzz.doap \
+	Android.mk \
+	README.python \
+	BUILD.md \
 	$(NULL)
 
 MAINTAINERCLEANFILES = \
+	$(GITIGNORE_MAINTAINERCLEANFILES_TOPLEVEL) \
+	$(GITIGNORE_MAINTAINERCLEANFILES_M4_LIBTOOL) \
+	$(GITIGNORE_MAINTAINERCLEANFILES_MAKEFILE_IN) \
 	$(srcdir)/INSTALL \
-	$(srcdir)/aclocal.m4 \
-	$(srcdir)/autoscan.log \
-	$(srcdir)/compile \
-	$(srcdir)/config.guess \
-	$(srcdir)/config.h.in \
-	$(srcdir)/config.sub \
-	$(srcdir)/configure.scan \
-	$(srcdir)/depcomp \
-	$(srcdir)/install-sh \
-	$(srcdir)/ltmain.sh \
-	$(srcdir)/missing \
-	$(srcdir)/mkinstalldirs \
 	$(srcdir)/ChangeLog \
-	`find "$(srcdir)" -type f -name Makefile.in -print`
+	$(srcdir)/gtk-doc.make \
+	$(srcdir)/m4/gtk-doc.m4 \
+	$(NULL)
 
 
 #
 # ChangeLog generation
 #
 CHANGELOG_RANGE =
 ChangeLog: $(srcdir)/ChangeLog
 $(srcdir)/ChangeLog:
-	$(AM_V_GEN) if test -d "$(srcdir)/.git"; then \
-	  (GIT_DIR=$(top_srcdir)/.git ./missing --run \
-	   git log $(CHANGELOG_RANGE) --stat) | fmt --split-only > $@.tmp \
-	  && mv -f $@.tmp $@ \
+	$(AM_V_GEN) if test -d "$(top_srcdir)/.git"; then \
+	  (GIT_DIR=$(top_srcdir)/.git \
+	   $(GIT) log $(CHANGELOG_RANGE) --stat) | fmt --split-only > $@.tmp \
+	  && mv -f $@.tmp "$(srcdir)/ChangeLog" \
 	  || ($(RM) $@.tmp; \
 	      echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \
-	      (test -f $@ || echo git-log is required to generate this file >> $@)); \
+	      (test -f $@ || echo git-log is required to generate this file >> "$(srcdir)/$@")); \
 	else \
 	  test -f $@ || \
 	  (echo A git checkout and git-log is required to generate ChangeLog >&2 && \
-	  echo A git checkout and git-log is required to generate this file >> $@); \
+	  echo A git checkout and git-log is required to generate this file >> "$(srcdir)/$@"); \
 	fi
-.PHONY: $(srcdir)/ChangeLog
+.PHONY: ChangeLog $(srcdir)/ChangeLog
 
 
 #
 # Release engineering
 #
 
+DISTCHECK_CONFIGURE_FLAGS = \
+	--enable-gtk-doc \
+	--disable-doc-cross-references \
+	--with-gobject \
+	--enable-introspection \
+	$(NULL)
+
 # TODO: Copy infrastructure from cairo
 
+# TAR_OPTIONS is not set as env var for 'make dist'.  How to fix that?
 TAR_OPTIONS = --owner=0 --group=0
+
 dist-hook: dist-clear-sticky-bits
 # Clean up any sticky bits we may inherit from parent dir
 dist-clear-sticky-bits:
 	chmod -R a-s $(distdir)
 
 
 tar_file = $(PACKAGE_TARNAME)-$(VERSION).tar.bz2
 sha256_file = $(tar_file).sha256
--- a/gfx/harfbuzz/README
+++ b/gfx/harfbuzz/README
@@ -1,7 +1,12 @@
+[![Build Status](https://travis-ci.org/behdad/harfbuzz.svg)](https://travis-ci.org/behdad/harfbuzz)
+[![Build Status](https://ci.appveyor.com/api/projects/status/4oaq58ns2h0m2soa?svg=true)](https://ci.appveyor.com/project/behdad/harfbuzz)
+[![Coverage Status](https://img.shields.io/coveralls/behdad/harfbuzz.svg)](https://coveralls.io/r/behdad/harfbuzz)
+[ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/)
+
 This is HarfBuzz, a text shaping library.
 
 For bug reports, mailing list, and other information please visit:
 
   http://harfbuzz.org/
 
 For license information, see the file COPYING.
--- a/gfx/harfbuzz/README-mozilla
+++ b/gfx/harfbuzz/README-mozilla
@@ -1,17 +1,14 @@
-gfx/harfbuzz status as of 2016-08-21:
+gfx/harfbuzz status as of 2016-10-26:
 
 This directory contains the harfbuzz source from the 'master' branch of
 https://github.com/behdad/harfbuzz.
 
-Current version: 1.3.0 + recent fixes from trunk,
-up to 547ddb0721365dca985aef5b759d08718f7c5f82
-+ the relevant part of https://github.com/behdad/harfbuzz/pull/334.
-
+Current version: 1.3.3
 
 UPDATING:
 
 Note that gfx/harfbuzz/src/hb-version.h is not present in the upstream Git
 repository. It is created at build time by the harfbuzz build system;
 but as we don't use that build system in mozilla, it is necessary to refresh
 this file when updating harfbuzz, and check it into the mozilla tree.
 
--- a/gfx/harfbuzz/TODO
+++ b/gfx/harfbuzz/TODO
@@ -1,85 +1,69 @@
 General fixes:
 =============
 
-- Move feature parsing from util into the library
+- AAT 'morx' implementation.
+
+- Return "safe-to-break" bit from shaping.
+
+- Implement 'rand' feature.
+
+- mask propagation? (when ligation, "or" the masks).
+
+
+API issues:
+===========
+
+- API to accept a list of languages?
+
+- Add init_func to font_funcs.  Adjust ft.
 
 - 'const' for getter APIs? (use mutable internally)
 
-- Fix TT 'kern' on/off and GPOS interaction (move kerning before GPOS)
-
-- Do proper rounding when scaling from font space?
-
-- Misc features:
-  * init/medi/fina/isol for non-cursive scripts
-  * vkna,hkna etc for kana, *jmo for hangul, etc
-
-- Move non-native direction and normalization handling to the generic non-OT
-  layer, such that uniscribe and other backends can use.
-
-- Uniscribe backend needs to enforce one direction only, otherwise cluster
-  values can confused the user.
+- Remove hb_ot_shape_glyphs_closure()?
 
 
-API issues to fix before 1.0:
-============================
+API additions
+=============
 
-- Rename all internal symbols (static ones even) to have _hb prefix?
+- Language to/from script.
 
-- Add pkg-config files for glue codes (harfbuzz-glib, etc)
-
-- Figure out how many .so objects, how to link, etc
+- blob_from_file?
 
 - Add hb-cairo glue
 
 - Add sanitize API (and a cached version, that saves result on blob user-data)
 
-- Add glib GBoxedType stuff and introspection
-
-
-API to add (maybe after 1.0):
-============================
-
-- Add Uniscribe face / font get API
-
 - BCP 47 language handling / API (language_matches?)
 
-- Add hb_face_get_glyph_count()?
-
-- Add hb_font_create_linear()?
+- Add hb_font_create_unscaled()?
 
-- Add hb_shape_plan()/hb_shape_execute()
-
-- Add query API for aalt-like features?
+- Add query / enumeration API for aalt-like features?
 
 - SFNT api? get_num_faces? get_table_tags? (there's something in stash)
 
 - Add segmentation API
 
-- Add hb-fribidi?
+- Add hb-fribidi glue?
 
 
-hb-view enhancements:
-====================
+hb-view / hb-shape enhancements:
+===============================
 
-- Add --format
-- Add --width, --height, --auto-size, --align, etc?
-- Port to GOption, --help
-- Add XML and JSON formats
+- Add --width, --height, --auto-size, --ink-box, --align, etc?
 
 
 Tests to write:
 ==============
 
 - ot-layout enumeration API (needs font)
 
 - Finish test-shape.c, grep for TODO
 
 - Finish test-unicode.c, grep for TODO
 
-
-Optimizations:
-=============
+- GObject, FreeType, etc
 
-- Avoid allocating blob objects internally for for_data() faces?
+- hb_cache_t and relatives
 
-- Add caching layer to hb-ft
+- hb_feature_to/from_string
+- hb_buffer_[sg]et_contents
--- a/gfx/harfbuzz/autogen.sh
+++ b/gfx/harfbuzz/autogen.sh
@@ -14,19 +14,32 @@ which ragel || {
 }
 
 echo -n "checking for pkg-config... "
 which pkg-config || {
 	echo "*** No pkg-config found, please install it ***"
 	exit 1
 }
 
+echo -n "checking for libtoolize... "
+which glibtoolize || which libtoolize || {
+	echo "*** No libtoolize (libtool) found, please install it ***"
+	exit 1
+}
+echo -n "checking for gtkdocize... "
+if which gtkdocize ; then
+	gtkdocize --copy || exit 1
+else
+	echo "*** No gtkdocize (gtk-doc) found, skipping documentation ***"
+	echo "EXTRA_DIST = " > gtk-doc.make
+fi
+
 echo -n "checking for autoreconf... "
 which autoreconf || {
-	echo "*** No autoreconf found, please install it ***"
+	echo "*** No autoreconf (autoconf) found, please install it ***"
 	exit 1
 }
 
 echo "running autoreconf --force --install --verbose"
 autoreconf --force --install --verbose || exit $?
 
 cd $olddir
 echo "running configure $@"
--- a/gfx/harfbuzz/configure.ac
+++ b/gfx/harfbuzz/configure.ac
@@ -1,29 +1,37 @@
 AC_PREREQ([2.64])
-AC_INIT([harfbuzz],
-        [0.7.0],
-        [http://bugs.freedesktop.org/enter_bug.cgi?product=harfbuzz],
+AC_INIT([HarfBuzz],
+        [1.3.3],
+        [https://github.com/behdad/harfbuzz/issues/new],
         [harfbuzz],
         [http://harfbuzz.org/])
 
-AC_CONFIG_SRCDIR([harfbuzz.pc.in])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_SRCDIR([src/harfbuzz.pc.in])
 AC_CONFIG_HEADERS([config.h])
 
-AM_INIT_AUTOMAKE([1.11.1 gnu dist-bzip2 no-dist-gzip -Wall no-define])
+AM_INIT_AUTOMAKE([1.11.1 gnits tar-ustar dist-bzip2 no-dist-gzip -Wall no-define color-tests -Wno-portability])
+AM_CONDITIONAL(AUTOMAKE_OLDER_THAN_1_13, test $am__api_version = 1.11 -o $am__api_version = 1.12)
 AM_SILENT_RULES([yes])
 
+# Initialize libtool
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
+LT_PREREQ([2.2])
+LT_INIT([disable-static])
+
 # Check for programs
+AC_USE_SYSTEM_EXTENSIONS
 AC_PROG_CC
 AM_PROG_CC_C_O
 AC_PROG_CXX
-
-# Initialize libtool
-LT_PREREQ([2.2])
-LT_INIT([disable-static])
+AC_SYS_LARGEFILE
+PKG_PROG_PKG_CONFIG([0.20])
+AM_MISSING_PROG([RAGEL], [ragel])
+AM_MISSING_PROG([GIT], [git])
 
 # Version
 m4_define(hb_version_triplet,m4_split(AC_PACKAGE_VERSION,[[.]]))
 m4_define(hb_version_major,m4_argn(1,hb_version_triplet))
 m4_define(hb_version_minor,m4_argn(2,hb_version_triplet))
 m4_define(hb_version_micro,m4_argn(3,hb_version_triplet))
 HB_VERSION_MAJOR=hb_version_major
 HB_VERSION_MINOR=hb_version_minor
@@ -40,150 +48,476 @@ m4_define([hb_version_int],
 m4_if(m4_eval(hb_version_minor % 2), [1],
       dnl for unstable releases
       [m4_define([hb_libtool_revision], 0)],
       dnl for stable releases
       [m4_define([hb_libtool_revision], hb_version_micro)])
 m4_define([hb_libtool_age],
 	  m4_eval(hb_version_int - hb_libtool_revision))
 m4_define([hb_libtool_current],
-	  m4_eval(hb_version_major + hb_libtool_age))
+	  m4_eval(hb_libtool_age))
 HB_LIBTOOL_VERSION_INFO=hb_libtool_current:hb_libtool_revision:hb_libtool_age
 AC_SUBST(HB_LIBTOOL_VERSION_INFO)
 
-dnl GTK_DOC_CHECK([1.15],[--flavour no-tmpl])
+# Documentation
+have_gtk_doc=false
+m4_ifdef([GTK_DOC_CHECK], [
+GTK_DOC_CHECK([1.15],[--flavour no-tmpl])
+	if test "x$enable_gtk_doc" = xyes; then
+		have_gtk_doc=true
+	fi
+], [
+	AM_CONDITIONAL([ENABLE_GTK_DOC], false)
+])
 
 # Functions and headers
-AC_CHECK_FUNCS(mprotect sysconf getpagesize mmap _setmode)
-AC_CHECK_HEADERS(unistd.h sys/mman.h io.h)
+AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty)
+AC_CHECK_HEADERS(unistd.h sys/mman.h)
 
 # Compiler flags
 AC_CANONICAL_HOST
+AC_CHECK_ALIGNOF([struct{char;}])
 if test "x$GCC" = "xyes"; then
 
 	# Make symbols link locally
 	LDFLAGS="$LDFLAGS -Bsymbolic-functions"
 
 	# Make sure we don't link to libstdc++
 	CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions"
 
+	# Assorted warnings
+	CXXFLAGS="$CXXFLAGS -Wcast-align"
+
+	case "$host" in
+		*-*-mingw*)
+		;;
+		*)
+			# Hide inline methods
+			CXXFLAGS="$CXXFLAGS -fvisibility-inlines-hidden"
+		;;
+	esac
+
 	case "$host" in
 		arm-*-*)
-			# Request byte alignment on arm
-			CXXFLAGS="$CXXFLAGS -mstructure-size-boundary=8"
+			if test "x$ac_cv_alignof_struct_char__" != x1; then
+				# Request byte alignment
+				CXXFLAGS="$CXXFLAGS -mstructure-size-boundary=8"
+			fi
 		;;
 	esac
 fi
 
+AM_CONDITIONAL(HAVE_GCC, test "x$GCC" = "xyes")
+
+hb_os_win32=no
+AC_MSG_CHECKING([for native Win32])
+case "$host" in
+  *-*-mingw*)
+    hb_os_win32=yes
+    ;;
+esac
+AC_MSG_RESULT([$hb_os_win32])
+AM_CONDITIONAL(OS_WIN32, test "$hb_os_win32" = "yes")
+
+have_pthread=false
+if test "$hb_os_win32" = no; then
+	AX_PTHREAD([have_pthread=true])
+fi
+if $have_pthread; then
+	AC_DEFINE(HAVE_PTHREAD, 1, [Have POSIX threads])
+fi
+AM_CONDITIONAL(HAVE_PTHREAD, $have_pthread)
+
 dnl ==========================================================================
 
-PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, have_glib=true, have_glib=false)
+have_ot=true
+if $have_ot; then
+	AC_DEFINE(HAVE_OT, 1, [Have native OpenType Layout backend])
+fi
+AM_CONDITIONAL(HAVE_OT, $have_ot)
+
+have_fallback=true
+if $have_fallback; then
+	AC_DEFINE(HAVE_FALLBACK, 1, [Have simple TrueType Layout backend])
+fi
+AM_CONDITIONAL(HAVE_FALLBACK, $have_fallback)
+
+dnl ===========================================================================
+
+AC_ARG_WITH(glib,
+	[AS_HELP_STRING([--with-glib=@<:@yes/no/auto@:>@],
+			[Use glib @<:@default=auto@:>@])],,
+	[with_glib=auto])
+have_glib=false
+GLIB_DEPS="glib-2.0 >= 2.38"
+AC_SUBST(GLIB_DEPS)
+if test "x$with_glib" = "xyes" -o "x$with_glib" = "xauto"; then
+	PKG_CHECK_MODULES(GLIB, $GLIB_DEPS, have_glib=true, :)
+fi
+if test "x$with_glib" = "xyes" -a "x$have_glib" != "xtrue"; then
+	AC_MSG_ERROR([glib support requested but glib-2.0 not found])
+fi
 if $have_glib; then
 	AC_DEFINE(HAVE_GLIB, 1, [Have glib2 library])
 fi
 AM_CONDITIONAL(HAVE_GLIB, $have_glib)
 
-PKG_CHECK_MODULES(GTHREAD, gthread-2.0, have_gthread=true, have_gthread=false)
-if $have_gthread; then
-	AC_DEFINE(HAVE_GTHREAD, 1, [Have gthread2 library])
+dnl ===========================================================================
+
+AC_ARG_WITH(gobject,
+	[AS_HELP_STRING([--with-gobject=@<:@yes/no/auto@:>@],
+			[Use gobject @<:@default=auto@:>@])],,
+	[with_gobject=no])
+have_gobject=false
+if test "x$with_gobject" = "xyes" -o "x$with_gobject" = "xauto"; then
+	PKG_CHECK_MODULES(GOBJECT, gobject-2.0 glib-2.0, have_gobject=true, :)
 fi
-AM_CONDITIONAL(HAVE_GTHREAD, $have_gthread)
-
-PKG_CHECK_MODULES(GOBJECT, gobject-2.0 glib-2.0 >= 2.16, have_gobject=true, have_gobject=false)
+if test "x$with_gobject" = "xyes" -a "x$have_gobject" != "xtrue"; then
+	AC_MSG_ERROR([gobject support requested but gobject-2.0 / glib-2.0 not found])
+fi
 if $have_gobject; then
 	AC_DEFINE(HAVE_GOBJECT, 1, [Have gobject2 library])
 	GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0`
 	AC_SUBST(GLIB_MKENUMS)
 fi
 AM_CONDITIONAL(HAVE_GOBJECT, $have_gobject)
 
+dnl ===========================================================================
+
+
+dnl ===========================================================================
+# Gobject-Introspection
+have_introspection=false
+m4_ifdef([GOBJECT_INTROSPECTION_CHECK], [
+	if $have_gobject; then
+		GOBJECT_INTROSPECTION_CHECK([1.34.0])
+		if test "x$found_introspection" = xyes; then
+			have_introspection=true
+		fi
+	else
+		AM_CONDITIONAL([HAVE_INTROSPECTION], false)
+	fi
+], [
+	AM_CONDITIONAL([HAVE_INTROSPECTION], false)
+])
+
 dnl ==========================================================================
 
-PKG_CHECK_MODULES(CAIRO, cairo >= 1.8.0, have_cairo=true, have_cairo=false)
+AC_ARG_WITH(cairo,
+	[AS_HELP_STRING([--with-cairo=@<:@yes/no/auto@:>@],
+			[Use cairo @<:@default=auto@:>@])],,
+	[with_cairo=auto])
+have_cairo=false
+if test "x$with_cairo" = "xyes" -o "x$with_cairo" = "xauto"; then
+	PKG_CHECK_MODULES(CAIRO, cairo >= 1.8.0, have_cairo=true, :)
+fi
+if test "x$with_cairo" = "xyes" -a "x$have_cairo" != "xtrue"; then
+	AC_MSG_ERROR([cairo support requested but not found])
+fi
 if $have_cairo; then
 	AC_DEFINE(HAVE_CAIRO, 1, [Have cairo graphics library])
 fi
 AM_CONDITIONAL(HAVE_CAIRO, $have_cairo)
 
-PKG_CHECK_MODULES(CAIRO_FT, cairo-ft, have_cairo_ft=true, have_cairo_ft=false)
+have_cairo_ft=false
+if $have_cairo; then
+	PKG_CHECK_MODULES(CAIRO_FT, cairo-ft, have_cairo_ft=true, :)
+fi
 if $have_cairo_ft; then
 	AC_DEFINE(HAVE_CAIRO_FT, 1, [Have cairo-ft support in cairo graphics library])
 fi
 AM_CONDITIONAL(HAVE_CAIRO_FT, $have_cairo_ft)
 
 dnl ==========================================================================
 
-PKG_CHECK_MODULES(ICU, icu, have_icu=true, [
-	have_icu=true
-	AC_CHECK_HEADERS(unicode/uchar.h,, have_icu=false)
-	AC_MSG_CHECKING([for libicuuc])
-	LIBS_old=$LIBS
-	LIBS="$LIBS -licuuc"
-	AC_TRY_LINK([#include <unicode/uchar.h>],
-		    [u_getIntPropertyValue (0, (UProperty)0);],
-		    AC_MSG_RESULT(yes),
-		    AC_MSG_RESULT(no);have_icu=false)
-	LIBS=$LIBS_old
-	if $have_icu; then
-		ICU_CFLAGS=-D_REENTRANT
-		ICU_LIBS="-licuuc"
-		AC_SUBST(ICU_CFLAGS)
-		AC_SUBST(ICU_LIBS)
-	fi
-])
-if $have_icu; then
-	AC_DEFINE(HAVE_ICU, 1, [Have ICU library])
+AC_ARG_WITH(fontconfig,
+	[AS_HELP_STRING([--with-fontconfig=@<:@yes/no/auto@:>@],
+			[Use fontconfig @<:@default=auto@:>@])],,
+	[with_fontconfig=auto])
+have_fontconfig=false
+if test "x$with_fontconfig" = "xyes" -o "x$with_fontconfig" = "xauto"; then
+	PKG_CHECK_MODULES(FONTCONFIG, fontconfig, have_fontconfig=true, :)
 fi
-AM_CONDITIONAL(HAVE_ICU, $have_icu)
+if test "x$with_fontconfig" = "xyes" -a "x$have_fontconfig" != "xtrue"; then
+	AC_MSG_ERROR([fontconfig support requested but not found])
+fi
+if $have_fontconfig; then
+	AC_DEFINE(HAVE_FONTCONFIG, 1, [Have fontconfig library])
+fi
+AM_CONDITIONAL(HAVE_FONTCONFIG, $have_fontconfig)
 
 dnl ==========================================================================
 
-PKG_CHECK_MODULES(GRAPHITE, graphite2, have_graphite=true, have_graphite=false)
-if $have_graphite; then
-    AC_DEFINE(HAVE_GRAPHITE, 1, [Have Graphite library])
+AC_ARG_WITH(icu,
+	[AS_HELP_STRING([--with-icu=@<:@yes/no/builtin/auto@:>@],
+			[Use ICU @<:@default=auto@:>@])],,
+	[with_icu=auto])
+have_icu=false
+if test "x$with_icu" = "xyes" -o "x$with_icu" = "xbuiltin" -o "x$with_icu" = "xauto"; then
+	PKG_CHECK_MODULES(ICU, icu-uc, have_icu=true, :)
+
+	dnl Fallback to icu-config if ICU pkg-config files could not be found
+	if test "$have_icu" != "true"; then
+		AC_CHECK_TOOL(ICU_CONFIG, icu-config, no)
+		AC_MSG_CHECKING([for ICU by using icu-config fallback])
+		if test "$ICU_CONFIG" != "no" && "$ICU_CONFIG" --version >/dev/null; then
+			have_icu=true
+			# We don't use --cflags as this gives us a lot of things that we don't
+			# necessarily want, like debugging and optimization flags
+			# See man (1) icu-config for more info.
+			ICU_CFLAGS=`$ICU_CONFIG --cppflags`
+			ICU_LIBS=`$ICU_CONFIG --ldflags-searchpath --ldflags-libsonly`
+			AC_SUBST(ICU_CFLAGS)
+			AC_SUBST(ICU_LIBS)
+			AC_MSG_RESULT([yes])
+		else
+			AC_MSG_RESULT([no])
+		fi
+	fi
 fi
-AM_CONDITIONAL(HAVE_GRAPHITE, $have_graphite)
+if test \( "x$with_icu" = "xyes" -o "x$with_icu" = "xbuiltin" \) -a "x$have_icu" != "xtrue"; then
+	AC_MSG_ERROR([icu support requested but icu-uc not found])
+fi
+
+if $have_icu; then
+	CXXFLAGS="$CXXFLAGS `$PKG_CONFIG --variable=CXXFLAGS icu-uc`"
+	AC_DEFINE(HAVE_ICU, 1, [Have ICU library])
+	if test "x$with_icu" = "xbuiltin"; then
+		AC_DEFINE(HAVE_ICU_BUILTIN, 1, [Use hb-icu Unicode callbacks])
+	fi
+fi
+AM_CONDITIONAL(HAVE_ICU, $have_icu)
+AM_CONDITIONAL(HAVE_ICU_BUILTIN, $have_icu && test "x$with_icu" = "xbuiltin")
+
+dnl ===========================================================================
+
+have_ucdn=true
+if $have_glib || test \( $have_icu -a "x$with_icu" = "xbuiltin" \); then
+	have_ucdn=false
+fi
+if $have_ucdn; then
+	AC_DEFINE(HAVE_UCDN, 1, [Have UCDN Unicode functions])
+fi
+AM_CONDITIONAL(HAVE_UCDN, $have_ucdn)
 
 dnl ==========================================================================
 
-PKG_CHECK_MODULES(FREETYPE, freetype2 >= 2.3.8, have_freetype=true, have_freetype=false)
+AC_ARG_WITH(graphite2,
+	[AS_HELP_STRING([--with-graphite2=@<:@yes/no/auto@:>@],
+			[Use the graphite2 library @<:@default=no@:>@])],,
+	[with_graphite2=no])
+have_graphite2=false
+GRAPHITE2_DEPS="graphite2"
+AC_SUBST(GRAPHITE2_DEPS)
+if test "x$with_graphite2" = "xyes" -o "x$with_graphite2" = "xauto"; then
+	PKG_CHECK_MODULES(GRAPHITE2, $GRAPHITE2_DEPS, have_graphite2=true, :)
+	if test "x$have_graphite2" != "xtrue"; then
+                # If pkg-config is not available, graphite2 can still be there
+		ac_save_CFLAGS="$CFLAGS"
+		ac_save_CPPFLAGS="$CPPFLAGS"
+		CFLAGS="$CFLAGS $GRAPHITE2_CFLAGS"
+		CPPFLAGS="$CPPFLAGS $GRAPHITE2_CFLAGS"
+		AC_CHECK_HEADER(graphite2/Segment.h, have_graphite2=true, :)
+		CPPFLAGS="$ac_save_CPPFLAGS"
+		CFLAGS="$ac_save_CFLAGS"
+	fi
+fi
+if test "x$with_graphite2" = "xyes" -a "x$have_graphite2" != "xtrue"; then
+	AC_MSG_ERROR([graphite2 support requested but libgraphite2 not found])
+fi
+if $have_graphite2; then
+	AC_DEFINE(HAVE_GRAPHITE2, 1, [Have Graphite2 library])
+fi
+AM_CONDITIONAL(HAVE_GRAPHITE2, $have_graphite2)
+
+dnl ==========================================================================
+
+AC_ARG_WITH(freetype,
+	[AS_HELP_STRING([--with-freetype=@<:@yes/no/auto@:>@],
+			[Use the FreeType library @<:@default=auto@:>@])],,
+	[with_freetype=auto])
+have_freetype=false
+FREETYPE_DEPS="freetype2 >= 12.0.6"
+AC_SUBST(FREETYPE_DEPS)
+if test "x$with_freetype" = "xyes" -o "x$with_freetype" = "xauto"; then
+	# See freetype/docs/VERSION.DLL; 12.0.6 means freetype-2.4.2
+	PKG_CHECK_MODULES(FREETYPE, $FREETYPE_DEPS, have_freetype=true, :)
+fi
+if test "x$with_freetype" = "xyes" -a "x$have_freetype" != "xtrue"; then
+	AC_MSG_ERROR([FreeType support requested but libfreetype2 not found])
+fi
 if $have_freetype; then
 	AC_DEFINE(HAVE_FREETYPE, 1, [Have FreeType 2 library])
-	_save_libs="$LIBS"
-	_save_cflags="$CFLAGS"
-	LIBS="$LIBS $FREETYPE_LIBS"
-	CFLAGS="$CFLAGS $FREETYPE_CFLAGS"
-	AC_CHECK_FUNCS(FT_Face_GetCharVariantIndex)
-	LIBS="$_save_libs"
-	CFLAGS="$_save_cflags"
 fi
 AM_CONDITIONAL(HAVE_FREETYPE, $have_freetype)
 
 dnl ===========================================================================
 
-have_ot=true;
-if $have_ot; then
-	AC_DEFINE(HAVE_OT, 1, [Have native OpenType Layout backend])
+AC_ARG_WITH(uniscribe,
+	[AS_HELP_STRING([--with-uniscribe=@<:@yes/no/auto@:>@],
+			[Use the Uniscribe library @<:@default=no@:>@])],,
+	[with_uniscribe=no])
+have_uniscribe=false
+if test "x$with_uniscribe" = "xyes" -o "x$with_uniscribe" = "xauto"; then
+	AC_CHECK_HEADERS(usp10.h windows.h, have_uniscribe=true)
+fi
+if test "x$with_uniscribe" = "xyes" -a "x$have_uniscribe" != "xtrue"; then
+	AC_MSG_ERROR([uniscribe support requested but not found])
+fi
+if $have_uniscribe; then
+	UNISCRIBE_CFLAGS=
+	UNISCRIBE_LIBS="-lusp10 -lgdi32 -lrpcrt4"
+	AC_SUBST(UNISCRIBE_CFLAGS)
+	AC_SUBST(UNISCRIBE_LIBS)
+	AC_DEFINE(HAVE_UNISCRIBE, 1, [Have Uniscribe library])
+fi
+AM_CONDITIONAL(HAVE_UNISCRIBE, $have_uniscribe)
+
+dnl ===========================================================================
+
+AC_ARG_WITH(directwrite,
+	[AS_HELP_STRING([--with-directwrite=@<:@yes/no/auto@:>@],
+			[Use the DirectWrite library (experimental) @<:@default=no@:>@])],,
+	[with_directwrite=no])
+have_directwrite=false
+AC_LANG_PUSH([C++])
+if test "x$with_directwrite" = "xyes" -o "x$with_directwrite" = "xauto"; then
+	AC_CHECK_HEADERS(dwrite.h, have_directwrite=true)
+fi
+AC_LANG_POP([C++])
+if test "x$with_directwrite" = "xyes" -a "x$have_directwrite" != "xtrue"; then
+	AC_MSG_ERROR([directwrite support requested but not found])
 fi
-AM_CONDITIONAL(HAVE_OT, $have_ot)
+if $have_directwrite; then
+	DIRECTWRITE_CXXFLAGS=
+	DIRECTWRITE_LIBS="-ldwrite"
+	AC_SUBST(DIRECTWRITE_CXXFLAGS)
+	AC_SUBST(DIRECTWRITE_LIBS)
+	AC_DEFINE(HAVE_DIRECTWRITE, 1, [Have DirectWrite library])
+fi
+AM_CONDITIONAL(HAVE_DIRECTWRITE, $have_directwrite)
+
+dnl ===========================================================================
+
+AC_ARG_WITH(coretext,
+	[AS_HELP_STRING([--with-coretext=@<:@yes/no/auto@:>@],
+			[Use CoreText @<:@default=no@:>@])],,
+	[with_coretext=no])
+have_coretext=false
+if test "x$with_coretext" = "xyes" -o "x$with_coretext" = "xauto"; then
+	AC_CHECK_TYPE(CTFontRef, have_coretext=true,, [#include <ApplicationServices/ApplicationServices.h>])
+
+	if $have_coretext; then
+		CORETEXT_CFLAGS=
+		CORETEXT_LIBS="-framework ApplicationServices"
+		AC_SUBST(CORETEXT_CFLAGS)
+		AC_SUBST(CORETEXT_LIBS)
+	else
+		# On iOS CoreText and CoreGraphics are stand-alone frameworks
+		if test "x$have_coretext" != "xtrue"; then
+			# Check for a different symbol to avoid getting cached result.
+			AC_CHECK_TYPE(CTRunRef, have_coretext=true,, [#include <CoreText/CoreText.h>])
+		fi
+
+		if $have_coretext; then
+			CORETEXT_CFLAGS=
+			CORETEXT_LIBS="-framework CoreText -framework CoreGraphics"
+			AC_SUBST(CORETEXT_CFLAGS)
+			AC_SUBST(CORETEXT_LIBS)
+		fi
+	fi
+fi
+if test "x$with_coretext" = "xyes" -a "x$have_coretext" != "xtrue"; then
+	AC_MSG_ERROR([CoreText support requested but libcoretext not found])
+fi
+if $have_coretext; then
+	AC_DEFINE(HAVE_CORETEXT, 1, [Have Core Text backend])
+fi
+AM_CONDITIONAL(HAVE_CORETEXT, $have_coretext)
 
 dnl ===========================================================================
 
-AC_CHECK_HEADERS(usp10.h windows.h, have_uniscribe=true, have_uniscribe=false)
-if $have_uniscribe; then
-	UNISCRIBE_CFLAGS=
-	UNISCRIBE_LIBS="-lusp10 -lgdi32"
-	AC_SUBST(UNISCRIBE_CFLAGS)
-	AC_SUBST(UNISCRIBE_LIBS)
-	AC_DEFINE(HAVE_UNISCRIBE, 1, [Have Uniscribe backend])
+AC_CACHE_CHECK([for Intel atomic primitives], hb_cv_have_intel_atomic_primitives, [
+	hb_cv_have_intel_atomic_primitives=false
+	AC_TRY_LINK([
+		void memory_barrier (void) { __sync_synchronize (); }
+		int atomic_add (int *i) { return __sync_fetch_and_add (i, 1); }
+		int mutex_trylock (int *m) { return __sync_lock_test_and_set (m, 1); }
+		void mutex_unlock (int *m) { __sync_lock_release (m); }
+		], [], hb_cv_have_intel_atomic_primitives=true
+	)
+])
+if $hb_cv_have_intel_atomic_primitives; then
+	AC_DEFINE(HAVE_INTEL_ATOMIC_PRIMITIVES, 1, [Have Intel __sync_* atomic primitives])
 fi
-AM_CONDITIONAL(HAVE_UNISCRIBE, $have_uniscribe)
+
+dnl ===========================================================================
+
+AC_CACHE_CHECK([for Solaris atomic operations], hb_cv_have_solaris_atomic_ops, [
+	hb_cv_have_solaris_atomic_ops=false
+	AC_TRY_LINK([
+		#include <atomic.h>
+		/* This requires Solaris Studio 12.2 or newer: */
+		#include <mbarrier.h>
+		void memory_barrier (void) { __machine_rw_barrier (); }
+		int atomic_add (volatile unsigned *i) { return atomic_add_int_nv (i, 1); }
+		void *atomic_ptr_cmpxchg (volatile void **target, void *cmp, void *newval) { return atomic_cas_ptr (target, cmp, newval); }
+		], [], hb_cv_have_solaris_atomic_ops=true
+	)
+])
+if $hb_cv_have_solaris_atomic_ops; then
+	AC_DEFINE(HAVE_SOLARIS_ATOMIC_OPS, 1, [Have Solaris __machine_*_barrier and atomic_* operations])
+fi
+
+if test "$os_win32" = no && ! $have_pthread; then
+	AC_CHECK_HEADERS(sched.h)
+	AC_SEARCH_LIBS(sched_yield,rt,AC_DEFINE(HAVE_SCHED_YIELD, 1, [Have sched_yield]))
+fi
+
+dnl ===========================================================================
 
 AC_CONFIG_FILES([
 Makefile
-harfbuzz.pc
 src/Makefile
 src/hb-version.h
+src/hb-ucdn/Makefile
 util/Makefile
 test/Makefile
+test/api/Makefile
+test/fuzzing/Makefile
+test/shaping/Makefile
+docs/Makefile
+docs/version.xml
+win32/Makefile
+win32/config.h.win32
 ])
 
 AC_OUTPUT
+
+AC_MSG_NOTICE([
+
+Build configuration:
+
+Unicode callbacks (you want at least one):
+	Glib:			${have_glib}
+	ICU:			${have_icu}
+	UCDN:			${have_ucdn}
+
+Font callbacks (the more the better):
+	FreeType:		${have_freetype}
+
+Tools used for command-line utilities:
+	Cairo:			${have_cairo}
+	Fontconfig:		${have_fontconfig}
+
+Additional shapers (the more the better):
+	Graphite2:		${have_graphite2}
+
+Platform shapers (not normally needed):
+	CoreText:		${have_coretext}
+	Uniscribe:		${have_uniscribe}
+	DirectWrite:		${have_directwrite}
+
+Other features:
+	Documentation:		${have_gtk_doc}
+	GObject bindings:	${have_gobject}
+	Introspection:		${have_introspection}
+])
--- a/gfx/harfbuzz/git.mk
+++ b/gfx/harfbuzz/git.mk
@@ -1,184 +1,347 @@
-# git.mk
+# git.mk, a small Makefile to autogenerate .gitignore files
+# for autotools-based projects.
 #
 # Copyright 2009, Red Hat, Inc.
+# Copyright 2010,2011,2012,2013 Behdad Esfahbod
 # Written by Behdad Esfahbod
 #
 # Copying and distribution of this file, with or without modification,
-# are permitted in any medium without royalty provided the copyright
+# is permitted in any medium without royalty provided the copyright
 # notice and this notice are preserved.
 #
-# The canonical source for this file is pango/git.mk, or whereever the
-# header of pango/git.mk suggests in the future.
+# The latest version of this file can be downloaded from:
+GIT_MK_URL = https://raw.githubusercontent.com/behdad/git.mk/master/git.mk
+#
+# Bugs, etc, should be reported upstream at:
+#   https://github.com/behdad/git.mk
 #
 # To use in your project, import this file in your git repo's toplevel,
 # then do "make -f git.mk".  This modifies all Makefile.am files in
-# your project to include git.mk.
+# your project to -include git.mk.  Remember to add that line to new
+# Makefile.am files you create in your project, or just rerun the
+# "make -f git.mk".
 #
 # This enables automatic .gitignore generation.  If you need to ignore
 # more files, add them to the GITIGNOREFILES variable in your Makefile.am.
 # But think twice before doing that.  If a file has to be in .gitignore,
 # chances are very high that it's a generated file and should be in one
 # of MOSTLYCLEANFILES, CLEANFILES, DISTCLEANFILES, or MAINTAINERCLEANFILES.
 #
 # The only case that you need to manually add a file to GITIGNOREFILES is
 # when remove files in one of mostlyclean-local, clean-local, distclean-local,
-# or maintainer-clean-local.
+# or maintainer-clean-local make targets.
 #
 # Note that for files like editor backup, etc, there are better places to
 # ignore them.  See "man gitignore".
 #
 # If "make maintainer-clean" removes the files but they are not recognized
 # by this script (that is, if "git status" shows untracked files still), send
 # me the output of "git status" as well as your Makefile.am and Makefile for
-# the directories involved.
+# the directories involved and I'll diagnose.
 #
 # For a list of toplevel files that should be in MAINTAINERCLEANFILES, see
-# pango/Makefile.am.
+# Makefile.am.sample in the git.mk git repo.
 #
 # Don't EXTRA_DIST this file.  It is supposed to only live in git clones,
 # not tarballs.  It serves no useful purpose in tarballs and clutters the
 # build dir.
 #
 # This file knows how to handle autoconf, automake, libtool, gtk-doc,
-# gnome-doc-utils, intltool.
+# gnome-doc-utils, yelp.m4, mallard, intltool, gsettings, dejagnu, appdata,
+# appstream.
+#
+# This makefile provides the following targets:
 #
+# - all: "make all" will build all gitignore files.
+# - gitignore: makes all gitignore files in the current dir and subdirs.
+# - .gitignore: make gitignore file for the current dir.
+# - gitignore-recurse: makes all gitignore files in the subdirs.
 #
 # KNOWN ISSUES:
 #
 # - Recursive configure doesn't work as $(top_srcdir)/git.mk inside the
 #   submodule doesn't find us.  If you have configure.{in,ac} files in
 #   subdirs, add a proxy git.mk file in those dirs that simply does:
 #   "include $(top_srcdir)/../git.mk".  Add more ..'s to your taste.
 #   And add those files to git.  See vte/gnome-pty-helper/git.mk for
 #   example.
 #
 
+
+
+###############################################################################
+# Variables user modules may want to add to toplevel MAINTAINERCLEANFILES:
+###############################################################################
+
+#
+# Most autotools-using modules should be fine including this variable in their
+# toplevel MAINTAINERCLEANFILES:
+GITIGNORE_MAINTAINERCLEANFILES_TOPLEVEL = \
+	$(srcdir)/aclocal.m4 \
+	$(srcdir)/autoscan.log \
+	$(srcdir)/configure.scan \
+	`AUX_DIR=$(srcdir)/$$(cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_AUX_DIR:$$1' ./configure.ac); \
+	 test "x$$AUX_DIR" = "x$(srcdir)/" && AUX_DIR=$(srcdir); \
+	 for x in \
+		ar-lib \
+		compile \
+		config.guess \
+		config.sub \
+		depcomp \
+		install-sh \
+		ltmain.sh \
+		missing \
+		mkinstalldirs \
+		test-driver \
+		ylwrap \
+	 ; do echo "$$AUX_DIR/$$x"; done` \
+	`cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_HEADERS:$$1' ./configure.ac | \
+	head -n 1 | while read f; do echo "$(srcdir)/$$f.in"; done`
+#
+# All modules should also be fine including the following variable, which
+# removes automake-generated Makefile.in files:
+GITIGNORE_MAINTAINERCLEANFILES_MAKEFILE_IN = \
+	`cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_FILES:$$1' ./configure.ac | \
+	while read f; do \
+	  case $$f in Makefile|*/Makefile) \
+	    test -f "$(srcdir)/$$f.am" && echo "$(srcdir)/$$f.in";; esac; \
+	done`
+#
+# Modules that use libtool and use  AC_CONFIG_MACRO_DIR() may also include this,
+# though it's harmless to include regardless.
+GITIGNORE_MAINTAINERCLEANFILES_M4_LIBTOOL = \
+	`MACRO_DIR=$(srcdir)/$$(cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_MACRO_DIR:$$1' ./configure.ac); \
+	 if test "x$$MACRO_DIR" != "x$(srcdir)/"; then \
+		for x in \
+			libtool.m4 \
+			ltoptions.m4 \
+			ltsugar.m4 \
+			ltversion.m4 \
+			lt~obsolete.m4 \
+		; do echo "$$MACRO_DIR/$$x"; done; \
+	 fi`
+
+
+
+###############################################################################
+# Default rule is to install ourselves in all Makefile.am files:
+###############################################################################
+
 git-all: git-mk-install
 
 git-mk-install:
-	@echo Installing git makefile
-	@any_failed=; find $(top_srcdir) -name Makefile.am | while read x; do \
+	@echo "Installing git makefile"
+	@any_failed=; \
+		find "`test -z "$(top_srcdir)" && echo . || echo "$(top_srcdir)"`" -name Makefile.am | while read x; do \
 		if grep 'include .*/git.mk' $$x >/dev/null; then \
-			echo $$x already includes git.mk; \
+			echo "$$x already includes git.mk"; \
 		else \
 			failed=; \
 			echo "Updating $$x"; \
 			{ cat $$x; \
 			  echo ''; \
 			  echo '-include $$(top_srcdir)/git.mk'; \
 			} > $$x.tmp || failed=1; \
 			if test x$$failed = x; then \
 				mv $$x.tmp $$x || failed=1; \
 			fi; \
 			if test x$$failed = x; then : else \
-				echo Failed updating $$x; >&2 \
+				echo "Failed updating $$x"; >&2 \
 				any_failed=1; \
 			fi; \
 	fi; done; test -z "$$any_failed"
 
-.PHONY: git-all git-mk-install
+git-mk-update:
+	wget $(GIT_MK_URL) -O $(top_srcdir)/git.mk
+
+.PHONY: git-all git-mk-install git-mk-update
+
 
 
-### .gitignore generation
+###############################################################################
+# Actual .gitignore generation:
+###############################################################################
 
 $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk
-	$(AM_V_GEN) \
-	{ \
+	@echo "git.mk: Generating $@"
+	@{ \
 		if test "x$(DOC_MODULE)" = x -o "x$(DOC_MAIN_SGML_FILE)" = x; then :; else \
 			for x in \
 				$(DOC_MODULE)-decl-list.txt \
 				$(DOC_MODULE)-decl.txt \
 				tmpl/$(DOC_MODULE)-unused.sgml \
 				"tmpl/*.bak" \
+				$(REPORT_FILES) \
+				$(DOC_MODULE).pdf \
 				xml html \
-			; do echo /$$x; done; \
+			; do echo "/$$x"; done; \
+			FLAVOR=$$(cd $(top_srcdir); $(AUTOCONF) --trace 'GTK_DOC_CHECK:$$2' ./configure.ac); \
+			case $$FLAVOR in *no-tmpl*) echo /tmpl;; esac; \
+			if echo "$(SCAN_OPTIONS)" | grep -q "\-\-rebuild-types"; then \
+				echo "/$(DOC_MODULE).types"; \
+			fi; \
+			if echo "$(SCAN_OPTIONS)" | grep -q "\-\-rebuild-sections"; then \
+				echo "/$(DOC_MODULE)-sections.txt"; \
+			fi; \
+			if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \
+				for x in \
+					$(SETUP_FILES) \
+					$(DOC_MODULE).types \
+				; do echo "/$$x"; done; \
+			fi; \
 		fi; \
-		if test "x$(DOC_MODULE)" = x -o "x$(DOC_LINGUAS)" = x; then :; else \
+		if test "x$(DOC_MODULE)$(DOC_ID)" = x -o "x$(DOC_LINGUAS)" = x; then :; else \
+			for lc in $(DOC_LINGUAS); do \
+				for x in \
+					$(if $(DOC_MODULE),$(DOC_MODULE).xml) \
+					$(DOC_PAGES) \
+					$(DOC_INCLUDES) \
+				; do echo "/$$lc/$$x"; done; \
+			done; \
 			for x in \
-				$(_DOC_C_DOCS) \
-				$(_DOC_LC_DOCS) \
 				$(_DOC_OMF_ALL) \
 				$(_DOC_DSK_ALL) \
 				$(_DOC_HTML_ALL) \
-				$(_DOC_POFILES) \
+				$(_DOC_MOFILES) \
+				$(DOC_H_FILE) \
 				"*/.xml2po.mo" \
 				"*/*.omf.out" \
 			; do echo /$$x; done; \
 		fi; \
+		if test "x$(HELP_ID)" = x -o "x$(HELP_LINGUAS)" = x; then :; else \
+			for lc in $(HELP_LINGUAS); do \
+				for x in \
+					$(HELP_FILES) \
+					"$$lc.stamp" \
+					"$$lc.mo" \
+				; do echo "/$$lc/$$x"; done; \
+			done; \
+		fi; \
+		if test "x$(gsettings_SCHEMAS)" = x; then :; else \
+			for x in \
+				$(gsettings_SCHEMAS:.xml=.valid) \
+				$(gsettings__enum_file) \
+			; do echo "/$$x"; done; \
+		fi; \
+		if test "x$(appdata_XML)" = x; then :; else \
+			for x in \
+				$(appdata_XML:.xml=.valid) \
+			; do echo "/$$x"; done; \
+		fi; \
+		if test "x$(appstream_XML)" = x; then :; else \
+			for x in \
+				$(appstream_XML:.xml=.valid) \
+			; do echo "/$$x"; done; \
+		fi; \
 		if test -f $(srcdir)/po/Makefile.in.in; then \
 			for x in \
 				po/Makefile.in.in \
+				po/Makefile.in.in~ \
 				po/Makefile.in \
 				po/Makefile \
+				po/Makevars.template \
 				po/POTFILES \
+				po/Rules-quot \
 				po/stamp-it \
 				po/.intltool-merge-cache \
 				"po/*.gmo" \
+				"po/*.header" \
 				"po/*.mo" \
+				"po/*.sed" \
+				"po/*.sin" \
 				po/$(GETTEXT_PACKAGE).pot \
 				intltool-extract.in \
 				intltool-merge.in \
 				intltool-update.in \
-			; do echo /$$x; done; \
+			; do echo "/$$x"; done; \
 		fi; \
 		if test -f $(srcdir)/configure; then \
 			for x in \
 				autom4te.cache \
 				configure \
 				config.h \
 				stamp-h1 \
 				libtool \
 				config.lt \
-			; do echo /$$x; done; \
+			; do echo "/$$x"; done; \
+		fi; \
+		if test "x$(DEJATOOL)" = x; then :; else \
+			for x in \
+				$(DEJATOOL) \
+			; do echo "/$$x.sum"; echo "/$$x.log"; done; \
+			echo /site.exp; \
+		fi; \
+		if test "x$(am__dirstamp)" = x; then :; else \
+			echo "$(am__dirstamp)"; \
+		fi; \
+		if test "x$(LTCOMPILE)" = x -a "x$(LTCXXCOMPILE)" = x -a "x$(GTKDOC_RUN)" = x; then :; else \
+			for x in \
+				"*.lo" \
+				".libs" "_libs" \
+			; do echo "$$x"; done; \
 		fi; \
 		for x in \
 			.gitignore \
 			$(GITIGNOREFILES) \
 			$(CLEANFILES) \
-			$(PROGRAMS) \
-			$(check_PROGRAMS) \
-			$(EXTRA_PROGRAMS) \
-			$(LTLIBRARIES) \
+			$(PROGRAMS) $(check_PROGRAMS) $(EXTRA_PROGRAMS) \
+			$(LIBRARIES) $(check_LIBRARIES) $(EXTRA_LIBRARIES) \
+			$(LTLIBRARIES) $(check_LTLIBRARIES) $(EXTRA_LTLIBRARIES) \
 			so_locations \
-			.libs _libs \
 			$(MOSTLYCLEANFILES) \
-			"*.$(OBJEXT)" \
-			"*.lo" \
+			$(TEST_LOGS) \
+			$(TEST_LOGS:.log=.trs) \
+			$(TEST_SUITE_LOG) \
+			$(TESTS:=.test) \
+			"*.gcda" \
+			"*.gcno" \
 			$(DISTCLEANFILES) \
 			$(am__CONFIG_DISTCLEAN_FILES) \
 			$(CONFIG_CLEAN_FILES) \
 			TAGS ID GTAGS GRTAGS GSYMS GPATH tags \
 			"*.tab.c" \
 			$(MAINTAINERCLEANFILES) \
 			$(BUILT_SOURCES) \
-			$(DEPDIR) \
+			$(patsubst %.vala,%.c,$(filter %.vala,$(SOURCES))) \
+			$(filter %_vala.stamp,$(DIST_COMMON)) \
+			$(filter %.vapi,$(DIST_COMMON)) \
+			$(filter $(addprefix %,$(notdir $(patsubst %.vapi,%.h,$(filter %.vapi,$(DIST_COMMON))))),$(DIST_COMMON)) \
 			Makefile \
 			Makefile.in \
 			"*.orig" \
 			"*.rej" \
 			"*.bak" \
 			"*~" \
 			".*.sw[nop]" \
-		; do echo /$$x; done; \
+			".dirstamp" \
+		; do echo "/$$x"; done; \
+		for x in \
+			"*.$(OBJEXT)" \
+			$(DEPDIR) \
+		; do echo "$$x"; done; \
 	} | \
 	sed "s@^/`echo "$(srcdir)" | sed 's/\(.\)/[\1]/g'`/@/@" | \
 	sed 's@/[.]/@/@g' | \
 	LC_ALL=C sort | uniq > $@.tmp && \
 	mv $@.tmp $@;
 
 all: $(srcdir)/.gitignore gitignore-recurse-maybe
+gitignore: $(srcdir)/.gitignore gitignore-recurse
+
 gitignore-recurse-maybe:
-	@if test "x$(SUBDIRS)" = "x$(DIST_SUBDIRS)"; then :; else \
-		$(MAKE) $(AM_MAKEFLAGS) gitignore-recurse; \
-	fi;
+	@for subdir in $(DIST_SUBDIRS); do \
+	  case " $(SUBDIRS) " in \
+	    *" $$subdir "*) :;; \
+	    *) test "$$subdir" = . -o -e "$$subdir/.git" || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) gitignore || echo "Skipping $$subdir");; \
+	  esac; \
+	done
 gitignore-recurse:
-	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
-	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) .gitignore gitignore-recurse || echo "Skipping $$subdir"); \
+	@for subdir in $(DIST_SUBDIRS); do \
+	    test "$$subdir" = . -o -e "$$subdir/.git" || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) gitignore || echo "Skipping $$subdir"); \
 	done
-gitignore: $(srcdir)/.gitignore gitignore-recurse
 
 maintainer-clean: gitignore-clean
 gitignore-clean:
 	-rm -f $(srcdir)/.gitignore
 
 .PHONY: gitignore-clean gitignore gitignore-recurse gitignore-recurse-maybe
new file mode 100644
--- /dev/null
+++ b/gfx/harfbuzz/harfbuzz.doap
@@ -0,0 +1,24 @@
+<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+         xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
+         xmlns:foaf="http://xmlns.com/foaf/0.1/"
+         xmlns="http://usefulinc.com/ns/doap#">
+
+  <name xml:lang="en">harfbuzz</name>
+  <shortdesc xml:lang="en">Text shaping library</shortdesc>
+
+  <homepage
+  rdf:resource="http://harfbuzz.org/" />
+  <mailing-list
+  rdf:resource="http://lists.freedesktop.org/mailman/listinfo/harfbuzz" />
+  <!--download-page
+  rdf:resource=""/-->
+  <bug-database
+  rdf:resource="http://bugs.freedesktop.org/enter_bug.cgi?product=harfbuzz"/>
+
+  <maintainer>
+    <foaf:Person>
+      <foaf:name>Behdad Esfahbod</foaf:name>
+      <foaf:mbox rdf:resource="mailto:harfbuzz@behdad.org" />
+    </foaf:Person>
+  </maintainer>
+</Project>
deleted file mode 100644
--- a/gfx/harfbuzz/harfbuzz.pc.in
+++ /dev/null
@@ -1,11 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: harfbuzz
-Description: Text shaping library
-Version: @VERSION@
-
-Libs: -L${libdir} -lharfbuzz
-Cflags: -I${includedir}/harfbuzz
--- a/gfx/harfbuzz/src/check-symbols.sh
+++ b/gfx/harfbuzz/src/check-symbols.sh
@@ -14,18 +14,18 @@ else
 	exit 77
 fi
 
 echo "Checking that we are not exposing internal symbols"
 tested=false
 for suffix in so dylib; do
 	so=.libs/libharfbuzz.$suffix
 	if ! test -f "$so"; then continue; fi
-	
-	EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>\| __gcov_flush\>\| llvm_' | cut -d' ' -f3`"
+
+	EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>\| __gcov_flush\>\| ___gcov_flush\>\| llvm_\| _llvm_' | cut -d' ' -f3`"
 
 	prefix=`basename "$so" | sed 's/libharfbuzz/hb/; s/-/_/g; s/[.].*//'`
 
 	# On mac, C symbols are prefixed with _
 	if test $suffix = dylib; then prefix="_$prefix"; fi
 
 	echo "Processing $so"
 	if echo "$EXPORTED_SYMBOLS" | grep -v "^${prefix}_"; then
--- a/gfx/harfbuzz/src/harfbuzz-icu.pc
+++ b/gfx/harfbuzz/src/harfbuzz-icu.pc
@@ -1,13 +1,13 @@
 prefix=/usr/local
 exec_prefix=/usr/local
 libdir=/usr/local/lib
 includedir=/usr/local/include
 
 Name: harfbuzz
 Description: HarfBuzz text shaping library ICU integration
-Version: 1.0.1
+Version: 1.3.3
 
 Requires: harfbuzz
 Requires.private: icu-uc
 Libs: -L${libdir} -lharfbuzz-icu
 Cflags: -I${includedir}/harfbuzz
--- a/gfx/harfbuzz/src/harfbuzz.pc
+++ b/gfx/harfbuzz/src/harfbuzz.pc
@@ -1,11 +1,13 @@
 prefix=/usr/local
 exec_prefix=/usr/local
 libdir=/usr/local/lib
 includedir=/usr/local/include
 
 Name: harfbuzz
 Description: HarfBuzz text shaping library
-Version: 1.0.1
+Version: 1.3.3
 
 Libs: -L${libdir} -lharfbuzz
+Libs.private:    
+Requires.private: glib-2.0 >= 2.38 
 Cflags: -I${includedir}/harfbuzz
--- a/gfx/harfbuzz/src/hb-coretext.cc
+++ b/gfx/harfbuzz/src/hb-coretext.cc
@@ -144,19 +144,27 @@ create_ct_font (CGFontRef cg_font, CGFlo
   if (unlikely (!ct_font)) {
     DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed");
     return NULL;
   }
 
   /* crbug.com/576941 and crbug.com/625902 and the investigation in the latter
    * bug indicate that the cascade list reconfiguration occasionally causes
    * crashes in CoreText on OS X 10.9, thus let's skip this step on older
-   * operating system versions. */
-  if (&CTGetCoreTextVersion != NULL && CTGetCoreTextVersion() <= kCTVersionNumber10_9)
-    return ct_font;
+   * operating system versions. Except for the emoji font, where _not_
+   * reconfiguring the cascade list causes CoreText crashes. For details, see
+   * crbug.com/549610 */
+  // 0x00070000 stands for "kCTVersionNumber10_10", see CoreText.h
+  if (&CTGetCoreTextVersion != NULL && CTGetCoreTextVersion() < 0x00070000) {
+    CFStringRef fontName = CTFontCopyPostScriptName (ct_font);
+    bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) == kCFCompareEqualTo;
+    CFRelease (fontName);
+    if (!isEmojiFont)
+      return ct_font;
+  }
 
   CFURLRef original_url = (CFURLRef)CTFontCopyAttribute(ct_font, kCTFontURLAttribute);
 
   /* Create font copy with cascade list that has LastResort first; this speeds up CoreText
    * font fallback which we don't need anyway. */
   {
     CTFontDescriptorRef last_resort_font_desc = get_last_resort_font_desc ();
     CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (ct_font, 0.0, NULL, last_resort_font_desc);
--- a/gfx/harfbuzz/src/hb-directwrite.cc
+++ b/gfx/harfbuzz/src/hb-directwrite.cc
@@ -24,20 +24,16 @@
 
 #define HB_SHAPER directwrite
 #include "hb-shaper-impl-private.hh"
 
 #include <DWrite_1.h>
 
 #include "hb-directwrite.h"
 
-#include "hb-open-file-private.hh"
-#include "hb-ot-name-table.hh"
-#include "hb-ot-tag.h"
-
 
 #ifndef HB_DEBUG_DIRECTWRITE
 #define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0)
 #endif
 
 HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, face)
 HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, font)
 
--- a/gfx/harfbuzz/src/hb-font-private.hh
+++ b/gfx/harfbuzz/src/hb-font-private.hh
@@ -111,18 +111,22 @@ struct hb_font_t {
   hb_font_funcs_t   *klass;
   void              *user_data;
   hb_destroy_func_t  destroy;
 
   struct hb_shaper_data_t shaper_data;
 
 
   /* Convert from font-space to user-space */
-  inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); }
-  inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); }
+  inline int dir_scale (hb_direction_t direction)
+  { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
+  inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
+  inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
+  inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
+  { return em_scale (v, dir_scale (direction)); }
 
   /* Convert from parent-font user-space to our user-space */
   inline hb_position_t parent_scale_x_distance (hb_position_t v) {
     if (unlikely (parent && parent->x_scale != x_scale))
       return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
     return v;
   }
   inline hb_position_t parent_scale_y_distance (hb_position_t v) {
@@ -499,17 +503,16 @@ struct hb_font_t {
 	  hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
 	  get_nominal_glyph (unichar, glyph))
 	return true;
     }
 
     return false;
   }
 
-  private:
   inline hb_position_t em_scale (int16_t v, int scale)
   {
     int upem = face->get_upem ();
     int64_t scaled = v * (int64_t) scale;
     scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
     return (hb_position_t) (scaled / upem);
   }
 };
--- a/gfx/harfbuzz/src/hb-glib.cc
+++ b/gfx/harfbuzz/src/hb-glib.cc
@@ -377,26 +377,24 @@ hb_glib_get_unicode_funcs (void)
       HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
 #undef HB_UNICODE_FUNC_IMPLEMENT
     }
   };
 
   return const_cast<hb_unicode_funcs_t *> (&_hb_glib_unicode_funcs);
 }
 
-#if GLIB_CHECK_VERSION(2,31,10)
 /**
  * hb_glib_blob_create:
  *
  * Since: 0.9.38
  **/
 hb_blob_t *
 hb_glib_blob_create (GBytes *gbytes)
 {
   gsize size = 0;
   gconstpointer data = g_bytes_get_data (gbytes, &size);
   return hb_blob_create ((const char *) data,
 			 size,
 			 HB_MEMORY_MODE_READONLY,
 			 g_bytes_ref (gbytes),
 			 (hb_destroy_func_t) g_bytes_unref);
 }
-#endif
--- a/gfx/harfbuzz/src/hb-glib.h
+++ b/gfx/harfbuzz/src/hb-glib.h
@@ -41,16 +41,15 @@ hb_glib_script_to_script (GUnicodeScript
 
 HB_EXTERN GUnicodeScript
 hb_glib_script_from_script (hb_script_t script);
 
 
 HB_EXTERN hb_unicode_funcs_t *
 hb_glib_get_unicode_funcs (void);
 
-#if GLIB_CHECK_VERSION(2,31,10)
 HB_EXTERN hb_blob_t *
 hb_glib_blob_create (GBytes *gbytes);
-#endif
+
 
 HB_END_DECLS
 
 #endif /* HB_GLIB_H */
--- a/gfx/harfbuzz/src/hb-gobject-structs.cc
+++ b/gfx/harfbuzz/src/hb-gobject-structs.cc
@@ -73,8 +73,11 @@ HB_DEFINE_OBJECT_TYPE (font_funcs)
 HB_DEFINE_OBJECT_TYPE (set)
 HB_DEFINE_OBJECT_TYPE (shape_plan)
 HB_DEFINE_OBJECT_TYPE (unicode_funcs)
 HB_DEFINE_VALUE_TYPE (feature)
 HB_DEFINE_VALUE_TYPE (glyph_info)
 HB_DEFINE_VALUE_TYPE (glyph_position)
 HB_DEFINE_VALUE_TYPE (segment_properties)
 HB_DEFINE_VALUE_TYPE (user_data_key)
+
+HB_DEFINE_VALUE_TYPE (ot_math_glyph_variant)
+HB_DEFINE_VALUE_TYPE (ot_math_glyph_part)
new file mode 100644
--- /dev/null
+++ b/gfx/harfbuzz/src/hb-ot-layout-math-table.hh
@@ -0,0 +1,722 @@
+/*
+ * Copyright © 2016  Igalia S.L.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Igalia Author(s): Frédéric Wang
+ */
+
+#ifndef HB_OT_LAYOUT_MATH_TABLE_HH
+#define HB_OT_LAYOUT_MATH_TABLE_HH
+
+#include "hb-open-type-private.hh"
+#include "hb-ot-layout-common-private.hh"
+#include "hb-ot-math.h"
+
+namespace OT {
+
+
+struct MathValueRecord
+{
+  inline hb_position_t get_x_value (hb_font_t *font, const void *base) const
+  { return font->em_scale_x (value) + (base+deviceTable).get_x_delta (font); }
+  inline hb_position_t get_y_value (hb_font_t *font, const void *base) const
+  { return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); }
+
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && deviceTable.sanitize (c, base));
+  }
+
+  protected:
+  SHORT			value;		/* The X or Y value in design units */
+  OffsetTo<Device>	deviceTable;	/* Offset to the device table - from the
+					 * beginning of parent table. May be NULL.
+					 * Suggested format for device table is 1. */
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct MathConstants
+{
+  inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+
+    unsigned int count = ARRAY_LENGTH (mathValueRecords);
+    for (unsigned int i = 0; i < count; i++)
+      if (!mathValueRecords[i].sanitize (c, this))
+	return_trace (false);
+
+    return_trace (true);
+  }
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && sanitize_math_value_records(c));
+  }
+
+  inline hb_position_t get_value (hb_ot_math_constant_t constant,
+				  hb_font_t *font) const
+  {
+    switch (constant) {
+
+    case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN:
+    case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN:
+      return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN];
+
+    case HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT:
+    case HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT:
+      return font->em_scale_y (minHeight[constant - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT]);
+
+    case HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE:
+    case HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE:
+    case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP:
+    case HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT:
+      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_x_value(font, this);
+
+    case HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT:
+    case HB_OT_MATH_CONSTANT_AXIS_HEIGHT:
+    case HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT:
+    case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS:
+    case HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN:
+    case HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_MATH_LEADING:
+    case HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER:
+    case HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS:
+    case HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER:
+    case HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS:
+    case HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_STACK_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN:
+    case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN:
+    case HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN:
+    case HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX:
+    case HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED:
+    case HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER:
+    case HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS:
+    case HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN:
+    case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN:
+      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value(font, this);
+
+    case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT:
+      return radicalDegreeBottomRaisePercent;
+
+    default:
+      return 0;
+    }
+  }
+
+  protected:
+  SHORT percentScaleDown[2];
+  USHORT minHeight[2];
+  MathValueRecord mathValueRecords[51];
+  SHORT radicalDegreeBottomRaisePercent;
+
+  public:
+  DEFINE_SIZE_STATIC (214);
+};
+
+struct MathItalicsCorrectionInfo
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+		  coverage.sanitize (c, this) &&
+		  italicsCorrection.sanitize (c, this));
+  }
+
+  inline hb_position_t get_value (hb_codepoint_t glyph,
+				  hb_font_t *font) const
+  {
+    unsigned int index = (this+coverage).get_coverage (glyph);
+    return italicsCorrection[index].get_x_value (font, this);
+  }
+
+  protected:
+  OffsetTo<Coverage>       coverage;		/* Offset to Coverage table -
+						 * from the beginning of
+						 * MathItalicsCorrectionInfo
+						 * table. */
+  ArrayOf<MathValueRecord> italicsCorrection;	/* Array of MathValueRecords
+						 * defining italics correction
+						 * values for each
+						 * covered glyph. */
+
+  public:
+  DEFINE_SIZE_ARRAY (4, italicsCorrection);
+};
+
+struct MathTopAccentAttachment
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+		  topAccentCoverage.sanitize (c, this) &&
+		  topAccentAttachment.sanitize (c, this));
+  }
+
+  inline hb_position_t get_value (hb_codepoint_t glyph,
+				  hb_font_t *font) const
+  {
+    unsigned int index = (this+topAccentCoverage).get_coverage (glyph);
+    if (index == NOT_COVERED)
+      return font->get_glyph_h_advance (glyph) / 2;
+    return topAccentAttachment[index].get_x_value(font, this);
+  }
+
+  protected:
+  OffsetTo<Coverage>       topAccentCoverage;   /* Offset to Coverage table -
+						 * from the beginning of
+						 * MathTopAccentAttachment
+						 * table. */
+  ArrayOf<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords
+						 * defining top accent
+						 * attachment points for each
+						 * covered glyph. */
+
+  public:
+  DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment);
+};
+
+struct MathKern
+{
+  inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    unsigned int count = 2 * heightCount + 1;
+    for (unsigned int i = 0; i < count; i++)
+      if (!mathValueRecords[i].sanitize (c, this)) return_trace (false);
+    return_trace (true);
+  }
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+		  c->check_array (mathValueRecords,
+				  mathValueRecords[0].static_size,
+				  2 * heightCount + 1) &&
+		  sanitize_math_value_records (c));
+  }
+
+  inline hb_position_t get_value (hb_position_t correction_height, hb_font_t *font) const
+  {
+    const MathValueRecord* correctionHeight = mathValueRecords;
+    const MathValueRecord* kernValue = mathValueRecords + heightCount;
+    int sign = font->y_scale < 0 ? -1 : +1;
+
+    /* The description of the MathKern table is a ambiguous, but interpreting
+     * "between the two heights found at those indexes" for 0 < i < len as
+     *
+     *   correctionHeight[i-1] < correction_height <= correctionHeight[i]
+     *
+     * makes the result consistent with the limit cases and we can just use the
+     * binary search algorithm of std::upper_bound:
+     */
+    unsigned int i = 0;
+    unsigned int count = heightCount;
+    while (count > 0)
+    {
+      unsigned int half = count / 2;
+      hb_position_t height = correctionHeight[i + half].get_y_value(font, this);
+      if (sign * height < sign * correction_height)
+      {
+	i += half + 1;
+	count -= half + 1;
+      } else
+	count = half;
+    }
+    return kernValue[i].get_x_value(font, this);
+  }
+
+  protected:
+  USHORT	  heightCount;
+  MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at
+					  * which the kern value changes.
+					  * Sorted by the height value in
+					  * design units (heightCount entries),
+					  * Followed by:
+					  * Array of kern values corresponding
+					  * to heights. (heightCount+1 entries).
+					  */
+
+  public:
+  DEFINE_SIZE_ARRAY (2, mathValueRecords);
+};
+
+struct MathKernInfoRecord
+{
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+
+    unsigned int count = ARRAY_LENGTH (mathKern);
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!mathKern[i].sanitize (c, base)))
+	return_trace (false);
+
+    return_trace (true);
+  }
+
+  inline hb_position_t get_kerning (hb_ot_math_kern_t kern,
+				    hb_position_t correction_height,
+				    hb_font_t *font,
+				    const void *base) const
+  {
+    unsigned int idx = kern;
+    if (unlikely (idx >= ARRAY_LENGTH (mathKern))) return 0;
+    return (base+mathKern[idx]).get_value (correction_height, font);
+  }
+
+  protected:
+  /* Offset to MathKern table for each corner -
+   * from the beginning of MathKernInfo table. May be NULL. */
+  OffsetTo<MathKern> mathKern[4];
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct MathKernInfo
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+		  mathKernCoverage.sanitize (c, this) &&
+		  mathKernInfoRecords.sanitize (c, this));
+  }
+
+  inline hb_position_t get_kerning (hb_codepoint_t glyph,
+				    hb_ot_math_kern_t kern,
+				    hb_position_t correction_height,
+				    hb_font_t *font) const
+  {
+    unsigned int index = (this+mathKernCoverage).get_coverage (glyph);
+    return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this);
+  }
+
+  protected:
+  OffsetTo<Coverage>		mathKernCoverage;    /* Offset to Coverage table -
+						      * from the beginning of the
+						      * MathKernInfo table. */
+  ArrayOf<MathKernInfoRecord>	mathKernInfoRecords; /* Array of
+						      * MathKernInfoRecords,
+						      * per-glyph information for
+						      * mathematical positioning
+						      * of subscripts and
+						      * superscripts. */
+
+  public:
+  DEFINE_SIZE_ARRAY (4, mathKernInfoRecords);
+};
+
+struct MathGlyphInfo
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+		  mathItalicsCorrectionInfo.sanitize (c, this) &&
+		  mathTopAccentAttachment.sanitize (c, this) &&
+		  extendedShapeCoverage.sanitize (c, this) &&
+		  mathKernInfo.sanitize(c, this));
+  }
+
+  inline hb_position_t
+  get_italics_correction (hb_codepoint_t  glyph, hb_font_t *font) const
+  { return (this+mathItalicsCorrectionInfo).get_value (glyph, font); }
+
+  inline hb_position_t
+  get_top_accent_attachment (hb_codepoint_t  glyph, hb_font_t *font) const
+  { return (this+mathTopAccentAttachment).get_value (glyph, font); }
+
+  inline bool is_extended_shape (hb_codepoint_t glyph) const
+  { return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; }
+
+  inline hb_position_t get_kerning (hb_codepoint_t glyph,
+				    hb_ot_math_kern_t kern,
+				    hb_position_t correction_height,
+				    hb_font_t *font) const
+  { return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); }
+
+  protected:
+  /* Offset to MathItalicsCorrectionInfo table -
+   * from the beginning of MathGlyphInfo table. */
+  OffsetTo<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo;
+
+  /* Offset to MathTopAccentAttachment table -
+   * from the beginning of MathGlyphInfo table. */
+  OffsetTo<MathTopAccentAttachment> mathTopAccentAttachment;
+
+  /* Offset to coverage table for Extended Shape glyphs -
+   * from the beginning of MathGlyphInfo table. When the left or right glyph of
+   * a box is an extended shape variant, the (ink) box (and not the default
+   * position defined by values in MathConstants table) should be used for
+   * vertical positioning purposes. May be NULL.. */
+  OffsetTo<Coverage> extendedShapeCoverage;
+
+   /* Offset to MathKernInfo table -
+    * from the beginning of MathGlyphInfo table. */
+  OffsetTo<MathKernInfo> mathKernInfo;
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct MathGlyphVariantRecord
+{
+  friend struct MathGlyphConstruction;
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  protected:
+  GlyphID variantGlyph;       /* Glyph ID for the variant. */
+  USHORT  advanceMeasurement; /* Advance width/height, in design units, of the
+			       * variant, in the direction of requested
+			       * glyph extension. */
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct PartFlags : USHORT
+{
+  enum Flags {
+    Extender	= 0x0001u, /* If set, the part can be skipped or repeated. */
+
+    Defined	= 0x0001u, /* All defined flags. */
+  };
+
+  public:
+  DEFINE_SIZE_STATIC (2);
+};
+
+struct MathGlyphPartRecord
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  inline void extract (hb_ot_math_glyph_part_t &out,
+		       int scale,
+		       hb_font_t *font) const
+  {
+    out.glyph			= glyph;
+
+    out.start_connector_length	= font->em_scale (startConnectorLength, scale);
+    out.end_connector_length	= font->em_scale (endConnectorLength, scale);
+    out.full_advance		= font->em_scale (fullAdvance, scale);
+
+    ASSERT_STATIC ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER ==
+		   (unsigned int) PartFlags::Extender);
+
+    out.flags = (hb_ot_math_glyph_part_flags_t)
+		(unsigned int)
+		(partFlags & PartFlags::Defined);
+  }
+
+  protected:
+  GlyphID   glyph;		  /* Glyph ID for the part. */
+  USHORT    startConnectorLength; /* Advance width/ height of the straight bar
+				   * connector material, in design units, is at
+				   * the beginning of the glyph, in the
+				   * direction of the extension. */
+  USHORT    endConnectorLength;   /* Advance width/ height of the straight bar
+				   * connector material, in design units, is at
+				   * the end of the glyph, in the direction of
+				   * the extension. */
+  USHORT    fullAdvance;	  /* Full advance width/height for this part,
+				   * in the direction of the extension.
+				   * In design units. */
+  PartFlags partFlags;		  /* Part qualifiers. */
+
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+struct MathGlyphAssembly
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+		  italicsCorrection.sanitize(c, this) &&
+		  partRecords.sanitize(c));
+  }
+
+  inline unsigned int get_parts (hb_direction_t direction,
+				 hb_font_t *font,
+				 unsigned int start_offset,
+				 unsigned int *parts_count, /* IN/OUT */
+				 hb_ot_math_glyph_part_t *parts /* OUT */,
+				 hb_position_t *italics_correction /* OUT */) const
+  {
+    if (parts_count)
+    {
+      int scale = font->dir_scale (direction);
+      const MathGlyphPartRecord *arr =
+	    partRecords.sub_array (start_offset, parts_count);
+      unsigned int count = *parts_count;
+      for (unsigned int i = 0; i < count; i++)
+	arr[i].extract (parts[i], scale, font);
+    }
+
+    if (italics_correction)
+      *italics_correction = italicsCorrection.get_x_value (font, this);
+
+    return partRecords.len;
+  }
+
+  protected:
+  MathValueRecord	   italicsCorrection; /* Italics correction of this
+					       * MathGlyphAssembly. Should not
+					       * depend on the assembly size. */
+  ArrayOf<MathGlyphPartRecord> partRecords;   /* Array of part records, from
+					       * left to right and bottom to
+					       * top. */
+
+  public:
+  DEFINE_SIZE_ARRAY (6, partRecords);
+};
+
+struct MathGlyphConstruction
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+		  glyphAssembly.sanitize(c, this) &&
+		  mathGlyphVariantRecord.sanitize(c));
+  }
+
+  inline const MathGlyphAssembly &get_assembly (void) const
+  { return this+glyphAssembly; }
+
+  inline unsigned int get_variants (hb_direction_t direction,
+				    hb_font_t *font,
+				    unsigned int start_offset,
+				    unsigned int *variants_count, /* IN/OUT */
+				    hb_ot_math_glyph_variant_t *variants /* OUT */) const
+  {
+    if (variants_count)
+    {
+      int scale = font->dir_scale (direction);
+      const MathGlyphVariantRecord *arr =
+	    mathGlyphVariantRecord.sub_array (start_offset, variants_count);
+      unsigned int count = *variants_count;
+      for (unsigned int i = 0; i < count; i++)
+      {
+	variants[i].glyph = arr[i].variantGlyph;
+	variants[i].advance = font->em_scale (arr[i].advanceMeasurement, scale);
+      }
+    }
+    return mathGlyphVariantRecord.len;
+  }
+
+  protected:
+  /* Offset to MathGlyphAssembly table for this shape - from the beginning of
+     MathGlyphConstruction table. May be NULL. */
+  OffsetTo<MathGlyphAssembly>	  glyphAssembly;
+
+  /* MathGlyphVariantRecords for alternative variants of the glyphs. */
+  ArrayOf<MathGlyphVariantRecord> mathGlyphVariantRecord;
+
+  public:
+  DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord);
+};
+
+struct MathVariants
+{
+  inline bool sanitize_offsets (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    unsigned int count = vertGlyphCount + horizGlyphCount;
+    for (unsigned int i = 0; i < count; i++)
+      if (!glyphConstruction[i].sanitize (c, this)) return_trace (false);
+    return_trace (true);
+  }
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+		  vertGlyphCoverage.sanitize (c, this) &&
+		  horizGlyphCoverage.sanitize (c, this) &&
+		  c->check_array (glyphConstruction,
+				  glyphConstruction[0].static_size,
+				  vertGlyphCount + horizGlyphCount) &&
+		  sanitize_offsets (c));
+  }
+
+  inline hb_position_t get_min_connector_overlap (hb_direction_t direction,
+						  hb_font_t *font) const
+  { return font->em_scale_dir (minConnectorOverlap, direction); }
+
+  inline unsigned int get_glyph_variants (hb_codepoint_t glyph,
+					  hb_direction_t direction,
+					  hb_font_t *font,
+					  unsigned int start_offset,
+					  unsigned int *variants_count, /* IN/OUT */
+					  hb_ot_math_glyph_variant_t *variants /* OUT */) const
+  { return get_glyph_construction (glyph, direction, font)
+	   .get_variants (direction, font, start_offset, variants_count, variants); }
+
+  inline unsigned int get_glyph_parts (hb_codepoint_t glyph,
+				       hb_direction_t direction,
+				       hb_font_t *font,
+				       unsigned int start_offset,
+				       unsigned int *parts_count, /* IN/OUT */
+				       hb_ot_math_glyph_part_t *parts /* OUT */,
+				       hb_position_t *italics_correction /* OUT */) const
+  { return get_glyph_construction (glyph, direction, font)
+	   .get_assembly ()
+	   .get_parts (direction, font,
+		       start_offset, parts_count, parts,
+		       italics_correction); }
+
+  private:
+  inline const MathGlyphConstruction &
+		get_glyph_construction (hb_codepoint_t glyph,
+					hb_direction_t direction,
+					hb_font_t *font) const
+  {
+    bool vertical = HB_DIRECTION_IS_VERTICAL (direction);
+    unsigned int count = vertical ? vertGlyphCount : horizGlyphCount;
+    const OffsetTo<Coverage> &coverage = vertical ? vertGlyphCoverage
+						  : horizGlyphCoverage;
+
+    unsigned int index = (this+coverage).get_coverage (glyph);
+    if (unlikely (index >= count)) return Null(MathGlyphConstruction);
+
+    if (!vertical)
+      index += vertGlyphCount;
+
+    return this+glyphConstruction[index];
+  }
+
+  protected:
+  USHORT	     minConnectorOverlap; /* Minimum overlap of connecting
+					   * glyphs during glyph construction,
+					   * in design units. */
+  OffsetTo<Coverage> vertGlyphCoverage;   /* Offset to Coverage table -
+					   * from the beginning of MathVariants
+					   * table. */
+  OffsetTo<Coverage> horizGlyphCoverage;  /* Offset to Coverage table -
+					   * from the beginning of MathVariants
+					   * table. */
+  USHORT	     vertGlyphCount;      /* Number of glyphs for which
+					   * information is provided for
+					   * vertically growing variants. */
+  USHORT	     horizGlyphCount;     /* Number of glyphs for which
+					   * information is provided for
+					   * horizontally growing variants. */
+
+  /* Array of offsets to MathGlyphConstruction tables - from the beginning of
+     the MathVariants table, for shapes growing in vertical/horizontal
+     direction. */
+  OffsetTo<MathGlyphConstruction> glyphConstruction[VAR];
+
+  public:
+  DEFINE_SIZE_ARRAY (10, glyphConstruction);
+};
+
+
+/*
+ * MATH -- The MATH Table
+ */
+
+struct MATH
+{
+  static const hb_tag_t tableTag	= HB_OT_TAG_MATH;
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (version.sanitize (c) &&
+		  likely (version.major == 1) &&
+		  mathConstants.sanitize (c, this) &&
+		  mathGlyphInfo.sanitize (c, this) &&
+		  mathVariants.sanitize (c, this));
+  }
+
+  inline hb_position_t get_constant (hb_ot_math_constant_t  constant,
+				     hb_font_t		   *font) const
+  { return (this+mathConstants).get_value (constant, font); }
+
+  inline const MathGlyphInfo &get_math_glyph_info (void) const
+  { return this+mathGlyphInfo; }
+
+  inline const MathVariants &get_math_variants (void) const
+  { return this+mathVariants; }
+
+  protected:
+  FixedVersion<>version;		/* Version of the MATH table
+					 * initially set to 0x00010000u */
+  OffsetTo<MathConstants> mathConstants;/* MathConstants table */
+  OffsetTo<MathGlyphInfo> mathGlyphInfo;/* MathGlyphInfo table */
+  OffsetTo<MathVariants>  mathVariants;	/* MathVariants table */
+
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+} /* mathspace OT */
+
+
+#endif /* HB_OT_LAYOUT_MATH_TABLE_HH */
--- a/gfx/harfbuzz/src/hb-ot-layout-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-private.hh
@@ -119,16 +119,17 @@ hb_ot_layout_position_finish_offsets (hb
 /*
  * hb_ot_layout_t
  */
 
 namespace OT {
   struct GDEF;
   struct GSUB;
   struct GPOS;
+  struct MATH;
 }
 
 struct hb_ot_layout_lookup_accelerator_t
 {
   template <typename TLookup>
   inline void init (const TLookup &lookup)
   {
     digest.init ();
@@ -147,20 +148,22 @@ struct hb_ot_layout_lookup_accelerator_t
   hb_set_digest_t digest;
 };
 
 struct hb_ot_layout_t
 {
   hb_blob_t *gdef_blob;
   hb_blob_t *gsub_blob;
   hb_blob_t *gpos_blob;
+  hb_blob_t *math_blob;
 
   const struct OT::GDEF *gdef;
   const struct OT::GSUB *gsub;
   const struct OT::GPOS *gpos;
+  const struct OT::MATH *math;
 
   unsigned int gsub_lookup_count;
   unsigned int gpos_lookup_count;
 
   hb_ot_layout_lookup_accelerator_t *gsub_accels;
   hb_ot_layout_lookup_accelerator_t *gpos_accels;
 };
 
--- a/gfx/harfbuzz/src/hb-ot-layout.cc
+++ b/gfx/harfbuzz/src/hb-ot-layout.cc
@@ -30,16 +30,17 @@
 
 #include "hb-open-type-private.hh"
 #include "hb-ot-layout-private.hh"
 
 #include "hb-ot-layout-gdef-table.hh"
 #include "hb-ot-layout-gsub-table.hh"
 #include "hb-ot-layout-gpos-table.hh"
 #include "hb-ot-layout-jstf-table.hh"
+#include "hb-ot-layout-math-table.hh"
 
 #include "hb-ot-map-private.hh"
 
 #include <stdlib.h>
 #include <string.h>
 
 
 HB_SHAPER_DATA_ENSURE_DECLARE(ot, face)
@@ -55,16 +56,20 @@ hb_ot_layout_t *
   layout->gdef = OT::Sanitizer<OT::GDEF>::lock_instance (layout->gdef_blob);
 
   layout->gsub_blob = OT::Sanitizer<OT::GSUB>::sanitize (face->reference_table (HB_OT_TAG_GSUB));
   layout->gsub = OT::Sanitizer<OT::GSUB>::lock_instance (layout->gsub_blob);
 
   layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (HB_OT_TAG_GPOS));
   layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob);
 
+  /* The MATH table is rarely used, so only try and load it in _get_math. */
+  layout->math_blob = NULL;
+  layout->math = NULL;
+
   {
     /*
      * The ugly business of blacklisting individual fonts' tables happen here!
      * See this thread for why we finally had to bend in and do this:
      * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
      */
     unsigned int gdef_len = hb_blob_get_length (layout->gdef_blob);
     unsigned int gsub_len = hb_blob_get_length (layout->gsub_blob);
@@ -115,16 +120,24 @@ hb_ot_layout_t *
       /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427  himalaya.ttf from Windows 8.1 */
       || (192 == gdef_len && 7254 == gpos_len && 12690 == gsub_len)
       /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44  cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */
       /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371  cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */
       || (188 == gdef_len && 3852 == gpos_len && 248 == gsub_len)
       /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f  cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
       /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b  cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
       || (188 == gdef_len && 3426 == gpos_len && 264 == gsub_len)
+      /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
+      || (1046 == gdef_len && 17112 == gpos_len && 71788 == gsub_len)
+      /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
+      || (1058 == gdef_len && 17514 == gpos_len && 71794 == gsub_len)
+      /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */
+      || (1330 == gdef_len && 57938 == gpos_len && 109904 == gsub_len)
+      /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
+      || (1330 == gdef_len && 58972 == gpos_len && 109904 == gsub_len)
     )
     {
       /* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks
        * such as certain IPA symbols as glyph class 3. So do older versions of Microsoft Himalaya,
        * and the version of Cantarell shipped by Ubuntu 16.04.
        * Nuke the GDEF tables of these fonts to avoid unwanted width-zeroing.
        * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925
        *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
@@ -164,16 +177,17 @@ void
     layout->gpos_accels[i].fini ();
 
   free (layout->gsub_accels);
   free (layout->gpos_accels);
 
   hb_blob_destroy (layout->gdef_blob);
   hb_blob_destroy (layout->gsub_blob);
   hb_blob_destroy (layout->gpos_blob);
+  hb_blob_destroy (layout->math_blob);
 
   free (layout);
 }
 
 static inline const OT::GDEF&
 _get_gdef (hb_face_t *face)
 {
   if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GDEF);
@@ -186,16 +200,40 @@ static inline const OT::GSUB&
   return *hb_ot_layout_from_face (face)->gsub;
 }
 static inline const OT::GPOS&
 _get_gpos (hb_face_t *face)
 {
   if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GPOS);
   return *hb_ot_layout_from_face (face)->gpos;
 }
+static inline const OT::MATH&
+_get_math (hb_face_t *face)
+{
+  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::MATH);
+
+  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
+
+retry:
+  const OT::MATH *math = (const OT::MATH *) hb_atomic_ptr_get (&layout->math);
+
+  if (unlikely (!math))
+  {
+    hb_blob_t *blob = OT::Sanitizer<OT::MATH>::sanitize (face->reference_table (HB_OT_TAG_MATH));
+    math = OT::Sanitizer<OT::MATH>::lock_instance (blob);
+    if (!hb_atomic_ptr_cmpexch (&layout->math, NULL, math))
+    {
+      hb_blob_destroy (blob);
+      goto retry;
+    }
+    layout->math_blob = blob;
+  }
+
+  return *math;
+}
 
 
 /*
  * GDEF
  */
 
 hb_bool_t
 hb_ot_layout_has_glyph_classes (hb_face_t *face)
@@ -1177,8 +1215,226 @@ void hb_ot_map_t::position (const hb_ot_
 
 HB_INTERNAL void
 hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
 				const OT::SubstLookup &lookup,
 				const hb_ot_layout_lookup_accelerator_t &accel)
 {
   apply_string<GSUBProxy> (c, lookup, accel);
 }
+
+
+/*
+ * MATH
+ */
+/* TODO Move this to hb-ot-math.cc and separate it from hb_ot_layout_t. */
+
+/**
+ * hb_ot_math_has_data:
+ * @face: #hb_face_t to test
+ *
+ * This function allows to verify the presence of an OpenType MATH table on the
+ * face. If so, such a table will be loaded into memory and sanitized. You can
+ * then safely call other functions for math layout and shaping.
+ *
+ * Return value: #TRUE if face has a MATH table and #FALSE otherwise
+ *
+ * Since: 1.3.3
+ **/
+hb_bool_t
+hb_ot_math_has_data (hb_face_t *face)
+{
+  return &_get_math (face) != &OT::Null(OT::MATH);
+}
+
+/**
+ * hb_ot_math_get_constant:
+ * @font: #hb_font_t from which to retrieve the value
+ * @constant: #hb_ot_math_constant_t the constant to retrieve
+ *
+ * This function returns the requested math constants as a #hb_position_t.
+ * If the request constant is HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN,
+ * HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or
+ * HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN then the return value is
+ * actually an integer between 0 and 100 representing that percentage.
+ *
+ * Return value: the requested constant or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_constant (hb_font_t *font,
+			 hb_ot_math_constant_t constant)
+{
+  const OT::MATH &math = _get_math (font->face);
+  return math.get_constant(constant, font);
+}
+
+/**
+ * hb_ot_math_get_glyph_italics_correction:
+ * @font: #hb_font_t from which to retrieve the value
+ * @glyph: glyph index from which to retrieve the value
+ *
+ * Return value: the italics correction of the glyph or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_glyph_italics_correction (hb_font_t *font,
+					 hb_codepoint_t glyph)
+{
+  const OT::MATH &math = _get_math (font->face);
+  return math.get_math_glyph_info().get_italics_correction (glyph, font);
+}
+
+/**
+ * hb_ot_math_get_glyph_top_accent_attachment:
+ * @font: #hb_font_t from which to retrieve the value
+ * @glyph: glyph index from which to retrieve the value
+ *
+ * Return value: the top accent attachment of the glyph or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
+					    hb_codepoint_t glyph)
+{
+  const OT::MATH &math = _get_math (font->face);
+  return math.get_math_glyph_info().get_top_accent_attachment (glyph, font);
+}
+
+/**
+ * hb_ot_math_is_glyph_extended_shape:
+ * @font: a #hb_font_t to test
+ * @glyph: a glyph index to test
+ *
+ * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise
+ *
+ * Since: 1.3.3
+ **/
+hb_bool_t
+hb_ot_math_is_glyph_extended_shape (hb_face_t *face,
+				    hb_codepoint_t glyph)
+{
+  const OT::MATH &math = _get_math (face);
+  return math.get_math_glyph_info().is_extended_shape (glyph);
+}
+
+/**
+ * hb_ot_math_get_glyph_kerning:
+ * @font: #hb_font_t from which to retrieve the value
+ * @glyph: glyph index from which to retrieve the value
+ * @kern: the #hb_ot_math_kern_t from which to retrieve the value
+ * @correction_height: the correction height to use to determine the kerning.
+ *
+ * This function tries to retrieve the MathKern table for the specified font,
+ * glyph and #hb_ot_math_kern_t. Then it browses the list of heights from the
+ * MathKern table to find one value that is greater or equal to specified
+ * correction_height. If one is found the corresponding value from the list of
+ * kerns is returned and otherwise the last kern value is returned.
+ *
+ * Return value: requested kerning or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_glyph_kerning (hb_font_t *font,
+			      hb_codepoint_t glyph,
+			      hb_ot_math_kern_t kern,
+			      hb_position_t correction_height)
+{
+  const OT::MATH &math = _get_math (font->face);
+  return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font);
+}
+
+/**
+ * hb_ot_math_get_glyph_variants:
+ * @font: #hb_font_t from which to retrieve the values
+ * @glyph: index of the glyph to stretch
+ * @direction: direction of the stretching
+ * @start_offset: offset of the first variant to retrieve
+ * @variants_count: maximum number of variants to retrieve after start_offset
+ * (IN) and actual number of variants retrieved (OUT)
+ * @variants: array of size at least @variants_count to store the result
+ *
+ * This function tries to retrieve the MathGlyphConstruction for the specified
+ * font, glyph and direction. Note that only the value of
+ * #HB_DIRECTION_IS_HORIZONTAL is considered. It provides the corresponding list
+ * of size variants as an array of hb_ot_math_glyph_variant_t structs.
+ *
+ * Return value: the total number of size variants available or 0
+ *
+ * Since: 1.3.3
+ **/
+unsigned int
+hb_ot_math_get_glyph_variants (hb_font_t *font,
+			       hb_codepoint_t glyph,
+			       hb_direction_t direction,
+			       unsigned int start_offset,
+			       unsigned int *variants_count, /* IN/OUT */
+			       hb_ot_math_glyph_variant_t *variants /* OUT */)
+{
+  const OT::MATH &math = _get_math (font->face);
+  return math.get_math_variants().get_glyph_variants (glyph, direction, font,
+						      start_offset,
+						      variants_count,
+						      variants);
+}
+
+/**
+ * hb_ot_math_get_min_connector_overlap:
+ * @font: #hb_font_t from which to retrieve the value
+ * @direction: direction of the stretching
+ *
+ * This function tries to retrieve the MathVariants table for the specified
+ * font and returns the minimum overlap of connecting glyphs to draw a glyph
+ * assembly in the specified direction. Note that only the value of
+ * #HB_DIRECTION_IS_HORIZONTAL is considered.
+ *
+ * Return value: requested min connector overlap or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_min_connector_overlap (hb_font_t *font,
+				      hb_direction_t direction)
+{
+  const OT::MATH &math = _get_math (font->face);
+  return math.get_math_variants().get_min_connector_overlap (direction, font);
+}
+
+/**
+ * hb_ot_math_get_glyph_assembly:
+ * @font: #hb_font_t from which to retrieve the values
+ * @glyph: index of the glyph to stretch
+ * @direction: direction of the stretching
+ * @start_offset: offset of the first glyph part to retrieve
+ * @parts_count: maximum number of glyph parts to retrieve after start_offset
+ * (IN) and actual number of parts retrieved (OUT)
+ * @parts: array of size at least @parts_count to store the result
+ * @italics_correction: italic correction of the glyph assembly
+ *
+ * This function tries to retrieve the GlyphAssembly for the specified font,
+ * glyph and direction. Note that only the value of #HB_DIRECTION_IS_HORIZONTAL
+ * is considered. It provides the information necessary to draw the glyph
+ * assembly as an array of #hb_ot_math_glyph_part_t.
+ *
+ * Return value: the total number of parts in the glyph assembly
+ *
+ * Since: 1.3.3
+ **/
+unsigned int
+hb_ot_math_get_glyph_assembly (hb_font_t *font,
+			       hb_codepoint_t glyph,
+			       hb_direction_t direction,
+			       unsigned int start_offset,
+			       unsigned int *parts_count, /* IN/OUT */
+			       hb_ot_math_glyph_part_t *parts, /* OUT */
+			       hb_position_t *italics_correction /* OUT */)
+{
+  const OT::MATH &math = _get_math (font->face);
+  return math.get_math_variants().get_glyph_parts (glyph, direction, font,
+						   start_offset,
+						   parts_count,
+						   parts,
+						   italics_correction);
+}
new file mode 100644
--- /dev/null
+++ b/gfx/harfbuzz/src/hb-ot-math.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright © 2016  Igalia S.L.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Igalia Author(s): Frédéric Wang
+ */
+
+#ifndef HB_OT_H_IN
+#error "Include <hb-ot.h> instead."
+#endif
+
+#ifndef HB_OT_MATH_H
+#define HB_OT_MATH_H
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+
+
+/*
+ * MATH
+ */
+
+#define HB_OT_TAG_MATH HB_TAG('M','A','T','H')
+
+/* Use with hb_buffer_set_script() for math shaping. */
+#define HB_OT_MATH_SCRIPT HB_TAG('m','a','t','h')
+
+/* Types */
+
+/**
+ * hb_ot_math_constant_t:
+ *
+ * Since: 1.3.3
+ */
+typedef enum {
+  HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN = 0,
+  HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN = 1,
+  HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT = 2,
+  HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT = 3,
+  HB_OT_MATH_CONSTANT_MATH_LEADING = 4,
+  HB_OT_MATH_CONSTANT_AXIS_HEIGHT = 5,
+  HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT = 6,
+  HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT = 7,
+  HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN = 8,
+  HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX = 9,
+  HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN = 10,
+  HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP = 11,
+  HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED = 12,
+  HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN = 13,
+  HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX = 14,
+  HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN = 15,
+  HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT = 16,
+  HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT = 17,
+  HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN = 18,
+  HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN = 19,
+  HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN = 20,
+  HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN = 21,
+  HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP = 22,
+  HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP = 23,
+  HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN = 24,
+  HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN = 25,
+  HB_OT_MATH_CONSTANT_STACK_GAP_MIN = 26,
+  HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN = 27,
+  HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP = 28,
+  HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN = 29,
+  HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN = 30,
+  HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN = 31,
+  HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP = 32,
+  HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP = 33,
+  HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN = 34,
+  HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN = 35,
+  HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN = 36,
+  HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN = 37,
+  HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS = 38,
+  HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN = 39,
+  HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN = 40,
+  HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP = 41,
+  HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP = 42,
+  HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP = 43,
+  HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS = 44,
+  HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER = 45,
+  HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP = 46,
+  HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS = 47,
+  HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER = 48,
+  HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP = 49,
+  HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP = 50,
+  HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS = 51,
+  HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER = 52,
+  HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE = 53,
+  HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE = 54,
+  HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT = 55
+} hb_ot_math_constant_t;
+
+/**
+ * hb_ot_math_kern_t:
+ *
+ * Since: 1.3.3
+ */
+typedef enum {
+  HB_OT_MATH_KERN_TOP_RIGHT = 0,
+  HB_OT_MATH_KERN_TOP_LEFT = 1,
+  HB_OT_MATH_KERN_BOTTOM_RIGHT = 2,
+  HB_OT_MATH_KERN_BOTTOM_LEFT = 3
+} hb_ot_math_kern_t;
+
+/**
+ * hb_ot_math_glyph_variant_t:
+ *
+ * Since: 1.3.3
+ */
+typedef struct hb_ot_math_glyph_variant_t {
+  hb_codepoint_t glyph;
+  hb_position_t advance;
+} hb_ot_math_glyph_variant_t;
+
+/**
+ * hb_ot_math_glyph_part_flags_t:
+ *
+ * Since: 1.3.3
+ */
+typedef enum { /*< flags >*/
+  HB_MATH_GLYPH_PART_FLAG_EXTENDER	= 0x00000001u  /* Extender glyph */
+} hb_ot_math_glyph_part_flags_t;
+
+/**
+ * hb_ot_math_glyph_part_t:
+ *
+ * Since: 1.3.3
+ */
+typedef struct hb_ot_math_glyph_part_t {
+  hb_codepoint_t glyph;
+  hb_position_t start_connector_length;
+  hb_position_t end_connector_length;
+  hb_position_t full_advance;
+  hb_ot_math_glyph_part_flags_t flags;
+} hb_ot_math_glyph_part_t;
+
+/* Methods */
+
+HB_EXTERN hb_bool_t
+hb_ot_math_has_data (hb_face_t *face);
+
+HB_EXTERN hb_position_t
+hb_ot_math_get_constant (hb_font_t *font,
+			 hb_ot_math_constant_t constant);
+
+HB_EXTERN hb_position_t
+hb_ot_math_get_glyph_italics_correction (hb_font_t *font,
+					 hb_codepoint_t glyph);
+
+HB_EXTERN hb_position_t
+hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
+					    hb_codepoint_t glyph);
+
+HB_EXTERN hb_bool_t
+hb_ot_math_is_glyph_extended_shape (hb_face_t *face,
+				    hb_codepoint_t glyph);
+
+HB_EXTERN hb_position_t
+hb_ot_math_get_glyph_kerning (hb_font_t *font,
+			      hb_codepoint_t glyph,
+			      hb_ot_math_kern_t kern,
+			      hb_position_t correction_height);
+
+HB_EXTERN unsigned int
+hb_ot_math_get_glyph_variants (hb_font_t *font,
+			       hb_codepoint_t glyph,
+			       hb_direction_t direction,
+			       unsigned int start_offset,
+			       unsigned int *variants_count, /* IN/OUT */
+			       hb_ot_math_glyph_variant_t *variants /* OUT */);
+
+HB_EXTERN hb_position_t
+hb_ot_math_get_min_connector_overlap (hb_font_t *font,
+				      hb_direction_t direction);
+
+HB_EXTERN unsigned int
+hb_ot_math_get_glyph_assembly (hb_font_t *font,
+			       hb_codepoint_t glyph,
+			       hb_direction_t direction,
+			       unsigned int start_offset,
+			       unsigned int *parts_count, /* IN/OUT */
+			       hb_ot_math_glyph_part_t *parts, /* OUT */
+			       hb_position_t *italics_correction /* OUT */);
+
+
+HB_END_DECLS
+
+#endif /* HB_OT_MATH_H */
--- a/gfx/harfbuzz/src/hb-ot.h
+++ b/gfx/harfbuzz/src/hb-ot.h
@@ -27,16 +27,17 @@
 #ifndef HB_OT_H
 #define HB_OT_H
 #define HB_OT_H_IN
 
 #include "hb.h"
 
 #include "hb-ot-font.h"
 #include "hb-ot-layout.h"
+#include "hb-ot-math.h"
 #include "hb-ot-tag.h"
 #include "hb-ot-shape.h"
 
 HB_BEGIN_DECLS
 
 HB_END_DECLS
 
 #undef HB_OT_H_IN
--- a/gfx/harfbuzz/src/hb-shape-plan.cc
+++ b/gfx/harfbuzz/src/hb-shape-plan.cc
@@ -284,19 +284,20 @@ hb_shape_plan_get_user_data (hb_shape_pl
 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)
 {
   DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
-		  "num_features=%d shaper_func=%p",
+		  "num_features=%d shaper_func=%p, shaper_name=%s",
 		  num_features,
-		  shape_plan->shaper_func);
+		  shape_plan->shaper_func,
+		  shape_plan->shaper_name);
 
   if (unlikely (!buffer->len))
     return true;
 
   assert (!hb_object_is_inert (buffer));
   assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE);
 
   if (unlikely (hb_object_is_inert (shape_plan)))
--- a/gfx/harfbuzz/src/hb-version.h
+++ b/gfx/harfbuzz/src/hb-version.h
@@ -33,19 +33,19 @@
 
 #include "hb-common.h"
 
 HB_BEGIN_DECLS
 
 
 #define HB_VERSION_MAJOR 1
 #define HB_VERSION_MINOR 3
-#define HB_VERSION_MICRO 0
+#define HB_VERSION_MICRO 3
 
-#define HB_VERSION_STRING "1.3.0"
+#define HB_VERSION_STRING "1.3.3"
 
 #define HB_VERSION_ATLEAST(major,minor,micro) \
 	((major)*10000+(minor)*100+(micro) <= \
 	 HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO)
 
 
 HB_EXTERN void
 hb_version (unsigned int *major,
--- a/gfx/harfbuzz/src/moz.build
+++ b/gfx/harfbuzz/src/moz.build
@@ -8,16 +8,17 @@ EXPORTS.harfbuzz += [
     'hb-blob.h',
     'hb-buffer.h',
     'hb-common.h',
     'hb-deprecated.h',
     'hb-face.h',
     'hb-font.h',
     'hb-ot-font.h',
     'hb-ot-layout.h',
+    'hb-ot-math.h',
     'hb-ot-shape.h',
     'hb-ot-tag.h',
     'hb-ot.h',
     'hb-set.h',
     'hb-shape-plan.h',
     'hb-shape.h',
     'hb-unicode.h',
     'hb-version.h',