merge in oc-release history after reset to master
diff --git a/Android.bp b/Android.bp
index ff6b430..f048737 100644
--- a/Android.bp
+++ b/Android.bp
@@ -75,7 +75,6 @@
         "src/hb-ot-font.cc",
         "src/hb-ot-layout.cc",
         "src/hb-ot-map.cc",
-        "src/hb-ot-math.cc",
         "src/hb-ot-shape.cc",
         "src/hb-ot-shape-complex-arabic.cc",
         "src/hb-ot-shape-complex-default.cc",
@@ -90,7 +89,6 @@
         "src/hb-ot-shape-complex-use-table.cc",
         "src/hb-ot-shape-normalize.cc",
         "src/hb-ot-shape-fallback.cc",
-        "src/hb-ot-var.cc",
 
         "src/hb-icu.cc",
     ],
diff --git a/Makefile.am b/Makefile.am
index 8dc8a4b..d56a151 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,6 +9,7 @@
 EXTRA_DIST = \
 	autogen.sh \
 	harfbuzz.doap \
+	Android.mk \
 	README.python \
 	BUILD.md \
 	$(NULL)
diff --git a/NEWS b/NEWS
index 43a3bac..ae0926e 100644
--- a/NEWS
+++ b/NEWS
@@ -1,110 +1,3 @@
-Overview of changes leading to 1.4.2
-Monday, January 23, 2017
-====================================
-
-- Implement OpenType Font Variation tables avar/fvar/HVAR/VVAR.
-- hb-shape and hb-view now accept --variations.
-- New API:
-
-hb_variation_t
-hb_variation_from_string()
-hb_variation_to_string()
-
-hb_font_set_variations()
-hb_font_set_var_coords_design()
-hb_font_get_var_coords_normalized()
-
-hb-ot-var.h:
-hb_ot_var_axis_t
-hb_ot_var_has_data()
-hb_ot_var_get_axis_count()
-hb_ot_var_get_axes()
-hb_ot_var_find_axis()
-hb_ot_var_normalize_variations()
-hb_ot_var_normalize_coords()
-
-- MVAR to be implemented later.  Access to named instances to be
-  implemented later as well.
-
-- Misc fixes.
-
-
-Overview of changes leading to 1.4.1
-Thursday, January 5, 2017
-====================================
-
-- Always build and use UCDN for Unicode data by default.
-  Reduces dependence on version of Unicode data in glib,
-  specially in the Windows bundles we are shipping, which
-  have very old glib.
-
-
-Overview of changes leading to 1.4.0
-Thursday, January 5, 2017
-====================================
-
-- Merged "OpenType GX" branch which adds core of support for
-  OpenType 1.8 Font Variations.  To that extent, the relevant
-  new API is:
-
-New API:
-hb_font_set_var_coords_normalized()
-
-  with supporting API:
-
-New API:
-HB_OT_LAYOUT_NO_VARIATIONS_INDEX
-hb_ot_layout_table_find_feature_variations()
-hb_ot_layout_feature_with_variations_get_lookups()
-hb_shape_plan_create2()
-hb_shape_plan_create_cached2()
-
-  Currently variations in GSUB/GPOS/GDEF are fully supported,
-  and no other tables are supported.  In particular, fvar/avar
-  are NOT supported, hence the hb_font_set_var_coords_normalized()
-  taking normalized coordinates.  API to take design coordinates
-  will be added in the future.
-
-  HVAR/VVAR/MVAR support will also be added to hb-ot-font in the
-  future.
-
-- Fix regression in GDEF glyph class processing.
-- Add decompositions for Chakma, Limbu, and Balinese in USE shaper.
-- Misc fixes.
-
-
-Overview of changes leading to 1.3.4
-Monday, December 5, 2016
-====================================
-
-- Fix vertical glyph origin in hb-ot-font.
-- Implement CBDT/CBLC color font glyph extents in hb-ot-font.
-
-
-Overview of changes leading to 1.3.3
-Wednesday, September 28, 2016
-====================================
-
-- Implement parsing of OpenType MATH table.
-New API:
-HB_OT_TAG_MATH
-HB_OT_MATH_SCRIPT
-hb_ot_math_constant_t
-hb_ot_math_kern_t
-hb_ot_math_glyph_variant_t
-hb_ot_math_glyph_part_flags_t
-hb_ot_math_glyph_part_t
-hb_ot_math_has_data
-hb_ot_math_get_constant
-hb_ot_math_get_glyph_italics_correction
-hb_ot_math_get_glyph_top_accent_attachment
-hb_ot_math_get_glyph_kerning
-hb_ot_math_is_glyph_extended_shape
-hb_ot_math_get_glyph_variants
-hb_ot_math_get_min_connector_overlap
-hb_ot_math_get_glyph_assembly
-
-
 Overview of changes leading to 1.3.2
 Wednesday, September 27, 2016
 ====================================
diff --git a/README.version b/README.version
index 93200ee..126e130 100644
--- a/README.version
+++ b/README.version
@@ -1,3 +1,3 @@
-URL: http://www.freedesktop.org/software/harfbuzz/release/harfbuzz-1.4.2.tar.bz2
-Version: 1.4.2
+URL: http://www.freedesktop.org/software/harfbuzz/release/harfbuzz-1.3.2.tar.bz2
+Version: 1.3.2
 BugComponent: 25699
diff --git a/appveyor.yml b/appveyor.yml
index 2a0e7c5..4677a27 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -4,19 +4,15 @@
   matrix:
     - compiler: msvc
       ARCH: amd64
-      VCPKG_ARCH: x64-windows
       CFG: release
     - compiler: msvc
       ARCH: x86
-      VCPKG_ARCH: x86-windows
       CFG: release
     - compiler: msvc
       ARCH: amd64
-      VCPKG_ARCH: x64-windows
       CFG: debug
     - compiler: msvc
       ARCH: x86
-      VCPKG_ARCH: x86-windows
       CFG: debug
 
     - compiler: msys2
@@ -31,19 +27,11 @@
 install:
   - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-ragel"
 
-  - 'if "%compiler%"=="msvc" call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %ARCH%'
-  - 'if "%compiler%"=="msvc" git clone https://github.com/Microsoft/vcpkg'
-  - 'if "%compiler%"=="msvc" cd vcpkg'
-  - 'if "%compiler%"=="msvc" powershell -exec bypass scripts\bootstrap.ps1'
-  - 'if "%compiler%"=="msvc" vcpkg install freetype:%VCPKG_ARCH%'
-  - 'if "%compiler%"=="msvc" copy installed\%VCPKG_ARCH%\debug\lib\freetyped.lib installed\%VCPKG_ARCH%\lib'
-  - 'if "%compiler%"=="msvc" cd ..'
-
 build_script:
+  - 'if "%compiler%"=="msvc" call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %ARCH%'
   - 'if "%compiler%"=="msvc" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh; make distdir"'
   - 'if "%compiler%"=="msvc" cd harfbuzz-*\win32'
-  - 'if "%compiler%"=="msvc" nmake /f Makefile.vc CFG=%CFG% UNISCRIBE=1 DIRECTWRITE=1 FREETYPE=1 FREETYPE_DIR=..\..\vcpkg\installed\%VCPKG_ARCH%\include ADDITIONAL_LIB_DIR=..\..\vcpkg\installed\%VCPKG_ARCH%\lib'
-  - 'if "%compiler%"=="msvc" nmake /f Makefile.vc CFG=%CFG% UNISCRIBE=1 DIRECTWRITE=1 FREETYPE=1 install'
+  - 'if "%compiler%"=="msvc" nmake /f Makefile.vc CFG=%CFG% DIRECTWRITE=1'
 
   - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-$MSYS2_ARCH-{freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config}"'
   - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --build=$MINGW_CHOST --host=$MINGW_CHOST --prefix=$MINGW_PREFIX; make; make check"'
diff --git a/configure.ac b/configure.ac
index 31fa97d..57e9e6d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [1.4.2],
+        [1.3.2],
         [https://github.com/behdad/harfbuzz/issues/new],
         [harfbuzz],
         [http://harfbuzz.org/])
@@ -19,11 +19,9 @@
 LT_INIT([disable-static])
 
 # Check for programs
-AC_USE_SYSTEM_EXTENSIONS
 AC_PROG_CC
 AM_PROG_CC_C_O
 AC_PROG_CXX
-AC_SYS_LARGEFILE
 PKG_PROG_PKG_CONFIG([0.20])
 AM_MISSING_PROG([RAGEL], [ragel])
 AM_MISSING_PROG([GIT], [git])
@@ -147,7 +145,7 @@
 			[Use glib @<:@default=auto@:>@])],,
 	[with_glib=auto])
 have_glib=false
-GLIB_DEPS="glib-2.0 >= 2.19.1"
+GLIB_DEPS="glib-2.0 >= 2.16"
 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, :)
@@ -289,13 +287,9 @@
 
 dnl ===========================================================================
 
-AC_ARG_WITH(ucdn,
-	[AS_HELP_STRING([--with-ucdn=@<:@yes/no@:>@],
-			[Use builtin UCDN library @<:@default=yes@:>@])],,
-	[with_ucdn=yes])
-have_ucdn=false
-if test "x$with_ucdn" = "xyes"; then
-	have_ucdn=true
+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])
@@ -350,10 +344,6 @@
 fi
 if $have_freetype; then
 	AC_DEFINE(HAVE_FREETYPE, 1, [Have FreeType 2 library])
-	save_libs=$LIBS
-	LIBS="$LIBS $FREETYPE_LIBS"
-	AC_CHECK_FUNCS(FT_Get_Var_Blend_Coordinates)
-	LIBS=$save_libs
 fi
 AM_CONDITIONAL(HAVE_FREETYPE, $have_freetype)
 
@@ -421,8 +411,7 @@
 	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>])
+			AC_CHECK_TYPE(CTFontRef, have_coretext=true,, [#include <CoreText/CoreText.h>])
 		fi
 
 		if $have_coretext; then
@@ -505,9 +494,9 @@
 Build configuration:
 
 Unicode callbacks (you want at least one):
-	Builtin (UCDN):		${have_ucdn}
 	Glib:			${have_glib}
 	ICU:			${have_icu}
+	UCDN:			${have_ucdn}
 
 Font callbacks (the more the better):
 	FreeType:		${have_freetype}
diff --git a/docs/harfbuzz-docs.xml b/docs/harfbuzz-docs.xml
index 00113e9..2c43c46 100644
--- a/docs/harfbuzz-docs.xml
+++ b/docs/harfbuzz-docs.xml
@@ -80,7 +80,6 @@
         <xi:include href="xml/hb-ot-tag.xml"/>
         <xi:include href="xml/hb-ot-font.xml"/>
         <xi:include href="xml/hb-ot-shape.xml"/>
-        <xi:include href="xml/hb-ot-math.xml"/>
 
         <xi:include href="xml/hb-shape-plan.xml"/>
 
@@ -176,14 +175,6 @@
         <title>Index of new symbols in 1.1.3</title>
         <xi:include href="xml/api-index-1.1.3.xml"><xi:fallback /></xi:include>
       </index>
-      <index id="api-index-1-2-3" role="1.2.3">
-        <title>Index of new symbols in 1.2.3</title>
-        <xi:include href="xml/api-index-1.2.3.xml"><xi:fallback /></xi:include>
-      </index>
-      <index id="api-index-1-3-3" role="1.3.3">
-        <title>Index of new symbols in 1.3.3</title>
-        <xi:include href="xml/api-index-1.3.3.xml"><xi:fallback /></xi:include>
-      </index>
       <index id="deprecated-api-index" role="deprecated">
         <title>Index of deprecated API</title>
         <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index a91eb4c..e0dc23d 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -144,8 +144,6 @@
 HB_BUFFER_FLAGS_DEFAULT
 HB_BUFFER_SERIALIZE_FLAGS_DEFAULT
 HB_SCRIPT_CANADIAN_ABORIGINAL
-hb_font_funcs_set_glyph_func
-hb_font_get_glyph_func_t
 </SECTION>
 
 <SECTION>
@@ -195,6 +193,7 @@
 hb_font_funcs_set_glyph_contour_point_func
 hb_font_funcs_set_glyph_extents_func
 hb_font_funcs_set_glyph_from_name_func
+hb_font_funcs_set_glyph_func
 hb_font_funcs_set_glyph_h_advance_func
 hb_font_funcs_set_glyph_h_kerning_func
 hb_font_funcs_set_glyph_h_origin_func
@@ -202,9 +201,7 @@
 hb_font_funcs_set_glyph_v_advance_func
 hb_font_funcs_set_glyph_v_kerning_func
 hb_font_funcs_set_glyph_v_origin_func
-hb_font_funcs_set_nominal_glyph_func
 hb_font_funcs_set_user_data
-hb_font_funcs_set_variation_glyph_func
 hb_font_funcs_t
 hb_font_get_empty
 hb_font_get_face
@@ -219,6 +216,7 @@
 hb_font_get_glyph_extents_func_t
 hb_font_get_glyph_from_name
 hb_font_get_glyph_from_name_func_t
+hb_font_get_glyph_func_t
 hb_font_get_glyph_h_advance
 hb_font_get_glyph_h_advance_func_t
 hb_font_get_glyph_h_kerning
@@ -237,15 +235,10 @@
 hb_font_get_glyph_v_kerning_func_t
 hb_font_get_glyph_v_origin
 hb_font_get_glyph_v_origin_func_t
-hb_font_get_nominal_glyph
-hb_font_get_nominal_glyph_func_t
 hb_font_get_parent
 hb_font_get_ppem
 hb_font_get_scale
 hb_font_get_user_data
-hb_font_get_variation_glyph
-hb_font_get_variation_glyph_func_t
-hb_font_get_var_coords_normalized
 hb_font_glyph_from_string
 hb_font_glyph_to_string
 hb_font_is_immutable
@@ -253,16 +246,9 @@
 hb_font_reference
 hb_font_set_funcs
 hb_font_set_funcs_data
-hb_font_set_parent
 hb_font_set_ppem
 hb_font_set_scale
 hb_font_set_user_data
-hb_variation_t
-hb_variation_from_string
-hb_variation_to_string
-hb_font_set_variations
-hb_font_set_var_coords_design
-hb_font_set_var_coords_normalized
 hb_font_subtract_glyph_origin_for_direction
 hb_font_t
 hb_reference_table_func_t
@@ -274,6 +260,7 @@
 hb_font_get_font_v_extents_func_t
 hb_font_get_h_extents
 hb_font_get_v_extents
+hb_font_set_parent
 </SECTION>
 
 <SECTION>
@@ -311,9 +298,6 @@
 HB_GOBJECT_TYPE_FONT_FUNCS
 HB_GOBJECT_TYPE_MEMORY_MODE
 HB_GOBJECT_TYPE_OT_LAYOUT_GLYPH_CLASS
-HB_GOBJECT_TYPE_OT_MATH_CONSTANT
-HB_GOBJECT_TYPE_OT_MATH_GLYPH_PART_FLAGS
-HB_GOBJECT_TYPE_OT_MATH_KERN
 HB_GOBJECT_TYPE_SCRIPT
 HB_GOBJECT_TYPE_SHAPE_PLAN
 HB_GOBJECT_TYPE_UNICODE_COMBINING_CLASS
@@ -338,9 +322,6 @@
 hb_gobject_font_get_type
 hb_gobject_memory_mode_get_type
 hb_gobject_ot_layout_glyph_class_get_type
-hb_gobject_ot_math_constant_get_type
-hb_gobject_ot_math_glyph_part_flags_get_type
-hb_gobject_ot_math_kern_get_type
 hb_gobject_script_get_type
 hb_gobject_shape_plan_get_type
 hb_gobject_unicode_combining_class_get_type
@@ -397,14 +378,12 @@
 HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX
 HB_OT_LAYOUT_NO_FEATURE_INDEX
 HB_OT_LAYOUT_NO_SCRIPT_INDEX
-HB_OT_LAYOUT_NO_VARIATIONS_INDEX
 HB_OT_TAG_GDEF
 HB_OT_TAG_GPOS
 HB_OT_TAG_GSUB
 HB_OT_TAG_JSTF
 hb_ot_layout_collect_lookups
 hb_ot_layout_feature_get_lookups
-hb_ot_layout_feature_with_variations_get_lookups
 hb_ot_layout_get_attach_points
 hb_ot_layout_get_glyph_class
 hb_ot_layout_get_glyphs_in_class
@@ -425,7 +404,6 @@
 hb_ot_layout_script_find_language
 hb_ot_layout_script_get_language_tags
 hb_ot_layout_table_choose_script
-hb_ot_layout_table_find_feature_variations
 hb_ot_layout_table_find_script
 hb_ot_layout_table_get_feature_tags
 hb_ot_layout_table_get_script_tags
@@ -439,43 +417,6 @@
 </SECTION>
 
 <SECTION>
-<FILE>hb-ot-var</FILE>
-HB_OT_TAG_VAR_AXIS_ITALIC
-HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE
-HB_OT_TAG_VAR_AXIS_SLANT
-HB_OT_TAG_VAR_AXIS_WEIGHT
-HB_OT_TAG_VAR_AXIS_WIDTH
-HB_OT_VAR_NO_AXIS_INDEX
-hb_ot_var_axis_t
-hb_ot_var_has_data
-hb_ot_var_find_axis
-hb_ot_var_get_axis_count
-hb_ot_var_get_axes
-hb_ot_var_normalize_variations
-hb_ot_var_normalize_coords
-</SECTION>
-
-<SECTION>
-<FILE>hb-ot-math</FILE>
-HB_OT_TAG_MATH
-HB_OT_MATH_SCRIPT
-hb_ot_math_constant_t
-hb_ot_math_kern_t
-hb_ot_math_glyph_variant_t
-hb_ot_math_glyph_part_flags_t
-hb_ot_math_glyph_part_t
-hb_ot_math_has_data
-hb_ot_math_get_constant
-hb_ot_math_get_glyph_italics_correction
-hb_ot_math_get_glyph_top_accent_attachment
-hb_ot_math_get_glyph_kerning
-hb_ot_math_is_glyph_extended_shape
-hb_ot_math_get_glyph_variants
-hb_ot_math_get_min_connector_overlap
-hb_ot_math_get_glyph_assembly
-</SECTION>
-
-<SECTION>
 <FILE>hb-ot-tag</FILE>
 HB_OT_TAG_DEFAULT_LANGUAGE
 HB_OT_TAG_DEFAULT_SCRIPT
@@ -519,8 +460,8 @@
 
 <SECTION>
 <FILE>hb-shape</FILE>
-hb_feature_t
 hb_feature_from_string
+hb_feature_t
 hb_feature_to_string
 hb_shape
 hb_shape_full
@@ -531,8 +472,6 @@
 <FILE>hb-shape-plan</FILE>
 hb_shape_plan_create
 hb_shape_plan_create_cached
-hb_shape_plan_create2
-hb_shape_plan_create_cached2
 hb_shape_plan_destroy
 hb_shape_plan_execute
 hb_shape_plan_get_empty
@@ -587,8 +526,6 @@
 <FILE>hb-uniscribe</FILE>
 hb_uniscribe_font_get_hfont
 hb_uniscribe_font_get_logfontw
-<SUBSECTION Private>
-hb_directwrite_shape_experimental_width
 </SECTION>
 
 <SECTION>
diff --git a/src/Makefile.am b/src/Makefile.am
index d7420a0..8cfe4ac 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -299,8 +299,6 @@
 test_buffer_serialize_CPPFLAGS = $(HBCFLAGS)
 test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS)
 
-check: harfbuzz.def # For check-defs.sh
-
 dist_check_SCRIPTS = \
 	check-c-linkage-decls.sh \
 	check-defs.sh \
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 8d7f1a0..ac80683 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -20,7 +20,6 @@
 	hb-object-private.hh \
 	hb-open-file-private.hh \
 	hb-open-type-private.hh \
-	hb-ot-cbdt-table.hh \
 	hb-ot-cmap-table.hh \
 	hb-ot-glyf-table.hh \
 	hb-ot-head-table.hh \
@@ -79,8 +78,6 @@
 	hb-ot-layout-private.hh \
 	hb-ot-map.cc \
 	hb-ot-map-private.hh \
-	hb-ot-math.cc \
-	hb-ot-math-table.hh \
 	hb-ot-shape.cc \
 	hb-ot-shape-complex-arabic.cc \
 	hb-ot-shape-complex-arabic-fallback.hh \
@@ -108,20 +105,14 @@
 	hb-ot-shape-fallback-private.hh \
 	hb-ot-shape-fallback.cc \
 	hb-ot-shape-private.hh \
-	hb-ot-var.cc \
-	hb-ot-var-avar-table.hh \
-	hb-ot-var-fvar-table.hh \
-	hb-ot-var-hvar-table.hh \
 	$(NULL)
 
 HB_OT_headers = \
 	hb-ot.h \
 	hb-ot-font.h \
 	hb-ot-layout.h \
-	hb-ot-math.h \
 	hb-ot-shape.h \
 	hb-ot-tag.h \
-	hb-ot-var.h \
 	$(NULL)
 
 # Optional Sources and Headers with external deps
diff --git a/src/check-symbols.sh b/src/check-symbols.sh
index ba09ba1..b2bf43f 100755
--- a/src/check-symbols.sh
+++ b/src/check-symbols.sh
@@ -19,8 +19,8 @@
 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\>\| ___gcov_flush\>\| llvm_\| _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\>\| llvm_' | cut -d' ' -f3`"
 
 	prefix=`basename "$so" | sed 's/libharfbuzz/hb/; s/-/_/g; s/[.].*//'`
 
diff --git a/src/hb-common.cc b/src/hb-common.cc
index 64e77d4..3564e43 100644
--- a/src/hb-common.cc
+++ b/src/hb-common.cc
@@ -605,347 +605,3 @@
 {
   return HB_VERSION_ATLEAST (major, minor, micro);
 }
-
-
-
-/* hb_feature_t and hb_variation_t */
-
-static bool
-parse_space (const char **pp, const char *end)
-{
-  while (*pp < end && ISSPACE (**pp))
-    (*pp)++;
-  return true;
-}
-
-static bool
-parse_char (const char **pp, const char *end, char c)
-{
-  parse_space (pp, end);
-
-  if (*pp == end || **pp != c)
-    return false;
-
-  (*pp)++;
-  return true;
-}
-
-static bool
-parse_uint (const char **pp, const char *end, unsigned int *pv)
-{
-  char buf[32];
-  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
-  strncpy (buf, *pp, len);
-  buf[len] = '\0';
-
-  char *p = buf;
-  char *pend = p;
-  unsigned int v;
-
-  /* Intentionally use strtol instead of strtoul, such that
-   * -1 turns into "big number"... */
-  errno = 0;
-  v = strtol (p, &pend, 0);
-  if (errno || p == pend)
-    return false;
-
-  *pv = v;
-  *pp += pend - p;
-  return true;
-}
-
-static bool
-parse_float (const char **pp, const char *end, float *pv)
-{
-  char buf[32];
-  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
-  strncpy (buf, *pp, len);
-  buf[len] = '\0';
-
-  char *p = buf;
-  char *pend = p;
-  float v;
-
-  errno = 0;
-  v = strtof (p, &pend);
-  if (errno || p == pend)
-    return false;
-
-  *pv = v;
-  *pp += pend - p;
-  return true;
-}
-
-static bool
-parse_bool (const char **pp, const char *end, unsigned int *pv)
-{
-  parse_space (pp, end);
-
-  const char *p = *pp;
-  while (*pp < end && ISALPHA(**pp))
-    (*pp)++;
-
-  /* CSS allows on/off as aliases 1/0. */
-  if (*pp - p == 2 || 0 == strncmp (p, "on", 2))
-    *pv = 1;
-  else if (*pp - p == 3 || 0 == strncmp (p, "off", 2))
-    *pv = 0;
-  else
-    return false;
-
-  return true;
-}
-
-/* hb_feature_t */
-
-static bool
-parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature)
-{
-  if (parse_char (pp, end, '-'))
-    feature->value = 0;
-  else {
-    parse_char (pp, end, '+');
-    feature->value = 1;
-  }
-
-  return true;
-}
-
-static bool
-parse_tag (const char **pp, const char *end, hb_tag_t *tag)
-{
-  parse_space (pp, end);
-
-  char quote = 0;
-
-  if (*pp < end && (**pp == '\'' || **pp == '"'))
-  {
-    quote = **pp;
-    (*pp)++;
-  }
-
-  const char *p = *pp;
-  while (*pp < end && ISALNUM(**pp))
-    (*pp)++;
-
-  if (p == *pp || *pp - p > 4)
-    return false;
-
-  *tag = hb_tag_from_string (p, *pp - p);
-
-  if (quote)
-  {
-    /* CSS expects exactly four bytes.  And we only allow quotations for
-     * CSS compatibility.  So, enforce the length. */
-     if (*pp - p != 4)
-       return false;
-    if (*pp == end || **pp != quote)
-      return false;
-    (*pp)++;
-  }
-
-  return true;
-}
-
-static bool
-parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
-{
-  parse_space (pp, end);
-
-  bool has_start;
-
-  feature->start = 0;
-  feature->end = (unsigned int) -1;
-
-  if (!parse_char (pp, end, '['))
-    return true;
-
-  has_start = parse_uint (pp, end, &feature->start);
-
-  if (parse_char (pp, end, ':')) {
-    parse_uint (pp, end, &feature->end);
-  } else {
-    if (has_start)
-      feature->end = feature->start + 1;
-  }
-
-  return parse_char (pp, end, ']');
-}
-
-static bool
-parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature)
-{
-  bool had_equal = parse_char (pp, end, '=');
-  bool had_value = parse_uint (pp, end, &feature->value) ||
-                   parse_bool (pp, end, &feature->value);
-  /* CSS doesn't use equal-sign between tag and value.
-   * If there was an equal-sign, then there *must* be a value.
-   * A value without an eqaul-sign is ok, but not required. */
-  return !had_equal || had_value;
-}
-
-static bool
-parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
-{
-  return parse_feature_value_prefix (pp, end, feature) &&
-	 parse_tag (pp, end, &feature->tag) &&
-	 parse_feature_indices (pp, end, feature) &&
-	 parse_feature_value_postfix (pp, end, feature) &&
-	 parse_space (pp, end) &&
-	 *pp == end;
-}
-
-/**
- * hb_feature_from_string:
- * @str: (array length=len) (element-type uint8_t): a string to parse
- * @len: length of @str, or -1 if string is %NULL terminated
- * @feature: (out): the #hb_feature_t to initialize with the parsed values
- *
- * Parses a string into a #hb_feature_t.
- *
- * TODO: document the syntax here.
- *
- * Return value:
- * %true if @str is successfully parsed, %false otherwise.
- *
- * Since: 0.9.5
- **/
-hb_bool_t
-hb_feature_from_string (const char *str, int len,
-			hb_feature_t *feature)
-{
-  hb_feature_t feat;
-
-  if (len < 0)
-    len = strlen (str);
-
-  if (likely (parse_one_feature (&str, str + len, &feat)))
-  {
-    if (feature)
-      *feature = feat;
-    return true;
-  }
-
-  if (feature)
-    memset (feature, 0, sizeof (*feature));
-  return false;
-}
-
-/**
- * hb_feature_to_string:
- * @feature: an #hb_feature_t to convert
- * @buf: (array length=size) (out): output string
- * @size: the allocated size of @buf
- *
- * Converts a #hb_feature_t into a %NULL-terminated string in the format
- * understood by hb_feature_from_string(). The client in responsible for
- * allocating big enough size for @buf, 128 bytes is more than enough.
- *
- * Since: 0.9.5
- **/
-void
-hb_feature_to_string (hb_feature_t *feature,
-		      char *buf, unsigned int size)
-{
-  if (unlikely (!size)) return;
-
-  char s[128];
-  unsigned int len = 0;
-  if (feature->value == 0)
-    s[len++] = '-';
-  hb_tag_to_string (feature->tag, s + len);
-  len += 4;
-  while (len && s[len - 1] == ' ')
-    len--;
-  if (feature->start != 0 || feature->end != (unsigned int) -1)
-  {
-    s[len++] = '[';
-    if (feature->start)
-      len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start));
-    if (feature->end != feature->start + 1) {
-      s[len++] = ':';
-      if (feature->end != (unsigned int) -1)
-	len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end));
-    }
-    s[len++] = ']';
-  }
-  if (feature->value > 1)
-  {
-    s[len++] = '=';
-    len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
-  }
-  assert (len < ARRAY_LENGTH (s));
-  len = MIN (len, size - 1);
-  memcpy (buf, s, len);
-  buf[len] = '\0';
-}
-
-/* hb_variation_t */
-
-static bool
-parse_variation_value (const char **pp, const char *end, hb_variation_t *variation)
-{
-  parse_char (pp, end, '='); /* Optional. */
-  return parse_float (pp, end, &variation->value);
-}
-
-static bool
-parse_one_variation (const char **pp, const char *end, hb_variation_t *variation)
-{
-  return parse_tag (pp, end, &variation->tag) &&
-	 parse_variation_value (pp, end, variation) &&
-	 parse_space (pp, end) &&
-	 *pp == end;
-}
-
-/**
- * hb_variation_from_string:
- *
- * Since: 1.4.2
- */
-hb_bool_t
-hb_variation_from_string (const char *str, int len,
-			  hb_variation_t *variation)
-{
-  hb_variation_t var;
-
-  if (len < 0)
-    len = strlen (str);
-
-  if (likely (parse_one_variation (&str, str + len, &var)))
-  {
-    if (variation)
-      *variation = var;
-    return true;
-  }
-
-  if (variation)
-    memset (variation, 0, sizeof (*variation));
-  return false;
-}
-
-/**
- * hb_variation_to_string:
- *
- * Since: 1.4.2
- */
-void
-hb_variation_to_string (hb_variation_t *variation,
-			char *buf, unsigned int size)
-{
-  if (unlikely (!size)) return;
-
-  char s[128];
-  unsigned int len = 0;
-  hb_tag_to_string (variation->tag, s + len);
-  len += 4;
-  while (len && s[len - 1] == ' ')
-    len--;
-  s[len++] = '=';
-  len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", variation->value));
-
-  assert (len < ARRAY_LENGTH (s));
-  len = MIN (len, size - 1);
-  memcpy (buf, s, len);
-  buf[len] = '\0';
-}
diff --git a/src/hb-common.h b/src/hb-common.h
index 634cb96..2cbee76 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -362,42 +362,6 @@
 typedef void (*hb_destroy_func_t) (void *user_data);
 
 
-/* Font features and variations. */
-
-typedef struct hb_feature_t {
-  hb_tag_t      tag;
-  uint32_t      value;
-  unsigned int  start;
-  unsigned int  end;
-} hb_feature_t;
-
-HB_EXTERN hb_bool_t
-hb_feature_from_string (const char *str, int len,
-			hb_feature_t *feature);
-
-HB_EXTERN void
-hb_feature_to_string (hb_feature_t *feature,
-		      char *buf, unsigned int size);
-
-/**
- * hb_variation_t:
- *
- * Since: 1.4.2
- */
-typedef struct hb_variation_t {
-  hb_tag_t tag;
-  float    value;
-} hb_variation_t;
-
-HB_EXTERN hb_bool_t
-hb_variation_from_string (const char *str, int len,
-			  hb_variation_t *variation);
-
-HB_EXTERN void
-hb_variation_to_string (hb_variation_t *variation,
-			char *buf, unsigned int size);
-
-
 HB_END_DECLS
 
 #endif /* HB_COMMON_H */
diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc
index e857dfa..507581b 100644
--- a/src/hb-coretext.cc
+++ b/src/hb-coretext.cc
@@ -288,9 +288,7 @@
 hb_coretext_shaper_shape_plan_data_t *
 _hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
 					     const hb_feature_t *user_features HB_UNUSED,
-					     unsigned int        num_user_features HB_UNUSED,
-					     const int          *coords HB_UNUSED,
-					     unsigned int        num_coords HB_UNUSED)
+					     unsigned int        num_user_features HB_UNUSED)
 {
   return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
@@ -1282,9 +1280,7 @@
 hb_coretext_aat_shaper_shape_plan_data_t *
 _hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
 					     const hb_feature_t *user_features HB_UNUSED,
-					     unsigned int        num_user_features HB_UNUSED,
-					     const int          *coords HB_UNUSED,
-					     unsigned int        num_coords HB_UNUSED)
+					     unsigned int        num_user_features HB_UNUSED)
 {
   return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc
index d63bc04..76482ac 100644
--- a/src/hb-directwrite.cc
+++ b/src/hb-directwrite.cc
@@ -209,8 +209,8 @@
     data->fontFile->Release ();
   if (data->dwriteFactory) {
     if (data->fontFileLoader)
-      data->dwriteFactory->UnregisterFontFileLoader (data->fontFileLoader);
-    data->dwriteFactory->Release ();
+      data->dwriteFactory->UnregisterFontFileLoader(data->fontFileLoader);
+    data->dwriteFactory->Release();
   }
   if (data->fontFileLoader)
     delete data->fontFileLoader;
@@ -258,10 +258,8 @@
 
 hb_directwrite_shaper_shape_plan_data_t *
 _hb_directwrite_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-					       const hb_feature_t *user_features HB_UNUSED,
-					       unsigned int        num_user_features HB_UNUSED,
-					       const int          *coords HB_UNUSED,
-					       unsigned int        num_coords HB_UNUSED)
+               const hb_feature_t *user_features HB_UNUSED,
+               unsigned int        num_user_features HB_UNUSED)
 {
   return (hb_directwrite_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
@@ -542,13 +540,12 @@
  * shaper
  */
 
-static hb_bool_t
-_hb_directwrite_shape_full(hb_shape_plan_t    *shape_plan,
+hb_bool_t
+_hb_directwrite_shape(hb_shape_plan_t    *shape_plan,
   hb_font_t          *font,
   hb_buffer_t        *buffer,
   const hb_feature_t *features,
-  unsigned int        num_features,
-  float               lineWidth)
+  unsigned int        num_features)
 {
   hb_face_t *face = font->face;
   hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
@@ -671,7 +668,7 @@
   DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*)
     malloc (maxGlyphCount * sizeof (DWRITE_SHAPING_GLYPH_PROPERTIES));
 
-  hr = analyzer->GetGlyphs (textString, textLength, fontFace, false,
+  hr = analyzer->GetGlyphs (textString, textLength, fontFace, FALSE,
     isRightToLeft, &runHead->mScript, localeName, NULL, &dwFeatures,
     featureRangeLengths, 1, maxGlyphCount, clusterMap, textProperties, glyphIndices,
     glyphProperties, &glyphCount);
@@ -719,7 +716,7 @@
   hr = analyzer->GetGlyphPlacements (textString,
     clusterMap, textProperties, textLength, glyphIndices,
     glyphProperties, glyphCount, fontFace, fontEmSize,
-    false, isRightToLeft, &runHead->mScript, localeName,
+    FALSE, isRightToLeft, &runHead->mScript, localeName,
     &dwFeatures, featureRangeLengths, 1,
     glyphAdvances, glyphOffsets);
 
@@ -729,6 +726,9 @@
     return false;
   }
 
+  // TODO: get lineWith from somewhere
+  float lineWidth = 0;
+
   IDWriteTextAnalyzer1* analyzer1;
   analyzer->QueryInterface (&analyzer1);
 
@@ -898,37 +898,3 @@
   /* Wow, done! */
   return true;
 }
-
-hb_bool_t
-_hb_directwrite_shape(hb_shape_plan_t    *shape_plan,
-  hb_font_t          *font,
-  hb_buffer_t        *buffer,
-  const hb_feature_t *features,
-  unsigned int        num_features)
-{
-  return _hb_directwrite_shape_full(shape_plan, font, buffer,
-    features, num_features, 0);
-}
-
-/*
- * Public [experimental] API
- */
-
-hb_bool_t
-hb_directwrite_shape_experimental_width(hb_font_t          *font,
-  hb_buffer_t        *buffer,
-  const hb_feature_t *features,
-  unsigned int        num_features,
-  float               width)
-{
-  static char *shapers = "directwrite";
-  hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face,
-    &buffer->props, features, num_features, &shapers);
-  hb_bool_t res = _hb_directwrite_shape_full (shape_plan, font, buffer,
-    features, num_features, width);
-
-  if (res)
-    buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
-
-  return res;
-}
diff --git a/src/hb-directwrite.h b/src/hb-directwrite.h
index e743af2..0e1b479 100644
--- a/src/hb-directwrite.h
+++ b/src/hb-directwrite.h
@@ -29,10 +29,6 @@
 
 HB_BEGIN_DECLS
 
