Merge remote-tracking branch 'upstream/master' into glyf-rebase
diff --git a/NEWS b/NEWS
index 20bb21b..ef5f487 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,37 @@
+Overview of changes leading to 2.6.1
+Thursday, August 22, 2019
+====================================
+- Fix regression with hb_font_create_sub_font scaling introduced in 2.6.0.
+- Change interpretation of font PTEM size / CoreText font size handling.
+  See https://github.com/harfbuzz/harfbuzz/pull/1484
+- hb-ot-font: Prefer symbol cmap subtable if present.
+- Apply 'dist'/'abvm'/'blwm' features to all scripts.
+- Drop experimental DirectWrite API.
+
+
+Overview of changes leading to 2.6.0
+Tuesday, August 13, 2019
+====================================
+- New OpenType metrics, baseline, and metadata table access APIs.
+- New API to set font variations to a named-instance.
+- New hb-gdi.h header and API for creating hb_face_t from HFONT.
+- Amalgam: Provide a single-file harfbuzz.cc file for easier alternate building.
+- More size-reduction configurable options, enabled by HB_TINY.
+- New API:
++hb_font_set_var_named_instance()
++hb_gdi_face_create()
++hb_ot_layout_baseline_tag_t
++hb_ot_layout_get_baseline()
++hb_ot_meta_tag_t
++hb_ot_meta_get_entry_tags()
++hb_ot_meta_reference_entry()
++hb_ot_metrics_tag_t
++hb_ot_metrics_get_position()
++hb_ot_metrics_get_variation()
++hb_ot_metrics_get_x_variation()
++hb_ot_metrics_get_y_variation()
+
+
 Overview of changes leading to 2.5.3
 Wednesday, June 26, 2019
 ====================================
diff --git a/README.md b/README.md
index ce3e84d..c3cc0c2 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
 [![Travis Build Status](https://travis-ci.org/harfbuzz/harfbuzz.svg?branch=master)](https://travis-ci.org/harfbuzz/harfbuzz)
 [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/0t0flrxpstj9lb9w?svg=true&branch=master)](https://ci.appveyor.com/project/harfbuzz/harfbuzz)
 [![CircleCI Build Status](https://circleci.com/gh/harfbuzz/harfbuzz/tree/master.svg?style=svg)](https://circleci.com/gh/harfbuzz/harfbuzz/tree/master)
+[![OSS-Fuzz Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/harfbuzz.svg)](https://oss-fuzz-build-logs.storage.googleapis.com/index.html)
 [![Coverity Code Health](https://img.shields.io/coverity/scan/5450.svg)](https://scan.coverity.com/projects/behdad-harfbuzz)
 [![Codacy Code Health](https://api.codacy.com/project/badge/Grade/f17f1708783c447488bc8dd317150eaa)](https://app.codacy.com/app/behdad/harfbuzz)
 [![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/master/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz)
diff --git a/README.python.md b/README.python.md
index 7cf091a..d9aaf89 100644
--- a/README.python.md
+++ b/README.python.md
@@ -6,21 +6,21 @@
 sudo apt-get install libgirepository1.0-dev
 ```
 
-And then run autogen.sh (if building from git), and then:
+And then run `autogen.sh` (if building from git), and then:
 
 ```bash
 ./configure --with-gobject --enable-introspection
 ```
 
-Make sure that gobject-introspection is enabled then in the final report.
+Make sure that gobject-introspection is reported enabled then in the `configure` script output.
 
 Compile and install.
 
-Make sure you have the installation lib dir in LD_LIBRARY_PATH, as needed
+Make sure you have the installation lib dir in `LD_LIBRARY_PATH`, as needed
 for the linker to find the library.
 
-Then make sure you also have GI_TYPELIB_PATH pointing to the resulting
-$prefix/lib/girepository-* directory.
+Then make sure you also have `GI_TYPELIB_PATH` pointing to the resulting
+`$prefix/lib/girepository-*` directory.
 
 Make sure you have pygobject installed.  Then check that the following
 import works in your Python interpreter:
@@ -30,7 +30,7 @@
 ```
 
 If it does, you are ready to call HarfBuzz from Python!  Congratulations.
-See src/sample.py.
+See [`src/sample.py`](src/sample.py).
 
 The Python API will change.  Let us know on the mailing list if you are
 using it, and send lots of feedback.
diff --git a/appveyor.yml b/appveyor.yml
index 6daf8d2..7fbcf49 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -3,17 +3,17 @@
 environment:
   matrix:
 
-    - compiler: msvc
-      generator: Visual Studio 14
-      platform: Win32
-      configuration: Debug
-      triplet: x86-windows
+    #- compiler: msvc
+    #  generator: Visual Studio 14
+    #  platform: Win32
+    #  configuration: Debug
+    #  triplet: x86-windows
 
-    - compiler: msvc
-      generator: Visual Studio 14 Win64
-      platform: x64
-      configuration: Debug
-      triplet: x64-windows
+    #- compiler: msvc
+    #  generator: Visual Studio 14 Win64
+    #  platform: x64
+    #  configuration: Debug
+    #  triplet: x64-windows
 
     - compiler: msvc
       generator: Visual Studio 14 ARM
diff --git a/configure.ac b/configure.ac
index cebb10a..ab079fc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [2.5.3],
+        [2.6.1],
         [https://github.com/harfbuzz/harfbuzz/issues/new],
         [harfbuzz],
         [http://harfbuzz.org/])
diff --git a/docs/harfbuzz-docs.xml b/docs/harfbuzz-docs.xml
index 2e4b35c..433c206 100644
--- a/docs/harfbuzz-docs.xml
+++ b/docs/harfbuzz-docs.xml
@@ -133,6 +133,10 @@
       <index id="api-index-full"><title>API Index</title><xi:include href="xml/api-index-full.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></index>
 
+      <index id="api-index-2-6-0" role="2.6.0"><title>Index of new symbols in 2.6.0</title><xi:include href="xml/api-index-2.6.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-2-5-0" role="2.5.0"><title>Index of new symbols in 2.5.0</title><xi:include href="xml/api-index-2.5.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-2-4-0" role="2.4.0"><title>Index of new symbols in 2.4.0</title><xi:include href="xml/api-index-2.4.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-2-3-0" role="2.3.0"><title>Index of new symbols in 2.3.0</title><xi:include href="xml/api-index-2.3.0.xml"><xi:fallback /></xi:include></index>
       <index id="api-index-2-2-0" role="2.2.0"><title>Index of new symbols in 2.2.0</title><xi:include href="xml/api-index-2.2.0.xml"><xi:fallback /></xi:include></index>
       <index id="api-index-2-1-0" role="2.1.0"><title>Index of new symbols in 2.1.0</title><xi:include href="xml/api-index-2.1.0.xml"><xi:fallback /></xi:include></index>
       <index id="api-index-2-0-0" role="2.0.0"><title>Index of new symbols in 2.0.0</title><xi:include href="xml/api-index-2.0.0.xml"><xi:fallback /></xi:include></index>
diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index f8650b0..52b43a9 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -613,7 +613,7 @@
 <SECTION>
 <FILE>hb-ot-meta</FILE>
 hb_ot_meta_t
-hb_ot_meta_get_entries
+hb_ot_meta_get_entry_tags
 hb_ot_meta_reference_entry
 </SECTION>
 
diff --git a/docs/usermanual-opentype-features.xml b/docs/usermanual-opentype-features.xml
index 3eedab3..881af2a 100644
--- a/docs/usermanual-opentype-features.xml
+++ b/docs/usermanual-opentype-features.xml
@@ -139,7 +139,8 @@
       Other features are more generic and can apply to several (or
       any) script, and shaping engines are expected to implement
       them. By default, HarfBuzz activates several of these features
-      on every text run. They include <literal>ccmp</literal>,
+      on every text run. They include <literal>abvm</literal>,
+      <literal>blwm</literal>, <literal>ccmp</literal>,
       <literal>locl</literal>, <literal>mark</literal>,
       <literal>mkmk</literal>, and <literal>rlig</literal>.
     </para>
@@ -147,8 +148,9 @@
       In addition, if the text direction is horizontal, HarfBuzz
       also applies the <literal>calt</literal>,
       <literal>clig</literal>, <literal>curs</literal>,
-      <literal>kern</literal>, <literal>liga</literal>,
-      <literal>rclt</literal>, and <literal>frac</literal> features.
+      <literal>dist</literal>, <literal>kern</literal>,
+      <literal>liga</literal>, <literal>rclt</literal>,
+      and <literal>frac</literal> features.
     </para>
     <para>
       If the text direction is vertical, HarfBuzz applies
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 38197a8..22e765d 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -10,6 +10,7 @@
 	hb-aat-layout-kerx-table.hh \
 	hb-aat-layout-lcar-table.hh \
 	hb-aat-layout-morx-table.hh \
+	hb-aat-layout-opbd-table.hh \
 	hb-aat-layout-trak-table.hh \
 	hb-aat-layout.cc \
 	hb-aat-layout.hh \
diff --git a/src/dev-run.sh b/src/dev-run.sh
deleted file mode 100755
index 82de688..0000000
--- a/src/dev-run.sh
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/bin/bash
-# Suggested setup to use the script:
-#  (on the root of the project)
-#  $ NOCONFIGURE=1 ./autogen.sh && mkdir build && cd build
-#  $ ../configure --with-freetype --with-glib --with-gobject --with-cairo
-#  $ make -j5 && cd ..
-#  $ src/dev-run.sh [FONT-FILE] [TEXT]
-#
-# Or, using cmake:
-#  $ cmake -DHB_CHECK=ON -Bbuild -H. -GNinja && ninja -Cbuild
-#  $ src/dev-run.sh [FONT-FILE] [TEXT]
-#
-# If you want to open the result rendering using a GUI app,
-#  $ src/dev-run.sh open [FONT-FILE] [TEXT]
-#
-# And if you are using iTerm2, you can use the script like this,
-#  $ src/dev-run.sh img [FONT-FILE] [TEXT]
-#
-
-[ $# = 0 ] && echo Usage: "src/dev-run.sh [FONT-FILE] [TEXT]" && exit
-command -v entr >/dev/null 2>&1 || { echo >&2 "This script needs `entr` be installed"; exit 1; }
-
-
-GDB=gdb
-# if gdb doesn't exist, hopefully lldb exist
-command -v $GDB >/dev/null 2>&1 || export GDB="lldb"
-
-
-[ $1 = "open" ] && openimg=1 && shift
-OPEN=xdg-open
-[ "$(uname)" == "Darwin" ] && OPEN=open
-
-
-[ $1 = "img" ] && img=1 && shift
-# http://iterm2.com/documentation-images.html
-osc="\033]"
-if [[ $TERM == screen* ]]; then osc="\033Ptmux;\033\033]"; fi
-st="\a"
-if [[ $TERM == screen* ]]; then st="\a"; fi
-
-
-tmp=tmp.png
-[ -f 'build/build.ninja' ] && CMAKENINJA=TRUE
-# or "fswatch -0 . -e build/ -e .git"
-find src/ | entr printf '\0' | while read -d ""; do
-	clear
-	yes = | head -n`tput cols` | tr -d '\n'
-	if [[ $CMAKENINJA ]]; then
-		ninja -Cbuild hb-shape hb-view && {
-			build/hb-shape $@
-			if [ $openimg ]; then
-				build/hb-view $@ -O png -o $tmp
-				$OPEN $tmp
-			elif [ $img ]; then
-				build/hb-view $@ -O png -o $tmp
-				printf "\n${osc}1337;File=;inline=1:`cat $tmp | base64`${st}\n"
-			else
-				build/hb-view $@
-			fi
-		}
-	else
-		make -Cbuild/src -j5 -s lib && {
-			build/util/hb-shape $@
-			if [ $openimg ]; then
-				build/util/hb-view $@ -O png -o $tmp
-				$OPEN $tmp
-			elif [ $img ]; then
-				build/util/hb-view $@ -O png -o $tmp
-				printf "\n${osc}1337;File=;inline=1:`cat $tmp | base64`${st}\n"
-			else
-				build/util/hb-view $@
-			fi
-		}
-	fi
-done
-
-read -n 1 -p "[C]heck, [D]ebug, [R]estart, [Q]uit? " answer
-case "$answer" in
-c|C )
-	if [[ $CMAKENINJA ]]; then
-		CTEST_OUTPUT_ON_FAILURE=1 CTEST_PARALLEL_LEVEL=5 ninja -Cbuild test
-	else
-		make -Cbuild -j5 check && .ci/fail.sh
-	fi
-;;
-d|D )
-	if [[ $CMAKENINJA ]]; then
-		echo "Not supported on cmake builds yet"
-	else
-		build/libtool --mode=execute $GDB -- build/util/hb-shape $@
-	fi
-;;
-r|R )
-	src/dev-run.sh $@
-;;
-* )
-	exit
-;;
-esac
diff --git a/src/gen-indic-table.py b/src/gen-indic-table.py
index cdf81fe..912b1d7 100755
--- a/src/gen-indic-table.py
+++ b/src/gen-indic-table.py
@@ -133,8 +133,8 @@
 what_short = ["ISC", "IMC"]
 print ('#pragma GCC diagnostic push')
 print ('#pragma GCC diagnostic ignored "-Wunused-macros"')
+cat_defs = []
 for i in range (2):
-	print ()
 	vv = sorted (values[i].keys ())
 	for v in vv:
 		v_no_and = v.replace ('_And_', '_')
@@ -146,10 +146,17 @@
 				raise Exception ("Duplicate short value alias", v, all_shorts[i][s])
 			all_shorts[i][s] = v
 			short[i][v] = s
-		print ("#define %s_%s	%s_%s	%s/* %3d chars; %s */" %
-			(what_short[i], s, what[i], v.upper (),
-			'	'* ((48-1 - len (what[i]) - 1 - len (v)) // 8),
-			values[i][v], v))
+		cat_defs.append ((what_short[i] + '_' + s, what[i] + '_' + v.upper (), str (values[i][v]), v))
+
+maxlen_s = max ([len (c[0]) for c in cat_defs])
+maxlen_l = max ([len (c[1]) for c in cat_defs])
+maxlen_n = max ([len (c[2]) for c in cat_defs])
+for s in what_short:
+	print ()
+	for c in [c for c in cat_defs if s in c[0]]:
+		print ("#define %s %s /* %s chars; %s */" %
+			(c[0].ljust (maxlen_s), c[1].ljust (maxlen_l), c[2].rjust (maxlen_n), c[3]))
+print ()
 print ('#pragma GCC diagnostic pop')
 print ()
 print ("#define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)")
@@ -249,14 +256,14 @@
 print ()
 print ("#undef _")
 for i in range (2):
-	print
+	print ()
 	vv = sorted (values[i].keys ())
 	for v in vv:
 		print ("#undef %s_%s" %
 			(what_short[i], short[i][v]))
 print ()
-print ()
 print ('#endif')
+print ()
 print ("/* == End of generated table == */")
 
 # Maintain at least 30% occupancy in the table */
diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh
index cec63ac..25de8c6 100644
--- a/src/hb-aat-layout-kerx-table.hh
+++ b/src/hb-aat-layout-kerx-table.hh
@@ -830,7 +830,7 @@
     for (unsigned int i = 0; i < count; i++)
     {
       if (st->get_type () == 1)
-        return true;
+	return true;
       st = &StructAfter<SubTable> (*st);
     }
     return false;
@@ -845,7 +845,7 @@
     for (unsigned int i = 0; i < count; i++)
     {
       if (st->u.header.coverage & st->u.header.CrossStream)
-        return true;
+	return true;
       st = &StructAfter<SubTable> (*st);
     }
     return false;
@@ -862,7 +862,7 @@
     {
       if ((st->u.header.coverage & (st->u.header.Variation | st->u.header.CrossStream)) ||
 	  !st->u.header.is_horizontal ())
-        continue;
+	continue;
       v += st->get_kerning (left, right);
       st = &StructAfter<SubTable> (*st);
     }
@@ -883,7 +883,7 @@
       bool reverse;
 
       if (!T::Types::extended && (st->u.header.coverage & st->u.header.Variation))
-        goto skip;
+	goto skip;
 
       if (HB_DIRECTION_IS_HORIZONTAL (c->buffer->props.direction) != st->u.header.is_horizontal ())
 	goto skip;
@@ -897,8 +897,8 @@
       if (!seenCrossStream &&
 	  (st->u.header.coverage & st->u.header.CrossStream))
       {
-        /* Attach all glyphs into a chain. */
-        seenCrossStream = true;
+	/* Attach all glyphs into a chain. */
+	seenCrossStream = true;
 	hb_glyph_position_t *pos = c->buffer->pos;
 	unsigned int count = c->buffer->len;
 	for (unsigned int i = 0; i < count; i++)
diff --git a/src/hb-aat-layout-lcar-table.hh b/src/hb-aat-layout-lcar-table.hh
index 2e45fd2..7063b38 100644
--- a/src/hb-aat-layout-lcar-table.hh
+++ b/src/hb-aat-layout-lcar-table.hh
@@ -38,6 +38,80 @@
 
 typedef ArrayOf<HBINT16> LigCaretClassEntry;
 
+struct lcarFormat0
+{
+  unsigned int get_lig_carets (hb_font_t      *font,
+			       hb_direction_t  direction,
+			       hb_codepoint_t  glyph,
+			       unsigned int    start_offset,
+			       unsigned int   *caret_count /* IN/OUT */,
+			       hb_position_t  *caret_array /* OUT */,
+			       const void     *base) const
+  {
+    const OffsetTo<LigCaretClassEntry>* entry_offset = lookupTable.get_value (glyph,
+									      font->face->get_num_glyphs ());
+    const LigCaretClassEntry& array = entry_offset ? base+*entry_offset : Null (LigCaretClassEntry);
+    if (caret_count)
+    {
+      hb_array_t<const HBINT16> arr = array.sub_array (start_offset, caret_count);
+      for (unsigned int i = 0; i < arr.length; ++i)
+	caret_array[i] = font->em_scale_dir (arr[i], direction);
+    }
+    return array.len;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) && lookupTable.sanitize (c, base)));
+  }
+
+  protected:
+  Lookup<OffsetTo<LigCaretClassEntry>>
+		lookupTable;	/* data Lookup table associating glyphs */
+  public:
+  DEFINE_SIZE_MIN (2);
+};
+
+struct lcarFormat1
+{
+  unsigned int get_lig_carets (hb_font_t      *font,
+			       hb_direction_t  direction,
+			       hb_codepoint_t  glyph,
+			       unsigned int    start_offset,
+			       unsigned int   *caret_count /* IN/OUT */,
+			       hb_position_t  *caret_array /* OUT */,
+			       const void     *base) const
+  {
+    const OffsetTo<LigCaretClassEntry>* entry_offset = lookupTable.get_value (glyph,
+									      font->face->get_num_glyphs ());
+    const LigCaretClassEntry& array = entry_offset ? base+*entry_offset : Null (LigCaretClassEntry);
+    if (caret_count)
+    {
+      hb_array_t<const HBINT16> arr = array.sub_array (start_offset, caret_count);
+      for (unsigned int i = 0; i < arr.length; ++i)
+      {
+	hb_position_t x = 0, y = 0;
+	font->get_glyph_contour_point_for_origin (glyph, arr[i], direction, &x, &y);
+	caret_array[i] = HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
+      }
+    }
+    return array.len;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) && lookupTable.sanitize (c, base)));
+  }
+
+  protected:
+  Lookup<OffsetTo<LigCaretClassEntry>>
+		lookupTable;	/* data Lookup table associating glyphs */
+  public:
+  DEFINE_SIZE_MIN (2);
+};
+
 struct lcar
 {
   static constexpr hb_tag_t tableTag = HB_AAT_TAG_lcar;
@@ -49,45 +123,36 @@
 			       unsigned int   *caret_count /* IN/OUT */,
 			       hb_position_t  *caret_array /* OUT */) const
   {
-    const OffsetTo<LigCaretClassEntry>* entry_offset = lookup.get_value (glyph,
-									 font->face->get_num_glyphs ());
-    const LigCaretClassEntry& array = entry_offset ? this+*entry_offset : Null (LigCaretClassEntry);
-    if (caret_count)
+    switch (format)
     {
-      hb_array_t<const HBINT16> arr = array.sub_array (start_offset, caret_count);
-      switch (format)
-      {
-      case 0:
-	for (unsigned int i = 0; i < arr.length; ++i)
-	  caret_array[i] = font->em_scale_dir (arr[i], direction);
-	break;
-      case 1:
-	for (unsigned int i = 0; i < arr.length; ++i)
-	{
-	  hb_position_t x, y;
-	  font->get_glyph_contour_point_for_origin (glyph, arr[i], direction, &x, &y);
-	  caret_array[i] = HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
-	}
-	break;
-      }
+    case 0: return u.format0.get_lig_carets (font, direction, glyph, start_offset,
+					     caret_count, caret_array, this);
+    case 1: return u.format1.get_lig_carets (font, direction, glyph, start_offset,
+					     caret_count, caret_array, this);
+    default:if (caret_count) *caret_count = 0; return 0;
     }
-    return array.len;
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-			  version.major == 1 &&
-			  lookup.sanitize (c, this)));
+    if (unlikely (!c->check_struct (this) || version.major != 1))
+      return_trace (false);
+
+    switch (format) {
+    case 0: return_trace (u.format0.sanitize (c, this));
+    case 1: return_trace (u.format1.sanitize (c, this));
+    default:return_trace (true);
+    }
   }
 
   protected:
   FixedVersion<>version;	/* Version number of the ligature caret table */
   HBUINT16	format;		/* Format of the ligature caret table. */
-  Lookup<OffsetTo<LigCaretClassEntry>>
-		lookup;		/* data Lookup table associating glyphs */
-
+  union {
+  lcarFormat0	format0;
+  lcarFormat0	format1;
+  } u;
   public:
   DEFINE_SIZE_MIN (8);
 };
diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index 81d7897..2925414 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -226,7 +226,7 @@
       hb_buffer_t *buffer = driver->buffer;
 
       if (buffer->idx == buffer->len && !mark_set)
-        return false;
+	return false;
 
       return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF;
     }
@@ -238,7 +238,7 @@
       /* Looks like CoreText applies neither mark nor current substitution for
        * end-of-text if mark was not explicitly set. */
       if (buffer->idx == buffer->len && !mark_set)
-        return;
+	return;
 
       const GlyphID *replacement;
 
@@ -488,7 +488,7 @@
 
 	unsigned int ligature_idx = 0;
 	unsigned int action;
-        do
+	do
 	{
 	  if (unlikely (!cursor))
 	  {
@@ -976,12 +976,12 @@
       bool reverse;
 
       if (!(subtable->subFeatureFlags & flags))
-        goto skip;
+	goto skip;
 
       if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) &&
 	  HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
 	  bool (subtable->get_coverage() & ChainSubtable<Types>::Vertical))
-        goto skip;
+	goto skip;
 
       /* Buffer contents is always in logical direction.  Determine if
        * we need to reverse before applying this subtable.  We reverse
@@ -1016,15 +1016,15 @@
 		HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
 
       if (!c->buffer->message (c->font, "start chain subtable %d", c->lookup_index))
-        goto skip;
+	goto skip;
 
       if (reverse)
-        c->buffer->reverse ();
+	c->buffer->reverse ();
 
       subtable->apply (c);
 
       if (reverse)
-        c->buffer->reverse ();
+	c->buffer->reverse ();
 
       (void) c->buffer->message (c->font, "end chain subtable %d", c->lookup_index);
 
diff --git a/src/hb-aat-layout-opbd-table.hh b/src/hb-aat-layout-opbd-table.hh
new file mode 100644
index 0000000..4e02340
--- /dev/null
+++ b/src/hb-aat-layout-opbd-table.hh
@@ -0,0 +1,173 @@
+/*
+ * Copyright © 2019  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_AAT_LAYOUT_OPBD_TABLE_HH
+#define HB_AAT_LAYOUT_OPBD_TABLE_HH
+
+#include "hb-aat-layout-common.hh"
+#include "hb-open-type.hh"
+
+/*
+ * opbd -- Optical Bounds
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6opbd.html
+ */
+#define HB_AAT_TAG_opbd HB_TAG('o','p','b','d')
+
+
+namespace AAT {
+
+struct OpticalBounds
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  FWORD		leftSide;
+  FWORD		topSide;
+  FWORD		rightSide;
+  FWORD		bottomSide;
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct opbdFormat0
+{
+  bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
+		   hb_glyph_extents_t *extents, const void *base) const
+  {
+    const OffsetTo<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
+    if (!bounds_offset) return false;
+    const OpticalBounds &bounds = base+*bounds_offset;
+
+    if (extents)
+      *extents = {
+	font->em_scale_x (bounds.leftSide),
+	font->em_scale_y (bounds.topSide),
+	font->em_scale_x (bounds.rightSide),
+	font->em_scale_y (bounds.bottomSide)
+      };
+    return true;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) && lookupTable.sanitize (c, base)));
+  }
+
+  protected:
+  Lookup<OffsetTo<OpticalBounds>>
+		lookupTable;	/* Lookup table associating glyphs with the four
+				 * int16 values for the left-side, top-side,
+				 * right-side, and bottom-side optical bounds. */
+  public:
+  DEFINE_SIZE_MIN (2);
+};
+
+struct opbdFormat1
+{
+  bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
+		   hb_glyph_extents_t *extents, const void *base) const
+  {
+    const OffsetTo<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
+    if (!bounds_offset) return false;
+    const OpticalBounds &bounds = base+*bounds_offset;
+
+    hb_position_t left = 0, top = 0, right = 0, bottom = 0, ignore;
+    if (font->get_glyph_contour_point (glyph_id, bounds.leftSide, &left, &ignore) ||
+	font->get_glyph_contour_point (glyph_id, bounds.topSide, &ignore, &top) ||
+	font->get_glyph_contour_point (glyph_id, bounds.rightSide, &right, &ignore) ||
+	font->get_glyph_contour_point (glyph_id, bounds.bottomSide, &ignore, &bottom))
+    {
+      if (extents)
+	*extents = {left, top, right, bottom};
+      return true;
+    }
+    return false;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) && lookupTable.sanitize (c, base)));
+  }
+
+  protected:
+  Lookup<OffsetTo<OpticalBounds>>
+		lookupTable;	/* Lookup table associating glyphs with the four
+				 * int16 values for the left-side, top-side,
+				 * right-side, and bottom-side optical bounds. */
+  public:
+  DEFINE_SIZE_MIN (2);
+};
+
+struct opbd
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_opbd;
+
+  bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
+		   hb_glyph_extents_t *extents) const
+  {
+    switch (format)
+    {
+    case 0: return u.format0.get_bounds (font, glyph_id, extents, this);
+    case 1: return u.format1.get_bounds (font, glyph_id, extents, this);
+    default:return false;
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this) || version.major != 1))
+      return_trace (false);
+
+    switch (format)
+    {
+    case 0: return_trace (u.format0.sanitize (c, this));
+    case 1: return_trace (u.format1.sanitize (c, this));
+    default:return_trace (true);
+    }
+  }
+
+  protected:
+  FixedVersion<>version;	/* Version number of the optical bounds
+				 * table (0x00010000 for the current version). */
+  HBUINT16	format;		/* Format of the optical bounds table.
+				 * Format 0 indicates distance and Format 1 indicates
+				 * control point. */
+  union {
+  opbdFormat0 format0;
+  opbdFormat1 format1;
+  } u;
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_OPBD_TABLE_HH */
diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh
index 2eace2a..cd272a5 100644
--- a/src/hb-aat-layout-trak-table.hh
+++ b/src/hb-aat-layout-trak-table.hh
@@ -93,13 +93,6 @@
 
   int get_tracking (const void *base, float ptem) const
   {
-    /* CoreText points are CSS pixels (96 per inch),
-     * NOT typographic points (72 per inch).
-     *
-     * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
-     */
-    float csspx = ptem * 96.f / 72.f;
-
     /*
      * Choose track.
      */
@@ -130,10 +123,10 @@
     hb_array_t<const Fixed> size_table ((base+sizeTable).arrayZ, sizes);
     unsigned int size_index;
     for (size_index = 0; size_index < sizes - 1; size_index++)
-      if (size_table[size_index].to_float () >= csspx)
-        break;
+      if (size_table[size_index].to_float () >= ptem)
+	break;
 
-    return roundf (interpolate_at (size_index ? size_index - 1 : 0, csspx,
+    return roundf (interpolate_at (size_index ? size_index - 1 : 0, ptem,
 				   *trackTableEntry, base));
   }
 
@@ -183,7 +176,7 @@
       hb_position_t advance_to_add = c->font->em_scalef_x (tracking);
       foreach_grapheme (buffer, start, end)
       {
-        if (!(buffer->info[start].mask & trak_mask)) continue;
+	if (!(buffer->info[start].mask & trak_mask)) continue;
 	buffer->pos[start].x_advance += advance_to_add;
 	buffer->pos[start].x_offset += offset_to_add;
       }
@@ -196,7 +189,7 @@
       hb_position_t advance_to_add = c->font->em_scalef_y (tracking);
       foreach_grapheme (buffer, start, end)
       {
-        if (!(buffer->info[start].mask & trak_mask)) continue;
+	if (!(buffer->info[start].mask & trak_mask)) continue;
 	buffer->pos[start].y_advance += advance_to_add;
 	buffer->pos[start].y_offset += offset_to_add;
       }
diff --git a/src/hb-array.hh b/src/hb-array.hh
index d60c249..2e7a4fa 100644
--- a/src/hb-array.hh
+++ b/src/hb-array.hh
@@ -181,6 +181,12 @@
   hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const
   { return sub_array (start_offset, &seg_count); }
 
+  template <typename T,
+	    unsigned P = sizeof (Type),
+	    hb_enable_if (P == 1)>
+  const T *as () const
+  { return length < hb_null_size (T) ? &Null (T) : reinterpret_cast<const T *> (arrayZ); }
+
   /* Only call if you allocated the underlying array using malloc() or similar. */
   void free ()
   { ::free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
@@ -281,9 +287,9 @@
       int mid = ((unsigned int) min + (unsigned int) max) / 2;
       int c = array[mid].cmp (x);
       if (c < 0)
-        max = mid - 1;
+	max = mid - 1;
       else if (c > 0)
-        min = mid + 1;
+	min = mid + 1;
       else
       {
 	if (i)
diff --git a/src/hb-blob.cc b/src/hb-blob.cc
index 9ed26bd..006de7d 100644
--- a/src/hb-blob.cc
+++ b/src/hb-blob.cc
@@ -592,7 +592,7 @@
     ceparams.lpSecurityAttributes = nullptr;
     ceparams.hTemplateFile = nullptr;
     fd = CreateFile2 (wchar_file_name, GENERIC_READ, FILE_SHARE_READ,
-                      OPEN_EXISTING, &ceparams);
+		      OPEN_EXISTING, &ceparams);
   }
 #else
   fd = CreateFileW (wchar_file_name, GENERIC_READ, FILE_SHARE_READ, nullptr,
@@ -669,7 +669,7 @@
   }
 
   return hb_blob_create (data, len, HB_MEMORY_MODE_WRITABLE, data,
-                         (hb_destroy_func_t) free);
+			 (hb_destroy_func_t) free);
 
 fread_fail:
   fclose (fp);
diff --git a/src/hb-blob.hh b/src/hb-blob.hh
index cff492f..d85bd82 100644
--- a/src/hb-blob.hh
+++ b/src/hb-blob.hh
@@ -54,13 +54,9 @@
   HB_INTERNAL bool try_make_writable_inplace ();
   HB_INTERNAL bool try_make_writable_inplace_unix ();
 
+  hb_bytes_t as_bytes () const { return hb_bytes_t (data, length); }
   template <typename Type>
-  const Type* as () const
-  {
-    return length < hb_null_size (Type) ? &Null(Type) : reinterpret_cast<const Type *> (data);
-  }
-  hb_bytes_t as_bytes () const
-  { return hb_bytes_t (data, length); }
+  const Type* as () const { return as_bytes ().as<Type> (); }
 
   public:
   hb_object_header_t header;
diff --git a/src/hb-buffer-serialize.cc b/src/hb-buffer-serialize.cc
index 77d997c..d1bcf4d 100644
--- a/src/hb-buffer-serialize.cc
+++ b/src/hb-buffer-serialize.cc
@@ -135,7 +135,7 @@
       hb_font_glyph_to_string (font, info[i].codepoint, g, sizeof (g));
       *p++ = '"';
       for (char *q = g; *q; q++) {
-        if (*q == '"')
+	if (*q == '"')
 	  *p++ = '\\';
 	*p++ = *q;
       }
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index db1978e..bd013a3 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -648,8 +648,8 @@
       if (likely (script != HB_SCRIPT_COMMON &&
 		  script != HB_SCRIPT_INHERITED &&
 		  script != HB_SCRIPT_UNKNOWN)) {
-        props.script = script;
-        break;
+	props.script = script;
+	break;
       }
     }
   }