-HB_EXTERN hb_bool_t
-hb_directwrite_shape_experimental_width(hb_font_t *font, hb_buffer_t *buffer,
-  const hb_feature_t *features, unsigned int num_features, float width);
-
 HB_END_DECLS
 
 #endif /* HB_DIRECTWRITE_H */
diff --git a/src/hb-face-private.hh b/src/hb-face-private.hh
index 43e7b1c..c4266ff 100644
--- a/src/hb-face-private.hh
+++ b/src/hb-face-private.hh
@@ -50,16 +50,12 @@
   void                      *user_data;
   hb_destroy_func_t          destroy;
 
-  unsigned int index;			/* Face index in a collection, zero-based. */
-  mutable unsigned int upem;		/* Units-per-EM. */
-  mutable unsigned int num_glyphs;	/* Number of glyphs. */
+  unsigned int index;
+  mutable unsigned int upem;
+  mutable unsigned int num_glyphs;
 
-  struct hb_shaper_data_t shaper_data;	/* Various shaper data. */
+  struct hb_shaper_data_t shaper_data;
 
-  /* Various non-shaping data. */
-  /* ... */
-
-  /* Cache */
   struct plan_node_t {
     hb_shape_plan_t *shape_plan;
     plan_node_t *next;
diff --git a/src/hb-face.cc b/src/hb-face.cc
index 1ba9707..6b563bc 100644
--- a/src/hb-face.cc
+++ b/src/hb-face.cc
@@ -28,11 +28,15 @@
 
 #include "hb-private.hh"
 
-#include "hb-face-private.hh"
+#include "hb-ot-layout-private.hh"
+
+#include "hb-font-private.hh"
 #include "hb-open-file-private.hh"
 #include "hb-ot-head-table.hh"
 #include "hb-ot-maxp-table.hh"
 
+#include <string.h>
+
 
 /*
  * hb_face_t
diff --git a/src/hb-fallback-shape.cc b/src/hb-fallback-shape.cc
index ac6d4b0..e2ad240 100644
--- a/src/hb-fallback-shape.cc
+++ b/src/hb-fallback-shape.cc
@@ -73,9 +73,7 @@
 hb_fallback_shaper_shape_plan_data_t *
 _hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
 					    const hb_feature_t *user_features HB_UNUSED,
-					    unsigned int        num_user_features HB_UNUSED,
-					    const int          *coords HB_UNUSED,
-					    unsigned int        num_coords HB_UNUSED)
+					    unsigned int        num_user_features HB_UNUSED)
 {
   return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index 53671d7..0b75577 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -108,10 +108,6 @@
   unsigned int x_ppem;
   unsigned int y_ppem;
 
-  /* Font variation coordinates. */
-  unsigned int num_coords;
-  int *coords;
-
   hb_font_funcs_t   *klass;
   void              *user_data;
   hb_destroy_func_t  destroy;
@@ -120,14 +116,8 @@
 
 
   /* Convert from font-space to user-space */
-  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_scalef_x (float v) { return em_scalef (v, this->x_scale); }
-  inline hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
-  inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
-  { return em_scale (v, dir_scale (direction)); }
+  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); }
 
   /* Convert from parent-font user-space to our user-space */
   inline hb_position_t parent_scale_x_distance (hb_position_t v) {
@@ -302,32 +292,24 @@
 
   /* A bit higher-level, and with fallback */
 
-  inline void get_h_extents_with_fallback (hb_font_extents_t *extents)
-  {
-    if (!get_font_h_extents (extents))
-    {
-      extents->ascender = y_scale * .8;
-      extents->descender = extents->ascender - y_scale;
-      extents->line_gap = 0;
-    }
-  }
-  inline void get_v_extents_with_fallback (hb_font_extents_t *extents)
-  {
-    if (!get_font_v_extents (extents))
-    {
-      extents->ascender = x_scale / 2;
-      extents->descender = extents->ascender - x_scale;
-      extents->line_gap = 0;
-    }
-  }
-
   inline void get_extents_for_direction (hb_direction_t direction,
 					 hb_font_extents_t *extents)
   {
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
-      get_h_extents_with_fallback (extents);
-    else
-      get_v_extents_with_fallback (extents);
+    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
+      if (!get_font_h_extents (extents))
+      {
+	extents->ascender = y_scale * .8;
+	extents->descender = y_scale - extents->ascender;
+	extents->line_gap = 0;
+      }
+    } else {
+      if (!get_font_v_extents (extents))
+      {
+	extents->ascender = x_scale / 2;
+	extents->descender = x_scale - extents->ascender;
+	extents->line_gap = 0;
+      }
+    }
   }
 
   inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
@@ -343,38 +325,14 @@
     }
   }
 
+  /* Internal only */
   inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
 					     hb_position_t *x, hb_position_t *y)
   {
     *x = get_glyph_h_advance (glyph) / 2;
 
-    /* TODO cache this somehow?! */
-    hb_font_extents_t extents;
-    get_h_extents_with_fallback (&extents);
-    *y = extents.ascender;
-  }
-
-  inline void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
-						hb_position_t *x, hb_position_t *y)
-  {
-    if (!get_glyph_h_origin (glyph, x, y) &&
-	 get_glyph_v_origin (glyph, x, y))
-    {
-      hb_position_t dx, dy;
-      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
-      *x -= dx; *y -= dy;
-    }
-  }
-  inline void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
-						hb_position_t *x, hb_position_t *y)
-  {
-    if (!get_glyph_v_origin (glyph, x, y) &&
-	 get_glyph_h_origin (glyph, x, y))
-    {
-      hb_position_t dx, dy;
-      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
-      *x += dx; *y += dy;
-    }
+    /* TODO use font_extents.ascender */
+    *y = y_scale;
   }
 
   inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
@@ -382,9 +340,25 @@
 					      hb_position_t *x, hb_position_t *y)
   {
     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
-      get_glyph_h_origin_with_fallback (glyph, x, y);
+    {
+      if (!get_glyph_h_origin (glyph, x, y) &&
+	   get_glyph_v_origin (glyph, x, y))
+      {
+	hb_position_t dx, dy;
+	guess_v_origin_minus_h_origin (glyph, &dx, &dy);
+	*x -= dx; *y -= dy;
+      }
+    }
     else
-      get_glyph_v_origin_with_fallback (glyph, x, y);
+    {
+      if (!get_glyph_v_origin (glyph, x, y) &&
+	   get_glyph_h_origin (glyph, x, y))
+      {
+	hb_position_t dx, dy;
+	guess_v_origin_minus_h_origin (glyph, &dx, &dy);
+	*x += dx; *y += dy;
+      }
+    }
   }
 
   inline void add_glyph_h_origin (hb_codepoint_t glyph,
@@ -392,7 +366,7 @@
   {
     hb_position_t origin_x, origin_y;
 
-    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
+    get_glyph_h_origin (glyph, &origin_x, &origin_y);
 
     *x += origin_x;
     *y += origin_y;
@@ -402,7 +376,7 @@
   {
     hb_position_t origin_x, origin_y;
 
-    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
+    get_glyph_v_origin (glyph, &origin_x, &origin_y);
 
     *x += origin_x;
     *y += origin_y;
@@ -424,7 +398,7 @@
   {
     hb_position_t origin_x, origin_y;
 
-    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
+    get_glyph_h_origin (glyph, &origin_x, &origin_y);
 
     *x -= origin_x;
     *y -= origin_y;
@@ -434,7 +408,7 @@
   {
     hb_position_t origin_x, origin_y;
 
-    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
+    get_glyph_v_origin (glyph, &origin_x, &origin_y);
 
     *x -= origin_x;
     *y -= origin_y;
@@ -530,6 +504,7 @@
     return false;
   }
 
+  private:
   inline hb_position_t em_scale (int16_t v, int scale)
   {
     int upem = face->get_upem ();
@@ -537,10 +512,6 @@
     scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
     return (hb_position_t) (scaled / upem);
   }
-  inline hb_position_t em_scalef (float v, int scale)
-  {
-    return (hb_position_t) (v * scale / face->get_upem ());
-  }
 };
 
 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
diff --git a/src/hb-font.cc b/src/hb-font.cc
index ea45501..08fcd64 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -28,7 +28,14 @@
 
 #include "hb-private.hh"
 
+#include "hb-ot-layout-private.hh"
+
 #include "hb-font-private.hh"
+#include "hb-open-file-private.hh"
+#include "hb-ot-head-table.hh"
+#include "hb-ot-maxp-table.hh"
+
+#include <string.h>
 
 
 /*
@@ -1158,8 +1165,6 @@
   font->x_ppem = parent->x_ppem;
   font->y_ppem = parent->y_ppem;
 
-  /* TODO: copy variation coordinates. */
-
   return font;
 }
 
@@ -1189,9 +1194,6 @@
     0, /* x_ppem */
     0, /* y_ppem */
 
-    0, /* num_coords */
-    NULL, /* coords */
-
     const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
     NULL, /* user_data */
     NULL, /* destroy */
@@ -1246,8 +1248,6 @@
   hb_face_destroy (font->face);
   hb_font_funcs_destroy (font->klass);
 
-  free (font->coords);
-
   free (font);
 }
 
@@ -1536,114 +1536,6 @@
   if (y_ppem) *y_ppem = font->y_ppem;
 }
 
-/*
- * Variations
- */
-
-static void
-_hb_font_adopt_var_coords_normalized (hb_font_t *font,
-				      int *coords, /* 2.14 normalized */
-				      unsigned int coords_length)
-{
-  free (font->coords);
-
-  font->coords = coords;
-  font->num_coords = coords_length;
-}
-
-/**
- * hb_font_set_variations:
- *
- * Since: 1.4.2
- */
-void
-hb_font_set_variations (hb_font_t *font,
-			const hb_variation_t *variations,
-			unsigned int variations_length)
-{
-  if (font->immutable)
-    return;
-
-  if (!variations_length)
-  {
-    hb_font_set_var_coords_normalized (font, NULL, 0);
-    return;
-  }
-
-  unsigned int coords_length = hb_ot_var_get_axis_count (font->face);
-
-  int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : NULL;
-  if (unlikely (coords_length && !normalized))
-    return;
-
-  hb_ot_var_normalize_variations (font->face,
-				  variations, variations_length,
-				  normalized, coords_length);
-  _hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
-}
-
-/**
- * hb_font_set_var_coords_design:
- *
- * Since: 1.4.2
- */
-void
-hb_font_set_var_coords_design (hb_font_t *font,
-			       const float *coords,
-			       unsigned int coords_length)
-{
-  if (font->immutable)
-    return;
-
-  int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : NULL;
-  if (unlikely (coords_length && !normalized))
-    return;
-
-  hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized);
-  _hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
-}
-
-/**
- * hb_font_set_var_coords_normalized:
- *
- * Since: 1.4.2
- */
-void
-hb_font_set_var_coords_normalized (hb_font_t *font,
-				   const int *coords, /* 2.14 normalized */
-				   unsigned int coords_length)
-{
-  if (font->immutable)
-    return;
-
-  int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : NULL;
-  if (unlikely (coords_length && !copy))
-    return;
-
-  if (coords_length)
-    memcpy (copy, coords, coords_length * sizeof (coords[0]));
-
-  _hb_font_adopt_var_coords_normalized (font, copy, coords_length);
-}
-
-/**
- * hb_font_set_var_coords_normalized:
- *
- * Return value is valid as long as variation coordinates of the font
- * are not modified.
- *
- * Since: 1.4.2
- */
-const int *
-hb_font_get_var_coords_normalized (hb_font_t *font,
-				   unsigned int *length)
-{
-  if (length)
-    *length = font->num_coords;
-
-  return font->coords;
-}
-
 
 #ifndef HB_DISABLE_DEPRECATED
 
diff --git a/src/hb-font.h b/src/hb-font.h
index e2e5979..2b6ab50 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -603,24 +603,6 @@
 		  unsigned int *x_ppem,
 		  unsigned int *y_ppem);
 
-HB_EXTERN void
-hb_font_set_variations (hb_font_t *font,
-			const hb_variation_t *variations,
-			unsigned int variations_length);
-
-HB_EXTERN void
-hb_font_set_var_coords_design (hb_font_t *font,
-			       const float *coords,
-			       unsigned int coords_length);
-
-HB_EXTERN void
-hb_font_set_var_coords_normalized (hb_font_t *font,
-				   const int *coords, /* 2.14 normalized */
-				   unsigned int coords_length);
-
-HB_EXTERN const int *
-hb_font_get_var_coords_normalized (hb_font_t *font,
-				   unsigned int *length);
 
 HB_END_DECLS
 
diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index 48d6a0e..2b06c59 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -36,7 +36,6 @@
 #include "hb-cache-private.hh" // Maybe use in the future?
 
 #include FT_ADVANCES_H
-#include FT_MULTIPLE_MASTERS_H
 #include FT_TRUETYPE_TABLES_H
 
 
@@ -617,28 +616,6 @@
 		    ft_face->size->metrics.y_ppem);
 #endif
 
-#ifdef HAVE_FT_GET_VAR_BLEND_COORDINATES
-  FT_MM_Var *mm_var = NULL;
-  if (!FT_Get_MM_Var (ft_face, &mm_var))
-  {
-    FT_Fixed *ft_coords = (FT_Fixed *) calloc (mm_var->num_axis, sizeof (FT_Fixed));
-    int *coords = (int *) calloc (mm_var->num_axis, sizeof (int));
-    if (coords && ft_coords)
-    {
-      if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, ft_coords))
-      {
-	for (unsigned int i = 0; i < mm_var->num_axis; ++i)
-	  coords[i] = ft_coords[i] >>= 2;
-
-	hb_font_set_var_coords_normalized (font, coords, mm_var->num_axis);
-      }
-      free (coords);
-      free (ft_coords);
-    }
-    free (mm_var);
-  }
-#endif
-
   return font;
 }
 
@@ -741,20 +718,6 @@
     FT_Set_Transform (ft_face, &matrix, NULL);
   }
 
-  unsigned int num_coords;
-  const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
-  if (num_coords)
-  {
-    FT_Fixed *ft_coords = (FT_Fixed *) calloc (num_coords, sizeof (FT_Fixed));
-    if (ft_coords)
-    {
-      for (unsigned int i = 0; i < num_coords; i++)
-	ft_coords[i] = coords[i] << 2;
-      FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
-      free (ft_coords);
-    }
-  }
-
   ft_face->generic.data = blob;
   ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;
 
diff --git a/src/hb-glib.cc b/src/hb-glib.cc
index 2b91b5b..e203524 100644
--- a/src/hb-glib.cc
+++ b/src/hb-glib.cc
@@ -382,7 +382,6 @@
   return const_cast<hb_unicode_funcs_t *> (&_hb_glib_unicode_funcs);
 }
 
-#if GLIB_CHECK_VERSION(2,31,10)
 /**
  * hb_glib_blob_create:
  *
@@ -399,4 +398,3 @@
 			 g_bytes_ref (gbytes),
 			 (hb_destroy_func_t) g_bytes_unref);
 }
-#endif
diff --git a/src/hb-glib.h b/src/hb-glib.h
index 5f04183..12c3e3b 100644
--- a/src/hb-glib.h
+++ b/src/hb-glib.h
@@ -46,10 +46,9 @@
 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
 
diff --git a/src/hb-gobject-structs.cc b/src/hb-gobject-structs.cc
index fef0024..6bd6336 100644
--- a/src/hb-gobject-structs.cc
+++ b/src/hb-gobject-structs.cc
@@ -78,6 +78,3 @@
 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)
diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc
index a2d90db..c32318d 100644
--- a/src/hb-graphite2.cc
+++ b/src/hb-graphite2.cc
@@ -195,9 +195,7 @@
 hb_graphite2_shaper_shape_plan_data_t *
 _hb_graphite2_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
 					     const hb_feature_t *user_features HB_UNUSED,
-					     unsigned int        num_user_features HB_UNUSED,
-					     const int          *coords HB_UNUSED,
-					     unsigned int        num_coords HB_UNUSED)
+					     unsigned int        num_user_features HB_UNUSED)
 {
   return (hb_graphite2_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
diff --git a/src/hb-open-file-private.hh b/src/hb-open-file-private.hh
index f208419..5357ddc 100644
--- a/src/hb-open-file-private.hh
+++ b/src/hb-open-file-private.hh
@@ -142,7 +142,7 @@
   Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
   FixedVersion<>version;	/* Version of the TTC Header (1.0),
 				 * 0x00010000u */
-  ArrayOf<LOffsetTo<OffsetTable>, ULONG>
+  ArrayOf<OffsetTo<OffsetTable, ULONG>, ULONG>
 		table;		/* Array of offsets to the OffsetTable for each font
 				 * from the beginning of the file */
   public:
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index d90d68c..df683ca 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -30,7 +30,6 @@
 #define HB_OPEN_TYPE_PRIVATE_HH
 
 #include "hb-private.hh"
-#include "hb-face-private.hh"
 
 
 namespace OT {
@@ -106,7 +105,7 @@
   inline unsigned int get_size (void) const { return (size); }
 
 #define DEFINE_SIZE_UNION(size, _member) \
-  DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (size)); \
+  DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \
   static const unsigned int min_size = (size)
 
 #define DEFINE_SIZE_MIN(size) \
@@ -651,9 +650,7 @@
   DEFINE_SIZE_STATIC (Size);
 };
 
-typedef	IntType<int8_t	, 1> CHAR;	/* 8-bit signed integer. */
 typedef	IntType<uint8_t	, 1> BYTE;	/* 8-bit unsigned integer. */
-typedef	IntType<int8_t	, 1> INT8;	/* 8-bit signed integer. */
 typedef IntType<uint16_t, 2> USHORT;	/* 16-bit unsigned integer. */
 typedef IntType<int16_t,  2> SHORT;	/* 16-bit signed integer. */
 typedef IntType<uint32_t, 4> ULONG;	/* 32-bit unsigned integer. */
@@ -808,7 +805,6 @@
     if (unlikely (!c->check_struct (this))) return_trace (false);
     unsigned int offset = *this;
     if (unlikely (!offset)) return_trace (true);
-    if (unlikely (!c->check_range (base, offset))) return_trace (false);
     const Type &obj = StructAtOffset<Type> (base, offset);
     return_trace (likely (obj.sanitize (c)) || neuter (c));
   }
@@ -819,7 +815,6 @@
     if (unlikely (!c->check_struct (this))) return_trace (false);
     unsigned int offset = *this;
     if (unlikely (!offset)) return_trace (true);
-    if (unlikely (!c->check_range (base, offset))) return_trace (false);
     const Type &obj = StructAtOffset<Type> (base, offset);
     return_trace (likely (obj.sanitize (c, user_data)) || neuter (c));
   }
@@ -830,7 +825,6 @@
   }
   DEFINE_SIZE_STATIC (sizeof(OffsetType));
 };
-template <typename Type> struct LOffsetTo : OffsetTo<Type, ULONG> {};
 template <typename Base, typename OffsetType, typename Type>
 static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
 template <typename Base, typename OffsetType, typename Type>
@@ -952,11 +946,10 @@
   public:
   DEFINE_SIZE_ARRAY (sizeof (LenType), array);
 };
-template <typename Type> struct LArrayOf : ArrayOf<Type, ULONG> {};
 
 /* Array of Offset's */
-template <typename Type, typename OffsetType=USHORT>
-struct OffsetArrayOf : ArrayOf<OffsetTo<Type, OffsetType> > {};
+template <typename Type>
+struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {};
 
 /* Array of offsets relative to the beginning of the array itself. */
 template <typename Type>
@@ -1064,104 +1057,6 @@
 };
 
 
-/* Lazy struct and blob loaders. */
-
-/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */
-template <typename T>
-struct hb_lazy_loader_t
-{
-  inline void init (hb_face_t *face_)
-  {
-    face = face_;
-    instance = NULL;
-  }
-
-  inline void fini (void)
-  {
-    if (instance && instance != &OT::Null(T))
-    {
-      instance->fini();
-      free (instance);
-    }
-  }
-
-  inline const T* get (void) const
-  {
-  retry:
-    T *p = (T *) hb_atomic_ptr_get (&instance);
-    if (unlikely (!p))
-    {
-      p = (T *) calloc (1, sizeof (T));
-      if (unlikely (!p))
-        p = const_cast<T *> (&OT::Null(T));
-      else
-	p->init (face);
-      if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), NULL, p)))
-      {
-	if (p != &OT::Null(T))
-	  p->fini ();
-	goto retry;
-      }
-    }
-    return p;
-  }
-
-  inline const T* operator-> (void) const
-  {
-    return get ();
-  }
-
-  private:
-  hb_face_t *face;
-  T *instance;
-};
-
-/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */
-template <typename T>
-struct hb_lazy_table_loader_t
-{
-  inline void init (hb_face_t *face_)
-  {
-    face = face_;
-    instance = NULL;
-    blob = NULL;
-  }
-
-  inline void fini (void)
-  {
-    hb_blob_destroy (blob);
-  }
-
-  inline const T* get (void) const
-  {
-  retry:
-    T *p = (T *) hb_atomic_ptr_get (&instance);
-    if (unlikely (!p))
-    {
-      hb_blob_t *blob_ = OT::Sanitizer<T>::sanitize (face->reference_table (T::tableTag));
-      p = const_cast<T *>(OT::Sanitizer<T>::lock_instance (blob_));
-      if (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), NULL, p))
-      {
-	hb_blob_destroy (blob_);
-	goto retry;
-      }
-      blob = blob_;
-    }
-    return p;
-  }
-
-  inline const T* operator-> (void) const
-  {
-    return get();
-  }
-
-  private:
-  hb_face_t *face;
-  T *instance;
-  mutable hb_blob_t *blob;
-};
-
-
 } /* namespace OT */
 
 
diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh
deleted file mode 100644
index 0a7fbf5..0000000
--- a/src/hb-ot-cbdt-table.hh
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Copyright © 2016  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Seigo Nonaka
- */
-
-#ifndef HB_OT_CBDT_TABLE_HH
-#define HB_OT_CBDT_TABLE_HH
-
-#include "hb-open-type-private.hh"
-
-namespace OT {
-
-struct SmallGlyphMetrics
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  inline void get_extents (hb_glyph_extents_t *extents) const
-  {
-    extents->x_bearing = bearingX;
-    extents->y_bearing = bearingY;
-    extents->width = width;
-    extents->height = -height;
-  }
-
-  BYTE height;
-  BYTE width;
-  CHAR bearingX;
-  CHAR bearingY;
-  BYTE advance;
-
-  DEFINE_SIZE_STATIC(5);
-};
-
-struct BigGlyphMetrics : SmallGlyphMetrics
-{
-  CHAR vertBearingX;
-  CHAR vertBearingY;
-  BYTE vertAdvance;
-
-  DEFINE_SIZE_STATIC(8);
-};
-
-struct SBitLineMetrics
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  CHAR ascender;
-  CHAR decender;
-  BYTE widthMax;
-  CHAR caretSlopeNumerator;
-  CHAR caretSlopeDenominator;
-  CHAR caretOffset;
-  CHAR minOriginSB;
-  CHAR minAdvanceSB;
-  CHAR maxBeforeBL;
-  CHAR minAfterBL;
-  CHAR padding1;
-  CHAR padding2;
-
-  DEFINE_SIZE_STATIC(12);
-};
-
-
-/*
- * Index Subtables.
- */
-
-struct IndexSubtableHeader
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  USHORT indexFormat;
-  USHORT imageFormat;
-  ULONG imageDataOffset;
-
-  DEFINE_SIZE_STATIC(8);
-};
-
-template <typename OffsetType>
-struct IndexSubtableFormat1Or3
-{
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  c->check_array (offsetArrayZ, offsetArrayZ[0].static_size, glyph_count + 1));
-  }
-
-  bool get_image_data (unsigned int idx,
-		       unsigned int *offset,
-		       unsigned int *length) const
-  {
-    if (unlikely (offsetArrayZ[idx + 1] <= offsetArrayZ[idx]))
-      return false;
-
-    *offset = header.imageDataOffset + offsetArrayZ[idx];
-    *length = offsetArrayZ[idx + 1] - offsetArrayZ[idx];
-    return true;
-  }
-
-  IndexSubtableHeader header;
-  Offset<OffsetType> offsetArrayZ[VAR];
-
-  DEFINE_SIZE_ARRAY(8, offsetArrayZ);
-};
-
-struct IndexSubtableFormat1 : IndexSubtableFormat1Or3<ULONG> {};
-struct IndexSubtableFormat3 : IndexSubtableFormat1Or3<USHORT> {};
-
-struct IndexSubtable
-{
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.header.sanitize (c)) return_trace (false);
-    switch (u.header.indexFormat) {
-    case 1: return_trace (u.format1.sanitize (c, glyph_count));
-    case 3: return_trace (u.format3.sanitize (c, glyph_count));
-    default:return_trace (true);
-    }
-  }
-
-  inline bool get_extents (hb_glyph_extents_t *extents) const
-  {
-    switch (u.header.indexFormat) {
-    case 2: case 5: /* TODO */
-    case 1: case 3: case 4: /* Variable-metrics formats do not have metrics here. */
-    default:return (false);
-    }
-  }
-
-  bool get_image_data (unsigned int idx,
-		       unsigned int *offset,
-		       unsigned int *length,
-		       unsigned int *format) const
-  {
-    *format = u.header.imageFormat;
-    switch (u.header.indexFormat) {
-    case 1: return u.format1.get_image_data (idx, offset, length);
-    case 3: return u.format3.get_image_data (idx, offset, length);
-    default: return false;
-    }
-  }
-
-  protected:
-  union {
-  IndexSubtableHeader	header;
-  IndexSubtableFormat1	format1;
-  IndexSubtableFormat3	format3;
-  /* TODO: Format 2, 4, 5. */
-  } u;
-  public:
-  DEFINE_SIZE_UNION (8, header);
-};
-
-struct IndexSubtableRecord
-{
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  firstGlyphIndex <= lastGlyphIndex &&
-		  offsetToSubtable.sanitize (c, this, lastGlyphIndex - firstGlyphIndex + 1));
-  }
-
-  inline bool get_extents (hb_glyph_extents_t *extents) const
-  {
-    return (this+offsetToSubtable).get_extents (extents);
-  }
-
-  bool get_image_data (unsigned int gid,
-		       unsigned int *offset,
-		       unsigned int *length,
-		       unsigned int *format) const
-  {
-    if (gid < firstGlyphIndex || gid > lastGlyphIndex)
-    {
-      return false;
-    }
-    return (this+offsetToSubtable).get_image_data (gid - firstGlyphIndex,
-						   offset, length, format);
-  }
-
-  USHORT firstGlyphIndex;
-  USHORT lastGlyphIndex;
-  LOffsetTo<IndexSubtable> offsetToSubtable;
-
-  DEFINE_SIZE_STATIC(8);
-};
-
-struct IndexSubtableArray
-{
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_array (&indexSubtablesZ, indexSubtablesZ[0].static_size, count)))
-      return_trace (false);
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!indexSubtablesZ[i].sanitize (c, this)))
-	return_trace (false);
-    return_trace (true);
-  }
-
-  public:
-  const IndexSubtableRecord* find_table (hb_codepoint_t glyph, unsigned int numTables) const
-  {
-    for (unsigned int i = 0; i < numTables; ++i)
-    {
-      unsigned int firstGlyphIndex = indexSubtablesZ[i].firstGlyphIndex;
-      unsigned int lastGlyphIndex = indexSubtablesZ[i].lastGlyphIndex;
-      if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) {
-        return &indexSubtablesZ[i];
-      }
-    }
-    return NULL;
-  }
-
-  protected:
-  IndexSubtableRecord indexSubtablesZ[VAR];
-
-  public:
-  DEFINE_SIZE_ARRAY(0, indexSubtablesZ);
-};
-
-struct BitmapSizeTable
-{
-  friend struct CBLC;
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  indexSubtableArrayOffset.sanitize (c, base, numberOfIndexSubtables) &&
-		  c->check_range (&(base+indexSubtableArrayOffset), indexTablesSize) &&
-		  horizontal.sanitize (c) &&
-		  vertical.sanitize (c));
-  }
-
-  const IndexSubtableRecord *find_table (hb_codepoint_t glyph, const void *base) const
-  {
-    return (base+indexSubtableArrayOffset).find_table (glyph, numberOfIndexSubtables);
-  }
-
-  protected:
-  LOffsetTo<IndexSubtableArray> indexSubtableArrayOffset;
-  ULONG indexTablesSize;
-  ULONG numberOfIndexSubtables;
-  ULONG colorRef;
-  SBitLineMetrics horizontal;
-  SBitLineMetrics vertical;
-  USHORT startGlyphIndex;
-  USHORT endGlyphIndex;
-  BYTE ppemX;
-  BYTE ppemY;
-  BYTE bitDepth;
-  CHAR flags;
-
-public:
-  DEFINE_SIZE_STATIC(48);
-};
-
-
-/*
- * Glyph Bitmap Data Formats.
- */
-
-struct GlyphBitmapDataFormat17
-{
-  SmallGlyphMetrics glyphMetrics;
-  ULONG dataLen;
-  BYTE dataZ[VAR];
-
-  DEFINE_SIZE_ARRAY(9, dataZ);
-};
-
-
-/*
- * CBLC -- Color Bitmap Location Table
- */
-
-#define HB_OT_TAG_CBLC HB_TAG('C','B','L','C')
-
-struct CBLC
-{
-  static const hb_tag_t tableTag = HB_OT_TAG_CBLC;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  likely (version.major == 2 || version.major == 3) &&
-		  sizeTables.sanitize (c, this));
-  }
-
-  public:
-  const IndexSubtableRecord *find_table (hb_codepoint_t glyph,
-					 unsigned int *x_ppem, unsigned int *y_ppem) const
-  {
-    /* TODO: Make it possible to select strike. */
-
-    unsigned int count = sizeTables.len;
-    for (uint32_t i = 0; i < count; ++i)
-    {
-      unsigned int startGlyphIndex = sizeTables.array[i].startGlyphIndex;
-      unsigned int endGlyphIndex = sizeTables.array[i].endGlyphIndex;
-      if (startGlyphIndex <= glyph && glyph <= endGlyphIndex)
-      {
-	*x_ppem = sizeTables[i].ppemX;
-	*y_ppem = sizeTables[i].ppemY;
-	return sizeTables[i].find_table (glyph, this);
-      }
-    }
-
-    return NULL;
-  }
-
-  protected:
-  FixedVersion<>		version;
-  LArrayOf<BitmapSizeTable>	sizeTables;
-
-  public:
-  DEFINE_SIZE_ARRAY(8, sizeTables);
-};
-
-/*
- * CBDT -- Color Bitmap Data Table
- */
-#define HB_OT_TAG_CBDT HB_TAG('C','B','D','T')
-
-struct CBDT
-{
-  static const hb_tag_t tableTag = HB_OT_TAG_CBDT;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  likely (version.major == 2 || version.major == 3));
-  }
-
-  protected:
-  FixedVersion<>version;
-  BYTE dataZ[VAR];
-
-  public:
-  DEFINE_SIZE_ARRAY(4, dataZ);
-};
-
-} /* namespace OT */
-
-#endif /* HB_OT_CBDT_TABLE_HH */
diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index 3a53a1c..d7a94a1 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -380,9 +380,9 @@
   }
 
   UINT24	varSelector;	/* Variation selector. */
-  LOffsetTo<DefaultUVS>
+  OffsetTo<DefaultUVS, ULONG>
 		defaultUVS;	/* Offset to Default UVS Table. May be 0. */
-  LOffsetTo<NonDefaultUVS>
+  OffsetTo<NonDefaultUVS, ULONG>
 		nonDefaultUVS;	/* Offset to Non-Default UVS Table. May be 0. */
   public:
   DEFINE_SIZE_STATIC (11);
@@ -486,7 +486,7 @@
 
   USHORT	platformID;	/* Platform ID. */
   USHORT	encodingID;	/* Platform-specific encoding ID. */
-  LOffsetTo<CmapSubtable>
+  OffsetTo<CmapSubtable, ULONG>
 		subtable;	/* Byte offset from beginning of table to the subtable for this encoding. */
   public:
   DEFINE_SIZE_STATIC (8);
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 009db20..0b7e31b 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -31,13 +31,11 @@
 #include "hb-font-private.hh"
 
 #include "hb-ot-cmap-table.hh"
-#include "hb-ot-cbdt-table.hh"
 #include "hb-ot-glyf-table.hh"
 #include "hb-ot-head-table.hh"
 #include "hb-ot-hhea-table.hh"
 #include "hb-ot-hmtx-table.hh"
 #include "hb-ot-os2-table.hh"
-#include "hb-ot-var-hvar-table.hh"
 //#include "hb-ot-post-table.hh"
 
 
@@ -49,22 +47,16 @@
   unsigned short ascender;
   unsigned short descender;
   unsigned short line_gap;
-  bool has_font_extents;
 
-  const OT::hmtxvmtx *table;
+  const OT::_mtx *table;
   hb_blob_t *blob;
 
-  const OT::HVARVVAR *var;
-  hb_blob_t *var_blob;
-
   inline void init (hb_face_t *face,
 		    hb_tag_t _hea_tag,
 		    hb_tag_t _mtx_tag,
-		    hb_tag_t _var_tag,
-		    hb_tag_t os2_tag,
-		    unsigned int default_advance = 0)
+		    hb_tag_t os2_tag)
   {
-    this->default_advance = default_advance ? default_advance : face->get_upem ();
+    this->default_advance = face->get_upem ();
 
     bool got_font_extents = false;
     if (os2_tag)
@@ -90,13 +82,10 @@
       this->ascender = _hea->ascender;
       this->descender = _hea->descender;
       this->line_gap = _hea->lineGap;
-      got_font_extents = (this->ascender | this->descender) != 0;
     }
     hb_blob_destroy (_hea_blob);
 
-    this->has_font_extents = got_font_extents;
-
-    this->blob = OT::Sanitizer<OT::hmtxvmtx>::sanitize (face->reference_table (_mtx_tag));
+    this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag));
 
     /* Cap num_metrics() and num_advances() based on table length. */
     unsigned int len = hb_blob_get_length (this->blob);
@@ -112,20 +101,15 @@
       hb_blob_destroy (this->blob);
       this->blob = hb_blob_get_empty ();
     }
-    this->table = OT::Sanitizer<OT::hmtxvmtx>::lock_instance (this->blob);
-
-    this->var_blob = OT::Sanitizer<OT::HVARVVAR>::sanitize (face->reference_table (_var_tag));
-    this->var = OT::Sanitizer<OT::HVARVVAR>::lock_instance (this->var_blob);
+    this->table = OT::Sanitizer<OT::_mtx>::lock_instance (this->blob);
   }
 
   inline void fini (void)
   {
     hb_blob_destroy (this->blob);
-    hb_blob_destroy (this->var_blob);
   }
 
-  inline unsigned int get_advance (hb_codepoint_t  glyph,
-				   hb_font_t      *font) const
+  inline unsigned int get_advance (hb_codepoint_t glyph) const
   {
     if (unlikely (glyph >= this->num_metrics))
     {
@@ -138,8 +122,10 @@
 	return this->default_advance;
     }
 
-    return this->table->longMetric[MIN (glyph, this->num_advances - 1)].advance
-	 + this->var->get_advance_var (glyph, font->coords, font->num_coords); // TODO Optimize?!
+    if (glyph >= this->num_advances)
+      glyph = this->num_advances - 1;
+
+    return this->table->longMetric[glyph].advance;
   }
 };
 
@@ -216,91 +202,6 @@
   }
 };
 
-struct hb_ot_face_cbdt_accelerator_t
-{
-  hb_blob_t *cblc_blob;
-  hb_blob_t *cbdt_blob;
-  const OT::CBLC *cblc;
-  const OT::CBDT *cbdt;
-
-  unsigned int cbdt_len;
-  float upem;
-
-  inline void init (hb_face_t *face)
-  {
-    upem = face->get_upem();
-
-    cblc_blob = OT::Sanitizer<OT::CBLC>::sanitize (face->reference_table (HB_OT_TAG_CBLC));
-    cbdt_blob = OT::Sanitizer<OT::CBDT>::sanitize (face->reference_table (HB_OT_TAG_CBDT));
-    cbdt_len = hb_blob_get_length (cbdt_blob);
-
-    if (hb_blob_get_length (cblc_blob) == 0) {
-      cblc = NULL;
-      cbdt = NULL;
-      return;  /* Not a bitmap font. */
-    }
-    cblc = OT::Sanitizer<OT::CBLC>::lock_instance (cblc_blob);
-    cbdt = OT::Sanitizer<OT::CBDT>::lock_instance (cbdt_blob);
-
-  }
-
-  inline void fini (void)
-  {
-    hb_blob_destroy (this->cblc_blob);
-    hb_blob_destroy (this->cbdt_blob);
-  }
-
-  inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
-  {
-    unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */
-
-    if (cblc == NULL)
-      return false;  // Not a color bitmap font.
-
-    const OT::IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem);
-    if (subtable_record == NULL)
-      return false;
-
-    if (subtable_record->get_extents (extents))
-      return true;
-
-    unsigned int image_offset = 0, image_length = 0, image_format = 0;
-    if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format))
-      return false;
-
-    {
-      /* TODO Move the following into CBDT struct when adding more formats. */
-
-      if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
-	return false;
-
-      switch (image_format)
-      {
-	case 17: {
-	  if (unlikely (image_length < OT::GlyphBitmapDataFormat17::min_size))
-	    return false;
-
-	  const OT::GlyphBitmapDataFormat17& glyphFormat17 =
-	      OT::StructAtOffset<OT::GlyphBitmapDataFormat17> (this->cbdt, image_offset);
-	  glyphFormat17.glyphMetrics.get_extents (extents);
-	}
-	break;
-	default:
-	  // TODO: Support other image formats.
-	  return false;
-      }
-    }
-
-    /* Convert to the font units. */
-    extents->x_bearing *= upem / (float) x_ppem;
-    extents->y_bearing *= upem / (float) y_ppem;
-    extents->width *= upem / (float) x_ppem;
-    extents->height *= upem / (float) y_ppem;
-
-    return true;
-  }
-};
-
 typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
 					  hb_codepoint_t codepoint,
 					  hb_codepoint_t *glyph);
@@ -363,11 +264,7 @@
     if (!subtable) subtable = cmap->find_subtable (0, 2);
     if (!subtable) subtable = cmap->find_subtable (0, 1);
     if (!subtable) subtable = cmap->find_subtable (0, 0);
-    if (!subtable)
-    {
-      subtable = cmap->find_subtable (3, 0);
-      if (subtable) symbol = true;
-    }
+    if (!subtable)(subtable = cmap->find_subtable (3, 0)) && (symbol = true);
     /* Meh. */
     if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
 
@@ -429,13 +326,54 @@
   }
 };
 
+template <typename T>
+struct hb_lazy_loader_t
+{
+  inline void init (hb_face_t *face_)
+  {
+    face = face_;
+    instance = NULL;
+  }
+
+  inline void fini (void)
+  {
+    if (instance && instance != &OT::Null(T))
+    {
+      instance->fini();
+      free (instance);
+    }
+  }
+
+  inline const T* operator-> (void) const
+  {
+  retry:
+    T *p = (T *) hb_atomic_ptr_get (&instance);
+    if (unlikely (!p))
+    {
+      p = (T *) calloc (1, sizeof (T));
+      if (unlikely (!p))
+        return &OT::Null(T);
+      p->init (face);
+      if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), NULL, p)))
+      {
+	p->fini ();
+	goto retry;
+      }
+    }
+    return p;
+  }
+
+  private:
+  hb_face_t *face;
+  T *instance;
+};
+
 struct hb_ot_font_t
 {
   hb_ot_face_cmap_accelerator_t cmap;
   hb_ot_face_metrics_accelerator_t h_metrics;
   hb_ot_face_metrics_accelerator_t v_metrics;
-  OT::hb_lazy_loader_t<hb_ot_face_glyf_accelerator_t> glyf;
-  OT::hb_lazy_loader_t<hb_ot_face_cbdt_accelerator_t> cbdt;
+  hb_lazy_loader_t<hb_ot_face_glyf_accelerator_t> glyf;
 };
 
 
@@ -448,11 +386,9 @@
     return NULL;
 
   ot_font->cmap.init (face);
-  ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_HVAR, HB_OT_TAG_os2);
-  ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_OT_TAG_VVAR, HB_TAG_NONE,
-			   ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
+  ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_os2);
+  ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE); /* TODO Can we do this lazily? */
   ot_font->glyf.init (face);
-  ot_font->cbdt.init (face);
 
   return ot_font;
 }
@@ -464,7 +400,6 @@
   ot_font->h_metrics.fini ();
   ot_font->v_metrics.fini ();
   ot_font->glyf.fini ();
-  ot_font->cbdt.fini ();
 
   free (ot_font);
 }
@@ -495,23 +430,23 @@
 }
 
 static hb_position_t
-hb_ot_get_glyph_h_advance (hb_font_t *font,
+hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
 			   void *font_data,
 			   hb_codepoint_t glyph,
 			   void *user_data HB_UNUSED)
 {
   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return font->em_scale_x (ot_font->h_metrics.get_advance (glyph, font));
+  return font->em_scale_x (ot_font->h_metrics.get_advance (glyph));
 }
 
 static hb_position_t
-hb_ot_get_glyph_v_advance (hb_font_t *font,
+hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
 			   void *font_data,
 			   hb_codepoint_t glyph,
 			   void *user_data HB_UNUSED)
 {
   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph, font));
+  return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph));
 }
 
 static hb_bool_t
@@ -523,9 +458,6 @@
 {
   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
   bool ret = ot_font->glyf->get_extents (glyph, extents);
-  if (!ret)
-    ret = ot_font->cbdt->get_extents (glyph, extents);
-  // TODO Hook up side-bearings variations.
   extents->x_bearing = font->em_scale_x (extents->x_bearing);
   extents->y_bearing = font->em_scale_y (extents->y_bearing);
   extents->width     = font->em_scale_x (extents->width);
@@ -543,8 +475,7 @@
   metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender);
   metrics->descender = font->em_scale_y (ot_font->h_metrics.descender);
   metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap);
-  // TODO Hook up variations.
-  return ot_font->h_metrics.has_font_extents;
+  return true;
 }
 
 static hb_bool_t
@@ -557,8 +488,7 @@
   metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender);
   metrics->descender = font->em_scale_x (ot_font->v_metrics.descender);
   metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap);
-  // TODO Hook up variations.
-  return ot_font->v_metrics.has_font_extents;
+  return true;
 }
 
 static hb_font_funcs_t *static_ot_funcs = NULL;
diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh
index 30aa625..a9606b3 100644
--- a/src/hb-ot-hmtx-table.hh
+++ b/src/hb-ot-hmtx-table.hh
@@ -50,8 +50,10 @@
   DEFINE_SIZE_STATIC (4);
 };
 
-struct hmtxvmtx
+struct _mtx
 {
+  static const hb_tag_t tableTag = HB_TAG('_','m','t','x');
+
   static const hb_tag_t hmtxTag	= HB_OT_TAG_hmtx;
   static const hb_tag_t vmtxTag	= HB_OT_TAG_vmtx;
 
@@ -89,10 +91,10 @@
   DEFINE_SIZE_ARRAY2 (0, longMetric, leadingBearingX);
 };
 
-struct hmtx : hmtxvmtx {
+struct hmtx : _mtx {
   static const hb_tag_t tableTag	= HB_OT_TAG_hmtx;
 };
-struct vmtx : hmtxvmtx {
+struct vmtx : _mtx {
   static const hb_tag_t tableTag	= HB_OT_TAG_vmtx;
 };
 
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 180e5f0..34fa1b7 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -507,7 +507,7 @@
   { return this+featureParams; }
 
   inline bool sanitize (hb_sanitize_context_t *c,
-			const Record<Feature>::sanitize_closure_t *closure = NULL) const
+			const Record<Feature>::sanitize_closure_t *closure) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
@@ -731,8 +731,8 @@
     inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; };
     inline bool more (void) { return i < c->glyphArray.len; }
     inline void next (void) { i++; }
-    inline hb_codepoint_t get_glyph (void) { return c->glyphArray[i]; }
-    inline unsigned int get_coverage (void) { return i; }
+    inline uint16_t get_glyph (void) { return c->glyphArray[i]; }
+    inline uint16_t get_coverage (void) { return i; }
 
     private:
     const struct CoverageFormat1 *c;
@@ -829,33 +829,26 @@
 
   public:
   /* Older compilers need this to be public. */
-  struct Iter
-  {
-    inline void init (const CoverageFormat2 &c_)
-    {
+  struct Iter {
+    inline void init (const CoverageFormat2 &c_) {
       c = &c_;
       coverage = 0;
       i = 0;
       j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0;
     }
     inline bool more (void) { return i < c->rangeRecord.len; }
-    inline void next (void)
-    {
-      if (j >= c->rangeRecord[i].end)
-      {
+    inline void next (void) {
+      coverage++;
+      if (j == c->rangeRecord[i].end) {
         i++;
 	if (more ())
-	{
 	  j = c->rangeRecord[i].start;
-	  coverage = c->rangeRecord[i].value;
-	}
 	return;
       }
-      coverage++;
       j++;
     }
-    inline hb_codepoint_t get_glyph (void) { return j; }
-    inline unsigned int get_coverage (void) { return coverage; }
+    inline uint16_t get_glyph (void) { return j; }
+    inline uint16_t get_coverage (void) { return coverage; }
 
     private:
     const struct CoverageFormat2 *c;
@@ -964,14 +957,14 @@
       default:                   break;
       }
     }
-    inline hb_codepoint_t get_glyph (void) {
+    inline uint16_t get_glyph (void) {
       switch (format) {
       case 1: return u.format1.get_glyph ();
       case 2: return u.format2.get_glyph ();
       default:return 0;
       }
     }
-    inline unsigned int get_coverage (void) {
+    inline uint16_t get_coverage (void) {
       switch (format) {
       case 1: return u.format1.get_coverage ();
       case 2: return u.format2.get_coverage ();
@@ -1169,388 +1162,11 @@
 
 
 /*
- * Item Variation Store
- */
-
-struct VarRegionAxis
-{
-  inline float evaluate (int coord) const
-  {
-    int start = startCoord, peak = peakCoord, end = endCoord;
-
-    /* TODO Move these to sanitize(). */
-    if (unlikely (start > peak || peak > end))
-      return 1.;
-    if (unlikely (start < 0 && end > 0 && peak != 0))
-      return 1.;
-
-    if (peak == 0 || coord == peak)
-      return 1.;
-
-    if (coord <= start || end <= coord)
-      return 0.;
-
-    /* Interpolate */
-    if (coord < peak)
-      return float (coord - start) / (peak - start);
-    else
-      return float (end - coord) / (end - peak);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-    /* TODO Handle invalid start/peak/end configs, so we don't
-     * have to do that at runtime. */
-  }
-
-  public:
-  F2DOT14	startCoord;
-  F2DOT14	peakCoord;
-  F2DOT14	endCoord;
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct VarRegionList
-{
-  inline float evaluate (unsigned int region_index,
-			 int *coords, unsigned int coord_len) const
-  {
-    if (unlikely (region_index >= regionCount))
-      return 0.;
-
-    const VarRegionAxis *axes = axesZ + (region_index * axisCount);
-
-    float v = 1.;
-    unsigned int count = MIN (coord_len, (unsigned int) axisCount);
-    for (unsigned int i = 0; i < count; i++)
-    {
-      float factor = axes[i].evaluate (coords[i]);
-      if (factor == 0.)
-        return 0.;
-      v *= factor;
-    }
-    return v;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  c->check_array (axesZ, axesZ[0].static_size,
-				  (unsigned int) axisCount * (unsigned int) regionCount));
-  }
-
-  protected:
-  USHORT	axisCount;
-  USHORT	regionCount;
-  VarRegionAxis	axesZ[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (4, axesZ);
-};
-
-struct VarData
-{
-  inline unsigned int get_row_size (void) const
-  { return shortCount + regionIndices.len; }
-
-  inline unsigned int get_size (void) const
-  { return itemCount * get_row_size (); }
-
-  inline float get_delta (unsigned int inner,
-			  int *coords, unsigned int coord_count,
-			  const VarRegionList &regions) const
-  {
-    if (unlikely (inner >= itemCount))
-      return 0.;
-
-   unsigned int count = regionIndices.len;
-   unsigned int scount = shortCount;
-
-   const BYTE *bytes = &StructAfter<BYTE> (regionIndices);
-   const BYTE *row = bytes + inner * (scount + count);
-
-   float delta = 0.;
-   unsigned int i = 0;
-
-   const SHORT *scursor = reinterpret_cast<const SHORT *> (row);
-   for (; i < scount; i++)
-   {
-     float scalar = regions.evaluate (regionIndices.array[i], coords, coord_count);
-     delta += scalar * *scursor++;
-   }
-   const INT8 *bcursor = reinterpret_cast<const INT8 *> (scursor);
-   for (; i < count; i++)
-   {
-     float scalar = regions.evaluate (regionIndices.array[i], coords, coord_count);
-     delta += scalar * *bcursor++;
-   }
-
-   return delta;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  regionIndices.sanitize(c) &&
-		  shortCount <= regionIndices.len &&
-		  c->check_array (&StructAfter<BYTE> (regionIndices),
-				  get_row_size (), itemCount));
-  }
-
-  protected:
-  USHORT		itemCount;
-  USHORT		shortCount;
-  ArrayOf<USHORT>	regionIndices;
-  BYTE			bytesX[VAR];
-  public:
-  DEFINE_SIZE_ARRAY2 (6, regionIndices, bytesX);
-};
-
-struct VariationStore
-{
-  inline float get_delta (unsigned int outer, unsigned int inner,
-			  int *coords, unsigned int coord_count) const
-  {
-    if (unlikely (outer >= dataSets.len))
-      return 0.;
-
-    return (this+dataSets[outer]).get_delta (inner,
-					     coords, coord_count,
-					     this+regions);
-  }
-
-  inline float get_delta (unsigned int index,
-			  int *coords, unsigned int coord_count) const
-  {
-    unsigned int outer = index >> 16;
-    unsigned int inner = index & 0xFFFF;
-    return get_delta (outer, inner, coords, coord_count);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  format == 1 &&
-		  regions.sanitize (c, this) &&
-		  dataSets.sanitize (c, this));
-  }
-
-  protected:
-  USHORT				format;
-  LOffsetTo<VarRegionList>		regions;
-  OffsetArrayOf<VarData, ULONG>		dataSets;
-  public:
-  DEFINE_SIZE_ARRAY (8, dataSets);
-};
-
-/*
- * Feature Variations
- */
-
-struct ConditionFormat1
-{
-  friend struct Condition;
-
-  private:
-  inline bool evaluate (const int *coords, unsigned int coord_len) const
-  {
-    int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
-    return filterRangeMinValue <= coord && coord <= filterRangeMaxValue;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  USHORT	format;		/* Format identifier--format = 1 */
-  USHORT	axisIndex;
-  F2DOT14	filterRangeMinValue;
-  F2DOT14	filterRangeMaxValue;
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-struct Condition
-{
-  inline bool evaluate (const int *coords, unsigned int coord_len) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.evaluate (coords, coord_len);
-    default:return false;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
-    switch (u.format) {
-    case 1: return_trace (u.format1.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  USHORT		format;		/* Format identifier */
-  ConditionFormat1	format1;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-struct ConditionSet
-{
-  inline bool evaluate (const int *coords, unsigned int coord_len) const
-  {
-    unsigned int count = conditions.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!(this+conditions.array[i]).evaluate (coords, coord_len))
-        return false;
-    return true;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (conditions.sanitize (c, this));
-  }
-
-  protected:
-  OffsetArrayOf<Condition, ULONG> conditions;
-  public:
-  DEFINE_SIZE_ARRAY (2, conditions);
-};
-
-struct FeatureTableSubstitutionRecord
-{
-  friend struct FeatureTableSubstitution;
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && feature.sanitize (c, base));
-  }
-
-  protected:
-  USHORT		featureIndex;
-  LOffsetTo<Feature>	feature;
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct FeatureTableSubstitution
-{
-  inline const Feature *find_substitute (unsigned int feature_index) const
-  {
-    unsigned int count = substitutions.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      const FeatureTableSubstitutionRecord &record = substitutions.array[i];
-      if (record.featureIndex == feature_index)
-	return &(this+record.feature);
-    }
-    return NULL;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-		  likely (version.major == 1) &&
-		  substitutions.sanitize (c, this));
-  }
-
-  protected:
-  FixedVersion<>	version;	/* Version--0x00010000u */
-  ArrayOf<FeatureTableSubstitutionRecord>
-			substitutions;
-  public:
-  DEFINE_SIZE_ARRAY (6, substitutions);
-};
-
-struct FeatureVariationRecord
-{
-  friend struct FeatureVariations;
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (conditions.sanitize (c, base) &&
-		  substitutions.sanitize (c, base));
-  }
-
-  protected:
-  LOffsetTo<ConditionSet>
-			conditions;
-  LOffsetTo<FeatureTableSubstitution>
-			substitutions;
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-struct FeatureVariations
-{
-  static const unsigned int NOT_FOUND_INDEX = 0xFFFFFFFFu;
-
-  inline bool find_index (const int *coords, unsigned int coord_len,
-			  unsigned int *index) const
-  {
-    unsigned int count = varRecords.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      const FeatureVariationRecord &record = varRecords.array[i];
-      if ((this+record.conditions).evaluate (coords, coord_len))
-      {
-	*index = i;
-	return true;
-      }
-    }
-    *index = NOT_FOUND_INDEX;
-    return false;
-  }
-
-  inline const Feature *find_substitute (unsigned int variations_index,
-					 unsigned int feature_index) const
-  {
-    const FeatureVariationRecord &record = varRecords[variations_index];
-    return (this+record.substitutions).find_substitute (feature_index);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-		  likely (version.major == 1) &&
-		  varRecords.sanitize (c, this));
-  }
-
-  protected:
-  FixedVersion<>	version;	/* Version--0x00010000u */
-  LArrayOf<FeatureVariationRecord>
-			varRecords;
-  public:
-  DEFINE_SIZE_ARRAY (8, varRecords);
-};
-
-
-/*
  * Device Tables
  */
 
-struct HintingDevice
+struct Device
 {
-  friend struct Device;
-
-  private:
 
   inline hb_position_t get_x_delta (hb_font_t *font) const
   { return get_delta (font->x_ppem, font->x_scale); }
@@ -1619,101 +1235,6 @@
   DEFINE_SIZE_ARRAY (6, deltaValue);
 };
 
-struct VariationDevice
-{
-  friend struct Device;
-
-  private:
-
-  inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const
-  { return font->em_scalef_x (get_delta (font, store)); }
-
-  inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const
-  { return font->em_scalef_y (get_delta (font, store)); }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  private:
-
-  inline float get_delta (hb_font_t *font, const VariationStore &store) const
-  {
-    return store.get_delta (outerIndex, innerIndex, font->coords, font->num_coords);
-  }
-
-  protected:
-  USHORT	outerIndex;
-  USHORT	innerIndex;
-  USHORT	deltaFormat;	/* Format identifier for this table: 0x0x8000 */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct DeviceHeader
-{
-  protected:
-  USHORT		reserved1;
-  USHORT		reserved2;
-  public:
-  USHORT		format;		/* Format identifier */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct Device
-{
-  inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const
-  {
-    switch (u.b.format)
-    {
-    case 1: case 2: case 3:
-      return u.hinting.get_x_delta (font);
-    case 0x8000:
-      return u.variation.get_x_delta (font, store);
-    default:
-      return 0;
-    }
-  }
-  inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const
-  {
-    switch (u.b.format)
-    {
-    case 1: case 2: case 3:
-      return u.hinting.get_y_delta (font);
-    case 0x8000:
-      return u.variation.get_y_delta (font, store);
-    default:
-      return 0;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.b.format.sanitize (c)) return_trace (false);
-    switch (u.b.format) {
-    case 1: case 2: case 3:
-      return_trace (u.hinting.sanitize (c));
-    case 0x8000:
-      return_trace (u.variation.sanitize (c));
-    default:
-      return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  DeviceHeader		b;
-  HintingDevice		hinting;
-  VariationDevice	variation;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (6, b);
-};
-
 
 } /* namespace OT */
 
diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh
index 552df0f..2b4bc5a 100644
--- a/src/hb-ot-layout-gdef-table.hh
+++ b/src/hb-ot-layout-gdef-table.hh
@@ -97,7 +97,7 @@
   friend struct CaretValue;
 
   private:
-  inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const
+  inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const
   {
     return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);
   }
@@ -146,11 +146,11 @@
 {
   friend struct CaretValue;
 
-  inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, const VariationStore &var_store) const
+  inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const
   {
     return HB_DIRECTION_IS_HORIZONTAL (direction) ?
-           font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) :
-           font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store);
+           font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font) :
+           font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -172,15 +172,12 @@
 
 struct CaretValue
 {
-  inline hb_position_t get_caret_value (hb_font_t *font,
-					hb_direction_t direction,
-					hb_codepoint_t glyph_id,
-					const VariationStore &var_store) const
+  inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
   {
     switch (u.format) {
-    case 1: return u.format1.get_caret_value (font, direction);
+    case 1: return u.format1.get_caret_value (font, direction, glyph_id);
     case 2: return u.format2.get_caret_value (font, direction, glyph_id);
-    case 3: return u.format3.get_caret_value (font, direction, var_store);
+    case 3: return u.format3.get_caret_value (font, direction, glyph_id);
     default:return 0;
     }
   }
@@ -213,7 +210,6 @@
   inline unsigned int get_lig_carets (hb_font_t *font,
 				      hb_direction_t direction,
 				      hb_codepoint_t glyph_id,
-				      const VariationStore &var_store,
 				      unsigned int start_offset,
 				      unsigned int *caret_count /* IN/OUT */,
 				      hb_position_t *caret_array /* OUT */) const
@@ -222,7 +218,7 @@
       const OffsetTo<CaretValue> *array = carets.sub_array (start_offset, caret_count);
       unsigned int count = *caret_count;
       for (unsigned int i = 0; i < count; i++)
-	caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id, var_store);
+	caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id);
     }
 
     return carets.len;
@@ -248,7 +244,6 @@
   inline unsigned int get_lig_carets (hb_font_t *font,
 				      hb_direction_t direction,
 				      hb_codepoint_t glyph_id,
-				      const VariationStore &var_store,
 				      unsigned int start_offset,
 				      unsigned int *caret_count /* IN/OUT */,
 				      hb_position_t *caret_array /* OUT */) const
@@ -261,7 +256,7 @@
       return 0;
     }
     const LigGlyph &lig_glyph = this+ligGlyph[index];
-    return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array);
+    return lig_glyph.get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -295,7 +290,7 @@
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
-  ArrayOf<LOffsetTo<Coverage> >
+  ArrayOf<OffsetTo<Coverage, ULONG> >
 		coverage;		/* Array of long offsets to mark set
 					 * coverage tables */
   public:
@@ -372,17 +367,11 @@
 				      unsigned int start_offset,
 				      unsigned int *caret_count /* IN/OUT */,
 				      hb_position_t *caret_array /* OUT */) const
-  { return (this+ligCaretList).get_lig_carets (font,
-					       direction, glyph_id, get_var_store(),
-					       start_offset, caret_count, caret_array); }
+  { return (this+ligCaretList).get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); }
 
-  inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; }
+  inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef[0] != 0; }
   inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
-  { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); }
-
-  inline bool has_var_store (void) const { return version.to_int () >= 0x00010003u && varStore != 0; }
-  inline const VariationStore &get_var_store (void) const
-  { return version.to_int () >= 0x00010003u ? this+varStore : Null(VariationStore); }
+  { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -393,10 +382,10 @@
 		  attachList.sanitize (c, this) &&
 		  ligCaretList.sanitize (c, this) &&
 		  markAttachClassDef.sanitize (c, this) &&
-		  (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
-		  (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
+		  (version.to_int () < 0x00010002u || markGlyphSetsDef[0].sanitize (c, this)));
   }
 
+
   /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
    * glyph class and other bits, and high 8-bit gthe mark attachment type (if any).
    * Not to be confused with lookup_props which is very similar. */
@@ -421,7 +410,7 @@
 
   protected:
   FixedVersion<>version;		/* Version of the GDEF table--currently
-					 * 0x00010003u */
+					 * 0x00010002u */
   OffsetTo<ClassDef>
 		glyphClassDef;		/* Offset to class definition table
 					 * for glyph type--from beginning of
@@ -439,17 +428,12 @@
 					 * mark attachment type--from beginning
 					 * of GDEF header (may be Null) */
   OffsetTo<MarkGlyphSets>
-		markGlyphSetsDef;	/* Offset to the table of mark set
+		markGlyphSetsDef[VAR];	/* Offset to the table of mark set
 					 * definitions--from beginning of GDEF
 					 * header (may be NULL).  Introduced
-					 * in version 0x00010002. */
-  LOffsetTo<VariationStore>
-		varStore;		/* Offset to the table of Item Variation
-					 * Store--from beginning of GDEF
-					 * header (may be NULL).  Introduced
-					 * in version 0x00010003. */
+					 * in version 00010002. */
   public:
-  DEFINE_SIZE_MIN (12);
+  DEFINE_SIZE_ARRAY (12, markGlyphSetsDef);
 };
 
 
diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index 952fd60..bbe390c 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -103,16 +103,17 @@
   inline unsigned int get_size (void) const
   { return get_len () * Value::static_size; }
 
-  void apply_value (hb_apply_context_t   *c,
+  void apply_value (hb_font_t            *font,
+		    hb_direction_t        direction,
 		    const void           *base,
 		    const Value          *values,
 		    hb_glyph_position_t  &glyph_pos) const
   {
+    unsigned int x_ppem, y_ppem;
     unsigned int format = *this;
-    if (!format) return;
+    hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (direction);
 
-    hb_font_t *font = c->font;
-    hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction);
+    if (!format) return;
 
     if (format & xPlacement) glyph_pos.x_offset  += font->em_scale_x (get_short (values++));
     if (format & yPlacement) glyph_pos.y_offset  += font->em_scale_y (get_short (values++));
@@ -128,29 +129,27 @@
 
     if (!has_device ()) return;
 
-    bool use_x_device = font->x_ppem || font->num_coords;
-    bool use_y_device = font->y_ppem || font->num_coords;
+    x_ppem = font->x_ppem;
+    y_ppem = font->y_ppem;
 
-    if (!use_x_device && !use_y_device) return;
-
-    const VariationStore &store = c->var_store;
+    if (!x_ppem && !y_ppem) return;
 
     /* pixel -> fractional pixel */
     if (format & xPlaDevice) {
-      if (use_x_device) glyph_pos.x_offset  += (base + get_device (values)).get_x_delta (font, store);
+      if (x_ppem) glyph_pos.x_offset  += (base + get_device (values)).get_x_delta (font);
       values++;
     }
     if (format & yPlaDevice) {
-      if (use_y_device) glyph_pos.y_offset  += (base + get_device (values)).get_y_delta (font, store);
+      if (y_ppem) glyph_pos.y_offset  += (base + get_device (values)).get_y_delta (font);
       values++;
     }
     if (format & xAdvDevice) {
-      if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font, store);
+      if (horizontal && x_ppem) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font);
       values++;
     }
     if (format & yAdvDevice) {
       /* y_advance values grow downward but font-space grows upward, hence negation */
-      if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font, store);
+      if (!horizontal && y_ppem) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font);
       values++;
     }
   }