@@ -1388,7 +1388,7 @@
  **/
 hb_glyph_info_t *
 hb_buffer_get_glyph_infos (hb_buffer_t  *buffer,
-                           unsigned int *length)
+			   unsigned int *length)
 {
   if (length)
     *length = buffer->len;
@@ -1412,7 +1412,7 @@
  **/
 hb_glyph_position_t *
 hb_buffer_get_glyph_positions (hb_buffer_t  *buffer,
-                               unsigned int *length)
+			       unsigned int *length)
 {
   if (!buffer->have_positions)
     buffer->clear_positions ();
@@ -1936,9 +1936,9 @@
     for (i = 0; i < count; i++)
     {
       if (contains && info[i].codepoint == dottedcircle_glyph)
-        result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT;
+	result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT;
       if (contains && info[i].codepoint == 0)
-        result |= HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT;
+	result |= HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT;
     }
     result |= HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH;
     return hb_buffer_diff_flags_t (result);
@@ -1973,12 +1973,12 @@
     for (unsigned int i = 0; i < count; i++)
     {
       if ((unsigned int) abs (buf_pos->x_advance - ref_pos->x_advance) > position_fuzz ||
-          (unsigned int) abs (buf_pos->y_advance - ref_pos->y_advance) > position_fuzz ||
-          (unsigned int) abs (buf_pos->x_offset - ref_pos->x_offset) > position_fuzz ||
-          (unsigned int) abs (buf_pos->y_offset - ref_pos->y_offset) > position_fuzz)
+	  (unsigned int) abs (buf_pos->y_advance - ref_pos->y_advance) > position_fuzz ||
+	  (unsigned int) abs (buf_pos->x_offset - ref_pos->x_offset) > position_fuzz ||
+	  (unsigned int) abs (buf_pos->y_offset - ref_pos->y_offset) > position_fuzz)
       {
-        result |= HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH;
-        break;
+	result |= HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH;
+	break;
       }
       buf_pos++;
       ref_pos++;
diff --git a/src/hb-buffer.h b/src/hb-buffer.h
index ac1d452..d5cb746 100644
--- a/src/hb-buffer.h
+++ b/src/hb-buffer.h
@@ -441,11 +441,11 @@
 
 HB_EXTERN hb_glyph_info_t *
 hb_buffer_get_glyph_infos (hb_buffer_t  *buffer,
-                           unsigned int *length);
+			   unsigned int *length);
 
 HB_EXTERN hb_glyph_position_t *
 hb_buffer_get_glyph_positions (hb_buffer_t  *buffer,
-                               unsigned int *length);
+			       unsigned int *length);
 
 
 HB_EXTERN void
diff --git a/src/hb-common.cc b/src/hb-common.cc
index 9035755..d96f397 100644
--- a/src/hb-common.cc
+++ b/src/hb-common.cc
@@ -67,7 +67,7 @@
     {
       const char *p = strchr (c, ':');
       if (!p)
-        p = c + strlen (c);
+	p = c + strlen (c);
 
 #define OPTION(name, symbol) \
 	if (0 == strncmp (c, name, p - c) && strlen (name) == static_cast<size_t>(p - c)) do { u.opts.symbol = true; } while (0)
@@ -956,7 +956,7 @@
 {
   bool had_equal = parse_char (pp, end, '=');
   bool had_value = parse_uint32 (pp, end, &feature->value) ||
-                   parse_bool (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 equal-sign is ok, but not required. */
diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc
index e8a4fd5..8c9b49c 100644
--- a/src/hb-coretext.cc
+++ b/src/hb-coretext.cc
@@ -49,24 +49,6 @@
 /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
 #define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
 
-static CGFloat
-coretext_font_size_from_ptem (float ptem)
-{
-  /* CoreText points are CSS pixels (96 per inch),
-   * NOT typographic points (72 per inch).
-   *
-   * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
-   */
-  ptem *= 96.f / 72.f;
-  return (CGFloat) (ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : ptem);
-}
-static float
-coretext_font_size_to_ptem (CGFloat size)
-{
-  size *= 72. / 96.;
-  return size <= 0 ? 0 : size;
-}
-
 static void
 release_table_data (void *user_data)
 {
@@ -129,7 +111,7 @@
 release_data (void *info, const void *data, size_t size)
 {
   assert (hb_blob_get_length ((hb_blob_t *) info) == size &&
-          hb_blob_get_data ((hb_blob_t *) info, nullptr) == data);
+	  hb_blob_get_data ((hb_blob_t *) info, nullptr) == data);
 
   hb_blob_destroy ((hb_blob_t *) info);
 }
@@ -251,21 +233,21 @@
       atsFont = CTFontGetPlatformFont (new_ct_font, NULL);
       status = ATSFontGetFileReference (atsFont, &fsref);
       if (status == noErr)
-        new_url = CFURLCreateFromFSRef (NULL, &fsref);
+	new_url = CFURLCreateFromFSRef (NULL, &fsref);
 #else
       new_url = (CFURLRef) CTFontCopyAttribute (new_ct_font, kCTFontURLAttribute);
 #endif
       // Keep reconfigured font if URL cannot be retrieved (seems to be the case
       // on Mac OS 10.12 Sierra), speculative fix for crbug.com/625606
       if (!original_url || !new_url || CFEqual (original_url, new_url)) {
-        CFRelease (ct_font);
-        ct_font = new_ct_font;
+	CFRelease (ct_font);
+	ct_font = new_ct_font;
       } else {
-        CFRelease (new_ct_font);
-        DEBUG_MSG (CORETEXT, ct_font, "Discarding reconfigured CTFont, location changed.");
+	CFRelease (new_ct_font);
+	DEBUG_MSG (CORETEXT, ct_font, "Discarding reconfigured CTFont, location changed.");
       }
       if (new_url)
-        CFRelease (new_url);
+	CFRelease (new_url);
     }
     else
       DEBUG_MSG (CORETEXT, ct_font, "Font copy with empty cascade list failed");
@@ -320,7 +302,8 @@
   if (unlikely (!face_data)) return nullptr;
   CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext;
 
-  CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size_from_ptem (font->ptem));
+  CGFloat font_size = font->ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : font->ptem;
+  CTFontRef ct_font = create_ct_font (cg_font, font_size);
 
   if (unlikely (!ct_font))
   {
@@ -344,7 +327,7 @@
   const hb_coretext_font_data_t *data = font->data.coretext;
   if (unlikely (!data)) return nullptr;
 
-  if (fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) > .5)
+  if (fabs (CTFontGetSize ((CTFontRef) data) - font->ptem) > .5)
   {
     /* XXX-MT-bug
      * Note that evaluating condition above can be dangerous if another thread
@@ -384,7 +367,7 @@
   if (unlikely (hb_object_is_immutable (font)))
     return font;
 
-  hb_font_set_ptem (font, coretext_font_size_to_ptem (CTFontGetSize(ct_font)));
+  hb_font_set_ptem (font, CTFontGetSize (ct_font));
 
   /* Let there be dragons here... */
   font->data.coretext.cmpexch (nullptr, (hb_coretext_font_data_t *) CFRetain (ct_font));
@@ -450,9 +433,9 @@
 hb_bool_t
 _hb_coretext_shape (hb_shape_plan_t    *shape_plan,
 		    hb_font_t          *font,
-                    hb_buffer_t        *buffer,
-                    const hb_feature_t *features,
-                    unsigned int        num_features)
+		    hb_buffer_t        *buffer,
+		    const hb_feature_t *features,
+		    unsigned int        num_features)
 {
   hb_face_t *face = font->face;
   CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext;
@@ -494,7 +477,7 @@
     {
       const hb_aat_feature_mapping_t * mapping = hb_aat_layout_find_feature_mapping (features[i].tag);
       if (!mapping)
-        continue;
+	continue;
 
       active_feature_t feature;
       feature.rec.feature = mapping->aatFeatureType;
@@ -536,7 +519,7 @@
 
       if (event->index != last_index)
       {
-        /* Save a snapshot of active features and the range. */
+	/* Save a snapshot of active features and the range. */
 	range_record_t *range = range_records.push ();
 
 	if (active_features.length)
@@ -597,9 +580,9 @@
 
       if (event->start)
       {
-        active_features.push (event->feature);
+	active_features.push (event->feature);
       } else {
-        active_feature_t *feature = active_features.find (&event->feature);
+	active_feature_t *feature = active_features.find (&event->feature);
 	if (feature)
 	  active_features.remove (feature - active_features.arrayZ);
       }
@@ -717,15 +700,15 @@
 #if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1090
 #  define kCTLanguageAttributeName CFSTR ("NSLanguage")
 #endif
-        CFStringRef lang = CFStringCreateWithCStringNoCopy (kCFAllocatorDefault,
+	CFStringRef lang = CFStringCreateWithCStringNoCopy (kCFAllocatorDefault,
 							    hb_language_to_string (buffer->props.language),
 							    kCFStringEncodingUTF8,
 							    kCFAllocatorNull);
 	if (unlikely (!lang))
-        {
+	{
 	  CFRelease (attr_string);
 	  FAIL ("CFStringCreateWithCStringNoCopy failed");
-        }
+	}
 	CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
 					kCTLanguageAttributeName, lang);
 	CFRelease (lang);
@@ -774,7 +757,7 @@
 	      feature.start < chars_len && feature.start < feature.end)
 	  {
 	    CFRange feature_range = CFRangeMake (feature.start,
-	                                         hb_min (feature.end, chars_len) - feature.start);
+						 hb_min (feature.end, chars_len) - feature.start);
 	    if (feature.value)
 	      CFAttributedStringRemoveAttribute (attr_string, feature_range, kCTKernAttributeName);
 	    else
@@ -798,8 +781,8 @@
       CFRelease (level_number);
       if (unlikely (!options))
       {
-        CFRelease (attr_string);
-        FAIL ("CFDictionaryCreate failed");
+	CFRelease (attr_string);
+	FAIL ("CFDictionaryCreate failed");
       }
 
       CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedStringAndOptions (attr_string, options);
@@ -910,7 +893,7 @@
 	if (!matched)
 	{
 	  CFRange range = CTRunGetStringRange (run);
-          DEBUG_MSG (CORETEXT, run, "Run used fallback font: %ld..%ld",
+	  DEBUG_MSG (CORETEXT, run, "Run used fallback font: %ld..%ld",
 		     range.location, range.location + range.length);
 	  if (!buffer->ensure_inplace (buffer->len + range.length))
 	    goto resize_and_retry;
@@ -938,7 +921,7 @@
 		  continue;
 	      }
 	      if (buffer->unicode->is_default_ignorable (ch))
-	        continue;
+		continue;
 
 	      info->codepoint = notdef;
 	      info->cluster = log_clusters[j];
@@ -983,7 +966,7 @@
   scratch = scratch_saved
 
       { /* Setup glyphs */
-        SCRATCH_SAVE();
+	SCRATCH_SAVE();
 	const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : nullptr;
 	if (!glyphs) {
 	  ALLOCATE_ARRAY (CGGlyph, glyph_buf, num_glyphs, goto resize_and_retry);
@@ -1006,12 +989,12 @@
 	SCRATCH_RESTORE();
       }
       {
-        /* Setup positions.
+	/* Setup positions.
 	 * Note that CoreText does not return advances for glyphs.  As such,
 	 * for all but last glyph, we use the delta position to next glyph as
 	 * advance (in the advance direction only), and for last glyph we set
 	 * whatever is needed to make the whole run's advance add up. */
-        SCRATCH_SAVE();
+	SCRATCH_SAVE();
 	const CGPoint* positions = USE_PTR ? CTRunGetPositionsPtr (run) : nullptr;
 	if (!positions) {
 	  ALLOCATE_ARRAY (CGPoint, position_buf, num_glyphs, goto resize_and_retry);
diff --git a/src/hb-debug.hh b/src/hb-debug.hh
index e6d06e3..a7e52c8 100644
--- a/src/hb-debug.hh
+++ b/src/hb-debug.hh
@@ -296,22 +296,23 @@
     if (plevel) --*plevel;
   }
 
-  ret_t ret (ret_t v,
-	     const char *func = "",
-	     unsigned int line = 0)
+  template <typename T>
+  T ret (T&& v,
+	 const char *func = "",
+	 unsigned int line = 0)
   {
     if (unlikely (returned)) {
       fprintf (stderr, "OUCH, double calls to return_trace().  This is a bug, please report.\n");
-      return v;
+      return hb_forward<T> (v);
     }
 
     _hb_debug_msg<max_level> (what, obj, func, true, plevel ? *plevel : 1, -1,
 			      "return %s (line %d)",
-			      hb_printer_t<ret_t>().print (v), line);
+			      hb_printer_t<decltype (v)>().print (v), line);
     if (plevel) --*plevel;
     plevel = nullptr;
     returned = true;
-    return v;
+    return hb_forward<T> (v);
   }
 
   private:
@@ -413,7 +414,7 @@
 #define TRACE_SANITIZE(this) \
 	hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
-	 " ");
+	 " ")
 #else
 #define TRACE_SANITIZE(this) hb_no_trace_t<bool> trace
 #endif
@@ -425,7 +426,7 @@
 #define TRACE_SERIALIZE(this) \
 	hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \
 	(&c->debug_depth, "SERIALIZE", c, HB_FUNC, \
-	 " ");
+	 " ")
 #else
 #define TRACE_SERIALIZE(this) hb_no_trace_t<bool> trace
 #endif
@@ -437,7 +438,7 @@
 #define TRACE_SUBSET(this) \
   hb_auto_trace_t<HB_DEBUG_SUBSET, bool> trace \
   (&c->debug_depth, c->get_name (), this, HB_FUNC, \
-   " ");
+   " ")
 #else
 #define TRACE_SUBSET(this) hb_no_trace_t<bool> trace
 #endif
@@ -454,7 +455,7 @@
 #define TRACE_DISPATCH(this, format) \
 	hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
-	 "format %d", (int) format);
+	 "format %d", (int) format)
 #else
 #define TRACE_DISPATCH(this, format) hb_no_trace_t<typename context_t::return_t> trace
 #endif
diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc
index c14e9d2..a079563 100644
--- a/src/hb-directwrite.cc
+++ b/src/hb-directwrite.cc
@@ -879,29 +879,12 @@
 				     features, num_features, 0);
 }
 
-/**
- * hb_directwrite_shape_experimental_width:
- * Experimental API to test DirectWrite's justification algorithm.
- *
- * It inserts Kashida at wrong order so don't use the API ever.
- *
- * It doesn't work with cygwin/msys due to header bugs so one
- * should use MSVC toolchain in order to use it for now.
- *
- * @font:
- * @buffer:
- * @features:
- * @num_features:
- * @width:
- *
- * Since: 1.4.2
- **/
-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_UNUSED static bool
+_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 const char *shapers = "directwrite";
   hb_shape_plan_t *shape_plan;
diff --git a/src/hb-directwrite.h b/src/hb-directwrite.h
index de813d0..f837627 100644
--- a/src/hb-directwrite.h
+++ b/src/hb-directwrite.h
@@ -29,11 +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_EXTERN hb_face_t *
 hb_directwrite_face_create (IDWriteFontFace *font_face);
 
diff --git a/src/hb-dispatch.hh b/src/hb-dispatch.hh
index be4a90f..1ce3fac 100644
--- a/src/hb-dispatch.hh
+++ b/src/hb-dispatch.hh
@@ -41,7 +41,7 @@
   private:
   /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
   const Context* thiz () const { return static_cast<const Context *> (this); }
-        Context* thiz ()       { return static_cast<      Context *> (this); }
+	Context* thiz ()       { return static_cast<      Context *> (this); }
   public:
   static constexpr unsigned max_debug_depth = MaxDebugDepth;
   typedef Return return_t;
diff --git a/src/hb-font.cc b/src/hb-font.cc
index 44953c9..ee35966 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -518,9 +518,9 @@
 /**
  * hb_font_funcs_create: (Xconstructor)
  *
- * 
  *
- * Return value: (transfer full): 
+ *
+ * Return value: (transfer full):
  *
  * Since: 0.9.2
  **/
@@ -540,9 +540,9 @@
 /**
  * hb_font_funcs_get_empty:
  *
- * 
  *
- * Return value: (transfer full): 
+ *
+ * Return value: (transfer full):
  *
  * Since: 0.9.2
  **/
@@ -556,9 +556,9 @@
  * hb_font_funcs_reference: (skip)
  * @ffuncs: font functions.
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -572,7 +572,7 @@
  * hb_font_funcs_destroy: (skip)
  * @ffuncs: font functions.
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -592,14 +592,14 @@
 /**
  * hb_font_funcs_set_user_data: (skip)
  * @ffuncs: font functions.
- * @key: 
- * @data: 
- * @destroy: 
- * @replace: 
+ * @key:
+ * @data:
+ * @destroy:
+ * @replace:
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -616,11 +616,11 @@
 /**
  * hb_font_funcs_get_user_data: (skip)
  * @ffuncs: font functions.
- * @key: 
+ * @key:
  *
- * 
  *
- * Return value: (transfer none): 
+ *
+ * Return value: (transfer none):
  *
  * Since: 0.9.2
  **/
@@ -636,7 +636,7 @@
  * hb_font_funcs_make_immutable:
  * @ffuncs: font functions.
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -653,9 +653,9 @@
  * hb_font_funcs_is_immutable:
  * @ffuncs: font functions.
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -667,22 +667,22 @@
 
 
 #define HB_FONT_FUNC_IMPLEMENT(name) \
-                                                                         \
+									 \
 void                                                                     \
 hb_font_funcs_set_##name##_func (hb_font_funcs_t             *ffuncs,    \
-                                 hb_font_get_##name##_func_t  func,      \
-                                 void                        *user_data, \
-                                 hb_destroy_func_t            destroy)   \
+				 hb_font_get_##name##_func_t  func,      \
+				 void                        *user_data, \
+				 hb_destroy_func_t            destroy)   \
 {                                                                        \
   if (hb_object_is_immutable (ffuncs)) {                                 \
     if (destroy)                                                         \
       destroy (user_data);                                               \
     return;                                                              \
   }                                                                      \
-                                                                         \
+									 \
   if (ffuncs->destroy.name)                                              \
     ffuncs->destroy.name (ffuncs->user_data.name);                       \
-                                                                         \
+									 \
   if (func) {                                                            \
     ffuncs->get.f.name = func;                                           \
     ffuncs->user_data.name = user_data;                                  \
@@ -751,13 +751,13 @@
 /**
  * hb_font_get_glyph:
  * @font: a font.
- * @unicode: 
- * @variation_selector: 
- * @glyph: (out): 
+ * @unicode:
+ * @variation_selector:
+ * @glyph: (out):
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -774,12 +774,12 @@
 /**
  * hb_font_get_nominal_glyph:
  * @font: a font.
- * @unicode: 
- * @glyph: (out): 
+ * @unicode:
+ * @glyph: (out):
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 1.2.3
  **/
@@ -794,13 +794,13 @@
 /**
  * hb_font_get_variation_glyph:
  * @font: a font.
- * @unicode: 
- * @variation_selector: 
- * @glyph: (out): 
+ * @unicode:
+ * @variation_selector:
+ * @glyph: (out):
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 1.2.3
  **/
@@ -815,11 +815,11 @@
 /**
  * hb_font_get_glyph_h_advance:
  * @font: a font.
- * @glyph: 
+ * @glyph:
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -833,11 +833,11 @@
 /**
  * hb_font_get_glyph_v_advance:
  * @font: a font.
- * @glyph: 
+ * @glyph:
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -852,7 +852,7 @@
  * hb_font_get_glyph_h_advances:
  * @font: a font.
  *
- * 
+ *
  *
  * Since: 1.8.6
  **/
@@ -870,7 +870,7 @@
  * hb_font_get_glyph_v_advances:
  * @font: a font.
  *
- * 
+ *
  *
  * Since: 1.8.6
  **/
@@ -888,13 +888,13 @@
 /**
  * hb_font_get_glyph_h_origin:
  * @font: a font.
- * @glyph: 
- * @x: (out): 
- * @y: (out): 
+ * @glyph:
+ * @x: (out):
+ * @y: (out):
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -909,13 +909,13 @@
 /**
  * hb_font_get_glyph_v_origin:
  * @font: a font.
- * @glyph: 
- * @x: (out): 
- * @y: (out): 
+ * @glyph:
+ * @x: (out):
+ * @y: (out):
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -930,12 +930,12 @@
 /**
  * hb_font_get_glyph_h_kerning:
  * @font: a font.
- * @left_glyph: 
- * @right_glyph: 
+ * @left_glyph:
+ * @right_glyph:
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -950,12 +950,12 @@
 /**
  * hb_font_get_glyph_v_kerning:
  * @font: a font.
- * @top_glyph: 
- * @bottom_glyph: 
+ * @top_glyph:
+ * @bottom_glyph:
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  * Deprecated: 2.0.0
@@ -971,12 +971,12 @@
 /**
  * hb_font_get_glyph_extents:
  * @font: a font.
- * @glyph: 
- * @extents: (out): 
+ * @glyph:
+ * @extents: (out):
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -991,14 +991,14 @@
 /**
  * hb_font_get_glyph_contour_point:
  * @font: a font.
- * @glyph: 
- * @point_index: 
- * @x: (out): 
- * @y: (out): 
+ * @glyph:
+ * @point_index:
+ * @x: (out):
+ * @y: (out):
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -1013,13 +1013,13 @@
 /**
  * hb_font_get_glyph_name:
  * @font: a font.
- * @glyph: 
- * @name: (array length=size): 
- * @size: 
+ * @glyph:
+ * @name: (array length=size):
+ * @size:
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -1034,13 +1034,13 @@
 /**
  * hb_font_get_glyph_from_name:
  * @font: a font.
- * @name: (array length=len): 
- * @len: 
- * @glyph: (out): 
+ * @name: (array length=len):
+ * @len:
+ * @glyph: (out):
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -1075,12 +1075,12 @@
 /**
  * hb_font_get_glyph_advance_for_direction:
  * @font: a font.
- * @glyph: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
+ * @glyph:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -1095,9 +1095,9 @@
 /**
  * hb_font_get_glyph_advances_for_direction:
  * @font: a font.
- * @direction: 
+ * @direction:
  *
- * 
+ *
  *
  * Since: 1.8.6
  **/
@@ -1116,12 +1116,12 @@
 /**
  * hb_font_get_glyph_origin_for_direction:
  * @font: a font.
- * @glyph: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
+ * @glyph:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -1137,12 +1137,12 @@
 /**
  * hb_font_add_glyph_origin_for_direction:
  * @font: a font.
- * @glyph: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
+ * @glyph:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -1158,12 +1158,12 @@
 /**
  * hb_font_subtract_glyph_origin_for_direction:
  * @font: a font.
- * @glyph: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
+ * @glyph:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -1179,13 +1179,13 @@
 /**
  * hb_font_get_glyph_kerning_for_direction:
  * @font: a font.
- * @first_glyph: 
- * @second_glyph: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
+ * @first_glyph:
+ * @second_glyph:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -1201,13 +1201,13 @@
 /**
  * hb_font_get_glyph_extents_for_origin:
  * @font: a font.
- * @glyph: 
- * @direction: 
- * @extents: (out): 
+ * @glyph:
+ * @direction:
+ * @extents: (out):
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -1223,15 +1223,15 @@
 /**
  * hb_font_get_glyph_contour_point_for_origin:
  * @font: a font.
- * @glyph: 
- * @point_index: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
+ * @glyph:
+ * @point_index:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -1248,11 +1248,11 @@
 /**
  * hb_font_glyph_to_string:
  * @font: a font.
- * @glyph: 
- * @s: (array length=size): 
- * @size: 
+ * @glyph:
+ * @s: (array length=size):
+ * @size:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -1268,13 +1268,13 @@
 /**
  * hb_font_glyph_from_string:
  * @font: a font.
- * @s: (array length=len) (element-type uint8_t): 
- * @len: 
- * @glyph: (out): 
+ * @s: (array length=len) (element-type uint8_t):
+ * @len:
+ * @glyph: (out):
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -1341,9 +1341,9 @@
  * hb_font_create: (Xconstructor)
  * @face: a face.
  *
- * 
  *
- * Return value: (transfer full): 
+ *
+ * Return value: (transfer full):
  *
  * Since: 0.9.2
  **/
@@ -1364,9 +1364,9 @@
  * hb_font_create_sub_font:
  * @parent: parent font.
  *
- * 
  *
- * Return value: (transfer full): 
+ *
+ * Return value: (transfer full):
  *
  * Since: 0.9.2
  **/
@@ -1385,14 +1385,13 @@
 
   font->x_scale = parent->x_scale;
   font->y_scale = parent->y_scale;
+  font->mults_changed ();
   font->x_ppem = parent->x_ppem;
   font->y_ppem = parent->y_ppem;
   font->ptem = parent->ptem;
 
   font->num_coords = parent->num_coords;
-  if (!font->num_coords)
-    font->coords = nullptr;
-  else
+  if (font->num_coords)
   {
     unsigned int size = parent->num_coords * sizeof (parent->coords[0]);
     font->coords = (int *) malloc (size);
@@ -1408,7 +1407,7 @@
 /**
  * hb_font_get_empty:
  *
- * 
+ *
  *
  * Return value: (transfer full)
  *
@@ -1424,9 +1423,9 @@
  * hb_font_reference: (skip)
  * @font: a font.
  *
- * 
  *
- * Return value: (transfer full): 
+ *
+ * Return value: (transfer full):
  *
  * Since: 0.9.2
  **/
@@ -1440,7 +1439,7 @@
  * hb_font_destroy: (skip)
  * @font: a font.
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -1466,14 +1465,14 @@
 /**
  * hb_font_set_user_data: (skip)
  * @font: a font.
- * @key: 
- * @data: 
- * @destroy: 
- * @replace: 
+ * @key:
+ * @data:
+ * @destroy:
+ * @replace:
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -1490,11 +1489,11 @@
 /**
  * hb_font_get_user_data: (skip)
  * @font: a font.
- * @key: 
+ * @key:
  *
- * 
  *
- * Return value: (transfer none): 
+ *
+ * Return value: (transfer none):
  *
  * Since: 0.9.2
  **/
@@ -1509,7 +1508,7 @@
  * hb_font_make_immutable:
  * @font: a font.
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -1529,9 +1528,9 @@
  * hb_font_is_immutable:
  * @font: a font.
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -1571,9 +1570,9 @@
  * hb_font_get_parent:
  * @font: a font.
  *
- * 
  *
- * Return value: (transfer none): 
+ *
+ * Return value: (transfer none):
  *
  * Since: 0.9.2
  **/
@@ -1615,9 +1614,9 @@
  * hb_font_get_face:
  * @font: a font.
  *
- * 
  *
- * Return value: (transfer none): 
+ *
+ * Return value: (transfer none):
  *
  * Since: 0.9.2
  **/
@@ -1632,10 +1631,10 @@
  * hb_font_set_funcs:
  * @font: a font.
  * @klass: (closure font_data) (destroy destroy) (scope notified):
- * @font_data: 
- * @destroy: 
+ * @font_data:
+ * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -1669,16 +1668,16 @@
  * hb_font_set_funcs_data:
  * @font: a font.
  * @font_data: (destroy destroy) (scope notified):
- * @destroy: 
+ * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_font_set_funcs_data (hb_font_t         *font,
-		        void              *font_data,
-		        hb_destroy_func_t  destroy)
+			void              *font_data,
+			hb_destroy_func_t  destroy)
 {
   /* Destroy user_data? */
   if (hb_object_is_immutable (font))
@@ -1699,10 +1698,10 @@
 /**
  * hb_font_set_scale:
  * @font: a font.
- * @x_scale: 
- * @y_scale: 
+ * @x_scale:
+ * @y_scale:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -1722,10 +1721,10 @@
 /**
  * hb_font_get_scale:
  * @font: a font.
- * @x_scale: (out): 
- * @y_scale: (out): 
+ * @x_scale: (out):
+ * @y_scale: (out):
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -1741,10 +1740,10 @@
 /**
  * hb_font_set_ppem:
  * @font: a font.
- * @x_ppem: 
- * @y_ppem: 
+ * @x_ppem:
+ * @y_ppem:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -1763,10 +1762,10 @@
 /**
  * hb_font_get_ppem:
  * @font: a font.
- * @x_ppem: (out): 
- * @y_ppem: (out): 
+ * @x_ppem: (out):
+ * @y_ppem: (out):
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -1815,6 +1814,7 @@
   return font->ptem;
 }
 
+#ifndef HB_NO_VAR
 /*
  * Variations
  */
@@ -1830,7 +1830,6 @@
   font->num_coords = coords_length;
 }
 
-#ifndef HB_NO_VAR
 /**
  * hb_font_set_variations:
  *
@@ -1890,7 +1889,7 @@
  *
  * Sets design coords of a font from a named instance index.
  *
- * Since: REPLACEME
+ * Since: 2.6.0
  */
 void
 hb_font_set_var_named_instance (hb_font_t *font,
@@ -1909,7 +1908,6 @@
   hb_font_set_var_coords_design (font, coords, coords_length);
   free (coords);
 }
-#endif
 
 /**
  * hb_font_set_var_coords_normalized:
@@ -1951,7 +1949,7 @@
 
   return font->coords;
 }
-
+#endif
 
 #ifndef HB_DISABLE_DEPRECATED
 /*
diff --git a/src/hb-font.h b/src/hb-font.h
index e68fd18..9b65187 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -224,7 +224,7 @@
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 1.2.3
  **/
@@ -256,7 +256,7 @@
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 1.2.3
  **/
@@ -272,7 +272,7 @@
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -288,7 +288,7 @@
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -304,7 +304,7 @@
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 1.8.6
  **/
@@ -320,7 +320,7 @@
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 1.8.6
  **/
@@ -336,7 +336,7 @@
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -352,7 +352,7 @@
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -368,7 +368,7 @@
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -384,7 +384,7 @@
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -400,7 +400,7 @@
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -416,7 +416,7 @@
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -432,7 +432,7 @@
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index 2d7f2b9..ec4748c 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -471,7 +471,7 @@
     /* Check whether the given name was actually the name of glyph 0. */
     char buf[128];
     if (!FT_Get_Glyph_Name(ft_face, 0, buf, sizeof (buf)) &&
-        len < 0 ? !strcmp (buf, name) : !strncmp (buf, name, len))
+	len < 0 ? !strcmp (buf, name) : !strncmp (buf, name, len))
       return true;
   }
 
diff --git a/src/hb-gdi.cc b/src/hb-gdi.cc
index 526f1cd..d55085c 100644
--- a/src/hb-gdi.cc
+++ b/src/hb-gdi.cc
@@ -62,7 +62,7 @@
  *
  * Return value: #hb_face_t object corresponding to the given input
  *
- * Since: REPLACEME
+ * Since: 2.6.0
  **/
 hb_face_t *
 hb_gdi_face_create (HFONT hfont)
diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc
index 40ac906..f0f2f8c 100644
--- a/src/hb-graphite2.cc
+++ b/src/hb-graphite2.cc
@@ -340,14 +340,14 @@
       c->num_glyphs = 0;
       if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
       {
-        c->advance = curradv - gr_slot_origin_X(is) * xscale;
-        curradv -= c->advance;
+	c->advance = curradv - gr_slot_origin_X(is) * xscale;
+	curradv -= c->advance;
       }
       else
       {
-        c->advance = 0;
-        clusters[ci].advance += gr_slot_origin_X(is) * xscale - curradv;
-        curradv += clusters[ci].advance;
+	c->advance = 0;
+	clusters[ci].advance += gr_slot_origin_X(is) * xscale - curradv;
+	curradv += clusters[ci].advance;
       }
       ci++;
     }
diff --git a/src/hb-iter.hh b/src/hb-iter.hh
index 8d2ff80..238663e 100644
--- a/src/hb-iter.hh
+++ b/src/hb-iter.hh
@@ -72,7 +72,7 @@
   private:
   /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
   const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
-        iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
+	iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
   public:
 
   /* TODO:
@@ -183,7 +183,7 @@
   private:
   /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
   const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
-        iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
+	iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
   public:
 
   /* Access: Implement __item__(), or __item_at__() if random-access. */
diff --git a/src/hb-kern.hh b/src/hb-kern.hh
index fd5bb9e..99d533c 100644
--- a/src/hb-kern.hh
+++ b/src/hb-kern.hh
@@ -82,11 +82,11 @@
 
 
       if (likely (!kern))
-        goto skip;
+	goto skip;
 
       if (horizontal)
       {
-        if (scale)
+	if (scale)
 	  kern = font->em_scale_x (kern);
 	if (crossStream)
 	{
@@ -104,7 +104,7 @@
       }
       else
       {
-        if (scale)
+	if (scale)
 	  kern = font->em_scale_y (kern);
 	if (crossStream)
 	{
diff --git a/src/hb-machinery.hh b/src/hb-machinery.hh
index 5a2087e..383c469 100644
--- a/src/hb-machinery.hh
+++ b/src/hb-machinery.hh
@@ -225,7 +225,7 @@
 
       if (unlikely (!cmpexch (nullptr, p)))
       {
-        do_destroy (p);
+	do_destroy (p);
 	goto retry;
       }
     }
diff --git a/src/hb-object.hh b/src/hb-object.hh
index 68520f2..c470532 100644
--- a/src/hb-object.hh
+++ b/src/hb-object.hh
@@ -62,7 +62,7 @@
 	old.fini ();
       }
       else {
-        item = nullptr;
+	item = nullptr;
 	l.unlock ();
       }
     } else {
diff --git a/src/hb-open-file.hh b/src/hb-open-file.hh
index f3f4dc0..b053936 100644
--- a/src/hb-open-file.hh
+++ b/src/hb-open-file.hh
@@ -92,9 +92,9 @@
     if (table_count)
     {
       if (start_offset >= tables.len)
-        *table_count = 0;
+	*table_count = 0;
       else
-        *table_count = hb_min (*table_count, tables.len - start_offset);
+	*table_count = hb_min (*table_count, tables.len - start_offset);
 
       const TableRecord *sub_tables = tables.arrayZ + start_offset;
       unsigned int count = *table_count;
diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh
index ad99575..94ee04b 100644
--- a/src/hb-open-type.hh
+++ b/src/hb-open-type.hh
@@ -63,6 +63,14 @@
   operator wide_type () const { return v; }
   bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; }
   bool operator != (const IntType &o) const { return !(*this == o); }
+
+  IntType& operator += (unsigned count) { *this = *this + count; return *this; }
+  IntType& operator -= (unsigned count) { *this = *this - count; return *this; }
+  IntType& operator ++ () { *this += 1; return *this; }
+  IntType& operator -- () { *this -= 1; return *this; }
+  IntType operator ++ (int) { IntType c (*this); ++*this; return c; }
+  IntType operator -- (int) { IntType c (*this); --*this; return c; }
+
   HB_INTERNAL static int cmp (const IntType *a, const IntType *b)
   { return b->cmp (*a); }
   template <typename Type2>
@@ -564,6 +572,8 @@
 
   explicit operator bool () const { return len; }
 
+  void pop () { len--; }
+
   hb_array_t<      Type> as_array ()       { return hb_array (arrayZ, len); }
   hb_array_t<const Type> as_array () const { return hb_array (arrayZ, len); }
 
@@ -606,6 +616,18 @@
     return_trace (true);
   }
 
+  Type* serialize_append (hb_serialize_context_t *c)
+  {
+    TRACE_SERIALIZE (this);
+    len++;
+    if (unlikely (!len || !c->extend (*this)))
+    {
+      len--;
+      return_trace (nullptr);
+    }
+    return_trace (&arrayZ[len - 1]);
+  }
+
   ArrayOf* copy (hb_serialize_context_t *c) const
   {
     TRACE_SERIALIZE (this);
@@ -720,17 +742,40 @@
     return arrayZ[i-1];
   }
   unsigned int get_size () const
-  { return lenP1.static_size + (lenP1 ? lenP1 - 1 : 0) * Type::static_size; }
+  { return lenP1.static_size + get_length () * Type::static_size; }
 
-  bool serialize (hb_serialize_context_t *c,
-		  hb_array_t<const Type> items)
+  unsigned get_length () const { return lenP1 ? lenP1 - 1 : 0; }
+
+  hb_array_t<      Type> as_array ()       { return hb_array (arrayZ, get_length ()); }
+  hb_array_t<const Type> as_array () const { return hb_array (arrayZ, get_length ()); }
+
+  /* Iterator. */
+  typedef hb_array_t<const Type>   iter_t;
+  typedef hb_array_t<      Type> writer_t;
+    iter_t   iter () const { return as_array (); }
+  writer_t writer ()       { return as_array (); }
+  operator   iter_t () const { return   iter (); }
+  operator writer_t ()       { return writer (); }
+
+  bool serialize (hb_serialize_context_t *c, unsigned int items_len)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    c->check_assign (lenP1, items.length + 1);
+    c->check_assign (lenP1, items_len + 1);
     if (unlikely (!c->extend (*this))) return_trace (false);
-    for (unsigned int i = 0; i < items.length; i++)
-      arrayZ[i] = items[i];
+    return_trace (true);
+  }
+  template <typename Iterator,
+	    hb_requires (hb_is_source_of (Iterator, Type))>
+  bool serialize (hb_serialize_context_t *c, Iterator items)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned count = items.len ();
+    if (unlikely (!serialize (c, count))) return_trace (false);
+    /* TODO Umm. Just exhaust the iterator instead?  Being extra
+     * cautious right now.. */
+    for (unsigned i = 0; i < count; i++, ++items)
+      arrayZ[i] = *items;
     return_trace (true);
   }
 
@@ -740,7 +785,7 @@
     TRACE_SANITIZE (this);
     if (unlikely (!sanitize_shallow (c))) return_trace (false);
     if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
-    unsigned int count = lenP1 ? lenP1 - 1 : 0;
+    unsigned int count = get_length ();
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
 	return_trace (false);
@@ -944,7 +989,7 @@
     unsigned int count = Type::TerminationWordCount;
     for (unsigned int i = 0; i < count; i++)
       if (words[i] != 0xFFFFu)
-        return false;
+	return false;
     return true;
   }
 
diff --git a/src/hb-ot-cff2-table.cc b/src/hb-ot-cff2-table.cc
index 33b51fe..0251efa 100644
--- a/src/hb-ot-cff2-table.cc
+++ b/src/hb-ot-cff2-table.cc
@@ -110,12 +110,10 @@
 
   if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
 
-  unsigned int num_coords;
-  const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
   unsigned int fd = fdSelect->get_fd (glyph);
   cff2_cs_interpreter_t<cff2_cs_opset_extents_t, cff2_extents_param_t> interp;
   const byte_str_t str = (*charStrings)[glyph];
-  interp.env.init (str, *this, fd, coords, num_coords);
+  interp.env.init (str, *this, fd, font->coords, font->num_coords);
   cff2_extents_param_t  param;
   param.init ();
   if (unlikely (!interp.interpret (param))) return false;
diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index d79b549..48ce881 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -74,153 +74,201 @@
 
 struct CmapSubtableFormat4
 {
-  struct segment_plan
+
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  HBUINT16* serialize_endcode_array (hb_serialize_context_t *c,
+				     Iterator it)
   {
-    HBUINT16 start_code;
-    HBUINT16 end_code;
-    bool use_delta;
-  };
+    HBUINT16 *endCode = c->start_embed<HBUINT16> ();
+    hb_codepoint_t prev_endcp = 0xFFFF;
 
-  bool serialize (hb_serialize_context_t *c,
-		  const hb_subset_plan_t *plan,
-		  const hb_sorted_vector_t<segment_plan> &segments)
+    + it
+    | hb_apply ([&] (const hb_item_type<Iterator> _)
+		{
+		  if (prev_endcp != 0xFFFF && prev_endcp + 1u != _.first)
+		  {
+		    HBUINT16 end_code;
+		    end_code = prev_endcp;
+		    c->copy<HBUINT16> (end_code);
+		  }
+		  prev_endcp = _.first;
+		})
+    ;
+
+    {
+      // last endCode
+      HBUINT16 endcode;
+      endcode = prev_endcp;
+      if (unlikely (!c->copy<HBUINT16> (endcode))) return nullptr;
+      // There must be a final entry with end_code == 0xFFFF.
+      if (prev_endcp != 0xFFFF)
+      {
+	HBUINT16 finalcode;
+	finalcode = 0xFFFF;
+	if (unlikely (!c->copy<HBUINT16> (finalcode))) return nullptr;
+      }
+    }
+
+    return endCode;
+  }
+
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  HBUINT16* serialize_startcode_array (hb_serialize_context_t *c,
+				       Iterator it)
   {
-    TRACE_SERIALIZE (this);
+    HBUINT16 *startCode = c->start_embed<HBUINT16> ();
+    hb_codepoint_t prev_cp = 0xFFFF;
 
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    + it
+    | hb_apply ([&] (const hb_item_type<Iterator> _)
+		{
+		  if (prev_cp == 0xFFFF || prev_cp + 1u != _.first)
+		  {
+		    HBUINT16 start_code;
+		    start_code = _.first;
+		    c->copy<HBUINT16> (start_code);
+		  }
 
+		  prev_cp = _.first;
+		})
+    ;
+
+    // There must be a final entry with end_code == 0xFFFF.
+    if (it.len () == 0 || prev_cp != 0xFFFF)
+    {
+      HBUINT16 finalcode;
+      finalcode = 0xFFFF;
+      if (unlikely (!c->copy<HBUINT16> (finalcode))) return nullptr;
+    }
+
+    return startCode;
+  }
+
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  HBINT16* serialize_idDelta_array (hb_serialize_context_t *c,
+				     Iterator it,
+				     HBUINT16 *endCode,
+				     HBUINT16 *startCode,
+				     unsigned segcount)
+  {
+    unsigned i = 0;
+    hb_codepoint_t last_gid = 0, start_gid = 0, last_cp = 0xFFFF;
+    bool use_delta = true;
+
+    HBINT16 *idDelta = c->start_embed<HBINT16> ();
+    if ((char *)idDelta - (char *)startCode != (int) segcount * (int) HBINT16::static_size)
+      return nullptr;
+
+    + it
+    | hb_apply ([&] (const hb_item_type<Iterator> _)
+		{
+		  if (_.first == startCode[i])
+		  {
+		    use_delta = true;
+		    start_gid = _.second;
+		  }
+		  else if (_.second != last_gid + 1) use_delta = false;
+
+		  if (_.first == endCode[i])
+		  {
+		    HBINT16 delta;
+		    if (use_delta) delta = (int)start_gid - (int)startCode[i];
+		    else delta = 0;
+		    c->copy<HBINT16> (delta);
+
+		    i++;
+		  }
+
+		  last_gid = _.second;
+		  last_cp = _.first;
+		})
+    ;
+
+    if (it.len () == 0 || last_cp != 0xFFFF)
+    {
+      HBINT16 delta;
+      delta = 1;
+      if (unlikely (!c->copy<HBINT16> (delta))) return nullptr;
+    }
+
+    return idDelta;
+  }
+
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  HBUINT16* serialize_rangeoffset_glyid (hb_serialize_context_t *c,
+					 Iterator it,
+					 HBUINT16 *endCode,
+					 HBUINT16 *startCode,
+					 HBINT16 *idDelta,
+					 unsigned segcount)
+  {
+    HBUINT16 *idRangeOffset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
+    if (unlikely (!c->check_success (idRangeOffset))) return nullptr;
+    if (unlikely ((char *)idRangeOffset - (char *)idDelta != (int) segcount * (int) HBINT16::static_size)) return nullptr;
+
+    + hb_range (segcount)
+    | hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; })
+    | hb_apply ([&] (const unsigned i)
+		{
+		  idRangeOffset[i] = 2 * (c->start_embed<HBUINT16> () - idRangeOffset - i);
+
+		  + it
+		  | hb_filter ([&] (const hb_item_type<Iterator> _) { return _.first >= startCode[i] && _.first <= endCode[i]; })
+		  | hb_apply ([&] (const hb_item_type<Iterator> _)
+			      {
+				HBUINT16 glyID;
+				glyID = _.second;
+				c->copy<HBUINT16> (glyID);
+			      })
+		  ;
+
+
+		})
+    ;
+
+    return idRangeOffset;
+  }
+
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  void serialize (hb_serialize_context_t *c,
+		  Iterator it)
+  {
+    unsigned table_initpos = c->length ();
+    if (unlikely (!c->extend_min (*this))) return;
     this->format = 4;
-    this->length = get_sub_table_size (segments);
 
-    this->segCountX2 = segments.length * 2;
-    this->entrySelector = hb_max (1u, hb_bit_storage (segments.length)) - 1;
+    //serialize endCode[]
+    HBUINT16 *endCode = serialize_endcode_array (c, it);
+    if (unlikely (!endCode)) return;
+
+    unsigned segcount = (c->length () - min_size) / HBUINT16::static_size;
+
+    // 2 bytes of padding.
+    if (unlikely (!c->allocate_size<HBUINT16> (HBUINT16::static_size))) return; // 2 bytes of padding.
+
+   // serialize startCode[]
+    HBUINT16 *startCode = serialize_startcode_array (c, it);
+    if (unlikely (!startCode)) return;
+
+    //serialize idDelta[]
+    HBINT16 *idDelta = serialize_idDelta_array (c, it, endCode, startCode, segcount);
+    if (unlikely (!idDelta)) return;
+
+    HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, it, endCode, startCode, idDelta, segcount);
+    if (unlikely (!c->check_success (idRangeOffset))) return;
+
+    if (unlikely (!c->check_assign(this->length, c->length () - table_initpos))) return;
+    this->segCountX2 = segcount * 2;
+    this->entrySelector = hb_max (1u, hb_bit_storage (segcount)) - 1;
     this->searchRange = 2 * (1u << this->entrySelector);
-    this->rangeShift = segments.length * 2 > this->searchRange
-		       ? 2 * segments.length - this->searchRange
+    this->rangeShift = segcount * 2 > this->searchRange
+		       ? 2 * segcount - this->searchRange
 		       : 0;
-
-    HBUINT16 *end_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
-    c->allocate_size<HBUINT16> (HBUINT16::static_size); // 2 bytes of padding.
-    HBUINT16 *start_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
-    HBINT16 *id_delta = c->allocate_size<HBINT16> (HBUINT16::static_size * segments.length);
-    HBUINT16 *id_range_offset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
-
-    if (id_range_offset == nullptr)
-      return_trace (false);
-
-    for (unsigned int i = 0; i < segments.length; i++)
-    {
-      end_count[i] = segments[i].end_code;
-      start_count[i] = segments[i].start_code;
-      if (segments[i].use_delta)
-      {
-	hb_codepoint_t cp = segments[i].start_code;
-	hb_codepoint_t start_gid = 0;
-	if (unlikely (!plan->new_gid_for_codepoint (cp, &start_gid) && cp != 0xFFFF))
-	  return_trace (false);
-	id_delta[i] = start_gid - segments[i].start_code;
-      } else {
-	id_delta[i] = 0;
-	unsigned int num_codepoints = segments[i].end_code - segments[i].start_code + 1;
-	HBUINT16 *glyph_id_array = c->allocate_size<HBUINT16> (HBUINT16::static_size * num_codepoints);
-	if (glyph_id_array == nullptr)
-	  return_trace (false);
-	// From the cmap spec:
-	//
-	// id_range_offset[i]/2
-	// + (cp - segments[i].start_code)
-	// + (id_range_offset + i)
-	// =
-	// glyph_id_array + (cp - segments[i].start_code)
-	//
-	// So, solve for id_range_offset[i]:
-	//
-	// id_range_offset[i]
-	// =
-	// 2 * (glyph_id_array - id_range_offset - i)
-	id_range_offset[i] = 2 * (glyph_id_array - id_range_offset - i);
-	for (unsigned int j = 0; j < num_codepoints; j++)
-	{
-	  hb_codepoint_t cp = segments[i].start_code + j;
-	  hb_codepoint_t new_gid = 0;
-	  if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
-	    return_trace (false);
-	  glyph_id_array[j] = new_gid;
-	}
-      }
-    }
-
-    return_trace (true);
-  }
-
-  static size_t get_sub_table_size (const hb_sorted_vector_t<segment_plan> &segments)
-  {
-    size_t segment_size = 0;
-    for (unsigned int i = 0; i < segments.length; i++)
-    {
-      // Parallel array entries
-      segment_size +=
-	    2  // end count
-	  + 2  // start count
-	  + 2  // delta
-	  + 2; // range offset
-
-      if (!segments[i].use_delta)
-	// Add bytes for the glyph index array entries for this segment.
-	segment_size += (segments[i].end_code - segments[i].start_code + 1) * 2;
-    }
-
-    return min_size
-	+ 2 // Padding
-	+ segment_size;
-  }
-
-  static bool create_sub_table_plan (const hb_subset_plan_t *plan,
-				     hb_sorted_vector_t<segment_plan> *segments)
-  {
-    segment_plan *segment = nullptr;
-    hb_codepoint_t last_gid = 0;
-
-    hb_codepoint_t cp = HB_SET_VALUE_INVALID;
-    while (plan->unicodes->next (&cp)) {
-      hb_codepoint_t new_gid = 0;
-      if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
-      {
-	DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
-	return false;
-      }
-
-      /* Stop adding to cmap if we are now outside of unicode BMP. */
-      if (cp > 0xFFFF) break;
-
-      if (!segment ||
-	  cp != segment->end_code + 1u)
-      {
-	segment = segments->push ();
-	segment->start_code = cp;
-	segment->end_code = cp;
-	segment->use_delta = true;
-      } else {
-	segment->end_code = cp;
-	if (last_gid + 1u != new_gid)
-	  // gid's are not consecutive in this segment so delta
-	  // cannot be used.
-	  segment->use_delta = false;
-      }
-
-      last_gid = new_gid;
-    }
-
-    // There must be a final entry with end_code == 0xFFFF. Check if we need to add one.
-    if (segment == nullptr || segment->end_code != 0xFFFF)
-    {
-      segment = segments->push ();
-      segment->start_code = 0xFFFF;
-      segment->end_code = 0xFFFF;
-      segment->use_delta = true;
-    }
-
-    return true;
   }
 
   struct accelerator_t
@@ -489,15 +537,6 @@
     return_trace (c->check_struct (this) && groups.sanitize (c));
   }
 
-  bool serialize (hb_serialize_context_t *c,
-		  const hb_sorted_vector_t<CmapSubtableLongGroup> &group_data)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!groups.serialize (c, group_data.as_array ()))) return_trace (false);
-    return_trace (true);
-  }
-
   protected:
   HBUINT16	format;		/* Subtable format; set to 12. */
   HBUINT16	reserved;	/* Reserved; set to 0. */
@@ -517,17 +556,56 @@
 	   group.glyphID + (u - group.startCharCode) : 0; }
 
 
-  bool serialize (hb_serialize_context_t *c,
-		  const hb_sorted_vector_t<CmapSubtableLongGroup> &groups_data)
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  void serialize (hb_serialize_context_t *c,
+		  Iterator it)
   {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (it.len () == 0) return;
+    unsigned table_initpos = c->length ();
+    if (unlikely (!c->extend_min (*this))) return;
+
+    hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF;
+    hb_codepoint_t glyphID = 0;
+
+    + it
+    | hb_apply ([&] (const hb_item_type<Iterator> _)
+	      {
+		if (startCharCode == 0xFFFF)
+		{
+		  startCharCode = _.first;
+		  endCharCode = _.first;
+		  glyphID = _.second;
+		}
+		else if (!_is_gid_consecutive (endCharCode, startCharCode, glyphID, _.first, _.second))
+		{
+		  CmapSubtableLongGroup  grouprecord;
+		  grouprecord.startCharCode = startCharCode;
+		  grouprecord.endCharCode = endCharCode;
+		  grouprecord.glyphID = glyphID;
+		  c->copy<CmapSubtableLongGroup> (grouprecord);
+
+		  startCharCode = _.first;
+		  endCharCode = _.first;
+		  glyphID = _.second;
+		}
+		else
+		{
+		  endCharCode = _.first;
+		}
+	      })
+    ;
+
+    CmapSubtableLongGroup record;
+    record.startCharCode = startCharCode;
+    record.endCharCode = endCharCode;
+    record.glyphID = glyphID;
+    c->copy<CmapSubtableLongGroup> (record);
 
     this->format = 12;
     this->reserved = 0;
-    this->length = get_sub_table_size (groups_data);
-
-    return_trace (CmapSubtableLongSegmented<CmapSubtableFormat12>::serialize (c, groups_data));
+    this->length = c->length () - table_initpos;
+    this->groups.len = (this->length - min_size)/CmapSubtableLongGroup::static_size;
   }
 
   static size_t get_sub_table_size (const hb_sorted_vector_t<CmapSubtableLongGroup> &groups_data)
@@ -535,46 +613,15 @@
     return 16 + 12 * groups_data.length;
   }
 
-  static bool create_sub_table_plan (const hb_subset_plan_t *plan,
-				     hb_sorted_vector_t<CmapSubtableLongGroup> *groups_out)
-  {
-    CmapSubtableLongGroup *group = nullptr;
-
-    hb_codepoint_t cp = HB_SET_VALUE_INVALID;
-    while (plan->unicodes->next (&cp)) {
-      hb_codepoint_t new_gid = 0;
-      if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
-      {
-	DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
-	return false;
-      }
-
-      if (!group || !_is_gid_consecutive (group, cp, new_gid))
-      {
-	group = groups_out->push ();
-	group->startCharCode = cp;
-	group->endCharCode = cp;
-	group->glyphID = new_gid;
-      }
-      else group->endCharCode = cp;
-    }
-
-    DEBUG_MSG(SUBSET, nullptr, "cmap");
-    for (unsigned int i = 0; i < groups_out->length; i++) {
-      CmapSubtableLongGroup& group = (*groups_out)[i];
-      DEBUG_MSG(SUBSET, nullptr, "  %d: U+%04X-U+%04X, gid %d-%d", i, (uint32_t) group.startCharCode, (uint32_t) group.endCharCode, (uint32_t) group.glyphID, (uint32_t) group.glyphID + ((uint32_t) group.endCharCode - (uint32_t) group.startCharCode));
-    }
-
-    return true;
-  }
-
  private:
-  static bool _is_gid_consecutive (CmapSubtableLongGroup *group,
+  static bool _is_gid_consecutive (hb_codepoint_t endCharCode,
+				   hb_codepoint_t startCharCode,
+				   hb_codepoint_t glyphID,
 				   hb_codepoint_t cp,
 				   hb_codepoint_t new_gid)
   {
-    return (cp - 1 == group->endCharCode) &&
-	new_gid == group->glyphID + (cp - group->startCharCode);
+    return (cp - 1 == endCharCode) &&
+	new_gid == glyphID + (cp - startCharCode);
   }
 
 };
@@ -756,12 +803,10 @@
 		  hb_codepoint_t *glyph) const
   {
     switch (u.format) {
-#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
     case  0: return u.format0 .get_glyph (codepoint, glyph);
+    case  4: return u.format4 .get_glyph (codepoint, glyph);
     case  6: return u.format6 .get_glyph (codepoint, glyph);
     case 10: return u.format10.get_glyph (codepoint, glyph);
-#endif
-    case  4: return u.format4 .get_glyph (codepoint, glyph);
     case 12: return u.format12.get_glyph (codepoint, glyph);
     case 13: return u.format13.get_glyph (codepoint, glyph);
     case 14:
@@ -771,12 +816,10 @@
   void collect_unicodes (hb_set_t *out) const
   {
     switch (u.format) {
-#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
     case  0: u.format0 .collect_unicodes (out); return;
+    case  4: u.format4 .collect_unicodes (out); return;
     case  6: u.format6 .collect_unicodes (out); return;
     case 10: u.format10.collect_unicodes (out); return;
-#endif
-    case  4: u.format4 .collect_unicodes (out); return;
     case 12: u.format12.collect_unicodes (out); return;
     case 13: u.format13.collect_unicodes (out); return;
     case 14:
@@ -784,17 +827,28 @@
     }
   }
 
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  void serialize (hb_serialize_context_t *c,
+		  Iterator it,
+		  unsigned format)
+  {
+    switch (format) {
+    case  4: u.format4.serialize (c, it);  return;
+    case 12: u.format12.serialize (c, it); return;
+    default: return;
+    }
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
     switch (u.format) {
-#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
     case  0: return_trace (u.format0 .sanitize (c));
+    case  4: return_trace (u.format4 .sanitize (c));
     case  6: return_trace (u.format6 .sanitize (c));
     case 10: return_trace (u.format10.sanitize (c));
-#endif
-    case  4: return_trace (u.format4 .sanitize (c));
     case 12: return_trace (u.format12.sanitize (c));
     case 13: return_trace (u.format13.sanitize (c));
     case 14: return_trace (u.format14.sanitize (c));
@@ -805,12 +859,10 @@
   public:
   union {
   HBUINT16		format;		/* Format identifier */
-#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
   CmapSubtableFormat0	format0;
+  CmapSubtableFormat4	format4;
   CmapSubtableFormat6	format6;
   CmapSubtableFormat10	format10;
-#endif
-  CmapSubtableFormat4	format4;
   CmapSubtableFormat12	format12;
   CmapSubtableFormat13	format13;
   CmapSubtableFormat14	format14;
@@ -839,6 +891,32 @@
 		  subtable.sanitize (c, base));
   }
 
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  EncodingRecord* copy (hb_serialize_context_t *c,
+			Iterator it,
+			unsigned format,
+			void *base,
+			/* INOUT */ unsigned *objidx) const
+  {
+    TRACE_SERIALIZE (this);
+    auto *out = c->embed (this);
+    if (unlikely (!out)) return_trace (nullptr);
+    out->subtable = 0;
+
+    if (*objidx == 0)
+    {
+      CmapSubtable *cmapsubtable = c->push<CmapSubtable> ();
+      unsigned origin_length = c->length ();
+      cmapsubtable->serialize (c, it, format);
+      if (c->length () - origin_length > 0) *objidx = c->pop_pack ();
+      else c->pop_discard ();
+    }
+
+    c->add_link (out->subtable, *objidx, base);
+    return_trace (out);
+  }
+
   HBUINT16	platformID;	/* Platform ID. */
   HBUINT16	encodingID;	/* Platform-specific encoding ID. */
   LOffsetTo<CmapSubtable>
@@ -851,182 +929,62 @@
 {
   static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap;
 
-  struct subset_plan
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  void serialize (hb_serialize_context_t *c,
+		  Iterator it,
+		  const EncodingRecord *unicode_bmp,
+		  const EncodingRecord *unicode_ucs4,
+		  const EncodingRecord *ms_bmp,
+		  const EncodingRecord *ms_ucs4)
   {
-    size_t final_size () const
-    {
-      return 4 // header
-	  +  8 * num_enc_records
-	  +  CmapSubtableFormat4::get_sub_table_size (this->format4_segments)
-	  +  CmapSubtableFormat12::get_sub_table_size (this->format12_groups);
-    }
+    if (unlikely (!c->extend_min ((*this))))  return;
+    this->version = 0;
 
-    unsigned int num_enc_records;
-    bool has_unicode_bmp;
-    bool has_unicode_ucs4;
-    bool has_ms_bmp;
-    bool has_ms_ucs4;
-    hb_sorted_vector_t<CmapSubtableFormat4::segment_plan> format4_segments;
-    hb_sorted_vector_t<CmapSubtableLongGroup> format12_groups;
-  };
+    unsigned numTables = (unicode_bmp ? 1 : 0) + (unicode_ucs4 ? 1 : 0) + (ms_bmp ? 1 : 0) + (ms_ucs4 ? 1 : 0);
+    if (unlikely (!c->check_assign(this->encodingRecord.len, numTables))) return;
 
-  bool _create_plan (const hb_subset_plan_t *plan,
-		     subset_plan *cmap_plan) const
-  {
-    cmap_plan->has_unicode_bmp = find_subtable (0, 3);
-    cmap_plan->has_unicode_ucs4 = find_subtable (0, 4);
-    cmap_plan->has_ms_bmp = find_subtable (3, 1);
-    cmap_plan->has_ms_ucs4 = find_subtable (3, 10);
-    cmap_plan->num_enc_records = cmap_plan->has_unicode_bmp + cmap_plan->has_unicode_ucs4 + cmap_plan->has_ms_bmp + cmap_plan->has_ms_ucs4;
+    unsigned format4objidx = 0, format12objidx = 0;
+    if (unicode_bmp) c->copy (unicode_bmp, it, 4u, this, &format4objidx);
+    if (unicode_ucs4) c->copy (unicode_ucs4, it, 12u, this, &format12objidx);
+    if (ms_bmp) c->copy (ms_bmp, it, 4u, this, &format4objidx);
+    if (ms_ucs4) c->copy (ms_ucs4, it, 12u, this, &format12objidx);
 
-    if (unlikely (!CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments)))
-      return false;
-
-    if (!find_subtable (12)) return true;
-    return CmapSubtableFormat12::create_sub_table_plan (plan, &cmap_plan->format12_groups);
   }
 
-  bool _subset (const hb_subset_plan_t *plan,
-		const subset_plan &cmap_subset_plan,
-		size_t dest_sz,
-		void *dest) const
+  bool subset (hb_subset_context_t *c) const
   {
-    hb_serialize_context_t c (dest, dest_sz);
+    TRACE_SUBSET (this);
 
-    cmap *table = c.start_serialize<cmap> ();
-    if (unlikely (!c.extend_min (*table)))
-    {
-      return false;
-    }
+    cmap *cmap_prime = c->serializer->start_embed<cmap> ();
+    if (unlikely (!c->serializer->check_success (cmap_prime))) return_trace (false);
 
-    table->version = 0;
+    const EncodingRecord *unicode_bmp = find_encodingrec (0, 3);
+    const EncodingRecord *unicode_ucs4 = find_encodingrec (0, 4);
+    const EncodingRecord *ms_bmp = find_encodingrec (3, 1);
+    const EncodingRecord *ms_ucs4 = find_encodingrec (3, 10);
+    bool has_format12 = find_subtable (12);
 
-    if (unlikely (!table->encodingRecord.serialize (&c, cmap_subset_plan.num_enc_records))) return false;
+    if (unlikely (!unicode_bmp && !ms_bmp)) return_trace (false);
+    if (unlikely (has_format12 && (!unicode_ucs4 && !ms_ucs4))) return_trace (false);
 
-    // TODO(grieger): Convert the below to a for loop
-    int enc_index = 0;
-    int unicode_bmp_index = 0;
-    int unicode_ucs4_index = 0;
-    int ms_bmp_index = 0;
-    int ms_ucs4_index = 0;
 
-    // Format 4, Plat 0 Encoding Record
-    if (cmap_subset_plan.has_unicode_bmp)
-    {
-      unicode_bmp_index = enc_index;
-      EncodingRecord &format4_plat0_rec = table->encodingRecord[enc_index++];
-      format4_plat0_rec.platformID = 0; // Unicode
-      format4_plat0_rec.encodingID = 3;
-    }
+    auto it =
+    + hb_iter (c->plan->unicodes)
+    | hb_map ([&] (hb_codepoint_t _)
+		 {
+		   hb_codepoint_t new_gid = HB_MAP_VALUE_INVALID;
+		   c->plan->new_gid_for_codepoint (_, &new_gid);
+		   return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (_, new_gid);
+		 })
+    | hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _)
+	      {
+		return (_.second != HB_MAP_VALUE_INVALID);
+	      })
+    ;
 
-    // Format 12, Plat 0 Encoding Record
-    if (cmap_subset_plan.has_unicode_ucs4)
-    {
-      unicode_ucs4_index = enc_index;
-      EncodingRecord &format12_rec = table->encodingRecord[enc_index++];
-      format12_rec.platformID = 0; // Unicode
-      format12_rec.encodingID = 4; // Unicode UCS-4
-    }
-
-    // Format 4, Plat 3 Encoding Record
-    if (cmap_subset_plan.has_ms_bmp)
-    {
-      ms_bmp_index = enc_index;
-      EncodingRecord &format4_plat3_rec = table->encodingRecord[enc_index++];
-      format4_plat3_rec.platformID = 3; // Windows
-      format4_plat3_rec.encodingID = 1; // Unicode BMP
-    }
-
-    // Format 12, Plat 3 Encoding Record
-    if (cmap_subset_plan.has_ms_ucs4)
-    {
-      ms_ucs4_index = enc_index;
-      EncodingRecord &format12_rec = table->encodingRecord[enc_index++];
-      format12_rec.platformID = 3; // Windows
-      format12_rec.encodingID = 10; // Unicode UCS-4
-    }
-
-    // Write out format 4 sub table
-    {
-      if (unlikely (!cmap_subset_plan.has_unicode_bmp && !cmap_subset_plan.has_ms_bmp)) return false;
-      EncodingRecord &format4_rec = cmap_subset_plan.has_unicode_bmp?
-				     table->encodingRecord[unicode_bmp_index]:
-				     table->encodingRecord[ms_bmp_index];
-      CmapSubtable &subtable = format4_rec.subtable.serialize (&c, table);
-      if (cmap_subset_plan.has_unicode_bmp && cmap_subset_plan.has_ms_bmp)
-      	table->encodingRecord[ms_bmp_index].subtable = (unsigned int) format4_rec.subtable;
-      subtable.u.format = 4;
-
-      CmapSubtableFormat4 &format4 = subtable.u.format4;
-      if (unlikely (!format4.serialize (&c, plan, cmap_subset_plan.format4_segments)))
-	return false;
-    }
-
-    // Write out format 12 sub table.
-    if (cmap_subset_plan.format12_groups)
-    {
-      if (unlikely (!cmap_subset_plan.has_unicode_ucs4 && !cmap_subset_plan.has_ms_ucs4)) return false;
-      EncodingRecord &format12_rec = cmap_subset_plan.has_unicode_ucs4?
-				     table->encodingRecord[unicode_ucs4_index]:
-				     table->encodingRecord[ms_ucs4_index];
-
-      CmapSubtable &subtable = format12_rec.subtable.serialize (&c, table);
-      if (cmap_subset_plan.has_unicode_ucs4 && cmap_subset_plan.has_ms_ucs4)
-      	table->encodingRecord[ms_ucs4_index].subtable = (unsigned int) format12_rec.subtable;
-      subtable.u.format = 12;
-
-      CmapSubtableFormat12 &format12 = subtable.u.format12;
-      if (unlikely (!format12.serialize (&c, cmap_subset_plan.format12_groups)))
-	return false;
-    }
-    else
-    {
-      // FIXME: Merge this with above or, remove and tweak #final_size
-      // and rebase all the tests expectations
-      HBUINT32 empty;
-      empty = 0;
-      for (unsigned int i = 0; i < 4; ++i) c.copy (empty);
-    }
-
-    c.end_serialize ();
-
-    return true;
-  }
-
-  bool subset (hb_subset_plan_t *plan) const
-  {
-    subset_plan cmap_subset_plan;
-
-    if (unlikely (!_create_plan (plan, &cmap_subset_plan)))
-    {
-      DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cmap subsetting plan.");
-      return false;
-    }
-
-    // We now know how big our blob needs to be
-    size_t dest_sz = cmap_subset_plan.final_size ();
-    void *dest = malloc (dest_sz);
-    if (unlikely (!dest)) {
-      DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for cmap subset output", (unsigned long) dest_sz);
-      return false;
-    }
-
-    if (unlikely (!_subset (plan, cmap_subset_plan, dest_sz, dest)))
-    {
-      DEBUG_MSG(SUBSET, nullptr, "Failed to perform subsetting of cmap.");
-      free (dest);
-      return false;
-    }
-
-    // all done, write the blob into dest
-    hb_blob_t *cmap_prime = hb_blob_create ((const char *) dest,
-					    dest_sz,
-					    HB_MEMORY_MODE_READONLY,
-					    dest,
-					    free);
-    bool result =  plan->add_table (HB_OT_TAG_cmap, cmap_prime);
-    hb_blob_destroy (cmap_prime);
-    return result;
+    cmap_prime->serialize (c->serializer, it, unicode_bmp, unicode_ucs4, ms_bmp, ms_ucs4);
+    return_trace (true);
   }
 
   const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const
@@ -1035,6 +993,15 @@
 
     const CmapSubtable *subtable;
 
+    /* Symbol subtable.
+     * Prefer symbol if available.
+     * https://github.com/harfbuzz/harfbuzz/issues/1918 */
+    if ((subtable = this->find_subtable (3, 0)))
+    {
+      if (symbol) *symbol = true;
+      return subtable;
+    }
+
     /* 32-bit subtables. */
     if ((subtable = this->find_subtable (3, 10))) return subtable;
     if ((subtable = this->find_subtable (0, 6))) return subtable;
@@ -1047,13 +1014,6 @@
     if ((subtable = this->find_subtable (0, 1))) return subtable;
     if ((subtable = this->find_subtable (0, 0))) return subtable;
 
-    /* Symbol subtable. */
-    if ((subtable = this->find_subtable (3, 0)))
-    {
-      if (symbol) *symbol = true;
-      return subtable;
-    }
-
     /* Meh. */
     return &Null (CmapSubtable);
   }