@@ -232,12 +231,11 @@
 
 struct AnchorFormat1
 {
-  inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+  inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
 			  hb_position_t *x, hb_position_t *y) const
   {
-    hb_font_t *font = c->font;
-    *x = font->em_scale_x (xCoordinate);
-    *y = font->em_scale_y (yCoordinate);
+      *x = font->em_scale_x (xCoordinate);
+      *y = font->em_scale_y (yCoordinate);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -256,19 +254,18 @@
 
 struct AnchorFormat2
 {
-  inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id,
+  inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id,
 			  hb_position_t *x, hb_position_t *y) const
   {
-    hb_font_t *font = c->font;
-    unsigned int x_ppem = font->x_ppem;
-    unsigned int y_ppem = font->y_ppem;
-    hb_position_t cx, cy;
-    hb_bool_t ret;
+      unsigned int x_ppem = font->x_ppem;
+      unsigned int y_ppem = font->y_ppem;
+      hb_position_t cx, cy;
+      hb_bool_t ret;
 
-    ret = (x_ppem || y_ppem) &&
-	   font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
-    *x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate);
-    *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate);
+      ret = (x_ppem || y_ppem) &&
+             font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
+      *x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate);
+      *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -288,17 +285,16 @@
 
 struct AnchorFormat3
 {
-  inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+  inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
 			  hb_position_t *x, hb_position_t *y) const
   {
-    hb_font_t *font = c->font;
-    *x = font->em_scale_x (xCoordinate);
-    *y = font->em_scale_y (yCoordinate);
+      *x = font->em_scale_x (xCoordinate);
+      *y = font->em_scale_y (yCoordinate);
 
-    if (font->x_ppem || font->num_coords)
-      *x += (this+xDeviceTable).get_x_delta (font, c->var_store);
-    if (font->y_ppem || font->num_coords)
-      *y += (this+yDeviceTable).get_y_delta (font, c->var_store);
+      if (font->x_ppem)
+	*x += (this+xDeviceTable).get_x_delta (font);
+      if (font->y_ppem)
+	*y += (this+yDeviceTable).get_x_delta (font);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -325,14 +321,14 @@
 
 struct Anchor
 {
-  inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id,
+  inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id,
 			  hb_position_t *x, hb_position_t *y) const
   {
     *x = *y = 0;
     switch (u.format) {
-    case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
-    case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
-    case 3: u.format3.get_anchor (c, glyph_id, x, y); return;
+    case 1: u.format1.get_anchor (font, glyph_id, x, y); return;
+    case 2: u.format2.get_anchor (font, glyph_id, x, y); return;
+    case 3: u.format3.get_anchor (font, glyph_id, x, y); return;
     default:						 return;
     }
   }
@@ -374,7 +370,7 @@
   {
     TRACE_SANITIZE (this);
     if (!c->check_struct (this)) return_trace (false);
-    if (unlikely (_hb_unsigned_int_mul_overflows (rows, cols))) return_trace (false);
+    if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return_trace (false);
     unsigned int count = rows * cols;
     if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return_trace (false);
     for (unsigned int i = 0; i < count; i++)
@@ -432,8 +428,8 @@
 
     hb_position_t mark_x, mark_y, base_x, base_y;
 
-    mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
-    glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
+    mark_anchor.get_anchor (c->font, buffer->cur().codepoint, &mark_x, &mark_y);
+    glyph_anchor.get_anchor (c->font, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
 
     hb_glyph_position_t &o = buffer->cur_pos();
     o.x_offset = base_x - mark_x;
@@ -476,7 +472,8 @@
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
-    valueFormat.apply_value (c, this, values, buffer->cur_pos());
+    valueFormat.apply_value (c->font, c->direction, this,
+			     values, buffer->cur_pos());
 
     buffer->idx++;
     return_trace (true);
@@ -526,7 +523,7 @@
 
     if (likely (index >= valueCount)) return_trace (false);
 
-    valueFormat.apply_value (c, this,
+    valueFormat.apply_value (c->font, c->direction, this,
 			     &values[index * valueFormat.get_len ()],
 			     buffer->cur_pos());
 
@@ -643,8 +640,10 @@
         min = mid + 1;
       else
       {
-	valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
-	valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
+	valueFormats[0].apply_value (c->font, c->direction, this,
+				     &record->values[0], buffer->cur_pos());
+	valueFormats[1].apply_value (c->font, c->direction, this,
+				     &record->values[len1], buffer->pos[pos]);
 	if (len2)
 	  pos++;
 	buffer->idx = pos;
@@ -690,7 +689,7 @@
     (this+coverage).add_coverage (c->input);
     unsigned int count = pairSet.len;
     for (unsigned int i = 0; i < count; i++)
-      (this+pairSet[i]).collect_glyphs (c, valueFormat);
+      (this+pairSet[i]).collect_glyphs (c, &valueFormat1);
   }
 
   inline const Coverage &get_coverage (void) const
@@ -709,7 +708,7 @@
     skippy_iter.reset (buffer->idx, 1);
     if (!skippy_iter.next ()) return_trace (false);
 
-    return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
+    return_trace ((this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -718,11 +717,11 @@
 
     if (!c->check_struct (this)) return_trace (false);
 
-    unsigned int len1 = valueFormat[0].get_len ();
-    unsigned int len2 = valueFormat[1].get_len ();
+    unsigned int len1 = valueFormat1.get_len ();
+    unsigned int len2 = valueFormat2.get_len ();
     PairSet::sanitize_closure_t closure = {
       this,
-      valueFormat,
+      &valueFormat1,
       len1,
       1 + len1 + len2
     };
@@ -735,10 +734,10 @@
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
-  ValueFormat	valueFormat[2];		/* [0] Defines the types of data in
+  ValueFormat	valueFormat1;		/* Defines the types of data in
 					 * ValueRecord1--for the first glyph
 					 * in the pair--may be zero (0) */
-					/* [1] Defines the types of data in
+  ValueFormat	valueFormat2;		/* Defines the types of data in
 					 * ValueRecord2--for the second glyph
 					 * in the pair--may be zero (0) */
   OffsetArrayOf<PairSet>
@@ -791,8 +790,10 @@
     if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false);
 
     const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
-    valueFormat1.apply_value (c, this, v, buffer->cur_pos());
-    valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
+    valueFormat1.apply_value (c->font, c->direction, this,
+			      v, buffer->cur_pos());
+    valueFormat2.apply_value (c->font, c->direction, this,
+			      v + len1, buffer->pos[skippy_iter.idx]);
 
     buffer->idx = skippy_iter.idx;
     if (len2)
@@ -930,8 +931,8 @@
     unsigned int j = skippy_iter.idx;
 
     hb_position_t entry_x, entry_y, exit_x, exit_y;
-    (this+this_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
-    (this+next_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
+    (this+this_record.exitAnchor).get_anchor (c->font, buffer->info[i].codepoint, &exit_x, &exit_y);
+    (this+next_record.entryAnchor).get_anchor (c->font, buffer->info[j].codepoint, &entry_x, &entry_y);
 
     hb_glyph_position_t *pos = buffer->pos;
 
@@ -1518,6 +1519,8 @@
     const OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList);
     return_trace (list.sanitize (c, this));
   }
+  public:
+  DEFINE_SIZE_STATIC (10);
 };
 
 
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index 66fcb3f..22031f4 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -41,10 +41,7 @@
   {
     TRACE_CLOSURE (this);
     Coverage::Iter iter;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      /* TODO Switch to range-based API to work around malicious fonts.
-       * https://github.com/behdad/harfbuzz/issues/363 */
+    for (iter.init (this+coverage); iter.more (); iter.next ()) {
       hb_codepoint_t glyph_id = iter.get_glyph ();
       if (c->glyphs->has (glyph_id))
 	c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
@@ -55,10 +52,7 @@
   {
     TRACE_COLLECT_GLYPHS (this);
     Coverage::Iter iter;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      /* TODO Switch to range-based API to work around malicious fonts.
-       * https://github.com/behdad/harfbuzz/issues/363 */
+    for (iter.init (this+coverage); iter.more (); iter.next ()) {
       hb_codepoint_t glyph_id = iter.get_glyph ();
       c->input->add (glyph_id);
       c->output->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
@@ -126,11 +120,7 @@
   {
     TRACE_CLOSURE (this);
     Coverage::Iter iter;
-    unsigned int count = substitute.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+    for (iter.init (this+coverage); iter.more (); iter.next ()) {
       if (c->glyphs->has (iter.get_glyph ()))
 	c->glyphs->add (substitute[iter.get_coverage ()]);
     }
@@ -140,11 +130,7 @@
   {
     TRACE_COLLECT_GLYPHS (this);
     Coverage::Iter iter;
-    unsigned int count = substitute.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+    for (iter.init (this+coverage); iter.more (); iter.next ()) {
       c->input->add (iter.get_glyph ());
       c->output->add (substitute[iter.get_coverage ()]);
     }
@@ -335,11 +321,7 @@
   {
     TRACE_CLOSURE (this);
     Coverage::Iter iter;
-    unsigned int count = sequence.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+    for (iter.init (this+coverage); iter.more (); iter.next ()) {
       if (c->glyphs->has (iter.get_glyph ()))
 	(this+sequence[iter.get_coverage ()]).closure (c);
     }
@@ -457,11 +439,7 @@
   {
     TRACE_CLOSURE (this);
     Coverage::Iter iter;
-    unsigned int count = alternateSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+    for (iter.init (this+coverage); iter.more (); iter.next ()) {
       if (c->glyphs->has (iter.get_glyph ())) {
 	const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
 	unsigned int count = alt_set.len;
@@ -475,11 +453,7 @@
   {
     TRACE_COLLECT_GLYPHS (this);
     Coverage::Iter iter;
-    unsigned int count = alternateSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+    for (iter.init (this+coverage); iter.more (); iter.next ()) {
       c->input->add (iter.get_glyph ());
       const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
       unsigned int count = alt_set.len;
@@ -788,11 +762,7 @@
   {
     TRACE_CLOSURE (this);
     Coverage::Iter iter;
-    unsigned int count = ligatureSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+    for (iter.init (this+coverage); iter.more (); iter.next ()) {
       if (c->glyphs->has (iter.get_glyph ()))
 	(this+ligatureSet[iter.get_coverage ()]).closure (c);
     }
@@ -802,11 +772,7 @@
   {
     TRACE_COLLECT_GLYPHS (this);
     Coverage::Iter iter;
-    unsigned int count = ligatureSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+    for (iter.init (this+coverage); iter.more (); iter.next ()) {
       c->input->add (iter.get_glyph ());
       (this+ligatureSet[iter.get_coverage ()]).collect_glyphs (c);
     }
@@ -957,11 +923,7 @@
 
     const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
     Coverage::Iter iter;
-    count = substitute.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+    for (iter.init (this+coverage); iter.more (); iter.next ()) {
       if (c->glyphs->has (iter.get_glyph ()))
 	c->glyphs->add (substitute[iter.get_coverage ()]);
     }
@@ -1311,6 +1273,8 @@
     const OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupList);
     return_trace (list.sanitize (c, this));
   }
+  public:
+  DEFINE_SIZE_STATIC (10);
 };
 
 
@@ -1321,10 +1285,28 @@
 
   const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef;
   unsigned int count = buffer->len;
+  hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = 0; i < count; i++)
   {
-    _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
-    _hb_glyph_info_clear_lig_props (&buffer->info[i]);
+    unsigned int props = gdef.get_glyph_props (info[i].codepoint);
+    if (!props)
+    {
+      /* Never mark default-ignorables as marks.
+       * They won't get in the way of lookups anyway,
+       * but having them as mark will cause them to be skipped
+       * over if the lookup-flag says so, but at least for the
+       * Mongolian variation selectors, looks like Uniscribe
+       * marks them as non-mark.  Some Mongolian fonts without
+       * GDEF rely on this.  Another notable character that
+       * this applies to is COMBINING GRAPHEME JOINER. */
+      props = (_hb_glyph_info_get_general_category (&info[i]) !=
+	       HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
+	       _hb_glyph_info_is_default_ignorable (&info[i])) ?
+	      HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
+	      HB_OT_LAYOUT_GLYPH_PROPS_MARK;
+    }
+    _hb_glyph_info_set_glyph_props (&info[i], props);
+    _hb_glyph_info_clear_lig_props (&info[i]);
     buffer->info[i].syllable() = 0;
   }
 }
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index b7a0122..997d225 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -469,7 +469,6 @@
   unsigned int lookup_props;
   const GDEF &gdef;
   bool has_glyph_classes;
-  const VariationStore &var_store;
   skipping_iterator_t iter_input, iter_context;
   unsigned int lookup_index;
   unsigned int debug_depth;
@@ -488,7 +487,6 @@
 			lookup_props (0),
 			gdef (*hb_ot_layout_from_face (face)->gdef),
 			has_glyph_classes (gdef.has_glyph_classes ()),
-			var_store (gdef.get_var_store ()),
 			iter_input (),
 			iter_context (),
 			lookup_index ((unsigned int) -1),
@@ -1001,12 +999,8 @@
     end = int (end) + delta;
     if (end <= match_positions[idx])
     {
-      /* End might end up being smaller than match_positions[idx] if the recursed
-       * lookup ended up removing many items, more than we have had matched.
-       * Just never rewind end back and get out of here.
-       * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */
-      end = match_positions[idx];
       /* There can't be any further changes. */
+      assert (end == match_positions[idx]);
       break;
     }
 
@@ -2275,24 +2269,6 @@
   inline const Lookup& get_lookup (unsigned int i) const
   { return (this+lookupList)[i]; }
 
-  inline bool find_variations_index (const int *coords, unsigned int num_coords,
-				     unsigned int *index) const
-  { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
-	   .find_index (coords, num_coords, index); }
-  inline const Feature& get_feature_variation (unsigned int feature_index,
-					       unsigned int variations_index) const
-  {
-    if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
-	version.to_int () >= 0x00010001u)
-    {
-      const Feature *feature = (this+featureVars).find_substitute (variations_index,
-								   feature_index);
-      if (feature)
-        return *feature;
-    }
-    return get_feature (feature_index);
-  }
-
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -2300,8 +2276,7 @@
 		  likely (version.major == 1) &&
 		  scriptList.sanitize (c, this) &&
 		  featureList.sanitize (c, this) &&
-		  lookupList.sanitize (c, this) &&
-		  (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)));
+		  lookupList.sanitize (c, this));
   }
 
   protected:
@@ -2313,13 +2288,8 @@
 		featureList; 	/* FeatureList table */
   OffsetTo<LookupList>
 		lookupList; 	/* LookupList table */
-  LOffsetTo<FeatureVariations>
-		featureVars;	/* Offset to Feature Variations
-				   table--from beginning of table
-				 * (may be NULL).  Introduced
-				 * in version 0x00010001. */
   public:
-  DEFINE_SIZE_MIN (10);
+  DEFINE_SIZE_STATIC (10);
 };
 
 
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index 8c348be..778b2c4 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -34,7 +34,6 @@
 #include "hb-font-private.hh"
 #include "hb-buffer-private.hh"
 #include "hb-set-private.hh"
-#include "hb-open-type-private.hh"
 
 
 /* Private API corresponding to hb-ot-layout.h: */
@@ -125,9 +124,6 @@
   struct GDEF;
   struct GSUB;
   struct GPOS;
-  struct MATH;
-  struct fvar;
-  struct avar;
 }
 
 struct hb_ot_layout_lookup_accelerator_t
@@ -161,11 +157,6 @@
   const struct OT::GSUB *gsub;
   const struct OT::GPOS *gpos;
 
-  /* TODO Move the following out of this struct. */
-  OT::hb_lazy_table_loader_t<struct OT::MATH> math;
-  OT::hb_lazy_table_loader_t<struct OT::fvar> fvar;
-  OT::hb_lazy_table_loader_t<struct OT::avar> avar;
-
   unsigned int gsub_lookup_count;
   unsigned int gpos_lookup_count;
 
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index d7ededd..5cb1491 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -34,10 +34,13 @@
 #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" // Just so we compile it; unused otherwise.
+#include "hb-ot-layout-jstf-table.hh"
 
 #include "hb-ot-map-private.hh"
 
+#include <stdlib.h>
+#include <string.h>
+
 
 HB_SHAPER_DATA_ENSURE_DECLARE(ot, face)
 
@@ -57,10 +60,6 @@
   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);
 
-  layout->math.init (face);
-  layout->fvar.init (face);
-  layout->avar.init (face);
-
   {
     /*
      * The ugly business of blacklisting individual fonts' tables happen here!
@@ -179,10 +178,6 @@
   hb_blob_destroy (layout->gsub_blob);
   hb_blob_destroy (layout->gpos_blob);
 
-  layout->math.fini ();
-  layout->fvar.fini ();
-  layout->avar.fini ();
-
   free (layout);
 }
 
@@ -205,6 +200,7 @@
   return *hb_ot_layout_from_face (face)->gpos;
 }
 
+
 /*
  * GDEF
  */
@@ -556,13 +552,10 @@
 				  unsigned int *lookup_count /* IN/OUT */,
 				  unsigned int *lookup_indexes /* OUT */)
 {
-  return hb_ot_layout_feature_with_variations_get_lookups (face,
-							   table_tag,
-							   feature_index,
-							   HB_OT_LAYOUT_NO_VARIATIONS_INDEX,
-							   start_offset,
-							   lookup_count,
-							   lookup_indexes);
+  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+  const OT::Feature &f = g.get_feature (feature_index);
+
+  return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes);
 }
 
 /**
@@ -813,38 +806,6 @@
 }
 
 
-/* Variations support */
-
-hb_bool_t
-hb_ot_layout_table_find_feature_variations (hb_face_t    *face,
-					    hb_tag_t      table_tag,
-					    const int    *coords,
-					    unsigned int  num_coords,
-					    unsigned int *variations_index /* out */)
-{
-  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
-
-  return g.find_variations_index (coords, num_coords, variations_index);
-}
-
-unsigned int
-hb_ot_layout_feature_with_variations_get_lookups (hb_face_t    *face,
-						  hb_tag_t      table_tag,
-						  unsigned int  feature_index,
-						  unsigned int  variations_index,
-						  unsigned int  start_offset,
-						  unsigned int *lookup_count /* IN/OUT */,
-						  unsigned int *lookup_indexes /* OUT */)
-{
-  ASSERT_STATIC (OT::FeatureVariations::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_VARIATIONS_INDEX);
-  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
-
-  const OT::Feature &f = g.get_feature_variation (feature_index, variations_index);
-
-  return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes);
-}
-
-
 /*
  * OT::GSUB
  */
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index 9861f0f..eb23d45 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -95,7 +95,6 @@
 #define HB_OT_LAYOUT_NO_SCRIPT_INDEX		0xFFFFu
 #define HB_OT_LAYOUT_NO_FEATURE_INDEX		0xFFFFu
 #define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX	0xFFFFu
-#define HB_OT_LAYOUT_NO_VARIATIONS_INDEX	0xFFFFFFFFu
 
 HB_EXTERN unsigned int
 hb_ot_layout_table_get_script_tags (hb_face_t    *face,
@@ -237,24 +236,6 @@
 					 void         *user_data);
 #endif
 
-/* Variations support */
-
-HB_EXTERN hb_bool_t
-hb_ot_layout_table_find_feature_variations (hb_face_t    *face,
-					    hb_tag_t      table_tag,
-					    const int    *coords,
-					    unsigned int  num_coords,
-					    unsigned int *variations_index /* out */);
-
-HB_EXTERN unsigned int
-hb_ot_layout_feature_with_variations_get_lookups (hb_face_t    *face,
-						  hb_tag_t      table_tag,
-						  unsigned int  feature_index,
-						  unsigned int  variations_index,
-						  unsigned int  start_offset,
-						  unsigned int *lookup_count /* IN/OUT */,
-						  unsigned int *lookup_indexes /* OUT */);
-
 
 /*
  * GSUB
diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index 0395c9c..8692caa 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -139,6 +139,12 @@
 
   private:
 
+  HB_INTERNAL void add_lookups (hb_face_t    *face,
+				unsigned int  table_index,
+				unsigned int  feature_index,
+				hb_mask_t     mask,
+				bool          auto_zwj);
+
   hb_mask_t global_mask;
 
   hb_prealloced_array_t<feature_map_t, 8> features;
@@ -176,9 +182,7 @@
   inline void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func)
   { add_pause (1, pause_func); }
 
-  HB_INTERNAL void compile (hb_ot_map_t  &m,
-			    const int    *coords,
-			    unsigned int  num_coords);
+  HB_INTERNAL void compile (struct hb_ot_map_t &m);
 
   inline void finish (void) {
     feature_infos.finish ();
@@ -190,14 +194,6 @@
 
   private:
 
-  HB_INTERNAL void add_lookups (hb_ot_map_t  &m,
-				hb_face_t    *face,
-				unsigned int  table_index,
-				unsigned int  feature_index,
-				unsigned int  variations_index,
-				hb_mask_t     mask,
-				bool          auto_zwj);
-
   struct feature_info_t {
     hb_tag_t tag;
     unsigned int seq; /* sequence#, used for stable sorting only */
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index 9b331d5..17e3f40 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -31,12 +31,43 @@
 #include "hb-ot-layout-private.hh"
 
 
-void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const
+void
+hb_ot_map_t::add_lookups (hb_face_t    *face,
+			  unsigned int  table_index,
+			  unsigned int  feature_index,
+			  hb_mask_t     mask,
+			  bool          auto_zwj)
 {
-  for (unsigned int i = 0; i < lookups[table_index].len; i++)
-    hb_set_add (lookups_out, lookups[table_index][i].index);
-}
+  unsigned int lookup_indices[32];
+  unsigned int offset, len;
+  unsigned int table_lookup_count;
 
+  table_lookup_count = hb_ot_layout_table_get_lookup_count (face, table_tags[table_index]);
+
+  offset = 0;
+  do {
+    len = ARRAY_LENGTH (lookup_indices);
+    hb_ot_layout_feature_get_lookups (face,
+				      table_tags[table_index],
+				      feature_index,
+				      offset, &len,
+				      lookup_indices);
+
+    for (unsigned int i = 0; i < len; i++)
+    {
+      if (lookup_indices[i] >= table_lookup_count)
+	continue;
+      hb_ot_map_t::lookup_map_t *lookup = lookups[table_index].push ();
+      if (unlikely (!lookup))
+        return;
+      lookup->mask = mask;
+      lookup->index = lookup_indices[i];
+      lookup->auto_zwj = auto_zwj;
+    }
+
+    offset += len;
+  } while (len == ARRAY_LENGTH (lookup_indices));
+}
 
 hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
 					  const hb_segment_properties_t *props_)
@@ -78,48 +109,13 @@
   info->stage[1] = current_stage[1];
 }
 
-void
-hb_ot_map_builder_t::add_lookups (hb_ot_map_t  &m,
-				  hb_face_t    *face,
-				  unsigned int  table_index,
-				  unsigned int  feature_index,
-				  unsigned int  variations_index,
-				  hb_mask_t     mask,
-				  bool          auto_zwj)
+
+void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const
 {
-  unsigned int lookup_indices[32];
-  unsigned int offset, len;
-  unsigned int table_lookup_count;
-
-  table_lookup_count = hb_ot_layout_table_get_lookup_count (face, table_tags[table_index]);
-
-  offset = 0;
-  do {
-    len = ARRAY_LENGTH (lookup_indices);
-    hb_ot_layout_feature_with_variations_get_lookups (face,
-						      table_tags[table_index],
-						      feature_index,
-						      variations_index,
-						      offset, &len,
-						      lookup_indices);
-
-    for (unsigned int i = 0; i < len; i++)
-    {
-      if (lookup_indices[i] >= table_lookup_count)
-	continue;
-      hb_ot_map_t::lookup_map_t *lookup = m.lookups[table_index].push ();
-      if (unlikely (!lookup))
-        return;
-      lookup->mask = mask;
-      lookup->index = lookup_indices[i];
-      lookup->auto_zwj = auto_zwj;
-    }
-
-    offset += len;
-  } while (len == ARRAY_LENGTH (lookup_indices));
+  for (unsigned int i = 0; i < lookups[table_index].len; i++)
+    hb_set_add (lookups_out, lookups[table_index][i].index);
 }
 
-
 void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func)
 {
   stage_info_t *s = stages[table_index].push ();
@@ -132,9 +128,7 @@
 }
 
 void
-hb_ot_map_builder_t::compile (hb_ot_map_t  &m,
-			      const int    *coords,
-			      unsigned int  num_coords)
+hb_ot_map_builder_t::compile (hb_ot_map_t &m)
 {
   m.global_mask = 1;
 
@@ -268,32 +262,23 @@
   {
     /* Collect lookup indices for features */
 
-    unsigned int variations_index;
-    hb_ot_layout_table_find_feature_variations (face,
-						table_tags[table_index],
-						coords,
-						num_coords,
-						&variations_index);
-
     unsigned int stage_index = 0;
     unsigned int last_num_lookups = 0;
     for (unsigned stage = 0; stage < current_stage[table_index]; stage++)
     {
       if (required_feature_index[table_index] != HB_OT_LAYOUT_NO_FEATURE_INDEX &&
 	  required_feature_stage[table_index] == stage)
-	add_lookups (m, face, table_index,
-		     required_feature_index[table_index],
-		     variations_index,
-		     1 /* mask */,
-		     true /* auto_zwj */);
+	m.add_lookups (face, table_index,
+		       required_feature_index[table_index],
+		       1 /* mask */,
+		       true /* auto_zwj */);
 
       for (unsigned i = 0; i < m.features.len; i++)
         if (m.features[i].stage[table_index] == stage)
-	  add_lookups (m, face, table_index,
-		       m.features[i].index[table_index],
-		       variations_index,
-		       m.features[i].mask,
-		       m.features[i].auto_zwj);
+	  m.add_lookups (face, table_index,
+			 m.features[i].index[table_index],
+			 m.features[i].mask,
+			 m.features[i].auto_zwj);
 
       /* Sort lookups and merge duplicates */
       if (last_num_lookups < m.lookups[table_index].len)
diff --git a/src/hb-ot-math-table.hh b/src/hb-ot-math-table.hh
deleted file mode 100644
index 191d79e..0000000
--- a/src/hb-ot-math-table.hh
+++ /dev/null
@@ -1,722 +0,0 @@
-/*
- * 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_MATH_TABLE_HH
-#define HB_OT_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);
-};
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_MATH_TABLE_HH */
diff --git a/src/hb-ot-math.cc b/src/hb-ot-math.cc
deleted file mode 100644
index 2d7e679..0000000
--- a/src/hb-ot-math.cc
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * 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
- */
-
-#include "hb-open-type-private.hh"
-
-#include "hb-ot-math-table.hh"
-
-HB_SHAPER_DATA_ENSURE_DECLARE(ot, face)
-
-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);
-  return *(layout->math.get ());
-}
-
-/*
- * OT::MATH
- */
-
-/**
- * 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.
- *
- * Return value: true if face has a MATH table, 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:
- * @face: a #hb_face_t to test
- * @glyph: a glyph index to test
- *
- * Return value: true if the glyph is an extended shape, 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);
-}
diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h
deleted file mode 100644
index 521a5ca..0000000
--- a/src/hb-ot-math.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * 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 */
diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc
index 56ec5cd..4da8990 100644
--- a/src/hb-ot-shape-complex-arabic.cc
+++ b/src/hb-ot-shape-complex-arabic.cc
@@ -618,7 +618,6 @@
   NULL, /* decompose */
   NULL, /* compose */
   setup_masks_arabic,
-  NULL, /* disable_otl */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
 };
diff --git a/src/hb-ot-shape-complex-default.cc b/src/hb-ot-shape-complex-default.cc
index 42830ab..be60e56 100644
--- a/src/hb-ot-shape-complex-default.cc
+++ b/src/hb-ot-shape-complex-default.cc
@@ -40,7 +40,6 @@
   NULL, /* decompose */
   NULL, /* compose */
   NULL, /* setup_masks */
-  NULL, /* disable_otl */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
 };
diff --git a/src/hb-ot-shape-complex-hangul.cc b/src/hb-ot-shape-complex-hangul.cc
index af50565..5f4d98b 100644
--- a/src/hb-ot-shape-complex-hangul.cc
+++ b/src/hb-ot-shape-complex-hangul.cc
@@ -32,7 +32,7 @@
 
 /* Same order as the feature array below */
 enum {
-  _JMO,
+  NONE,
 
   LJMO,
   VJMO,
@@ -419,7 +419,6 @@
   NULL, /* decompose */
   NULL, /* compose */
   setup_masks_hangul,
-  NULL, /* disable_otl */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
   false, /* fallback_position */
 };
diff --git a/src/hb-ot-shape-complex-hebrew.cc b/src/hb-ot-shape-complex-hebrew.cc
index 96f2494..3215900 100644
--- a/src/hb-ot-shape-complex-hebrew.cc
+++ b/src/hb-ot-shape-complex-hebrew.cc
@@ -154,18 +154,6 @@
   return found;
 }
 
-static bool
-disable_otl_hebrew (const hb_ot_shape_plan_t *plan)
-{
-  /* For Hebrew shaper, use fallback if GPOS does not have 'hebr'
-   * script.  This matches Uniscribe better, and makes fonts like
-   * Arial that have GSUB/GPOS/GDEF but no data for Hebrew work.
-   * See:
-   * https://github.com/behdad/harfbuzz/issues/347#issuecomment-267838368
-   */
-  return plan->map.chosen_script[1] != HB_TAG ('h','e','b','r');
-}
-
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
 {
@@ -180,7 +168,6 @@
   NULL, /* decompose */
   compose_hebrew,
   NULL, /* setup_masks */
-  disable_otl_hebrew,
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
 };
diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index b48fb56..94556f6 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -1713,28 +1713,33 @@
   switch (ab)
   {
     /* Don't decompose these. */
-    case 0x0931u  : return false; /* DEVANAGARI LETTER RRA */
-    case 0x0B94u  : return false; /* TAMIL LETTER AU */
+    case 0x0931u  : return false;
+    case 0x0B94u  : return false;
 
 
     /*
      * Decompose split matras that don't have Unicode decompositions.
      */
 
-    /* Khmer */
+    case 0x0F77u  : *a = 0x0FB2u; *b= 0x0F81u; return true;
+    case 0x0F79u  : *a = 0x0FB3u; *b= 0x0F81u; return true;
     case 0x17BEu  : *a = 0x17C1u; *b= 0x17BEu; return true;
     case 0x17BFu  : *a = 0x17C1u; *b= 0x17BFu; return true;
     case 0x17C0u  : *a = 0x17C1u; *b= 0x17C0u; return true;
     case 0x17C4u  : *a = 0x17C1u; *b= 0x17C4u; return true;
     case 0x17C5u  : *a = 0x17C1u; *b= 0x17C5u; return true;
-
+    case 0x1925u  : *a = 0x1920u; *b= 0x1923u; return true;
+    case 0x1926u  : *a = 0x1920u; *b= 0x1924u; return true;
+    case 0x1B3Cu  : *a = 0x1B42u; *b= 0x1B3Cu; return true;
+    case 0x1112Eu  : *a = 0x11127u; *b= 0x11131u; return true;
+    case 0x1112Fu  : *a = 0x11127u; *b= 0x11132u; return true;
 #if 0
-    /* Gujarati */
     /* This one has no decomposition in Unicode, but needs no decomposition either. */
     /* case 0x0AC9u  : return false; */
-
-    /* Oriya */
     case 0x0B57u  : *a = no decomp, -> RIGHT; return true;
+    case 0x1C29u  : *a = no decomp, -> LEFT; return true;
+    case 0xA9C0u  : *a = no decomp, -> RIGHT; return true;
+    case 0x111BuF  : *a = no decomp, -> ABOVE; return true;
 #endif
   }
 
@@ -1814,7 +1819,6 @@
   decompose_indic,
   compose_indic,
   setup_masks_indic,
-  NULL, /* disable_otl */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
   false, /* fallback_position */
 };
diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc
index bb68622..577d790 100644
--- a/src/hb-ot-shape-complex-myanmar.cc
+++ b/src/hb-ot-shape-complex-myanmar.cc
@@ -521,7 +521,6 @@
   NULL, /* decompose */
   NULL, /* compose */
   NULL, /* setup_masks */
-  NULL, /* disable_otl */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
 };
@@ -539,7 +538,6 @@
   NULL, /* decompose */
   NULL, /* compose */
   setup_masks_myanmar,
-  NULL, /* disable_otl */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
   false, /* fallback_position */
 };
diff --git a/src/hb-ot-shape-complex-private.hh b/src/hb-ot-shape-complex-private.hh
index 39572df..fb0c704 100644
--- a/src/hb-ot-shape-complex-private.hh
+++ b/src/hb-ot-shape-complex-private.hh
@@ -146,14 +146,6 @@
 		       hb_buffer_t              *buffer,
 		       hb_font_t                *font);
 
-  /* disable_otl()
-   * Called during shape().
-   * If set and returns true, GDEF/GSUB/GPOS of the font are ignored
-   * and fallback operations used.
-   * May be NULL.
-   */
-  bool (*disable_otl) (const hb_ot_shape_plan_t *plan);
-
   hb_ot_shape_zero_width_marks_type_t zero_width_marks;
 
   bool fallback_position;
diff --git a/src/hb-ot-shape-complex-thai.cc b/src/hb-ot-shape-complex-thai.cc
index e6f80f5..4322b0d 100644
--- a/src/hb-ot-shape-complex-thai.cc
+++ b/src/hb-ot-shape-complex-thai.cc
@@ -376,7 +376,6 @@
   NULL, /* decompose */
   NULL, /* compose */
   NULL, /* setup_masks */
-  NULL, /* disable_otl */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   false,/* fallback_position */
 };
diff --git a/src/hb-ot-shape-complex-tibetan.cc b/src/hb-ot-shape-complex-tibetan.cc
index aadf59f..a77b531 100644
--- a/src/hb-ot-shape-complex-tibetan.cc
+++ b/src/hb-ot-shape-complex-tibetan.cc
@@ -57,7 +57,6 @@
   NULL, /* decompose */
   NULL, /* compose */
   NULL, /* setup_masks */
-  NULL, /* disable_otl */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
 };
diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc
index af68706..045ead5 100644
--- a/src/hb-ot-shape-complex-use.cc
+++ b/src/hb-ot-shape-complex-use.cc
@@ -559,25 +559,6 @@
 }
 
 static bool
-decompose_use (const hb_ot_shape_normalize_context_t *c,
-                hb_codepoint_t  ab,
-                hb_codepoint_t *a,
-                hb_codepoint_t *b)
-{
-  switch (ab)
-  {
-    /* Chakma:
-     * Special case where the Unicode decomp gives matras in the wrong order
-     * for cluster validation.
-     */
-    case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true;
-    case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true;
-  }
-
-  return (bool) c->unicode->decompose (ab, a, b);
-}
-
-static bool
 compose_use (const hb_ot_shape_normalize_context_t *c,
 	     hb_codepoint_t  a,
 	     hb_codepoint_t  b,
@@ -601,10 +582,9 @@
   NULL, /* preprocess_text */
   NULL, /* postprocess_glyphs */
   HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
-  decompose_use,
+  NULL, /* decompose */
   compose_use,
   setup_masks_use,
-  NULL, /* disable_otl */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
   false, /* fallback_position */
 };
diff --git a/src/hb-ot-shape-private.hh b/src/hb-ot-shape-private.hh
index 594e54c..54ac2c3 100644
--- a/src/hb-ot-shape-private.hh
+++ b/src/hb-ot-shape-private.hh
@@ -77,13 +77,11 @@
 			 map (face, &props) {}
   ~hb_ot_shape_planner_t (void) { map.finish (); }
 
-  inline void compile (hb_ot_shape_plan_t &plan,
-		       const int          *coords,
-		       unsigned int        num_coords)
+  inline void compile (hb_ot_shape_plan_t &plan)
   {
     plan.props = props;
     plan.shaper = shaper;
-    map.compile (plan.map, coords, num_coords);
+    map.compile (plan.map);
 
     plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
     plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 6b38739..7811cb7 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -69,9 +69,6 @@
 {
   hb_ot_map_builder_t *map = &planner->map;
 
-  map->add_global_bool_feature (HB_TAG('r','v','r','n'));
-  map->add_gsub_pause (NULL);
-
   switch (props->direction) {
     case HB_DIRECTION_LTR:
       map->add_global_bool_feature (HB_TAG ('l','t','r','a'));
@@ -166,9 +163,7 @@
 hb_ot_shaper_shape_plan_data_t *
 _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan,
 				      const hb_feature_t *user_features,
-				      unsigned int        num_user_features,
-				      const int          *coords,
-				      unsigned int        num_coords)
+				      unsigned int        num_user_features)
 {
   hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t));
   if (unlikely (!plan))
@@ -178,10 +173,9 @@
 
   planner.shaper = hb_ot_shape_complex_categorize (&planner);
 
-  hb_ot_shape_collect_features (&planner, &shape_plan->props,
-				user_features, num_user_features);
+  hb_ot_shape_collect_features (&planner, &shape_plan->props, user_features, num_user_features);
 
-  planner.compile (*plan, coords, num_coords);
+  planner.compile (*plan);
 
   if (plan->shaper->data_create) {
     plan->data = plan->shaper->data_create (plan);
@@ -218,8 +212,6 @@
   unsigned int        num_user_features;
 
   /* Transient stuff */
-  bool fallback_positioning;
-  bool fallback_glyph_classes;
   hb_direction_t target_direction;
 };
 