@@ -1220,6 +1180,16 @@
     return &(this+result.subtable);
   }
 
+  const EncodingRecord *find_encodingrec (unsigned int platform_id,
+				    unsigned int encoding_id) const
+  {
+    EncodingRecord key;
+    key.platformID = platform_id;
+    key.encodingID = encoding_id;
+
+    return encodingRecord.as_array ().bsearch (key);
+  }
+
   bool find_subtable (unsigned format) const
   {
     auto it =
diff --git a/src/hb-ot-color-cbdt-table.hh b/src/hb-ot-color-cbdt-table.hh
index 7955cf6..e85e4ad 100644
--- a/src/hb-ot-color-cbdt-table.hh
+++ b/src/hb-ot-color-cbdt-table.hh
@@ -251,7 +251,7 @@
       unsigned int firstGlyphIndex = indexSubtablesZ[i].firstGlyphIndex;
       unsigned int lastGlyphIndex = indexSubtablesZ[i].lastGlyphIndex;
       if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex)
-        return &indexSubtablesZ[i];
+	return &indexSubtablesZ[i];
     }
     return nullptr;
   }
diff --git a/src/hb-ot-color-cpal-table.hh b/src/hb-ot-color-cpal-table.hh
index 9ec2957..76df889 100644
--- a/src/hb-ot-color-cpal-table.hh
+++ b/src/hb-ot-color-cpal-table.hh
@@ -147,7 +147,7 @@
       unsigned int count = hb_min ((unsigned) hb_max ((int) (numColors - start_offset), 0), *color_count);
       *color_count = count;
       for (unsigned int i = 0; i < count; i++)
-        colors[i] = segment_colors[i]; /* Bound-checked read. */
+	colors[i] = segment_colors[i]; /* Bound-checked read. */
     }
     return numColors;
   }
diff --git a/src/hb-ot-color-sbix-table.hh b/src/hb-ot-color-sbix-table.hh
index 8a915a6..824b960 100644
--- a/src/hb-ot-color-sbix-table.hh
+++ b/src/hb-ot-color-sbix-table.hh
@@ -173,11 +173,11 @@
     {
       unsigned count = table->strikes.len;
       if (unlikely (!count))
-        return Null(SBIXStrike);
+	return Null(SBIXStrike);
 
       unsigned int requested_ppem = hb_max (font->x_ppem, font->y_ppem);
       if (!requested_ppem)
-        requested_ppem = 1<<30; /* Choose largest strike. */
+	requested_ppem = 1<<30; /* Choose largest strike. */
       /* TODO Add DPI sensitivity as well? */
       unsigned int best_i = 0;
       unsigned int best_ppem = table->get_strike (0).ppem;
@@ -201,7 +201,7 @@
       HBUINT8	signature[8];
       struct
       {
-        struct
+	struct
 	{
 	  HBUINT32	length;
 	  Tag		type;
@@ -226,7 +226,7 @@
       /* Following code is safe to call even without data.
        * But faster to short-circuit. */
       if (!has_data ())
-        return false;
+	return false;
 
       int x_offset = 0, y_offset = 0;
       unsigned int strike_ppem = 0;
diff --git a/src/hb-ot-face-table-list.hh b/src/hb-ot-face-table-list.hh
index 9799edd..30bab5c 100644
--- a/src/hb-ot-face-table-list.hh
+++ b/src/hb-ot-face-table-list.hh
@@ -115,6 +115,7 @@
 HB_OT_TABLE (AAT, lcar)
 HB_OT_TABLE (AAT, ltag)
 HB_OT_TABLE (AAT, feat)
+// HB_OT_TABLE (AAT, opbd)
 #endif
 
 /* OpenType color fonts. */
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 530b6be..5b6fe27 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -209,20 +209,20 @@
 #ifndef HB_NO_OT_FONT_GLYPH_NAMES
 static hb_bool_t
 hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
-                      void *font_data,
-                      hb_codepoint_t glyph,
-                      char *name, unsigned int size,
-                      void *user_data HB_UNUSED)
+		      void *font_data,
+		      hb_codepoint_t glyph,
+		      char *name, unsigned int size,
+		      void *user_data HB_UNUSED)
 {
   const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
   return ot_face->post->get_glyph_name (glyph, name, size);
 }
 static hb_bool_t
 hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
-                           void *font_data,
-                           const char *name, int len,
-                           hb_codepoint_t *glyph,
-                           void *user_data HB_UNUSED)
+			   void *font_data,
+			   const char *name, int len,
+			   hb_codepoint_t *glyph,
+			   void *user_data HB_UNUSED)
 {
   const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
   return ot_face->post->get_glyph_from_name (name, len, glyph);
diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh
index 240aac6..687c1f1 100644
--- a/src/hb-ot-hmtx-table.hh
+++ b/src/hb-ot-hmtx-table.hh
@@ -72,7 +72,7 @@
 
 
   bool subset_update_header (hb_subset_plan_t *plan,
-                             unsigned int num_hmetrics) const
+			     unsigned int num_hmetrics) const
   {
     hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (plan->source, H::tableTag);
     hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob);
@@ -93,30 +93,30 @@
   }
 
   template<typename Iterator,
-           hb_requires (hb_is_iterator (Iterator))>
+	   hb_requires (hb_is_iterator (Iterator))>
   void serialize (hb_serialize_context_t *c,
-                  Iterator it,
-                  unsigned num_advances)
+		  Iterator it,
+		  unsigned num_advances)
   {
     unsigned idx = 0;
     + it
     | hb_apply ([c, &idx, num_advances] (const hb_item_type<Iterator>& _)
-                {
-                  if (idx < num_advances)
-                  {
-                    LongMetric lm;
-                    lm.advance = _.first;
-                    lm.sb = _.second;
-                    if (unlikely (!c->embed<LongMetric> (&lm))) return;
-                  }
-                  else
-                  {
-                    FWORD *sb = c->allocate_size<FWORD> (FWORD::static_size);
-                    if (unlikely (!sb)) return;
-                    *sb = _.second;
-                  }
-                  idx++;
-                })
+		{
+		  if (idx < num_advances)
+		  {
+		    LongMetric lm;
+		    lm.advance = _.first;
+		    lm.sb = _.second;
+		    if (unlikely (!c->embed<LongMetric> (&lm))) return;
+		  }
+		  else
+		  {
+		    FWORD *sb = c->allocate_size<FWORD> (FWORD::static_size);
+		    if (unlikely (!sb)) return;
+		    *sb = _.second;
+		  }
+		  idx++;
+		})
     ;
   }
 
@@ -137,8 +137,8 @@
 	{
 	  hb_codepoint_t old_gid;
 	  if (c->plan->old_gid_for_new_gid (_, &old_gid))
-            return hb_pair (_mtx.get_advance (old_gid), _mtx.get_side_bearing (old_gid));
-          else
+	    return hb_pair (_mtx.get_advance (old_gid), _mtx.get_side_bearing (old_gid));
+	  else
 	    return hb_pair (0u, 0);
 	})
     ;
@@ -164,7 +164,7 @@
     friend struct hmtxvmtx;
 
     void init (hb_face_t *face,
-               unsigned int default_advance_ = 0)
+	       unsigned int default_advance_ = 0)
     {
       memset (this, 0, sizeof (*this));
       default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
@@ -202,10 +202,10 @@
     int get_side_bearing (hb_codepoint_t glyph) const
     {
       if (glyph < num_advances)
-        return table->longMetricZ[glyph].sb;
+	return table->longMetricZ[glyph].sb;
 
       if (unlikely (glyph >= num_metrics))
-        return 0;
+	return 0;
 
       const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_advances];
       return bearings[glyph - num_advances];
@@ -264,12 +264,12 @@
     {
       unsigned int num_advances = plan->num_output_glyphs ();
       unsigned int last_advance = _advance_for_new_gid (plan,
-                                                        num_advances - 1);
+							num_advances - 1);
       while (num_advances > 1 &&
-             last_advance == _advance_for_new_gid (plan,
-                                                   num_advances - 2))
+	     last_advance == _advance_for_new_gid (plan,
+						   num_advances - 2))
       {
-        num_advances--;
+	num_advances--;
       }
 
       return num_advances;
@@ -277,11 +277,11 @@
 
     private:
     unsigned int _advance_for_new_gid (const hb_subset_plan_t *plan,
-                                       hb_codepoint_t new_gid) const
+				       hb_codepoint_t new_gid) const
     {
       hb_codepoint_t old_gid;
       if (!plan->old_gid_for_new_gid (new_gid, &old_gid))
-        return 0;
+	return 0;
 
       return get_advance (old_gid);
     }
diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh
index 52bf4f8..7e08436 100644
--- a/src/hb-ot-layout-common.hh
+++ b/src/hb-ot-layout-common.hh
@@ -896,7 +896,7 @@
     for (auto g: glyphs)
     {
       if (last + 1 != g)
-        num_ranges++;
+	num_ranges++;
       last = g;
     }
 
@@ -909,7 +909,7 @@
     {
       if (last + 1 != g)
       {
-        range++;
+	range++;
 	rangeRecord[range].start = g;
 	rangeRecord[range].value = count;
       }
@@ -1059,7 +1059,7 @@
     for (auto g: glyphs)
     {
       if (last + 1 != g)
-        num_ranges++;
+	num_ranges++;
       last = g;
       count++;
     }
@@ -1527,7 +1527,7 @@
 	  num_ranges++;
 
       if (1 + (glyph_max - glyph_min + 1) < num_ranges * 3)
-        format = 1;
+	format = 1;
     }
     u.format = format;
 
@@ -1762,9 +1762,9 @@
   }
 
   void get_scalars (int *coords, unsigned int coord_count,
-                    const VarRegionList &regions,
-                    float *scalars /*OUT */,
-                    unsigned int num_scalars) const
+		    const VarRegionList &regions,
+		    float *scalars /*OUT */,
+		    unsigned int num_scalars) const
   {
     unsigned count = hb_min (num_scalars, regionIndices.len);
     for (unsigned int i = 0; i < count; i++)
@@ -1989,7 +1989,7 @@
 #endif
 
     (this+dataSets[ivs]).get_scalars (coords, coord_count, this+regions,
-                                      &scalars[0], num_scalars);
+				      &scalars[0], num_scalars);
   }
 
   unsigned int get_sub_table_count () const { return dataSets.len; }
diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh
index 0fca994..dc751d8 100644
--- a/src/hb-ot-layout-gdef-table.hh
+++ b/src/hb-ot-layout-gdef-table.hh
@@ -149,8 +149,8 @@
 				 const VariationStore &var_store) 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, var_store) :
+	   font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store);
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index 5c21980..a9ec962 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -236,6 +236,11 @@
   }
 };
 
+template<typename Iterator>
+static inline void SinglePos_serialize (hb_serialize_context_t *c,
+					Iterator it,
+					ValueFormat valFormat);
+
 
 struct AnchorFormat1
 {
@@ -496,11 +501,49 @@
     return_trace (true);
   }
 
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  void serialize (hb_serialize_context_t *c,
+		  Iterator it,
+		  ValueFormat valFormat)
+  {
+    if (unlikely (!c->extend_min (*this))) return;
+    if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
+
+    auto vals = hb_second (*it);
+
+    + vals
+    | hb_apply ([=] (const Value& _) { c->copy (_); })
+    ;
+
+    auto glyphs =
+    + it
+    | hb_map_retains_sorting (hb_first)
+    ;
+
+    coverage.serialize (c, this).serialize (c, glyphs);
+  }
+
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    // TODO(subset)
-    return_trace (false);
+    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+    unsigned length = valueFormat.get_len ();
+
+    auto it =
+    + hb_iter (this+coverage)
+    | hb_filter (glyphset)
+    | hb_map_retains_sorting ([&] (hb_codepoint_t p)
+			      {
+				return hb_pair (glyph_map[p], values.as_array (length));
+			      })
+    ;
+
+    bool ret = bool (it);
+    SinglePos_serialize (c->serializer, it, valueFormat);
+    return_trace (ret);
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -552,11 +595,55 @@
     return_trace (true);
   }
 
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  void serialize (hb_serialize_context_t *c,
+		  Iterator it,
+		  ValueFormat valFormat)
+  {
+    if (unlikely (!c->extend_min (*this))) return;
+    if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
+    if (unlikely (!c->check_assign (valueCount, it.len ()))) return;
+
+    + it
+    | hb_map (hb_second)
+    | hb_apply ([=] (hb_array_t<const Value> val_iter)
+		{
+		  + val_iter
+		  | hb_apply ([=] (const Value& _) { c->copy (_); })
+		  ;
+		})
+    ;
+
+    auto glyphs =
+    + it
+    | hb_map_retains_sorting (hb_first)
+    ;
+
+    coverage.serialize (c, this).serialize (c, glyphs);
+  }
+
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    // TODO(subset)
-    return_trace (false);
+    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+    unsigned sub_length = valueFormat.get_len ();
+    unsigned total_length = (unsigned)valueCount * sub_length;
+
+    auto it =
+    + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
+    | hb_filter (glyphset, hb_first)
+    | hb_map_retains_sorting ([&] (const hb_pair_t<hb_codepoint_t, unsigned>& _)
+			      {
+				return hb_pair (glyph_map[_.first], values.as_array (total_length).sub_array (_.second * sub_length, sub_length));
+			      })
+    ;
+
+    bool ret = bool (it);
+    SinglePos_serialize (c->serializer, it, valueFormat);
+    return_trace (ret);
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -583,6 +670,55 @@
 
 struct SinglePos
 {
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  unsigned get_format (Iterator glyph_val_iter_pairs)
+  {
+    unsigned subset_format = 1;
+    hb_array_t<const Value> first_val_iter = hb_second (*glyph_val_iter_pairs);
+
+    + glyph_val_iter_pairs
+    | hb_map (hb_second)
+    | hb_apply ([&] (hb_array_t<const Value> val_iter)
+		{
+		  + hb_zip (val_iter, first_val_iter)
+		  | hb_apply ([&] (const hb_pair_t<Value, Value>& _)
+			      {
+				if (_.first != _.second)
+				{
+				  subset_format = 2;
+				  return;
+				}
+			      })
+		  ;
+		})
+    ;
+
+    return subset_format;
+  }
+
+
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  void serialize (hb_serialize_context_t *c,
+		  Iterator glyph_val_iter_pairs,
+		  ValueFormat valFormat)
+  {
+    if (unlikely (!c->extend_min (u.format))) return;
+    unsigned format = 2;
+
+    if (glyph_val_iter_pairs) format = get_format (glyph_val_iter_pairs);
+
+    u.format = format;
+    switch (u.format) {
+    case 1: u.format1.serialize (c, glyph_val_iter_pairs, valFormat);
+	    return;
+    case 2: u.format2.serialize (c, glyph_val_iter_pairs, valFormat);
+	    return;
+    default:return;
+    }
+  }
+
   template <typename context_t, typename ...Ts>
   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
@@ -603,6 +739,13 @@
   } u;
 };
 
+template<typename Iterator>
+static inline void
+SinglePos_serialize (hb_serialize_context_t *c,
+		     Iterator it,
+		     ValueFormat valFormat)
+{ c->start_embed<SinglePos> ()->serialize (c, it, valFormat); }
+
 
 struct PairValueRecord
 {
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index 84e1b15..91aee11 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -296,12 +296,11 @@
 
 struct Sequence
 {
+  bool intersects (const hb_set_t *glyphs) const
+  { return hb_all (substitute, glyphs); }
+
   void closure (hb_closure_context_t *c) const
-  {
-    unsigned int count = substitute.len;
-    for (unsigned int i = 0; i < count; i++)
-      c->output->add (substitute[i]);
-  }
+  { c->output->add_array (substitute.arrayZ, substitute.len); }
 
   void collect_glyphs (hb_collect_glyphs_context_t *c) const
   { c->output->add_array (substitute.arrayZ, substitute.len); }
@@ -347,6 +346,23 @@
     return_trace (substitute.serialize (c, subst));
   }
 
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    const hb_set_t &glyphset = *c->plan->glyphset ();
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+    if (!intersects (&glyphset)) return_trace (false);
+
+    auto it =
+      + hb_iter (substitute)
+      | hb_map (glyph_map)
+      ;
+
+    auto *out = c->serializer->start_embed (*this);
+    return_trace (out->serialize (c->serializer, it));
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -422,8 +438,37 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    // TODO(subset)
-    return_trace (false);
+    const hb_set_t &glyphset = *c->plan->glyphset ();
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+    out->format = format;
+
+    hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+    + hb_zip (this+coverage, sequence)
+    | hb_filter (glyphset, hb_first)
+    | hb_filter ([this, c, out] (const OffsetTo<Sequence>& _)
+		 {
+		   auto *o = out->sequence.serialize_append (c->serializer);
+		   if (unlikely (!o)) return false;
+		   auto snap = c->serializer->snapshot ();
+		   bool ret = o->serialize_subset (c, _, this, out);
+		   if (!ret)
+		   {
+		     out->sequence.pop ();
+		     c->serializer->revert (snap);
+		   }
+		   return ret;
+		 },
+		 hb_second)
+    | hb_map (hb_first)
+    | hb_map (glyph_map)
+    | hb_sink (new_coverage)
+    ;
+    out->coverage.serialize (c->serializer, out)
+		 .serialize (c->serializer, new_coverage.iter ());
+    return_trace (bool (new_coverage));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -481,12 +526,11 @@
 
 struct AlternateSet
 {
+  bool intersects (const hb_set_t *glyphs) const
+  { return hb_any (alternates, glyphs); }
+
   void closure (hb_closure_context_t *c) const
-  {
-    unsigned int count = alternates.len;
-    for (unsigned int i = 0; i < count; i++)
-      c->output->add (alternates[i]);
-  }
+  { c->output->add_array (alternates.arrayZ, alternates.len); }
 
   void collect_glyphs (hb_collect_glyphs_context_t *c) const
   { c->output->add_array (alternates.arrayZ, alternates.len); }
@@ -525,6 +569,23 @@
     return_trace (alternates.serialize (c, alts));
   }
 
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    const hb_set_t &glyphset = *c->plan->glyphset ();
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+    auto it =
+      + hb_iter (alternates)
+      | hb_filter (glyphset)
+      | hb_map (glyph_map)
+      ;
+
+    auto *out = c->serializer->start_embed (*this);
+    return_trace (out->serialize (c->serializer, it) &&
+		  out->alternates);
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -600,8 +661,37 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    // TODO(subset)
-    return_trace (false);
+    const hb_set_t &glyphset = *c->plan->glyphset ();
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+    out->format = format;
+
+    hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+    + hb_zip (this+coverage, alternateSet)
+    | hb_filter (glyphset, hb_first)
+    | hb_filter ([this, c, out] (const OffsetTo<AlternateSet>& _)
+		 {
+		   auto *o = out->alternateSet.serialize_append (c->serializer);
+		   if (unlikely (!o)) return false;
+		   auto snap = c->serializer->snapshot ();
+		   bool ret = o->serialize_subset (c, _, this, out);
+		   if (!ret)
+		   {
+		     out->alternateSet.pop ();
+		     c->serializer->revert (snap);
+		   }
+		   return ret;
+		 },
+		 hb_second)
+    | hb_map (hb_first)
+    | hb_map (glyph_map)
+    | hb_sink (new_coverage)
+    ;
+    out->coverage.serialize (c->serializer, out)
+		 .serialize (c->serializer, new_coverage.iter ());
+    return_trace (bool (new_coverage));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -661,13 +751,7 @@
 struct Ligature
 {
   bool intersects (const hb_set_t *glyphs) const
-  {
-    unsigned int count = component.lenP1;
-    for (unsigned int i = 1; i < count; i++)
-      if (!glyphs->has (component[i]))
-	return false;
-    return true;
-  }
+  { return hb_all (component, glyphs); }
 
   void closure (hb_closure_context_t *c) const
   {
@@ -677,7 +761,7 @@
 
   void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    c->input->add_array (component.arrayZ, component.lenP1 ? component.lenP1 - 1 : 0);
+    c->input->add_array (component.arrayZ, component.get_length ());
     c->output->add (ligGlyph);
   }
 
@@ -735,7 +819,7 @@
   template <typename Iterator,
 	    hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
   bool serialize (hb_serialize_context_t *c,
-		  GlyphID ligature,
+		  hb_codepoint_t ligature,
 		  Iterator components /* Starting from second */)
   {
     TRACE_SERIALIZE (this);
@@ -745,6 +829,25 @@
     return_trace (true);
   }
 
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    const hb_set_t &glyphset = *c->plan->glyphset ();
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+    if (!intersects (&glyphset) || !glyphset.has (ligGlyph)) return_trace (false);
+
+    auto it =
+      + hb_iter (component)
+      | hb_map (glyph_map)
+      ;
+
+    auto *out = c->serializer->start_embed (*this);
+    return_trace (out->serialize (c->serializer,
+				   glyph_map[ligGlyph],
+				   it));
+  }
+
   public:
   bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -834,6 +937,31 @@
     return_trace (true);
   }
 
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+    + hb_iter (ligature)
+    | hb_filter ([this, c, out] (const OffsetTo<Ligature>& _)
+		 {
+		   auto *o = out->ligature.serialize_append (c->serializer);
+		   if (unlikely (!o)) return false;
+		   auto snap = c->serializer->snapshot ();
+		   bool ret = o->serialize_subset (c, _, this, out);
+		   if (!ret)
+		   {
+		     out->ligature.pop ();
+		     c->serializer->revert (snap);
+		   }
+		   return ret;
+		 })
+    | hb_drain
+    ;
+    return_trace (bool (out->ligature));
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -932,8 +1060,37 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    // TODO(subset)
-    return_trace (false);
+    const hb_set_t &glyphset = *c->plan->glyphset ();
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+    out->format = format;
+
+    hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+    + hb_zip (this+coverage, ligatureSet)
+    | hb_filter (glyphset, hb_first)
+    | hb_filter ([this, c, out] (const OffsetTo<LigatureSet>& _)
+		 {
+		   auto *o = out->ligatureSet.serialize_append (c->serializer);
+		   if (unlikely (!o)) return false;
+		   auto snap = c->serializer->snapshot ();
+		   bool ret = o->serialize_subset (c, _, this, out);
+		   if (!ret)
+		   {
+		     out->ligatureSet.pop ();
+		     c->serializer->revert (snap);
+		   }
+		   return ret;
+		 },
+		 hb_second)
+    | hb_map (hb_first)
+    | hb_map (glyph_map)
+    | hb_sink (new_coverage)
+    ;
+    out->coverage.serialize (c->serializer, out)
+		 .serialize (c->serializer, new_coverage.iter ());
+    return_trace (bool (new_coverage));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 666e162..8172614 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -54,6 +54,7 @@
 #include "hb-aat-layout-lcar-table.hh"
 #include "hb-aat-layout-morx-table.hh"
 
+#include "hb-aat-layout-opbd-table.hh" // Just so we compile it; unused otherwise.
 
 /**
  * SECTION:hb-ot-layout
@@ -374,10 +375,14 @@
   {
     if (caret_count) *caret_count = result_caret_count;
   }
-#ifndef HB_NO_AAT
   else
+  {
+#ifndef HB_NO_AAT
     result = font->face->table.lcar->get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
+#else
+    if (caret_count) *caret_count = 0;
 #endif
+  }
   return result;
 }
 #endif
@@ -562,7 +567,7 @@
     if (g.find_script_index (script_tags[i], script_index))
     {
       if (chosen_script)
-        *chosen_script = script_tags[i];
+	*chosen_script = script_tags[i];
       return true;
     }
   }
@@ -994,9 +999,9 @@
 
 struct hb_collect_features_context_t
 {
-  hb_collect_features_context_t (hb_face_t       *face,
-				 hb_tag_t         table_tag,
-				 hb_set_t        *feature_indexes_)
+  hb_collect_features_context_t (hb_face_t *face,
+				 hb_tag_t   table_tag,
+				 hb_set_t  *feature_indexes_)
     : g (get_gsubgpos_table (face, table_tag)),
       feature_indexes (feature_indexes_),
       script_count(0),langsys_count(0) {}
@@ -1142,11 +1147,11 @@
  **/
 void
 hb_ot_layout_collect_features (hb_face_t      *face,
-                               hb_tag_t        table_tag,
-                               const hb_tag_t *scripts,
-                               const hb_tag_t *languages,
-                               const hb_tag_t *features,
-                               hb_set_t       *feature_indexes /* OUT */)
+			       hb_tag_t        table_tag,
+			       const hb_tag_t *scripts,
+			       const hb_tag_t *languages,
+			       const hb_tag_t *features,
+			       hb_set_t       *feature_indexes /* OUT */)
 {
   hb_collect_features_context_t c (face, table_tag, feature_indexes);
   if (!scripts)
@@ -1477,8 +1482,8 @@
  **/
 void
 hb_ot_layout_lookups_substitute_closure (hb_face_t      *face,
-                                         const hb_set_t *lookups,
-                                         hb_set_t       *glyphs /* OUT */)
+					 const hb_set_t *lookups,
+					 hb_set_t       *glyphs /* OUT */)
 {
   hb_map_t done_lookups;
   OT::hb_closure_context_t c (face, glyphs, &done_lookups);
@@ -1492,12 +1497,12 @@
     if (lookups != nullptr)
     {
       for (hb_codepoint_t lookup_index = HB_SET_VALUE_INVALID; hb_set_next (lookups, &lookup_index);)
-        gsub.get_lookup (lookup_index).closure (&c, lookup_index);
+	gsub.get_lookup (lookup_index).closure (&c, lookup_index);
     }
     else
     {
       for (unsigned int i = 0; i < gsub.get_lookup_count (); i++)
-        gsub.get_lookup (i).closure (&c, i);
+	gsub.get_lookup (i).closure (&c, i);
     }
   } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
 	   glyphs_length != glyphs->get_population ());