@@ -362,18 +354,6 @@
 
   hb_buffer_t *buffer = c->buffer;
 
-  hb_mask_t pre_mask, post_mask;
-  if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
-  {
-    pre_mask = c->plan->numr_mask | c->plan->frac_mask;
-    post_mask = c->plan->frac_mask | c->plan->dnom_mask;
-  }
-  else
-  {
-    pre_mask = c->plan->frac_mask | c->plan->dnom_mask;
-    post_mask = c->plan->numr_mask | c->plan->frac_mask;
-  }
-
   /* TODO look in pre/post context text also. */
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
@@ -392,10 +372,10 @@
         end++;
 
       for (unsigned int j = start; j < i; j++)
-        info[j].mask |= pre_mask;
+        info[j].mask |= c->plan->numr_mask | c->plan->frac_mask;
       info[i].mask |= c->plan->frac_mask;
       for (unsigned int j = i + 1; j < end; j++)
-        info[j].mask |= post_mask;
+        info[j].mask |= c->plan->frac_mask | c->plan->dnom_mask;
 
       i = end - 1;
     }
@@ -544,32 +524,6 @@
 }
 
 static inline void
-hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
-{
-  unsigned int count = c->buffer->len;
-  hb_glyph_info_t *info = c->buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-  {
-    hb_ot_layout_glyph_props_flags_t klass;
-
-    /* Never mark default-ignorables as marks.
-     * They won't get in the way of lookups anyway,
-     * but having them as mark will cause them to be skipped
-     * over if the lookup-flag says so, but at least for the
-     * Mongolian variation selectors, looks like Uniscribe
-     * marks them as non-mark.  Some Mongolian fonts without
-     * GDEF rely on this.  Another notable character that
-     * this applies to is COMBINING GRAPHEME JOINER. */
-    klass = (_hb_glyph_info_get_general_category (&info[i]) !=
-	     HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
-	     _hb_glyph_info_is_default_ignorable (&info[i])) ?
-	    HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
-	    HB_OT_LAYOUT_GLYPH_PROPS_MARK;
-    _hb_glyph_info_set_glyph_props (&info[i], klass);
-  }
-}
-
-static inline void
 hb_ot_substitute_default (hb_ot_shape_context_t *c)
 {
   hb_buffer_t *buffer = c->buffer;
@@ -585,7 +539,7 @@
   hb_ot_shape_setup_masks (c);
 
   /* This is unfortunate to go here, but necessary... */
-  if (c->fallback_positioning)
+  if (!hb_ot_layout_has_positioning (c->face))
     _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, buffer);
 
   hb_ot_map_glyphs_fast (buffer);
@@ -600,9 +554,6 @@
 
   hb_ot_layout_substitute_start (c->font, buffer);
 
-  if (!hb_ot_layout_has_glyph_classes (c->face))
-    hb_synthesize_glyph_classes (c);
-
   c->plan->substitute (c->font, buffer);
 
   return;
@@ -681,12 +632,14 @@
     _hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer);
 }
 
-static inline void
+static inline bool
 hb_ot_position_complex (hb_ot_shape_context_t *c)
 {
   hb_ot_layout_position_start (c->font, c->buffer);
 
+  bool ret = false;
   unsigned int count = c->buffer->len;
+  bool has_positioning = (bool) hb_ot_layout_has_positioning (c->face);
 
   /* If the font has no GPOS, AND, no fallback positioning will
    * happen, AND, direction is forward, then when zeroing mark
@@ -697,9 +650,8 @@
    * If fallback positinoing happens or GPOS is present, we don't
    * care.
    */
-  bool adjust_offsets_when_zeroing = c->fallback_positioning &&
-				     !c->plan->shaper->fallback_position &&
-				     HB_DIRECTION_IS_FORWARD (c->buffer->props.direction);
+  bool adjust_offsets_when_zeroing = !(has_positioning || c->plan->shaper->fallback_position ||
+                                       HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction));
 
   switch (c->plan->shaper->zero_width_marks)
   {
@@ -713,7 +665,7 @@
       break;
   }
 
-  if (likely (!c->fallback_positioning))
+  if (has_positioning)
   {
     hb_glyph_info_t *info = c->buffer->info;
     hb_glyph_position_t *pos = c->buffer->pos;
@@ -736,6 +688,7 @@
 					  &pos[i].x_offset,
 					  &pos[i].y_offset);
 
+    ret = true;
   }
 
   switch (c->plan->shaper->zero_width_marks)
@@ -754,6 +707,8 @@
   hb_ot_layout_position_finish_advances (c->font, c->buffer);
   hb_ot_zero_width_default_ignorables (c);
   hb_ot_layout_position_finish_offsets (c->font, c->buffer);
+
+  return ret;
 }
 
 static inline void
@@ -763,9 +718,9 @@
 
   hb_ot_position_default (c);
 
-  hb_ot_position_complex (c);
+  hb_bool_t fallback = !hb_ot_position_complex (c);
 
-  if (c->fallback_positioning && c->plan->shaper->fallback_position)
+  if (fallback && c->plan->shaper->fallback_position)
     _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer);
 
   if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
@@ -773,7 +728,7 @@
 
   /* Visual fallback goes here. */
 
-  if (c->fallback_positioning)
+  if (fallback)
     _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
 
   _hb_buffer_deallocate_gsubgpos_vars (c->buffer);
@@ -793,11 +748,6 @@
 			      (unsigned) HB_BUFFER_MAX_LEN_MIN);
   }
 
-  bool disable_otl = c->plan->shaper->disable_otl && c->plan->shaper->disable_otl (c->plan);
-  //c->fallback_substitute     = disable_otl || !hb_ot_layout_has_substitution (c->face);
-  c->fallback_positioning    = disable_otl || !hb_ot_layout_has_positioning (c->face);
-  c->fallback_glyph_classes  = disable_otl || !hb_ot_layout_has_glyph_classes (c->face);
-
   /* Save the original direction, we use it later. */
   c->target_direction = c->buffer->props.direction;
 
diff --git a/src/hb-ot-tag.cc b/src/hb-ot-tag.cc
index 9b0db50..5f21ac0 100644
--- a/src/hb-ot-tag.cc
+++ b/src/hb-ot-tag.cc
@@ -28,6 +28,9 @@
 
 #include "hb-private.hh"
 
+#include <string.h>
+
+
 
 /* hb_script_t */
 
@@ -198,7 +201,6 @@
   {"alt",	HB_TAG('A','L','T',' ')},	/* [Southern] Altai */
   {"am",	HB_TAG('A','M','H',' ')},	/* Amharic */
   {"amf",	HB_TAG('H','B','N',' ')},	/* Hammer-Banna */
-  {"amw",	HB_TAG('S','Y','R',' ')},	/* Western Neo-Aramaic */
   {"an",	HB_TAG('A','R','G',' ')},	/* Aragonese */
   {"ang",	HB_TAG('A','N','G',' ')},	/* Old English (ca. 450-1100) */
   {"ar",	HB_TAG('A','R','A',' ')},	/* Arabic [macrolanguage] */
@@ -237,7 +239,6 @@
   {"bg",	HB_TAG('B','G','R',' ')},	/* Bulgarian */
   {"bgc",	HB_TAG('B','G','C',' ')},	/* Haryanvi */
   {"bgq",	HB_TAG('B','G','Q',' ')},	/* Bagri */
-  {"bgr",	HB_TAG('Q','I','N',' ')},	/* Bawm Chin */
   {"bhb",	HB_TAG('B','H','I',' ')},	/* Bhili */
   {"bhk",	HB_TAG('B','I','K',' ')},	/* Albay Bicolano (retired code) */
   {"bho",	HB_TAG('B','H','O',' ')},	/* Bhojpuri */
@@ -269,10 +270,8 @@
   {"ca",	HB_TAG('C','A','T',' ')},	/* Catalan */
   {"cak",	HB_TAG('C','A','K',' ')},	/* Kaqchikel */
   {"cbk",	HB_TAG('C','B','K',' ')},	/* Chavacano */
-  {"cbl",	HB_TAG('Q','I','N',' ')},	/* Bualkhaw Chin */
   {"ce",	HB_TAG('C','H','E',' ')},	/* Chechen */
   {"ceb",	HB_TAG('C','E','B',' ')},	/* Cebuano */
-  {"cfm",	HB_TAG('H','A','L',' ')},	/* Halam/Falam Chin */
   {"cgg",	HB_TAG('C','G','G',' ')},	/* Chiga */
   {"ch",	HB_TAG('C','H','A',' ')},	/* Chamorro */
   {"chk",	HB_TAG('C','H','K','0')},	/* Chuukese */
@@ -280,17 +279,8 @@
   {"chp",	HB_TAG('C','H','P',' ')},	/* Chipewyan */
   {"chr",	HB_TAG('C','H','R',' ')},	/* Cherokee */
   {"chy",	HB_TAG('C','H','Y',' ')},	/* Cheyenne */
-  {"cja",	HB_TAG('C','J','A',' ')},	/* Western Cham */
-  {"cjm",	HB_TAG('C','J','M',' ')},	/* Eastern Cham */
-  {"cka",	HB_TAG('Q','I','N',' ')},	/* Khumi Awa Chin */
   {"ckb",	HB_TAG('K','U','R',' ')},	/* Central Kurdish (Sorani) */
   {"ckt",	HB_TAG('C','H','K',' ')},	/* Chukchi */
-  {"cld",	HB_TAG('S','Y','R',' ')},	/* Chaldean Neo-Aramaic */
-  {"cmr",	HB_TAG('Q','I','N',' ')},	/* Mro-Khimi Chin */
-  {"cnb",	HB_TAG('Q','I','N',' ')},	/* Chinbon Chin */
-  {"cnh",	HB_TAG('Q','I','N',' ')},	/* Hakha Chin */
-  {"cnk",	HB_TAG('Q','I','N',' ')},	/* Khumi Chin */
-  {"cnw",	HB_TAG('Q','I','N',' ')},	/* Ngawn Chin */
   {"cop",	HB_TAG('C','O','P',' ')},	/* Coptic */
   {"cpp",	HB_TAG('C','P','P',' ')},	/* Creoles */
   {"cr",	HB_TAG('C','R','E',' ')},	/* Cree */
@@ -303,9 +293,6 @@
   {"crx",	HB_TAG('C','R','R',' ')},	/* Carrier */
   {"cs",	HB_TAG('C','S','Y',' ')},	/* Czech */
   {"csb",	HB_TAG('C','S','B',' ')},	/* Kashubian */
-  {"csh",	HB_TAG('Q','I','N',' ')},	/* Asho Chin */
-  {"csy",	HB_TAG('Q','I','N',' ')},	/* Siyin Chin */
-  {"ctd",	HB_TAG('Q','I','N',' ')},	/* Tedim Chin */
   {"ctg",	HB_TAG('C','T','G',' ')},	/* Chittagonian */
   {"cts",	HB_TAG('B','I','K',' ')},	/* Northern Catanduanes Bikol */
   {"cu",	HB_TAG('C','S','L',' ')},	/* Church Slavic */
@@ -313,9 +300,7 @@
   {"cv",	HB_TAG('C','H','U',' ')},	/* Chuvash */
   {"cwd",	HB_TAG('D','C','R',' ')},	/* Woods Cree */
   {"cy",	HB_TAG('W','E','L',' ')},	/* Welsh */
-  {"czt",	HB_TAG('Q','I','N',' ')},	/* Zotung Chin */
   {"da",	HB_TAG('D','A','N',' ')},	/* Danish */
-  {"dao",	HB_TAG('Q','I','N',' ')},	/* Daai Chin */
   {"dap",	HB_TAG('N','I','S',' ')},	/* Nisi (India) */
   {"dar",	HB_TAG('D','A','R',' ')},	/* Dargwa */
   {"dax",	HB_TAG('D','A','X',' ')},	/* Dayi */
@@ -358,7 +343,7 @@
   {"fi",	HB_TAG('F','I','N',' ')},	/* Finnish */
   {"fil",	HB_TAG('P','I','L',' ')},	/* Filipino */
   {"fj",	HB_TAG('F','J','I',' ')},	/* Fijian */
-  {"flm",	HB_TAG('H','A','L',' ')},	/* Halam/Falam Chin [retired ISO639 code] */
+  {"flm",	HB_TAG('H','A','L',' ')},	/* Halam */
   {"fo",	HB_TAG('F','O','S',' ')},	/* Faroese */
   {"fon",	HB_TAG('F','O','N',' ')},	/* Fon */
   {"fr",	HB_TAG('F','R','A',' ')},	/* French */
@@ -405,7 +390,6 @@
   {"he",	HB_TAG('I','W','R',' ')},	/* Hebrew */
   {"hi",	HB_TAG('H','I','N',' ')},	/* Hindi */
   {"hil",	HB_TAG('H','I','L',' ')},	/* Hiligaynon */
-  {"hlt",	HB_TAG('Q','I','N',' ')},	/* Matu Chin */
   {"hmn",	HB_TAG('H','M','N',' ')},	/* Hmong */
   {"hnd",	HB_TAG('H','N','D',' ')},	/* [Southern] Hindko */
   {"hne",	HB_TAG('C','H','H',' ')},	/* Chattisgarhi */
@@ -569,7 +553,6 @@
   {"mos",	HB_TAG('M','O','S',' ')},	/* Mossi */
   {"mpe",	HB_TAG('M','A','J',' ')},	/* Majang */
   {"mr",	HB_TAG('M','A','R',' ')},	/* Marathi */
-  {"mrh",	HB_TAG('Q','I','N',' ')},	/* Mara Chin */
   {"mrj",	HB_TAG('H','M','A',' ')},	/* High Mari */
   {"ms",	HB_TAG('M','L','Y',' ')},	/* Malay [macrolanguage] */
   {"msc",	HB_TAG('M','N','K',' ')},	/* Sankaran Maninka */
@@ -634,7 +617,6 @@
   {"pcc",	HB_TAG('P','C','C',' ')},	/* Bouyei */
   {"pcd",	HB_TAG('P','C','D',' ')},	/* Picard */
   {"pce",	HB_TAG('P','L','G',' ')},	/* [Ruching] Palaung */
-  {"pck",	HB_TAG('Q','I','N',' ')},	/* Paite Chin */
   {"pdc",	HB_TAG('P','D','C',' ')},	/* Pennsylvania German */
   {"pes",	HB_TAG('F','A','R',' ')},	/* Iranian Persian */
   {"phk",	HB_TAG('P','H','K',' ')},	/* Phake */
@@ -692,7 +674,6 @@
   {"se",	HB_TAG('N','S','M',' ')},	/* Northern Sami */
   {"seh",	HB_TAG('S','N','A',' ')},	/* Sena */
   {"sel",	HB_TAG('S','E','L',' ')},	/* Selkup */
-  {"sez",	HB_TAG('Q','I','N',' ')},	/* Senthang Chin */
   {"sg",	HB_TAG('S','G','O',' ')},	/* Sango */
   {"sga",	HB_TAG('S','G','A',' ')},	/* Old Irish (to 900) */
   {"sgs",	HB_TAG('S','G','S',' ')},	/* Samogitian */
@@ -732,15 +713,12 @@
   {"swh",	HB_TAG('S','W','K',' ')},	/* Kiswahili/Swahili */
   {"swv",	HB_TAG('M','A','W',' ')},	/* Shekhawati */
   {"sxu",	HB_TAG('S','X','U',' ')},	/* Upper Saxon */
-  {"syc",	HB_TAG('S','Y','R',' ')},	/* Classical Syriac */
   {"syl",	HB_TAG('S','Y','L',' ')},	/* Sylheti */
   {"syr",	HB_TAG('S','Y','R',' ')},	/* Syriac [macrolanguage] */
   {"szl",	HB_TAG('S','Z','L',' ')},	/* Silesian */
   {"ta",	HB_TAG('T','A','M',' ')},	/* Tamil */
   {"tab",	HB_TAG('T','A','B',' ')},	/* Tabasaran */
-  {"tcp",	HB_TAG('Q','I','N',' ')},	/* Tawr Chin */
   {"tcy",	HB_TAG('T','U','L',' ')},	/* Tulu */
-  {"tcz",	HB_TAG('Q','I','N',' ')},	/* Thado Chin */
   {"tdd",	HB_TAG('T','D','D',' ')},	/* Tai Nüa */
   {"te",	HB_TAG('T','E','L',' ')},	/* Telugu */
   {"tem",	HB_TAG('T','M','N',' ')},	/* Temne */
@@ -808,13 +786,11 @@
   {"yap",	HB_TAG('Y','A','P',' ')},	/* Yapese */
   {"yi",	HB_TAG('J','I','I',' ')},	/* Yiddish [macrolanguage] */
   {"yo",	HB_TAG('Y','B','A',' ')},	/* Yoruba */
-  {"yos",	HB_TAG('Q','I','N',' ')},	/* Yos, deprecated by IANA in favor of Zou [zom] */
   {"yso",	HB_TAG('N','I','S',' ')},	/* Nisi (China) */
   {"za",	HB_TAG('Z','H','A',' ')},	/* Chuang/Zhuang [macrolanguage] */
   {"zea",	HB_TAG('Z','E','A',' ')},	/* Zeeuws */
   {"zgh",	HB_TAG('Z','G','H',' ')},	/* Standard Morrocan Tamazigh */
   {"zne",	HB_TAG('Z','N','D',' ')},	/* Zande */
-  {"zom",	HB_TAG('Q','I','N',' ')},	/* Zou */
   {"zu",	HB_TAG('Z','U','L',' ')}, 	/* Zulu */
   {"zum",	HB_TAG('L','R','C',' ')},	/* Kumzari */
   {"zza",	HB_TAG('Z','Z','A',' ')},	/* Zazaki */
@@ -931,30 +907,6 @@
     return HB_TAG('A','P','P','H');  /* Phonetic transcription—Americanist conventions */
   }
 
-  /*
-   * "Syre" is a BCP-47 script tag, meaning the Estrangela variant of the Syriac script.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-syre")) {
-    return HB_TAG('S','Y','R','E');  /* Estrangela Syriac */
-  }
-
-  /*
-   * "Syrj" is a BCP-47 script tag, meaning the Western variant of the Syriac script.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-syrj")) {
-    return HB_TAG('S','Y','R','J');  /* Western Syriac */
-  }
-
-  /*
-   * "Syrn" is a BCP-47 script tag, meaning the Eastern variant of the Syriac script.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-syrn")) {
-    return HB_TAG('S','Y','R','N');  /* Eastern Syriac */
-  }
-
   /* Find a language matching in the first component */
   {
     const LangTag *lang_tag;
@@ -1010,22 +962,6 @@
   if (tag == HB_OT_TAG_DEFAULT_LANGUAGE)
     return NULL;
 
-  /* struct LangTag has only room for 3-letter language tags. */
-  switch (tag) {
-  case HB_TAG('A','P','P','H'):  /* Phonetic transcription—Americanist conventions */
-    return hb_language_from_string ("und-fonnapa", -1);
-  case HB_TAG('I','P','P','H'):  /* Phonetic transcription—IPA conventions */
-    return hb_language_from_string ("und-fonipa", -1);
-  case HB_TAG('S','Y','R',' '):  /* Syriac [macrolanguage] */
-    return hb_language_from_string ("syr", -1);
-  case HB_TAG('S','Y','R','E'):  /* Estrangela Syriac */
-    return hb_language_from_string ("und-Syre", -1);
-  case HB_TAG('S','Y','R','J'):  /* Western Syriac */
-    return hb_language_from_string ("und-Syrj", -1);
-  case HB_TAG('S','Y','R','N'):  /* Eastern Syriac */
-    return hb_language_from_string ("und-Syrn", -1);
-  }
-
   for (i = 0; i < ARRAY_LENGTH (ot_languages); i++)
     if (ot_languages[i].tag == tag)
       return hb_language_from_string (ot_languages[i].language, -1);
@@ -1040,6 +976,14 @@
     }
   }
 
+  /* struct LangTag has only room for 3-letter language tags. */
+  switch (tag) {
+  case HB_TAG('A','P','P','H'):  /* Phonetic transcription—Americanist conventions */
+    return hb_language_from_string ("und-fonnapa", -1);
+  case HB_TAG('I','P','P','H'):  /* Phonetic transcription—IPA conventions */
+    return hb_language_from_string ("und-fonipa", -1);
+  }
+
   /* Else return a custom language in the form of "x-hbotABCD" */
   {
     unsigned char buf[11] = "x-hbot";
diff --git a/src/hb-ot-var-avar-table.hh b/src/hb-ot-var-avar-table.hh
deleted file mode 100644
index ace0f5f..0000000
--- a/src/hb-ot-var-avar-table.hh
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_VAR_AVAR_TABLE_HH
-#define HB_OT_VAR_AVAR_TABLE_HH
-
-#include "hb-open-type-private.hh"
-
-namespace OT {
-
-
-struct AxisValueMap
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  public:
-  F2DOT14	fromCoord;	/* A normalized coordinate value obtained using
-				 * default normalization. */
-  F2DOT14	toCoord;	/* The modified, normalized coordinate value. */
-
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-struct SegmentMaps : ArrayOf<AxisValueMap>
-{
-  inline int map (int value) const
-  {
-    /* The following special-cases are not part of OpenType, which requires
-     * that at least -1, 0, and +1 must be mapped. But we include these as
-     * part of a better error recovery scheme. */
-
-    if (!len)
-      return value;
-
-    if (value <= array[0].fromCoord)
-      return value - array[0].fromCoord + array[0].toCoord;
-
-    unsigned int i;
-    unsigned int count = len;
-    for (i = 1; i < count && value > array[i].fromCoord; i++)
-      ;
-
-    if (value >= array[i].fromCoord)
-      return value - array[i].fromCoord + array[i].toCoord;
-
-    if (unlikely (array[i-1].fromCoord == array[i].fromCoord))
-      return array[i-1].toCoord;
-
-    int denom = array[i].fromCoord - array[i-1].fromCoord;
-    return array[i-1].toCoord +
-	   (array[i].toCoord - array[i-1].toCoord) *
-	   (value - array[i-1].fromCoord + denom/2) / denom;
-  }
-
-  DEFINE_SIZE_ARRAY (2, array);
-};
-
-/*
- * avar — Axis Variations Table
- */
-
-#define HB_OT_TAG_avar HB_TAG('a','v','a','r')
-
-struct avar
-{
-  static const hb_tag_t tableTag	= HB_OT_TAG_avar;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!(version.sanitize (c) &&
-		    version.major == 1 &&
-		    c->check_struct (this))))
-      return_trace (false);
-
-    const SegmentMaps *map = &axisSegmentMapsZ;
-    unsigned int count = axisCount;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (unlikely (!map->sanitize (c)))
-        return_trace (false);
-      map = &StructAfter<SegmentMaps> (*map);
-    }
-
-    return_trace (true);
-  }
-
-  inline void map_coords (int *coords, unsigned int coords_length) const
-  {
-    unsigned int count = MIN<unsigned int> (coords_length, axisCount);
-
-    const SegmentMaps *map = &axisSegmentMapsZ;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      coords[i] = map->map (coords[i]);
-      map = &StructAfter<SegmentMaps> (*map);
-    }
-  }
-
-  protected:
-  FixedVersion<>version;	/* Version of the avar table
-				 * initially set to 0x00010000u */
-  USHORT	reserved;	/* This field is permanently reserved. Set to 0. */
-  USHORT	axisCount;	/* The number of variation axes in the font. This
-				 * must be the same number as axisCount in the
-				 * 'fvar' table. */
-  SegmentMaps	axisSegmentMapsZ;
-
-  public:
-  DEFINE_SIZE_MIN (8);
-};
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_VAR_AVAR_TABLE_HH */
diff --git a/src/hb-ot-var-fvar-table.hh b/src/hb-ot-var-fvar-table.hh
deleted file mode 100644
index 9f6fb32..0000000
--- a/src/hb-ot-var-fvar-table.hh
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_VAR_FVAR_TABLE_HH
-#define HB_OT_VAR_FVAR_TABLE_HH
-
-#include "hb-open-type-private.hh"
-
-namespace OT {
-
-
-struct InstanceRecord
-{
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  c->check_array (coordinates, coordinates[0].static_size, axis_count));
-  }
-
-  protected:
-  USHORT	subfamilyNameID;/* The name ID for entries in the 'name' table
-				 * that provide subfamily names for this instance. */
-  USHORT	reserved;	/* Reserved for future use — set to 0. */
-  Fixed		coordinates[VAR];/* The coordinates array for this instance. */
-  //USHORT	postScriptNameIDX;/*Optional. The name ID for entries in the 'name'
-  //				  * table that provide PostScript names for this
-  //				  * instance. */
-
-  public:
-  DEFINE_SIZE_ARRAY (4, coordinates);
-};
-
-struct AxisRecord
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  public:
-  Tag		axisTag;	/* Tag identifying the design variation for the axis. */
-  Fixed		minValue;	/* The minimum coordinate value for the axis. */
-  Fixed		defaultValue;	/* The default coordinate value for the axis. */
-  Fixed		maxValue;	/* The maximum coordinate value for the axis. */
-  USHORT	reserved;	/* Reserved for future use — set to 0. */
-  USHORT	axisNameID;	/* The name ID for entries in the 'name' table that
-				 * provide a display name for this axis. */
-
-  public:
-  DEFINE_SIZE_STATIC (20);
-};
-
-
-/*
- * fvar — Font Variations Table
- */
-
-#define HB_OT_TAG_fvar HB_TAG('f','v','a','r')
-
-struct fvar
-{
-  static const hb_tag_t tableTag	= HB_OT_TAG_fvar;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-		  likely (version.major == 1) &&
-		  c->check_struct (this) &&
-		  instanceSize >= axisCount * 4 + 4 &&
-		  axisSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */
-		  instanceSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */
-		  c->check_range (this, things) &&
-		  c->check_range (&StructAtOffset<char> (this, things),
-				  axisCount * axisSize + instanceCount * instanceSize));
-  }
-
-  inline unsigned int get_axis_count (void) const
-  { return axisCount; }
-
-  inline bool get_axis (unsigned int index, hb_ot_var_axis_t *info) const
-  {
-    if (unlikely (index >= axisCount))
-      return false;
-
-    if (info)
-    {
-      const AxisRecord &axis = get_axes ()[index];
-      info->tag = axis.axisTag;
-      info->name_id =  axis.axisNameID;
-      info->default_value = axis.defaultValue / 65536.;
-      /* Ensure order, to simplify client math. */
-      info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
-      info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
-    }
-
-    return true;
-  }
-
-  inline unsigned int get_axis_infos (unsigned int      start_offset,
-				      unsigned int     *axes_count /* IN/OUT */,
-				      hb_ot_var_axis_t *axes_array /* OUT */) const
-  {
-    if (axes_count)
-    {
-      unsigned int count = axisCount;
-      start_offset = MIN (start_offset, count);
-
-      count -= start_offset;
-      axes_array += start_offset;
-
-      count = MIN (count, *axes_count);
-      *axes_count = count;
-
-      for (unsigned int i = 0; i < count; i++)
-	get_axis (start_offset + i, axes_array + i);
-    }
-    return axisCount;
-  }
-
-  inline bool find_axis (hb_tag_t tag, unsigned int *index, hb_ot_var_axis_t *info) const
-  {
-    const AxisRecord *axes = get_axes ();
-    unsigned int count = get_axis_count ();
-    for (unsigned int i = 0; i < count; i++)
-      if (axes[i].axisTag == tag)
-      {
-        if (index)
-	  *index = i;
-	return get_axis (i, info);
-      }
-    if (index)
-      *index = HB_OT_VAR_NO_AXIS_INDEX;
-    return false;
-  }
-
-  inline int normalize_axis_value (unsigned int axis_index, float v) const
-  {
-    hb_ot_var_axis_t axis;
-    if (!get_axis (axis_index, &axis))
-      return 0;
-
-    v = MAX (MIN (v, axis.max_value), axis.min_value); /* Clamp. */
-
-    if (v == axis.default_value)
-      return 0;
-    else if (v < axis.default_value)
-      v = (v - axis.default_value) / (axis.default_value - axis.min_value);
-    else
-      v = (v - axis.default_value) / (axis.max_value - axis.default_value);
-    return (int) (v * 16384. + (v >= 0. ? .5 : -.5));
-  }
-
-  protected:
-  inline const AxisRecord * get_axes (void) const
-  { return &StructAtOffset<AxisRecord> (this, things); }
-
-  inline const InstanceRecord * get_instances (void) const
-  { return &StructAtOffset<InstanceRecord> (get_axes () + axisCount, 0); }
-
-  protected:
-  FixedVersion<>version;	/* Version of the fvar table
-				 * initially set to 0x00010000u */
-  Offset<>	things;		/* Offset in bytes from the beginning of the table
-				 * to the start of the AxisRecord array. */
-  USHORT	reserved;	/* This field is permanently reserved. Set to 2. */
-  USHORT	axisCount;	/* The number of variation axes in the font (the
-				 * number of records in the axes array). */
-  USHORT	axisSize;	/* The size in bytes of each VariationAxisRecord —
-				 * set to 20 (0x0014) for this version. */
-  USHORT	instanceCount;	/* The number of named instances defined in the font
-				 * (the number of records in the instances array). */
-  USHORT	instanceSize;	/* The size in bytes of each InstanceRecord — set
-				 * to either axisCount * sizeof(Fixed) + 4, or to
-				 * axisCount * sizeof(Fixed) + 6. */
-
-  public:
-  DEFINE_SIZE_STATIC (16);
-};
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_VAR_FVAR_TABLE_HH */
diff --git a/src/hb-ot-var-hvar-table.hh b/src/hb-ot-var-hvar-table.hh
deleted file mode 100644
index 3a2a820..0000000
--- a/src/hb-ot-var-hvar-table.hh
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_VAR_HVAR_TABLE_HH
-#define HB_OT_VAR_HVAR_TABLE_HH
-
-#include "hb-ot-layout-common-private.hh"
-
-
-namespace OT {
-
-
-struct DeltaSetIndexMap
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  c->check_array (mapData, get_width (), mapCount));
-  }
-
-  unsigned int map (unsigned int v) const /* Returns 16.16 outer.inner. */
-  {
-    /* If count is zero, pass value unchanged.  This takes
-     * care of direct mapping for advance map. */
-    if (!mapCount)
-      return v;
-
-    if (v >= mapCount)
-      v = mapCount - 1;
-
-    unsigned int u = 0;
-    { /* Fetch it. */
-      unsigned int w = get_width ();
-      const BYTE *p = mapData + w * v;
-      for (; w; w--)
-	u = (u << 8) + *p++;
-    }
-
-    { /* Repack it. */
-      unsigned int n = get_inner_bitcount ();
-      unsigned int outer = u >> n;
-      unsigned int inner = u & ((1 << n) - 1);
-      u = (outer<<16) | inner;
-    }
-
-    return u;
-  }
-
-  protected:
-  inline unsigned int get_width (void) const
-  { return ((format >> 4) & 3) + 1; }
-
-  inline unsigned int get_inner_bitcount (void) const
-  { return (format & 0xF) + 1; }
-
-  protected:
-  USHORT format;		/* A packed field that describes the compressed
-				 * representation of delta-set indices. */
-  USHORT mapCount;		/* The number of mapping entries. */
-  BYTE mapData[VAR];		/* The delta-set index mapping data. */
-
-  public:
-  DEFINE_SIZE_ARRAY (4, mapData);
-};
-
-
-/*
- * HVAR -- The Horizontal Metrics Variations Table
- * VVAR -- The Vertical Metrics Variations Table
- */
-
-#define HB_OT_TAG_HVAR HB_TAG('H','V','A','R')
-#define HB_OT_TAG_VVAR HB_TAG('V','V','A','R')
-
-struct HVARVVAR
-{
-  static const hb_tag_t HVARTag	= HB_OT_TAG_HVAR;
-  static const hb_tag_t VVARTag	= HB_OT_TAG_VVAR;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-		  likely (version.major == 1) &&
-		  varStore.sanitize (c, this) &&
-		  advMap.sanitize (c, this) &&
-		  lsbMap.sanitize (c, this) &&
-		  rsbMap.sanitize (c, this));
-  }
-
-  inline float get_advance_var (hb_codepoint_t glyph,
-				int *coords, unsigned int coord_count) const
-  {
-    unsigned int varidx = (this+advMap).map (glyph);
-    return (this+varStore).get_delta (varidx, coords, coord_count);
-  }
-
-  inline bool has_sidebearing_deltas (void) const
-  { return lsbMap && rsbMap; }
-
-  protected:
-  FixedVersion<>version;	/* Version of the metrics variation table
-				 * initially set to 0x00010000u */
-  LOffsetTo<VariationStore>
-		varStore;	/* Offset to item variation store table. */
-  LOffsetTo<DeltaSetIndexMap>
-		advMap;		/* Offset to advance var-idx mapping. */
-  LOffsetTo<DeltaSetIndexMap>
-		lsbMap;		/* Offset to lsb/tsb var-idx mapping. */
-  LOffsetTo<DeltaSetIndexMap>
-		rsbMap;		/* Offset to rsb/bsb var-idx mapping. */
-
-  public:
-  DEFINE_SIZE_STATIC (20);
-};
-
-struct HVAR : HVARVVAR {
-  static const hb_tag_t tableTag	= HB_OT_TAG_HVAR;
-};
-struct VVAR : HVARVVAR {
-  static const hb_tag_t tableTag	= HB_OT_TAG_VVAR;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (static_cast<const HVARVVAR *> (this)->sanitize (c) &&
-		  vorgMap.sanitize (c, this));
-  }
-
-  protected:
-  LOffsetTo<DeltaSetIndexMap>
-		vorgMap;	/* Offset to vertical-origin var-idx mapping. */
-
-  public:
-  DEFINE_SIZE_STATIC (24);
-};
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_VAR_HVAR_TABLE_HH */
diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc
deleted file mode 100644
index d4d16df..0000000
--- a/src/hb-ot-var.cc
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-open-type-private.hh"
-
-#include "hb-ot-layout-private.hh"
-#include "hb-ot-var-avar-table.hh"
-#include "hb-ot-var-fvar-table.hh"
-#include "hb-ot-var.h"
-
-HB_SHAPER_DATA_ENSURE_DECLARE(ot, face)
-
-/*
- * fvar/avar
- */
-
-static inline const OT::fvar&
-_get_fvar (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::fvar);
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  return *(layout->fvar.get ());
-}
-static inline const OT::avar&
-_get_avar (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::avar);
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  return *(layout->avar.get ());
-}
-
-/**
- * hb_ot_var_has_data:
- * @face: #hb_face_t to test
- *
- * This function allows to verify the presence of OpenType variation data on the face.
- * Alternatively, use hb_ot_var_get_axis_count().
- *
- * Return value: true if face has a `fvar' table and false otherwise
- *
- * Since: 1.4.2
- **/
-hb_bool_t
-hb_ot_var_has_data (hb_face_t *face)
-{
-  return &_get_fvar (face) != &OT::Null(OT::fvar);
-}
-
-/**
- * hb_ot_var_get_axis_count:
- *
- * Since: 1.4.2
- **/
-unsigned int
-hb_ot_var_get_axis_count (hb_face_t *face)
-{
-  const OT::fvar &fvar = _get_fvar (face);
-  return fvar.get_axis_count ();
-}
-
-/**
- * hb_ot_var_get_axes:
- *
- * Since: 1.4.2
- **/
-unsigned int
-hb_ot_var_get_axes (hb_face_t        *face,
-		    unsigned int      start_offset,
-		    unsigned int     *axes_count /* IN/OUT */,
-		    hb_ot_var_axis_t *axes_array /* OUT */)
-{
-  const OT::fvar &fvar = _get_fvar (face);
-  return fvar.get_axis_infos (start_offset, axes_count, axes_array);
-}
-
-/**
- * hb_ot_var_find_axis:
- *
- * Since: 1.4.2
- **/
-hb_bool_t
-hb_ot_var_find_axis (hb_face_t        *face,
-		     hb_tag_t          axis_tag,
-		     unsigned int     *axis_index,
-		     hb_ot_var_axis_t *axis_info)
-{
-  const OT::fvar &fvar = _get_fvar (face);
-  return fvar.find_axis (axis_tag, axis_index, axis_info);
-}
-
-
-/**
- * hb_ot_var_normalize_variations:
- *
- * Since: 1.4.2
- **/
-void
-hb_ot_var_normalize_variations (hb_face_t            *face,
-				const hb_variation_t *variations, /* IN */
-				unsigned int          variations_length,
-				int                  *coords, /* OUT */
-				unsigned int          coords_length)
-{
-  for (unsigned int i = 0; i < coords_length; i++)
-    coords[i] = 0;
-
-  const OT::fvar &fvar = _get_fvar (face);
-  for (unsigned int i = 0; i < variations_length; i++)
-  {
-    unsigned int axis_index;
-    if (hb_ot_var_find_axis (face, variations[i].tag, &axis_index, NULL) &&
-	axis_index < coords_length)
-      coords[axis_index] = fvar.normalize_axis_value (axis_index, variations[i].value);
-  }
-
-  const OT::avar &avar = _get_avar (face);
-  avar.map_coords (coords, coords_length);
-}
-
-/**
- * hb_ot_var_normalize_coords:
- *
- * Since: 1.4.2
- **/
-void
-hb_ot_var_normalize_coords (hb_face_t    *face,
-			    unsigned int coords_length,
-			    const float *design_coords, /* IN */
-			    int *normalized_coords /* OUT */)
-{
-  const OT::fvar &fvar = _get_fvar (face);
-  for (unsigned int i = 0; i < coords_length; i++)
-    normalized_coords[i] = fvar.normalize_axis_value (i, design_coords[i]);
-
-  const OT::avar &avar = _get_avar (face);
-  avar.map_coords (normalized_coords, coords_length);
-}
diff --git a/src/hb-ot-var.h b/src/hb-ot-var.h
deleted file mode 100644
index a2c0c5f..0000000
--- a/src/hb-ot-var.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_H_IN
-#error "Include <hb-ot.h> instead."
-#endif
-
-#ifndef HB_OT_VAR_H
-#define HB_OT_VAR_H
-
-#include "hb.h"
-
-HB_BEGIN_DECLS
-
-
-#define HB_OT_TAG_VAR_AXIS_ITALIC	HB_TAG('i','t','a','l')
-#define HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE	HB_TAG('o','p','s','z')
-#define HB_OT_TAG_VAR_AXIS_SLANT	HB_TAG('s','l','n','t')
-#define HB_OT_TAG_VAR_AXIS_WIDTH	HB_TAG('w','d','t','h')
-#define HB_OT_TAG_VAR_AXIS_WEIGHT	HB_TAG('w','g','h','t')
-
-
-/*
- * fvar / avar
- */
-
-/**
- * hb_ot_var_axis_t:
- *
- * Since: 1.4.2
- */
-typedef struct hb_ot_var_axis_t {
-  hb_tag_t tag;
-  unsigned int name_id;
-  float min_value;
-  float default_value;
-  float max_value;
-} hb_ot_var_axis_t;
-
-HB_EXTERN hb_bool_t
-hb_ot_var_has_data (hb_face_t *face);
-
-/**
- * HB_OT_VAR_NO_AXIS_INDEX:
- *
- * Since: 1.4.2
- */
-#define HB_OT_VAR_NO_AXIS_INDEX		0xFFFFFFFFu
-
-HB_EXTERN unsigned int
-hb_ot_var_get_axis_count (hb_face_t *face);
-
-HB_EXTERN unsigned int
-hb_ot_var_get_axes (hb_face_t        *face,
-		    unsigned int      start_offset,
-		    unsigned int     *axes_count /* IN/OUT */,
-		    hb_ot_var_axis_t *axes_array /* OUT */);
-
-HB_EXTERN hb_bool_t
-hb_ot_var_find_axis (hb_face_t        *face,
-		     hb_tag_t          axis_tag,
-		     unsigned int     *axis_index,
-		     hb_ot_var_axis_t *axis_info);
-
-
-HB_EXTERN void
-hb_ot_var_normalize_variations (hb_face_t            *face,
-				const hb_variation_t *variations, /* IN */
-				unsigned int          variations_length,
-				int                  *coords, /* OUT */
-				unsigned int          coords_length);
-
-HB_EXTERN void
-hb_ot_var_normalize_coords (hb_face_t    *face,
-			    unsigned int coords_length,
-			    const float *design_coords, /* IN */
-			    int *normalized_coords /* OUT */);
-
-
-HB_END_DECLS
-
-#endif /* HB_OT_VAR_H */
diff --git a/src/hb-ot.h b/src/hb-ot.h
index 2120a3e..47c92a5 100644
--- a/src/hb-ot.h
+++ b/src/hb-ot.h
@@ -32,10 +32,8 @@
 
 #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"