@@ -1953,6 +1958,8 @@
  * Fetches a baseline value from the face.
  *
  * Return value: if found baseline value in the the font.
+ *
+ * Since: 2.6.0
  **/
 hb_bool_t
 hb_ot_layout_get_baseline (hb_font_t                   *font,
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index 73254aa..7e8a897 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -249,11 +249,11 @@
 
 HB_EXTERN void
 hb_ot_layout_collect_features (hb_face_t      *face,
-                               hb_tag_t        table_tag,
-                               const hb_tag_t *scripts,
-                               const hb_tag_t *languages,
-                               const hb_tag_t *features,
-                               hb_set_t       *feature_indexes /* OUT */);
+			       hb_tag_t        table_tag,
+			       const hb_tag_t *scripts,
+			       const hb_tag_t *languages,
+			       const hb_tag_t *features,
+			       hb_set_t       *feature_indexes /* OUT */);
 
 HB_EXTERN void
 hb_ot_layout_collect_lookups (hb_face_t      *face,
@@ -333,14 +333,14 @@
 
 HB_EXTERN void
 hb_ot_layout_lookup_substitute_closure (hb_face_t    *face,
-				        unsigned int  lookup_index,
-				        hb_set_t     *glyphs
+					unsigned int  lookup_index,
+					hb_set_t     *glyphs
 					/*TODO , hb_bool_t  inclusive */);
 
 HB_EXTERN void
 hb_ot_layout_lookups_substitute_closure (hb_face_t      *face,
-                                         const hb_set_t *lookups,
-                                         hb_set_t       *glyphs);
+					 const hb_set_t *lookups,
+					 hb_set_t       *glyphs);
 
 
 #ifdef HB_NOT_IMPLEMENTED
@@ -408,10 +408,27 @@
 
 /**
  * hb_ot_layout_baseline_tag_t:
+ * @HB_OT_LAYOUT_BASELINE_TAG_ROMAN: The baseline used by alphabetic scripts such as Latin, Cyrillic and Greek.
+ * In vertical writing mode, the alphabetic baseline for characters rotated 90 degrees clockwise.
+ * (This would not apply to alphabetic characters that remain upright in vertical writing mode, since these
+ * characters are not rotated.)
+ * @HB_OT_LAYOUT_BASELINE_TAG_HANGING: The hanging baseline. In horizontal direction, this is the horizontal
+ * line from which syllables seem, to hang in Tibetan and other similar scripts. In vertical writing mode,
+ * for Tibetan (or some other similar script) characters rotated 90 degrees clockwise.
+ * @HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT: Ideographic character face bottom or left edge,
+ * if the direction is horizontal or vertical, respectively.
+ * @HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT: Ideographic character face top or right edge,
+ * if the direction is horizontal or vertical, respectively.
+ * @HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT: Ideographic em-box bottom or left edge,
+ * if the direction is horizontal or vertical, respectively.
+ * @HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT: Ideographic em-box top or right edge baseline,
+ * if the direction is horizontal or vertical, respectively.
+ * @HB_OT_LAYOUT_BASELINE_TAG_MATH: The baseline about which mathematical characters are centered.
+ * In vertical writing mode when mathematical characters rotated 90 degrees clockwise, are centered.
  *
- * https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags
+ * Baseline tags from https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags
  *
- * Since: REPLACEME
+ * Since: 2.6.0
  */
 typedef enum {
   HB_OT_LAYOUT_BASELINE_TAG_ROMAN			= HB_TAG ('r','o','m','n'),
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index b0bc472..6d623f5 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -297,7 +297,7 @@
 		     global_bit_mask);
 
       for (unsigned i = 0; i < m.features.length; i++)
-        if (m.features[i].stage[table_index] == stage)
+	if (m.features[i].stage[table_index] == stage)
 	  add_lookups (m, table_index,
 		       m.features[i].index[table_index],
 		       key.variations_index[table_index],
diff --git a/src/hb-ot-maxp-table.hh b/src/hb-ot-maxp-table.hh
index 2ba2cf4..9945ea6 100644
--- a/src/hb-ot-maxp-table.hh
+++ b/src/hb-ot-maxp-table.hh
@@ -108,7 +108,7 @@
       if (unlikely (!dest_v1)) return_trace (false);
 
       if (c->plan->drop_hints)
-        drop_hint_fields (dest_v1);
+	drop_hint_fields (dest_v1);
     }
 
     return_trace (true);
diff --git a/src/hb-ot-meta.cc b/src/hb-ot-meta.cc
index a5ce148..a1e081b 100644
--- a/src/hb-ot-meta.cc
+++ b/src/hb-ot-meta.cc
@@ -46,13 +46,13 @@
  *
  * Return value: Number of all available feature types.
  *
- * Since: REPLACEME
+ * Since: 2.6.0
  **/
 unsigned int
-hb_ot_meta_get_entries (hb_face_t        *face,
-			unsigned int      start_offset,
-			unsigned int     *entries_count, /* IN/OUT.  May be NULL. */
-			hb_ot_meta_tag_t *entries        /* OUT.     May be NULL. */)
+hb_ot_meta_get_entry_tags (hb_face_t        *face,
+			   unsigned int      start_offset,
+			   unsigned int     *entries_count, /* IN/OUT.  May be NULL. */
+			   hb_ot_meta_tag_t *entries        /* OUT.     May be NULL. */)
 {
   return face->table.meta->get_entries (start_offset, entries_count, entries);
 }
@@ -66,7 +66,7 @@
  *
  * Returns: (transfer full): A blob containing the blob.
  *
- * Since: REPLACEME
+ * Since: 2.6.0
  **/
 hb_blob_t *
 hb_ot_meta_reference_entry (hb_face_t *face, hb_ot_meta_tag_t meta_tag)
diff --git a/src/hb-ot-meta.h b/src/hb-ot-meta.h
index 7afad84..0278d84 100644
--- a/src/hb-ot-meta.h
+++ b/src/hb-ot-meta.h
@@ -35,10 +35,16 @@
 
 /**
  * hb_ot_meta_tag_t:
+ * @HB_OT_META_TAG_DESIGN_LANGUAGES: Design languages. Text, using only
+ * Basic Latin (ASCII) characters. Indicates languages and/or scripts
+ * for the user audiences that the font was primarily designed for.
+ * @HB_OT_META_TAG_SUPPORTED_LANGUAGES: Supported languages. Text, using
+ * only Basic Latin (ASCII) characters. Indicates languages and/or scripts
+ * that the font is declared to be capable of supporting.
  *
- * From https://docs.microsoft.com/en-us/typography/opentype/spec/meta
+ * Known metadata tags from https://docs.microsoft.com/en-us/typography/opentype/spec/meta
  *
- * Since: REPLACEME
+ * Since: 2.6.0
  **/
 typedef enum {
 /*
@@ -52,10 +58,10 @@
 } hb_ot_meta_tag_t;
 
 HB_EXTERN unsigned int
-hb_ot_meta_get_entries (hb_face_t        *face,
-			unsigned int      start_offset,
-			unsigned int     *entries_count, /* IN/OUT.  May be NULL. */
-			hb_ot_meta_tag_t *entries        /* OUT.     May be NULL. */);
+hb_ot_meta_get_entry_tags (hb_face_t        *face,
+			   unsigned int      start_offset,
+			   unsigned int     *entries_count, /* IN/OUT.  May be NULL. */
+			   hb_ot_meta_tag_t *entries        /* OUT.     May be NULL. */);
 
 HB_EXTERN hb_blob_t *
 hb_ot_meta_reference_entry (hb_face_t *face, hb_ot_meta_tag_t meta_tag);
diff --git a/src/hb-ot-metrics.cc b/src/hb-ot-metrics.cc
index f04984c..181ac4d 100644
--- a/src/hb-ot-metrics.cc
+++ b/src/hb-ot-metrics.cc
@@ -117,7 +117,7 @@
  * It fetches metrics value corresponding to a given tag from a font.
  *
  * Returns: Whether found the requested metrics in the font.
- * Since: REPLACEME
+ * Since: 2.6.0
  **/
 hb_bool_t
 hb_ot_metrics_get_position (hb_font_t           *font,
@@ -189,7 +189,7 @@
  *
  * Returns:
  *
- * Since: REPLACEME
+ * Since: 2.6.0
  **/
 float
 hb_ot_metrics_get_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag)
@@ -204,7 +204,7 @@
  *
  * Returns:
  *
- * Since: REPLACEME
+ * Since: 2.6.0
  **/
 hb_position_t
 hb_ot_metrics_get_x_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag)
@@ -219,7 +219,7 @@
  *
  * Returns:
  *
- * Since: REPLACEME
+ * Since: 2.6.0
  **/
 hb_position_t
 hb_ot_metrics_get_y_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag)
diff --git a/src/hb-ot-metrics.h b/src/hb-ot-metrics.h
index b98c500..42c7363 100644
--- a/src/hb-ot-metrics.h
+++ b/src/hb-ot-metrics.h
@@ -37,10 +37,38 @@
 
 /**
  * hb_ot_metrics_tag_t:
+ * @HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER: horizontal ascender.
+ * @HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER: horizontal descender.
+ * @HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP: horizontal line gap.
+ * @HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_ASCENT: horizontal clipping ascent.
+ * @HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_DESCENT: horizontal clipping descent.
+ * @HB_OT_METRICS_TAG_VERTICAL_ASCENDER: vertical ascender.
+ * @HB_OT_METRICS_TAG_VERTICAL_DESCENDER: vertical descender.
+ * @HB_OT_METRICS_TAG_VERTICAL_LINE_GAP: vertical line gap.
+ * @HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE: horizontal caret rise.
+ * @HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN: horizontal caret run.
+ * @HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET: horizontal caret offset.
+ * @HB_OT_METRICS_TAG_VERTICAL_CARET_RISE: vertical caret rise.
+ * @HB_OT_METRICS_TAG_VERTICAL_CARET_RUN: vertical caret run.
+ * @HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET: vertical caret offset.
+ * @HB_OT_METRICS_TAG_X_HEIGHT: x height.
+ * @HB_OT_METRICS_TAG_CAP_HEIGHT: cap height.
+ * @HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_SIZE: subscript em x size.
+ * @HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_SIZE: subscript em y size.
+ * @HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_OFFSET: subscript em x offset.
+ * @HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_OFFSET: subscript em y offset.
+ * @HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_SIZE: superscript em x size.
+ * @HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_SIZE: superscript em y size.
+ * @HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_OFFSET: superscript em x offset.
+ * @HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_OFFSET: superscript em y offset.
+ * @HB_OT_METRICS_TAG_STRIKEOUT_SIZE: strikeout size.
+ * @HB_OT_METRICS_TAG_STRIKEOUT_OFFSET: strikeout offset.
+ * @HB_OT_METRICS_TAG_UNDERLINE_SIZE: underline size.
+ * @HB_OT_METRICS_TAG_UNDERLINE_OFFSET: underline offset.
  *
  * From https://docs.microsoft.com/en-us/typography/opentype/spec/mvar#value-tags
  *
- * Since: REPLACEME
+ * Since: 2.6.0
  **/
 typedef enum {
   HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER		= HB_TAG ('h','a','s','c'),
diff --git a/src/hb-ot-name-table.hh b/src/hb-ot-name-table.hh
index 59bf438..4a8b57f 100644
--- a/src/hb-ot-name-table.hh
+++ b/src/hb-ot-name-table.hh
@@ -265,10 +265,10 @@
       unsigned int j = 0;
       for (unsigned int i = 0; i < this->names.length; i++)
       {
-        if (this->names[i].entry_score == UNSUPPORTED ||
+	if (this->names[i].entry_score == UNSUPPORTED ||
 	    this->names[i].language == HB_LANGUAGE_INVALID)
 	  continue;
-        if (i &&
+	if (i &&
 	    this->names[i - 1].name_id  == this->names[i].name_id &&
 	    this->names[i - 1].language == this->names[i].language)
 	  continue;
@@ -295,10 +295,10 @@
 						    sizeof (key),
 						    _hb_ot_name_entry_cmp_key);
       if (!entry)
-        return -1;
+	return -1;
 
       if (width)
-        *width = entry->entry_score < 10 ? 2 : 1;
+	*width = entry->entry_score < 10 ? 2 : 1;
 
       return entry->entry_index;
     }
diff --git a/src/hb-ot-name.cc b/src/hb-ot-name.cc
index 0b5ce81..10122b8 100644
--- a/src/hb-ot-name.cc
+++ b/src/hb-ot-name.cc
@@ -90,7 +90,7 @@
       const typename in_utf_t::codepoint_t *src_next = in_utf_t::next (src, src_end, &unicode, replacement);
       typename out_utf_t::codepoint_t *dst_next = out_utf_t::encode (dst, dst_end, unicode);
       if (dst_next == dst)
-        break; /* Out-of-room. */
+	break; /* Out-of-room. */
 
       dst = dst_next;
       src = src_next;
diff --git a/src/hb-ot-os2-table.hh b/src/hb-ot-os2-table.hh
index 67f21eb..037fcae 100644
--- a/src/hb-ot-os2-table.hh
+++ b/src/hb-ot-os2-table.hh
@@ -59,7 +59,7 @@
 
 struct OS2V2Tail
 {
-  bool has_data () const { return this != &Null (OS2V2Tail); }
+  bool has_data () const { return sxHeight || sCapHeight; }
 
   const OS2V2Tail * operator -> () const { return this; }
 
@@ -81,6 +81,23 @@
 
 struct OS2V5Tail
 {
+  inline bool get_optical_size (unsigned int *lower, unsigned int *upper) const
+  {
+    unsigned int lower_optical_size = usLowerOpticalPointSize;
+    unsigned int upper_optical_size = usUpperOpticalPointSize;
+
+    /* Per https://docs.microsoft.com/en-us/typography/opentype/spec/os2#lps */
+    if (lower_optical_size < upper_optical_size &&
+	lower_optical_size >= 1 && lower_optical_size <= 0xFFFE &&
+	upper_optical_size >= 2 && upper_optical_size <= 0xFFFF)
+    {
+      *lower = lower_optical_size;
+      *upper = upper_optical_size;
+      return true;
+    }
+    return false;
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -98,7 +115,7 @@
 {
   static constexpr hb_tag_t tableTag = HB_OT_TAG_OS2;
 
-  bool has_data () const { return this != &Null (OS2); }
+  bool has_data () const { return usWeightClass || usWidthClass || usFirstCharIndex || usLastCharIndex; }
 
   const OS2V1Tail &v1 () const { return version >= 1 ? v1X : Null (OS2V1Tail); }
   const OS2V2Tail &v2 () const { return version >= 2 ? v2X : Null (OS2V2Tail); }
diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc
index b24833b..f92e637 100644
--- a/src/hb-ot-shape-complex-arabic.cc
+++ b/src/hb-ot-shape-complex-arabic.cc
@@ -476,13 +476,13 @@
     {
       if (!hb_in_range<uint8_t> (info[i - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING))
       {
-        if (step == CUT)
+	if (step == CUT)
 	{
 	  --j;
 	  info[j] = info[i - 1];
 	  pos[j] = pos[i - 1];
 	}
-        continue;
+	continue;
       }
 
       /* Yay, justification! */
@@ -540,10 +540,10 @@
       hb_position_t shortfall = sign * w_remaining - sign * w_repeating * (n_copies + 1);
       if (shortfall > 0 && n_repeating > 0)
       {
-        ++n_copies;
-        hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining;
-        if (excess > 0)
-          extra_repeat_overlap = excess / (n_copies * n_repeating);
+	++n_copies;
+	hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining;
+	if (excess > 0)
+	  extra_repeat_overlap = excess / (n_copies * n_repeating);
       }
 
       if (step == MEASURE)
@@ -583,7 +583,7 @@
     if (step == MEASURE)
     {
       if (unlikely (!buffer->ensure (count + extra_glyphs_needed)))
-        break;
+	break;
     }
     else
     {
diff --git a/src/hb-ot-shape-complex-hangul.cc b/src/hb-ot-shape-complex-hangul.cc
index 32e0e66..f5915f4 100644
--- a/src/hb-ot-shape-complex-hangul.cc
+++ b/src/hb-ot-shape-complex-hangul.cc
@@ -204,7 +204,7 @@
       if (start < end && end == buffer->out_len)
       {
 	/* Tone mark follows a valid syllable; move it in front, unless it's zero width. */
-        buffer->unsafe_to_break_from_outbuffer (start, buffer->idx);
+	buffer->unsafe_to_break_from_outbuffer (start, buffer->idx);
 	buffer->next_glyph ();
 	if (!is_zero_width_char (font, u))
 	{
@@ -354,9 +354,9 @@
 	   */
 	  if (has_glyph && !tindex)
 	  {
-            buffer->next_glyph ();
-            s_len++;
-          }
+	    buffer->next_glyph ();
+	    s_len++;
+	  }
 
 	  if (unlikely (!buffer->successful))
 	    return;
@@ -365,7 +365,7 @@
 	   * that are now in buffer->out_info.
 	   */
 	  hb_glyph_info_t *info = buffer->out_info;
-          end = start + s_len;
+	  end = start + s_len;
 
 	  unsigned int i = start;
 	  info[i++].hangul_shaping_feature() = LJMO;
@@ -383,7 +383,7 @@
 
       if (has_glyph)
       {
-        /* We didn't decompose the S, so just advance past it. */
+	/* We didn't decompose the S, so just advance past it. */
 	end = start + 1;
 	buffer->next_glyph ();
 	continue;
diff --git a/src/hb-ot-shape-complex-indic-table.cc b/src/hb-ot-shape-complex-indic-table.cc
index 419aae1..cc91f17 100644
--- a/src/hb-ot-shape-complex-indic-table.cc
+++ b/src/hb-ot-shape-complex-indic-table.cc
@@ -23,58 +23,59 @@
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wunused-macros"
 
-#define ISC_A	INDIC_SYLLABIC_CATEGORY_AVAGRAHA		/*  17 chars; Avagraha */
-#define ISC_Bi	INDIC_SYLLABIC_CATEGORY_BINDU			/*  86 chars; Bindu */
-#define ISC_BJN	INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER	/*  20 chars; Brahmi_Joining_Number */
-#define ISC_Ca	INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK	/*  59 chars; Cantillation_Mark */
-#define ISC_C	INDIC_SYLLABIC_CATEGORY_CONSONANT		/* 2160 chars; Consonant */
-#define ISC_CD	INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD		/*  12 chars; Consonant_Dead */
-#define ISC_CF	INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL		/*  67 chars; Consonant_Final */
-#define ISC_CHL	INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER	/*   5 chars; Consonant_Head_Letter */
-#define ISC_CIP	INDIC_SYLLABIC_CATEGORY_CONSONANT_INITIAL_POSTFIXED	/*   1 chars; Consonant_Initial_Postfixed */
-#define ISC_CK	INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER	/*   2 chars; Consonant_Killer */
-#define ISC_CM	INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL	/*  29 chars; Consonant_Medial */
-#define ISC_CP	INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER	/*  22 chars; Consonant_Placeholder */
-#define ISC_CPR	INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA	/*   2 chars; Consonant_Preceding_Repha */
-#define ISC_CPrf	INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED	/*   9 chars; Consonant_Prefixed */
-#define ISC_CS	INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED	/*  94 chars; Consonant_Subjoined */
-#define ISC_CSR	INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA	/*   4 chars; Consonant_Succeeding_Repha */
-#define ISC_CWS	INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER	/*   6 chars; Consonant_With_Stacker */
-#define ISC_GM	INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK		/*   3 chars; Gemination_Mark */
-#define ISC_IS	INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER	/*  11 chars; Invisible_Stacker */
-#define ISC_ZWJ	INDIC_SYLLABIC_CATEGORY_JOINER			/*   1 chars; Joiner */
-#define ISC_ML	INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER	/*   1 chars; Modifying_Letter */
-#define ISC_ZWNJ	INDIC_SYLLABIC_CATEGORY_NON_JOINER		/*   1 chars; Non_Joiner */
-#define ISC_N	INDIC_SYLLABIC_CATEGORY_NUKTA			/*  30 chars; Nukta */
-#define ISC_Nd	INDIC_SYLLABIC_CATEGORY_NUMBER			/* 481 chars; Number */
-#define ISC_NJ	INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER		/*   1 chars; Number_Joiner */
-#define ISC_x	INDIC_SYLLABIC_CATEGORY_OTHER			/*   1 chars; Other */
-#define ISC_PK	INDIC_SYLLABIC_CATEGORY_PURE_KILLER		/*  21 chars; Pure_Killer */
-#define ISC_RS	INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER	/*   2 chars; Register_Shifter */
-#define ISC_SM	INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER	/*  25 chars; Syllable_Modifier */
-#define ISC_TL	INDIC_SYLLABIC_CATEGORY_TONE_LETTER		/*   7 chars; Tone_Letter */
-#define ISC_TM	INDIC_SYLLABIC_CATEGORY_TONE_MARK		/*  42 chars; Tone_Mark */
-#define ISC_V	INDIC_SYLLABIC_CATEGORY_VIRAMA			/*  27 chars; Virama */
-#define ISC_Vs	INDIC_SYLLABIC_CATEGORY_VISARGA			/*  35 chars; Visarga */
-#define ISC_Vo	INDIC_SYLLABIC_CATEGORY_VOWEL			/*  30 chars; Vowel */
-#define ISC_M	INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT		/* 673 chars; Vowel_Dependent */
-#define ISC_VI	INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT	/* 476 chars; Vowel_Independent */
+#define ISC_A    INDIC_SYLLABIC_CATEGORY_AVAGRAHA                    /*   17 chars; Avagraha */
+#define ISC_Bi   INDIC_SYLLABIC_CATEGORY_BINDU                       /*   86 chars; Bindu */
+#define ISC_BJN  INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER       /*   20 chars; Brahmi_Joining_Number */
+#define ISC_Ca   INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK           /*   59 chars; Cantillation_Mark */
+#define ISC_C    INDIC_SYLLABIC_CATEGORY_CONSONANT                   /* 2160 chars; Consonant */
+#define ISC_CD   INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD              /*   12 chars; Consonant_Dead */
+#define ISC_CF   INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL             /*   67 chars; Consonant_Final */
+#define ISC_CHL  INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER       /*    5 chars; Consonant_Head_Letter */
+#define ISC_CIP  INDIC_SYLLABIC_CATEGORY_CONSONANT_INITIAL_POSTFIXED /*    1 chars; Consonant_Initial_Postfixed */
+#define ISC_CK   INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER            /*    2 chars; Consonant_Killer */
+#define ISC_CM   INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL            /*   29 chars; Consonant_Medial */
+#define ISC_CP   INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER       /*   22 chars; Consonant_Placeholder */
+#define ISC_CPR  INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA   /*    2 chars; Consonant_Preceding_Repha */
+#define ISC_CPrf INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED          /*    9 chars; Consonant_Prefixed */
+#define ISC_CS   INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED         /*   94 chars; Consonant_Subjoined */
+#define ISC_CSR  INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA  /*    4 chars; Consonant_Succeeding_Repha */
+#define ISC_CWS  INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER      /*    6 chars; Consonant_With_Stacker */
+#define ISC_GM   INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK             /*    3 chars; Gemination_Mark */
+#define ISC_IS   INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER           /*   11 chars; Invisible_Stacker */
+#define ISC_ZWJ  INDIC_SYLLABIC_CATEGORY_JOINER                      /*    1 chars; Joiner */
+#define ISC_ML   INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER            /*    1 chars; Modifying_Letter */
+#define ISC_ZWNJ INDIC_SYLLABIC_CATEGORY_NON_JOINER                  /*    1 chars; Non_Joiner */
+#define ISC_N    INDIC_SYLLABIC_CATEGORY_NUKTA                       /*   30 chars; Nukta */
+#define ISC_Nd   INDIC_SYLLABIC_CATEGORY_NUMBER                      /*  481 chars; Number */
+#define ISC_NJ   INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER               /*    1 chars; Number_Joiner */
+#define ISC_x    INDIC_SYLLABIC_CATEGORY_OTHER                       /*    1 chars; Other */
+#define ISC_PK   INDIC_SYLLABIC_CATEGORY_PURE_KILLER                 /*   21 chars; Pure_Killer */
+#define ISC_RS   INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER            /*    2 chars; Register_Shifter */
+#define ISC_SM   INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER           /*   25 chars; Syllable_Modifier */
+#define ISC_TL   INDIC_SYLLABIC_CATEGORY_TONE_LETTER                 /*    7 chars; Tone_Letter */
+#define ISC_TM   INDIC_SYLLABIC_CATEGORY_TONE_MARK                   /*   42 chars; Tone_Mark */
+#define ISC_V    INDIC_SYLLABIC_CATEGORY_VIRAMA                      /*   27 chars; Virama */
+#define ISC_Vs   INDIC_SYLLABIC_CATEGORY_VISARGA                     /*   35 chars; Visarga */
+#define ISC_Vo   INDIC_SYLLABIC_CATEGORY_VOWEL                       /*   30 chars; Vowel */
+#define ISC_M    INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT             /*  673 chars; Vowel_Dependent */
+#define ISC_VI   INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT           /*  476 chars; Vowel_Independent */
 
-#define IMC_B	INDIC_MATRA_CATEGORY_BOTTOM			/* 349 chars; Bottom */
-#define IMC_BL	INDIC_MATRA_CATEGORY_BOTTOM_AND_LEFT		/*   1 chars; Bottom_And_Left */
-#define IMC_BR	INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT		/*   2 chars; Bottom_And_Right */
-#define IMC_L	INDIC_MATRA_CATEGORY_LEFT			/*  61 chars; Left */
-#define IMC_LR	INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT		/*  21 chars; Left_And_Right */
-#define IMC_x	INDIC_MATRA_CATEGORY_NOT_APPLICABLE		/*   1 chars; Not_Applicable */
-#define IMC_O	INDIC_MATRA_CATEGORY_OVERSTRUCK			/*  10 chars; Overstruck */
-#define IMC_R	INDIC_MATRA_CATEGORY_RIGHT			/* 281 chars; Right */
-#define IMC_T	INDIC_MATRA_CATEGORY_TOP			/* 398 chars; Top */
-#define IMC_TB	INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM		/*  10 chars; Top_And_Bottom */
-#define IMC_TBR	INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT	/*   1 chars; Top_And_Bottom_And_Right */
-#define IMC_TL	INDIC_MATRA_CATEGORY_TOP_AND_LEFT		/*   6 chars; Top_And_Left */
-#define IMC_TLR	INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT	/*   4 chars; Top_And_Left_And_Right */
-#define IMC_TR	INDIC_MATRA_CATEGORY_TOP_AND_RIGHT		/*  13 chars; Top_And_Right */
-#define IMC_VOL	INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT		/*  19 chars; Visual_Order_Left */
+#define IMC_B    INDIC_MATRA_CATEGORY_BOTTOM                         /*  349 chars; Bottom */
+#define IMC_BL   INDIC_MATRA_CATEGORY_BOTTOM_AND_LEFT                /*    1 chars; Bottom_And_Left */
+#define IMC_BR   INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT               /*    2 chars; Bottom_And_Right */
+#define IMC_L    INDIC_MATRA_CATEGORY_LEFT                           /*   61 chars; Left */
+#define IMC_LR   INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT                 /*   21 chars; Left_And_Right */
+#define IMC_x    INDIC_MATRA_CATEGORY_NOT_APPLICABLE                 /*    1 chars; Not_Applicable */
+#define IMC_O    INDIC_MATRA_CATEGORY_OVERSTRUCK                     /*   10 chars; Overstruck */
+#define IMC_R    INDIC_MATRA_CATEGORY_RIGHT                          /*  281 chars; Right */
+#define IMC_T    INDIC_MATRA_CATEGORY_TOP                            /*  398 chars; Top */
+#define IMC_TB   INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM                 /*   10 chars; Top_And_Bottom */
+#define IMC_TBR  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT       /*    1 chars; Top_And_Bottom_And_Right */
+#define IMC_TL   INDIC_MATRA_CATEGORY_TOP_AND_LEFT                   /*    6 chars; Top_And_Left */
+#define IMC_TLR  INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT         /*    4 chars; Top_And_Left_And_Right */
+#define IMC_TR   INDIC_MATRA_CATEGORY_TOP_AND_RIGHT                  /*   13 chars; Top_And_Right */
+#define IMC_VOL  INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT              /*   19 chars; Visual_Order_Left */
+
 #pragma GCC diagnostic pop
 
 #define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)
@@ -439,6 +440,7 @@
 }
 
 #undef _
+
 #undef ISC_A
 #undef ISC_Bi
 #undef ISC_BJN
@@ -475,6 +477,7 @@
 #undef ISC_Vo
 #undef ISC_M
 #undef ISC_VI
+
 #undef IMC_B
 #undef IMC_BL
 #undef IMC_BR
@@ -491,6 +494,6 @@
 #undef IMC_TR
 #undef IMC_VOL
 
-
 #endif
+
 /* == End of generated table == */
diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index fd099ca..26dc60d 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -131,13 +131,6 @@
   {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS},
   {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS},
   {HB_TAG('h','a','l','n'), F_GLOBAL_MANUAL_JOINERS},
-  /*
-   * Positioning features.
-   * We don't care about the types.
-   */
-  {HB_TAG('d','i','s','t'), F_GLOBAL},
-  {HB_TAG('a','b','v','m'), F_GLOBAL},
-  {HB_TAG('b','l','w','m'), F_GLOBAL},
 };
 
 /*
@@ -163,10 +156,6 @@
   _INDIC_PSTS,
   _INDIC_HALN,
 
-  _INDIC_DIST,
-  _INDIC_ABVM,
-  _INDIC_BLWM,
-
   INDIC_NUM_FEATURES,
   INDIC_BASIC_FEATURES = INDIC_INIT, /* Don't forget to update this! */
 };
@@ -551,7 +540,7 @@
 
       case BASE_POS_LAST_SINHALA:
       {
-        /* Sinhala base positioning is slightly different from main Indic, in that:
+	/* Sinhala base positioning is slightly different from main Indic, in that:
 	 * 1. Its ZWJ behavior is different,
 	 * 2. We don't need to look into the font for consonant positions.
 	 */
@@ -680,8 +669,8 @@
     for (unsigned int i = base + 1; i < end; i++)
       if (info[i].indic_category() == OT_H)
       {
-        unsigned int j;
-        for (j = end - 1; j > i; j--)
+	unsigned int j;
+	for (j = end - 1; j > i; j--)
 	  if (is_consonant (info[j]) ||
 	      (disallow_double_halants && info[j].indic_category() == OT_H))
 	    break;
@@ -691,7 +680,7 @@
 	  memmove (&info[i], &info[i + 1], (j - i) * sizeof (info[0]));
 	  info[j] = t;
 	}
-        break;
+	break;
       }
   }
 
@@ -722,7 +711,7 @@
 	    }
 	}
       } else if (info[i].indic_position() != POS_SMVD) {
-        last_pos = (indic_position_t) info[i].indic_position();
+	last_pos = (indic_position_t) info[i].indic_position();
       }
     }
   }
@@ -738,7 +727,7 @@
 	    info[j].indic_position() = info[i].indic_position();
 	last = i;
       } else if (info[i].indic_category() == OT_M)
-        last = i;
+	last = i;
   }
 
 
@@ -775,7 +764,7 @@
     {
       /* Note!  syllable() is a one-byte field. */
       for (unsigned int i = base; i < end; i++)
-        if (info[i].syllable() != 255)
+	if (info[i].syllable() != 255)
 	{
 	  unsigned int max = i;
 	  unsigned int j = start + info[i].syllable();
@@ -863,7 +852,7 @@
     for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) {
       hb_codepoint_t glyphs[2];
       for (unsigned int j = 0; j < pref_len; j++)
-        glyphs[j] = info[i + j].codepoint;
+	glyphs[j] = info[i + j].codepoint;
       if (indic_plan->pref.would_substitute (glyphs, pref_len, face))
       {
 	for (unsigned int j = 0; j < pref_len; j++)
@@ -994,7 +983,7 @@
       while (buffer->idx < buffer->len && buffer->successful &&
 	     last_syllable == buffer->cur().syllable() &&
 	     buffer->cur().indic_category() == OT_Repha)
-        buffer->next_glyph ();
+	buffer->next_glyph ();
 
       buffer->output_info (ginfo);
     }
@@ -1040,7 +1029,7 @@
 	  _hb_glyph_info_ligated (&info[i]) &&
 	  _hb_glyph_info_multiplied (&info[i]))
       {
-        /* This will make sure that this glyph passes is_halant() test. */
+	/* This will make sure that this glyph passes is_halant() test. */
 	info[i].indic_category() = OT_H;
 	_hb_glyph_info_clear_ligated_and_multiplied (&info[i]);
       }
@@ -1103,7 +1092,7 @@
       }
 
       if (start < base && info[base].indic_position() > POS_BASE_C)
-        base--;
+	base--;
       break;
     }
   if (base == end && start < base &&
@@ -1193,7 +1182,7 @@
 	}
       }
       else
-        new_pos = start; /* No move. */
+	new_pos = start; /* No move. */
     }
 
     if (start < new_pos && info[new_pos].indic_position () != POS_PRE_M)
@@ -1295,7 +1284,7 @@
       while (new_reph_pos + 1 < end && info[new_reph_pos + 1].indic_position() <= POS_AFTER_MAIN)
 	new_reph_pos++;
       if (new_reph_pos < end)
-        goto reph_move;
+	goto reph_move;
     }
 
     /*       4. If reph should be positioned before post-base consonant, find
@@ -1311,7 +1300,7 @@
 	     !( FLAG_UNSAFE (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_POST_C) | FLAG (POS_AFTER_POST) | FLAG (POS_SMVD))))
 	new_reph_pos++;
       if (new_reph_pos < end)
-        goto reph_move;
+	goto reph_move;
     }
 
     /*       5. If no consonant is found in steps 3 or 4, move reph to a position
@@ -1393,7 +1382,7 @@
 	 *          of the <pref> feature. (Note that a font may shape a Ra consonant with
 	 *          the feature generally but block it in certain contexts.)
 	 */
-        /* Note: We just check that something got substituted.  We don't check that
+	/* Note: We just check that something got substituted.  We don't check that
 	 * the <pref> feature actually did it...
 	 *
 	 * Reorder pref only if it ligated. */
@@ -1439,7 +1428,7 @@
 	  }
 	}
 
-        break;
+	break;
       }
   }
 
@@ -1465,7 +1454,7 @@
     {
       case HB_SCRIPT_TAMIL:
       case HB_SCRIPT_SINHALA:
-        break;
+	break;
 
       default:
 	/* Uniscribe merges the entire syllable into a single cluster... Except for Tamil & Sinhala.
diff --git a/src/hb-ot-shape-complex-khmer.cc b/src/hb-ot-shape-complex-khmer.cc
index b1fa015..fd8a9be 100644
--- a/src/hb-ot-shape-complex-khmer.cc
+++ b/src/hb-ot-shape-complex-khmer.cc
@@ -56,13 +56,6 @@
   {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS},
   {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS},
   {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS},
-  /*
-   * Positioning features.
-   * We don't care about the types.
-   */
-  {HB_TAG('d','i','s','t'), F_GLOBAL},
-  {HB_TAG('a','b','v','m'), F_GLOBAL},
-  {HB_TAG('b','l','w','m'), F_GLOBAL},
 };
 
 /*
@@ -80,10 +73,6 @@
   _KHMER_BLWS,
   _KHMER_PSTS,
 
-  _KHMER_DIST,
-  _KHMER_ABVM,
-  _KHMER_BLWM,
-
   KHMER_NUM_FEATURES,
   KHMER_BASIC_FEATURES = _KHMER_PRES, /* Don't forget to update this! */
 };
@@ -389,7 +378,7 @@
       while (buffer->idx < buffer->len && buffer->successful &&
 	     last_syllable == buffer->cur().syllable() &&
 	     buffer->cur().khmer_category() == OT_Repha)
-        buffer->next_glyph ();
+	buffer->next_glyph ();
 
       buffer->output_info (ginfo);
     }
diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc
index 14d215e..dad1dba 100644
--- a/src/hb-ot-shape-complex-myanmar.cc
+++ b/src/hb-ot-shape-complex-myanmar.cc
@@ -59,25 +59,6 @@
   HB_TAG('b','l','w','s'),
   HB_TAG('p','s','t','s'),
 };
-static const hb_tag_t
-myanmar_positioning_features[] =
-{
-  /*
-   * Positioning features.
-   * We don't care about the types.
-   */
-  HB_TAG('d','i','s','t'),
-  /* Pre-release version of Windows 8 Myanmar font had abvm,blwm
-   * features.  The released Windows 8 version of the font (as well
-   * as the released spec) used 'mark' instead.  The Windows 8
-   * shaper however didn't apply 'mark' but did apply 'mkmk'.
-   * Perhaps it applied abvm/blwm.  This was fixed in a Windows 8
-   * update, so now it applies mark/mkmk.  We are guessing that
-   * it still applies abvm/blwm too.
-   */
-  HB_TAG('a','b','v','m'),
-  HB_TAG('b','l','w','m'),
-};
 
 static void
 setup_syllables_myanmar (const hb_ot_shape_plan_t *plan,
@@ -114,9 +95,6 @@
 
   for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_other_features); i++)
     map->enable_feature (myanmar_other_features[i], F_MANUAL_ZWJ);
-
-  for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_positioning_features); i++)
-    map->enable_feature (myanmar_positioning_features[i]);
 }
 
 static void
@@ -261,7 +239,7 @@
       }
       if (pos == POS_BELOW_C && info[i].myanmar_category() != OT_A)
       {
-        pos = POS_AFTER_SUB;
+	pos = POS_AFTER_SUB;
 	info[i].myanmar_position() = pos;
 	continue;
       }
diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc
index 1ea2957..10f5822 100644
--- a/src/hb-ot-shape-complex-use.cc
+++ b/src/hb-ot-shape-complex-use.cc
@@ -88,17 +88,6 @@
   HB_TAG('p','r','e','s'),
   HB_TAG('p','s','t','s'),
 };
-static const hb_tag_t
-use_positioning_features[] =
-{
-  /*
-   * Positioning features.
-   * We don't care about the types.
-   */
-  HB_TAG('d','i','s','t'),
-  HB_TAG('a','b','v','m'),
-  HB_TAG('b','l','w','m'),
-};
 
 static void
 setup_syllables_use (const hb_ot_shape_plan_t *plan,
@@ -154,10 +143,6 @@
   /* "Standard typographic presentation" */
   for (unsigned int i = 0; i < ARRAY_LENGTH (use_other_features); i++)
     map->enable_feature (use_other_features[i], F_MANUAL_ZWJ);
-
-  /* "Positional feature application" */
-  for (unsigned int i = 0; i < ARRAY_LENGTH (use_positioning_features); i++)
-    map->enable_feature (use_positioning_features[i]);
 }
 
 struct use_shape_plan_t
@@ -549,7 +534,7 @@
       while (buffer->idx < buffer->len && buffer->successful &&
 	     last_syllable == buffer->cur().syllable() &&
 	     buffer->cur().use_category() == USE_R)
-        buffer->next_glyph ();
+	buffer->next_glyph ();
 
       buffer->output_info (ginfo);
     }
diff --git a/src/hb-ot-shape-fallback.cc b/src/hb-ot-shape-fallback.cc
index 03a42df..024bcfe 100644
--- a/src/hb-ot-shape-fallback.cc
+++ b/src/hb-ot-shape-fallback.cc
@@ -45,30 +45,30 @@
     {
       switch (u)
       {
-        case 0x0E31u:
-        case 0x0E34u:
-        case 0x0E35u:
-        case 0x0E36u:
-        case 0x0E37u:
-        case 0x0E47u:
-        case 0x0E4Cu:
-        case 0x0E4Du:
-        case 0x0E4Eu:
+	case 0x0E31u:
+	case 0x0E34u:
+	case 0x0E35u:
+	case 0x0E36u:
+	case 0x0E37u:
+	case 0x0E47u:
+	case 0x0E4Cu:
+	case 0x0E4Du:
+	case 0x0E4Eu:
 	  klass = HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
 	  break;
 
-        case 0x0EB1u:
-        case 0x0EB4u:
-        case 0x0EB5u:
-        case 0x0EB6u:
-        case 0x0EB7u:
-        case 0x0EBBu:
-        case 0x0ECCu:
-        case 0x0ECDu:
+	case 0x0EB1u:
+	case 0x0EB4u:
+	case 0x0EB5u:
+	case 0x0EB6u:
+	case 0x0EB7u:
+	case 0x0EBBu:
+	case 0x0ECCu:
+	case 0x0ECDu:
 	  klass = HB_UNICODE_COMBINING_CLASS_ABOVE;
 	  break;
 
-        case 0x0EBCu:
+	case 0x0EBCu:
 	  klass = HB_UNICODE_COMBINING_CLASS_BELOW;
 	  break;
       }
@@ -167,8 +167,8 @@
 
 void
 _hb_ot_shape_fallback_mark_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED,
-						        hb_font_t *font HB_UNUSED,
-						        hb_buffer_t  *buffer)
+							hb_font_t *font HB_UNUSED,
+							hb_buffer_t  *buffer)
 {
 #ifdef HB_NO_OT_SHAPE_FALLBACK
   return;
@@ -232,10 +232,10 @@
     case HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE:
       if (buffer->props.direction == HB_DIRECTION_LTR) {
 	pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width / 2 - mark_extents.x_bearing;
-        break;
+	break;
       } else if (buffer->props.direction == HB_DIRECTION_RTL) {
 	pos.x_offset += base_extents.x_bearing - mark_extents.width / 2 - mark_extents.x_bearing;
-        break;
+	break;
       }
       HB_FALLTHROUGH;
 
@@ -387,7 +387,7 @@
       if (last_combining_class != this_combining_class)
       {
 	last_combining_class = this_combining_class;
-        cluster_extents = component_extents;
+	cluster_extents = component_extents;
       }
 
       position_mark (plan, font, buffer, cluster_extents, i, this_combining_class);
diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc
index 14c5bd4..553d532 100644
--- a/src/hb-ot-shape-normalize.cc
+++ b/src/hb-ot-shape-normalize.cc
@@ -233,7 +233,7 @@
       }
       else
       {
-        /* Just pass on the two characters separately, let GSUB do its magic. */
+	/* Just pass on the two characters separately, let GSUB do its magic. */
 	set_glyph (buffer->cur(), font);
 	buffer->next_glyph ();
 	set_glyph (buffer->cur(), font);
@@ -343,7 +343,7 @@
       /* From idx to end are simple clusters. */
       if (might_short_circuit)
       {
-        unsigned int done = font->get_nominal_glyphs (end - buffer->idx,
+	unsigned int done = font->get_nominal_glyphs (end - buffer->idx,
 						      &buffer->cur().codepoint,
 						      sizeof (buffer->info[0]),
 						      &buffer->cur().glyph_index(),
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index c8bda2a..5d9a70c 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -285,6 +285,8 @@
 static const hb_ot_map_feature_t
 common_features[] =
 {
+  {HB_TAG('a','b','v','m'), F_GLOBAL},
+  {HB_TAG('b','l','w','m'), F_GLOBAL},
   {HB_TAG('c','c','m','p'), F_GLOBAL},
   {HB_TAG('l','o','c','l'), F_GLOBAL},
   {HB_TAG('m','a','r','k'), F_GLOBAL_MANUAL_JOINERS},
@@ -299,6 +301,7 @@
   {HB_TAG('c','a','l','t'), F_GLOBAL},
   {HB_TAG('c','l','i','g'), F_GLOBAL},
   {HB_TAG('c','u','r','s'), F_GLOBAL},
+  {HB_TAG('d','i','s','t'), F_GLOBAL},
   {HB_TAG('k','e','r','n'), F_GLOBAL_HAS_FALLBACK},
   {HB_TAG('l','i','g','a'), F_GLOBAL},
   {HB_TAG('r','c','l','t'), F_GLOBAL},
@@ -486,7 +489,7 @@
       if (i + 1 < count &&
 	  _hb_unicode_is_emoji_Extended_Pictographic (info[i + 1].codepoint))
       {
-        i++;
+	i++;
 	_hb_glyph_info_set_unicode_props (&info[i], buffer);
 	_hb_glyph_info_set_continuation (&info[i]);
       }
@@ -647,19 +650,19 @@
       while (start &&
 	     _hb_glyph_info_get_general_category (&info[start - 1]) ==
 	     HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
-        start--;
+	start--;
       while (end < count &&
 	     _hb_glyph_info_get_general_category (&info[end]) ==
 	     HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
-        end++;
+	end++;
 
       buffer->unsafe_to_break (start, end);
 
       for (unsigned int j = start; j < i; j++)
-        info[j].mask |= pre_mask;
+	info[j].mask |= pre_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 |= post_mask;
 
       i = end - 1;
     }
@@ -866,7 +869,7 @@
     if (_hb_glyph_info_is_mark (&info[i]))
     {
       if (adjust_offsets)
-        adjust_mark_offsets (&buffer->pos[i]);
+	adjust_mark_offsets (&buffer->pos[i]);
       zero_mark_width (&buffer->pos[i]);
     }
 }
@@ -882,7 +885,7 @@
   if (HB_DIRECTION_IS_HORIZONTAL (direction))
   {
     c->font->get_glyph_h_advances (count, &info[0].codepoint, sizeof(info[0]),
-                                   &pos[0].x_advance, sizeof(pos[0]));
+				   &pos[0].x_advance, sizeof(pos[0]));
     /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
     if (c->font->has_glyph_h_origin_func ())
       for (unsigned int i = 0; i < count; i++)
@@ -893,7 +896,7 @@
   else
   {
     c->font->get_glyph_v_advances (count, &info[0].codepoint, sizeof(info[0]),
-                                   &pos[0].y_advance, sizeof(pos[0]));
+				   &pos[0].y_advance, sizeof(pos[0]));
     for (unsigned int i = 0; i < count; i++)
     {
       c->font->subtract_glyph_v_origin (info[i].codepoint,
diff --git a/src/hb-ot-stat-table.hh b/src/hb-ot-stat-table.hh
index 98bdfa3..b5ea604 100644
--- a/src/hb-ot-stat-table.hh
+++ b/src/hb-ot-stat-table.hh
@@ -304,8 +304,8 @@
 
 
   protected:
-  FixedVersion<>version;        /* Version of the stat table
-                                 * initially set to 0x00010002u */
+  FixedVersion<>version;	/* Version of the stat table
+				 * initially set to 0x00010002u */
   HBUINT16	designAxisSize;	/* The size in bytes of each axis record. */
   HBUINT16	designAxisCount;/* The number of design axis records. In a
 				 * font with an 'fvar' table, this value must be
diff --git a/src/hb-ot-var-avar-table.hh b/src/hb-ot-var-avar-table.hh
index 57a3a6d..ef8ba3f 100644
--- a/src/hb-ot-var-avar-table.hh
+++ b/src/hb-ot-var-avar-table.hh
@@ -49,9 +49,10 @@
   }
 
   public:
-  F2DOT14	fromCoord;	/* A normalized coordinate value obtained using
-				 * default normalization. */
-  F2DOT14	toCoord;	/* The modified, normalized coordinate value. */
+  F2DOT14	coords[2];
+//   F2DOT14	fromCoord;	/* A normalized coordinate value obtained using
+// 				 * default normalization. */
+//   F2DOT14	toCoord;	/* The modified, normalized coordinate value. */
 
   public:
   DEFINE_SIZE_STATIC (4);
@@ -59,12 +60,13 @@
 
 struct SegmentMaps : ArrayOf<AxisValueMap>
 {
-  int map (int value) const
+  int map (int value, unsigned int from_offset = 0, unsigned int to_offset = 1) const
   {
+#define fromCoord coords[from_offset]
+#define toCoord coords[to_offset]
     /* 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 < 2)
     {
       if (!len)
@@ -91,8 +93,12 @@
     return arrayZ[i-1].toCoord +
 	   ((arrayZ[i].toCoord - arrayZ[i-1].toCoord) *
 	    (value - arrayZ[i-1].fromCoord) + denom/2) / denom;
+#undef toCoord
+#undef fromCoord
   }
 
+  int unmap (int value) const { return map (value, 1, 0); }
+
   public:
   DEFINE_SIZE_ARRAY (2, *this);
 };
@@ -114,7 +120,7 @@
     for (unsigned int i = 0; i < count; i++)
     {
       if (unlikely (!map->sanitize (c)))
-        return_trace (false);
+	return_trace (false);
       map = &StructAfter<SegmentMaps> (*map);
     }
 
@@ -133,6 +139,18 @@
     }
   }
 
+  void unmap_coords (int *coords, unsigned int coords_length) const
+  {
+    unsigned int count = hb_min (coords_length, axisCount);
+
+    const SegmentMaps *map = &firstAxisSegmentMaps;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      coords[i] = map->unmap (coords[i]);
+      map = &StructAfter<SegmentMaps> (*map);
+    }
+  }
+
   protected:
   FixedVersion<>version;	/* Version of the avar table
 				 * initially set to 0x00010000u */
@@ -140,7 +158,7 @@
   HBUINT16	axisCount;	/* The number of variation axes in the font. This
 				 * must be the same number as axisCount in the
 				 * 'fvar' table. */
-  SegmentMaps   firstAxisSegmentMaps;
+  SegmentMaps	firstAxisSegmentMaps;
 
   public:
   DEFINE_SIZE_MIN (8);
diff --git a/src/hb-ot-var-fvar-table.hh b/src/hb-ot-var-fvar-table.hh
index 7df8142..3d30d7a 100644
--- a/src/hb-ot-var-fvar-table.hh
+++ b/src/hb-ot-var-fvar-table.hh
@@ -199,7 +199,7 @@
     for (unsigned int i = 0; i < count; i++)
       if (axes[i].axisTag == tag)
       {
-        if (axis_index)
+	if (axis_index)
 	  *axis_index = i;
 	get_axis_deprecated (i, info);
 	return true;
@@ -237,7 +237,21 @@
       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.f + (v >= 0.f ? .5f : -.5f));
+    return roundf (v * 16384.f);
+  }
+
+  float unnormalize_axis_value (unsigned int axis_index, float v) const
+  {
+    hb_ot_var_axis_info_t axis;
+    get_axis_info (axis_index, &axis);
+
+    if (v == 0)
+      return axis.default_value;
+    else if (v < 0)
+      v = v * (axis.default_value - axis.min_value) / 16384.f + axis.default_value;
+    else
+      v = v * (axis.max_value - axis.default_value) / 16384.f + axis.default_value;
+    return v;
   }
 
   unsigned int get_instance_count () const { return instanceCount; }
@@ -266,7 +280,7 @@
     if (unlikely (!instance))
     {
       if (coords_length)
-        *coords_length = 0;
+	*coords_length = 0;
       return 0;
     }
 
@@ -275,7 +289,7 @@
       hb_array_t<const Fixed> instanceCoords = instance->get_coordinates (axisCount)
 							 .sub_array (0, *coords_length);
       for (unsigned int i = 0; i < instanceCoords.length; i++)
-        coords[i] = instanceCoords.arrayZ[i].to_float ();
+	coords[i] = instanceCoords.arrayZ[i].to_float ();
     }
     return axisCount;
   }
diff --git a/src/hb-ot-vorg-table.hh b/src/hb-ot-vorg-table.hh
index d9002f3..e1b25f9 100644
--- a/src/hb-ot-vorg-table.hh
+++ b/src/hb-ot-vorg-table.hh
@@ -70,10 +70,10 @@
   }
 
   template <typename Iterator,
-            hb_requires (hb_is_iterator (Iterator))>
+	    hb_requires (hb_is_iterator (Iterator))>
   void serialize (hb_serialize_context_t *c,
-                  Iterator it,
-                  FWORD defaultVertOriginY)
+		  Iterator it,
+		  FWORD defaultVertOriginY)
   {
 
     if (unlikely (!c->extend_min ((*this))))  return;
@@ -99,15 +99,15 @@
     + vertYOrigins.as_array ()
     | hb_filter (c->plan->glyphset (), &VertOriginMetric::glyph)
     | hb_map ([&] (const VertOriginMetric& _)
-              {
-                hb_codepoint_t new_glyph = HB_SET_VALUE_INVALID;
-                c->plan->new_gid_for_old_gid (_.glyph, &new_glyph);
+	      {
+		hb_codepoint_t new_glyph = HB_SET_VALUE_INVALID;
+		c->plan->new_gid_for_old_gid (_.glyph, &new_glyph);
 
-                VertOriginMetric metric;
-                metric.glyph = new_glyph;
-                metric.vertOriginY = _.vertOriginY;
-                return metric;
-              })
+		VertOriginMetric metric;
+		metric.glyph = new_glyph;
+		metric.vertOriginY = _.vertOriginY;
+		return metric;
+	      })
     ;
 
     /* serialize the new table */
@@ -119,8 +119,8 @@
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  version.major == 1 &&
-                  vertYOrigins.sanitize (c));
+		  version.major == 1 &&
+		  vertYOrigins.sanitize (c));
   }
 
   protected:
diff --git a/src/hb-pool.hh b/src/hb-pool.hh
index ff0ee19..83875db 100644
--- a/src/hb-pool.hh
+++ b/src/hb-pool.hh
@@ -77,14 +77,14 @@
 
   static_assert (ChunkLen > 1, "");
   static_assert (sizeof (T) >= sizeof (void *), "");
-  static_assert (alignof (T) % sizeof (void *) == 0, "");
+  static_assert (alignof (T) % alignof (void *) == 0, "");
 
   struct chunk_t
   {
     T* thread ()
     {
       for (unsigned i = 0; i < ARRAY_LENGTH (arrayZ) - 1; i++)
-        * (T**) &arrayZ[i] = &arrayZ[i + 1];
+	* (T**) &arrayZ[i] = &arrayZ[i + 1];
 
       * (T**) &arrayZ[ARRAY_LENGTH (arrayZ) - 1] = nullptr;
 
diff --git a/src/hb-sanitize.hh b/src/hb-sanitize.hh
index 5f5b4bd..7859c6a 100644
--- a/src/hb-sanitize.hh
+++ b/src/hb-sanitize.hh
@@ -326,8 +326,8 @@
       {
 	DEBUG_MSG_FUNC (SANITIZE, start, "passed first round with %d edits; going for second round", edit_count);
 
-        /* sanitize again to ensure no toe-stepping */
-        edit_count = 0;
+	/* sanitize again to ensure no toe-stepping */
+	edit_count = 0;
 	sane = t->sanitize (this);
 	if (edit_count) {
 	  DEBUG_MSG_FUNC (SANITIZE, start, "requested %d edits in second round; FAILLING", edit_count);
@@ -338,7 +338,7 @@
     else
     {
       if (edit_count && !writable) {
-        start = hb_blob_get_data_writable (blob, nullptr);
+	start = hb_blob_get_data_writable (blob, nullptr);
 	end = start + blob->length;
 
 	if (start)
diff --git a/src/hb-set.hh b/src/hb-set.hh
index ad449d0..6e1295d 100644
--- a/src/hb-set.hh
+++ b/src/hb-set.hh
@@ -63,7 +63,7 @@
     bool is_empty () const
     {
       for (unsigned int i = 0; i < len (); i++)
-        if (v[i])
+	if (v[i])
 	  return false;
       return true;
     }
@@ -77,7 +77,7 @@
       elt_t *la = &elt (a);
       elt_t *lb = &elt (b);
       if (la == lb)
-        *la |= (mask (b) << 1) - mask(a);
+	*la |= (mask (b) << 1) - mask(a);
       else
       {
 	*la |= ~(mask (a) - 1);
@@ -98,7 +98,7 @@
     {
       unsigned int pop = 0;
       for (unsigned int i = 0; i < len (); i++)
-        pop += hb_popcount (v[i]);
+	pop += hb_popcount (v[i]);
       return pop;
     }
 
@@ -149,14 +149,14 @@
     hb_codepoint_t get_min () const
     {
       for (unsigned int i = 0; i < len (); i++)
-        if (v[i])
+	if (v[i])
 	  return i * ELT_BITS + elt_get_min (v[i]);
       return INVALID;
     }
     hb_codepoint_t get_max () const
     {
       for (int i = len () - 1; i >= 0; i--)
-        if (v[i])
+	if (v[i])
 	  return i * ELT_BITS + elt_get_max (v[i]);
       return 0;
     }
@@ -249,7 +249,7 @@
     unsigned int count = pages.length;
     for (unsigned int i = 0; i < count; i++)
       if (!pages[i].is_empty ())
-        return false;
+	return false;
     return true;
   }
 
@@ -333,9 +333,9 @@
       unsigned int end = major_start (m + 1);
       do
       {
-        /* If we try harder we can change the following comparison to <=;
+	/* If we try harder we can change the following comparison to <=;
 	 * Not sure if it's worth it. */
-        if (g < last_g) return false;
+	if (g < last_g) return false;
 	last_g = g;
 	page->add (g);
 
@@ -415,7 +415,7 @@
       if (other->page_at (b).is_empty ()) { b++; continue; }
       if (page_map[a].major != other->page_map[b].major ||
 	  !page_at (a).is_equal (&other->page_at (b)))
-        return false;
+	return false;
       a++;
       b++;
     }
@@ -436,7 +436,7 @@
     hb_codepoint_t c = INVALID;
     while (next (&c))
       if (!larger_set->has (c))
-        return false;
+	return false;
 
     return true;
   }
@@ -458,21 +458,21 @@
     {
       if (page_map[a].major == other->page_map[b].major)
       {
-        count++;
+	count++;
 	a++;
 	b++;
       }
       else if (page_map[a].major < other->page_map[b].major)
       {
-        if (Op::passthru_left)
+	if (Op::passthru_left)
 	  count++;
-        a++;
+	a++;
       }
       else
       {
-        if (Op::passthru_right)
+	if (Op::passthru_right)
 	  count++;
-        b++;
+	b++;
       }
     }
     if (Op::passthru_left)
@@ -482,7 +482,7 @@
 
     if (count > pages.length)
       if (!resize (count))
-        return;
+	return;
     newCount = count;
 
     /* Process in-place backward. */
@@ -673,7 +673,7 @@
     unsigned int count = pages.length;
     for (unsigned int i = 0; i < count; i++)
       if (!page_at (i).is_empty ())
-        return page_map[i].major * page_t::PAGE_BITS + page_at (i).get_min ();
+	return page_map[i].major * page_t::PAGE_BITS + page_at (i).get_min ();
     return INVALID;
   }
   hb_codepoint_t get_max () const
@@ -681,7 +681,7 @@
     unsigned int count = pages.length;
     for (int i = count - 1; i >= 0; i++)
       if (!page_at (i).is_empty ())
-        return page_map[(unsigned) i].major * page_t::PAGE_BITS + page_at (i).get_max ();
+	return page_map[(unsigned) i].major * page_t::PAGE_BITS + page_at (i).get_max ();
     return INVALID;
   }
 
diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc
index 2b23dee..ffd723d 100644
--- a/src/hb-shape-plan.cc
+++ b/src/hb-shape-plan.cc
@@ -164,13 +164,13 @@
 
 /**
  * hb_shape_plan_create: (Xconstructor)
- * @face: 
- * @props: 
+ * @face:
+ * @props:
  * @user_features: (array length=num_user_features):
- * @num_user_features: 
+ * @num_user_features:
  * @shaper_list: (array zero-terminated=1):
  *
- * 
+ *
  *
  * Return value: (transfer full):
  *
@@ -248,7 +248,7 @@
 /**
  * hb_shape_plan_get_empty:
  *
- * 
+ *
  *
  * Return value: (transfer full):
  *
@@ -264,7 +264,7 @@
  * hb_shape_plan_reference: (skip)
  * @shape_plan: a shape plan.
  *
- * 
+ *
  *
  * Return value: (transfer full):
  *
@@ -280,7 +280,7 @@
  * hb_shape_plan_destroy: (skip)
  * @shape_plan: a shape plan.
  *
- * 
+ *
  *
  * Since: 0.9.7
  **/
@@ -299,14 +299,14 @@
 /**
  * hb_shape_plan_set_user_data: (skip)
  * @shape_plan: a shape plan.
- * @key: 
- * @data: 
- * @destroy: 
- * @replace: 
+ * @key:
+ * @data:
+ * @destroy:
+ * @replace:
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.7
  **/
@@ -323,9 +323,9 @@
 /**
  * hb_shape_plan_get_user_data: (skip)
  * @shape_plan: a shape plan.
- * @key: 
+ * @key:
  *
- * 
+ *
  *
  * Return value: (transfer none):
  *
@@ -342,7 +342,7 @@
  * hb_shape_plan_get_shaper:
  * @shape_plan: a shape plan.
  *
- * 
+ *
  *
  * Return value: (transfer none):
  *
@@ -361,11 +361,11 @@
  * @font: a font.
  * @buffer: a buffer.
  * @features: (array length=num_features):
- * @num_features: 
+ * @num_features:
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.7
  **/
@@ -420,13 +420,13 @@
 
 /**
  * hb_shape_plan_create_cached:
- * @face: 
- * @props: 
+ * @face:
+ * @props:
  * @user_features: (array length=num_user_features):
- * @num_user_features: 
+ * @num_user_features:
  * @shaper_list: (array zero-terminated=1):
  *
- * 
+ *
  *
  * Return value: (transfer full):
  *
@@ -481,8 +481,8 @@
     for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next)
       if (node->shape_plan->key.equal (&key))
       {
-        DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache");
-        return hb_shape_plan_reference (node->shape_plan);
+	DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache");
+	return hb_shape_plan_reference (node->shape_plan);
       }
   }
 
diff --git a/src/hb-subset-cff2.cc b/src/hb-subset-cff2.cc
index 1c5308a..319cc26 100644
--- a/src/hb-subset-cff2.cc
+++ b/src/hb-subset-cff2.cc
@@ -330,15 +330,15 @@
       {
 	subset_localsubrs[fd].init ();
 	offsets.localSubrsInfos[fd].init ();
-        if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
-          return false;
+	if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
+	  return false;
 
-        unsigned int dataSize = subset_localsubrs[fd].total_size ();
-        if (dataSize > 0)
-        {
-          offsets.localSubrsInfos[fd].offset = final_size;
-          offsets.localSubrsInfos[fd].offSize = calcOffSize (dataSize);
-          offsets.localSubrsInfos[fd].size = CFF2Subrs::calculate_serialized_size (offsets.localSubrsInfos[fd].offSize, subset_localsubrs[fd].length, dataSize);
+	unsigned int dataSize = subset_localsubrs[fd].total_size ();
+	if (dataSize > 0)
+	{
+	  offsets.localSubrsInfos[fd].offset = final_size;
+	  offsets.localSubrsInfos[fd].offSize = calcOffSize (dataSize);
+	  offsets.localSubrsInfos[fd].size = CFF2Subrs::calculate_serialized_size (offsets.localSubrsInfos[fd].offSize, subset_localsubrs[fd].length, dataSize);
 	}
       }
     }
diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc
index 34f1cb8..d92f33f 100644
--- a/src/hb-subset-input.cc
+++ b/src/hb-subset-input.cc
@@ -172,7 +172,7 @@
 
 HB_EXTERN void
 hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
-        hb_bool_t desubroutinize)
+				    hb_bool_t desubroutinize)
 {
   subset_input->desubroutinize = desubroutinize;
 }
diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index e244da1..1387e0a 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -58,8 +58,8 @@
 #ifndef HB_NO_SUBSET_CFF
 static inline void
 _add_cff_seac_components (const OT::cff1::accelerator_t &cff,
-           hb_codepoint_t gid,
-           hb_set_t *gids_to_retain)
+	   hb_codepoint_t gid,
+	   hb_set_t *gids_to_retain)
 {
   hb_codepoint_t base_gid, accent_gid;
   if (cff.get_seac_components (gid, &base_gid, &accent_gid))
@@ -102,7 +102,7 @@
 static void
 _populate_gids_to_retain (hb_subset_plan_t* plan,
 			  const hb_set_t *unicodes,
-                          const hb_set_t *input_glyphs_to_retain,
+			  const hb_set_t *input_glyphs_to_retain,
 			  bool close_over_gsub)
 {
   OT::cmap::accelerator_t cmap;
@@ -157,11 +157,11 @@
 
 static void
 _create_old_gid_to_new_gid_map (const hb_face_t *face,
-                                bool             retain_gids,
+				bool             retain_gids,
 				const hb_set_t  *all_gids_to_retain,
-                                hb_map_t        *glyph_map, /* OUT */
-                                hb_map_t        *reverse_glyph_map, /* OUT */
-                                unsigned int    *num_glyphs /* OUT */)
+				hb_map_t        *glyph_map, /* OUT */
+				hb_map_t        *reverse_glyph_map, /* OUT */
+				unsigned int    *num_glyphs /* OUT */)
 {
   if (!retain_gids)
   {
@@ -191,8 +191,8 @@
 }
 
 static void
-_nameid_closure (hb_face_t           *face,
-                 hb_set_t            *nameids)
+_nameid_closure (hb_face_t *face,
+		 hb_set_t  *nameids)
 {
 #ifndef HB_NO_STAT
   face->table.STAT->collect_name_ids (nameids);
@@ -213,8 +213,8 @@
  * Since: 1.7.5
  **/
 hb_subset_plan_t *
-hb_subset_plan_create (hb_face_t           *face,
-		       hb_subset_input_t   *input)
+hb_subset_plan_create (hb_face_t         *face,
+		       hb_subset_input_t *input)
 {
   hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> ();
 
@@ -235,16 +235,16 @@
   plan->reverse_glyph_map = hb_map_create ();
 
   _populate_gids_to_retain (plan,
-                            input->unicodes,
-                            input->glyphs,
-                            !input->drop_tables->has (HB_OT_TAG_GSUB));
+			    input->unicodes,
+			    input->glyphs,
+			    !input->drop_tables->has (HB_OT_TAG_GSUB));
 
   _create_old_gid_to_new_gid_map (face,
-                                  input->retain_gids,
+				  input->retain_gids,
 				  plan->_glyphset,
 				  plan->glyph_map,
-                                  plan->reverse_glyph_map,
-                                  &plan->_num_output_glyphs);
+				  plan->reverse_glyph_map,
+				  &plan->_num_output_glyphs);
 
   return plan;
 }
diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh
index ee44b63..af2337e 100644
--- a/src/hb-subset-plan.hh
+++ b/src/hb-subset-plan.hh
@@ -108,7 +108,7 @@
   }
 
   inline bool new_gid_for_codepoint (hb_codepoint_t codepoint,
-                                     hb_codepoint_t *new_gid) const
+				     hb_codepoint_t *new_gid) const
   {
     hb_codepoint_t old_gid = codepoint_to_glyph->get (codepoint);
     if (old_gid == HB_MAP_VALUE_INVALID)
@@ -118,7 +118,7 @@
   }
 
   inline bool new_gid_for_old_gid (hb_codepoint_t old_gid,
-                                   hb_codepoint_t *new_gid) const
+				   hb_codepoint_t *new_gid) const
   {
     hb_codepoint_t gid = glyph_map->get (old_gid);
     if (gid == HB_MAP_VALUE_INVALID)
@@ -129,7 +129,7 @@
   }
 
   inline bool old_gid_for_new_gid (hb_codepoint_t  new_gid,
-                                   hb_codepoint_t *old_gid) const
+				   hb_codepoint_t *old_gid) const
   {
     hb_codepoint_t gid = reverse_glyph_map->get (new_gid);
     if (gid == HB_MAP_VALUE_INVALID)
@@ -157,7 +157,7 @@
 
 HB_INTERNAL hb_subset_plan_t *
 hb_subset_plan_create (hb_face_t           *face,
-                       hb_subset_input_t   *input);
+		       hb_subset_input_t   *input);
 
 HB_INTERNAL void
 hb_subset_plan_destroy (hb_subset_plan_t *plan);
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 7c27cef..827784f 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -84,6 +84,7 @@
     if (unlikely (!buf.alloc (buf_size)))
     {
       DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
+      hb_blob_destroy (source_blob);
       return false;
     }
   retry:
@@ -98,6 +99,7 @@
       if (unlikely (!buf.alloc (buf_size)))
       {
 	DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", HB_UNTAG (tag), buf_size);
+	hb_blob_destroy (source_blob);
 	return false;
       }
       goto retry;
@@ -189,7 +191,7 @@
       DEBUG_MSG(SUBSET, nullptr, "skip loca handled by glyf");
       return true;
     case HB_OT_TAG_cmap:
-      result = _subset<const OT::cmap> (plan);
+      result = _subset2<const OT::cmap> (plan);
       break;
     case HB_OT_TAG_OS2:
       result = _subset2<const OT::OS2> (plan);
@@ -247,6 +249,11 @@
 static bool
 _should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
 {
+  if (!tag)
+    /* Drop tables with no tag as that means table header in
+       _hb_face_builder_reference_table */
+    return true;
+
   if (plan->drop_tables->has (tag))
     return true;
 
diff --git a/src/hb-subset.h b/src/hb-subset.h
index c778896..960afef 100644
--- a/src/hb-subset.h
+++ b/src/hb-subset.h
@@ -68,7 +68,7 @@
 
 HB_EXTERN void
 hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
-        hb_bool_t desubroutinize);
+				    hb_bool_t desubroutinize);
 HB_EXTERN hb_bool_t
 hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input);
 
diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc
index 289a347..e93cf7f 100644
--- a/src/hb-uniscribe.cc
+++ b/src/hb-uniscribe.cc
@@ -385,8 +385,8 @@
   static const uint16_t name_IDs[] = { 1, 2, 3, 4, 6 };
 
   unsigned int name_table_length = OT::name::min_size +
-                                   ARRAY_LENGTH (name_IDs) * OT::NameRecord::static_size +
-                                   name_str_len * 2; /* for name data in UTF16BE form */
+				   ARRAY_LENGTH (name_IDs) * OT::NameRecord::static_size +
+				   name_str_len * 2; /* for name data in UTF16BE form */
   unsigned int padded_name_table_length = ((name_table_length + 3) & ~3);
   unsigned int name_table_offset = (length + 3) & ~3;
 
@@ -666,7 +666,7 @@
 
       if (event->index != last_index)
       {
-        /* Save a snapshot of active features and the range. */
+	/* Save a snapshot of active features and the range. */
 	range_record_t *range = range_records.push ();
 
 	unsigned int offset = feature_records.length;
@@ -701,7 +701,7 @@
       }
       else
       {
-        active_feature_t *feature = active_features.find (&event->feature);
+	active_feature_t *feature = active_features.find (&event->feature);
 	if (feature)
 	  active_features.remove (feature - active_features.arrayZ);
       }
diff --git a/src/hb-utf.hh b/src/hb-utf.hh
index 59ec75e..ff5712d 100644
--- a/src/hb-utf.hh
+++ b/src/hb-utf.hh
@@ -235,10 +235,10 @@
       hb_codepoint_t h = text[-1];
       if (likely (hb_in_range<hb_codepoint_t> (h, 0xD800u, 0xDBFFu)))
       {
-        /* High-surrogate in h */
-        *unicode = (h << 10) + c - ((0xD800u << 10) - 0x10000u + 0xDC00u);
-        text--;
-        return text;
+	/* High-surrogate in h */
+	*unicode = (h << 10) + c - ((0xD800u << 10) - 0x10000u + 0xDC00u);
+	text--;
+	return text;
       }
     }
 
diff --git a/src/hb-vector.hh b/src/hb-vector.hh
index 035c6d0..288a541 100644
--- a/src/hb-vector.hh
+++ b/src/hb-vector.hh
@@ -290,7 +290,7 @@
   typedef hb_sorted_array_t<      Type>       iter_t;
   const_iter_t  iter () const { return as_array (); }
   const_iter_t citer () const { return as_array (); }
-        iter_t  iter ()       { return as_array (); }
+	iter_t  iter ()       { return as_array (); }
   operator       iter_t ()       { return iter (); }
   operator const_iter_t () const { return iter (); }
 
diff --git a/src/hb-version.h b/src/hb-version.h
index 251cc63..18b3c2c 100644
--- a/src/hb-version.h
+++ b/src/hb-version.h
@@ -37,10 +37,10 @@
 
 
 #define HB_VERSION_MAJOR 2
-#define HB_VERSION_MINOR 5
-#define HB_VERSION_MICRO 3
+#define HB_VERSION_MINOR 6
+#define HB_VERSION_MICRO 1
 
-#define HB_VERSION_STRING "2.5.3"
+#define HB_VERSION_STRING "2.6.1"
 
 #define HB_VERSION_ATLEAST(major,minor,micro) \
 	((major)*10000+(minor)*100+(micro) <= \
diff --git a/src/hb.hh b/src/hb.hh
index 8dcd5aa..0e7b890 100644
--- a/src/hb.hh
+++ b/src/hb.hh
@@ -526,7 +526,7 @@
 #endif
 #endif
     return (v[0] <<  8)
-         + (v[1]      );
+	 + (v[1]      );
   }
   private: uint8_t v[2];
 };
@@ -544,8 +544,8 @@
   operator Type () const
   {
     return (v[0] << 16)
-         + (v[1] <<  8)
-         + (v[2]      );
+	 + (v[1] <<  8)
+	 + (v[2]      );
   }
   private: uint8_t v[3];
 };
@@ -564,9 +564,9 @@
   operator Type () const
   {
     return (v[0] << 24)
-         + (v[1] << 16)
-         + (v[2] <<  8)
-         + (v[3]      );
+	 + (v[1] << 16)
+	 + (v[2] <<  8)
+	 + (v[3]      );
   }
   private: uint8_t v[4];
 };
diff --git a/src/test-ot-color.cc b/src/test-ot-color.cc
index 3b4c8b6..88924b4 100644
--- a/src/test-ot-color.cc
+++ b/src/test-ot-color.cc
@@ -330,8 +330,8 @@
 
     // disabled when color font as cairo rendering of NotoColorEmoji is soooo slow
     if (!hb_ot_color_has_layers (face) &&
-        !hb_ot_color_has_png (face) &&
-        !hb_ot_color_has_svg (face))
+	!hb_ot_color_has_png (face) &&
+	!hb_ot_color_has_svg (face))
       dump_glyphs (cairo_face, upem, num_glyphs, face_index);
 
     hb_font_destroy (font);
diff --git a/src/test-ot-meta.cc b/src/test-ot-meta.cc
index 512df5a..1045007 100644
--- a/src/test-ot-meta.cc
+++ b/src/test-ot-meta.cc
@@ -48,11 +48,11 @@
   unsigned int count = 0;
 
 #ifndef HB_NO_META
-  count = hb_ot_meta_get_entries (face, 0, nullptr, nullptr);
+  count = hb_ot_meta_get_entry_tags (face, 0, nullptr, nullptr);
 
   hb_ot_meta_tag_t *tags = (hb_ot_meta_tag_t *)
 			   malloc (sizeof (hb_ot_meta_tag_t) * count);
-  hb_ot_meta_get_entries (face, 0, &count, tags);
+  hb_ot_meta_get_entry_tags (face, 0, &count, tags);
   for (unsigned i = 0; i < count; ++i)
   {
     hb_blob_t *entry = hb_ot_meta_reference_entry (face, tags[i]);
diff --git a/src/test-unicode-ranges.cc b/src/test-unicode-ranges.cc
index 0eef8c2..33cac6b 100644
--- a/src/test-unicode-ranges.cc
+++ b/src/test-unicode-ranges.cc
@@ -33,9 +33,9 @@
   if (OT::_hb_ot_os2_get_unicode_range_bit (cp) != bit)
   {
     fprintf (stderr, "got incorrect bit (%d) for cp 0x%X. Should have been %d.",
-             OT::_hb_ot_os2_get_unicode_range_bit (cp),
-             cp,
-             bit);
+	     OT::_hb_ot_os2_get_unicode_range_bit (cp),
+	     cp,
+	     bit);
     abort();
   }
 }
diff --git a/test/api/fonts/Roboto-Regular.D7,D8,D9,DA,DE.ttf b/test/api/fonts/Roboto-Regular.D7,D8,D9,DA,DE.ttf
index 3a71f53..7860f2f 100644
--- a/test/api/fonts/Roboto-Regular.D7,D8,D9,DA,DE.ttf
+++ b/test/api/fonts/Roboto-Regular.D7,D8,D9,DA,DE.ttf
Binary files differ
diff --git a/test/api/fonts/Roboto-Regular.abc.ttf b/test/api/fonts/Roboto-Regular.abc.ttf
index 9d791f7..705ec69 100644
--- a/test/api/fonts/Roboto-Regular.abc.ttf
+++ b/test/api/fonts/Roboto-Regular.abc.ttf
Binary files differ
diff --git a/test/api/fonts/Roboto-Regular.ac.ttf b/test/api/fonts/Roboto-Regular.ac.ttf
index 6ac1b33..5a5e68e 100644
--- a/test/api/fonts/Roboto-Regular.ac.ttf
+++ b/test/api/fonts/Roboto-Regular.ac.ttf
Binary files differ
diff --git a/test/api/hb-subset-test.h b/test/api/hb-subset-test.h
index 25cf1e3..99f567a 100644
--- a/test/api/hb-subset-test.h
+++ b/test/api/hb-subset-test.h
@@ -76,7 +76,7 @@
 
 static inline hb_face_t *
 hb_subset_test_create_subset (hb_face_t *source,
-                              hb_subset_input_t *input)
+			      hb_subset_input_t *input)
 {
   hb_face_t *subset = hb_subset (source, input);
   g_assert (subset);
@@ -87,8 +87,8 @@
 
 static inline void
 hb_subset_test_check (hb_face_t *expected,
-                      hb_face_t *actual,
-                      hb_tag_t   table)
+		      hb_face_t *actual,
+		      hb_tag_t   table)
 {
   hb_blob_t *expected_blob, *actual_blob;
   expected_blob = hb_face_reference_table (expected, table);
diff --git a/test/api/test-buffer.c b/test/api/test-buffer.c
index 64ab3db..228f0f3 100644
--- a/test/api/test-buffer.c
+++ b/test/api/test-buffer.c
@@ -208,7 +208,7 @@
       if (buffer_type == BUFFER_UTF16)
 	cluster++;
       else if (buffer_type == BUFFER_UTF8)
-        cluster += 3;
+	cluster += 3;
     }
     g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
     g_assert_cmphex (glyphs[i].cluster,   ==, cluster);
diff --git a/test/api/test-object.c b/test/api/test-object.c
index 093615e..5154621 100644
--- a/test/api/test-object.c
+++ b/test/api/test-object.c
@@ -345,7 +345,7 @@
       if (!obj)
 	continue;
       if (obj == o->get_empty ())
-        continue; /* Tested already */
+	continue; /* Tested already */
 
       g_assert (obj == o->reference (obj));
       o->destroy (obj);
diff --git a/test/api/test-ot-color.c b/test/api/test-ot-color.c
index d646f73..c2bbad2 100644
--- a/test/api/test-ot-color.c
+++ b/test/api/test-ot-color.c
@@ -210,7 +210,7 @@
 test_hb_ot_color_palette_get_colors_v0 (void)
 {
   unsigned int num_colors = hb_ot_color_palette_get_colors (cpal_v0, 0, 0, NULL, NULL);
-  hb_color_t *colors = (hb_color_t*) alloca (num_colors * sizeof (hb_color_t));
+  hb_color_t *colors = (hb_color_t*) malloc (num_colors * sizeof (hb_color_t));
   size_t colors_size = num_colors * sizeof(*colors);
   g_assert_cmpint (num_colors, ==, 2);
 
@@ -252,6 +252,8 @@
   g_assert_cmpint (num_colors, ==, 0);
   assert_color_rgba (colors, 0, 0x44, 0x44, 0x44, 0x44);  /* untouched */
   assert_color_rgba (colors, 1, 0x44, 0x44, 0x44, 0x44);  /* untouched */
+	
+  free (colors);
 }
 
 
diff --git a/test/api/test-ot-face.c b/test/api/test-ot-face.c
index eff0ff7..44a9116 100644
--- a/test/api/test-ot-face.c
+++ b/test/api/test-ot-face.c
@@ -90,7 +90,7 @@
   hb_ot_math_get_min_connector_overlap (font, HB_DIRECTION_RTL);
   hb_ot_math_get_glyph_assembly (font, cp, HB_DIRECTION_BTT, 0, NULL, NULL, NULL);
 
-  hb_ot_meta_get_entries (face, 0, NULL, NULL);
+  hb_ot_meta_get_entry_tags (face, 0, NULL, NULL);
   hb_blob_destroy (hb_ot_meta_reference_entry (face, HB_OT_META_TAG_DESIGN_LANGUAGES));
 
   hb_ot_metrics_get_position (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, NULL);
diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c
index 000b0a2..73b1a25 100644
--- a/test/api/test-ot-math.c
+++ b/test/api/test-ot-math.c
@@ -457,41 +457,41 @@
 
   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);
+						 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);
+						 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);
+						 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);
+						 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);
+				   glyph,
+				   HB_DIRECTION_RTL,
+				   offset,
+				   &count,
+				   variants);
     offset += count;
   } while (count == variantsSize);
   g_assert_cmpint(offset, ==, 3);
@@ -510,11 +510,11 @@
   do {
     count = variantsSize;
     hb_ot_math_get_glyph_variants (hb_font,
-                                   glyph,
-                                   HB_DIRECTION_BTT,
-                                   offset,
-                                   &count,
-                                   variants);
+				   glyph,
+				   HB_DIRECTION_BTT,
+				   offset,
+				   &count,
+				   variants);
     offset += count;
   } while (count == variantsSize);
   g_assert_cmpint(offset, ==, 4);
@@ -581,46 +581,46 @@
 
   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);
+						 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);
+						 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);
+						 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);
+						 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);
+				   glyph,
+				   HB_DIRECTION_RTL,
+				   offset,
+				   &count,
+				   parts,
+				   NULL);
     offset += count;
   } while (count == partsSize);
   g_assert_cmpint(offset, ==, 3);
@@ -648,12 +648,12 @@
   do {
     count = partsSize;
     hb_ot_math_get_glyph_assembly (hb_font,
-                                   glyph,
-                                   HB_DIRECTION_BTT,
-                                   offset,
-                                   &count,
-                                   parts,
-                                   NULL);
+				   glyph,
+				   HB_DIRECTION_BTT,
+				   offset,
+				   &count,
+				   parts,
+				   NULL);
     offset += count;
   } while (count == partsSize);
   g_assert_cmpint(offset, ==, 5);
diff --git a/test/api/test-ot-meta.c b/test/api/test-ot-meta.c
index c15cc1b..573c8c6 100644
--- a/test/api/test-ot-meta.c
+++ b/test/api/test-ot-meta.c
@@ -35,18 +35,18 @@
   hb_ot_meta_tag_t entries[2];
 
   unsigned int entries_count = 2;
-  g_assert_cmpint (hb_ot_meta_get_entries (face, 0, &entries_count, entries), ==, 5);
+  g_assert_cmpint (hb_ot_meta_get_entry_tags (face, 0, &entries_count, entries), ==, 5);
   g_assert_cmpint (entries_count, ==, 2);
   g_assert_cmpint (entries[0], ==, HB_TAG ('a','p','p','l'));
   g_assert_cmpint (entries[1], ==, HB_TAG ('b','i','l','d'));
 
   entries_count = 1;
-  g_assert_cmpint (hb_ot_meta_get_entries (face, 2, &entries_count, entries), ==, 5);
+  g_assert_cmpint (hb_ot_meta_get_entry_tags (face, 2, &entries_count, entries), ==, 5);
   g_assert_cmpint (entries_count, ==, 1);
   g_assert_cmpint (entries[0], ==, HB_TAG ('d','l','n','g'));
 
   entries_count = 2;
-  g_assert_cmpint (hb_ot_meta_get_entries (face, 4, &entries_count, entries), ==, 5);
+  g_assert_cmpint (hb_ot_meta_get_entry_tags (face, 4, &entries_count, entries), ==, 5);
   g_assert_cmpint (entries_count, ==, 1);
   g_assert_cmpint (entries[0], ==, HB_TAG ('s','l','n','g'));
 
diff --git a/test/api/test-shape.c b/test/api/test-shape.c
index 8fbe7f7..fd7acec 100644
--- a/test/api/test-shape.c
+++ b/test/api/test-shape.c
@@ -70,30 +70,13 @@
 static const char TesT[] = "TesT";
 
 static void
-test_shape (void)
+test_font (hb_font_t *font)
 {
-  hb_blob_t *blob;
-  hb_face_t *face;
-  hb_font_funcs_t *ffuncs;
-  hb_font_t *font;
   hb_buffer_t *buffer;
   unsigned int len;
   hb_glyph_info_t *glyphs;
   hb_glyph_position_t *positions;
 
-  blob = hb_blob_create (test_data, sizeof (test_data), HB_MEMORY_MODE_READONLY, NULL, NULL);
-  face = hb_face_create (blob, 0);
-  hb_blob_destroy (blob);
-  font = hb_font_create (face);
-  hb_face_destroy (face);
-  hb_font_set_scale (font, 10, 10);
-
-  ffuncs = hb_font_funcs_create ();
-  hb_font_funcs_set_glyph_h_advance_func (ffuncs, glyph_h_advance_func, NULL, NULL);
-  hb_font_funcs_set_nominal_glyph_func (ffuncs, glyph_func, malloc (10), free);
-  hb_font_set_funcs (font, ffuncs, NULL, NULL);
-  hb_font_funcs_destroy (ffuncs);
-
   buffer =  hb_buffer_create ();
   hb_buffer_set_direction (buffer, HB_DIRECTION_LTR);
   hb_buffer_add_utf8 (buffer, TesT, 4, 0, 4);
@@ -123,6 +106,35 @@
   }
 
   hb_buffer_destroy (buffer);
+}
+
+static void
+test_shape (void)
+{
+  hb_blob_t *blob;
+  hb_face_t *face;
+  hb_font_funcs_t *ffuncs;
+  hb_font_t *font, *sub_font;
+
+  blob = hb_blob_create (test_data, sizeof (test_data), HB_MEMORY_MODE_READONLY, NULL, NULL);
+  face = hb_face_create (blob, 0);
+  hb_blob_destroy (blob);
+  font = hb_font_create (face);
+  hb_face_destroy (face);
+  hb_font_set_scale (font, 10, 10);
+
+  ffuncs = hb_font_funcs_create ();
+  hb_font_funcs_set_glyph_h_advance_func (ffuncs, glyph_h_advance_func, NULL, NULL);
+  hb_font_funcs_set_nominal_glyph_func (ffuncs, glyph_func, malloc (10), free);
+  hb_font_set_funcs (font, ffuncs, NULL, NULL);
+  hb_font_funcs_destroy (ffuncs);
+
+  test_font (font);
+
+  sub_font = hb_font_create_sub_font (font);
+  test_font (sub_font);
+
+  hb_font_destroy (sub_font);
   hb_font_destroy (font);
 }
 
diff --git a/test/api/test-unicode.c b/test/api/test-unicode.c
index 4376fd0..71a471d 100644
--- a/test/api/test-unicode.c
+++ b/test/api/test-unicode.c
@@ -62,8 +62,8 @@
 
 static hb_script_t
 simple_get_script (hb_unicode_funcs_t *ufuncs,
-                   hb_codepoint_t      codepoint,
-                   void               *user_data)
+		   hb_codepoint_t      codepoint,
+		   void               *user_data)
 {
   data_t *data = (data_t *) user_data;
 
@@ -79,8 +79,8 @@
 
 static hb_script_t
 a_is_for_arabic_get_script (hb_unicode_funcs_t *ufuncs,
-                            hb_codepoint_t      codepoint,
-                            void               *user_data)
+			    hb_codepoint_t      codepoint,
+			    void               *user_data)
 {
   data_t *data = (data_t *) user_data;
 
@@ -751,7 +751,7 @@
   hb_unicode_funcs_destroy (uf);
 
   hb_unicode_funcs_set_script_func (aa, a_is_for_arabic_get_script,
-                                    &f->data[1], free_up);
+				    &f->data[1], free_up);
 
   g_assert_cmphex (hb_unicode_script (aa, 'a'), ==, HB_SCRIPT_ARABIC);
   g_assert_cmphex (hb_unicode_script (aa, 'b'), ==, HB_SCRIPT_UNKNOWN);
@@ -770,7 +770,7 @@
   aa = hb_unicode_funcs_create (uf);
 
   hb_unicode_funcs_set_script_func (aa, a_is_for_arabic_get_script,
-                                    &f->data[1], free_up);
+				    &f->data[1], free_up);
 
   g_assert_cmphex (hb_unicode_script (aa, 'a'), ==, HB_SCRIPT_ARABIC);
   g_assert_cmphex (hb_unicode_script (aa, 'b'), ==, HB_SCRIPT_LATIN);
@@ -788,7 +788,7 @@
   uf = hb_unicode_funcs_create (NULL);
 
   hb_unicode_funcs_set_script_func (uf, simple_get_script,
-                                    &f->data[0], free_up);
+				    &f->data[0], free_up);
 
   aa = hb_unicode_funcs_create (uf);
 
@@ -798,7 +798,7 @@
   g_assert (!f->data[0].freed);
 
   hb_unicode_funcs_set_script_func (aa, a_is_for_arabic_get_script,
-                                    &f->data[1], free_up);
+				    &f->data[1], free_up);
 
   g_assert_cmphex (hb_unicode_script (aa, 'a'), ==, HB_SCRIPT_ARABIC);
   g_assert_cmphex (hb_unicode_script (aa, 'b'), ==, HB_SCRIPT_LATIN);
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5667673584697344 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5667673584697344
new file mode 100644
index 0000000..e08ab56
--- /dev/null
+++ b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5667673584697344
Binary files differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5675720390475776 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5675720390475776
new file mode 100644
index 0000000..3881fbe
--- /dev/null
+++ b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5675720390475776
Binary files differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5754526379802624 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5754526379802624
new file mode 100644
index 0000000..3a7cc9d
--- /dev/null
+++ b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5754526379802624
Binary files differ
diff --git a/test/fuzzing/run-subset-fuzzer-tests.py b/test/fuzzing/run-subset-fuzzer-tests.py
index f94c13f..820519f 100755
--- a/test/fuzzing/run-subset-fuzzer-tests.py
+++ b/test/fuzzing/run-subset-fuzzer-tests.py
@@ -33,7 +33,7 @@
 		def timeout(p, is_killed):
 			is_killed['value'] = True
 			p.kill()
-		timer = threading.Timer (8, timeout, [p, is_killed])
+		timer = threading.Timer (16, timeout, [p, is_killed])
 
 		try:
 			timer.start()
diff --git a/test/shaping/data/in-house/Makefile.sources b/test/shaping/data/in-house/Makefile.sources
index 0e9a3a2..bf14a98 100644
--- a/test/shaping/data/in-house/Makefile.sources
+++ b/test/shaping/data/in-house/Makefile.sources
@@ -41,6 +41,7 @@
 	tests/myanmar-syllable.tests \
 	tests/myanmar-zawgyi.tests \
 	tests/none-directional.tests \
+	tests/positioning-features.tests \
 	tests/rand.tests \
 	tests/spaces.tests \
 	tests/simple.tests \
diff --git a/test/shaping/data/in-house/fonts/53a91c20e33a596f2be17fb68b382d6b7eb85d5c.ttf b/test/shaping/data/in-house/fonts/53a91c20e33a596f2be17fb68b382d6b7eb85d5c.ttf
new file mode 100644
index 0000000..f3d52e5
--- /dev/null
+++ b/test/shaping/data/in-house/fonts/53a91c20e33a596f2be17fb68b382d6b7eb85d5c.ttf
Binary files differ
diff --git a/test/shaping/data/in-house/fonts/ea3f63620511b2097200d23774ffef197e829e69.ttf b/test/shaping/data/in-house/fonts/ea3f63620511b2097200d23774ffef197e829e69.ttf
new file mode 100644
index 0000000..31d4e50
--- /dev/null
+++ b/test/shaping/data/in-house/fonts/ea3f63620511b2097200d23774ffef197e829e69.ttf
Binary files differ
diff --git a/test/shaping/data/in-house/fonts/f79eb71df4e4c9c273b67b89a06e5ff9e3c1f834.ttf b/test/shaping/data/in-house/fonts/f79eb71df4e4c9c273b67b89a06e5ff9e3c1f834.ttf
new file mode 100644
index 0000000..be48fd0
--- /dev/null
+++ b/test/shaping/data/in-house/fonts/f79eb71df4e4c9c273b67b89a06e5ff9e3c1f834.ttf
Binary files differ
diff --git a/test/shaping/data/in-house/tests/aat-trak.tests b/test/shaping/data/in-house/tests/aat-trak.tests
index 4bbe729..6da3ba8 100644
--- a/test/shaping/data/in-house/tests/aat-trak.tests
+++ b/test/shaping/data/in-house/tests/aat-trak.tests
@@ -1,11 +1,11 @@
 ../fonts/TRAK.ttf::U+0041,U+0042,U+0043:[A.alt=0+1000|B=1+1000|C.alt=2+1000]
 ../fonts/TRAK.ttf:--font-ptem=.5:U+0041,U+0042,U+0043:[A.alt=0@100,0+1200|B=1@100,0+1200|C.alt=2@100,0+1200]
 ../fonts/TRAK.ttf:--font-ptem=1:U+0041,U+0042,U+0043:[A.alt=0@100,0+1200|B=1@100,0+1200|C.alt=2@100,0+1200]