-#include "hb-ot-var.h"
 
 HB_BEGIN_DECLS
 
diff --git a/src/hb-private.hh b/src/hb-private.hh
index 666af62..c45be6f 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -689,20 +689,17 @@
     fprintf (stderr, " %*s  ", (unsigned int) (2 * sizeof (void *)), "");
 
   if (indented) {
+/* One may want to add ASCII version of these.  See:
+ * https://bugs.freedesktop.org/show_bug.cgi?id=50970 */
 #define VBAR	"\342\224\202"	/* U+2502 BOX DRAWINGS LIGHT VERTICAL */
 #define VRBAR	"\342\224\234"	/* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
 #define DLBAR	"\342\225\256"	/* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */
 #define ULBAR	"\342\225\257"	/* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */
 #define LBAR	"\342\225\264"	/* U+2574 BOX DRAWINGS LIGHT LEFT */
-    static const char bars[] =
-      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
-      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
-      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
-      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
-      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR;
+    static const char bars[] = VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR;
     fprintf (stderr, "%2u %s" VRBAR "%s",
 	     level,
-	     bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level),
+	     bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars), (unsigned int) (sizeof (VBAR) - 1) * level),
 	     level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR);
   } else
     fprintf (stderr, "   " VRBAR LBAR);
diff --git a/src/hb-set.cc b/src/hb-set.cc
index f3fe1ba..cb7fcdb 100644
--- a/src/hb-set.cc
+++ b/src/hb-set.cc
@@ -105,7 +105,7 @@
  * @set: a set.
  * @key:
  * @data:
- * @destroy:
+ * @destroy (closure data):
  * @replace:
  *
  * Return value:
diff --git a/src/hb-shape-plan-private.hh b/src/hb-shape-plan-private.hh
index aa0413a..607da5e 100644
--- a/src/hb-shape-plan-private.hh
+++ b/src/hb-shape-plan-private.hh
@@ -47,17 +47,12 @@
   hb_feature_t *user_features;
   unsigned int num_user_features;
 
-  int *coords;
-  unsigned int num_coords;
-
   struct hb_shaper_data_t shaper_data;
 };
 
 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS \
-	, const hb_feature_t *user_features \
-	, unsigned int        num_user_features \
-	, const int          *coords \
-	, unsigned int        num_coords
+	, const hb_feature_t            *user_features \
+	, unsigned int                   num_user_features
 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, shape_plan);
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc
index 600faae..87231fb 100644
--- a/src/hb-shape-plan.cc
+++ b/src/hb-shape-plan.cc
@@ -46,14 +46,11 @@
 hb_shape_plan_plan (hb_shape_plan_t    *shape_plan,
 		    const hb_feature_t *user_features,
 		    unsigned int        num_user_features,
-		    const int          *coords,
-		    unsigned int        num_coords,
 		    const char * const *shaper_list)
 {
   DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
-		  "num_features=%d num_coords=%d shaper_list=%p",
+		  "num_features=%d shaper_list=%p",
 		  num_user_features,
-		  num_coords,
 		  shaper_list);
 
   const hb_shaper_pair_t *shapers = _hb_shapers_get ();
@@ -62,9 +59,7 @@
 	HB_STMT_START { \
 	  if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) { \
 	    HB_SHAPER_DATA (shaper, shape_plan) = \
-	      HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, \
-							       user_features, num_user_features, \
-							       coords, num_coords); \
+	      HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, user_features, num_user_features); \
 	    shape_plan->shaper_func = _hb_##shaper##_shape; \
 	    shape_plan->shaper_name = #shaper; \
 	    return; \
@@ -120,31 +115,14 @@
 		      unsigned int                   num_user_features,
 		      const char * const            *shaper_list)
 {
-  return hb_shape_plan_create2 (face, props,
-				user_features, num_user_features,
-				NULL, 0,
-				shaper_list);
-}
-
-hb_shape_plan_t *
-hb_shape_plan_create2 (hb_face_t                     *face,
-		       const hb_segment_properties_t *props,
-		       const hb_feature_t            *user_features,
-		       unsigned int                   num_user_features,
-		       const int                     *orig_coords,
-		       unsigned int                   num_coords,
-		       const char * const            *shaper_list)
-{
   DEBUG_MSG_FUNC (SHAPE_PLAN, NULL,
-		  "face=%p num_features=%d num_coords=%d shaper_list=%p",
+		  "face=%p num_features=%d shaper_list=%p",
 		  face,
 		  num_user_features,
-		  num_coords,
 		  shaper_list);
 
   hb_shape_plan_t *shape_plan;
   hb_feature_t *features = NULL;
-  int *coords = NULL;
 
   if (unlikely (!face))
     face = hb_face_get_empty ();
@@ -152,14 +130,7 @@
     return hb_shape_plan_get_empty ();
   if (num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t))))
     return hb_shape_plan_get_empty ();
-  if (num_coords && !(coords = (int *) calloc (num_coords, sizeof (int))))
-  {
-    free (features);
-    return hb_shape_plan_get_empty ();
-  }
-  if (!(shape_plan = hb_object_create<hb_shape_plan_t> ()))
-  {
-    free (coords);
+  if (!(shape_plan = hb_object_create<hb_shape_plan_t> ())) {
     free (features);
     return hb_shape_plan_get_empty ();
   }
@@ -174,15 +145,8 @@
   shape_plan->user_features = features;
   if (num_user_features)
     memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
-  shape_plan->num_coords = num_coords;
-  shape_plan->coords = coords;
-  if (num_coords)
-    memcpy (coords, orig_coords, num_coords * sizeof (int));
 
-  hb_shape_plan_plan (shape_plan,
-		      user_features, num_user_features,
-		      coords, num_coords,
-		      shaper_list);
+  hb_shape_plan_plan (shape_plan, user_features, num_user_features, shaper_list);
 
   return shape_plan;
 }
@@ -212,9 +176,6 @@
     NULL, /* user_features */
     0,    /* num_user_featurs */
 
-    NULL, /* coords */
-    0,    /* num_coords */
-
     {
 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
 #include "hb-shaper-list.hh"
@@ -259,7 +220,6 @@
 #undef HB_SHAPER_IMPLEMENT
 
   free (shape_plan->user_features);
-  free (shape_plan->coords);
 
   free (shape_plan);
 }
@@ -391,8 +351,6 @@
   const char * const            *shaper_list;
   const hb_feature_t            *user_features;
   unsigned int                   num_user_features;
-  const int                     *coords;
-  unsigned int                   num_coords;
   hb_shape_func_t               *shaper_func;
 };
 
@@ -400,26 +358,12 @@
 hb_shape_plan_user_features_match (const hb_shape_plan_t          *shape_plan,
 				   const hb_shape_plan_proposal_t *proposal)
 {
-  if (proposal->num_user_features != shape_plan->num_user_features)
-    return false;
+  if (proposal->num_user_features != shape_plan->num_user_features) return false;
   for (unsigned int i = 0, n = proposal->num_user_features; i < n; i++)
     if (proposal->user_features[i].tag   != shape_plan->user_features[i].tag   ||
         proposal->user_features[i].value != shape_plan->user_features[i].value ||
         proposal->user_features[i].start != shape_plan->user_features[i].start ||
-        proposal->user_features[i].end   != shape_plan->user_features[i].end)
-      return false;
-  return true;
-}
-
-static inline hb_bool_t
-hb_shape_plan_coords_match (const hb_shape_plan_t          *shape_plan,
-			    const hb_shape_plan_proposal_t *proposal)
-{
-  if (proposal->num_coords != shape_plan->num_coords)
-    return false;
-  for (unsigned int i = 0, n = proposal->num_coords; i < n; i++)
-    if (proposal->coords[i] != shape_plan->coords[i])
-      return false;
+        proposal->user_features[i].end   != shape_plan->user_features[i].end) return false;
   return true;
 }
 
@@ -429,7 +373,6 @@
 {
   return hb_segment_properties_equal (&shape_plan->props, &proposal->props) &&
 	 hb_shape_plan_user_features_match (shape_plan, proposal) &&
-	 hb_shape_plan_coords_match (shape_plan, proposal) &&
 	 ((shape_plan->default_shaper_list && proposal->shaper_list == NULL) ||
 	  (shape_plan->shaper_func == proposal->shaper_func));
 }
@@ -446,13 +389,6 @@
   return false;
 }
 
-static inline hb_bool_t
-hb_coords_present (const int *coords,
-		   unsigned int num_coords)
-{
-  return num_coords != 0;
-}
-
 /**
  * hb_shape_plan_create_cached:
  * @face: 
@@ -474,21 +410,6 @@
 			     unsigned int                   num_user_features,
 			     const char * const            *shaper_list)
 {
-  return hb_shape_plan_create_cached2 (face, props,
-				       user_features, num_user_features,
-				       NULL, 0,
-				       shaper_list);
-}
-
-hb_shape_plan_t *
-hb_shape_plan_create_cached2 (hb_face_t                     *face,
-			      const hb_segment_properties_t *props,
-			      const hb_feature_t            *user_features,
-			      unsigned int                   num_user_features,
-			      const int                     *coords,
-			      unsigned int                   num_coords,
-			      const char * const            *shaper_list)
-{
   DEBUG_MSG_FUNC (SHAPE_PLAN, NULL,
 		  "face=%p num_features=%d shaper_list=%p",
 		  face,
@@ -535,21 +456,16 @@
 
   /* Not found. */
 
-  hb_shape_plan_t *shape_plan = hb_shape_plan_create2 (face, props,
-						       user_features, num_user_features,
-						       coords, num_coords,
-						       shaper_list);
+  hb_shape_plan_t *shape_plan = hb_shape_plan_create (face, props, user_features, num_user_features, shaper_list);
 
   /* Don't add to the cache if face is inert. */
   if (unlikely (hb_object_is_inert (face)))
     return shape_plan;
 
   /* Don't add the plan to the cache if there were user features with non-global ranges */
+
   if (hb_non_global_user_features_present (user_features, num_user_features))
     return shape_plan;
-  /* Don't add the plan to the cache if there were variation coordinates XXX Fix me. */
-  if (hb_coords_present (coords, num_coords))
-    return shape_plan;
 
   hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (hb_face_t::plan_node_t));
   if (unlikely (!node))
diff --git a/src/hb-shape-plan.h b/src/hb-shape-plan.h
index b62ae7c..aa5e0c7 100644
--- a/src/hb-shape-plan.h
+++ b/src/hb-shape-plan.h
@@ -53,25 +53,6 @@
 			     const char * const            *shaper_list);
 
 HB_EXTERN hb_shape_plan_t *
-hb_shape_plan_create2 (hb_face_t                     *face,
-		       const hb_segment_properties_t *props,
-		       const hb_feature_t            *user_features,
-		       unsigned int                   num_user_features,
-		       const int                     *coords,
-		       unsigned int                   num_coords,
-		       const char * const            *shaper_list);
-
-HB_EXTERN hb_shape_plan_t *
-hb_shape_plan_create_cached2 (hb_face_t                     *face,
-			      const hb_segment_properties_t *props,
-			      const hb_feature_t            *user_features,
-			      unsigned int                   num_user_features,
-			      const int                     *coords,
-			      unsigned int                   num_coords,
-			      const char * const            *shaper_list);
-
-
-HB_EXTERN hb_shape_plan_t *
 hb_shape_plan_get_empty (void);
 
 HB_EXTERN hb_shape_plan_t *
diff --git a/src/hb-shape.cc b/src/hb-shape.cc
index f080a15..41a4fc5 100644
--- a/src/hb-shape.cc
+++ b/src/hb-shape.cc
@@ -45,6 +45,254 @@
  * contains the output glyphs and their positions.
  **/
 
+static bool
+parse_space (const char **pp, const char *end)
+{
+  while (*pp < end && ISSPACE (**pp))
+    (*pp)++;
+  return true;
+}
+
+static bool
+parse_char (const char **pp, const char *end, char c)
+{
+  parse_space (pp, end);
+
+  if (*pp == end || **pp != c)
+    return false;
+
+  (*pp)++;
+  return true;
+}
+
+static bool
+parse_uint (const char **pp, const char *end, unsigned int *pv)
+{
+  char buf[32];
+  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
+  strncpy (buf, *pp, len);
+  buf[len] = '\0';
+
+  char *p = buf;
+  char *pend = p;
+  unsigned int v;
+
+  /* Intentionally use strtol instead of strtoul, such that
+   * -1 turns into "big number"... */
+  errno = 0;
+  v = strtol (p, &pend, 0);
+  if (errno || p == pend)
+    return false;
+
+  *pv = v;
+  *pp += pend - p;
+  return true;
+}
+
+static bool
+parse_bool (const char **pp, const char *end, unsigned int *pv)
+{
+  parse_space (pp, end);
+
+  const char *p = *pp;
+  while (*pp < end && ISALPHA(**pp))
+    (*pp)++;
+
+  /* CSS allows on/off as aliases 1/0. */
+  if (*pp - p == 2 || 0 == strncmp (p, "on", 2))
+    *pv = 1;
+  else if (*pp - p == 3 || 0 == strncmp (p, "off", 2))
+    *pv = 0;
+  else
+    return false;
+
+  return true;
+}
+
+static bool
+parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature)
+{
+  if (parse_char (pp, end, '-'))
+    feature->value = 0;
+  else {
+    parse_char (pp, end, '+');
+    feature->value = 1;
+  }
+
+  return true;
+}
+
+static bool
+parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature)
+{
+  parse_space (pp, end);
+
+  char quote = 0;
+
+  if (*pp < end && (**pp == '\'' || **pp == '"'))
+  {
+    quote = **pp;
+    (*pp)++;
+  }
+
+  const char *p = *pp;
+  while (*pp < end && ISALNUM(**pp))
+    (*pp)++;
+
+  if (p == *pp || *pp - p > 4)
+    return false;
+
+  feature->tag = hb_tag_from_string (p, *pp - p);
+
+  if (quote)
+  {
+    /* CSS expects exactly four bytes.  And we only allow quotations for
+     * CSS compatibility.  So, enforce the length. */
+     if (*pp - p != 4)
+       return false;
+    if (*pp == end || **pp != quote)
+      return false;
+    (*pp)++;
+  }
+
+  return true;
+}
+
+static bool
+parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
+{
+  parse_space (pp, end);
+
+  bool has_start;
+
+  feature->start = 0;
+  feature->end = (unsigned int) -1;
+
+  if (!parse_char (pp, end, '['))
+    return true;
+
+  has_start = parse_uint (pp, end, &feature->start);
+
+  if (parse_char (pp, end, ':')) {
+    parse_uint (pp, end, &feature->end);
+  } else {
+    if (has_start)
+      feature->end = feature->start + 1;
+  }
+
+  return parse_char (pp, end, ']');
+}
+
+static bool
+parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature)
+{
+  bool had_equal = parse_char (pp, end, '=');
+  bool had_value = parse_uint (pp, end, &feature->value) ||
+                   parse_bool (pp, end, &feature->value);
+  /* CSS doesn't use equal-sign between tag and value.
+   * If there was an equal-sign, then there *must* be a value.
+   * A value without an eqaul-sign is ok, but not required. */
+  return !had_equal || had_value;
+}
+
+
+static bool
+parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
+{
+  return parse_feature_value_prefix (pp, end, feature) &&
+	 parse_feature_tag (pp, end, feature) &&
+	 parse_feature_indices (pp, end, feature) &&
+	 parse_feature_value_postfix (pp, end, feature) &&
+	 parse_space (pp, end) &&
+	 *pp == end;
+}
+
+/**
+ * hb_feature_from_string:
+ * @str: (array length=len) (element-type uint8_t): a string to parse
+ * @len: length of @str, or -1 if string is %NULL terminated
+ * @feature: (out): the #hb_feature_t to initialize with the parsed values
+ *
+ * Parses a string into a #hb_feature_t.
+ *
+ * TODO: document the syntax here.
+ *
+ * Return value:
+ * %true if @str is successfully parsed, %false otherwise.
+ *
+ * Since: 0.9.5
+ **/
+hb_bool_t
+hb_feature_from_string (const char *str, int len,
+			hb_feature_t *feature)
+{
+  hb_feature_t feat;
+
+  if (len < 0)
+    len = strlen (str);
+
+  if (likely (parse_one_feature (&str, str + len, &feat)))
+  {
+    if (feature)
+      *feature = feat;
+    return true;
+  }
+
+  if (feature)
+    memset (feature, 0, sizeof (*feature));
+  return false;
+}
+
+/**
+ * hb_feature_to_string:
+ * @feature: an #hb_feature_t to convert
+ * @buf: (array length=size) (out): output string
+ * @size: the allocated size of @buf
+ *
+ * Converts a #hb_feature_t into a %NULL-terminated string in the format
+ * understood by hb_feature_from_string(). The client in responsible for
+ * allocating big enough size for @buf, 128 bytes is more than enough.
+ *
+ * Since: 0.9.5
+ **/
+void
+hb_feature_to_string (hb_feature_t *feature,
+		      char *buf, unsigned int size)
+{
+  if (unlikely (!size)) return;
+
+  char s[128];
+  unsigned int len = 0;
+  if (feature->value == 0)
+    s[len++] = '-';
+  hb_tag_to_string (feature->tag, s + len);
+  len += 4;
+  while (len && s[len - 1] == ' ')
+    len--;
+  if (feature->start != 0 || feature->end != (unsigned int) -1)
+  {
+    s[len++] = '[';
+    if (feature->start)
+      len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start));
+    if (feature->end != feature->start + 1) {
+      s[len++] = ':';
+      if (feature->end != (unsigned int) -1)
+	len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end));
+    }
+    s[len++] = ']';
+  }
+  if (feature->value > 1)
+  {
+    s[len++] = '=';
+    len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
+  }
+  assert (len < ARRAY_LENGTH (s));
+  len = MIN (len, size - 1);
+  memcpy (buf, s, len);
+  buf[len] = '\0';
+}
+
+
 static const char **static_shaper_list;
 
 #ifdef HB_USE_ATEXIT
@@ -114,7 +362,7 @@
  * shapers will be used in the given order, otherwise the default shapers list
  * will be used.
  *
- * Return value: false if all shapers failed, true otherwise
+ * Return value: %FALSE if all shapers failed, %TRUE otherwise
  *
  * Since: 0.9.2
  **/
@@ -125,10 +373,7 @@
 	       unsigned int        num_features,
 	       const char * const *shaper_list)
 {
-  hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached2 (font->face, &buffer->props,
-							      features, num_features,
-							      font->coords, font->num_coords,
-							      shaper_list);
+  hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list);
   hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features);
   hb_shape_plan_destroy (shape_plan);
 
diff --git a/src/hb-shape.h b/src/hb-shape.h
index 39507ff..53bb845 100644
--- a/src/hb-shape.h
+++ b/src/hb-shape.h
@@ -40,6 +40,22 @@
 HB_BEGIN_DECLS
 
 