-../fonts/TRAK.ttf:--font-ptem=2:U+0041,U+0042,U+0043:[A.alt=0@93,0+1187|B=1@93,0+1187|C.alt=2@93,0+1187]
-../fonts/TRAK.ttf:--font-ptem=9:U+0041,U+0042,U+0043:[A.alt=0+1000|B=1+1000|C.alt=2+1000]
-../fonts/TRAK.ttf:--font-ptem=24:U+0041,U+0042,U+0043:[A.alt=0@-12,0+976|B=1@-12,0+976|C.alt=2@-12,0+976]
-../fonts/TRAK.ttf:--font-ptem=72:U+0041,U+0042,U+0043:[A.alt=0@-50,0+900|B=1@-50,0+900|C.alt=2@-50,0+900]
-../fonts/TRAK.ttf:--font-ptem=144:U+0041,U+0042,U+0043:[A.alt=0@-107,0+786|B=1@-107,0+786|C.alt=2@-107,0+786]
-../fonts/TRAK.ttf:--font-ptem=144:U+0041,U+0042,U+0043:[A.alt=0@-107,0+786|B=1@-107,0+786|C.alt=2@-107,0+786]
+../fonts/TRAK.ttf:--font-ptem=2:U+0041,U+0042,U+0043:[A.alt=0@100,0+1200|B=1@100,0+1200|C.alt=2@100,0+1200]
+../fonts/TRAK.ttf:--font-ptem=9:U+0041,U+0042,U+0043:[A.alt=0@30,0+1060|B=1@30,0+1060|C.alt=2@30,0+1060]
+../fonts/TRAK.ttf:--font-ptem=24:U+0041,U+0042,U+0043:[A.alt=0@-7,0+986|B=1@-7,0+986|C.alt=2@-7,0+986]
+../fonts/TRAK.ttf:--font-ptem=72:U+0041,U+0042,U+0043:[A.alt=0@-35,0+929|B=1@-35,0+929|C.alt=2@-35,0+929]
+../fonts/TRAK.ttf:--font-ptem=144:U+0041,U+0042,U+0043:[A.alt=0@-78,0+843|B=1@-78,0+843|C.alt=2@-78,0+843]
+../fonts/TRAK.ttf:--font-ptem=144:U+0041,U+0042,U+0043:[A.alt=0@-78,0+843|B=1@-78,0+843|C.alt=2@-78,0+843]
 ../fonts/TRAK.ttf:--font-ptem=144 --features=-trak:U+0041,U+0042,U+0043:[A.alt=0+1000|B=1+1000|C.alt=2+1000]
-../fonts/TRAK.ttf:--font-ptem=144 --features=-trak[1;3]:U+0041,U+0042,U+0043,U+0041,U+0042,U+0043:[A.alt=0@-107,0+786|B=1+1000|C.alt=2+1000|A.alt=3@-107,0+786|B=4@-107,0+786|C.alt=5@-107,0+786]
+../fonts/TRAK.ttf:--font-ptem=144 --features=-trak[1;3]:U+0041,U+0042,U+0043,U+0041,U+0042,U+0043:[A.alt=0@-78,0+843|B=1+1000|C.alt=2+1000|A.alt=3@-78,0+843|B=4@-78,0+843|C.alt=5@-78,0+843]
diff --git a/test/shaping/data/in-house/tests/macos.tests b/test/shaping/data/in-house/tests/macos.tests
index db4a31d..434e0a5 100644
--- a/test/shaping/data/in-house/tests/macos.tests
+++ b/test/shaping/data/in-house/tests/macos.tests
@@ -13,7 +13,7 @@
 /System/Library/Fonts/GeezaPro.ttc@f43ee7151c2e9f1dddfbc26cfc148609eb5c5820:--font-funcs ot:U+0631,U+0628:[u0628.beh=1+1415|u0631.reh=0@-202,0+700]
 /System/Library/Fonts/GeezaPro.ttc@f43ee7151c2e9f1dddfbc26cfc148609eb5c5820:--font-funcs ot:U+0628,U+064F:[u064f.damma=0@250,-250+250|u0628.beh=0@-250,0+1165]
 /System/Library/Fonts/SFNSDisplay.ttf@92787c30716672737e9059bc367c15d04fbc1ced:--font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[gid225=0+1105|gid584=1@-105,0+979|gid3=2+490|gid4=3+1227|gid265=4@-65,0+1227|gid3=5+490|gid225=6+1130|gid728=7@-80,0+569|gid3=8+490|gid265=9+1227|gid505=10@-65,0+997|gid3=11+490|gid728=12+609|gid225=13@-40,0+1170|gid3=14+490|gid584=15+1004|gid225=16@-80,0+1130|gid3=17+490|gid225=18+1105|gid576=19@-105,0+1068]
-/System/Library/Fonts/SFNSDisplay.ttf@92787c30716672737e9059bc367c15d04fbc1ced:--font-ptem 9 --font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[gid225=0@46,0+1197|gid584=1@-59,0+1071|gid3=2@46,0+582|gid4=3@46,0+1319|gid265=4@-19,0+1319|gid3=5@46,0+582|gid225=6@46,0+1222|gid728=7@-34,0+661|gid3=8@46,0+582|gid265=9@46,0+1319|gid505=10@-19,0+1089|gid3=11@46,0+582|gid728=12@46,0+701|gid225=13@6,0+1262|gid3=14@46,0+582|gid584=15@46,0+1096|gid225=16@-34,0+1222|gid3=17@46,0+582|gid225=18@46,0+1197|gid576=19@-59,0+1160]
+/System/Library/Fonts/SFNSDisplay.ttf@92787c30716672737e9059bc367c15d04fbc1ced:--font-ptem 9 --font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[gid225=0@65,0+1235|gid584=1@-40,0+1109|gid3=2@65,0+620|gid4=3@65,0+1357|gid265=4+1357|gid3=5@65,0+620|gid225=6@65,0+1260|gid728=7@-15,0+699|gid3=8@65,0+620|gid265=9@65,0+1357|gid505=10+1127|gid3=11@65,0+620|gid728=12@65,0+739|gid225=13@25,0+1300|gid3=14@65,0+620|gid584=15@65,0+1134|gid225=16@-15,0+1260|gid3=17@65,0+620|gid225=18@65,0+1235|gid576=19@-40,0+1198]
 /System/Library/Fonts/Apple Color Emoji.ttc@d2fe8a134483aa48a43a9d1e4b7204d37a4abdf5:--remove-default-ignorables --font-funcs ot:U+1F468,U+200D,U+1F469,U+200D,U+1F467,U+200D,U+1F466:[u1F46A.MWGB=0+800]
 /Library/Fonts/Zapfino.ttf@9ee799ffb09516ead6b0cf6f2ca807276e150748:--font-funcs ot:U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+006F:[Z=0+416|a=1@-21,0+264|p_f=2+433|i=4+181|n=5+261|Z=6+416|a=7@-21,0+264|p_f=8+433|i=10+181|n=11+261|Z=12+416|a=13@-21,0+264|p_f=14+433|i=16+181|n=17+261|Z=18+416|a=19@-21,0+264|p_f=20+433|i=22+181|n=23+261|Z=24+416|a=25@-21,0+264|p_f=26+433|i=28+181|n=29+261|Z=30+416|a=31@-21,0+264|p_f=32+433|i=34+181|n=35+261|Z=36+416|a=37@-21,0+264|p_f=38+433|i=40+181|n=41+261|Z=42+416|a=43@-21,0+264|p_f=44+433|i=46+181|n=47+261|Z=48+416|a=49@-21,0+264|p_f=50+433|i=52+181|n=53+261|Z=54+416|a=55@-21,0+264|p_f=56+433|i=58+181|n=59+261|Z=60+416|a=61@-21,0+264|p_f=62+433|i=64+181|n=65+261|Z_a_p_f_i_n_o=66+2333]
 
@@ -32,7 +32,7 @@
 /System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334:--font-funcs ot:U+0631,U+0628:[u0628.beh=1+1415|u0631.reh=0@-202,0+700]
 /System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334:--font-funcs ot:U+0628,U+064F:[u064f.damma=0@250,-250+250|u0628.beh=0@-250,0+1165]
 /System/Library/Fonts/SFNSDisplay.ttf@c8948f464ff822a5f9bbf2e12d0e4e32268815aa:--font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[gid282=0+1055|gid658=1@-135,0+914|gid3=2+420|gid4=3+1227|gid332=4@-65,0+1227|gid3=5+420|gid282=6+1075|gid813=7@-115,0+516|gid3=8+420|gid332=9+1217|gid572=10@-75,0+953|gid3=11+420|gid813=12+546|gid282=13@-85,0+1105|gid3=14+420|gid658=15+914|gid282=16@-135,0+1055|gid3=17+420|gid282=18+1055|gid649=19@-135,0+999]
-/System/Library/Fonts/SFNSDisplay.ttf@c8948f464ff822a5f9bbf2e12d0e4e32268815aa:--font-ptem 9 --font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[gid282=0@46,0+1147|gid658=1@-89,0+1006|gid3=2@46,0+512|gid4=3@46,0+1319|gid332=4@-19,0+1319|gid3=5@46,0+512|gid282=6@46,0+1167|gid813=7@-69,0+608|gid3=8@46,0+512|gid332=9@46,0+1309|gid572=10@-29,0+1045|gid3=11@46,0+512|gid813=12@46,0+638|gid282=13@-39,0+1197|gid3=14@46,0+512|gid658=15@46,0+1006|gid282=16@-89,0+1147|gid3=17@46,0+512|gid282=18@46,0+1147|gid649=19@-89,0+1091]
+/System/Library/Fonts/SFNSDisplay.ttf@c8948f464ff822a5f9bbf2e12d0e4e32268815aa:--font-ptem 9 --font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[gid282=0@65,0+1185|gid658=1@-70,0+1044|gid3=2@65,0+550|gid4=3@65,0+1357|gid332=4+1357|gid3=5@65,0+550|gid282=6@65,0+1205|gid813=7@-50,0+646|gid3=8@65,0+550|gid332=9@65,0+1347|gid572=10@-10,0+1083|gid3=11@65,0+550|gid813=12@65,0+676|gid282=13@-20,0+1235|gid3=14@65,0+550|gid658=15@65,0+1044|gid282=16@-70,0+1185|gid3=17@65,0+550|gid282=18@65,0+1185|gid649=19@-70,0+1129]
 /System/Library/Fonts/Apple Color Emoji.ttc@2e09b1f3d42c3821cc6c4ac5b6ce16237ab0d496:--remove-default-ignorables --font-funcs ot:U+1F468,U+200D,U+1F469,U+200D,U+1F467,U+200D,U+1F466:[u1F46A.MWGB=0+800]
 /Library/Fonts/Zapfino.ttf@99a1e15163c3e9567d5b1019c45e9254dae63b08:--font-funcs ot:U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+006F:[Z=0+416|a=1@-21,0+264|p_f=2+433|i=4+181|n=5+261|Z=6+416|a=7@-21,0+264|p_f=8+433|i=10+181|n=11+261|Z=12+416|a=13@-21,0+264|p_f=14+433|i=16+181|n=17+261|Z=18+416|a=19@-21,0+264|p_f=20+433|i=22+181|n=23+261|Z=24+416|a=25@-21,0+264|p_f=26+433|i=28+181|n=29+261|Z=30+416|a=31@-21,0+264|p_f=32+433|i=34+181|n=35+261|Z=36+416|a=37@-21,0+264|p_f=38+433|i=40+181|n=41+261|Z=42+416|a=43@-21,0+264|p_f=44+433|i=46+181|n=47+261|Z=48+416|a=49@-21,0+264|p_f=50+433|i=52+181|n=53+261|Z=54+416|a=55@-21,0+264|p_f=56+433|i=58+181|n=59+261|Z=60+416|a=61@-21,0+264|p_f=62+433|i=64+181|n=65+261|Z_a_p_f_i_n_o=66+2333]
 
@@ -51,6 +51,6 @@
 /System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334:--font-funcs ot:U+0631,U+0628:[u0628.beh=1+1415|u0631.reh=0@-202,0+700]
 /System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334:--font-funcs ot:U+0628,U+064F:[u064f.damma=0@250,-250+250|u0628.beh=0@-250,0+1165]
 /System/Library/Fonts/SFNSDisplay.ttf@6e9677c443f6583228a63fd147663cfc635924d9:--font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[gid283=0+1055|gid659=1@-135,0+914|gid3=2+420|gid4=3+1227|gid333=4@-65,0+1227|gid3=5+420|gid283=6+1075|gid815=7@-115,0+516|gid3=8+420|gid333=9+1217|gid573=10@-75,0+953|gid3=11+420|gid815=12+546|gid283=13@-85,0+1105|gid3=14+420|gid659=15+914|gid283=16@-135,0+1055|gid3=17+420|gid283=18+1055|gid650=19@-135,0+999]
-/System/Library/Fonts/SFNSDisplay.ttf@6e9677c443f6583228a63fd147663cfc635924d9:--font-ptem 9 --font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[gid283=0@46,0+1147|gid659=1@-89,0+1006|gid3=2@46,0+512|gid4=3@46,0+1319|gid333=4@-19,0+1319|gid3=5@46,0+512|gid283=6@46,0+1167|gid815=7@-69,0+608|gid3=8@46,0+512|gid333=9@46,0+1309|gid573=10@-29,0+1045|gid3=11@46,0+512|gid815=12@46,0+638|gid283=13@-39,0+1197|gid3=14@46,0+512|gid659=15@46,0+1006|gid283=16@-89,0+1147|gid3=17@46,0+512|gid283=18@46,0+1147|gid650=19@-89,0+1091]
+/System/Library/Fonts/SFNSDisplay.ttf@6e9677c443f6583228a63fd147663cfc635924d9:--font-ptem 9 --font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[gid283=0@65,0+1185|gid659=1@-70,0+1044|gid3=2@65,0+550|gid4=3@65,0+1357|gid333=4+1357|gid3=5@65,0+550|gid283=6@65,0+1205|gid815=7@-50,0+646|gid3=8@65,0+550|gid333=9@65,0+1347|gid573=10@-10,0+1083|gid3=11@65,0+550|gid815=12@65,0+676|gid283=13@-20,0+1235|gid3=14@65,0+550|gid659=15@65,0+1044|gid283=16@-70,0+1185|gid3=17@65,0+550|gid283=18@65,0+1185|gid650=19@-70,0+1129]
 /System/Library/Fonts/Apple Color Emoji.ttc@60f77161021b1b87e99c3690e1a9b56341cf8792:--remove-default-ignorables --font-funcs ot:U+1F468,U+200D,U+1F469,U+200D,U+1F467,U+200D,U+1F466:[u1F46A.MWGB=0+800]
 /Library/Fonts/Zapfino.ttf@99a1e15163c3e9567d5b1019c45e9254dae63b08:--font-funcs ot:U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+006F:[Z=0+416|a=1@-21,0+264|p_f=2+433|i=4+181|n=5+261|Z=6+416|a=7@-21,0+264|p_f=8+433|i=10+181|n=11+261|Z=12+416|a=13@-21,0+264|p_f=14+433|i=16+181|n=17+261|Z=18+416|a=19@-21,0+264|p_f=20+433|i=22+181|n=23+261|Z=24+416|a=25@-21,0+264|p_f=26+433|i=28+181|n=29+261|Z=30+416|a=31@-21,0+264|p_f=32+433|i=34+181|n=35+261|Z=36+416|a=37@-21,0+264|p_f=38+433|i=40+181|n=41+261|Z=42+416|a=43@-21,0+264|p_f=44+433|i=46+181|n=47+261|Z=48+416|a=49@-21,0+264|p_f=50+433|i=52+181|n=53+261|Z=54+416|a=55@-21,0+264|p_f=56+433|i=58+181|n=59+261|Z=60+416|a=61@-21,0+264|p_f=62+433|i=64+181|n=65+261|Z_a_p_f_i_n_o=66+2333]
diff --git a/test/shaping/data/in-house/tests/positioning-features.tests b/test/shaping/data/in-house/tests/positioning-features.tests
new file mode 100644
index 0000000..8cab9d8
--- /dev/null
+++ b/test/shaping/data/in-house/tests/positioning-features.tests
@@ -0,0 +1,3 @@
+../fonts/53a91c20e33a596f2be17fb68b382d6b7eb85d5c.ttf::U+0041,U+0056:[A=0+625|V=1+675]
+../fonts/f79eb71df4e4c9c273b67b89a06e5ff9e3c1f834.ttf::U+006D,U+0315:[m=0+945|uni0315=0@32,-178+0]
+../fonts/ea3f63620511b2097200d23774ffef197e829e69.ttf::U+0079,U+0325:[y=0+565|uni0325=0@-422,-240+0]
diff --git a/test/subset/data/Makefile.am b/test/subset/data/Makefile.am
index 618e663..1e90367 100644
--- a/test/subset/data/Makefile.am
+++ b/test/subset/data/Makefile.am
@@ -13,6 +13,7 @@
 	expected/japanese \
 	expected/cff-japanese \
 	expected/layout \
+	expected/layout.gpos \
 	fonts \
 	profiles \
 	$(NULL)
diff --git a/test/subset/data/Makefile.sources b/test/subset/data/Makefile.sources
index f065e83..8bacc51 100644
--- a/test/subset/data/Makefile.sources
+++ b/test/subset/data/Makefile.sources
@@ -5,6 +5,7 @@
 	tests/japanese.tests \
 	tests/cff-japanese.tests \
 	tests/layout.tests \
+	tests/layout.gpos.tests \
 	$(NULL)
 
 XFAIL_TESTS = \
diff --git a/test/subset/data/expected/layout.gpos/gpos1_2_font.keep-layout-retain-gids.41,43.otf b/test/subset/data/expected/layout.gpos/gpos1_2_font.keep-layout-retain-gids.41,43.otf
new file mode 100644
index 0000000..6b2879f
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos/gpos1_2_font.keep-layout-retain-gids.41,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos/gpos1_2_font.keep-layout-retain-gids.41,46.otf b/test/subset/data/expected/layout.gpos/gpos1_2_font.keep-layout-retain-gids.41,46.otf
new file mode 100644
index 0000000..eebb3e1
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos/gpos1_2_font.keep-layout-retain-gids.41,46.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos/gpos1_2_font.keep-layout-retain-gids.43,46.otf b/test/subset/data/expected/layout.gpos/gpos1_2_font.keep-layout-retain-gids.43,46.otf
new file mode 100644
index 0000000..c271bde
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos/gpos1_2_font.keep-layout-retain-gids.43,46.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos/gpos1_2_font.keep-layout-retain-gids.retain-all-codepoint.otf b/test/subset/data/expected/layout.gpos/gpos1_2_font.keep-layout-retain-gids.retain-all-codepoint.otf
new file mode 100644
index 0000000..2d6962b
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos/gpos1_2_font.keep-layout-retain-gids.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/fonts/gpos1_2_font.otf b/test/subset/data/fonts/gpos1_2_font.otf
new file mode 100644
index 0000000..28331f2
--- /dev/null
+++ b/test/subset/data/fonts/gpos1_2_font.otf
Binary files differ
diff --git a/test/subset/data/tests/layout.gpos.tests b/test/subset/data/tests/layout.gpos.tests
new file mode 100644
index 0000000..2d0f936
--- /dev/null
+++ b/test/subset/data/tests/layout.gpos.tests
@@ -0,0 +1,11 @@
+FONTS:
+gpos1_2_font.otf
+
+PROFILES:
+keep-layout-retain-gids.txt
+
+SUBSETS:
+AC
+CF
+AF
+*
diff --git a/util/ansi-print.cc b/util/ansi-print.cc
index 49a0477..58df0a6 100644
--- a/util/ansi-print.cc
+++ b/util/ansi-print.cc
@@ -133,7 +133,7 @@
 	for (unsigned int col = 0; col < w; col++)
 	  *q++ = *p++;
       else {
-        unsigned int limit = width - x;
+	unsigned int limit = width - x;
 	for (unsigned int col = 0; col < limit; col++)
 	  *q++ = *p++;
 	p--;
@@ -171,17 +171,17 @@
     int freq[8] = {0};
     for (unsigned int y = 0; y < height; y++)
       for (unsigned int x = 0; x < width; x++) {
-        color_t c = image (x, y);
-        freq[c.to_ansi ()]++;
+	color_t c = image (x, y);
+	freq[c.to_ansi ()]++;
       }
     bg = 0;
     for (unsigned int i = 1; i < 8; i++)
       if (freq[bg] < freq[i])
-        bg = i;
+	bg = i;
     fg = 0;
     for (unsigned int i = 1; i < 8; i++)
       if (i != bg && freq[fg] < freq[i])
-        fg = i;
+	fg = i;
     if (fg == bg || freq[fg] == 0) {
       fg = bg;
       unicolor = true;
@@ -202,7 +202,7 @@
     int dd = diff.dot (diff);
     for (unsigned int y = 0; y < height; y++)
       for (unsigned int x = 0; x < width; x++) {
-        int d = diff.dot (image (x, y).diff (bgc));
+	int d = diff.dot (image (x, y).diff (bgc));
 	(*this)(x, y) = d < 0 ? 0 : d > dd ? 255 : lround (d * 255. / dd);
       }
   }
@@ -287,13 +287,13 @@
       unsigned int s;
       s = row_sum[i] + total_i - row_sum_i[i];
       if (s < best_s) {
-        best_s = s;
+	best_s = s;
 	best_i = i;
 	best_inv = false;
       }
       s = row_sum_i[i] + total - row_sum[i];
       if (s < best_s) {
-        best_s = s;
+	best_s = s;
 	best_i = i;
 	best_inv = true;
       }
@@ -319,13 +319,13 @@
       unsigned int s;
       s = col_sum[i] + total_i - col_sum_i[i];
       if (s < best_s) {
-        best_s = s;
+	best_s = s;
 	best_i = i;
 	best_inv = true;
       }
       s = col_sum_i[i] + total - col_sum[i];
       if (s < best_s) {
-        best_s = s;
+	best_s = s;
 	best_i = i;
 	best_inv = false;
       }
@@ -396,15 +396,15 @@
       image.copy_sub_image (cell, col * CELL_W, row * CELL_H, CELL_W, CELL_H);
       bi.set (cell);
       if (bi.unicolor) {
-        if (last_bg != bi.bg) {
+	if (last_bg != bi.bg) {
 	  printf ("%c[%dm", ESC_E, 40 + bi.bg);
 	  last_bg = bi.bg;
 	}
 	printf (" ");
       } else {
-        /* Figure out the closest character to the biimage */
+	/* Figure out the closest character to the biimage */
 	bool inverse = false;
-        const char *c = block_best (bi, &inverse);
+	const char *c = block_best (bi, &inverse);
 	if (inverse) {
 	  if (last_bg != bi.fg || last_fg != bi.bg) {
 	    printf ("%c[%d;%dm", ESC_E, 30 + bi.bg, 40 + bi.fg);
diff --git a/util/hb-fc-list.c b/util/hb-fc-list.c
index 573d11e..39cbb4b 100644
--- a/util/hb-fc-list.c
+++ b/util/hb-fc-list.c
@@ -171,7 +171,7 @@
 	os = FcObjectSetBuild (FC_FAMILY, FC_STYLE, FC_FILE, (char *) 0);
     FcObjectSetAdd (os, FC_CHARSET);
     if (!format)
-        format = (const FcChar8 *) "%{=fclist}\n";
+	format = (const FcChar8 *) "%{=fclist}\n";
     fs = FcFontList (0, pat, os);
     if (os)
 	FcObjectSetDestroy (os);
diff --git a/util/hb-fc.cc b/util/hb-fc.cc
index 2fe0146..9042346 100644
--- a/util/hb-fc.cc
+++ b/util/hb-fc.cc
@@ -55,9 +55,9 @@
     {
       unsigned int var_num = 0;
       if (variation_selector - 0xFE00u < 16)
-        var_num = variation_selector - 0xFE00 + 1;
+	var_num = variation_selector - 0xFE00 + 1;
       else if (variation_selector - 0xE0100u < (256 - 16))
-        var_num = variation_selector - 0xE0100 + 17;
+	var_num = variation_selector - 0xE0100 + 17;
       *glyph = (var_num << 21) | unicode;
     }
     else
diff --git a/util/hb-shape.cc b/util/hb-shape.cc
index 3ae3fa1..bab5cba 100644
--- a/util/hb-shape.cc
+++ b/util/hb-shape.cc
@@ -181,7 +181,7 @@
       fflush (stdout);
 
       if (ret)
-        break;
+	break;
     }
     return ret;
   }
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
index 6d87c56..008e4e6 100644
--- a/util/hb-subset.cc
+++ b/util/hb-subset.cc
@@ -40,16 +40,16 @@
       : failed (false), options (parser), subset_options (parser), font (nullptr), input (nullptr) {}
 
   void init (hb_buffer_t  *buffer_,
-             const font_options_t *font_opts)
+	     const font_options_t *font_opts)
   {
     font = hb_font_reference (font_opts->get_font ());
     input = hb_subset_input_reference (subset_options.input);
   }
 
   void consume_line (const char   *text,
-                     unsigned int  text_len,
-                     const char   *text_before,
-                     const char   *text_after)
+		     unsigned int  text_len,
+		     const char   *text_before,
+		     const char   *text_after)
   {
     // TODO(Q1) does this only get called with at least 1 codepoint?
     hb_set_t *codepoints = hb_subset_input_unicode_set (input);
@@ -88,7 +88,7 @@
     }
     if ((unsigned int) bytes_written != data_length) {
       fprintf(stderr, "Expected %u bytes written, got %d\n", data_length,
-              bytes_written);
+	      bytes_written);
       return false;
     }
     return true;
diff --git a/util/helper-cairo-ansi.cc b/util/helper-cairo-ansi.cc
index 50f9eb4..cbda493 100644
--- a/util/helper-cairo-ansi.cc
+++ b/util/helper-cairo-ansi.cc
@@ -71,7 +71,7 @@
     unsigned int i;
     for (i = 0; i < width; i++)
       if (data[i] != bg_color)
-        break;
+	break;
     if (i < width)
       break;
     data += stride / 4;
@@ -86,7 +86,7 @@
     unsigned int i;
     for (i = 0; i < width; i++)
       if (row[i] != bg_color)
-        break;
+	break;
     if (i < width)
       break;
     height--;
diff --git a/util/helper-cairo.cc b/util/helper-cairo.cc
index b4f94a9..42cce71 100644
--- a/util/helper-cairo.cc
+++ b/util/helper-cairo.cc
@@ -97,7 +97,7 @@
 
     if (FT_New_Memory_Face (ft_library,
 			    (const FT_Byte *) blob_data,
-                            blob_length,
+			    blob_length,
 			    font_opts->face_index,
 			    &ft_face))
       fail (false, "FT_New_Memory_Face fail");
diff --git a/util/options-subset.cc b/util/options-subset.cc
index b2f4db0..35fa05e 100644
--- a/util/options-subset.cc
+++ b/util/options-subset.cc
@@ -30,9 +30,9 @@
 
 static gboolean
 parse_nameids (const char *name,
-               const char *arg,
-               gpointer    data,
-               GError    **error G_GNUC_UNUSED)
+	       const char *arg,
+	       gpointer    data,
+	       GError    **error G_GNUC_UNUSED)
 {
   subset_options_t *subset_opts = (subset_options_t *) data;
   hb_set_t *name_ids = subset_opts->input->name_ids;
@@ -46,7 +46,7 @@
   {
     if (last_name_char == '-')
       hb_set_del_range (name_ids, 0, 0x7FFF);
-    else 
+    else
       hb_set_add_range (name_ids, 0, 0x7FFF);
     return true;
   }
@@ -67,7 +67,7 @@
     {
       hb_set_destroy (name_ids);
       g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
-                   "Failed parsing nameID values at: '%s'", s);
+		   "Failed parsing nameID values at: '%s'", s);
       return false;
     }
 
@@ -86,9 +86,9 @@
 
 static gboolean
 parse_drop_tables (const char *name,
-                   const char *arg,
-                   gpointer    data,
-                   GError    **error G_GNUC_UNUSED)
+		   const char *arg,
+		   gpointer    data,
+		   GError    **error G_GNUC_UNUSED)
 {
   subset_options_t *subset_opts = (subset_options_t *) data;
   hb_set_t *drop_tables = subset_opts->input->drop_tables;
@@ -104,7 +104,7 @@
     if (strlen (s) > 4) // Table tags are at most 4 bytes.
     {
       g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
-                   "Failed parsing table tag values at: '%s'", s);
+		   "Failed parsing table tag values at: '%s'", s);
       return false;
     }
 
@@ -137,8 +137,8 @@
     {nullptr}
   };
   parser->add_group (entries,
-         "subset",
-         "Subset options:",
-         "Options subsetting",
-         this);
+	 "subset",
+	 "Subset options:",
+	 "Options subsetting",
+	 this);
 }
diff --git a/util/options.cc b/util/options.cc
index f71a5a3..43ff90a 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -196,8 +196,8 @@
     bool found = false;
     for (const char **hb_shaper = hb_shape_list_shapers (); *hb_shaper; hb_shaper++) {
       if (strcmp (*shaper, *hb_shaper) == 0) {
-        found = true;
-        break;
+	found = true;
+	break;
       }
     }
     if (!found) {
@@ -228,9 +228,9 @@
 
 static gboolean
 parse_features (const char *name G_GNUC_UNUSED,
-	        const char *arg,
-	        gpointer    data,
-	        GError    **error G_GNUC_UNUSED)
+		const char *arg,
+		gpointer    data,
+		GError    **error G_GNUC_UNUSED)
 {
   shape_options_t *shape_opts = (shape_options_t *) data;
   char *s = (char *) arg;
@@ -271,9 +271,9 @@
 
 static gboolean
 parse_variations (const char *name G_GNUC_UNUSED,
-	        const char *arg,
-	        gpointer    data,
-	        GError    **error 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;
@@ -335,9 +335,9 @@
 
 static gboolean
 parse_unicodes (const char *name G_GNUC_UNUSED,
-	        const char *arg,
-	        gpointer    data,
-	        GError    **error G_GNUC_UNUSED)
+		const char *arg,
+		gpointer    data,
+		GError    **error G_GNUC_UNUSED)
 {
   text_options_t *text_opts = (text_options_t *) data;
 
@@ -349,7 +349,7 @@
   }
 
   GString *gs = g_string_new (nullptr);
-  if (0 == strcmp (arg, "*")) 
+  if (0 == strcmp (arg, "*"))
   {
     g_string_append_c (gs, '*');
   }
@@ -358,26 +358,26 @@
 
     char *s = (char *) arg;
     char *p;
-  
+
     while (s && *s)
     {
       while (*s && strchr (DELIMITERS, *s))
-        s++;
+	s++;
       if (!*s)
-        break;
-  
+	break;
+
       errno = 0;
       hb_codepoint_t u = strtoul (s, &p, 16);
       if (errno || s == p)
       {
-        g_string_free (gs, TRUE);
-        g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+	g_string_free (gs, TRUE);
+	g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
   		   "Failed parsing Unicode values at: '%s'", s);
-        return false;
+	return false;
       }
-  
+
       g_string_append_unichar (gs, u);
-  
+
       s = p;
     }
   }
@@ -716,7 +716,7 @@
       GString *s = g_string_new (nullptr);
       for (unsigned int i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++)
       {
-        if (i)
+	if (i)
 	  g_string_append_c (s, '/');
 	g_string_append (s, supported_font_funcs[i].name);
       }
@@ -877,9 +877,9 @@
   parser->add_group (entries,
 		     "output-syntax",
 		     "Output syntax:\n"
-         "    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:",
+	 "    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",
 		     this);
 }
diff --git a/util/options.hh b/util/options.hh
index 63360ca..9e22b40 100644
--- a/util/options.hh
+++ b/util/options.hh
@@ -242,7 +242,7 @@
     if (!hb_shape_full (font, buffer, features, num_features, shapers))
     {
       if (error)
-        *error = "all shapers failed.";
+	*error = "all shapers failed.";
       goto fail;
     }
 
@@ -341,7 +341,7 @@
       /* Shape segment corresponding to glyphs start..end. */
       if (end == num_glyphs)
       {
-        if (forward)
+	if (forward)
 	  text_end = num_chars;
 	else
 	  text_start = 0;
@@ -372,9 +372,9 @@
       /* TODO: Add pre/post context text. */
       hb_buffer_flags_t flags = hb_buffer_get_flags (fragment);
       if (0 < text_start)
-        flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_BOT);
+	flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_BOT);
       if (text_end < num_chars)
-        flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_EOT);
+	flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_EOT);
       hb_buffer_set_flags (fragment, flags);
 
       hb_buffer_append (fragment, text_buffer, text_start, text_end);