+typedef struct hb_feature_t {
+  hb_tag_t      tag;
+  uint32_t      value;
+  unsigned int  start;
+  unsigned int  end;
+} hb_feature_t;
+
+HB_EXTERN hb_bool_t
+hb_feature_from_string (const char *str, int len,
+			hb_feature_t *feature);
+
+HB_EXTERN void
+hb_feature_to_string (hb_feature_t *feature,
+		      char *buf, unsigned int size);
+
+
 HB_EXTERN void
 hb_shape (hb_font_t           *font,
 	  hb_buffer_t         *buffer,
diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc
index d553a71..487d10b 100644
--- a/src/hb-unicode.cc
+++ b/src/hb-unicode.cc
@@ -131,12 +131,12 @@
 #define HB_UNICODE_FUNCS_IMPLEMENT(set) \
   return hb_##set##_get_unicode_funcs ();
 
-#if defined(HAVE_UCDN)
-  HB_UNICODE_FUNCS_IMPLEMENT(ucdn)
-#elif defined(HAVE_GLIB)
+#ifdef HAVE_GLIB
   HB_UNICODE_FUNCS_IMPLEMENT(glib)
 #elif defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN)
   HB_UNICODE_FUNCS_IMPLEMENT(icu)
+#elif defined(HAVE_UCDN)
+  HB_UNICODE_FUNCS_IMPLEMENT(ucdn)
 #else
 #define HB_UNICODE_FUNCS_NIL 1
   HB_UNICODE_FUNCS_IMPLEMENT(nil)
diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc
index 6e4db01..07007a6 100644
--- a/src/hb-uniscribe.cc
+++ b/src/hb-uniscribe.cc
@@ -587,9 +587,7 @@
 hb_uniscribe_shaper_shape_plan_data_t *
 _hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
 					     const hb_feature_t *user_features HB_UNUSED,
-					     unsigned int        num_user_features HB_UNUSED,
-					     const int          *coords HB_UNUSED,
-					     unsigned int        num_coords HB_UNUSED)
+					     unsigned int        num_user_features HB_UNUSED)
 {
   return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
diff --git a/src/hb-version.h b/src/hb-version.h
index df83a8a..bf199ce 100644
--- a/src/hb-version.h
+++ b/src/hb-version.h
@@ -37,10 +37,10 @@
 
 
 #define HB_VERSION_MAJOR 1
-#define HB_VERSION_MINOR 4
+#define HB_VERSION_MINOR 3
 #define HB_VERSION_MICRO 2
 
-#define HB_VERSION_STRING "1.4.2"
+#define HB_VERSION_STRING "1.3.2"
 
 #define HB_VERSION_ATLEAST(major,minor,micro) \
 	((major)*10000+(minor)*100+(micro) <= \
diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index 530bf3e..d7d40af 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -43,29 +43,10 @@
 
 
 if HAVE_OT
-
 TEST_PROGS += \
 	test-ot-tag \
 	$(NULL)
-
-if HAVE_FREETYPE
-TEST_PROGS += \
-	test-ot-math \
-	$(NULL)
-test_ot_math_LDADD = $(LDADD) $(FREETYPE_LIBS)
-test_ot_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS)
-EXTRA_DIST += \
-	fonts/MathTestFontEmpty.otf \
-	fonts/MathTestFontFull.otf \
-	fonts/MathTestFontNone.otf \
-	fonts/MathTestFontPartial1.otf \
-	fonts/MathTestFontPartial2.otf \
-	fonts/MathTestFontPartial3.otf \
-	fonts/MathTestFontPartial4.otf \
-	$(NULL)
-endif # HAVE_FREETYPE
-
-endif # HAVE_OT
+endif
 
 # Tests for header compilation
 TEST_PROGS += \
@@ -92,8 +73,6 @@
 	G_DEBUG=gc-friendly \
 	G_SLICE=always-malloc \
 	srcdir=$(srcdir) \
-	G_TEST_SRCDIR=$(abs_srcdir) \
-	G_TEST_BUILDDIR=$(abs_builddir) \
 	$(NULL)
 
 
diff --git a/test/api/fonts/MathTestFontEmpty.otf b/test/api/fonts/MathTestFontEmpty.otf
deleted file mode 100644
index 6b50d66..0000000
--- a/test/api/fonts/MathTestFontEmpty.otf
+++ /dev/null
Binary files differ
diff --git a/test/api/fonts/MathTestFontFull.otf b/test/api/fonts/MathTestFontFull.otf
deleted file mode 100644
index 6c7c9a9..0000000
--- a/test/api/fonts/MathTestFontFull.otf
+++ /dev/null
Binary files differ
diff --git a/test/api/fonts/MathTestFontNone.otf b/test/api/fonts/MathTestFontNone.otf
deleted file mode 100644
index 52984ee..0000000
--- a/test/api/fonts/MathTestFontNone.otf
+++ /dev/null
Binary files differ
diff --git a/test/api/fonts/MathTestFontPartial1.otf b/test/api/fonts/MathTestFontPartial1.otf
deleted file mode 100644
index b3bf36e..0000000
--- a/test/api/fonts/MathTestFontPartial1.otf
+++ /dev/null
Binary files differ
diff --git a/test/api/fonts/MathTestFontPartial2.otf b/test/api/fonts/MathTestFontPartial2.otf
deleted file mode 100644
index 4607c11..0000000
--- a/test/api/fonts/MathTestFontPartial2.otf
+++ /dev/null
Binary files differ
diff --git a/test/api/fonts/MathTestFontPartial3.otf b/test/api/fonts/MathTestFontPartial3.otf
deleted file mode 100644
index ca18a9a..0000000
--- a/test/api/fonts/MathTestFontPartial3.otf
+++ /dev/null
Binary files differ
diff --git a/test/api/fonts/MathTestFontPartial4.otf b/test/api/fonts/MathTestFontPartial4.otf
deleted file mode 100644
index cda3057..0000000
--- a/test/api/fonts/MathTestFontPartial4.otf
+++ /dev/null
Binary files differ
diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c
deleted file mode 100644
index 0ca5566..0000000
--- a/test/api/test-ot-math.c
+++ /dev/null
@@ -1,712 +0,0 @@
-/*
- * 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
- */
-
-
-#include "hb-test.h"
-
-#include "hb-ft.h"
-#include "hb-ot.h"
-
-/* Unit tests for hb-ot-math.h - OpenType MATH table  */
-
-static FT_Library ft_library;
-static FT_Face ft_face;
-static hb_font_t *hb_font;
-static hb_face_t *hb_face;
-
-static inline void
-initFreeType (void)
-{
-  FT_Error ft_error;
-  if ((ft_error = FT_Init_FreeType (&ft_library)))
-    abort();
-}
-
-static inline void
-cleanupFreeType (void)
-{
-  FT_Done_FreeType (ft_library);
-}
-
-static void
-openFont(const char* fontFile)
-{
-#if GLIB_CHECK_VERSION(2,37,2)
-  gchar* path = g_test_build_filename(G_TEST_DIST, fontFile, NULL);
-#else
-  gchar* path = g_strdup(fontFile);
-#endif
-
-  FT_Error ft_error;
-  if ((ft_error = FT_New_Face (ft_library, path, 0, &ft_face))) {
-    g_free(path);
-    abort();
-  }
-  g_free(path);
-
-  if ((ft_error = FT_Set_Char_Size (ft_face, 2000, 1000, 0, 0)))
-    abort();
-  hb_font = hb_ft_font_create (ft_face, NULL);
-  hb_face = hb_face_reference (hb_font_get_face (hb_font));
-}
-
-static inline void
-closeFont (void)
-{
-  hb_face_destroy (hb_face);
-  hb_font_destroy (hb_font);
-  FT_Done_Face (ft_face);
-  hb_face = NULL;
-  hb_font = NULL;
-  ft_face = NULL;
-}
-
-static void
-test_has_data (void)
-{
-  initFreeType();
-
-  openFont("fonts/MathTestFontNone.otf");
-  g_assert(!hb_ot_math_has_data (hb_face)); // MATH table not available
-  closeFont();
-
-  openFont("fonts/MathTestFontEmpty.otf");
-  g_assert(hb_ot_math_has_data (hb_face)); // MATH table available
-  closeFont();
-
-  hb_face = hb_face_get_empty ();
-  hb_font = hb_font_create (hb_face);
-  g_assert(!hb_ot_math_has_data (hb_face)); // MATH table not available
-
-  hb_font = hb_font_get_empty ();
-  hb_face = hb_font_get_face (hb_font);
-  g_assert(!hb_ot_math_has_data (hb_face)); // MATH table not available
-
-  cleanupFreeType();
-}
-
-static void
-test_get_constant (void)
-{
-  initFreeType();
-
-  openFont("fonts/MathTestFontEmpty.otf");
-  g_assert_cmpint(hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT), ==, 0); // MathConstants not available
-  closeFont();
-
-  openFont("fonts/MathTestFontFull.otf");
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT)), ==, 100);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT)), ==, 200);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_MATH_LEADING)), ==, 300);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_AXIS_HEIGHT)), ==, 400);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT)), ==, 500);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT)), ==, 600);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN)), ==, 700);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX)), ==, 800);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN)), ==, 900);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP)), ==, 1100);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED)), ==, 1200);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN)), ==, 1300);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX)), ==, 1400);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN)), ==, 1500);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT)), ==, 1600);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT)), ==, 3400);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN)), ==, 1800);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN)), ==, 1900);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN)), ==, 2200);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN)), ==, 2300);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP)), ==, 2400);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP)), ==, 2500);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN)), ==, 2600);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN)), ==, 2700);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_GAP_MIN)), ==, 2800);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN)), ==, 2900);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP)), ==, 3000);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN)), ==, 3100);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN)), ==, 3200);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN)), ==, 3300);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP)), ==, 3400);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP)), ==, 3500);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN)), ==, 3600);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN)), ==, 3700);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN)), ==, 3800);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN)), ==, 3900);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS)), ==, 4000);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN)), ==, 4100);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN)), ==, 4200);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP)), ==, 8600);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP)), ==, 4400);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP)), ==, 4500);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS)), ==, 4600);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER)), ==, 4700);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP)), ==, 4800);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS)), ==, 4900);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER)), ==, 5000);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP)), ==, 5100);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP)), ==, 5200);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS)), ==, 5300);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER)), ==, 5400);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE)), ==, 11000);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE)), ==, 11200);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 87);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 76);
-  g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT)), ==, 65);
-  closeFont();
-
-  cleanupFreeType();
-}
-
-static void
-test_get_glyph_italics_correction (void)
-{
-  hb_codepoint_t glyph;
-  initFreeType();
-
-  openFont("fonts/MathTestFontEmpty.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial1.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial2.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty
-  closeFont();
-
-  openFont("fonts/MathTestFontFull.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // Glyph without italic correction.
-  g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 394);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 300);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 904);
-  closeFont();
-
-  cleanupFreeType();
-}
-
-static void
-test_get_glyph_top_accent_attachment (void)
-{
-  hb_codepoint_t glyph;
-  initFreeType();
-
-  openFont("fonts/MathTestFontEmpty.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathGlyphInfo not available
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial1.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathGlyphInfo empty
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial2.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathTopAccentAttachment empty
-  closeFont();
-
-  openFont("fonts/MathTestFontFull.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // Glyph without top accent attachment.
-  g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 748);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 692);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "F", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 636);
-  closeFont();
-
-  cleanupFreeType();
-}
-
-static void
-test_is_glyph_extended_shape (void)
-{
-  hb_codepoint_t glyph;
-  initFreeType();
-
-  openFont("fonts/MathTestFontEmpty.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph)); // MathGlyphInfo not available
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial1.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph)); // MathGlyphInfo empty
-  closeFont();
-
-  openFont("fonts/MathTestFontFull.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "G", -1, &glyph));
-  g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph));
-  g_assert(hb_font_get_glyph_from_name (hb_font, "H", -1, &glyph));
-  g_assert(hb_ot_math_is_glyph_extended_shape (hb_face, glyph));
-  closeFont();
-
-  cleanupFreeType();
-}
-
-static void
-test_get_glyph_kerning (void)
-{
-  hb_codepoint_t glyph;
-  initFreeType();
-
-  openFont("fonts/MathTestFontEmpty.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathGlyphInfo not available
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathGlyphInfo not available
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathGlyphInfo not available
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathGlyphInfo not available
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial2.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfo empty
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfo empty
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfo empty
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfo empty
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial3.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfoRecords empty
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfoRecords empty
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfoRecords empty
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfoRecords empty
-  closeFont();
-
-  openFont("fonts/MathTestFontFull.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "I", -1, &glyph));
-
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 62); // lower than min heigth
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 62); // equal to min height
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 104);
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 104);
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 146);
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 146);
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 398); // equal to max height
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 440); // larger than max height
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 440); // larger than max height
-
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 188); // top right
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 110); // top left
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 44); // bottom right
-  g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 100); // bottom left
-
-  closeFont();
-
-  cleanupFreeType();
-}
-
-
-static hb_position_t
-get_glyph_assembly_italics_correction (hb_font_t *font,
-				       hb_codepoint_t glyph,
-				       hb_bool_t horizontal)
-{
-  hb_position_t corr;
-  hb_ot_math_get_glyph_assembly (font, glyph,
-				 horizontal ? HB_DIRECTION_LTR : HB_DIRECTION_TTB,
-				 0, NULL, NULL,
-				 &corr);
-  return corr;
-}
-
-static void
-test_get_glyph_assembly_italics_correction (void)
-{
-  hb_codepoint_t glyph;
-  initFreeType();
-
-  openFont("fonts/MathTestFontEmpty.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // MathVariants not available
-  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // MathVariants not available
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial1.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
-  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial2.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
-  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial3.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty
-  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0);  // HorizGlyphConstruction and VertGlyphConstruction empty
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial4.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0);
-  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0);
-  closeFont();
-
-  openFont("fonts/MathTestFontFull.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
-  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 248);
-  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph));
-  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0);
-  g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 662);
-  closeFont();
-
-  cleanupFreeType();
-}
-
-static void
-test_get_min_connector_overlap (void)
-{
-  initFreeType();
-
-  openFont("fonts/MathTestFontEmpty.otf");
-  g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, FALSE), ==, 0); // MathVariants not available
-  g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, TRUE), ==, 0); // MathVariants not available
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial1.otf");
-  g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_LTR), ==, 108);
-  g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_TTB), ==, 54);
-  closeFont();
-
-  cleanupFreeType();
-}
-
-static void
-test_get_glyph_variants (void)
-{
-  hb_codepoint_t glyph;
-  hb_ot_math_glyph_variant_t variants[20];
-  unsigned variantsSize = sizeof (variants) / sizeof (variants[0]);
-  unsigned int count;
-  unsigned int offset = 0;
-
-  initFreeType();
-
-  openFont("fonts/MathTestFontEmpty.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
-  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial1.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
-  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial2.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
-  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial3.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
-  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial4.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0);
-  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0);
-  closeFont();
-
-  openFont("fonts/MathTestFontFull.otf");
-
-  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font,
-                                                 glyph,
-                                                 HB_DIRECTION_BTT,
-                                                 0,
-                                                 NULL,
-                                                 NULL), ==, 0);
-  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font,
-                                                 glyph,
-                                                 HB_DIRECTION_RTL,
-                                                 0,
-                                                 NULL,
-                                                 NULL), ==, 3);
-
-  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font,
-                                                 glyph,
-                                                 HB_DIRECTION_BTT,
-                                                 0,
-                                                 NULL,
-                                                 NULL), ==, 4);
-  g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font,
-                                                 glyph,
-                                                 HB_DIRECTION_RTL,
-                                                 0,
-                                                 NULL,
-                                                 NULL), ==, 0);
-
-  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph));
-  do {
-    count = variantsSize;
-    hb_ot_math_get_glyph_variants (hb_font,
-                                   glyph,
-                                   HB_DIRECTION_RTL,
-                                   offset,
-                                   &count,
-                                   variants);
-    offset += count;
-  } while (count == variantsSize);
-  g_assert_cmpint(offset, ==, 3);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size2", -1, &glyph));
-  g_assert_cmpint(variants[0].glyph, ==, glyph);
-  g_assert_cmpint(variants[0].advance, ==, 4302);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size3", -1, &glyph));
-  g_assert_cmpint(variants[1].glyph, ==, glyph);
-  g_assert_cmpint(variants[1].advance, ==, 4802);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size4", -1, &glyph));
-  g_assert_cmpint(variants[2].glyph, ==, glyph);
-  g_assert_cmpint(variants[2].advance, ==, 5802);
-
-  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph));
-  offset = 0;
-  do {
-    count = variantsSize;
-    hb_ot_math_get_glyph_variants (hb_font,
-                                   glyph,
-                                   HB_DIRECTION_BTT,
-                                   offset,
-                                   &count,
-                                   variants);
-    offset += count;
-  } while (count == variantsSize);
-  g_assert_cmpint(offset, ==, 4);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size2", -1, &glyph));
-  g_assert_cmpint(variants[0].glyph, ==, glyph);
-  g_assert_cmpint(variants[0].advance, ==, 2251);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size3", -1, &glyph));
-  g_assert_cmpint(variants[1].glyph, ==, glyph);
-  g_assert_cmpint(variants[1].advance, ==, 2501);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size4", -1, &glyph));
-  g_assert_cmpint(variants[2].glyph, ==, glyph);
-  g_assert_cmpint(variants[2].advance, ==, 3001);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size5", -1, &glyph));
-  g_assert_cmpint(variants[3].glyph, ==, glyph);
-  g_assert_cmpint(variants[3].advance, ==, 3751);
-
-  closeFont();
-
-  cleanupFreeType();
-}
-
-static void
-test_get_glyph_assembly (void)
-{
-  hb_codepoint_t glyph;
-  hb_ot_math_glyph_part_t parts[20];
-  unsigned partsSize = sizeof (parts) / sizeof (parts[0]);
-  unsigned int count;
-  unsigned int offset = 0;
-
-  initFreeType();
-
-  openFont("fonts/MathTestFontEmpty.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
-  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial1.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
-  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial2.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
-  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial3.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
-  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
-  closeFont();
-
-  openFont("fonts/MathTestFontPartial4.otf");
-  g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0);
-  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0);
-  closeFont();
-
-  openFont("fonts/MathTestFontFull.otf");
-
-  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font,
-                                                 glyph,
-                                                 HB_DIRECTION_BTT,
-                                                 0,
-                                                 NULL,
-                                                 NULL,
-                                                 NULL), ==, 0);
-  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font,
-                                                 glyph,
-                                                 HB_DIRECTION_RTL,
-                                                 0,
-                                                 NULL,
-                                                 NULL,
-                                                 NULL), ==, 3);
-
-  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowdown", -1, &glyph));
-  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font,
-                                                 glyph,
-                                                 HB_DIRECTION_BTT,
-                                                 0,
-                                                 NULL,
-                                                 NULL,
-                                                 NULL), ==, 5);
-  g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font,
-                                                 glyph,
-                                                 HB_DIRECTION_RTL,
-                                                 0,
-                                                 NULL,
-                                                 NULL,
-                                                 NULL), ==, 0);
-
-  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph));
-  do {
-    count = partsSize;
-    hb_ot_math_get_glyph_assembly (hb_font,
-                                   glyph,
-                                   HB_DIRECTION_RTL,
-                                   offset,
-                                   &count,
-                                   parts,
-                                   NULL);
-    offset += count;
-  } while (count == partsSize);
-  g_assert_cmpint(offset, ==, 3);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "left", -1, &glyph));
-  g_assert_cmpint(parts[0].glyph, ==, glyph);
-  g_assert_cmpint(parts[0].start_connector_length, ==, 800);
-  g_assert_cmpint(parts[0].end_connector_length, ==, 384);
-  g_assert_cmpint(parts[0].full_advance, ==, 2000);
-  g_assert(!(parts[0].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
-  g_assert(hb_font_get_glyph_from_name (hb_font, "horizontal", -1, &glyph));
-  g_assert_cmpint(parts[1].glyph, ==, glyph);
-  g_assert_cmpint(parts[1].start_connector_length, ==, 524);
-  g_assert_cmpint(parts[1].end_connector_length, ==, 800);
-  g_assert_cmpint(parts[1].full_advance, ==, 2000);
-  g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "right", -1, &glyph));
-  g_assert_cmpint(parts[2].glyph, ==, glyph);
-  g_assert_cmpint(parts[2].start_connector_length, ==, 316);
-  g_assert_cmpint(parts[2].end_connector_length, ==, 454);
-  g_assert_cmpint(parts[2].full_advance, ==, 2000);
-  g_assert(!(parts[2].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
-
-  g_assert(hb_font_get_glyph_from_name (hb_font, "arrowdown", -1, &glyph));
-  offset = 0;
-  do {
-    count = partsSize;
-    hb_ot_math_get_glyph_assembly (hb_font,
-                                   glyph,
-                                   HB_DIRECTION_BTT,
-                                   offset,
-                                   &count,
-                                   parts,
-                                   NULL);
-    offset += count;
-  } while (count == partsSize);
-  g_assert_cmpint(offset, ==, 5);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "bottom", -1, &glyph));
-  g_assert_cmpint(parts[0].glyph, ==, glyph);
-  g_assert_cmpint(parts[0].start_connector_length, ==, 365);
-  g_assert_cmpint(parts[0].end_connector_length, ==, 158);
-  g_assert_cmpint(parts[0].full_advance, ==, 1000);
-  g_assert(!(parts[0].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
-  g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph));
-  g_assert_cmpint(parts[1].glyph, ==, glyph);
-  g_assert_cmpint(parts[1].glyph, ==, glyph);
-  g_assert_cmpint(parts[1].start_connector_length, ==, 227);
-  g_assert_cmpint(parts[1].end_connector_length, ==, 365);
-  g_assert_cmpint(parts[1].full_advance, ==, 1000);
-  g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "center", -1, &glyph));
-  g_assert_cmpint(parts[2].glyph, ==, glyph);
-  g_assert_cmpint(parts[2].start_connector_length, ==, 54);
-  g_assert_cmpint(parts[2].end_connector_length, ==, 158);
-  g_assert_cmpint(parts[2].full_advance, ==, 1000);
-  g_assert(!(parts[2].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
-  g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph));
-  g_assert_cmpint(parts[3].glyph, ==, glyph);
-  g_assert_cmpint(parts[3].glyph, ==, glyph);
-  g_assert_cmpint(parts[3].glyph, ==, glyph);
-  g_assert_cmpint(parts[3].start_connector_length, ==, 400);
-  g_assert_cmpint(parts[3].end_connector_length, ==, 296);
-  g_assert_cmpint(parts[3].full_advance, ==, 1000);
-  g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER);
-  g_assert(hb_font_get_glyph_from_name (hb_font, "top", -1, &glyph));
-  g_assert_cmpint(parts[4].glyph, ==, glyph);
-  g_assert_cmpint(parts[4].start_connector_length, ==, 123);
-  g_assert_cmpint(parts[4].end_connector_length, ==, 192);
-  g_assert_cmpint(parts[4].full_advance, ==, 1000);
-  g_assert(!(parts[4].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
-
-  closeFont();
-
-  cleanupFreeType();
-}
-
-int
-main (int argc, char **argv)
-{
-  hb_test_init (&argc, &argv);
-
-  hb_test_add (test_has_data);
-  hb_test_add (test_get_constant);
-  hb_test_add (test_get_glyph_italics_correction);
-  hb_test_add (test_get_glyph_top_accent_attachment);
-  hb_test_add (test_is_glyph_extended_shape);
-  hb_test_add (test_get_glyph_kerning);
-  hb_test_add (test_get_glyph_assembly_italics_correction);
-  hb_test_add (test_get_min_connector_overlap);
-  hb_test_add (test_get_glyph_variants);
-  hb_test_add (test_get_glyph_assembly);
-
-  return hb_test_run();
-}
diff --git a/test/api/test-ot-tag.c b/test/api/test-ot-tag.c
index f5cbd9d..e54e552 100644
--- a/test/api/test-ot-tag.c
+++ b/test/api/test-ot-tag.c
@@ -188,48 +188,11 @@
   test_language_two_way ("ENG", "en");
   test_tag_from_language ("ENG", "en_US");
 
-  test_language_two_way ("CJA", "cja"); /* Western Cham */
-  test_language_two_way ("CJM", "cjm"); /* Eastern Cham */
   test_language_two_way ("EVN", "eve");
 
-  test_language_two_way ("HAL", "cfm"); /* BCP47 and current ISO639-3 code for Halam/Falam Chin */
-  test_tag_from_language ("HAL", "flm"); /* Retired ISO639-3 code for Halam/Falam Chin */
-
-  test_tag_from_language ("QIN", "bgr"); /* Bawm Chin */
-  test_tag_from_language ("QIN", "cbl"); /* Bualkhaw Chin */
-  test_tag_from_language ("QIN", "cka"); /* Khumi Awa Chin */
-  test_tag_from_language ("QIN", "cmr"); /* Mro-Khimi Chin */
-  test_tag_from_language ("QIN", "cnb"); /* Chinbon Chin */
-  test_tag_from_language ("QIN", "cnh"); /* Hakha Chin */
-  test_tag_from_language ("QIN", "cnk"); /* Khumi Chin */
-  test_tag_from_language ("QIN", "cnw"); /* Ngawn Chin */
-  test_tag_from_language ("QIN", "csh"); /* Asho Chin */
-  test_tag_from_language ("QIN", "csy"); /* Siyin Chin */
-  test_tag_from_language ("QIN", "ctd"); /* Tedim Chin */
-  test_tag_from_language ("QIN", "czt"); /* Zotung Chin */
-  test_tag_from_language ("QIN", "dao"); /* Daai Chin */
-  test_tag_from_language ("QIN", "hlt"); /* Matu Chin */
-  test_tag_from_language ("QIN", "mrh"); /* Mara Chin */
-  test_tag_from_language ("QIN", "pck"); /* Paite Chin */
-  test_tag_from_language ("QIN", "sez"); /* Senthang Chin */
-  test_tag_from_language ("QIN", "tcp"); /* Tawr Chin */
-  test_tag_from_language ("QIN", "tcz"); /* Thado Chin */
-  test_tag_from_language ("QIN", "yos"); /* Yos, deprecated by IANA in favor of Zou [zom] */
-  test_tag_from_language ("QIN", "zom"); /* Zou */
-  test_tag_to_language ("QIN", "bgr");   /* no single BCP47 tag for Chin; picking Bawm Chin */
-
   test_language_two_way ("FAR", "fa");
   test_tag_from_language ("FAR", "fa_IR");
 
-  test_language_two_way ("SWA", "aii"); /* Swadaya Aramaic */
-
-  test_language_two_way ("SYR", "syr"); /* Syriac [macrolanguage] */
-  test_tag_from_language ("SYR", "amw"); /* Western Neo-Aramaic */
-  test_tag_from_language ("SYR", "cld"); /* Chaldean Neo-Aramaic */
-  test_tag_from_language ("SYR", "syc"); /* Classical Syriac */
-
-  test_language_two_way ("TUA", "tru"); /* Turoyo Aramaic */
-
   test_language_two_way ("ZHH", "zh-hk"); /* Chinese (Hong Kong) */
 
   test_tag_from_language ("ZHS", "zh"); /* Chinese */
@@ -275,27 +238,6 @@
   test_tag_from_language ("APPH", "und-fonnapa");
   test_tag_to_language ("APPH", "und-fonnapa");
 
-  /* Estrangela Syriac */
-  test_tag_from_language ("SYRE", "aii-Syre");
-  test_tag_from_language ("SYRE", "de-Syre");
-  test_tag_from_language ("SYRE", "syr-Syre");
-  test_tag_from_language ("SYRE", "und-Syre");
-  test_tag_to_language ("SYRE", "und-Syre");
-
-  /* Western Syriac */
-  test_tag_from_language ("SYRJ", "aii-Syrj");
-  test_tag_from_language ("SYRJ", "de-Syrj");
-  test_tag_from_language ("SYRJ", "syr-Syrj");
-  test_tag_from_language ("SYRJ", "und-Syrj");
-  test_tag_to_language ("SYRJ", "und-Syrj");
-
-  /* Eastern Syriac */
-  test_tag_from_language ("SYRN", "aii-Syrn");
-  test_tag_from_language ("SYRN", "de-Syrn");
-  test_tag_from_language ("SYRN", "syr-Syrn");
-  test_tag_from_language ("SYRN", "und-Syrn");
-  test_tag_to_language ("SYRN", "und-Syrn");
-
   /* Test that x-hbot overrides the base language */
   test_tag_from_language ("ABC", "fa-x-hbotabc-zxc");
   test_tag_from_language ("ABC", "fa-ir-x-hbotabc-zxc");
diff --git a/test/fuzzing/Makefile.am b/test/fuzzing/Makefile.am
index 3ea8605..7b0eb94 100644
--- a/test/fuzzing/Makefile.am
+++ b/test/fuzzing/Makefile.am
@@ -30,15 +30,14 @@
 	$(NULL)
 
 hb_fuzzer_SOURCES = \
-	hb-fuzzer.hh \
 	hb-fuzzer.cc \
-	main.cc \
 	$(NULL)
 hb_fuzzer_LDADD = \
 	$(LDADD) \
 	$(NULL)
 hb_fuzzer_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
+	-DMAIN \
 	$(NULL)
 hb_fuzzer_DEPENDENCIES = \
 	lib \
diff --git a/test/fuzzing/hb-fuzzer.cc b/test/fuzzing/hb-fuzzer.cc
index 79f3222..b319a71 100644
--- a/test/fuzzing/hb-fuzzer.cc
+++ b/test/fuzzing/hb-fuzzer.cc
@@ -1,10 +1,10 @@
-#include "hb-fuzzer.hh"
-
+#include <stddef.h>
+#include <hb.h>
 #include <hb-ot.h>
 #include <string.h>
 
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
-{
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+
   hb_blob_t *blob = hb_blob_create((const char *)data, size,
                                    HB_MEMORY_MODE_READONLY, NULL, NULL);
   hb_face_t *face = hb_face_create(blob, 0);
@@ -28,19 +28,6 @@
     hb_buffer_add_utf32(buffer, text32, sizeof(text32)/sizeof(text32[0]), 0, -1);
     hb_buffer_guess_segment_properties(buffer);
     hb_shape(font, buffer, NULL, 0);
-
-    unsigned int len = hb_buffer_get_length (buffer);
-    hb_glyph_info_t *infos = hb_buffer_get_glyph_infos (buffer, NULL);
-    //hb_glyph_position_t *positions = hb_buffer_get_glyph_positions (buffer, NULL);
-    for (unsigned int i = 0; i < len; i++)
-    {
-      hb_glyph_info_t info = infos[i];
-      //hb_glyph_position_t pos = positions[i];
-
-      hb_glyph_extents_t extents;
-      hb_font_get_glyph_extents (font, info.codepoint, &extents);
-    }
-
     hb_buffer_destroy(buffer);
   }
 
@@ -50,3 +37,25 @@
   hb_blob_destroy(blob);
   return 0;
 }
+
+#ifdef MAIN
+#include <iostream>
+#include <iterator>
+#include <fstream>
+#include <assert.h>
+
+std::string FileToString(const std::string &Path) {
+  /* TODO This silently passes if file does not exist.  Fix it! */
+  std::ifstream T(Path.c_str());
+  return std::string((std::istreambuf_iterator<char>(T)),
+                     std::istreambuf_iterator<char>());
+}
+
+int main(int argc, char **argv) {
+  for (int i = 1; i < argc; i++) {
+    std::string s = FileToString(argv[i]);
+    std::cout << argv[i] << std::endl;
+    LLVMFuzzerTestOneInput((const unsigned char*)s.data(), s.size());
+  }
+}
+#endif
diff --git a/test/fuzzing/hb-fuzzer.hh b/test/fuzzing/hb-fuzzer.hh
deleted file mode 100644
index d0c617e..0000000
--- a/test/fuzzing/hb-fuzzer.hh
+++ /dev/null
@@ -1,4 +0,0 @@
-#include <hb.h>
-#include <stddef.h>
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
diff --git a/test/fuzzing/main.cc b/test/fuzzing/main.cc
deleted file mode 100644
index 4692f7b..0000000
--- a/test/fuzzing/main.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "hb-fuzzer.hh"
-
-#include <iostream>
-#include <iterator>
-#include <fstream>
-#include <assert.h>
-
-std::string FileToString(const std::string &Path) {
-  /* TODO This silently passes if file does not exist.  Fix it! */
-  std::ifstream T(Path.c_str());
-  return std::string((std::istreambuf_iterator<char>(T)),
-                     std::istreambuf_iterator<char>());
-}
-
-int main(int argc, char **argv) {
-  for (int i = 1; i < argc; i++) {
-    std::string s = FileToString(argv[i]);
-    std::cout << argv[i] << std::endl;
-    LLVMFuzzerTestOneInput((const unsigned char*)s.data(), s.size());
-  }
-}
diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am
index ea0b28a..c5efe62 100644
--- a/test/shaping/Makefile.am
+++ b/test/shaping/Makefile.am
@@ -43,9 +43,7 @@
 TESTS = \
 	tests/arabic-fallback-shaping.tests \
 	tests/arabic-feature-order.tests \
-	tests/automatic-fractions.tests \
 	tests/cluster.tests \
-	tests/color-fonts.tests \
 	tests/context-matching.tests \
 	tests/cursive-positioning.tests \
 	tests/default-ignorables.tests \
@@ -63,7 +61,6 @@
 	tests/spaces.tests \
 	tests/simple.tests \
 	tests/use.tests \
-	tests/use-marchen.tests \
 	tests/vertical.tests \
 	tests/zero-width-marks.tests \
 	$(NULL)
diff --git a/test/shaping/fonts/sha1sum/15dfc433a135a658b9f4b1a861b5cdd9658ccbb9.ttf b/test/shaping/fonts/sha1sum/15dfc433a135a658b9f4b1a861b5cdd9658ccbb9.ttf
deleted file mode 100644
index 4b80f80..0000000
--- a/test/shaping/fonts/sha1sum/15dfc433a135a658b9f4b1a861b5cdd9658ccbb9.ttf
+++ /dev/null
Binary files differ
diff --git a/test/shaping/fonts/sha1sum/217a934cfe15c548b572c203dceb2befdf026462.ttf b/test/shaping/fonts/sha1sum/217a934cfe15c548b572c203dceb2befdf026462.ttf
deleted file mode 100644
index 12b91a0..0000000
--- a/test/shaping/fonts/sha1sum/217a934cfe15c548b572c203dceb2befdf026462.ttf
+++ /dev/null
Binary files differ
diff --git a/test/shaping/fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf b/test/shaping/fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf
deleted file mode 100644
index 18881fe..0000000
--- a/test/shaping/fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf
+++ /dev/null
Binary files differ
diff --git a/test/shaping/fonts/sha1sum/ee39587d13b2afa5499cc79e45780aa79293bbd4.ttf b/test/shaping/fonts/sha1sum/ee39587d13b2afa5499cc79e45780aa79293bbd4.ttf
deleted file mode 100644
index fa2d0e1..0000000
--- a/test/shaping/fonts/sha1sum/ee39587d13b2afa5499cc79e45780aa79293bbd4.ttf
+++ /dev/null
Binary files differ
diff --git a/test/shaping/fonts/sha1sum/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf b/test/shaping/fonts/sha1sum/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf
deleted file mode 100644
index ed2fab9..0000000
--- a/test/shaping/fonts/sha1sum/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf
+++ /dev/null
Binary files differ
diff --git a/test/shaping/tests/automatic-fractions.tests b/test/shaping/tests/automatic-fractions.tests
deleted file mode 100644
index f9510e2..0000000
--- a/test/shaping/tests/automatic-fractions.tests
+++ /dev/null
@@ -1,3 +0,0 @@
-fonts/sha1sum/15dfc433a135a658b9f4b1a861b5cdd9658ccbb9.ttf::U+0031,U+0032,U+0033,U+2044,U+0034,U+0035,U+0036:[one.numr=0+600|two.numr=1+600|three.numr=2+600|fraction=3+252|four.small=4+600|five.small=5+600|six.small=6+600]
-fonts/sha1sum/15dfc433a135a658b9f4b1a861b5cdd9658ccbb9.ttf:--direction=l --script=arab:U+0031,U+0032,U+0033,U+2044,U+0034,U+0035,U+0036:[one.numr=0+600|two.numr=1+600|three.numr=2+600|fraction=3+252|four.small=4+600|five.small=5+600|six.small=6+600]
-fonts/sha1sum/15dfc433a135a658b9f4b1a861b5cdd9658ccbb9.ttf:--direction=l:U+0661,U+0662,U+0663,U+2044,U+0664,U+0665,U+0666:[uni0661.numr=0+600|uni0662.numr=1+600|uni0663.numr=2+600|fraction=3+252|uni0664.small=4+600|uni0665.small=5+600|uni0666.small=6+600]
diff --git a/test/shaping/tests/color-fonts.tests b/test/shaping/tests/color-fonts.tests
deleted file mode 100644
index 397796a..0000000
--- a/test/shaping/tests/color-fonts.tests
+++ /dev/null
@@ -1 +0,0 @@
-fonts/sha1sum/ee39587d13b2afa5499cc79e45780aa79293bbd4.ttf:--font-funcs=ot --show-extents:U+1F42F:[gid1=0+2963<0,2178,2963,-2788>]
diff --git a/test/shaping/tests/fuzzed.tests b/test/shaping/tests/fuzzed.tests
index 771ac2b..7a5d395 100644
--- a/test/shaping/tests/fuzzed.tests
+++ b/test/shaping/tests/fuzzed.tests
@@ -9,4 +9,3 @@
 fonts/sha1sum/3511ff5c1647150595846ac414c595cccac34f18.ttf:--font-funcs=ot:U+0041:[gid0=0+1000|gid512=0+1000|gid15104=0+1000|gid11004=0+1000|gid3408=0+1000|gid18244=0+1000|gid17872=0+1000|gid17961=0+1000|gid0=0+1000|gid992=0+1000|gid15616=0+1000|gid0=0+1000|gid14151=0+1000|gid20559=0+1000|gid20992=0+1000|gid5440=0+1000|gid256=0+1000|gid0=0+1000|gid10=0+1000|gid8960=0+1000|gid256=0+1000|gid1024=0+1000|gid1490=0+1000|gid0=0+1000|gid768=0+1000|gid4096=0+1000|gid256=0+1000|gid2216=0+1000|gid0=0+1000|gid256=0+1000|gid256=0+1000|gid0=0+1000|gid768=0+1000|gid10752=0+1000|gid11004=0+1000|gid3408=0+1000|gid18244=0+1000|gid17734=0+1000|gid53248=0+1000|gid256=0+1000|gid0=0+1000|gid512=0+1000|gid14848=0+1000|gid10793=0+1000|gid57344=0+1000|gid768=0+1000|gid18227=0+1000|gid20285=0+1000|gid20480=0+1000|gid0=0+1000|gid256=0+1000|gid0=0+1000|gid810=0+1000|gid0=0+1000|gid11004=0+1000|gid3408=0+1000|gid18244=0+1000|gid17734=0+1000|gid53289=0+1000|gid57344=0+1000|gid768=0+1000|gid15667=0+1000|gid71=0+1000|gid0=0+1000|gid20559=0+1000|gid21248=0+1000|gid256=0+1000|gid0=0+1000|gid2816=0+1000|gid2776=0+1000|gid0=0+1000|gid51516=0+1000|gid0=0+1000|gid32=0+1000|gid26209=0+1000|gid28005=0+1000|gid65249=0+1000|gid29690=0+1000|gid0=0+1000|gid51548=0+1000|gid0=0+1000|gid2454=0+1000|gid28783=0+1000|gid29556=0+1000|gid1291=0+1000|gid3458=0+1000|gid80=0+1000|gid0=0+1000|gid2804=0+1000|gid210=0+1000|gid28786=0+1000|gid25968=0+1000|gid45763=0+1000|gid50546=0+1000|gid0=0+1000|gid59136=0+1000|gid0=0+1000|gid38144=0+1000|gid256=0+1000|gid0=0+1000|gid2560=0+1000|gid30208=0+1000|gid52224=0+1000|gid580=0+1000|gid17996=0+1000|gid21504=0+1000|gid6734=0+1000|gid108=0+1000|gid116=0+1000|gid24846=0+1000|gid1024=0+1000|gid0=0+1000|gid255=0+1000|gid65280=0+1000|gid256=0+1000|gid0=0+1000|gid8704=0+1000|gid1345=0+1000|gid23109=0+1000|gid8192=0+1000|gid10823=0+1000|gid21076=0+1000|gid8192=0+1000|gid12877=0+1000|gid20300=0+1000|gid8192=0+1000|gid6738=0+1000|gid20301=0+1000|gid8192=0+1000|gid16980=0+1000|gid21067=0+1000|gid8251=0+1000|gid18944=0+1000|gid255=0+1000|gid65280=0+1000|gid15360=0+1000|gid256=0+1000|gid255=0+1000|gid65280=0+1000|gid256=0+1000|gid768=0+1000|gid255=0+1000|gid65280=0+1000|gid256=0+1000|gid768=0+1000|gid255=0+1000|gid65280=0+1000|gid256=0+1000|gid1024=0+1000|gid12=0+1000|gid65280=0+1000|gid256=0+1000|gid1280=0+1000|gid255=0+1000|gid65280=0+1000|gid256=0+1000|gid1536=0+1000|gid1899=0+1000|gid25970=0+1000|gid110=0+1000|gid11264=0+1000|gid27502=0+1000|gid29285=0+1000|gid12907=0+1000|gid25974=0+1000|gid28160=0+1000|gid14443=0+1000|gid25970=0+1000|gid28288=0+1000|gid3=0+1000|gid118=0+1000|gid18259=0+1000|gid21826=0+1000|gid45716=0+1000|gid46369=0+1000|gid0=0+1000|gid0=0+1000|gid1=0+1000|gid16=0+1000|gid17=0+1000|gid256=0+1000|gid4=0+1000|gid16=0+1000|gid18244=0+1000|gid17734=0+1000|gid28=0+1000|gid12=0+1000|gid0=0+1000|gid284=0+1000|gid0=0+1000|gid28=0+1000|gid18256=0+1000|gid20307=0+1000|gid45114=0+1000|gid47616=0+1000|gid226=0+1000|gid10296=0+1000|gid0=0+1000|gid57927=0+1000|gid1=0+1000|gid0=0+1000|gid0=0+1000|gid21248=0+1000|gid5440=0+1000|gid256=0+1000|gid0=0+1000|gid10=0+1000|gid768=0+1000|gid256=0+1000|gid1024=0+1000|gid512=0+1000|gid0=0+1000|gid297=0+1000|gid16=0+1000|gid24833=0+1000|gid28774=0+1000|gid10794=0+1000|gid2304=0+1000|gid29=0+1000|gid32=0+1000|gid42=0+1000|gid64515=0+1000|gid42=0+1000|gid42=0+1000|gid64525=0+1000|gid20551=0+1000|gid17477=0+1000|gid18128=0+1000|gid10720=0+1000|gid3=0+1000|gid61=0+1000|gid3408=0+1000|gid18244=0+1000|gid17734=0+1000|gid53289=0+1000|gid57344=0+1000|gid768=0+1000|gid15616=0+1000|gid512=0+1000|gid55=0+1000|gid10576=0+1000|gid20307=0+1000|gid0=0+1000|gid255=0+1000|gid56063=0+1000|gid53504=0+1000|gid42=0+1000|gid42=0+1000|gid64525=0+1000|gid12288=0+1000|gid18176=0+1000|gid80=0+1000|gid20307=0+1000|gid1=0+1000|gid0=0+1000|gid62=0+1000]
 fonts/sha1sum/fab39d60d758cb586db5a504f218442cd1395725.ttf:--font-funcs=ot:U+0041,U+0041:[gid0=0+1000|gid0=1+1000]
 fonts/sha1sum/205edd09bd3d141cc9580f650109556cc28b22cb.ttf:--font-funcs=ot:U+0041:[gid0=0+1000]
-fonts/sha1sum/217a934cfe15c548b572c203dceb2befdf026462.ttf:--font-funcs=ot:U+0061,U+0061,U+0061:[]
diff --git a/test/shaping/tests/use-marchen.tests b/test/shaping/tests/use-marchen.tests
deleted file mode 100644
index 6497178..0000000
--- a/test/shaping/tests/use-marchen.tests
+++ /dev/null
@@ -1,35 +0,0 @@
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8F:[u11C8F=0+3000]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C71:[u11C71=0+1600]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8A,U+11CB5:[u11C8A=0+2000|u11CB5=0@-2000,0+0]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C84,U+11C71:[u11C84=0+2200|u11C71=1+1600]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C7E,U+11C8A:[u11C7E=0+2600|u11C8A=1+2000]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8A,U+11C92,U+11CA9:[u11C8A.11C92.11CA9=0+2600]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8A,U+11C94,U+11CA9:[u11C8A.11C94.11CA9=0+2600]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11C92,U+11CA9:[u11C8D.11C92.11CA9=0+2600]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11C94,U+11CA9:[u11C8D.11C94.11CA9=0+2600]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11C9E,U+11CA9:[u11C8D.11C9E.11CA9=0+3200]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11CA0,U+11CA9:[u11C8D.11CA0.11CA9=0+3000]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11C92,U+11CAA:[u11C8D.11C92.11CAA=0+2000]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11C94,U+11CAA:[u11C8D.11C94.11CAA=0+2000]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11C9D,U+11CAA:[u11C8D.11C9D.11CAA=0+2000]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11C9E,U+11CAA:[u11C8D.11C9E.11CAA=0+2600]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11CA0,U+11CAA:[u11C8D.11CA0.11CAA=0+2400]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C80,U+11C72,U+11CAA:[u11C80=0+2400|u11C72.11CAA=1+2000]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8C,U+11CB1,U+11C8D:[u11C8C.11CB1=0+2793|u11C8D=2+2000]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C80,U+11C7C,U+11CB3:[u11C80=0+2400|u11C7C.11CB3=1+2200]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C7F,U+11CB2,U+11C7D:[u11C7F.11CB2=0+2400|u11C7D=2+2000]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11CB2,U+11C81:[u11C8D.11CB2=0+2000|u11C81=2+2400]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8C,U+11CB4,U+11C74:[u11C8C.11CB4=0+2800|u11C74=2+2000]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8A,U+11CA1,U+11CA9,U+11C71:[u11C8A.11CA1.11CA9=0+3000|u11C71=3+1600]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11CA1,U+11CA9,U+11C71:[u11C8D.11CA1.11CA9=0+3000|u11C71=3+1600]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11CA1,U+11CAA,U+11C71:[u11C8D.11CA1.11CAA=0+2400|u11C71=3+1600]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8F,U+11CB0,U+11CB4,U+11CB6:[u11C8F.11CB0.11CB4=0+3600|u11CB6=0@-3200,0+0]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8E,U+11CB0,U+11CB2,U+11CB5:[u11C8E.11CB0.11CB2=0+2000|u11CB5=0@-2000,0+0]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C74,U+11C89,U+11CB2,U+11C75:[u11C74=0+2000|u11C89.11CB2=1+2000|u11C75=3+2000]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C7C,U+11CAA,U+11CB2,U+11C75:[u11C7C.11CAA.11CB2=0+2200|u11C75=3+2000]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C81,U+11C74,U+11CB2,U+11C8B:[u11C81=0+2400|u11C74.11CB2=1+2000|u11C8B=3+2400]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8B,U+11CB3,U+11C74,U+11C8D:[u11C8B.11CB3=0+2400|u11C74=2+2000|u11C8D=3+2000]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C83,U+11CB4,U+11C74,U+11C8D:[u11C83.11CB4=0+2800|u11C74=2+2000|u11C8D=3+2000]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8B,U+11CB3,U+11C74,U+11C8D,U+11C71:[u11C8B.11CB3=0+2400|u11C74=2+2000|u11C8D=3+2000|u11C71=4+1600]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C80,U+11C76,U+11CB1,U+11C75,U+11C8D:[u11C80=0+2400|u11C76.11CB1=1+3200|u11C75=3+2000|u11C8D=4+2000]
-fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C80,U+11C8D,U+11C94,U+11CAA,U+11CB1,U+11C74,U+11C8D:[u11C80=0+2400|u11C8D.11C94.11CAA.11CB1.shorti=1+2600|u11C74=5+2000|u11C8D=6+2000]
diff --git a/test/shaping/tests/vertical.tests b/test/shaping/tests/vertical.tests
index 3586080..8276890 100644
--- a/test/shaping/tests/vertical.tests
+++ b/test/shaping/tests/vertical.tests
@@ -1,3 +1 @@
 fonts/sha1sum/191826b9643e3f124d865d617ae609db6a2ce203.ttf:--direction=t:U+300C:[uni300C.vert=0@-512,-578+0,-1024]
-fonts/sha1sum/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf:--direction=t --font-funcs=ft:U+0041,U+0042:[gid1=0@-654,-2128+0,-2789|gid2=1@-665,-2125+0,-2789]
-fonts/sha1sum/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf:--direction=t --font-funcs=ot:U+0041,U+0042:[gid1=0@-654,-2189+0,-2789|gid2=1@-665,-2189+0,-2789]
diff --git a/util/helper-cairo.cc b/util/helper-cairo.cc
index 2e2952b..8f30eea 100644
--- a/util/helper-cairo.cc
+++ b/util/helper-cairo.cc
@@ -28,7 +28,6 @@
 
 #include <cairo-ft.h>
 #include <hb-ft.h>
-#include FT_MULTIPLE_MASTERS_H
 
 #include "helper-cairo-ansi.hh"
 #ifdef CAIRO_HAS_SVG_SURFACE
@@ -77,8 +76,7 @@
 
   cairo_font_face_t *cairo_face;
   /* We cannot use the FT_Face from hb_font_t, as doing so will confuse hb_font_t because
-   * cairo will reset the face size.  As such, create new face...
-   * TODO Perhaps add API to hb-ft to encapsulate this code. */
+   * cairo will reset the face size.  As such, create new face... */
   FT_Face ft_face = NULL;//hb_ft_font_get_face (font);
   if (!ft_face)
   {
@@ -102,23 +100,7 @@
 					     CAIRO_FONT_WEIGHT_NORMAL);
   }
   else
-  {
-    unsigned int num_coords;
-    const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
-    if (num_coords)
-    {
-      FT_Fixed *ft_coords = (FT_Fixed *) calloc (num_coords, sizeof (FT_Fixed));
-      if (ft_coords)
-      {
-	for (unsigned int i = 0; i < num_coords; i++)
-	  ft_coords[i] = coords[i] << 2;
-	FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
-	free (ft_coords);
-      }
-    }
-
     cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
-  }
   cairo_matrix_t ctm, font_matrix;
   cairo_font_options_t *font_options;
 
diff --git a/util/options.cc b/util/options.cc
index 0f2e207..bc699c1 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -254,47 +254,6 @@
   return true;
 }
 
-static gboolean
-parse_variations (const char *name G_GNUC_UNUSED,
-	        const char *arg,
-	        gpointer    data,
-	        GError    **error G_GNUC_UNUSED)
-{
-  font_options_t *font_opts = (font_options_t *) data;
-  char *s = (char *) arg;
-  char *p;
-
-  font_opts->num_variations = 0;
-  g_free (font_opts->variations);
-  font_opts->variations = NULL;
-
-  if (!*s)
-    return true;
-
-  /* count the variations first, so we can allocate memory */
-  p = s;
-  do {
-    font_opts->num_variations++;
-    p = strchr (p, ',');
-    if (p)
-      p++;
-  } while (p);
-
-  font_opts->variations = (hb_variation_t *) calloc (font_opts->num_variations, sizeof (*font_opts->variations));
-
-  /* now do the actual parsing */
-  p = s;
-  font_opts->num_variations = 0;
-  while (p && *p) {
-    char *end = strchr (p, ',');
-    if (hb_variation_from_string (p, end ? end - p : -1, &font_opts->variations[font_opts->num_variations]))
-      font_opts->num_variations++;
-    p = end ? end + 1 : NULL;
-  }
-
-  return true;
-}
-
 
 void
 view_options_t::add_options (option_parser_t *parser)
@@ -311,7 +270,7 @@
   parser->add_group (entries,
 		     "view",
 		     "View options:",
-		     "Options for output rendering",
+		     "Options controlling output rendering",
 		     this);
 }
 
@@ -340,7 +299,7 @@
   parser->add_group (entries,
 		     "shape",
 		     "Shape options:",
-		     "Options for the shaping process",
+		     "Options controlling the shaping process",
 		     this);
 
   const gchar *features_help = "Comma-separated list of font features\n"
@@ -387,7 +346,7 @@
   parser->add_group (entries2,
 		     "features",
 		     "Features options:",
-		     "Options for font features used",
+		     "Options controlling font features used",
 		     this);
 }
 
@@ -454,30 +413,7 @@
   parser->add_group (entries,
 		     "font",
 		     "Font options:",
-		     "Options for the font",
-		     this);
-
-  const gchar *variations_help = "Comma-separated list of font variations\n"
-    "\n"
-    "    Variations are set globally. The format for specifying variation settings\n"
-    "    follows.  All valid CSS font-variation-settings values other than 'normal'\n"
-    "    and 'inherited' are also accepted, though, not documented below.\n"
-    "\n"
-    "    The format is a tag, optionally followed by an equals sign, followed by a\n"
-    "    number. For example:\n"
-    "\n"
-    "      \"wght=500\"\n"
-    "      \"slnt=-7.5\"\n";
-
-  GOptionEntry entries2[] =
-  {
-    {"variations",	0, 0, G_OPTION_ARG_CALLBACK,	(gpointer) &parse_variations,	variations_help,	"list"},
-    {NULL}
-  };
-  parser->add_group (entries2,
-		     "variations",
-		     "Varitions options:",
-		     "Options for font variations used",
+		     "Options controlling the font",
 		     this);
 }
 
@@ -495,7 +431,7 @@
   parser->add_group (entries,
 		     "text",
 		     "Text options:",
-		     "Options for the input text",
+		     "Options controlling the input text",
 		     this);
 }
 
@@ -523,7 +459,7 @@
   parser->add_group (entries,
 		     "output",
 		     "Output destination & format options:",
-		     "Options for the destination & form of the output",
+		     "Options controlling the destination and form of the output",
 		     this);
 }
 
@@ -625,8 +561,6 @@
   hb_font_set_scale (font, scale_x, scale_y);
   hb_face_destroy (face);
 
-  hb_font_set_variations (font, variations, num_variations);
-
   void (*set_font_funcs) (hb_font_t *) = NULL;
   if (!font_funcs)
   {
@@ -785,7 +719,7 @@
          "    text: [<glyph name or index>=<glyph cluster index within input>@<horizontal displacement>,<vertical displacement>+<horizontal advance>,<vertical advance>|...]\n"
          "    json: [{\"g\": <glyph name or index>, \"ax\": <horizontal advance>, \"ay\": <vertical advance>, \"dx\": <horizontal displacement>, \"dy\": <vertical displacement>, \"cl\": <glyph cluster index within input>}, ...]\n"
          "\nOutput syntax options:",
-		     "Options for the syntax of the output",
+		     "Options controlling the syntax of the output",
 		     this);
 }
 
diff --git a/util/options.hh b/util/options.hh
index 9ed4fd0..919e4f8 100644
--- a/util/options.hh
+++ b/util/options.hh
@@ -285,10 +285,7 @@
 {
   font_options_t (option_parser_t *parser,
 		  int default_font_size_,
-		  unsigned int subpixel_bits_)
-  {
-    variations = NULL;
-    num_variations = 0;
+		  unsigned int subpixel_bits_) {
     default_font_size = default_font_size_;
     subpixel_bits = subpixel_bits_;
     font_file = NULL;
@@ -302,7 +299,6 @@
   }
   ~font_options_t (void) {
     g_free (font_file);
-    free (variations);
     g_free (font_funcs);
     hb_font_destroy (font);
   }
@@ -313,8 +309,6 @@
 
   char *font_file;
   int face_index;
-  hb_variation_t *variations;
-  unsigned int num_variations;
   int default_font_size;
   unsigned int subpixel_bits;
   mutable double font_size_x;
diff --git a/win32/README.txt b/win32/README.txt
index af0dc15..e2ead01 100644
--- a/win32/README.txt
+++ b/win32/README.txt
@@ -7,10 +7,11 @@
 The following are instructions for performing such a build, as there is a

 number of build configurations supported for the build.  Note that for all

 build configurations, the OpenType and Simple TrueType layout (fallback)

-backends are enabled, and this is the base configuration that is built if no

-options (see below) are specified.  A 'clean' target is provided-it is recommended

-that one cleans the build and redo the build if any configuration option changed.

-An 'install' target is also provided to copy the built items in their appropriate

+backends are enabled, as well as the Uniscribe platform shaper, and this

+is the base configuration that is built if no options (see below) are

+specified.  A 'clean' target is provided-it is recommended that one cleans

+the build and redo the build if any configuration option changed.  An

+'install' target is also provided to copy the built items in their appropriate

 locations under $(PREFIX), which is described below.

 

 Invoke the build by issuing the command:

@@ -63,11 +64,11 @@
 

 GRAPHITE2: Enable the Graphite2 shaper, requires the SIL Graphite2 library.

 

-ICU: Enables the build of ICU Unicode functions. Requires the ICU libraries.
+ICU: Enables the build HarfBuzz-ICU, which is now the recommended layout engine

+     for ICU (International Components for Unicode), which deprecated ICU LE.

+     Requires the ICU libraries.

 

-UNISCRIBE: Enable Uniscribe platform shaper support.

-

-DIRECTWRITE: Enable DirectWrite platform shaper support,

+DIRECTWRITE: Enable (experimental) DirectWrite platform shaper support,

              requires a rather recent Windows SDK, and at least Windows Vista/

              Server 2008 with SP2 and platform update.

 

diff --git a/win32/build-rules-msvc.mak b/win32/build-rules-msvc.mak
index bfe0286..03b3833 100644
--- a/win32/build-rules-msvc.mak
+++ b/win32/build-rules-msvc.mak
@@ -23,6 +23,11 @@
 $<
 <<
 
+{..\src\}.cc{$(CFG)\$(PLAT)\harfbuzz-icu\}.obj::
+	$(CXX) $(CFLAGS) $(HB_LIB_CFLAGS) $(HB_ICU_CFLAGS) /Fo$(CFG)\$(PLAT)\harfbuzz-icu\ /c @<<
+$<
+<<
+
 {..\util\}.cc{$(CFG)\$(PLAT)\util\}.obj::
 	$(CXX) $(CFLAGS) $(HB_DEFINES) $(HB_CFLAGS) /Fo$(CFG)\$(PLAT)\util\ /c @<<
 $<
@@ -43,6 +48,7 @@
 
 # Rules for building .lib files
 $(CFG)\$(PLAT)\harfbuzz.lib: $(HARFBUZZ_DLL_FILENAME).dll
+$(CFG)\$(PLAT)\harfbuzz-icu.lib: $(HARFBUZZ_ICU_DLL_FILENAME).dll
 $(CFG)\$(PLAT)\harfbuzz-gobject.lib: $(HARFBUZZ_GOBJECT_DLL_FILENAME).dll
 
 # Rules for linking DLLs
@@ -58,6 +64,12 @@
 <<
 	@-if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;2
 
+$(HARFBUZZ_ICU_DLL_FILENAME).dll: $(CFG)\$(PLAT)\harfbuzz.lib $(harfbuzz_icu_OBJS) $(CFG)\$(PLAT)\harfbuzz-icu
+	link /DLL $(LDFLAGS) $(CFG)\$(PLAT)\harfbuzz.lib $(HB_ICU_DEP_LIBS) /implib:$(CFG)\$(PLAT)\harfbuzz-icu.lib -out:$@ @<<
+$(harfbuzz_icu_OBJS)
+<<
+	@-if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;2
+
 $(HARFBUZZ_GOBJECT_DLL_FILENAME).dll: $(CFG)\$(PLAT)\harfbuzz.lib $(harfbuzz_gobject_OBJS) $(CFG)\$(PLAT)\harfbuzz-gobject
 	link /DLL $(LDFLAGS) $(CFG)\$(PLAT)\harfbuzz.lib $(HB_GOBJECT_DEP_LIBS) /implib:$(CFG)\$(PLAT)\harfbuzz-gobject.lib -out:$@ @<<
 $(harfbuzz_gobject_OBJS)
@@ -119,6 +131,7 @@
 	@-del /f /q $(CFG)\$(PLAT)\*.obj
 	@-if exist $(CFG)\$(PLAT)\util del /f /q $(CFG)\$(PLAT)\util\*.obj
 	@-if exist $(CFG)\$(PLAT)\harfbuzz-gobject del /f /q $(CFG)\$(PLAT)\harfbuzz-gobject\*.obj
+	@-if exist $(CFG)\$(PLAT)\harfbuzz-icu del /f /q $(CFG)\$(PLAT)\harfbuzz-icu\*.obj
 	@-del /f /q $(CFG)\$(PLAT)\harfbuzz\*.obj
 	@-rmdir /s /q $(CFG)\$(PLAT)
 	@-if exist $(CFG)\$(PLAT)\harfbuzz-gobject\hb-gobject-enums.h del $(CFG)\$(PLAT)\harfbuzz-gobject\hb-gobject-enums.h
diff --git a/win32/config-msvc.mak b/win32/config-msvc.mak
index 4cffaea..e0c6468 100644
--- a/win32/config-msvc.mak
+++ b/win32/config-msvc.mak
@@ -12,11 +12,7 @@
 HB_GOBJECT_DEP_LIBS = gobject-2.0.lib $(HB_GLIB_LIBS)
 
 # Freetype is needed for building FreeType support and hb-view
-!if "$(CFG)" == "debug"
-FREETYPE_LIB = freetyped.lib
-!else
 FREETYPE_LIB = freetype.lib
-!endif
 
 # Cairo is needed for building hb-view
 CAIRO_LIB = cairo.lib
@@ -24,9 +20,6 @@
 # Graphite2 is needed for building SIL Graphite2 support
 GRAPHITE2_LIB = graphite2.lib
 
-# Uniscribe is needed for Uniscribe shaping support
-UNISCRIBE_LIB = usp10.lib gdi32.lib rpcrt4.lib user32.lib
-
 # Directwrite is needed for DirectWrite shaping support
 DIRECTWRITE_LIB = dwrite.lib
 
@@ -38,15 +31,17 @@
 HB_SOURCES =	\
 	$(HB_BASE_sources)		\
 	$(HB_FALLBACK_sources)	\
-	$(HB_OT_sources)
+	$(HB_OT_sources)		\
+	$(HB_UNISCRIBE_sources)	\
 
 HB_HEADERS =	\
 	$(HB_BASE_headers)		\
 	$(HB_NODIST_headers)	\
-	$(HB_OT_headers)
+	$(HB_OT_headers)		\
+	$(HB_UNISCRIBE_headers)
 
 # Minimal set of (system) libraries needed for the HarfBuzz DLL
-HB_DEP_LIBS =
+HB_DEP_LIBS = usp10.lib gdi32.lib rpcrt4.lib user32.lib
 
 # We build the HarfBuzz DLL/LIB at least
 HB_LIBS = $(CFG)\$(PLAT)\harfbuzz.lib
@@ -60,12 +55,29 @@
 # Use libtool-style DLL names, if desired
 !if "$(LIBTOOL_DLL_NAME)" == "1"
 HARFBUZZ_DLL_FILENAME = $(CFG)\$(PLAT)\libharfbuzz-0
+HARFBUZZ_ICU_DLL_FILENAME = $(CFG)\$(PLAT)\libharfbuzz-icu-0
 HARFBUZZ_GOBJECT_DLL_FILENAME = $(CFG)\$(PLAT)\libharfbuzz-gobject-0
 !else
 HARFBUZZ_DLL_FILENAME = $(CFG)\$(PLAT)\harfbuzz-vs$(VSVER)
+HARFBUZZ_ICU_DLL_FILENAME = $(CFG)\$(PLAT)\harfbuzz-icu-vs$(VSVER)
 HARFBUZZ_GOBJECT_DLL_FILENAME = $(CFG)\$(PLAT)\harfbuzz-gobject-vs$(VSVER)
 !endif
 
+# Enable HarfBuzz-ICU, if desired
+!if "$(ICU)" == "1"
+HB_ICU_CFLAGS =
+HB_LIBS =	\
+	$(HB_LIBS)	\
+	$(CFG)\$(PLAT)\harfbuzz-icu.lib
+
+# We don't want to re-define int8_t Visual Studio 2008, will cause build breakage
+# as we define it in hb-common.h, and we ought to use the definitions there.
+!if "$(VSVER)" == "9"
+HB_ICU_CFLAGS = /DU_HAVE_INT8_T
+!endif
+
+!endif
+
 # Enable Introspection (enables HarfBuzz-Gobject as well)
 !if "$(INTROSPECTION)" == "1"
 GOBJECT = 1
@@ -112,9 +124,6 @@
 
 # Enable freetype if desired
 !if "$(FREETYPE)" == "1"
-!if "$(FREETYPE_DIR)" != ""
-HB_CFLAGS = $(HB_CFLAGS) /I$(FREETYPE_DIR)
-!endif
 HB_DEFINES = $(HB_DEFINES) /DHAVE_FREETYPE=1
 HB_SOURCES = $(HB_SOURCES) $(HB_FT_sources)
 HB_HEADERS = $(HB_HEADERS) $(HB_FT_headers)
@@ -164,31 +173,10 @@
 	$(CFG)\$(PLAT)\test-unicode.exe				\
 	$(CFG)\$(PLAT)\test-version.exe
 
-!elseif "$(ICU)" == "1"
-# use ICU for Unicode functions
+!else
+# If there is no GLib support, use the built-in UCDN
 # and define some of the macros in GLib's msvc_recommended_pragmas.h
 # to reduce some unneeded build-time warnings
-HB_DEFINES = $(HB_DEFINES) /DHAVE_ICU=1 /DHAVE_ICU_BUILTIN=1
-HB_CFLAGS =	\
-	$(HB_CFLAGS)					\
-	/wd4244							\
-	/D_CRT_SECURE_NO_WARNINGS		\
-	/D_CRT_NONSTDC_NO_WARNINGS
-
-# We don't want ICU to re-define int8_t in VS 2008, will cause build breakage
-# as we define it in hb-common.h, and we ought to use the definitions there.
-!if "$(VSVER)" == "9"
-HB_CFLAGS =	$(HB_CFLAGS) /DU_HAVE_INT8_T
-!endif
-
-HB_SOURCES = $(HB_SOURCES) $(HB_ICU_sources)
-HB_HEADERS = $(HB_HEADERS) $(HB_ICU_headers)
-HB_DEP_LIBS = $(HB_DEP_LIBS) $(HB_ICU_DEP_LIBS)
-!endif
-
-!if "$(UCDN)" != "0"
-# Define some of the macros in GLib's msvc_recommended_pragmas.h
-# to reduce some unneeded build-time warnings
 HB_DEFINES = $(HB_DEFINES) /DHAVE_UCDN=1
 HB_CFLAGS =	\
 	$(HB_CFLAGS)					\
@@ -200,13 +188,6 @@
 HB_SOURCES = $(HB_SOURCES) $(LIBHB_UCDN_sources) $(HB_UCDN_sources)
 !endif
 
-!if "$(UNISCRIBE)" == "1"
-HB_CFLAGS = $(HB_CFLAGS) /DHAVE_UNISCRIBE
-HB_SOURCES = $(HB_SOURCES) $(HB_UNISCRIBE_sources)
-HB_HEADERS = $(HB_HEADERS) $(HB_UNISCRIBE_headers)
-HB_DEP_LIBS = $(HB_DEP_LIBS) $(UNISCRIBE_LIB)
-!endif
-
 !if "$(DIRECTWRITE)" == "1"
 HB_CFLAGS = $(HB_CFLAGS) /DHAVE_DIRECTWRITE
 HB_SOURCES = $(HB_SOURCES) $(HB_DIRECTWRITE_sources)
diff --git a/win32/config.h.win32.in b/win32/config.h.win32.in
index d45cefb..73ad205 100644
--- a/win32/config.h.win32.in
+++ b/win32/config.h.win32.in
@@ -115,7 +115,7 @@
 #define HAVE_UCDN 1
 
 /* Have Uniscribe library */
-/* #undef HAVE_UNISCRIBE */
+#define HAVE_UNISCRIBE 1
 
 /* Define to 1 if you have the <unistd.h> header file. */
 #ifndef _MSC_VER
diff --git a/win32/create-lists-msvc.mak b/win32/create-lists-msvc.mak
index dbd2a57..9b5574b 100644
--- a/win32/create-lists-msvc.mak
+++ b/win32/create-lists-msvc.mak
@@ -59,6 +59,19 @@
 !endif
 !endif
 
+# For HarfBuzz-ICU
+!if "$(ICU)" == "1"
+
+!if [call create-lists.bat header hb_objs.mak harfbuzz_icu_OBJS]
+!endif
+
+!if [for %c in ($(HB_ICU_sources)) do @if "%~xc" == ".cc" @call create-lists.bat file hb_objs.mak ^$(CFG)\^$(PLAT)\harfbuzz-icu\%~nc.obj]
+!endif
+
+!if [call create-lists.bat footer hb_objs.mak]
+!endif
+!endif
+
 # For the utility programs (GLib support is required)
 !if "$(GLIB)" == "1"
 
diff --git a/win32/detectenv-msvc.mak b/win32/detectenv-msvc.mak
index ca09793..83d8786 100644
--- a/win32/detectenv-msvc.mak
+++ b/win32/detectenv-msvc.mak
@@ -110,9 +110,7 @@
 # the resulting binaries
 !if "$(CFG)" == "release"
 CFLAGS_ADD = /MD /O2 /GL /MP
-!if $(VSVER) > 9 && $(VSVER) < 14
-# Undocumented "enhance optimized debugging" switch. Became documented
-# as "/Zo" in VS 2013 Update 3, and is turned on by default in VS 2015.
+!if "$(VSVER)" != "9"
 CFLAGS_ADD = $(CFLAGS_ADD) /d2Zi+
 !endif
 !else
@@ -131,10 +129,7 @@
 !if "$(VALID_CFGSET)" == "TRUE"
 CFLAGS = $(CFLAGS_ADD) /W3 /Zi /I.. /I..\src /I. /I$(PREFIX)\include
 
-!if "$(ADDITIONAL_LIB_DIR)" != ""
-ADDITIONAL_LIB_ARG = /libpath:$(ADDITIONAL_LIB_DIR)
-!endif
-LDFLAGS_BASE = $(LDFLAGS_ARCH) /libpath:$(PREFIX)\lib $(ADDITIONAL_LIB_ARG) /DEBUG
+LDFLAGS_BASE = $(LDFLAGS_ARCH) /libpath:$(PREFIX)\lib /DEBUG
 
 !if "$(CFG)" == "debug"
 LDFLAGS = $(LDFLAGS_BASE)
diff --git a/win32/generate-msvc.mak b/win32/generate-msvc.mak
index 32214eb..7c17a94 100644
--- a/win32/generate-msvc.mak
+++ b/win32/generate-msvc.mak
@@ -22,5 +22,5 @@
 !endif
 
 # Create the build directories
-$(CFG)\$(PLAT)\harfbuzz $(CFG)\$(PLAT)\harfbuzz-gobject $(CFG)\$(PLAT)\util:
-	@-md $@
+$(CFG)\$(PLAT)\harfbuzz $(CFG)\$(PLAT)\harfbuzz-icu $(CFG)\$(PLAT)\harfbuzz-gobject $(CFG)\$(PLAT)\util:
+	@-mkdir -p $@
diff --git a/win32/info-msvc.mak b/win32/info-msvc.mak
index 3ec11d4..bc85dc9 100644
--- a/win32/info-msvc.mak
+++ b/win32/info-msvc.mak
@@ -1,6 +1,6 @@
 # NMake Makefile portion for displaying config info
 
-INC_FEATURES = Fallback OT
+INC_FEATURES = Uniscribe Fallback OT
 BUILT_TOOLS =
 BUILT_LIBRARIES = HarfBuzz
 
@@ -11,8 +11,6 @@
 !if "$(CAIRO_FT)" == "1"
 BUILT_TOOLS = hb-view.exe $(BUILT_TOOLS)
 !endif
-!elseif "$(ICU)" == "1"
-UNICODE_IMPL = ICU
 !else
 UNICODE_IMPL = ucdn
 !endif
@@ -25,14 +23,14 @@
 INC_FEATURES = $(INC_FEATURES) Graphite2
 !endif
 
-!if "$(UNISCRIBE)" == "1"
-INC_FEATURES = $(INC_FEATURES) Uniscribe
-!endif
-
 !if "$(DIRECTWRITE)" == "1"
 INC_FEATURES = $(INC_FEATURES) DirectWrite
 !endif
 
+!if "$(ICU)" == "1"
+BUILT_LIBRARIES = $(BUILT_LIBRARIES) HarfBuzz-ICU
+!endif
+
 !if "$(GOBJECT)" == "1"
 BUILT_LIBRARIES = $(BUILT_LIBRARIES) HarfBuzz-GObject
 !endif
@@ -79,12 +77,9 @@
 	@echo.
 	@echo OPTION: Optional, may be any of the following, use OPTION=1 to enable;
 	@echo multiple OPTION's may be used.  If no OPTION is specified, a default
-	@echo HarfBuzz DLL is built with OpenType and fallback support
+	@echo HarfBuzz DLL is built with OpenType, fallback and Uniscribe support
 	@echo with a bundled Unicode implementation (UCDN).
 	@echo ======
-	@echo UNISCRIBE:
-	@echo Enable Uniscribe support.
-	@echo.
 	@echo DIRECTWRITE:
 	@echo Enable DirectWrite support, requires a recent enough Windows SDK.
 	@echo.
@@ -99,20 +94,20 @@
 	@echo library.  Enables the build of utility programs.
 	@echo.
 	@echo ICU:
-	@echo Enable build with ICU Unicode functions, requires the International
+	@echo Enable the HarfBuzz-ICU layout library, requires the International
 	@echo Components for Unicode (ICU) libraries.
 	@echo.
 	@echo GOBJECT:
 	@echo Enable the HarfBuzz-GObject library, also implies GLib2 support,
 	@echo requires the GNOME GLib2 libraries and tools, notably the glib-mkenums
-	@echo tool script, which will require a PERL interpreter (use
+	@echo tool script, which will require a PERL interpretor (use
 	@echo PERL=^$(PATH_TO_PERL_INTERPRETOR)) if it is not already in your PATH).
 	@echo.
 	@echo INTROSPECTION:
 	@echo Enable the build of introspection files, also implies GObject/GLib2 support,
 	@echo requires the GNOME gobject-introspection libraries and tools.  You will need
 	@echo to ensure the pkg-config (.pc) files can be found for GObject-2.0 and the
-	@echo Python interpreter (that was used to build the gobject-introspection tools)
+	@echo Python interpretor (that was used to build the gobject-introsoection tools)
 	@echo can be found by setting PKG_CONFIG_PATH beforehand, and passing in PYTHON=
 	@echo ^$(PATH_TO_PYTHON_INTERPRETOR) respectively, if python.exe is not already
 	@echo in your PATH.
diff --git a/win32/install.mak b/win32/install.mak
index e0a38e3..fa239ea 100644
--- a/win32/install.mak
+++ b/win32/install.mak
@@ -8,6 +8,9 @@
 	@copy /b $(HARFBUZZ_DLL_FILENAME).dll $(PREFIX)\bin
 	@copy /b $(HARFBUZZ_DLL_FILENAME).pdb $(PREFIX)\bin
 	@copy /b $(CFG)\$(PLAT)\harfbuzz.lib $(PREFIX)\lib
+	@if exist $(HARFBUZZ_ICU_DLL_FILENAME).dll copy /b $(HARFBUZZ_ICU_DLL_FILENAME).dll $(PREFIX)\bin
+	@if exist $(HARFBUZZ_ICU_DLL_FILENAME).dll copy /b $(HARFBUZZ_ICU_DLL_FILENAME).pdb $(PREFIX)\bin
+	@if exist $(HARFBUZZ_ICU_DLL_FILENAME).dll copy /b $(CFG)\$(PLAT)\harfbuzz-icu.lib $(PREFIX)\lib
 	@if exist $(HARFBUZZ_GOBJECT_DLL_FILENAME).dll copy /b $(HARFBUZZ_GOBJECT_DLL_FILENAME).dll $(PREFIX)\bin
 	@if exist $(HARFBUZZ_GOBJECT_DLL_FILENAME).dll copy /b $(HARFBUZZ_GOBJECT_DLL_FILENAME).pdb $(PREFIX)\bin
 	@if exist $(HARFBUZZ_GOBJECT_DLL_FILENAME).dll copy /b $(CFG)\$(PLAT)\harfbuzz-gobject.lib $(PREFIX)\lib
@@ -18,6 +21,7 @@
 	@if exist $(CFG)\$(PLAT)\hb-shape.exe copy /b $(CFG)\$(PLAT)\hb-shape.exe $(PREFIX)\bin
 	@if exist $(CFG)\$(PLAT)\hb-shape.exe copy /b $(CFG)\$(PLAT)\hb-shape.pdb $(PREFIX)\bin
 	@for %h in ($(HB_ACTUAL_HEADERS)) do @copy %h $(PREFIX)\include\harfbuzz
+	@if exist $(HARFBUZZ_ICU_DLL_FILENAME).dll for %h in ($(HB_ICU_headers)) do @copy ..\src\%h $(PREFIX)\include\harfbuzz
 	@if exist $(HARFBUZZ_GOBJECT_DLL_FILENAME).dll for %h in ($(HB_GOBJECT_headers)) do @copy ..\src\%h $(PREFIX)\include\harfbuzz
 	@if exist $(HARFBUZZ_GOBJECT_DLL_FILENAME).dll copy $(CFG)\$(PLAT)\harfbuzz-gobject\hb-gobject-enums.h $(PREFIX)\include\harfbuzz
 	@rem Copy the generated introspection files