Bug 1157758 - Update harfbuzz to pick up fix for vertical-upright Arabic script (non-)shaping behavior; now at upstream commit f724cc351640ee075a9867ef42df32cf5e0ef3b7. r=jdaggett
authorJonathan Kew <jkew@mozilla.com>
Mon, 11 May 2015 06:58:21 +0100
changeset 243332 e2aabff6bd77fb01564d47d139010e56bb0ae326
parent 243331 3cd634573d29d195bae4718bc4c6aba1032a1f7b
child 243333 876a0813cdc5b3567a3426594e4b1d44d595fabd
push id28738
push usercbook@mozilla.com
push dateTue, 12 May 2015 14:11:31 +0000
treeherdermozilla-central@bedce1b405a3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdaggett
bugs1157758
milestone40.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1157758 - Update harfbuzz to pick up fix for vertical-upright Arabic script (non-)shaping behavior; now at upstream commit f724cc351640ee075a9867ef42df32cf5e0ef3b7. r=jdaggett
gfx/harfbuzz/README-mozilla
gfx/harfbuzz/src/Makefile.am
gfx/harfbuzz/src/check-defs.sh
gfx/harfbuzz/src/check-libstdc++.sh
gfx/harfbuzz/src/gen-indic-table.py
gfx/harfbuzz/src/hb-atomic-private.hh
gfx/harfbuzz/src/hb-blob.cc
gfx/harfbuzz/src/hb-buffer-deserialize-json.hh
gfx/harfbuzz/src/hb-buffer-deserialize-text.hh
gfx/harfbuzz/src/hb-buffer-deserialize-text.rl
gfx/harfbuzz/src/hb-buffer.cc
gfx/harfbuzz/src/hb-buffer.h
gfx/harfbuzz/src/hb-common.cc
gfx/harfbuzz/src/hb-coretext.cc
gfx/harfbuzz/src/hb-face.cc
gfx/harfbuzz/src/hb-font.cc
gfx/harfbuzz/src/hb-ft.cc
gfx/harfbuzz/src/hb-ft.h
gfx/harfbuzz/src/hb-glib.cc
gfx/harfbuzz/src/hb-glib.h
gfx/harfbuzz/src/hb-icu.cc
gfx/harfbuzz/src/hb-mutex-private.hh
gfx/harfbuzz/src/hb-object-private.hh
gfx/harfbuzz/src/hb-open-file-private.hh
gfx/harfbuzz/src/hb-open-type-private.hh
gfx/harfbuzz/src/hb-ot-cmap-table.hh
gfx/harfbuzz/src/hb-ot-font.cc
gfx/harfbuzz/src/hb-ot-head-table.hh
gfx/harfbuzz/src/hb-ot-hhea-table.hh
gfx/harfbuzz/src/hb-ot-hmtx-table.hh
gfx/harfbuzz/src/hb-ot-layout-common-private.hh
gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh
gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh
gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh
gfx/harfbuzz/src/hb-ot-layout-jstf-table.hh
gfx/harfbuzz/src/hb-ot-layout-private.hh
gfx/harfbuzz/src/hb-ot-layout.cc
gfx/harfbuzz/src/hb-ot-maxp-table.hh
gfx/harfbuzz/src/hb-ot-name-table.hh
gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh
gfx/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh
gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
gfx/harfbuzz/src/hb-ot-shape-complex-private.hh
gfx/harfbuzz/src/hb-ot-shape-complex-sea-machine.hh
gfx/harfbuzz/src/hb-ot-shape-fallback.cc
gfx/harfbuzz/src/hb-ot-shape-normalize.cc
gfx/harfbuzz/src/hb-ot-shape.cc
gfx/harfbuzz/src/hb-private.hh
gfx/harfbuzz/src/hb-set-private.hh
gfx/harfbuzz/src/hb-shape-plan.cc
gfx/harfbuzz/src/hb-shape.cc
gfx/harfbuzz/src/hb-shaper-private.hh
gfx/harfbuzz/src/hb-shaper.cc
gfx/harfbuzz/src/hb-unicode.cc
gfx/harfbuzz/src/hb-utf-private.hh
gfx/harfbuzz/src/hb-version.h
gfx/harfbuzz/src/hb-warning.cc
gfx/harfbuzz/src/sample.py
--- a/gfx/harfbuzz/README-mozilla
+++ b/gfx/harfbuzz/README-mozilla
@@ -1,23 +1,20 @@
-gfx/harfbuzz status as of 2012-08-16:
+gfx/harfbuzz status as of 2015-04-25:
 
-This directory contains the "harfbuzz-ng" source from the 'master' branch of
-git://anongit.freedesktop.org/git/harfbuzz.
+This directory contains the harfbuzz source from the 'master' branch of
+https://github.com/behdad/harfbuzz.
 
 UPDATING:
 
-Note that hb-ot-shape-complex-indic-machine.hh and gfx/harfbuzz/src/hb-version.h
-are not present in the upstream Git repository. These are created at build time
-by the harfbuzz build system; but as we don't use that build system in mozilla,
-it is necessary to refresh these files when updating harfbuzz, and check them in
-to the mozilla tree. (This avoids adding the ragel processor to mozilla's build
-prerequisites.)
+Note that gfx/harfbuzz/src/hb-version.h is not present in the upstream Git
+repository. It is created at build time by the harfbuzz build system;
+but as we don't use that build system in mozilla, it is necessary to refresh
+this files when updating harfbuzz, and check them into the mozilla tree.
 
 The normal approach to updating harfbuzz, therefore, is to pull the latest HB
 source into a scratch directory and do a local build; then copy the original
 sources AND the generated headers mentioned above from the build directory into
 the mozilla tree.
 
 In addition, the src/Makefile.in file here is NOT from upstream, nor is it
 generated from src/Makefile.am (the original harfbuzz version); it is a mozilla-
-specific makefile that is maintained by hand. It should only need updating when
-new source files or exported headers are added in harfbuzz.
+specific makefile that is maintained by hand.
--- a/gfx/harfbuzz/src/Makefile.am
+++ b/gfx/harfbuzz/src/Makefile.am
@@ -8,16 +8,19 @@ EXTRA_DIST =
 CLEANFILES =
 DISTCLEANFILES =
 MAINTAINERCLEANFILES =
 DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
 
 # The following warning options are useful for debugging: -Wpadded
 #AM_CXXFLAGS =
 
+# Convenience targets:
+lib: libharfbuzz.la
+
 lib_LTLIBRARIES = libharfbuzz.la
 
 HBCFLAGS =
 HBLIBS =
 HBSOURCES =  \
 	hb-atomic-private.hh \
 	hb-blob.cc \
 	hb-buffer-deserialize-json.hh \
new file mode 100755
--- /dev/null
+++ b/gfx/harfbuzz/src/check-defs.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+LC_ALL=C
+export LC_ALL
+
+test -z "$srcdir" && srcdir=.
+test -z "$MAKE" && MAKE=make
+stat=0
+
+if which nm 2>/dev/null >/dev/null; then
+	:
+else
+	echo "check-defs.sh: 'nm' not found; skipping test"
+	exit 77
+fi
+
+defs="harfbuzz.def"
+$MAKE $defs > /dev/null
+tested=false
+for def in $defs; do
+	lib=`echo "$def" | sed 's/[.]def$//;s@.*/@@'`
+	so=.libs/lib${lib}.so
+
+	EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>\| __gcov_flush\>\| llvm_' | cut -d' ' -f3`"
+
+	if test -f "$so"; then
+
+		echo "Checking that $so has the same symbol list as $def"
+		{
+			echo EXPORTS
+			echo "$EXPORTED_SYMBOLS"
+			# cheat: copy the last line from the def file!
+			tail -n1 "$def"
+		} | diff "$def" - >&2 || stat=1
+
+		tested=true
+	fi
+done
+if ! $tested; then
+	echo "check-defs.sh: libharfbuzz shared library not found; skipping test"
+	exit 77
+fi
+
+exit $stat
--- a/gfx/harfbuzz/src/check-libstdc++.sh
+++ b/gfx/harfbuzz/src/check-libstdc++.sh
@@ -14,19 +14,19 @@ else
 	exit 77
 fi
 
 tested=false
 for suffix in so dylib; do
 	so=.libs/libharfbuzz.$suffix
 	if ! test -f "$so"; then continue; fi
 
-	echo "Checking that we are not linking to libstdc++"
-	if ldd $so | grep 'libstdc[+][+]'; then
-		echo "Ouch, linked to libstdc++"
+	echo "Checking that we are not linking to libstdc++ or libc++"
+	if ldd $so | grep 'libstdc[+][+]\|libc[+][+]'; then
+		echo "Ouch, linked to libstdc++ or libc++"
 		stat=1
 	fi
 	tested=true
 done
 if ! $tested; then
 	echo "check-libstdc++.sh: libharfbuzz shared library not found; skipping test"
 	exit 77
 fi
--- a/gfx/harfbuzz/src/gen-indic-table.py
+++ b/gfx/harfbuzz/src/gen-indic-table.py
@@ -204,17 +204,17 @@ print "{"
 print "  switch (u >> %d)" % page_bits
 print "  {"
 pages = set([u>>page_bits for u in starts+ends+singles.keys()])
 for p in sorted(pages):
 	print "    case 0x%0Xu:" % p
 	for (start,end) in zip (starts, ends):
 		if p not in [start>>page_bits, end>>page_bits]: continue
 		offset = "indic_offset_0x%04xu" % start
-		print "      if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return indic_table[u - 0x%04Xu + %s];" % (start, end, start, offset)
+		print "      if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return indic_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset)
 	for u,d in singles.items ():
 		if p != u>>page_bits: continue
 		print "      if (unlikely (u == 0x%04Xu)) return _(%s,%s);" % (u, short[0][d[0]], short[1][d[1]])
 	print "      break;"
 	print ""
 print "    default:"
 print "      break;"
 print "  }"
--- a/gfx/harfbuzz/src/hb-atomic-private.hh
+++ b/gfx/harfbuzz/src/hb-atomic-private.hh
@@ -34,17 +34,21 @@
 
 #include "hb-private.hh"
 
 
 /* atomic_int */
 
 /* We need external help for these */
 
-#if 0
+#if defined(hb_atomic_int_impl_add) \
+ && defined(hb_atomic_ptr_impl_get) \
+ && defined(hb_atomic_ptr_impl_cmpexch)
+
+/* Defined externally, i.e. in config.h; must have typedef'ed hb_atomic_int_impl_t as well. */
 
 
 #elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
 
 #include <windows.h>
 
 /* MinGW has a convoluted history of supporting MemoryBarrier
  * properly.  As such, define a function to wrap the whole
@@ -53,83 +57,108 @@ static inline void _HBMemoryBarrier (voi
 #if !defined(MemoryBarrier)
   long dummy = 0;
   InterlockedExchange (&dummy, 1);
 #else
   MemoryBarrier ();
 #endif
 }
 
-typedef LONG hb_atomic_int_t;
-#define hb_atomic_int_add(AI, V)	InterlockedExchangeAdd (&(AI), (V))
+typedef LONG hb_atomic_int_impl_t;
+#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
+#define hb_atomic_int_impl_add(AI, V)		InterlockedExchangeAdd (&(AI), (V))
 
-#define hb_atomic_ptr_get(P)		(_HBMemoryBarrier (), (void *) *(P))
-#define hb_atomic_ptr_cmpexch(P,O,N)	(InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O))
+#define hb_atomic_ptr_impl_get(P)		(_HBMemoryBarrier (), (void *) *(P))
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)	(InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O))
 
 
 #elif !defined(HB_NO_MT) && defined(__APPLE__)
 
 #include <libkern/OSAtomic.h>
 #ifdef __MAC_OS_X_MIN_REQUIRED
 #include <AvailabilityMacros.h>
 #elif defined(__IPHONE_OS_MIN_REQUIRED)
 #include <Availability.h>
 #endif
 
-typedef int32_t hb_atomic_int_t;
-#define hb_atomic_int_add(AI, V)	(OSAtomicAdd32Barrier ((V), &(AI)) - (V))
 
-#define hb_atomic_ptr_get(P)		(OSMemoryBarrier (), (void *) *(P))
+typedef int32_t hb_atomic_int_impl_t;
+#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
+#define hb_atomic_int_impl_add(AI, V)		(OSAtomicAdd32Barrier ((V), &(AI)) - (V))
+
+#define hb_atomic_ptr_impl_get(P)		(OSMemoryBarrier (), (void *) *(P))
 #if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
-#define hb_atomic_ptr_cmpexch(P,O,N)	OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P))
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)	OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P))
 #else
 #if __ppc64__ || __x86_64__ || __aarch64__
-#define hb_atomic_ptr_cmpexch(P,O,N)    OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P))
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)	OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P))
 #else
-#define hb_atomic_ptr_cmpexch(P,O,N)    OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P))
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)	OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P))
 #endif
 #endif
 
 
 #elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
 
-typedef int hb_atomic_int_t;
-#define hb_atomic_int_add(AI, V)	__sync_fetch_and_add (&(AI), (V))
+typedef int hb_atomic_int_impl_t;
+#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
+#define hb_atomic_int_impl_add(AI, V)		__sync_fetch_and_add (&(AI), (V))
 
-#define hb_atomic_ptr_get(P)		(void *) (__sync_synchronize (), *(P))
-#define hb_atomic_ptr_cmpexch(P,O,N)	__sync_bool_compare_and_swap ((P), (O), (N))
+#define hb_atomic_ptr_impl_get(P)		(void *) (__sync_synchronize (), *(P))
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)	__sync_bool_compare_and_swap ((P), (O), (N))
 
 
 #elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS)
 
 #include <atomic.h>
 #include <mbarrier.h>
 
-typedef unsigned int hb_atomic_int_t;
-#define hb_atomic_int_add(AI, V)	( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V))
+typedef unsigned int hb_atomic_int_impl_t;
+#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
+#define hb_atomic_int_impl_add(AI, V)		( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V))
 
-#define hb_atomic_ptr_get(P)		( ({__machine_rw_barrier ();}), (void *) *(P))
-#define hb_atomic_ptr_cmpexch(P,O,N)	( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false)
+#define hb_atomic_ptr_impl_get(P)		( ({__machine_rw_barrier ();}), (void *) *(P))
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)	( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false)
 
 
 #elif !defined(HB_NO_MT)
 
 #define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
-typedef volatile int hb_atomic_int_t;
-#define hb_atomic_int_add(AI, V)	(((AI) += (V)) - (V))
 
-#define hb_atomic_ptr_get(P)		((void *) *(P))
-#define hb_atomic_ptr_cmpexch(P,O,N)	(* (void * volatile *) (P) == (void *) (O) ? (* (void * volatile *) (P) = (void *) (N), true) : false)
+typedef volatile int hb_atomic_int_impl_t;
+#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
+#define hb_atomic_int_impl_add(AI, V)		(((AI) += (V)) - (V))
+
+#define hb_atomic_ptr_impl_get(P)		((void *) *(P))
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)	(* (void * volatile *) (P) == (void *) (O) ? (* (void * volatile *) (P) = (void *) (N), true) : false)
 
 
 #else /* HB_NO_MT */
 
-typedef int hb_atomic_int_t;
-#define hb_atomic_int_add(AI, V)	(((AI) += (V)) - (V))
+typedef int hb_atomic_int_impl_t;
+#define HB_ATOMIC_INT_IMPL_INIT(V)		(V)
+#define hb_atomic_int_impl_add(AI, V)		(((AI) += (V)) - (V))
 
-#define hb_atomic_ptr_get(P)		((void *) *(P))
-#define hb_atomic_ptr_cmpexch(P,O,N)	(* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
+#define hb_atomic_ptr_impl_get(P)		((void *) *(P))
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)	(* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
+
 
 #endif
 
-/* TODO Add tracing. */
+
+#define HB_ATOMIC_INT_INIT(V)		{HB_ATOMIC_INT_IMPL_INIT(V)}
+
+struct hb_atomic_int_t
+{
+  hb_atomic_int_impl_t v;
+
+  inline void set_unsafe (int v_) { v = v_; }
+  inline int get_unsafe (void) const { return v; }
+  inline int inc (void) { return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v),  1); }
+  inline int dec (void) { return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v), -1); }
+};
+
+
+#define hb_atomic_ptr_get(P) hb_atomic_ptr_impl_get(P)
+#define hb_atomic_ptr_cmpexch(P,O,N) hb_atomic_ptr_impl_cmpexch((P),(O),(N))
+
 
 #endif /* HB_ATOMIC_PRIVATE_HH */
--- a/gfx/harfbuzz/src/hb-blob.cc
+++ b/gfx/harfbuzz/src/hb-blob.cc
@@ -73,18 +73,18 @@ static void
   if (blob->destroy) {
     blob->destroy (blob->user_data);
     blob->user_data = NULL;
     blob->destroy = NULL;
   }
 }
 
 /**
- * hb_blob_create: (Xconstructor)
- * @data: (array length=length) (closure user_data) (destroy destroy) (scope notified) (transfer none): Pointer to blob data.
+ * hb_blob_create: (skip)
+ * @data: Pointer to blob data.
  * @length: Length of @data in bytes.
  * @mode: Memory mode for @data.
  * @user_data: Data parameter to pass to @destroy.
  * @destroy: Callback to call when @data is not needed anymore.
  *
  * Creates a new "blob" object wrapping @data.  The @mode parameter is used
  * to negotiate ownership and lifecycle of @data.
  *
--- a/gfx/harfbuzz/src/hb-buffer-deserialize-json.hh
+++ b/gfx/harfbuzz/src/hb-buffer-deserialize-json.hh
@@ -1,10 +1,10 @@
 
-#line 1 "../../src/hb-buffer-deserialize-json.rl"
+#line 1 "hb-buffer-deserialize-json.rl"
 /*
  * Copyright © 2013  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
  * Permission is hereby granted, without written agreement and without
  * license or royalty fees, to use, copy, modify, and distribute this
  * software and its documentation for any purpose, provided that the
@@ -27,17 +27,17 @@
  */
 
 #ifndef HB_BUFFER_DESERIALIZE_JSON_HH
 #define HB_BUFFER_DESERIALIZE_JSON_HH
 
 #include "hb-private.hh"
 
 
-#line 36 "hb-buffer-deserialize-json.hh.tmp"
+#line 36 "hb-buffer-deserialize-json.hh"
 static const unsigned char _deserialize_json_trans_keys[] = {
 	0u, 0u, 9u, 123u, 9u, 34u, 97u, 103u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 
 	48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 
 	9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u, 
 	120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 
 	9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 
 	65u, 122u, 34u, 122u, 9u, 125u, 9u, 125u, 9u, 93u, 9u, 123u, 0u, 0u, 0
 };
@@ -430,17 +430,17 @@ static const char _deserialize_json_tran
 
 static const int deserialize_json_start = 1;
 static const int deserialize_json_first_final = 44;
 static const int deserialize_json_error = 0;
 
 static const int deserialize_json_en_main = 1;
 
 
-#line 97 "../../src/hb-buffer-deserialize-json.rl"
+#line 97 "hb-buffer-deserialize-json.rl"
 
 
 static hb_bool_t
 _hb_buffer_deserialize_glyphs_json (hb_buffer_t *buffer,
 				    const char *buf,
 				    unsigned int buf_len,
 				    const char **end_ptr,
 				    hb_font_t *font)
@@ -454,25 +454,25 @@ static hb_bool_t
     p++;
   if (p < pe && *p == (buffer->len ? ',' : '['))
   {
     *end_ptr = ++p;
   }
 
   const char *tok = NULL;
   int cs;
-  hb_glyph_info_t info;
-  hb_glyph_position_t pos;
+  hb_glyph_info_t info = {0};
+  hb_glyph_position_t pos = {0};
   
-#line 466 "hb-buffer-deserialize-json.hh.tmp"
+#line 466 "hb-buffer-deserialize-json.hh"
 	{
 	cs = deserialize_json_start;
 	}
 
-#line 471 "hb-buffer-deserialize-json.hh.tmp"
+#line 471 "hb-buffer-deserialize-json.hh"
 	{
 	int _slen;
 	int _trans;
 	const unsigned char *_keys;
 	const char *_inds;
 	if ( p == pe )
 		goto _test_eof;
 	if ( cs == 0 )
@@ -488,156 +488,156 @@ static hb_bool_t
 
 	cs = _deserialize_json_trans_targs[_trans];
 
 	if ( _deserialize_json_trans_actions[_trans] == 0 )
 		goto _again;
 
 	switch ( _deserialize_json_trans_actions[_trans] ) {
 	case 1:
-#line 38 "../../src/hb-buffer-deserialize-json.rl"
+#line 38 "hb-buffer-deserialize-json.rl"
 	{
 	memset (&info, 0, sizeof (info));
 	memset (&pos , 0, sizeof (pos ));
 }
 	break;
 	case 5:
-#line 43 "../../src/hb-buffer-deserialize-json.rl"
+#line 43 "hb-buffer-deserialize-json.rl"
 	{
 	buffer->add_info (info);
 	if (buffer->in_error)
 	  return false;
 	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 }
 	break;
 	case 2:
-#line 51 "../../src/hb-buffer-deserialize-json.rl"
+#line 51 "hb-buffer-deserialize-json.rl"
 	{
 	tok = p;
 }
 	break;
 	case 14:
-#line 55 "../../src/hb-buffer-deserialize-json.rl"
+#line 55 "hb-buffer-deserialize-json.rl"
 	{
 	if (!hb_font_glyph_from_string (font,
 					tok, p - tok,
 					&info.codepoint))
 	  return false;
 }
 	break;
 	case 15:
-#line 62 "../../src/hb-buffer-deserialize-json.rl"
+#line 62 "hb-buffer-deserialize-json.rl"
 	{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
 	break;
 	case 8:
-#line 63 "../../src/hb-buffer-deserialize-json.rl"
+#line 63 "hb-buffer-deserialize-json.rl"
 	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
 	break;
 	case 10:
-#line 64 "../../src/hb-buffer-deserialize-json.rl"
+#line 64 "hb-buffer-deserialize-json.rl"
 	{ if (!parse_int  (tok, p, &pos.x_offset )) return false; }
 	break;
 	case 12:
-#line 65 "../../src/hb-buffer-deserialize-json.rl"
+#line 65 "hb-buffer-deserialize-json.rl"
 	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
 	break;
 	case 3:
-#line 66 "../../src/hb-buffer-deserialize-json.rl"
+#line 66 "hb-buffer-deserialize-json.rl"
 	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
 	break;
 	case 6:
-#line 67 "../../src/hb-buffer-deserialize-json.rl"
+#line 67 "hb-buffer-deserialize-json.rl"
 	{ if (!parse_int  (tok, p, &pos.y_advance)) return false; }
 	break;
 	case 16:
-#line 62 "../../src/hb-buffer-deserialize-json.rl"
+#line 62 "hb-buffer-deserialize-json.rl"
 	{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
-#line 43 "../../src/hb-buffer-deserialize-json.rl"
+#line 43 "hb-buffer-deserialize-json.rl"
 	{
 	buffer->add_info (info);
 	if (buffer->in_error)
 	  return false;
 	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 }
 	break;
 	case 9:
-#line 63 "../../src/hb-buffer-deserialize-json.rl"
+#line 63 "hb-buffer-deserialize-json.rl"
 	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
-#line 43 "../../src/hb-buffer-deserialize-json.rl"
+#line 43 "hb-buffer-deserialize-json.rl"
 	{
 	buffer->add_info (info);
 	if (buffer->in_error)
 	  return false;
 	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 }
 	break;
 	case 11:
-#line 64 "../../src/hb-buffer-deserialize-json.rl"
+#line 64 "hb-buffer-deserialize-json.rl"
 	{ if (!parse_int  (tok, p, &pos.x_offset )) return false; }
-#line 43 "../../src/hb-buffer-deserialize-json.rl"
+#line 43 "hb-buffer-deserialize-json.rl"
 	{
 	buffer->add_info (info);
 	if (buffer->in_error)
 	  return false;
 	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 }
 	break;
 	case 13:
-#line 65 "../../src/hb-buffer-deserialize-json.rl"
+#line 65 "hb-buffer-deserialize-json.rl"
 	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
-#line 43 "../../src/hb-buffer-deserialize-json.rl"
+#line 43 "hb-buffer-deserialize-json.rl"
 	{
 	buffer->add_info (info);
 	if (buffer->in_error)
 	  return false;
 	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 }
 	break;
 	case 4:
-#line 66 "../../src/hb-buffer-deserialize-json.rl"
+#line 66 "hb-buffer-deserialize-json.rl"
 	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
-#line 43 "../../src/hb-buffer-deserialize-json.rl"
+#line 43 "hb-buffer-deserialize-json.rl"
 	{
 	buffer->add_info (info);
 	if (buffer->in_error)
 	  return false;
 	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 }
 	break;
 	case 7:
-#line 67 "../../src/hb-buffer-deserialize-json.rl"
+#line 67 "hb-buffer-deserialize-json.rl"
 	{ if (!parse_int  (tok, p, &pos.y_advance)) return false; }
-#line 43 "../../src/hb-buffer-deserialize-json.rl"
+#line 43 "hb-buffer-deserialize-json.rl"
 	{
 	buffer->add_info (info);
 	if (buffer->in_error)
 	  return false;
 	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 }
 	break;
-#line 624 "hb-buffer-deserialize-json.hh.tmp"
+#line 624 "hb-buffer-deserialize-json.hh"
 	}
 
 _again:
 	if ( cs == 0 )
 		goto _out;
 	if ( ++p != pe )
 		goto _resume;
 	_test_eof: {}
 	_out: {}
 	}
 
-#line 125 "../../src/hb-buffer-deserialize-json.rl"
+#line 125 "hb-buffer-deserialize-json.rl"
 
 
   *end_ptr = p;
 
   return p == pe && *(p-1) != ']';
 }
 
 #endif /* HB_BUFFER_DESERIALIZE_JSON_HH */
--- a/gfx/harfbuzz/src/hb-buffer-deserialize-text.hh
+++ b/gfx/harfbuzz/src/hb-buffer-deserialize-text.hh
@@ -1,10 +1,10 @@
 
-#line 1 "../../src/hb-buffer-deserialize-text.rl"
+#line 1 "hb-buffer-deserialize-text.rl"
 /*
  * Copyright © 2013  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
  * Permission is hereby granted, without written agreement and without
  * license or royalty fees, to use, copy, modify, and distribute this
  * software and its documentation for any purpose, provided that the
@@ -27,17 +27,17 @@
  */
 
 #ifndef HB_BUFFER_DESERIALIZE_TEXT_HH
 #define HB_BUFFER_DESERIALIZE_TEXT_HH
 
 #include "hb-private.hh"
 
 
-#line 36 "hb-buffer-deserialize-text.hh.tmp"
+#line 36 "hb-buffer-deserialize-text.hh"
 static const unsigned char _deserialize_text_trans_keys[] = {
 	0u, 0u, 9u, 122u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, 
 	48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, 
 	9u, 122u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 
 	9u, 124u, 9u, 124u, 9u, 124u, 0
 };
 
 static const char _deserialize_text_key_spans[] = {
@@ -307,17 +307,17 @@ static const char _deserialize_text_eof_
 
 static const int deserialize_text_start = 1;
 static const int deserialize_text_first_final = 13;
 static const int deserialize_text_error = 0;
 
 static const int deserialize_text_en_main = 1;
 
 
-#line 91 "../../src/hb-buffer-deserialize-text.rl"
+#line 91 "hb-buffer-deserialize-text.rl"
 
 
 static hb_bool_t
 _hb_buffer_deserialize_glyphs_text (hb_buffer_t *buffer,
 				    const char *buf,
 				    unsigned int buf_len,
 				    const char **end_ptr,
 				    hb_font_t *font)
@@ -331,25 +331,25 @@ static hb_bool_t
     p++;
   if (p < pe && *p == (buffer->len ? '|' : '['))
   {
     *end_ptr = ++p;
   }
 
   const char *eof = pe, *tok = NULL;
   int cs;
-  hb_glyph_info_t info;
-  hb_glyph_position_t pos;
+  hb_glyph_info_t info = {0};
+  hb_glyph_position_t pos = {0};
   
-#line 343 "hb-buffer-deserialize-text.hh.tmp"
+#line 343 "hb-buffer-deserialize-text.hh"
 	{
 	cs = deserialize_text_start;
 	}
 
-#line 348 "hb-buffer-deserialize-text.hh.tmp"
+#line 348 "hb-buffer-deserialize-text.hh"
 	{
 	int _slen;
 	int _trans;
 	const unsigned char *_keys;
 	const char *_inds;
 	if ( p == pe )
 		goto _test_eof;
 	if ( cs == 0 )
@@ -365,207 +365,207 @@ static hb_bool_t
 
 	cs = _deserialize_text_trans_targs[_trans];
 
 	if ( _deserialize_text_trans_actions[_trans] == 0 )
 		goto _again;
 
 	switch ( _deserialize_text_trans_actions[_trans] ) {
 	case 2:
-#line 51 "../../src/hb-buffer-deserialize-text.rl"
+#line 51 "hb-buffer-deserialize-text.rl"
 	{
 	tok = p;
 }
 	break;
 	case 5:
-#line 55 "../../src/hb-buffer-deserialize-text.rl"
+#line 55 "hb-buffer-deserialize-text.rl"
 	{
 	if (!hb_font_glyph_from_string (font,
 					tok, p - tok,
 					&info.codepoint))
 	  return false;
 }
 	break;
 	case 10:
-#line 62 "../../src/hb-buffer-deserialize-text.rl"
+#line 62 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
 	break;
 	case 3:
-#line 63 "../../src/hb-buffer-deserialize-text.rl"
+#line 63 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_int  (tok, p, &pos.x_offset )) return false; }
 	break;
 	case 12:
-#line 64 "../../src/hb-buffer-deserialize-text.rl"
+#line 64 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
 	break;
 	case 7:
-#line 65 "../../src/hb-buffer-deserialize-text.rl"
+#line 65 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
 	break;
 	case 1:
-#line 38 "../../src/hb-buffer-deserialize-text.rl"
+#line 38 "hb-buffer-deserialize-text.rl"
 	{
 	memset (&info, 0, sizeof (info));
 	memset (&pos , 0, sizeof (pos ));
 }
-#line 51 "../../src/hb-buffer-deserialize-text.rl"
+#line 51 "hb-buffer-deserialize-text.rl"
 	{
 	tok = p;
 }
 	break;
 	case 4:
-#line 55 "../../src/hb-buffer-deserialize-text.rl"
+#line 55 "hb-buffer-deserialize-text.rl"
 	{
 	if (!hb_font_glyph_from_string (font,
 					tok, p - tok,
 					&info.codepoint))
 	  return false;
 }
-#line 43 "../../src/hb-buffer-deserialize-text.rl"
+#line 43 "hb-buffer-deserialize-text.rl"
 	{
 	buffer->add_info (info);
 	if (buffer->in_error)
 	  return false;
 	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 }
 	break;
 	case 9:
-#line 62 "../../src/hb-buffer-deserialize-text.rl"
+#line 62 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
-#line 43 "../../src/hb-buffer-deserialize-text.rl"
+#line 43 "hb-buffer-deserialize-text.rl"
 	{
 	buffer->add_info (info);
 	if (buffer->in_error)
 	  return false;
 	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 }
 	break;
 	case 11:
-#line 64 "../../src/hb-buffer-deserialize-text.rl"
+#line 64 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
-#line 43 "../../src/hb-buffer-deserialize-text.rl"
+#line 43 "hb-buffer-deserialize-text.rl"
 	{
 	buffer->add_info (info);
 	if (buffer->in_error)
 	  return false;
 	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 }
 	break;
 	case 6:
-#line 65 "../../src/hb-buffer-deserialize-text.rl"
+#line 65 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
-#line 43 "../../src/hb-buffer-deserialize-text.rl"
+#line 43 "hb-buffer-deserialize-text.rl"
 	{
 	buffer->add_info (info);
 	if (buffer->in_error)
 	  return false;
 	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 }
 	break;
 	case 8:
-#line 66 "../../src/hb-buffer-deserialize-text.rl"
+#line 66 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_int  (tok, p, &pos.y_advance)) return false; }
-#line 43 "../../src/hb-buffer-deserialize-text.rl"
+#line 43 "hb-buffer-deserialize-text.rl"
 	{
 	buffer->add_info (info);
 	if (buffer->in_error)
 	  return false;
 	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 }
 	break;
-#line 480 "hb-buffer-deserialize-text.hh.tmp"
+#line 480 "hb-buffer-deserialize-text.hh"
 	}
 
 _again:
 	if ( cs == 0 )
 		goto _out;
 	if ( ++p != pe )
 		goto _resume;
 	_test_eof: {}
 	if ( p == eof )
 	{
 	switch ( _deserialize_text_eof_actions[cs] ) {
 	case 4:
-#line 55 "../../src/hb-buffer-deserialize-text.rl"
+#line 55 "hb-buffer-deserialize-text.rl"
 	{
 	if (!hb_font_glyph_from_string (font,
 					tok, p - tok,
 					&info.codepoint))
 	  return false;
 }
-#line 43 "../../src/hb-buffer-deserialize-text.rl"
+#line 43 "hb-buffer-deserialize-text.rl"
 	{
 	buffer->add_info (info);
 	if (buffer->in_error)
 	  return false;
 	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 }
 	break;
 	case 9:
-#line 62 "../../src/hb-buffer-deserialize-text.rl"
+#line 62 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
-#line 43 "../../src/hb-buffer-deserialize-text.rl"
+#line 43 "hb-buffer-deserialize-text.rl"
 	{
 	buffer->add_info (info);
 	if (buffer->in_error)
 	  return false;
 	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 }
 	break;
 	case 11:
-#line 64 "../../src/hb-buffer-deserialize-text.rl"
+#line 64 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
-#line 43 "../../src/hb-buffer-deserialize-text.rl"
+#line 43 "hb-buffer-deserialize-text.rl"
 	{
 	buffer->add_info (info);
 	if (buffer->in_error)
 	  return false;
 	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 }
 	break;
 	case 6:
-#line 65 "../../src/hb-buffer-deserialize-text.rl"
+#line 65 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
-#line 43 "../../src/hb-buffer-deserialize-text.rl"
+#line 43 "hb-buffer-deserialize-text.rl"
 	{
 	buffer->add_info (info);
 	if (buffer->in_error)
 	  return false;
 	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 }
 	break;
 	case 8:
-#line 66 "../../src/hb-buffer-deserialize-text.rl"
+#line 66 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_int  (tok, p, &pos.y_advance)) return false; }
-#line 43 "../../src/hb-buffer-deserialize-text.rl"
+#line 43 "hb-buffer-deserialize-text.rl"
 	{
 	buffer->add_info (info);
 	if (buffer->in_error)
 	  return false;
 	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 }
 	break;
-#line 557 "hb-buffer-deserialize-text.hh.tmp"
+#line 557 "hb-buffer-deserialize-text.hh"
 	}
 	}
 
 	_out: {}
 	}
 
-#line 119 "../../src/hb-buffer-deserialize-text.rl"
+#line 119 "hb-buffer-deserialize-text.rl"
 
 
   *end_ptr = p;
 
   return p == pe && *(p-1) != ']';
 }
 
 #endif /* HB_BUFFER_DESERIALIZE_TEXT_HH */
--- a/gfx/harfbuzz/src/hb-buffer-deserialize-text.rl
+++ b/gfx/harfbuzz/src/hb-buffer-deserialize-text.rl
@@ -106,18 +106,18 @@ static hb_bool_t
     p++;
   if (p < pe && *p == (buffer->len ? '|' : '['))
   {
     *end_ptr = ++p;
   }
 
   const char *eof = pe, *tok = NULL;
   int cs;
-  hb_glyph_info_t info;
-  hb_glyph_position_t pos;
+  hb_glyph_info_t info = {0};
+  hb_glyph_position_t pos = {0};
   %%{
     write init;
     write exec;
   }%%
 
   *end_ptr = p;
 
   return p == pe && *(p-1) != ']';
--- a/gfx/harfbuzz/src/hb-buffer.cc
+++ b/gfx/harfbuzz/src/hb-buffer.cc
@@ -438,28 +438,28 @@ hb_buffer_t::set_masks (hb_mask_t    val
 }
 
 void
 hb_buffer_t::reverse_range (unsigned int start,
 			    unsigned int end)
 {
   unsigned int i, j;
 
-  if (start == end - 1)
+  if (end - start < 2)
     return;
 
   for (i = start, j = end - 1; i < j; i++, j--) {
     hb_glyph_info_t t;
 
     t = info[i];
     info[i] = info[j];
     info[j] = t;
   }
 
-  if (pos) {
+  if (have_positions) {
     for (i = start, j = end - 1; i < j; i++, j--) {
       hb_glyph_position_t t;
 
       t = pos[i];
       pos[i] = pos[j];
       pos[j] = t;
     }
   }
@@ -962,17 +962,17 @@ hb_buffer_set_language (hb_buffer_t   *b
 }
 
 /**
  * hb_buffer_get_language:
  * @buffer: a buffer.
  *
  * 
  *
- * Return value: 
+ * Return value: (transfer none):
  *
  * Since: 1.0
  **/
 hb_language_t
 hb_buffer_get_language (hb_buffer_t *buffer)
 {
   return buffer->props.language;
 }
@@ -994,17 +994,17 @@ hb_buffer_set_segment_properties (hb_buf
     return;
 
   buffer->props = *props;
 }
 
 /**
  * hb_buffer_get_segment_properties:
  * @buffer: a buffer.
- * @props: 
+ * @props: (out):
  *
  * 
  *
  * Since: 1.0
  **/
 void
 hb_buffer_get_segment_properties (hb_buffer_t *buffer,
 				  hb_segment_properties_t *props)
@@ -1323,25 +1323,25 @@ hb_buffer_reverse_clusters (hb_buffer_t 
  * Since: 1.0
  **/
 void
 hb_buffer_guess_segment_properties (hb_buffer_t *buffer)
 {
   buffer->guess_segment_properties ();
 }
 
-template <bool validate, typename T>
+template <typename utf_t>
 static inline void
 hb_buffer_add_utf (hb_buffer_t  *buffer,
-		   const T      *text,
+		   const typename utf_t::codepoint_t *text,
 		   int           text_length,
 		   unsigned int  item_offset,
 		   int           item_length)
 {
-  typedef hb_utf_t<T, true> utf_t;
+  typedef typename utf_t::codepoint_t T;
   const hb_codepoint_t replacement = buffer->replacement;
 
   assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
 	  (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
 
   if (unlikely (hb_object_is_inert (buffer)))
     return;
 
@@ -1395,33 +1395,33 @@ hb_buffer_add_utf (hb_buffer_t  *buffer,
   }
 
   buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE;
 }
 
 /**
  * hb_buffer_add_utf8:
  * @buffer: a buffer.
- * @text: (array length=text_length):
+ * @text: (array length=text_length) (element-type uint8_t):
  * @text_length: 
  * @item_offset: 
  * @item_length: 
  *
  * 
  *
  * Since: 1.0
  **/
 void
 hb_buffer_add_utf8 (hb_buffer_t  *buffer,
 		    const char   *text,
 		    int           text_length,
 		    unsigned int  item_offset,
 		    int           item_length)
 {
-  hb_buffer_add_utf<true> (buffer, (const uint8_t *) text, text_length, item_offset, item_length);
+  hb_buffer_add_utf<hb_utf8_t> (buffer, (const uint8_t *) text, text_length, item_offset, item_length);
 }
 
 /**
  * hb_buffer_add_utf16:
  * @buffer: a buffer.
  * @text: (array length=text_length):
  * @text_length: 
  * @item_offset: 
@@ -1433,17 +1433,17 @@ hb_buffer_add_utf8 (hb_buffer_t  *buffer
  **/
 void
 hb_buffer_add_utf16 (hb_buffer_t    *buffer,
 		     const uint16_t *text,
 		     int             text_length,
 		     unsigned int    item_offset,
 		     int             item_length)
 {
-  hb_buffer_add_utf<true> (buffer, text, text_length, item_offset, item_length);
+  hb_buffer_add_utf<hb_utf16_t> (buffer, text, text_length, item_offset, item_length);
 }
 
 /**
  * hb_buffer_add_utf32:
  * @buffer: a buffer.
  * @text: (array length=text_length):
  * @text_length: 
  * @item_offset: 
@@ -1455,17 +1455,39 @@ hb_buffer_add_utf16 (hb_buffer_t    *buf
  **/
 void
 hb_buffer_add_utf32 (hb_buffer_t    *buffer,
 		     const uint32_t *text,
 		     int             text_length,
 		     unsigned int    item_offset,
 		     int             item_length)
 {
-  hb_buffer_add_utf<true> (buffer, text, text_length, item_offset, item_length);
+  hb_buffer_add_utf<hb_utf32_t<> > (buffer, text, text_length, item_offset, item_length);
+}
+
+/**
+ * hb_buffer_add_latin1:
+ * @buffer: a buffer.
+ * @text: (array length=text_length) (element-type uint8_t):
+ * @text_length: 
+ * @item_offset: 
+ * @item_length: 
+ *
+ * 
+ *
+ * Since: 1.0
+ **/
+void
+hb_buffer_add_latin1 (hb_buffer_t   *buffer,
+		      const uint8_t *text,
+		      int            text_length,
+		      unsigned int   item_offset,
+		      int            item_length)
+{
+  hb_buffer_add_utf<hb_latin1_t> (buffer, text, text_length, item_offset, item_length);
 }
 
 /**
  * hb_buffer_add_codepoints:
  * @buffer: a buffer.
  * @text: (array length=text_length):
  * @text_length: 
  * @item_offset: 
@@ -1477,17 +1499,17 @@ hb_buffer_add_utf32 (hb_buffer_t    *buf
  **/
 void
 hb_buffer_add_codepoints (hb_buffer_t          *buffer,
 			  const hb_codepoint_t *text,
 			  int                   text_length,
 			  unsigned int          item_offset,
 			  int                   item_length)
 {
-  hb_buffer_add_utf<false> (buffer, text, text_length, item_offset, item_length);
+  hb_buffer_add_utf<hb_utf32_t<false> > (buffer, text, text_length, item_offset, item_length);
 }
 
 
 static int
 compare_info_codepoint (const hb_glyph_info_t *pa,
 			const hb_glyph_info_t *pb)
 {
   return (int) pb->codepoint - (int) pa->codepoint;
--- a/gfx/harfbuzz/src/hb-buffer.h
+++ b/gfx/harfbuzz/src/hb-buffer.h
@@ -248,16 +248,24 @@ hb_buffer_add_utf16 (hb_buffer_t    *buf
 
 void
 hb_buffer_add_utf32 (hb_buffer_t    *buffer,
 		     const uint32_t *text,
 		     int             text_length,
 		     unsigned int    item_offset,
 		     int             item_length);
 
+/* Allows only access to first 256 Unicode codepoints. */
+void
+hb_buffer_add_latin1 (hb_buffer_t   *buffer,
+		      const uint8_t *text,
+		      int            text_length,
+		      unsigned int   item_offset,
+		      int            item_length);
+
 /* Like add_utf32 but does NOT check for invalid Unicode codepoints. */
 void
 hb_buffer_add_codepoints (hb_buffer_t          *buffer,
 			  const hb_codepoint_t *text,
 			  int                   text_length,
 			  unsigned int          item_offset,
 			  int                   item_length);
 
--- a/gfx/harfbuzz/src/hb-common.cc
+++ b/gfx/harfbuzz/src/hb-common.cc
@@ -52,17 +52,17 @@ void
   _hb_options = u;
 }
 
 
 /* hb_tag_t */
 
 /**
  * hb_tag_from_string:
- * @str: (array length=len): 
+ * @str: (array length=len) (element-type uint8_t): 
  * @len: 
  *
  * 
  *
  * Return value: 
  *
  * Since: 1.0
  **/
@@ -110,17 +110,17 @@ const char direction_strings[][4] = {
   "ltr",
   "rtl",
   "ttb",
   "btt"
 };
 
 /**
  * hb_direction_from_string:
- * @str: (array length=len): 
+ * @str: (array length=len) (element-type uint8_t): 
  * @len: 
  *
  * 
  *
  * Return value: 
  *
  * Since: 1.0
  **/
@@ -174,17 +174,17 @@ static const char canon_map[256] = {
    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,  '-',  0,   0,
   '0', '1', '2', '3', '4', '5', '6', '7',  '8', '9',  0,   0,   0,   0,   0,   0,
   '-', 'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
   'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,  '-',
    0,  'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
   'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,   0
 };
 
-static hb_bool_t
+static bool
 lang_equal (hb_language_t  v1,
 	    const void    *v2)
 {
   const unsigned char *p1 = (const unsigned char *) v1;
   const unsigned char *p2 = (const unsigned char *) v2;
 
   while (*p1 && *p1 == canon_map[*p2])
     p1++, p2++;
@@ -230,17 +230,17 @@ struct hb_language_item_t {
 };
 
 
 /* Thread-safe lock-free language list */
 
 static hb_language_item_t *langs;
 
 #ifdef HB_USE_ATEXIT
-static inline
+static
 void free_langs (void)
 {
   while (langs) {
     hb_language_item_t *next = langs->next;
     langs->finish ();
     free (langs);
     langs = next;
   }
@@ -260,37 +260,38 @@ retry:
   /* Not found; allocate one. */
   hb_language_item_t *lang = (hb_language_item_t *) calloc (1, sizeof (hb_language_item_t));
   if (unlikely (!lang))
     return NULL;
   lang->next = first_lang;
   *lang = key;
 
   if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) {
+    lang->finish ();
     free (lang);
     goto retry;
   }
 
 #ifdef HB_USE_ATEXIT
   if (!first_lang)
     atexit (free_langs); /* First person registers atexit() callback. */
 #endif
 
   return lang;
 }
 
 
 /**
  * hb_language_from_string:
- * @str: (array length=len): 
+ * @str: (array length=len) (element-type uint8_t): 
  * @len: 
  *
  * 
  *
- * Return value: 
+ * Return value: (transfer none):
  *
  * Since: 1.0
  **/
 hb_language_t
 hb_language_from_string (const char *str, int len)
 {
   char strbuf[64];
 
@@ -340,17 +341,17 @@ hb_language_to_string (hb_language_t lan
 hb_language_t
 hb_language_get_default (void)
 {
   static hb_language_t default_language = HB_LANGUAGE_INVALID;
 
   hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language);
   if (unlikely (language == HB_LANGUAGE_INVALID)) {
     language = hb_language_from_string (setlocale (LC_CTYPE, NULL), -1);
-    hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language);
+    (void) hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language);
   }
 
   return default_language;
 }
 
 
 /* hb_script_t */
 
@@ -395,17 +396,17 @@ hb_script_from_iso15924_tag (hb_tag_t ta
     return (hb_script_t) tag;
 
   /* Otherwise, return unknown */
   return HB_SCRIPT_UNKNOWN;
 }
 
 /**
  * hb_script_from_string:
- * @s: (array length=len): 
+ * @s: (array length=len) (element-type uint8_t): 
  * @len: 
  *
  * 
  *
  * Return value: 
  *
  * Since: 1.0
  **/
--- a/gfx/harfbuzz/src/hb-coretext.cc
+++ b/gfx/harfbuzz/src/hb-coretext.cc
@@ -135,31 +135,42 @@ hb_coretext_face_get_cg_font (hb_face_t 
 
 
 /*
  * shaper font data
  */
 
 struct hb_coretext_shaper_font_data_t {
   CTFontRef ct_font;
+  CGFloat x_mult, y_mult; /* From CT space to HB space. */
 };
 
 hb_coretext_shaper_font_data_t *
 _hb_coretext_shaper_font_data_create (hb_font_t *font)
 {
   if (unlikely (!hb_coretext_shaper_face_data_ensure (font->face))) return NULL;
 
   hb_coretext_shaper_font_data_t *data = (hb_coretext_shaper_font_data_t *) calloc (1, sizeof (hb_coretext_shaper_font_data_t));
   if (unlikely (!data))
     return NULL;
 
   hb_face_t *face = font->face;
   hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
 
-  data->ct_font = CTFontCreateWithGraphicsFont (face_data, font->y_scale, NULL, NULL);
+  /* Choose a CoreText font size and calculate multipliers to convert to HarfBuzz space. */
+  CGFloat font_size = 36.; /* Default... */
+  /* No idea if the following is even a good idea. */
+  if (font->y_ppem)
+    font_size = font->y_ppem;
+
+  if (font_size < 0)
+    font_size = -font_size;
+  data->x_mult = (CGFloat) font->x_scale / font_size;
+  data->y_mult = (CGFloat) font->y_scale / font_size;
+  data->ct_font = CTFontCreateWithGraphicsFont (face_data, font_size, NULL, NULL);
   if (unlikely (!data->ct_font)) {
     DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed");
     free (data);
     return NULL;
   }
 
   return data;
 }
@@ -771,26 +782,42 @@ retry:
     }
 
     CFArrayRef glyph_runs = CTLineGetGlyphRuns (line);
     unsigned int num_runs = CFArrayGetCount (glyph_runs);
     DEBUG_MSG (CORETEXT, NULL, "Num runs: %d", num_runs);
 
     buffer->len = 0;
     uint32_t status_and = ~0, status_or = 0;
+    double advances_so_far = 0;
+    /* For right-to-left runs, CoreText returns the glyphs positioned such that
+     * any trailing whitespace is to the left of (0,0).  Adjust coordinate system
+     * to fix for that.  Test with any RTL string with trailing spaces.
+     * https://code.google.com/p/chromium/issues/detail?id=469028
+     */
+    if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
+    {
+      advances_so_far -= CTLineGetTrailingWhitespaceWidth (line);
+      if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction))
+	  advances_so_far = -advances_so_far;
+    }
 
     const CFRange range_all = CFRangeMake (0, 0);
 
     for (unsigned int i = 0; i < num_runs; i++)
     {
       CTRunRef run = static_cast<CTRunRef>(CFArrayGetValueAtIndex (glyph_runs, i));
       CTRunStatus run_status = CTRunGetStatus (run);
       status_or  |= run_status;
       status_and &= run_status;
       DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status);
+      double run_advance = CTRunGetTypographicBounds (run, range_all, NULL, NULL, NULL);
+      if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction))
+	  run_advance = -run_advance;
+      DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance);
 
       /* CoreText does automatic font fallback (AKA "cascading") for  characters
        * not supported by the requested font, and provides no way to turn it off,
        * so we must detect if the returned run uses a font other than the requested
        * one and fill in the buffer with .notdef glyphs instead of random glyph
        * indices from a different font.
        */
       CFDictionaryRef attributes = CTRunGetAttributes (run);
@@ -855,44 +882,53 @@ retry:
 	{
 	  CFRange range = CTRunGetStringRange (run);
           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;
 	  hb_glyph_info_t *info = buffer->info + buffer->len;
 
-	  CGGlyph notdef = 0;
-	  double advance = CTFontGetAdvancesForGlyphs (font_data->ct_font, kCTFontHorizontalOrientation, &notdef, NULL, 1);
+	  hb_codepoint_t notdef = 0;
+	  hb_direction_t dir = buffer->props.direction;
+	  hb_position_t x_advance, y_advance, x_offset, y_offset;
+	  hb_font_get_glyph_advance_for_direction (font, notdef, dir, &x_advance, &y_advance);
+	  hb_font_get_glyph_origin_for_direction (font, notdef, dir, &x_offset, &y_offset);
+	  hb_position_t advance = x_advance + y_advance;
+	  x_offset = -x_offset;
+	  y_offset = -y_offset;
 
 	  unsigned int old_len = buffer->len;
 	  for (CFIndex j = range.location; j < range.location + range.length; j++)
 	  {
 	      UniChar ch = CFStringGetCharacterAtIndex (string_ref, j);
 	      if (hb_in_range<UniChar> (ch, 0xDC00u, 0xDFFFu) && range.location < j)
 	      {
 		ch = CFStringGetCharacterAtIndex (string_ref, j - 1);
 		if (hb_in_range<UniChar> (ch, 0xD800u, 0xDBFFu))
 		  /* This is the second of a surrogate pair.  Don't need .notdef
 		   * for this one. */
 		  continue;
 	      }
+	      if (buffer->unicode->is_default_ignorable (ch))
+	        continue;
 
 	      info->codepoint = notdef;
 	      info->cluster = log_clusters[j];
 
 	      info->mask = advance;
-	      info->var1.u32 = 0;
-	      info->var2.u32 = 0;
+	      info->var1.u32 = x_offset;
+	      info->var2.u32 = y_offset;
 
 	      info++;
 	      buffer->len++;
 	  }
 	  if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
 	    buffer->reverse_range (old_len, buffer->len);
+	  advances_so_far += run_advance;
 	  continue;
 	}
       }
 
       unsigned int num_glyphs = CTRunGetGlyphCount (run);
       if (num_glyphs == 0)
 	continue;
 
@@ -912,17 +948,17 @@ retry:
 #define SCRATCH_SAVE() \
   unsigned int scratch_size_saved = scratch_size; \
   hb_buffer_t::scratch_buffer_t *scratch_saved = scratch
 
 #define SCRATCH_RESTORE() \
   scratch_size = scratch_size_saved; \
   scratch = scratch_saved;
 
-      {
+      { /* Setup glyphs */
         SCRATCH_SAVE();
 	const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : NULL;
 	if (!glyphs) {
 	  ALLOCATE_ARRAY (CGGlyph, glyph_buf, num_glyphs, goto resize_and_retry);
 	  CTRunGetGlyphs (run, range_all, glyph_buf);
 	  glyphs = glyph_buf;
 	}
 	const CFIndex* string_indices = USE_PTR ? CTRunGetStringIndicesPtr (run) : NULL;
@@ -936,50 +972,64 @@ retry:
 	{
 	  info->codepoint = glyphs[j];
 	  info->cluster = log_clusters[string_indices[j]];
 	  info++;
 	}
 	SCRATCH_RESTORE();
       }
       {
+        /* Setup positions.
+	 * Note that CoreText does not return advances for glyphs.  As such,
+	 * for all but last glyph, we use the delta position to next glyph as
+	 * advance (in the advance direction only), and for last glyph we set
+	 * whatever is needed to make the whole run's advance add up. */
         SCRATCH_SAVE();
 	const CGPoint* positions = USE_PTR ? CTRunGetPositionsPtr (run) : NULL;
 	if (!positions) {
 	  ALLOCATE_ARRAY (CGPoint, position_buf, num_glyphs, goto resize_and_retry);
 	  CTRunGetPositions (run, range_all, position_buf);
 	  positions = position_buf;
 	}
-	double run_advance = CTRunGetTypographicBounds (run, range_all, NULL, NULL, NULL);
-	DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance);
 	hb_glyph_info_t *info = run_info;
+	CGFloat x_mult = font_data->x_mult, y_mult = font_data->y_mult;
 	if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
 	{
+	  hb_position_t x_offset = (positions[0].x - advances_so_far) * x_mult;
 	  for (unsigned int j = 0; j < num_glyphs; j++)
 	  {
-	    double advance = (j + 1 < num_glyphs ? positions[j + 1].x : positions[0].x + run_advance) - positions[j].x;
-	    info->mask = advance;
-	    info->var1.u32 = positions[0].x; /* Yes, zero. */
-	    info->var2.u32 = positions[j].y;
+	    double advance;
+	    if (likely (j + 1 < num_glyphs))
+	      advance = positions[j + 1].x - positions[j].x;
+	    else /* last glyph */
+	      advance = run_advance - (positions[j].x - positions[0].x);
+	    info->mask = advance * x_mult;
+	    info->var1.u32 = x_offset;
+	    info->var2.u32 = positions[j].y * y_mult;
 	    info++;
 	  }
 	}
 	else
 	{
-	  run_advance = -run_advance;
+	  hb_position_t y_offset = (positions[0].y - advances_so_far) * y_mult;
 	  for (unsigned int j = 0; j < num_glyphs; j++)
 	  {
-	    double advance = (j + 1 < num_glyphs ? positions[j + 1].y : positions[0].y + run_advance) - positions[j].y;
-	    info->mask = advance;
-	    info->var1.u32 = positions[j].x;
-	    info->var2.u32 = positions[0].y; /* Yes, zero. */
+	    double advance;
+	    if (likely (j + 1 < num_glyphs))
+	      advance = positions[j + 1].y - positions[j].y;
+	    else /* last glyph */
+	      advance = run_advance - (positions[j].y - positions[0].y);
+	    info->mask = advance * y_mult;
+	    info->var1.u32 = positions[j].x * x_mult;
+	    info->var2.u32 = y_offset;
 	    info++;
 	  }
 	}
 	SCRATCH_RESTORE();
+	advances_so_far += run_advance;
       }
 #undef SCRATCH_RESTORE
 #undef SCRATCH_SAVE
 #undef USE_PTR
 #undef ALLOCATE_ARRAY
 
       buffer->len += num_glyphs;
     }
--- a/gfx/harfbuzz/src/hb-face.cc
+++ b/gfx/harfbuzz/src/hb-face.cc
@@ -160,18 +160,18 @@ static hb_blob_t *
  * Since: 1.0
  **/
 hb_face_t *
 hb_face_create (hb_blob_t    *blob,
 		unsigned int  index)
 {
   hb_face_t *face;
 
-  if (unlikely (!blob || !hb_blob_get_length (blob)))
-    return hb_face_get_empty ();
+  if (unlikely (!blob))
+    blob = hb_blob_get_empty ();
 
   hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index);
 
   if (unlikely (!closure))
     return hb_face_get_empty ();
 
   face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
 				    closure,
--- a/gfx/harfbuzz/src/hb-font.cc
+++ b/gfx/harfbuzz/src/hb-font.cc
@@ -809,17 +809,17 @@ hb_font_glyph_to_string (hb_font_t *font
 {
   font->glyph_to_string (glyph, s, size);
 }
 
 /* Parses gidDDD and uniUUUU strings automatically. */
 /**
  * hb_font_glyph_from_string:
  * @font: a font.
- * @s: (array length=len): 
+ * @s: (array length=len) (element-type uint8_t): 
  * @len: 
  * @glyph: (out): 
  *
  * 
  *
  * Return value: 
  *
  * Since: 1.0
@@ -849,18 +849,16 @@ hb_font_glyph_from_string (hb_font_t *fo
  **/
 hb_font_t *
 hb_font_create (hb_face_t *face)
 {
   hb_font_t *font;
 
   if (unlikely (!face))
     face = hb_face_get_empty ();
-  if (unlikely (hb_object_is_inert (face)))
-    return hb_font_get_empty ();
   if (!(font = hb_object_create<hb_font_t> ()))
     return hb_font_get_empty ();
 
   hb_face_make_immutable (face);
   font->face = hb_face_reference (face);
   font->klass = hb_font_funcs_get_empty ();
 
   return font;
@@ -875,17 +873,17 @@ hb_font_create (hb_face_t *face)
  * Return value: (transfer full): 
  *
  * Since: 1.0
  **/
 hb_font_t *
 hb_font_create_sub_font (hb_font_t *parent)
 {
   if (unlikely (!parent))
-    return hb_font_get_empty ();
+    parent = hb_font_get_empty ();
 
   hb_font_t *font = hb_font_create (parent->face);
 
   if (unlikely (hb_object_is_inert (font)))
     return font;
 
   hb_font_make_immutable (parent);
   font->parent = hb_font_reference (parent);
--- a/gfx/harfbuzz/src/hb-ft.cc
+++ b/gfx/harfbuzz/src/hb-ft.cc
@@ -46,16 +46,23 @@
  * In general, this file does a fine job of what it's supposed to do.
  * There are, however, things that need more work:
  *
  *   - We don't handle any load_flags.  That definitely has API implications. :(
  *     I believe hb_ft_font_create() should take load_flags input.
  *     In particular, FT_Get_Advance() without the NO_HINTING flag seems to be
  *     buggy.
  *
+ *     FreeType works in 26.6 mode.  Clients can decide to use that mode, and everything
+ *     would work fine.  However, we also abuse this API for performing in font-space,
+ *     but don't pass the correct flags to FreeType.  We just abuse the no-hinting mode
+ *     for that, such that no rounding etc happens.  As such, we don't set ppem, and
+ *     pass NO_HINTING around.  This seems to work best, until we go ahead and add a full
+ *     load_flags API.
+ *
  *   - We don't handle / allow for emboldening / obliqueing.
  *
  *   - In the future, we should add constructors to create fonts in font space?
  *
  *   - FT_Load_Glyph() is exteremely costly.  Do something about it?
  */
 
 
@@ -65,22 +72,20 @@ hb_ft_get_glyph (hb_font_t *font HB_UNUS
 		 hb_codepoint_t unicode,
 		 hb_codepoint_t variation_selector,
 		 hb_codepoint_t *glyph,
 		 void *user_data HB_UNUSED)
 
 {
   FT_Face ft_face = (FT_Face) font_data;
 
-#ifdef HAVE_FT_FACE_GETCHARVARIANTINDEX
   if (unlikely (variation_selector)) {
     *glyph = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector);
     return *glyph != 0;
   }
-#endif
 
   *glyph = FT_Get_Char_Index (ft_face, unicode);
   return *glyph != 0;
 }
 
 static hb_position_t
 hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
 			   void *font_data,
@@ -89,32 +94,38 @@ hb_ft_get_glyph_h_advance (hb_font_t *fo
 {
   FT_Face ft_face = (FT_Face) font_data;
   int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
   FT_Fixed v;
 
   if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v)))
     return 0;
 
+  if (font->x_scale < 0)
+    v = -v;
+
   return (v + (1<<9)) >> 10;
 }
 
 static hb_position_t
 hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
 			   void *font_data,
 			   hb_codepoint_t glyph,
 			   void *user_data HB_UNUSED)
 {
   FT_Face ft_face = (FT_Face) font_data;
   int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING | FT_LOAD_VERTICAL_LAYOUT;
   FT_Fixed v;
 
   if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v)))
     return 0;
 
+  if (font->y_scale < 0)
+    v = -v;
+
   /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
    * have a Y growing upward.  Hence the extra negation. */
   return (-v + (1<<9)) >> 10;
 }
 
 static hb_bool_t
 hb_ft_get_glyph_h_origin (hb_font_t *font HB_UNUSED,
 			  void *font_data HB_UNUSED,
@@ -141,16 +152,21 @@ hb_ft_get_glyph_v_origin (hb_font_t *fon
   if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
     return false;
 
   /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
    * have a Y growing upward.  Hence the extra negation. */
   *x = ft_face->glyph->metrics.horiBearingX -   ft_face->glyph->metrics.vertBearingX;
   *y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY);
 
+  if (font->x_scale < 0)
+    *x = -*x;
+  if (font->y_scale < 0)
+    *y = -*y;
+
   return true;
 }
 
 static hb_position_t
 hb_ft_get_glyph_h_kerning (hb_font_t *font,
 			   void *font_data,
 			   hb_codepoint_t left_glyph,
 			   hb_codepoint_t right_glyph,
@@ -335,34 +351,46 @@ hb_ft_face_create (FT_Face           ft_
 {
   hb_face_t *face;
 
   if (ft_face->stream->read == NULL) {
     hb_blob_t *blob;
 
     blob = hb_blob_create ((const char *) ft_face->stream->base,
 			   (unsigned int) ft_face->stream->size,
-			   /* TODO: We assume that it's mmap()'ed, but FreeType code
-			    * suggests that there are cases we reach here but font is
-			    * not mmapped.  For example, when mmap() fails.  No idea
-			    * how to deal with it better here. */
-			   HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE,
+			   HB_MEMORY_MODE_READONLY,
 			   ft_face, destroy);
     face = hb_face_create (blob, ft_face->face_index);
     hb_blob_destroy (blob);
   } else {
     face = hb_face_create_for_tables (reference_table, ft_face, destroy);
   }
 
   hb_face_set_index (face, ft_face->face_index);
   hb_face_set_upem (face, ft_face->units_per_EM);
 
   return face;
 }
 
+/**
+ * hb_ft_face_create_referenced:
+ * @ft_face:
+ *
+ * 
+ *
+ * Return value: (transfer full): 
+ * Since: 1.0
+ **/
+hb_face_t *
+hb_ft_face_create_referenced (FT_Face ft_face)
+{
+  FT_Reference_Face (ft_face);
+  return hb_ft_face_create (ft_face, (hb_destroy_func_t) FT_Done_Face);
+}
+
 static void
 hb_ft_face_finalize (FT_Face ft_face)
 {
   hb_face_destroy ((hb_face_t *) ft_face->generic.data);
 }
 
 /**
  * hb_ft_face_create_cached:
@@ -415,33 +443,53 @@ hb_ft_font_create (FT_Face           ft_
   font = hb_font_create (face);
   hb_face_destroy (face);
   hb_font_set_funcs (font,
 		     _hb_ft_get_font_funcs (),
 		     ft_face, (hb_destroy_func_t) _do_nothing);
   hb_font_set_scale (font,
 		     (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16),
 		     (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16));
+#if 0 /* hb-ft works in no-hinting model */
   hb_font_set_ppem (font,
 		    ft_face->size->metrics.x_ppem,
 		    ft_face->size->metrics.y_ppem);
+#endif
 
   return font;
 }
 
+/**
+ * hb_ft_font_create_referenced:
+ * @ft_face:
+ *
+ * 
+ *
+ * Return value: (transfer full): 
+ * Since: 1.0
+ **/
+hb_font_t *
+hb_ft_font_create_referenced (FT_Face ft_face)
+{
+  FT_Reference_Face (ft_face);
+  return hb_ft_font_create (ft_face, (hb_destroy_func_t) FT_Done_Face);
+}
+
 
 /* Thread-safe, lock-free, FT_Library */
 
 static FT_Library ft_library;
 
-static inline
+#ifdef HB_USE_ATEXIT
+static
 void free_ft_library (void)
 {
   FT_Done_FreeType (ft_library);
 }
+#endif
 
 static FT_Library
 get_ft_library (void)
 {
 retry:
   FT_Library library = (FT_Library) hb_atomic_ptr_get (&ft_library);
 
   if (unlikely (!library))
@@ -488,24 +536,29 @@ hb_ft_font_set_funcs (hb_font_t *font)
   if (unlikely (err)) {
     hb_blob_destroy (blob);
     DEBUG_MSG (FT, font, "Font face FT_New_Memory_Face() failed");
     return;
   }
 
   FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE);
 
-  assert (font->y_scale >= 0);
   FT_Set_Char_Size (ft_face,
-		    font->x_scale, font->y_scale,
+		    abs (font->x_scale), abs (font->y_scale),
 		    0, 0);
 #if 0
 		    font->x_ppem * 72 * 64 / font->x_scale,
 		    font->y_ppem * 72 * 64 / font->y_scale);
 #endif
+  if (font->x_scale < 0 || font->y_scale < 0)
+  {
+    FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0,
+			  0, font->y_scale < 0 ? -1 : +1};
+    FT_Set_Transform (ft_face, &matrix, NULL);
+  }
 
   ft_face->generic.data = blob;
   ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;
 
   hb_font_set_funcs (font,
 		     _hb_ft_get_font_funcs (),
 		     ft_face,
 		     (hb_destroy_func_t) FT_Done_Face);
--- a/gfx/harfbuzz/src/hb-ft.h
+++ b/gfx/harfbuzz/src/hb-ft.h
@@ -29,29 +29,86 @@
 
 #include "hb.h"
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
 
 HB_BEGIN_DECLS
 
-/* Note: FreeType is not thread-safe.  Hence, these functions are not either. */
+/*
+ * Note: FreeType is not thread-safe.
+ * Hence, these functions are not either.
+ */
+
+/*
+ * hb-face from ft-face.
+ */
 
+/* This one creates a new hb-face for given ft-face.
+ * When the returned hb-face is destroyed, the destroy
+ * callback is called (if not NULL), with the ft-face passed
+ * to it.
+ *
+ * The client is responsible to make sure that ft-face is
+ * destroyed after hb-face is destroyed.
+ *
+ * Most often you don't want this function.  You should use either
+ * hb_ft_face_create_cached(), or hb_ft_face_create_referenced().
+ * In particular, if you are going to pass NULL as destroy, you
+ * probably should use (the more recent) hb_ft_face_create_referenced()
+ * instead.
+ */
 hb_face_t *
 hb_ft_face_create (FT_Face           ft_face,
 		   hb_destroy_func_t destroy);
 
+/* This version is like hb_ft_face_create(), except that it caches
+ * the hb-face using the generic pointer of the ft-face.  This means
+ * that subsequent calls to this function with the same ft-face will
+ * return the same hb-face (correctly referenced).
+ *
+ * Client is still responsible for making sure that ft-face is destroyed
+ * after hb-face is.
+ */
 hb_face_t *
 hb_ft_face_create_cached (FT_Face ft_face);
 
+/* This version is like hb_ft_face_create(), except that it calls
+ * FT_Reference_Face() on ft-face, as such keeping ft-face alive
+ * as long as the hb-face is.
+ *
+ * This is the most convenient version to use.  Use it unless you have
+ * very good reasons not to.
+ */
+hb_face_t *
+hb_ft_face_create_referenced (FT_Face ft_face);
+
+
+/*
+ * hb-font from ft-face.
+ */
+
+/*
+ * Note:
+ *
+ * Set face size on ft-face before creating hb-font from it.
+ * Otherwise hb-ft would NOT pick up the font size correctly.
+ */
+
+/* See notes on hb_ft_face_create().  Same issues re lifecycle-management
+ * apply here.  Use hb_ft_font_create_referenced() if you can. */
 hb_font_t *
 hb_ft_font_create (FT_Face           ft_face,
 		   hb_destroy_func_t destroy);
 
+/* See notes on hb_ft_face_create_referenced() re lifecycle-management
+ * issues. */
+hb_font_t *
+hb_ft_font_create_referenced (FT_Face ft_face);
 
 
 /* Makes an hb_font_t use FreeType internally to implement font functions. */
 void
 hb_ft_font_set_funcs (hb_font_t *font);
 
 FT_Face
 hb_ft_font_get_face (hb_font_t *font);
--- a/gfx/harfbuzz/src/hb-glib.cc
+++ b/gfx/harfbuzz/src/hb-glib.cc
@@ -377,8 +377,19 @@ hb_glib_get_unicode_funcs (void)
       HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
 #undef HB_UNICODE_FUNC_IMPLEMENT
     }
   };
 
   return const_cast<hb_unicode_funcs_t *> (&_hb_glib_unicode_funcs);
 }
 
+hb_blob_t *
+hb_glib_blob_create (GBytes *gbytes)
+{
+  gsize size = 0;
+  gconstpointer data = g_bytes_get_data (gbytes, &size);
+  return hb_blob_create ((const char *) data,
+			 size,
+			 HB_MEMORY_MODE_READONLY,
+			 g_bytes_ref (gbytes),
+			 (hb_destroy_func_t) g_bytes_unref);
+}
--- a/gfx/harfbuzz/src/hb-glib.h
+++ b/gfx/harfbuzz/src/hb-glib.h
@@ -41,12 +41,15 @@ hb_glib_script_to_script (GUnicodeScript
 
 GUnicodeScript
 hb_glib_script_from_script (hb_script_t script);
 
 
 hb_unicode_funcs_t *
 hb_glib_get_unicode_funcs (void);
 
+hb_blob_t *
+hb_glib_blob_create (GBytes *gbytes);
+
 
 HB_END_DECLS
 
 #endif /* HB_GLIB_H */
--- a/gfx/harfbuzz/src/hb-icu.cc
+++ b/gfx/harfbuzz/src/hb-icu.cc
@@ -358,15 +358,13 @@ hb_icu_get_unicode_funcs (void)
 #undef HB_UNICODE_FUNC_IMPLEMENT
     }
   };
 
 #if U_ICU_VERSION_MAJOR_NUM >= 49
   if (!hb_atomic_ptr_get (&normalizer)) {
     UErrorCode icu_err = U_ZERO_ERROR;
     /* We ignore failure in getNFCInstace(). */
-    hb_atomic_ptr_cmpexch (&normalizer, NULL, unorm2_getNFCInstance (&icu_err));
+    (void) hb_atomic_ptr_cmpexch (&normalizer, NULL, unorm2_getNFCInstance (&icu_err));
   }
 #endif
   return const_cast<hb_unicode_funcs_t *> (&_hb_icu_unicode_funcs);
 }
-
-
--- a/gfx/harfbuzz/src/hb-mutex-private.hh
+++ b/gfx/harfbuzz/src/hb-mutex-private.hh
@@ -34,25 +34,35 @@
 
 #include "hb-private.hh"
 
 
 /* mutex */
 
 /* We need external help for these */
 
-#if 0
+#if defined(HB_MUTEX_IMPL_INIT) \
+ && defined(hb_mutex_impl_init) \
+ && defined(hb_mutex_impl_lock) \
+ && defined(hb_mutex_impl_unlock) \
+ && defined(hb_mutex_impl_finish)
+
+/* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */
 
 
 #elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
 
 #include <windows.h>
 typedef CRITICAL_SECTION hb_mutex_impl_t;
 #define HB_MUTEX_IMPL_INIT	{0}
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+#define hb_mutex_impl_init(M)	InitializeCriticalSectionEx (M, 0, 0)
+#else
 #define hb_mutex_impl_init(M)	InitializeCriticalSection (M)
+#endif
 #define hb_mutex_impl_lock(M)	EnterCriticalSection (M)
 #define hb_mutex_impl_unlock(M)	LeaveCriticalSection (M)
 #define hb_mutex_impl_finish(M)	DeleteCriticalSection (M)
 
 
 #elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
 
 #include <pthread.h>
@@ -104,20 +114,22 @@ typedef volatile int hb_mutex_impl_t;
 
 typedef int hb_mutex_impl_t;
 #define HB_MUTEX_IMPL_INIT	0
 #define hb_mutex_impl_init(M)	HB_STMT_START {} HB_STMT_END
 #define hb_mutex_impl_lock(M)	HB_STMT_START {} HB_STMT_END
 #define hb_mutex_impl_unlock(M)	HB_STMT_START {} HB_STMT_END
 #define hb_mutex_impl_finish(M)	HB_STMT_START {} HB_STMT_END
 
+
 #endif
 
 
 #define HB_MUTEX_INIT		{HB_MUTEX_IMPL_INIT}
+
 struct hb_mutex_t
 {
   /* TODO Add tracing. */
 
   hb_mutex_impl_t m;
 
   inline void init   (void) { hb_mutex_impl_init   (&m); }
   inline void lock   (void) { hb_mutex_impl_lock   (&m); }
--- a/gfx/harfbuzz/src/hb-object-private.hh
+++ b/gfx/harfbuzz/src/hb-object-private.hh
@@ -42,29 +42,30 @@
 
 #ifndef HB_DEBUG_OBJECT
 #define HB_DEBUG_OBJECT (HB_DEBUG+0)
 #endif
 
 
 /* reference_count */
 
-#define HB_REFERENCE_COUNT_INVALID_VALUE ((hb_atomic_int_t) -1)
-#define HB_REFERENCE_COUNT_INVALID {HB_REFERENCE_COUNT_INVALID_VALUE}
+#define HB_REFERENCE_COUNT_INVALID_VALUE -1
+#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT(HB_REFERENCE_COUNT_INVALID_VALUE)}
+
 struct hb_reference_count_t
 {
   hb_atomic_int_t ref_count;
 
-  inline void init (int v) { ref_count = v; }
-  inline int inc (void) { return hb_atomic_int_add (const_cast<hb_atomic_int_t &> (ref_count),  1); }
-  inline int dec (void) { return hb_atomic_int_add (const_cast<hb_atomic_int_t &> (ref_count), -1); }
-  inline void finish (void) { ref_count = HB_REFERENCE_COUNT_INVALID_VALUE; }
+  inline void init (int v) { ref_count.set_unsafe (v); }
+  inline int get_unsafe (void) const { return ref_count.get_unsafe (); }
+  inline int inc (void) { return ref_count.inc (); }
+  inline int dec (void) { return ref_count.dec (); }
+  inline void finish (void) { ref_count.set_unsafe (HB_REFERENCE_COUNT_INVALID_VALUE); }
 
-  inline bool is_invalid (void) const { return ref_count == HB_REFERENCE_COUNT_INVALID_VALUE; }
-
+  inline bool is_invalid (void) const { return ref_count.get_unsafe () == HB_REFERENCE_COUNT_INVALID_VALUE; }
 };
 
 
 /* user_data */
 
 #define HB_USER_DATA_ARRAY_INIT {HB_MUTEX_INIT, HB_LOCKABLE_SET_INIT}
 struct hb_user_data_array_t
 {
@@ -97,32 +98,32 @@ struct hb_user_data_array_t
 
 /* object_header */
 
 struct hb_object_header_t
 {
   hb_reference_count_t ref_count;
   hb_user_data_array_t user_data;
 
-#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INVALID, HB_USER_DATA_ARRAY_INIT}
+#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, HB_USER_DATA_ARRAY_INIT}
 
   private:
   ASSERT_POD ();
 };
 
 
 /* object */
 
 template <typename Type>
 static inline void hb_object_trace (const Type *obj, const char *function)
 {
   DEBUG_MSG (OBJECT, (void *) obj,
 	     "%s refcount=%d",
 	     function,
-	     obj ? obj->header.ref_count.ref_count : 0);
+	     obj ? obj->header.ref_count.get_unsafe () : 0);
 }
 
 template <typename Type>
 static inline Type *hb_object_create (void)
 {
   Type *obj = (Type *) calloc (1, sizeof (Type));
 
   if (unlikely (!obj))
--- a/gfx/harfbuzz/src/hb-open-file-private.hh
+++ b/gfx/harfbuzz/src/hb-open-file-private.hh
@@ -48,17 +48,18 @@ namespace OT {
 
 struct OpenTypeFontFile;
 struct OffsetTable;
 struct TTCHeader;
 
 
 typedef struct TableRecord
 {
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this));
   }
 
   Tag		tag;		/* 4-byte identifier. */
   CheckSum	checkSum;	/* CheckSum for this table. */
   ULONG		offset;		/* Offset from beginning of TrueType font
 				 * file. */
@@ -97,17 +98,18 @@ typedef struct OffsetTable
   inline const TableRecord& get_table_by_tag (hb_tag_t tag) const
   {
     unsigned int table_index;
     find_table_index (tag, &table_index);
     return get_table (table_index);
   }
 
   public:
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables));
   }
 
   protected:
   Tag		sfnt_version;	/* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
   USHORT	numTables;	/* Number of tables. */
   USHORT	searchRangeZ;	/* (Maximum power of 2 <= numTables) x 16 */
@@ -125,17 +127,18 @@ typedef struct OffsetTable
 
 struct TTCHeaderVersion1
 {
   friend struct TTCHeader;
 
   inline unsigned int get_face_count (void) const { return table.len; }
   inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (table.sanitize (c, this));
   }
 
   protected:
   Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
   FixedVersion	version;	/* Version of the TTC Header (1.0),
 				 * 0x00010000u */
@@ -164,17 +167,18 @@ struct TTCHeader
   {
     switch (u.header.version.major) {
     case 2: /* version 2 is compatible with version 1 */
     case 1: return u.version1.get_face (i);
     default:return Null(OpenTypeFontFace);
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (unlikely (!u.header.version.sanitize (c))) return TRACE_RETURN (false);
     switch (u.header.version.major) {
     case 2: /* version 2 is compatible with version 1 */
     case 1: return TRACE_RETURN (u.version1.sanitize (c));
     default:return TRACE_RETURN (true);
     }
   }
@@ -228,17 +232,18 @@ struct OpenTypeFontFile
     case TrueTag:
     case Typ1Tag:
     case TrueTypeTag:	return u.fontFace;
     case TTCTag:	return u.ttcHeader.get_face (i);
     default:		return Null(OpenTypeFontFace);
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (unlikely (!u.tag.sanitize (c))) return TRACE_RETURN (false);
     switch (u.tag) {
     case CFFTag:	/* All the non-collection tags */
     case TrueTag:
     case Typ1Tag:
     case TrueTypeTag:	return TRACE_RETURN (u.fontFace.sanitize (c));
     case TTCTag:	return TRACE_RETURN (u.ttcHeader.sanitize (c));
--- a/gfx/harfbuzz/src/hb-open-type-private.hh
+++ b/gfx/harfbuzz/src/hb-open-type-private.hh
@@ -174,20 +174,23 @@ ASSERT_STATIC (Type::min_size + 1 <= siz
 #define HB_SANITIZE_MAX_EDITS 100
 #endif
 
 struct hb_sanitize_context_t
 {
   inline const char *get_name (void) { return "SANITIZE"; }
   static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE;
   typedef bool return_t;
+  template <typename T, typename F>
+  inline bool may_dispatch (const T *obj, const F *format)
+  { return format->sanitize (this); }
   template <typename T>
   inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
   static return_t default_return_value (void) { return true; }
-  bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; }
+  bool stop_sublookup_iteration (const return_t r) const { return !r; }
 
   inline void init (hb_blob_t *b)
   {
     this->blob = hb_blob_reference (b);
     this->writable = false;
   }
 
   inline void start_processing (void)
@@ -265,19 +268,19 @@ struct hb_sanitize_context_t
        p, p + len, len,
        this->start, this->end,
        this->writable ? "GRANTED" : "DENIED");
 
     return this->writable;
   }
 
   template <typename Type, typename ValueType>
-  inline bool try_set (Type *obj, const ValueType &v) {
+  inline bool try_set (const Type *obj, const ValueType &v) {
     if (this->may_edit (obj, obj->static_size)) {
-      obj->set (v);
+      const_cast<Type *> (obj)->set (v);
       return true;
     }
     return false;
   }
 
   mutable unsigned int debug_depth;
   const char *start, *end;
   bool writable;
@@ -541,22 +544,16 @@ struct BEInt<Type, 2>
     v[0] = (V >>  8) & 0xFF;
     v[1] = (V      ) & 0xFF;
   }
   inline operator Type (void) const
   {
     return (v[0] <<  8)
          + (v[1]      );
   }
-  inline bool operator == (const BEInt<Type, 2>& o) const
-  {
-    return v[0] == o.v[0]
-        && v[1] == o.v[1];
-  }
-  inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); }
   private: uint8_t v[2];
 };
 template <typename Type>
 struct BEInt<Type, 3>
 {
   public:
   inline void set (Type V)
   {
@@ -565,23 +562,16 @@ struct BEInt<Type, 3>
     v[2] = (V      ) & 0xFF;
   }
   inline operator Type (void) const
   {
     return (v[0] << 16)
          + (v[1] <<  8)
          + (v[2]      );
   }
-  inline bool operator == (const BEInt<Type, 3>& o) const
-  {
-    return v[0] == o.v[0]
-        && v[1] == o.v[1]
-        && v[2] == o.v[2];
-  }
-  inline bool operator != (const BEInt<Type, 3>& o) const { return !(*this == o); }
   private: uint8_t v[3];
 };
 template <typename Type>
 struct BEInt<Type, 4>
 {
   public:
   inline void set (Type V)
   {
@@ -592,39 +582,38 @@ struct BEInt<Type, 4>
   }
   inline operator Type (void) const
   {
     return (v[0] << 24)
          + (v[1] << 16)
          + (v[2] <<  8)
          + (v[3]      );
   }
-  inline bool operator == (const BEInt<Type, 4>& o) const
-  {
-    return v[0] == o.v[0]
-        && v[1] == o.v[1]
-        && v[2] == o.v[2]
-        && v[3] == o.v[3];
-  }
-  inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); }
   private: uint8_t v[4];
 };
 
 /* Integer types in big-endian order and no alignment requirement */
 template <typename Type, unsigned int Size>
 struct IntType
 {
   inline void set (Type i) { v.set (i); }
   inline operator Type(void) const { return v; }
-  inline bool operator == (const IntType<Type,Size> &o) const { return v == o.v; }
-  inline bool operator != (const IntType<Type,Size> &o) const { return v != o.v; }
+  inline bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
+  inline bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
   static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
-  inline int cmp (IntType<Type,Size> va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; }
-  inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; }
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline int cmp (Type a) const
+  {
+    Type b = v;
+    if (sizeof (Type) < sizeof (int))
+      return (int) a - (int) b;
+    else
+      return a < b ? -1 : a == b ? 0 : +1;
+  }
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (likely (c->check_struct (this)));
   }
   protected:
   BEInt<Type, Size> v;
   public:
   DEFINE_SIZE_STATIC (Size);
 };
@@ -641,17 +630,18 @@ typedef SHORT FWORD;
 
 /* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
 typedef USHORT UFWORD;
 
 /* Date represented in number of seconds since 12:00 midnight, January 1,
  * 1904. The value is represented as a signed 64-bit integer. */
 struct LONGDATETIME
 {
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (likely (c->check_struct (this)));
   }
   protected:
   LONG major;
   ULONG minor;
   public:
   DEFINE_SIZE_STATIC (8);
@@ -665,17 +655,20 @@ struct Tag : ULONG
   inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); }
   inline operator char* (void) { return reinterpret_cast<char *> (&this->v); }
   public:
   DEFINE_SIZE_STATIC (4);
 };
 DEFINE_NULL_DATA (Tag, "    ");
 
 /* Glyph index number, same as uint16 (length = 16 bits) */
-typedef USHORT GlyphID;
+struct GlyphID : USHORT {
+  static inline int cmp (const GlyphID *a, const GlyphID *b) { return b->USHORT::cmp (*a); }
+  inline int cmp (hb_codepoint_t a) const { return (int) a - (int) *this; }
+};
 
 /* Script/language-system/feature index */
 struct Index : USHORT {
   static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
 };
 DEFINE_NULL_DATA (Index, "\xff\xff");
 
 /* Offset, Null offset = 0 */
@@ -714,17 +707,18 @@ struct CheckSum : ULONG
 /*
  * Version Numbers
  */
 
 struct FixedVersion
 {
   inline uint32_t to_int (void) const { return (major << 16) + minor; }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this));
   }
 
   USHORT major;
   USHORT minor;
   public:
   DEFINE_SIZE_STATIC (4);
@@ -742,43 +736,45 @@ struct OffsetTo : Offset<OffsetType>
 {
   inline const Type& operator () (const void *base) const
   {
     unsigned int offset = *this;
     if (unlikely (!offset)) return Null(Type);
     return StructAtOffset<Type> (base, offset);
   }
 
-  inline Type& serialize (hb_serialize_context_t *c, void *base)
+  inline Type& serialize (hb_serialize_context_t *c, const void *base)
   {
     Type *t = c->start_embed<Type> ();
     this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
     return *t;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
     unsigned int offset = *this;
     if (unlikely (!offset)) return TRACE_RETURN (true);
-    Type &obj = StructAtOffset<Type> (base, offset);
+    const Type &obj = StructAtOffset<Type> (base, offset);
     return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c));
   }
   template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) {
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
+  {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
     unsigned int offset = *this;
     if (unlikely (!offset)) return TRACE_RETURN (true);
-    Type &obj = StructAtOffset<Type> (base, offset);
+    const Type &obj = StructAtOffset<Type> (base, offset);
     return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c));
   }
 
   /* Set the offset to Null */
-  inline bool neuter (hb_sanitize_context_t *c) {
+  inline bool neuter (hb_sanitize_context_t *c) const {
     return c->try_set (this, 0);
   }
   DEFINE_SIZE_STATIC (sizeof(OffsetType));
 };
 template <typename Base, typename OffsetType, typename Type>
 static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
 template <typename Base, typename OffsetType, typename Type>
 static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); }
@@ -833,42 +829,45 @@ struct ArrayOf
     TRACE_SERIALIZE (this);
     if (unlikely (!serialize (c, items_len))) return TRACE_RETURN (false);
     for (unsigned int i = 0; i < items_len; i++)
       array[i] = items[i];
     items.advance (items_len);
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
 
     /* Note: for structs that do not reference other structs,
      * we do not need to call their sanitize() as we already did
      * a bound check on the aggregate array size.  We just include
      * a small unreachable expression to make sure the structs
      * pointed to do have a simple sanitize(), ie. they do not
      * reference other structs via offsets.
      */
     (void) (false && array[0].sanitize (c));
 
     return TRACE_RETURN (true);
   }
-  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
     TRACE_SANITIZE (this);
     if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
     unsigned int count = len;
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!array[i].sanitize (c, base)))
         return TRACE_RETURN (false);
     return TRACE_RETURN (true);
   }
   template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) {
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
+  {
     TRACE_SANITIZE (this);
     if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
     unsigned int count = len;
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!array[i].sanitize (c, base, user_data)))
         return TRACE_RETURN (false);
     return TRACE_RETURN (true);
   }
@@ -879,17 +878,18 @@ struct ArrayOf
     unsigned int count = len;
     for (unsigned int i = 0; i < count; i++)
       if (!this->array[i].cmp (x))
         return i;
     return -1;
   }
 
   private:
-  inline bool sanitize_shallow (hb_sanitize_context_t *c) {
+  inline bool sanitize_shallow (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len));
   }
 
   public:
   LenType len;
   Type array[VAR];
   public:
@@ -905,22 +905,24 @@ template <typename Type>
 struct OffsetListOf : OffsetArrayOf<Type>
 {
   inline const Type& operator [] (unsigned int i) const
   {
     if (unlikely (i >= this->len)) return Null(Type);
     return this+this->array[i];
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this));
   }
   template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, T user_data) {
+  inline bool sanitize (hb_sanitize_context_t *c, T user_data) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data));
   }
 };
 
 
 /* An array starting at second element. */
 template <typename Type, typename LenType=USHORT>
@@ -944,22 +946,24 @@ struct HeadlessArrayOf
     if (unlikely (!items_len)) return TRACE_RETURN (true);
     if (unlikely (!c->extend (*this))) return TRACE_RETURN (false);
     for (unsigned int i = 0; i < items_len - 1; i++)
       array[i] = items[i];
     items.advance (items_len - 1);
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize_shallow (hb_sanitize_context_t *c) {
+  inline bool sanitize_shallow (hb_sanitize_context_t *c) const
+  {
     return c->check_struct (this)
 	&& c->check_array (this, Type::static_size, len);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
 
     /* Note: for structs that do not reference other structs,
      * we do not need to call their sanitize() as we already did
      * a bound check on the aggregate array size.  We just include
      * a small unreachable expression to make sure the structs
      * pointed to do have a simple sanitize(), ie. they do not
--- a/gfx/harfbuzz/src/hb-ot-cmap-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-cmap-table.hh
@@ -46,17 +46,18 @@ struct CmapSubtableFormat0
   {
     hb_codepoint_t gid = codepoint < 256 ? glyphIdArray[codepoint] : 0;
     if (!gid)
       return false;
     *glyph = gid;
     return true;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this));
   }
 
   protected:
   USHORT	format;		/* Format number is set to 0. */
   USHORT	lengthZ;	/* Byte length of this subtable. */
   USHORT	languageZ;	/* Ignore. */
@@ -120,17 +121,17 @@ struct CmapSubtableFormat4
 	return false;
       gid += idDelta[i];
     }
 
     *glyph = gid & 0xFFFFu;
     return true;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c)
+  inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
       return TRACE_RETURN (false);
 
     if (unlikely (!c->check_range (this, length)))
     {
       /* Some broken fonts have too long of a "length" value.
@@ -178,17 +179,18 @@ struct CmapSubtableLongGroup
 
   int cmp (hb_codepoint_t codepoint) const
   {
     if (codepoint < startCharCode) return -1;
     if (codepoint > endCharCode)   return +1;
     return 0;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this));
   }
 
   private:
   ULONG		startCharCode;	/* First character code in this group. */
   ULONG		endCharCode;	/* Last character code in this group. */
   ULONG		glyphID;	/* Glyph index; interpretation depends on
@@ -205,17 +207,18 @@ struct CmapSubtableTrimmed
     /* Rely on our implicit array bound-checking. */
     hb_codepoint_t gid = glyphIdArray[codepoint - startCharCode];
     if (!gid)
       return false;
     *glyph = gid;
     return true;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && glyphIdArray.sanitize (c));
   }
 
   protected:
   UINT		formatReserved;	/* Subtable format and (maybe) padding. */
   UINT		lengthZ;	/* Byte length of this subtable. */
   UINT		languageZ;	/* Ignore. */
@@ -237,17 +240,18 @@ struct CmapSubtableLongSegmented
   {
     int i = groups.bsearch (codepoint);
     if (i == -1)
       return false;
     *glyph = T::group_get_glyph (groups[i], codepoint);
     return true;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && groups.sanitize (c));
   }
 
   protected:
   USHORT	format;		/* Subtable format; set to 12. */
   USHORT	reservedZ;	/* Reserved; set to 0. */
   ULONG		lengthZ;	/* Byte length of this subtable. */
@@ -283,17 +287,18 @@ struct UnicodeValueRange
 {
   inline int cmp (const hb_codepoint_t &codepoint) const
   {
     if (codepoint < startUnicodeValue) return -1;
     if (codepoint > startUnicodeValue + additionalCount) return +1;
     return 0;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this));
   }
 
   UINT24	startUnicodeValue;	/* First value in this range. */
   BYTE		additionalCount;	/* Number of additional values in this
 					 * range. */
   public:
@@ -304,17 +309,18 @@ typedef SortedArrayOf<UnicodeValueRange,
 
 struct UVSMapping
 {
   inline int cmp (const hb_codepoint_t &codepoint) const
   {
     return unicodeValue.cmp (codepoint);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this));
   }
 
   UINT24	unicodeValue;	/* Base Unicode value of the UVS */
   GlyphID	glyphID;	/* Glyph ID of the UVS */
   public:
   DEFINE_SIZE_STATIC (5);
@@ -343,17 +349,18 @@ struct VariationSelectorRecord
     return GLYPH_VARIANT_NOT_FOUND;
   }
 
   inline int cmp (const hb_codepoint_t &variation_selector) const
   {
     return varSelector.cmp (variation_selector);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) &&
 			 defaultUVS.sanitize (c, base) &&
 			 nonDefaultUVS.sanitize (c, base));
   }
 
   UINT24	varSelector;	/* Variation selector. */
   OffsetTo<DefaultUVS, ULONG>
@@ -368,17 +375,18 @@ struct CmapSubtableFormat14
 {
   inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
 					    hb_codepoint_t variation_selector,
 					    hb_codepoint_t *glyph) const
   {
     return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) &&
 			 record.sanitize (c, this));
   }
 
   protected:
   USHORT	format;		/* Format number is set to 0. */
   ULONG		lengthZ;	/* Byte length of this subtable. */
@@ -413,17 +421,18 @@ struct CmapSubtable
 					    hb_codepoint_t *glyph) const
   {
     switch (u.format) {
     case 14: return u.format14.get_glyph_variant(codepoint, variation_selector, glyph);
     default: return GLYPH_VARIANT_NOT_FOUND;
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return TRACE_RETURN (false);
     switch (u.format) {
     case  0: return TRACE_RETURN (u.format0 .sanitize (c));
     case  4: return TRACE_RETURN (u.format4 .sanitize (c));
     case  6: return TRACE_RETURN (u.format6 .sanitize (c));
     case 10: return TRACE_RETURN (u.format10.sanitize (c));
     case 12: return TRACE_RETURN (u.format12.sanitize (c));
@@ -456,17 +465,18 @@ struct EncodingRecord
     int ret;
     ret = platformID.cmp (other.platformID);
     if (ret) return ret;
     ret = encodingID.cmp (other.encodingID);
     if (ret) return ret;
     return 0;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) &&
 			 subtable.sanitize (c, base));
   }
 
   USHORT	platformID;	/* Platform ID. */
   USHORT	encodingID;	/* Platform-specific encoding ID. */
   OffsetTo<CmapSubtable, ULONG>
@@ -491,17 +501,18 @@ struct cmap
      * unsorted subtable list. */
     int result = encodingRecord./*bsearch*/lsearch (key);
     if (result == -1 || !encodingRecord[result].subtable)
       return NULL;
 
     return &(this+encodingRecord[result].subtable);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) &&
 			 likely (version == 0) &&
 			 encodingRecord.sanitize (c, this));
   }
 
   USHORT		version;	/* Table version number (0). */
   SortedArrayOf<EncodingRecord>
--- a/gfx/harfbuzz/src/hb-ot-font.cc
+++ b/gfx/harfbuzz/src/hb-ot-font.cc
@@ -40,19 +40,19 @@ struct hb_ot_face_metrics_accelerator_t
   unsigned int num_metrics;
   unsigned int num_advances;
   unsigned int default_advance;
   const OT::_mtx *table;
   hb_blob_t *blob;
 
   inline void init (hb_face_t *face,
 		    hb_tag_t _hea_tag, hb_tag_t _mtx_tag,
-		    unsigned int default_advance)
+		    unsigned int default_advance_)
   {
-    this->default_advance = default_advance;
+    this->default_advance = default_advance_;
     this->num_metrics = face->get_num_glyphs ();
 
     hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag));
     const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob);
     this->num_advances = _hea->numberOfLongMetrics;
     hb_blob_destroy (_hea_blob);
 
     this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag));
@@ -109,16 +109,17 @@ struct hb_ot_face_cmap_accelerator_t
     if (!subtable) subtable = cmap->find_subtable (0, 6);
     if (!subtable) subtable = cmap->find_subtable (0, 4);
     /* 16-bit subtables. */
     if (!subtable) subtable = cmap->find_subtable (3, 1);
     if (!subtable) subtable = cmap->find_subtable (0, 3);
     if (!subtable) subtable = cmap->find_subtable (0, 2);
     if (!subtable) subtable = cmap->find_subtable (0, 1);
     if (!subtable) subtable = cmap->find_subtable (0, 0);
+    if (!subtable) subtable = cmap->find_subtable (3, 0);
     /* Meh. */
     if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
 
     /* UVS subtable. */
     if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5);
     /* Meh. */
     if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable);
 
--- a/gfx/harfbuzz/src/hb-ot-head-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-head-table.hh
@@ -40,23 +40,25 @@ namespace OT {
  */
 
 #define HB_OT_TAG_head HB_TAG('h','e','a','d')
 
 struct head
 {
   static const hb_tag_t tableTag	= HB_OT_TAG_head;
 
-  inline unsigned int get_upem (void) const {
+  inline unsigned int get_upem (void) const
+  {
     unsigned int upem = unitsPerEm;
     /* If no valid head table found, assume 1000, which matches typical Type1 usage. */
     return 16 <= upem && upem <= 16384 ? upem : 1000;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1));
   }
 
   protected:
   FixedVersion	version;		/* Version of the head table--currently
 					 * 0x00010000u for version 1.0. */
   FixedVersion	fontRevision;		/* Set by font manufacturer. */
--- a/gfx/harfbuzz/src/hb-ot-hhea-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-hhea-table.hh
@@ -44,17 +44,18 @@ namespace OT {
 
 struct _hea
 {
   static const hb_tag_t tableTag = HB_TAG('_','h','e','a');
 
   static const hb_tag_t hheaTag	= HB_OT_TAG_hhea;
   static const hb_tag_t vheaTag	= HB_OT_TAG_vhea;
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1));
   }
 
   public:
   FixedVersion	version;		/* 0x00010000u for version 1.0. */
   FWORD		ascender;		/* Typographic ascent. */
   FWORD		descender;		/* Typographic descent. */
--- a/gfx/harfbuzz/src/hb-ot-hmtx-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-hmtx-table.hh
@@ -52,17 +52,18 @@ struct LongMetric
 
 struct _mtx
 {
   static const hb_tag_t tableTag = HB_TAG('_','m','t','x');
 
   static const hb_tag_t hmtxTag	= HB_OT_TAG_hmtx;
   static const hb_tag_t vmtxTag	= HB_OT_TAG_vmtx;
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     /* We don't check for anything specific here.  The users of the
      * struct do all the hard work... */
     return TRACE_RETURN (true);
   }
 
   public:
   LongMetric	longMetric[VAR];	/* Paired advance width and leading
--- a/gfx/harfbuzz/src/hb-ot-layout-common-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-common-private.hh
@@ -32,16 +32,22 @@
 #include "hb-ot-layout-private.hh"
 #include "hb-open-type-private.hh"
 #include "hb-set-private.hh"
 
 
 namespace OT {
 
 
+#define TRACE_DISPATCH(this, format) \
+	hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
+	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
+	 "format %d", (int) format);
+
+
 #define NOT_COVERED		((unsigned int) -1)
 #define MAX_NESTING_LEVEL	8
 #define MAX_CONTEXT_LENGTH	64
 
 
 
 /*
  *
@@ -58,19 +64,20 @@ template <typename Type>
 struct Record
 {
   inline int cmp (hb_tag_t a) const {
     return tag.cmp (a);
   }
 
   struct sanitize_closure_t {
     hb_tag_t tag;
-    void *list_base;
+    const void *list_base;
   };
-  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
     TRACE_SANITIZE (this);
     const sanitize_closure_t closure = {tag, base};
     return TRACE_RETURN (c->check_struct (this) && offset.sanitize (c, base, &closure));
   }
 
   Tag		tag;		/* 4-byte Tag identifier */
   OffsetTo<Type>
 		offset;		/* Offset from beginning of object holding
@@ -116,30 +123,32 @@ struct RecordArrayOf : SortedArrayOf<Rec
 };
 
 template <typename Type>
 struct RecordListOf : RecordArrayOf<Type>
 {
   inline const Type& operator [] (unsigned int i) const
   { return this+RecordArrayOf<Type>::operator [](i).offset; }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (RecordArrayOf<Type>::sanitize (c, this));
   }
 };
 
 
 struct RangeRecord
 {
   inline int cmp (hb_codepoint_t g) const {
     return g < start ? -1 : g <= end ? 0 : +1 ;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this));
   }
 
   inline bool intersects (const hb_set_t *glyphs) const {
     return glyphs->intersects (start, end);
   }
 
@@ -194,17 +203,18 @@ struct LangSys
   inline unsigned int get_required_feature_index (void) const
   {
     if (reqFeatureIndex == 0xFFFFu)
       return Index::NOT_FOUND_INDEX;
    return reqFeatureIndex;;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c,
-			const Record<LangSys>::sanitize_closure_t * = NULL) {
+			const Record<LangSys>::sanitize_closure_t * = NULL) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c));
   }
 
   Offset<>	lookupOrderZ;	/* = Null (reserved for an offset to a
 				 * reordering table) */
   USHORT	reqFeatureIndex;/* Index of a feature required for this
 				 * language system--if no required features
@@ -233,17 +243,18 @@ struct Script
   }
   inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
   { return langSys.find_index (tag, index); }
 
   inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
   inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
 
   inline bool sanitize (hb_sanitize_context_t *c,
-			const Record<Script>::sanitize_closure_t * = NULL) {
+			const Record<Script>::sanitize_closure_t * = NULL) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
   }
 
   protected:
   OffsetTo<LangSys>
 		defaultLangSys;	/* Offset to DefaultLangSys table--from
 				 * beginning of Script table--may be Null */
@@ -255,17 +266,18 @@ struct Script
 };
 
 typedef RecordListOf<Script> ScriptList;
 
 
 /* http://www.microsoft.com/typography/otspec/features_pt.htm#size */
 struct FeatureParamsSize
 {
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
 
     /* This subtable has some "history", if you will.  Some earlier versions of
      * Adobe tools calculated the offset of the FeatureParams sutable from the
      * beginning of the FeatureList table!  Now, that is dealt with in the
      * Feature implementation.  But we still need to be able to tell junk from
      * real data.  Note: We don't check that the nameID actually exists.
@@ -366,17 +378,18 @@ struct FeatureParamsSize
 				 * (decipoints). */
   public:
   DEFINE_SIZE_STATIC (10);
 };
 
 /* http://www.microsoft.com/typography/otspec/features_pt.htm#ssxx */
 struct FeatureParamsStylisticSet
 {
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     /* Right now minorVersion is at zero.  Which means, any table supports
      * the uiNameID field. */
     return TRACE_RETURN (c->check_struct (this));
   }
 
   USHORT	version;	/* (set to 0): This corresponds to a “minor”
 				 * version number. Additional data may be
@@ -399,17 +412,18 @@ struct FeatureParamsStylisticSet
 				 * different application interfaces. */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
 /* http://www.microsoft.com/typography/otspec/features_ae.htm#cv01-cv99 */
 struct FeatureParamsCharacterVariants
 {
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) &&
 			 characters.sanitize (c));
   }
 
   USHORT	format;			/* Format number is set to 0. */
   USHORT	featUILableNameID;	/* The ‘name’ table name ID that
 					 * specifies a string (or strings,
@@ -439,17 +453,18 @@ struct FeatureParamsCharacterVariants
 					 * feature provides glyph variants.
 					 * (May be zero.) */
   public:
   DEFINE_SIZE_ARRAY (14, characters);
 };
 
 struct FeatureParams
 {
-  inline bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) {
+  inline bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) const
+  {
     TRACE_SANITIZE (this);
     if (tag == HB_TAG ('s','i','z','e'))
       return TRACE_RETURN (u.size.sanitize (c));
     if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
       return TRACE_RETURN (u.stylisticSet.sanitize (c));
     if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
       return TRACE_RETURN (u.characterVariants.sanitize (c));
     return TRACE_RETURN (true);
@@ -481,17 +496,18 @@ struct Feature
 					  unsigned int *lookup_count /* IN/OUT */,
 					  unsigned int *lookup_tags /* OUT */) const
   { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
 
   inline const FeatureParams &get_feature_params (void) const
   { return this+featureParams; }
 
   inline bool sanitize (hb_sanitize_context_t *c,
-			const Record<Feature>::sanitize_closure_t *closure) {
+			const Record<Feature>::sanitize_closure_t *closure) const
+  {
     TRACE_SANITIZE (this);
     if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
       return TRACE_RETURN (false);
 
     /* Some earlier versions of Adobe tools calculated the offset of the
      * FeatureParams subtable from the beginning of the FeatureList table!
      *
      * If sanitizing "failed" for the FeatureParams subtable, try it with the
@@ -556,32 +572,57 @@ struct LookupFlag : USHORT
   public:
   DEFINE_SIZE_STATIC (2);
 };
 
 struct Lookup
 {
   inline unsigned int get_subtable_count (void) const { return subTable.len; }
 
+  template <typename SubTableType>
+  inline const SubTableType& get_subtable (unsigned int i) const
+  { return this+CastR<OffsetArrayOf<SubTableType> > (subTable)[i]; }
+
+  template <typename SubTableType>
+  inline const OffsetArrayOf<SubTableType>& get_subtables (void) const
+  { return CastR<OffsetArrayOf<SubTableType> > (subTable); }
+  template <typename SubTableType>
+  inline OffsetArrayOf<SubTableType>& get_subtables (void)
+  { return CastR<OffsetArrayOf<SubTableType> > (subTable); }
+
   inline unsigned int get_type (void) const { return lookupType; }
 
   /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
    * higher 16-bit is mark-filtering-set if the lookup uses one.
    * Not to be confused with glyph_props which is very similar. */
   inline uint32_t get_props (void) const
   {
     unsigned int flag = lookupFlag;
     if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
     {
       const USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
       flag += (markFilteringSet << 16);
     }
     return flag;
   }
 
+  template <typename SubTableType, typename context_t>
+  inline typename context_t::return_t dispatch (context_t *c) const
+  {
+    unsigned int lookup_type = get_type ();
+    TRACE_DISPATCH (this, lookup_type);
+    unsigned int count = get_subtable_count ();
+    for (unsigned int i = 0; i < count; i++) {
+      typename context_t::return_t r = get_subtable<SubTableType> (i).dispatch (c, lookup_type);
+      if (c->stop_sublookup_iteration (r))
+        return TRACE_RETURN (r);
+    }
+    return TRACE_RETURN (c->default_return_value ());
+  }
+
   inline bool serialize (hb_serialize_context_t *c,
 			 unsigned int lookup_type,
 			 uint32_t lookup_props,
 			 unsigned int num_subtables)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
     lookupType.set (lookup_type);
@@ -590,28 +631,30 @@ struct Lookup
     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
     {
       USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
       markFilteringSet.set (lookup_props >> 16);
     }
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     /* Real sanitize of the subtables is done by GSUB/GPOS/... */
     if (!(c->check_struct (this) && subTable.sanitize (c))) return TRACE_RETURN (false);
     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
     {
-      USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
+      const USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
       if (!markFilteringSet.sanitize (c)) return TRACE_RETURN (false);
     }
     return TRACE_RETURN (true);
   }
 
+  private:
   USHORT	lookupType;		/* Different enumerations for GSUB and GPOS */
   USHORT	lookupFlag;		/* Lookup qualifiers */
   ArrayOf<Offset<> >
 		subTable;		/* Array of SubTables */
   USHORT	markFilteringSetX[VAR];	/* Index (base 0) into GDEF mark glyph sets
 					 * structure. This field is only present if bit
 					 * UseMarkFilteringSet of lookup flags is set. */
   public:
@@ -646,17 +689,18 @@ struct CoverageFormat1
     glyphArray.len.set (num_glyphs);
     if (unlikely (!c->extend (glyphArray))) return TRACE_RETURN (false);
     for (unsigned int i = 0; i < num_glyphs; i++)
       glyphArray[i] = glyphs[i];
     glyphs.advance (num_glyphs);
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (glyphArray.sanitize (c));
   }
 
   inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
     return glyphs->has (glyphArray[index]);
   }
 
@@ -732,17 +776,18 @@ struct CoverageFormat2
         rangeRecord[range].end = glyphs[i];
       } else {
         rangeRecord[range].end = glyphs[i];
       }
     glyphs.advance (num_glyphs);
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (rangeRecord.sanitize (c));
   }
 
   inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
     unsigned int i;
     unsigned int count = rangeRecord.len;
     for (i = 0; i < count; i++) {
@@ -827,17 +872,18 @@ struct Coverage
     u.format.set (num_glyphs * 2 < num_ranges * 3 ? 1 : 2);
     switch (u.format) {
     case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, num_glyphs));
     case 2: return TRACE_RETURN (u.format2.serialize (c, glyphs, num_glyphs));
     default:return TRACE_RETURN (false);
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return TRACE_RETURN (false);
     switch (u.format) {
     case 1: return TRACE_RETURN (u.format1.sanitize (c));
     case 2: return TRACE_RETURN (u.format2.sanitize (c));
     default:return TRACE_RETURN (true);
     }
   }
@@ -933,22 +979,24 @@ struct Coverage
 
 struct ClassDefFormat1
 {
   friend struct ClassDef;
 
   private:
   inline unsigned int get_class (hb_codepoint_t glyph_id) const
   {
-    if (unlikely ((unsigned int) (glyph_id - startGlyph) < classValue.len))
-      return classValue[glyph_id - startGlyph];
+    unsigned int i = (unsigned int) (glyph_id - startGlyph);
+    if (unlikely (i < classValue.len))
+      return classValue[i];
     return 0;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && classValue.sanitize (c));
   }
 
   template <typename set_t>
   inline void add_class (set_t *glyphs, unsigned int klass) const {
     unsigned int count = classValue.len;
     for (unsigned int i = 0; i < count; i++)
@@ -989,22 +1037,23 @@ struct ClassDefFormat1
 struct ClassDefFormat2
 {
   friend struct ClassDef;
 
   private:
   inline unsigned int get_class (hb_codepoint_t glyph_id) const
   {
     int i = rangeRecord.bsearch (glyph_id);
-    if (i != -1)
+    if (unlikely (i != -1))
       return rangeRecord[i].value;
     return 0;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (rangeRecord.sanitize (c));
   }
 
   template <typename set_t>
   inline void add_class (set_t *glyphs, unsigned int klass) const {
     unsigned int count = rangeRecord.len;
     for (unsigned int i = 0; i < count; i++)
@@ -1051,17 +1100,18 @@ struct ClassDef
   {
     switch (u.format) {
     case 1: return u.format1.get_class(glyph_id);
     case 2: return u.format2.get_class(glyph_id);
     default:return 0;
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return TRACE_RETURN (false);
     switch (u.format) {
     case 1: return TRACE_RETURN (u.format1.sanitize (c));
     case 2: return TRACE_RETURN (u.format2.sanitize (c));
     default:return TRACE_RETURN (true);
     }
   }
@@ -1143,17 +1193,18 @@ struct Device
 
   inline unsigned int get_size (void) const
   {
     unsigned int f = deltaFormat;
     if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::static_size;
     return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f)));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && c->check_range (this, this->get_size ()));
   }
 
   protected:
   USHORT	startSize;		/* Smallest size to correct--in ppem */
   USHORT	endSize;		/* Largest size to correct--in ppem */
   USHORT	deltaFormat;		/* Format of DeltaValue array data: 1, 2, or 3
--- a/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh
@@ -66,17 +66,18 @@ struct AttachList
       unsigned int count = *point_count;
       for (unsigned int i = 0; i < count; i++)
 	point_array[i] = array[i];
     }
 
     return points.len;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (coverage.sanitize (c, this) && attachPoint.sanitize (c, this));
   }
 
   protected:
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table -- from
 					 * beginning of AttachList table */
@@ -96,17 +97,18 @@ struct CaretValueFormat1
   friend struct CaretValue;
 
   private:
   inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const
   {
     return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this));
   }
 
   protected:
   USHORT	caretValueFormat;	/* Format identifier--format = 1 */
   SHORT		coordinate;		/* X or Y value, in design units */
   public:
@@ -122,17 +124,18 @@ struct CaretValueFormat2
   {
     hb_position_t x, y;
     if (font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y))
       return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
     else
       return 0;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this));
   }
 
   protected:
   USHORT	caretValueFormat;	/* Format identifier--format = 2 */
   USHORT	caretValuePoint;	/* Contour point index on glyph */
   public:
@@ -145,17 +148,18 @@ struct CaretValueFormat3
 
   inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const
   {
     return HB_DIRECTION_IS_HORIZONTAL (direction) ?
            font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font) :
            font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && deviceTable.sanitize (c, this));
   }
 
   protected:
   USHORT	caretValueFormat;	/* Format identifier--format = 3 */
   SHORT		coordinate;		/* X or Y value, in design units */
   OffsetTo<Device>
@@ -173,17 +177,18 @@ struct CaretValue
     switch (u.format) {
     case 1: return u.format1.get_caret_value (font, direction, glyph_id);
     case 2: return u.format2.get_caret_value (font, direction, glyph_id);
     case 3: return u.format3.get_caret_value (font, direction, glyph_id);
     default:return 0;
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return TRACE_RETURN (false);
     switch (u.format) {
     case 1: return TRACE_RETURN (u.format1.sanitize (c));
     case 2: return TRACE_RETURN (u.format2.sanitize (c));
     case 3: return TRACE_RETURN (u.format3.sanitize (c));
     default:return TRACE_RETURN (true);
     }
@@ -214,17 +219,18 @@ struct LigGlyph
       unsigned int count = *caret_count;
       for (unsigned int i = 0; i < count; i++)
 	caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id);
     }
 
     return carets.len;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (carets.sanitize (c, this));
   }
 
   protected:
   OffsetArrayOf<CaretValue>
 		carets;			/* Offset array of CaretValue tables
 					 * --from beginning of LigGlyph table
@@ -248,17 +254,18 @@ struct LigCaretList
       if (caret_count)
 	*caret_count = 0;
       return 0;
     }
     const LigGlyph &lig_glyph = this+ligGlyph[index];
     return lig_glyph.get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this));
   }
 
   protected:
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of LigCaretList table */
@@ -270,17 +277,18 @@ struct LigCaretList
 };
 
 
 struct MarkGlyphSetsFormat1
 {
   inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
   { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (coverage.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   ArrayOf<OffsetTo<Coverage, ULONG> >
 		coverage;		/* Array of long offsets to mark set
@@ -294,17 +302,18 @@ struct MarkGlyphSets
   inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
   {
     switch (u.format) {
     case 1: return u.format1.covers (set_index, glyph_id);
     default:return false;
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return TRACE_RETURN (false);
     switch (u.format) {
     case 1: return TRACE_RETURN (u.format1.sanitize (c));
     default:return TRACE_RETURN (true);
     }
   }
 
@@ -359,17 +368,18 @@ struct GDEF
 				      unsigned int *caret_count /* IN/OUT */,
 				      hb_position_t *caret_array /* OUT */) const
   { return (this+ligCaretList).get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); }
 
   inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef[0] != 0; }
   inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
   { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (version.sanitize (c) &&
 			 likely (version.major == 1) &&
 			 glyphClassDef.sanitize (c, this) &&
 			 attachList.sanitize (c, this) &&
 			 ligCaretList.sanitize (c, this) &&
 			 markAttachClassDef.sanitize (c, this) &&
 			 (version.to_int () < 0x00010002u || markGlyphSetsDef[0].sanitize (c, this)));
--- a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
@@ -141,17 +141,18 @@ struct ValueFormat : USHORT
     if (format & yAdvDevice) {
       /* y_advance values grow downward but font-space grows upward, hence negation */
       if (!horizontal && y_ppem) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font);
       values++;
     }
   }
 
   private:
-  inline bool sanitize_value_devices (hb_sanitize_context_t *c, void *base, Value *values) {
+  inline bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
+  {
     unsigned int format = *this;
 
     if (format & xPlacement) values++;
     if (format & yPlacement) values++;
     if (format & xAdvance)   values++;
     if (format & yAdvance)   values++;
 
     if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
@@ -172,22 +173,24 @@ struct ValueFormat : USHORT
 
   public:
 
   inline bool has_device (void) const {
     unsigned int format = *this;
     return (format & devices) != 0;
   }
 
-  inline bool sanitize_value (hb_sanitize_context_t *c, void *base, Value *values) {
+  inline bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
   }
 
-  inline bool sanitize_values (hb_sanitize_context_t *c, void *base, Value *values, unsigned int count) {
+  inline bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
+  {
     TRACE_SANITIZE (this);
     unsigned int len = get_len ();
 
     if (!c->check_array (values, get_size (), count)) return TRACE_RETURN (false);
 
     if (!has_device ()) return TRACE_RETURN (true);
 
     for (unsigned int i = 0; i < count; i++) {
@@ -195,17 +198,18 @@ struct ValueFormat : USHORT
         return TRACE_RETURN (false);
       values += len;
     }
 
     return TRACE_RETURN (true);
   }
 
   /* Just sanitize referenced Device tables.  Doesn't check the values themselves. */
-  inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, void *base, Value *values, unsigned int count, unsigned int stride) {
+  inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
+  {
     TRACE_SANITIZE (this);
 
     if (!has_device ()) return TRACE_RETURN (true);
 
     for (unsigned int i = 0; i < count; i++) {
       if (!sanitize_value_devices (c, base, values))
         return TRACE_RETURN (false);
       values += stride;
@@ -220,17 +224,18 @@ struct AnchorFormat1
 {
   inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
 			  hb_position_t *x, hb_position_t *y) const
   {
       *x = font->em_scale_x (xCoordinate);
       *y = font->em_scale_y (yCoordinate);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   SHORT		xCoordinate;		/* Horizontal value--in design units */
   SHORT		yCoordinate;		/* Vertical value--in design units */
@@ -249,17 +254,18 @@ struct AnchorFormat2
       hb_bool_t ret;
 
       ret = (x_ppem || y_ppem) &&
              font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
       *x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate);
       *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 2 */
   SHORT		xCoordinate;		/* Horizontal value--in design units */
   SHORT		yCoordinate;		/* Vertical value--in design units */
@@ -277,17 +283,18 @@ struct AnchorFormat3
       *y = font->em_scale_y (yCoordinate);
 
       if (font->x_ppem)
 	*x += (this+xDeviceTable).get_x_delta (font);
       if (font->y_ppem)
 	*y += (this+yDeviceTable).get_x_delta (font);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 3 */
   SHORT		xCoordinate;		/* Horizontal value--in design units */
   SHORT		yCoordinate;		/* Vertical value--in design units */
@@ -312,17 +319,18 @@ struct Anchor
     switch (u.format) {
     case 1: u.format1.get_anchor (font, glyph_id, x, y); return;
     case 2: u.format2.get_anchor (font, glyph_id, x, y); return;
     case 3: u.format3.get_anchor (font, glyph_id, x, y); return;
     default:						 return;
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return TRACE_RETURN (false);
     switch (u.format) {
     case 1: return TRACE_RETURN (u.format1.sanitize (c));
     case 2: return TRACE_RETURN (u.format2.sanitize (c));
     case 3: return TRACE_RETURN (u.format3.sanitize (c));
     default:return TRACE_RETURN (true);
     }
@@ -344,17 +352,18 @@ struct AnchorMatrix
 {
   inline const Anchor& get_anchor (unsigned int row, unsigned int col, unsigned int cols, bool *found) const {
     *found = false;
     if (unlikely (row >= rows || col >= cols)) return Null(Anchor);
     *found = !matrixZ[row * cols + col].is_null ();
     return this+matrixZ[row * cols + col];
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) {
+  inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
+  {
     TRACE_SANITIZE (this);
     if (!c->check_struct (this)) return TRACE_RETURN (false);
     if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return TRACE_RETURN (false);
     unsigned int count = rows * cols;
     if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return TRACE_RETURN (false);
     for (unsigned int i = 0; i < count; i++)
       if (!matrixZ[i].sanitize (c, this)) return TRACE_RETURN (false);
     return TRACE_RETURN (true);
@@ -369,17 +378,18 @@ struct AnchorMatrix
   DEFINE_SIZE_ARRAY (2, matrixZ);
 };
 
 
 struct MarkRecord
 {
   friend struct MarkArray;
 
-  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && markAnchor.sanitize (c, base));
   }
 
   protected:
   USHORT	klass;			/* Class defined for this mark */
   OffsetTo<Anchor>
 		markAnchor;		/* Offset to Anchor table--from
@@ -416,17 +426,18 @@ struct MarkArray : ArrayOf<MarkRecord>	/
     o.x_offset = base_x - mark_x;
     o.y_offset = base_y - mark_y;
     o.attach_lookback() = buffer->idx - glyph_pos;
 
     buffer->idx++;
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (ArrayOf<MarkRecord>::sanitize (c, this));
   }
 };
 
 
 /* Lookups */
 
@@ -452,19 +463,22 @@ struct SinglePosFormat1
 
     valueFormat.apply_value (c->font, c->direction, this,
 			     values, buffer->cur_pos());
 
     buffer->idx++;
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) && valueFormat.sanitize_value (c, this, values));
+    return TRACE_RETURN (c->check_struct (this)
+        && coverage.sanitize (c, this)
+	&& valueFormat.sanitize_value (c, this, values));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
   ValueFormat	valueFormat;		/* Defines the types of data in the
@@ -501,19 +515,22 @@ struct SinglePosFormat2
     valueFormat.apply_value (c->font, c->direction, this,
 			     &values[index * valueFormat.get_len ()],
 			     buffer->cur_pos());
 
     buffer->idx++;
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) && valueFormat.sanitize_values (c, this, values, valueCount));
+    return TRACE_RETURN (c->check_struct (this)
+	&& coverage.sanitize (c, this)
+	&& valueFormat.sanitize_values (c, this, values, valueCount));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 2 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
   ValueFormat	valueFormat;		/* Defines the types of data in the
@@ -526,33 +543,24 @@ struct SinglePosFormat2
 };
 
 struct SinglePos
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
     switch (u.format) {
     case 1: return TRACE_RETURN (c->dispatch (u.format1));
     case 2: return TRACE_RETURN (c->dispatch (u.format2));
     default:return TRACE_RETURN (c->default_return_value ());
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
-    switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    case 2: return TRACE_RETURN (u.format2.sanitize (c));
-    default:return TRACE_RETURN (true);
-    }
-  }
-
   protected:
   union {
   USHORT		format;		/* Format identifier */
   SinglePosFormat1	format1;
   SinglePosFormat2	format2;
   } u;
 };
 
@@ -597,52 +605,64 @@ struct PairSet
 		     unsigned int pos) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
     unsigned int len1 = valueFormats[0].get_len ();
     unsigned int len2 = valueFormats[1].get_len ();
     unsigned int record_size = USHORT::static_size * (1 + len1 + len2);
 
-    const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
+    const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ);
     unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
+
+    /* Hand-coded bsearch. */
+    if (unlikely (!count))
+      return TRACE_RETURN (false);
+    hb_codepoint_t x = buffer->info[pos].codepoint;
+    int min = 0, max = (int) count - 1;
+    while (min <= max)
     {
-      /* TODO bsearch */
-      if (buffer->info[pos].codepoint == record->secondGlyph)
+      int mid = (min + max) / 2;
+      const PairValueRecord *record = &StructAtOffset<PairValueRecord> (record_array, record_size * mid);
+      hb_codepoint_t mid_x = record->secondGlyph;
+      if (x < mid_x)
+        max = mid - 1;
+      else if (x > mid_x)
+        min = mid + 1;
+      else
       {
 	valueFormats[0].apply_value (c->font, c->direction, this,
 				     &record->values[0], buffer->cur_pos());
 	valueFormats[1].apply_value (c->font, c->direction, this,
 				     &record->values[len1], buffer->pos[pos]);
 	if (len2)
 	  pos++;
 	buffer->idx = pos;
 	return TRACE_RETURN (true);
       }
-      record = &StructAtOffset<PairValueRecord> (record, record_size);
     }
 
     return TRACE_RETURN (false);
   }
 
   struct sanitize_closure_t {
-    void *base;
-    ValueFormat *valueFormats;
+    const void *base;
+    const ValueFormat *valueFormats;
     unsigned int len1; /* valueFormats[0].get_len() */
     unsigned int stride; /* 1 + len1 + len2 */
   };
 
-  inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) {
+  inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
+  {
     TRACE_SANITIZE (this);
     if (!(c->check_struct (this)
        && c->check_array (arrayZ, USHORT::static_size * closure->stride, len))) return TRACE_RETURN (false);
 
     unsigned int count = len;
-    PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
+    const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
     return TRACE_RETURN (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride)
 		      && closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
   }
 
   protected:
   USHORT	len;			/* Number of PairValueRecords */
   USHORT	arrayZ[VAR];		/* Array of PairValueRecords--ordered
 					 * by GlyphID of the second glyph */
@@ -665,28 +685,28 @@ struct PairPosFormat1
   {
     return this+coverage;
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
-    hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, 1);
-    if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
-
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
 
+    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    skippy_iter.reset (buffer->idx, 1);
     if (!skippy_iter.next ()) return TRACE_RETURN (false);
 
     return TRACE_RETURN ((this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
 
     unsigned int len1 = valueFormat1.get_len ();
     unsigned int len2 = valueFormat2.get_len ();
     PairSet::sanitize_closure_t closure = {
       this,
       &valueFormat1,
       len1,
@@ -736,22 +756,21 @@ struct PairPosFormat2
   {
     return this+coverage;
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
-    hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, 1);
-    if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
-
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
 
+    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    skippy_iter.reset (buffer->idx, 1);
     if (!skippy_iter.next ()) return TRACE_RETURN (false);
 
     unsigned int len1 = valueFormat1.get_len ();
     unsigned int len2 = valueFormat2.get_len ();
     unsigned int record_len = len1 + len2;
 
     unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
     unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
@@ -765,17 +784,18 @@ struct PairPosFormat2
 
     buffer->idx = skippy_iter.idx;
     if (len2)
       buffer->idx++;
 
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (!(c->check_struct (this)
        && coverage.sanitize (c, this)
        && classDef1.sanitize (c, this)
        && classDef2.sanitize (c, this))) return TRACE_RETURN (false);
 
     unsigned int len1 = valueFormat1.get_len ();
     unsigned int len2 = valueFormat2.get_len ();
@@ -818,47 +838,39 @@ struct PairPosFormat2
 };
 
 struct PairPos
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
     switch (u.format) {
     case 1: return TRACE_RETURN (c->dispatch (u.format1));
     case 2: return TRACE_RETURN (c->dispatch (u.format2));
     default:return TRACE_RETURN (c->default_return_value ());
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
-    switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    case 2: return TRACE_RETURN (u.format2.sanitize (c));
-    default:return TRACE_RETURN (true);
-    }
-  }
-
   protected:
   union {
   USHORT		format;		/* Format identifier */
   PairPosFormat1	format1;
   PairPosFormat2	format2;
   } u;
 };
 
 
 struct EntryExitRecord
 {
   friend struct CursivePosFormat1;
 
-  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
   }
 
   protected:
   OffsetTo<Anchor>
 		entryAnchor;		/* Offset to EntryAnchor table--from
 					 * beginning of CursivePos
@@ -887,22 +899,21 @@ struct CursivePosFormat1
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
 
     /* We don't handle mark glyphs here. */
     if (unlikely (_hb_glyph_info_is_mark (&buffer->cur()))) return TRACE_RETURN (false);
 
-    hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, 1);
-    if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
-
     const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage  (buffer->cur().codepoint)];
     if (!this_record.exitAnchor) return TRACE_RETURN (false);
 
+    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    skippy_iter.reset (buffer->idx, 1);
     if (!skippy_iter.next ()) return TRACE_RETURN (false);
 
     const EntryExitRecord &next_record = entryExitRecord[(this+coverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint)];
     if (!next_record.entryAnchor) return TRACE_RETURN (false);
 
     unsigned int i = buffer->idx;
     unsigned int j = skippy_iter.idx;
 
@@ -962,17 +973,18 @@ struct CursivePosFormat1
       else
 	pos[j].x_offset = exit_x - entry_x;
     }
 
     buffer->idx = j;
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
@@ -985,31 +997,23 @@ struct CursivePosFormat1
 };
 
 struct CursivePos
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
     switch (u.format) {
     case 1: return TRACE_RETURN (c->dispatch (u.format1));
     default:return TRACE_RETURN (c->default_return_value ());
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
-    switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    default:return TRACE_RETURN (true);
-    }
-  }
-
   protected:
   union {
   USHORT		format;		/* Format identifier */
   CursivePosFormat1	format1;
   } u;
 };
 
 
@@ -1035,17 +1039,18 @@ struct MarkBasePosFormat1
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
     unsigned int mark_index = (this+markCoverage).get_coverage  (buffer->cur().codepoint);
     if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false);
 
     /* now we search backwards for a non-mark glyph */
-    hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, buffer->idx, 1);
+    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    skippy_iter.reset (buffer->idx, 1);
     skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
     do {
       if (!skippy_iter.prev ()) return TRACE_RETURN (false);
       /* We only want to attach to the first of a MultipleSubst sequence.  Reject others. */
       if (0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx])) break;
       skippy_iter.reject ();
     } while (1);
 
@@ -1053,17 +1058,18 @@ struct MarkBasePosFormat1
     if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { /*return TRACE_RETURN (false);*/ }
 
     unsigned int base_index = (this+baseCoverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint);
     if (base_index == NOT_COVERED) return TRACE_RETURN (false);
 
     return TRACE_RETURN ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, this) && baseCoverage.sanitize (c, this) &&
 			 markArray.sanitize (c, this) && baseArray.sanitize (c, this, (unsigned int) classCount));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
@@ -1084,31 +1090,23 @@ struct MarkBasePosFormat1
 };
 
 struct MarkBasePos
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
     switch (u.format) {
     case 1: return TRACE_RETURN (c->dispatch (u.format1));
     default:return TRACE_RETURN (c->default_return_value ());
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
-    switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    default:return TRACE_RETURN (true);
-    }
-  }
-
   protected:
   union {
   USHORT		format;		/* Format identifier */
   MarkBasePosFormat1	format1;
   } u;
 };
 
 
@@ -1139,17 +1137,18 @@ struct MarkLigPosFormat1
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
     unsigned int mark_index = (this+markCoverage).get_coverage  (buffer->cur().codepoint);
     if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false);
 
     /* now we search backwards for a non-mark glyph */
-    hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, buffer->idx, 1);
+    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    skippy_iter.reset (buffer->idx, 1);
     skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
     if (!skippy_iter.prev ()) return TRACE_RETURN (false);
 
     /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
     if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { /*return TRACE_RETURN (false);*/ }
 
     unsigned int j = skippy_iter.idx;
     unsigned int lig_index = (this+ligatureCoverage).get_coverage  (buffer->info[j].codepoint);
@@ -1173,17 +1172,18 @@ struct MarkLigPosFormat1
     if (lig_id && lig_id == mark_id && mark_comp > 0)
       comp_index = MIN (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
     else
       comp_index = comp_count - 1;
 
     return TRACE_RETURN ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, this) && ligatureCoverage.sanitize (c, this) &&
 			 markArray.sanitize (c, this) && ligatureArray.sanitize (c, this, (unsigned int) classCount));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
@@ -1205,31 +1205,23 @@ struct MarkLigPosFormat1
 };
 
 struct MarkLigPos
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
     switch (u.format) {
     case 1: return TRACE_RETURN (c->dispatch (u.format1));
     default:return TRACE_RETURN (c->default_return_value ());
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
-    switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    default:return TRACE_RETURN (true);
-    }
-  }
-
   protected:
   union {
   USHORT		format;		/* Format identifier */
   MarkLigPosFormat1	format1;
   } u;
 };
 
 
@@ -1255,17 +1247,18 @@ struct MarkMarkPosFormat1
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
     unsigned int mark1_index = (this+mark1Coverage).get_coverage  (buffer->cur().codepoint);
     if (likely (mark1_index == NOT_COVERED)) return TRACE_RETURN (false);
 
     /* now we search backwards for a suitable mark glyph until a non-mark glyph */
-    hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, buffer->idx, 1);
+    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    skippy_iter.reset (buffer->idx, 1);
     skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags);
     if (!skippy_iter.prev ()) return TRACE_RETURN (false);
 
     if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) { return TRACE_RETURN (false); }
 
     unsigned int j = skippy_iter.idx;
 
     unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur());
@@ -1290,17 +1283,18 @@ struct MarkMarkPosFormat1
 
     good:
     unsigned int mark2_index = (this+mark2Coverage).get_coverage  (buffer->info[j].codepoint);
     if (mark2_index == NOT_COVERED) return TRACE_RETURN (false);
 
     return TRACE_RETURN ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && mark1Coverage.sanitize (c, this) &&
 			 mark2Coverage.sanitize (c, this) && mark1Array.sanitize (c, this)
 			 && mark2Array.sanitize (c, this, (unsigned int) classCount));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
@@ -1324,31 +1318,23 @@ struct MarkMarkPosFormat1
 };
 
 struct MarkMarkPos
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
     switch (u.format) {
     case 1: return TRACE_RETURN (c->dispatch (u.format1));
     default:return TRACE_RETURN (c->default_return_value ());
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
-    switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    default:return TRACE_RETURN (true);
-    }
-  }
-
   protected:
   union {
   USHORT		format;		/* Format identifier */
   MarkMarkPosFormat1	format1;
   } u;
 };
 
 
@@ -1383,132 +1369,93 @@ struct PosLookupSubTable
     ChainContext	= 8,
     Extension		= 9
   };
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
   {
     TRACE_DISPATCH (this, lookup_type);
+    /* The sub_format passed to may_dispatch is unnecessary but harmless. */
+    if (unlikely (!c->may_dispatch (this, &u.sub_format))) TRACE_RETURN (c->default_return_value ());
     switch (lookup_type) {
     case Single:		return TRACE_RETURN (u.single.dispatch (c));
     case Pair:			return TRACE_RETURN (u.pair.dispatch (c));
     case Cursive:		return TRACE_RETURN (u.cursive.dispatch (c));
     case MarkBase:		return TRACE_RETURN (u.markBase.dispatch (c));
     case MarkLig:		return TRACE_RETURN (u.markLig.dispatch (c));
     case MarkMark:		return TRACE_RETURN (u.markMark.dispatch (c));
     case Context:		return TRACE_RETURN (u.context.dispatch (c));
     case ChainContext:		return TRACE_RETURN (u.chainContext.dispatch (c));
     case Extension:		return TRACE_RETURN (u.extension.dispatch (c));
     default:			return TRACE_RETURN (c->default_return_value ());
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) {
-    TRACE_SANITIZE (this);
-    if (!u.header.sub_format.sanitize (c))
-      return TRACE_RETURN (false);
-    switch (lookup_type) {
-    case Single:		return TRACE_RETURN (u.single.sanitize (c));
-    case Pair:			return TRACE_RETURN (u.pair.sanitize (c));
-    case Cursive:		return TRACE_RETURN (u.cursive.sanitize (c));
-    case MarkBase:		return TRACE_RETURN (u.markBase.sanitize (c));
-    case MarkLig:		return TRACE_RETURN (u.markLig.sanitize (c));
-    case MarkMark:		return TRACE_RETURN (u.markMark.sanitize (c));
-    case Context:		return TRACE_RETURN (u.context.sanitize (c));
-    case ChainContext:		return TRACE_RETURN (u.chainContext.sanitize (c));
-    case Extension:		return TRACE_RETURN (u.extension.sanitize (c));
-    default:			return TRACE_RETURN (true);
-    }
-  }
-
   protected:
   union {
-  struct {
-    USHORT		sub_format;
-  } header;
+  USHORT		sub_format;
   SinglePos		single;
   PairPos		pair;
   CursivePos		cursive;
   MarkBasePos		markBase;
   MarkLigPos		markLig;
   MarkMarkPos		markMark;
   ContextPos		context;
   ChainContextPos	chainContext;
   ExtensionPos		extension;
   } u;
   public:
-  DEFINE_SIZE_UNION (2, header.sub_format);
+  DEFINE_SIZE_UNION (2, sub_format);
 };
 
 
 struct PosLookup : Lookup
 {
   inline const PosLookupSubTable& get_subtable (unsigned int i) const
-  { return this+CastR<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; }
+  { return Lookup::get_subtable<PosLookupSubTable> (i); }
 
   inline bool is_reverse (void) const
   {
     return false;
   }
 
+  inline bool apply (hb_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    return TRACE_RETURN (dispatch (c));
+  }
+
   inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
-    c->set_recurse_func (NULL);
     return TRACE_RETURN (dispatch (c));
   }
 
   template <typename set_t>
   inline void add_coverage (set_t *glyphs) const
   {
-    hb_get_coverage_context_t c;
-    const Coverage *last = NULL;
-    unsigned int count = get_subtable_count ();
-    for (unsigned int i = 0; i < count; i++) {
-      const Coverage *coverage = &get_subtable (i).dispatch (&c, get_type ());
-      if (coverage != last) {
-        coverage->add_coverage (glyphs);
-        last = coverage;
-      }
-    }
-  }
-
-  inline bool apply_once (hb_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props))
-      return TRACE_RETURN (false);
-    return TRACE_RETURN (dispatch (c));
+    hb_add_coverage_context_t<set_t> c (glyphs);
+    dispatch (&c);
   }
 
   static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index);
 
   template <typename context_t>
   static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
+  { return Lookup::dispatch<PosLookupSubTable> (c); }
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
   {
-    unsigned int lookup_type = get_type ();
-    TRACE_DISPATCH (this, lookup_type);
-    unsigned int count = get_subtable_count ();
-    for (unsigned int i = 0; i < count; i++) {
-      typename context_t::return_t r = get_subtable (i).dispatch (c, lookup_type);
-      if (c->stop_sublookup_iteration (r))
-        return TRACE_RETURN (r);
-    }
-    return TRACE_RETURN (c->default_return_value ());
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) {
     TRACE_SANITIZE (this);
     if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false);
-    OffsetArrayOf<PosLookupSubTable> &list = CastR<OffsetArrayOf<PosLookupSubTable> > (subTable);
-    return TRACE_RETURN (list.sanitize (c, this, get_type ()));
+    return TRACE_RETURN (dispatch (c));
   }
 };
 
 typedef OffsetListOf<PosLookup> PosLookupList;
 
 /*
  * GPOS -- The Glyph Positioning Table
  */
@@ -1518,20 +1465,21 @@ struct GPOS : GSUBGPOS
   static const hb_tag_t tableTag	= HB_OT_TAG_GPOS;
 
   inline const PosLookup& get_lookup (unsigned int i) const
   { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); }
 
   static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
   static inline void position_finish (hb_font_t *font, hb_buffer_t *buffer);
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false);
-    OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList);
+    const OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList);
     return TRACE_RETURN (list.sanitize (c, this));
   }
   public:
   DEFINE_SIZE_STATIC (10);
 };
 
 
 static void
@@ -1616,18 +1564,18 @@ template <typename context_t>
 }
 
 /*static*/ inline bool PosLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index)
 {
   const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
   const PosLookup &l = gpos.get_lookup (lookup_index);
   unsigned int saved_lookup_props = c->lookup_props;
   c->set_lookup (l);
-  bool ret = l.apply_once (c);
-  c->lookup_props = saved_lookup_props;
+  bool ret = l.dispatch (c);
+  c->set_lookup_props (saved_lookup_props);
   return ret;
 }
 
 
 #undef attach_lookback
 #undef cursive_chain
 
 
--- a/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh
@@ -92,17 +92,18 @@ struct SingleSubstFormat1
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
     if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
     deltaGlyphID.set (delta); /* TODO(serilaize) overflow? */
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
@@ -168,17 +169,18 @@ struct SingleSubstFormat2
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
     if (unlikely (!substitute.serialize (c, substitutes, num_glyphs))) return TRACE_RETURN (false);
     if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (coverage.sanitize (c, this) && substitute.sanitize (c));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 2 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
@@ -218,33 +220,24 @@ struct SingleSubst
     default:return TRACE_RETURN (false);
     }
   }
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
     switch (u.format) {
     case 1: return TRACE_RETURN (c->dispatch (u.format1));
     case 2: return TRACE_RETURN (c->dispatch (u.format2));
     default:return TRACE_RETURN (c->default_return_value ());
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
-    switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    case 2: return TRACE_RETURN (u.format2.sanitize (c));
-    default:return TRACE_RETURN (true);
-    }
-  }
-
   protected:
   union {
   USHORT		format;		/* Format identifier */
   SingleSubstFormat1	format1;
   SingleSubstFormat2	format2;
   } u;
 };
 
@@ -307,17 +300,18 @@ struct Sequence
 			 unsigned int num_glyphs)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
     if (unlikely (!substitute.serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (substitute.sanitize (c));
   }
 
   protected:
   ArrayOf<GlyphID>
 		substitute;		/* String of GlyphIDs to substitute */
   public:
@@ -379,17 +373,18 @@ struct MultipleSubstFormat1
       if (unlikely (!sequence[i].serialize (c, this).serialize (c,
 								substitute_glyphs_list,
 								substitute_len_list[i]))) return TRACE_RETURN (false);
     substitute_len_list.advance (num_glyphs);
     if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (coverage.sanitize (c, this) && sequence.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
@@ -418,31 +413,23 @@ struct MultipleSubst
     default:return TRACE_RETURN (false);
     }
   }
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
     switch (u.format) {
     case 1: return TRACE_RETURN (c->dispatch (u.format1));
     default:return TRACE_RETURN (c->default_return_value ());
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
-    switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    default:return TRACE_RETURN (true);
-    }
-  }
-
   protected:
   union {
   USHORT		format;		/* Format identifier */
   MultipleSubstFormat1	format1;
   } u;
 };
 
 
@@ -530,17 +517,18 @@ struct AlternateSubstFormat1
       if (unlikely (!alternateSet[i].serialize (c, this).serialize (c,
 								    alternate_glyphs_list,
 								    alternate_len_list[i]))) return TRACE_RETURN (false);
     alternate_len_list.advance (num_glyphs);
     if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
@@ -569,31 +557,23 @@ struct AlternateSubst
     default:return TRACE_RETURN (false);
     }
   }
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
     switch (u.format) {
     case 1: return TRACE_RETURN (c->dispatch (u.format1));
     default:return TRACE_RETURN (c->default_return_value ());
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
-    switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    default:return TRACE_RETURN (true);
-    }
-  }
-
   protected:
   union {
   USHORT		format;		/* Format identifier */
   AlternateSubstFormat1	format1;
   } u;
 };
 
 
@@ -681,17 +661,18 @@ struct Ligature
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
     ligGlyph = ligature;
     if (unlikely (!component.serialize (c, components, num_components))) return TRACE_RETURN (false);
     return TRACE_RETURN (true);
   }
 
   public:
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (ligGlyph.sanitize (c) && component.sanitize (c));
   }
 
   protected:
   GlyphID	ligGlyph;		/* GlyphID of ligature to substitute */
   HeadlessArrayOf<GlyphID>
 		component;		/* Array of component GlyphIDs--start
@@ -759,17 +740,18 @@ struct LigatureSet
 								ligatures[i],
 								component_list,
 								component_count_list[i]))) return TRACE_RETURN (false);
     ligatures.advance (num_ligatures);
     component_count_list.advance (num_ligatures);
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (ligature.sanitize (c, this));
   }
 
   protected:
   OffsetArrayOf<Ligature>
 		ligature;		/* Array LigatureSet tables
 					 * ordered by preference */
@@ -843,17 +825,18 @@ struct LigatureSubstFormat1
 								   component_count_list,
 								   ligature_per_first_glyph_count_list[i],
 								   component_list))) return TRACE_RETURN (false);
     ligature_per_first_glyph_count_list.advance (num_first_glyphs);
     if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_first_glyphs))) return TRACE_RETURN (false);
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
@@ -885,31 +868,23 @@ struct LigatureSubst
     default:return TRACE_RETURN (false);
     }
   }
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
     switch (u.format) {
     case 1: return TRACE_RETURN (c->dispatch (u.format1));
     default:return TRACE_RETURN (c->default_return_value ());
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
-    switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    default:return TRACE_RETURN (true);
-    }
-  }
-
   protected:
   union {
   USHORT		format;		/* Format identifier */
   LigatureSubstFormat1	format1;
   } u;
 };
 
 
@@ -1012,24 +987,25 @@ struct ReverseChainSingleSubstFormat1
        * for us.  This is useful for preventing surprises if someone
        * calls us through a Context lookup. */
       return TRACE_RETURN (true);
     }
 
     return TRACE_RETURN (false);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
       return TRACE_RETURN (false);
-    OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
     if (!lookahead.sanitize (c, this))
       return TRACE_RETURN (false);
-    ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
+    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
     return TRACE_RETURN (substitute.sanitize (c));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
@@ -1049,31 +1025,23 @@ struct ReverseChainSingleSubstFormat1
 };
 
 struct ReverseChainSingleSubst
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
     switch (u.format) {
     case 1: return TRACE_RETURN (c->dispatch (u.format1));
     default:return TRACE_RETURN (c->default_return_value ());
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
-    switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    default:return TRACE_RETURN (true);
-    }
-  }
-
   protected:
   union {
   USHORT				format;		/* Format identifier */
   ReverseChainSingleSubstFormat1	format1;
   } u;
 };
 
 
@@ -1096,81 +1064,70 @@ struct SubstLookupSubTable
     Extension		= 7,
     ReverseChainSingle	= 8
   };
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
   {
     TRACE_DISPATCH (this, lookup_type);
+    /* The sub_format passed to may_dispatch is unnecessary but harmless. */
+    if (unlikely (!c->may_dispatch (this, &u.sub_format))) TRACE_RETURN (c->default_return_value ());
     switch (lookup_type) {
     case Single:		return TRACE_RETURN (u.single.dispatch (c));
     case Multiple:		return TRACE_RETURN (u.multiple.dispatch (c));
     case Alternate:		return TRACE_RETURN (u.alternate.dispatch (c));
     case Ligature:		return TRACE_RETURN (u.ligature.dispatch (c));
     case Context:		return TRACE_RETURN (u.context.dispatch (c));
     case ChainContext:		return TRACE_RETURN (u.chainContext.dispatch (c));
     case Extension:		return TRACE_RETURN (u.extension.dispatch (c));
     case ReverseChainSingle:	return TRACE_RETURN (u.reverseChainContextSingle.dispatch (c));
     default:			return TRACE_RETURN (c->default_return_value ());
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) {
-    TRACE_SANITIZE (this);
-    if (!u.header.sub_format.sanitize (c))
-      return TRACE_RETURN (false);
-    switch (lookup_type) {
-    case Single:		return TRACE_RETURN (u.single.sanitize (c));
-    case Multiple:		return TRACE_RETURN (u.multiple.sanitize (c));
-    case Alternate:		return TRACE_RETURN (u.alternate.sanitize (c));
-    case Ligature:		return TRACE_RETURN (u.ligature.sanitize (c));
-    case Context:		return TRACE_RETURN (u.context.sanitize (c));
-    case ChainContext:		return TRACE_RETURN (u.chainContext.sanitize (c));
-    case Extension:		return TRACE_RETURN (u.extension.sanitize (c));
-    case ReverseChainSingle:	return TRACE_RETURN (u.reverseChainContextSingle.sanitize (c));
-    default:			return TRACE_RETURN (true);
-    }
-  }
-
   protected:
   union {
-  struct {
-    USHORT			sub_format;
-  } header;
+  USHORT			sub_format;
   SingleSubst			single;
   MultipleSubst			multiple;
   AlternateSubst		alternate;
   LigatureSubst			ligature;
   ContextSubst			context;
   ChainContextSubst		chainContext;
   ExtensionSubst		extension;
   ReverseChainSingleSubst	reverseChainContextSingle;
   } u;
   public:
-  DEFINE_SIZE_UNION (2, header.sub_format);
+  DEFINE_SIZE_UNION (2, sub_format);
 };
 
 
 struct SubstLookup : Lookup
 {
   inline const SubstLookupSubTable& get_subtable (unsigned int i) const
-  { return this+CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable)[i]; }
+  { return Lookup::get_subtable<SubstLookupSubTable> (i); }
 
   inline static bool lookup_type_is_reverse (unsigned int lookup_type)
   { return lookup_type == SubstLookupSubTable::ReverseChainSingle; }
 
   inline bool is_reverse (void) const
   {
     unsigned int type = get_type ();
     if (unlikely (type == SubstLookupSubTable::Extension))
       return CastR<ExtensionSubst> (get_subtable(0)).is_reverse ();
     return lookup_type_is_reverse (type);
   }
 
+  inline bool apply (hb_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    return TRACE_RETURN (dispatch (c));
+  }
+
   inline hb_closure_context_t::return_t closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
     c->set_recurse_func (dispatch_recurse_func<hb_closure_context_t>);
     return TRACE_RETURN (dispatch (c));
   }
 
   inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
@@ -1178,49 +1135,34 @@ struct SubstLookup : Lookup
     TRACE_COLLECT_GLYPHS (this);
     c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
     return TRACE_RETURN (dispatch (c));
   }
 
   template <typename set_t>
   inline void add_coverage (set_t *glyphs) const
   {
-    hb_get_coverage_context_t c;
-    const Coverage *last = NULL;
-    unsigned int count = get_subtable_count ();
-    for (unsigned int i = 0; i < count; i++) {
-      const Coverage *coverage = &get_subtable (i).dispatch (&c, get_type ());
-      if (coverage != last) {
-        coverage->add_coverage (glyphs);
-        last = coverage;
-      }
-    }
+    hb_add_coverage_context_t<set_t> c (glyphs);
+    dispatch (&c);
   }
 
-  inline bool would_apply (hb_would_apply_context_t *c, const hb_set_digest_t *digest) const
+  inline bool would_apply (hb_would_apply_context_t *c,
+			   const hb_ot_layout_lookup_accelerator_t *accel) const
   {
     TRACE_WOULD_APPLY (this);
     if (unlikely (!c->len))  return TRACE_RETURN (false);
-    if (!digest->may_have (c->glyphs[0]))  return TRACE_RETURN (false);
+    if (!accel->may_have (c->glyphs[0]))  return TRACE_RETURN (false);
       return TRACE_RETURN (dispatch (c));
   }
 
-  inline bool apply_once (hb_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props))
-      return TRACE_RETURN (false);
-    return TRACE_RETURN (dispatch (c));
-  }
-
   static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index);
 
   inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c,
 						  unsigned int i)
-  { return CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable)[i].serialize (c, this); }
+  { return get_subtables<SubstLookupSubTable> ()[i].serialize (c, this); }
 
   inline bool serialize_single (hb_serialize_context_t *c,
 				uint32_t lookup_props,
 			        Supplier<GlyphID> &glyphs,
 			        Supplier<GlyphID> &substitutes,
 			        unsigned int num_glyphs)
   {
     TRACE_SERIALIZE (this);
@@ -1269,34 +1211,23 @@ struct SubstLookup : Lookup
 									 ligatures_list, component_count_list, component_list));
   }
 
   template <typename context_t>
   static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    unsigned int lookup_type = get_type ();
-    TRACE_DISPATCH (this, lookup_type);
-    unsigned int count = get_subtable_count ();
-    for (unsigned int i = 0; i < count; i++) {
-      typename context_t::return_t r = get_subtable (i).dispatch (c, lookup_type);
-      if (c->stop_sublookup_iteration (r))
-        return TRACE_RETURN (r);
-    }
-    return TRACE_RETURN (c->default_return_value ());
-  }
+  { return Lookup::dispatch<SubstLookupSubTable> (c); }
 
-  inline bool sanitize (hb_sanitize_context_t *c)
+  inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false);
-    OffsetArrayOf<SubstLookupSubTable> &list = CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable);
-    if (unlikely (!list.sanitize (c, this, get_type ()))) return TRACE_RETURN (false);
+    if (unlikely (!dispatch (c))) return TRACE_RETURN (false);
 
     if (unlikely (get_type () == SubstLookupSubTable::Extension))
     {
       /* The spec says all subtables of an Extension lookup should
        * have the same type.  This is specially important if one has
        * a reverse type! */
       unsigned int type = get_subtable (0).u.extension.get_type ();
       unsigned int count = get_subtable_count ();
@@ -1319,20 +1250,21 @@ struct GSUB : GSUBGPOS
   static const hb_tag_t tableTag	= HB_OT_TAG_GSUB;
 
   inline const SubstLookup& get_lookup (unsigned int i) const
   { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
 
   static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer);
   static inline void substitute_finish (hb_font_t *font, hb_buffer_t *buffer);
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false);
-    OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupList);
+    const OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupList);
     return TRACE_RETURN (list.sanitize (c, this));
   }
   public:
   DEFINE_SIZE_STATIC (10);
 };
 
 
 void
@@ -1357,17 +1289,17 @@ GSUB::substitute_finish (hb_font_t *font
 
 
 /* Out-of-class implementation for methods recursing */
 
 /*static*/ inline bool ExtensionSubst::is_reverse (void) const
 {
   unsigned int type = get_type ();
   if (unlikely (type == SubstLookupSubTable::Extension))
-    return CastR<ExtensionSubst> (get_subtable<SubstLookupSubTable>()).is_reverse ();
+    return CastR<ExtensionSubst> (get_subtable<LookupSubTable>()).is_reverse ();
   return SubstLookup::lookup_type_is_reverse (type);
 }
 
 template <typename context_t>
 /*static*/ inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
 {
   const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
   const SubstLookup &l = gsub.get_lookup (lookup_index);
@@ -1375,18 +1307,18 @@ template <typename context_t>
 }
 
 /*static*/ inline bool SubstLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index)
 {
   const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
   const SubstLookup &l = gsub.get_lookup (lookup_index);
   unsigned int saved_lookup_props = c->lookup_props;
   c->set_lookup (l);
-  bool ret = l.apply_once (c);
-  c->lookup_props = saved_lookup_props;
+  bool ret = l.dispatch (c);
+  c->set_lookup_props (saved_lookup_props);
   return ret;
 }
 
 
 } /* namespace OT */
 
 
 #endif /* HB_OT_LAYOUT_GSUB_TABLE_HH */
--- a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh
@@ -32,37 +32,33 @@
 #include "hb-buffer-private.hh"
 #include "hb-ot-layout-gdef-table.hh"
 #include "hb-set-private.hh"
 
 
 namespace OT {
 
 
-
-#define TRACE_DISPATCH(this, format) \
-	hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
-	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
-	 "format %d", (int) format);
-
 #ifndef HB_DEBUG_CLOSURE
 #define HB_DEBUG_CLOSURE (HB_DEBUG+0)
 #endif
 
 #define TRACE_CLOSURE(this) \
 	hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
 	 "");
 
 struct hb_closure_context_t
 {
   inline const char *get_name (void) { return "CLOSURE"; }
   static const unsigned int max_debug_depth = HB_DEBUG_CLOSURE;
   typedef hb_void_t return_t;
   typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
+  template <typename T, typename F>
+  inline bool may_dispatch (const T *obj, const F *format) { return true; }
   template <typename T>
   inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
   static return_t default_return_value (void) { return HB_VOID; }
   bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
   return_t recurse (unsigned int lookup_index)
   {
     if (unlikely (nesting_level_left == 0 || !recurse_func))
       return default_return_value ();
@@ -102,16 +98,18 @@ struct hb_closure_context_t
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
 	 "%d glyphs", c->len);
 
 struct hb_would_apply_context_t
 {
   inline const char *get_name (void) { return "WOULD_APPLY"; }
   static const unsigned int max_debug_depth = HB_DEBUG_WOULD_APPLY;
   typedef bool return_t;
+  template <typename T, typename F>
+  inline bool may_dispatch (const T *obj, const F *format) { return true; }
   template <typename T>
   inline return_t dispatch (const T &obj) { return obj.would_apply (this); }
   static return_t default_return_value (void) { return false; }
   bool stop_sublookup_iteration (return_t r) const { return r; }
 
   hb_face_t *face;
   const hb_codepoint_t *glyphs;
   unsigned int len;
@@ -141,16 +139,18 @@ struct hb_would_apply_context_t
 	 "");
 
 struct hb_collect_glyphs_context_t
 {
   inline const char *get_name (void) { return "COLLECT_GLYPHS"; }
   static const unsigned int max_debug_depth = HB_DEBUG_COLLECT_GLYPHS;
   typedef hb_void_t return_t;
   typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
+  template <typename T, typename F>
+  inline bool may_dispatch (const T *obj, const F *format) { return true; }
   template <typename T>
   inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
   static return_t default_return_value (void) { return HB_VOID; }
   bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
   return_t recurse (unsigned int lookup_index)
   {
     if (unlikely (nesting_level_left == 0 || !recurse_func))
       return default_return_value ();
@@ -227,99 +227,54 @@ struct hb_collect_glyphs_context_t
 };
 
 
 
 #ifndef HB_DEBUG_GET_COVERAGE
 #define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0)
 #endif
 
-struct hb_get_coverage_context_t
+template <typename set_t>
+struct hb_add_coverage_context_t
 {
   inline const char *get_name (void) { return "GET_COVERAGE"; }
   static const unsigned int max_debug_depth = HB_DEBUG_GET_COVERAGE;
   typedef const Coverage &return_t;
+  template <typename T, typename F>
+  inline bool may_dispatch (const T *obj, const F *format) { return true; }
   template <typename T>
   inline return_t dispatch (const T &obj) { return obj.get_coverage (); }
   static return_t default_return_value (void) { return Null(Coverage); }
+  bool stop_sublookup_iteration (return_t r) const
+  {
+    r.add_coverage (set);
+    return false;
+  }
 
-  hb_get_coverage_context_t (void) :
+  hb_add_coverage_context_t (set_t *set_) :
+			    set (set_),
 			    debug_depth (0) {}
 
+  set_t *set;
   unsigned int debug_depth;
 };
 
 
 
 #ifndef HB_DEBUG_APPLY
 #define HB_DEBUG_APPLY (HB_DEBUG+0)
 #endif
 
 #define TRACE_APPLY(this) \
 	hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
 	 "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint);
 
 struct hb_apply_context_t
 {
-  inline const char *get_name (void) { return "APPLY"; }
-  static const unsigned int max_debug_depth = HB_DEBUG_APPLY;
-  typedef bool return_t;
-  typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.apply (this); }
-  static return_t default_return_value (void) { return false; }
-  bool stop_sublookup_iteration (return_t r) const { return r; }
-  return_t recurse (unsigned int lookup_index)
-  {
-    if (unlikely (nesting_level_left == 0 || !recurse_func))
-      return default_return_value ();
-
-    nesting_level_left--;
-    bool ret = recurse_func (this, lookup_index);
-    nesting_level_left++;
-    return ret;
-  }
-
-  unsigned int table_index; /* GSUB/GPOS */
-  hb_font_t *font;
-  hb_face_t *face;
-  hb_buffer_t *buffer;
-  hb_direction_t direction;
-  hb_mask_t lookup_mask;
-  bool auto_zwj;
-  recurse_func_t recurse_func;
-  unsigned int nesting_level_left;
-  unsigned int lookup_props;
-  const GDEF &gdef;
-  bool has_glyph_classes;
-  unsigned int debug_depth;
-
-
-  hb_apply_context_t (unsigned int table_index_,
-		      hb_font_t *font_,
-		      hb_buffer_t *buffer_) :
-			table_index (table_index_),
-			font (font_), face (font->face), buffer (buffer_),
-			direction (buffer_->props.direction),
-			lookup_mask (1),
-			auto_zwj (true),
-			recurse_func (NULL),
-			nesting_level_left (MAX_NESTING_LEVEL),
-			lookup_props (0),
-			gdef (*hb_ot_layout_from_face (face)->gdef),
-			has_glyph_classes (gdef.has_glyph_classes ()),
-			debug_depth (0) {}
-
-  inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; }
-  inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; }
-  inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
-  inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
-  inline void set_lookup (const Lookup &l) { lookup_props = l.get_props (); }
-
   struct matcher_t
   {
     inline matcher_t (void) :
 	     lookup_props (0),
 	     ignore_zwnj (false),
 	     ignore_zwj (false),
 	     mask (-1),
 #define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
@@ -385,53 +340,57 @@ struct hb_apply_context_t
     bool ignore_zwnj;
     bool ignore_zwj;
     hb_mask_t mask;
     uint8_t syllable;
     match_func_t match_func;
     const void *match_data;
   };
 
-  struct skipping_forward_iterator_t
+  struct skipping_iterator_t
   {
-    inline skipping_forward_iterator_t (hb_apply_context_t *c_,
-					unsigned int start_index_,
-					unsigned int num_items_,
-					bool context_match = false) :
-					 idx (start_index_),
-					 c (c_),
-					 match_glyph_data (NULL),
-					 num_items (num_items_),
-					 end (c->buffer->len)
+    inline void init (hb_apply_context_t *c_, bool context_match = false)
     {
+      c = c_;
+      match_glyph_data = NULL,
+      matcher.set_match_func (NULL, NULL);
       matcher.set_lookup_props (c->lookup_props);
       /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
       matcher.set_ignore_zwnj (context_match || c->table_index == 1);
       /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */
       matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj);
-      if (!context_match)
-	matcher.set_mask (c->lookup_mask);
-      matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
+      matcher.set_mask (context_match ? -1 : c->lookup_mask);
     }
-    inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); }
-    inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); }
+    inline void set_lookup_props (unsigned int lookup_props)
+    {
+      matcher.set_lookup_props (lookup_props);
+    }
     inline void set_match_func (matcher_t::match_func_t match_func,
 				const void *match_data,
 				const USHORT glyph_data[])
     {
       matcher.set_match_func (match_func, match_data);
       match_glyph_data = glyph_data;
     }
 
-    inline bool has_no_chance (void) const { return unlikely (num_items && idx + num_items >= end); }
+    inline void reset (unsigned int start_index_,
+		       unsigned int num_items_)
+    {
+      idx = start_index_;
+      num_items = num_items_;
+      end = c->buffer->len;
+      matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
+    }
+
     inline void reject (void) { num_items++; match_glyph_data--; }
+
     inline bool next (void)
     {
       assert (num_items > 0);
-      while (!has_no_chance ())
+      while (idx + num_items < end)
       {
 	idx++;
 	const hb_glyph_info_t &info = c->buffer->info[idx];
 
 	matcher_t::may_skip_t skip = matcher.may_skip (c, info);
 	if (unlikely (skip == matcher_t::SKIP_YES))
 	  continue;
 
@@ -445,132 +404,156 @@ struct hb_apply_context_t
 	  return true;
 	}
 
 	if (skip == matcher_t::SKIP_NO)
 	  return false;
       }
       return false;
     }
+    inline bool prev (void)
+    {
+      assert (num_items > 0);
+      while (idx >= num_items)
+      {
+	idx--;
+	const hb_glyph_info_t &info = c->buffer->out_info[idx];
+
+	matcher_t::may_skip_t skip = matcher.may_skip (c, info);
+	if (unlikely (skip == matcher_t::SKIP_YES))
+	  continue;
+
+	matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
+	if (match == matcher_t::MATCH_YES ||
+	    (match == matcher_t::MATCH_MAYBE &&
+	     skip == matcher_t::SKIP_NO))
+	{
+	  num_items--;
+	  match_glyph_data++;
+	  return true;
+	}
+
+	if (skip == matcher_t::SKIP_NO)
+	  return false;
+      }
+      return false;
+    }
 
     unsigned int idx;
     protected:
     hb_apply_context_t *c;
     matcher_t matcher;
     const USHORT *match_glyph_data;
 
     unsigned int num_items;
     unsigned int end;
   };
 
-  struct skipping_backward_iterator_t
+
+  inline const char *get_name (void) { return "APPLY"; }
+  static const unsigned int max_debug_depth = HB_DEBUG_APPLY;
+  typedef bool return_t;
+  typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
+  template <typename T, typename F>
+  inline bool may_dispatch (const T *obj, const F *format) { return true; }
+  template <typename T>
+  inline return_t dispatch (const T &obj) { return obj.apply (this); }
+  static return_t default_return_value (void) { return false; }
+  bool stop_sublookup_iteration (return_t r) const { return r; }
+  return_t recurse (unsigned int lookup_index)
   {
-    inline skipping_backward_iterator_t (hb_apply_context_t *c_,
-					 unsigned int start_index_,
-					 unsigned int num_items_,
-					 bool context_match = false) :
-					  idx (start_index_),
-					  c (c_),
-					  match_glyph_data (NULL),
-					  num_items (num_items_)
-    {
-      matcher.set_lookup_props (c->lookup_props);
-      /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
-      matcher.set_ignore_zwnj (context_match || c->table_index == 1);
-      /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */
-      matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj);
-      if (!context_match)
-	matcher.set_mask (c->lookup_mask);
-      matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
-    }
-    inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); }
-    inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); }
-    inline void set_match_func (matcher_t::match_func_t match_func,
-				const void *match_data,
-				const USHORT glyph_data[])
-    {
-      matcher.set_match_func (match_func, match_data);
-      match_glyph_data = glyph_data;
-    }
+    if (unlikely (nesting_level_left == 0 || !recurse_func))
+      return default_return_value ();
+
+    nesting_level_left--;
+    bool ret = recurse_func (this, lookup_index);
+    nesting_level_left++;
+    return ret;
+  }
 
-    inline bool has_no_chance (void) const { return unlikely (idx < num_items); }
-    inline void reject (void) { num_items++; }
-    inline bool prev (void)
-    {
-      assert (num_items > 0);
-      while (!has_no_chance ())
-      {
-	idx--;
-	const hb_glyph_info_t &info = c->buffer->out_info[idx];
+  unsigned int table_index; /* GSUB/GPOS */
+  hb_font_t *font;
+  hb_face_t *face;
+  hb_buffer_t *buffer;
+  hb_direction_t direction;
+  hb_mask_t lookup_mask;
+  bool auto_zwj;
+  recurse_func_t recurse_func;
+  unsigned int nesting_level_left;
+  unsigned int lookup_props;
+  const GDEF &gdef;
+  bool has_glyph_classes;
+  skipping_iterator_t iter_input, iter_context;
+  unsigned int debug_depth;
 
-	matcher_t::may_skip_t skip = matcher.may_skip (c, info);
-	if (unlikely (skip == matcher_t::SKIP_YES))
-	  continue;
 
-	matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
-	if (match == matcher_t::MATCH_YES ||
-	    (match == matcher_t::MATCH_MAYBE &&
-	     skip == matcher_t::SKIP_NO))
-	{
-	  num_items--;
-	  match_glyph_data++;
-	  return true;
-	}
+  hb_apply_context_t (unsigned int table_index_,
+		      hb_font_t *font_,
+		      hb_buffer_t *buffer_) :
+			table_index (table_index_),
+			font (font_), face (font->face), buffer (buffer_),
+			direction (buffer_->props.direction),
+			lookup_mask (1),
+			auto_zwj (true),
+			recurse_func (NULL),
+			nesting_level_left (MAX_NESTING_LEVEL),
+			lookup_props (0),
+			gdef (*hb_ot_layout_from_face (face)->gdef),
+			has_glyph_classes (gdef.has_glyph_classes ()),
+			iter_input (),
+			iter_context (),
+			debug_depth (0) {}
 
-	if (skip == matcher_t::SKIP_NO)
-	  return false;
-      }
-      return false;
-    }
-
-    unsigned int idx;
-    protected:
-    hb_apply_context_t *c;
-    matcher_t matcher;
-    const USHORT *match_glyph_data;
-
-    unsigned int num_items;
-  };
+  inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; }
+  inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; }
+  inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
+  inline void set_lookup (const Lookup &l) { set_lookup_props (l.get_props ()); }
+  inline void set_lookup_props (unsigned int lookup_props_)
+  {
+    lookup_props = lookup_props_;
+    iter_input.init (this, false);
+    iter_context.init (this, true);
+  }
 
   inline bool
   match_properties_mark (hb_codepoint_t  glyph,
 			 unsigned int    glyph_props,
-			 unsigned int    lookup_props) const
+			 unsigned int    match_props) const
   {
     /* If using mark filtering sets, the high short of
-     * lookup_props has the set index.
+     * match_props has the set index.
      */
-    if (lookup_props & LookupFlag::UseMarkFilteringSet)
-      return gdef.mark_set_covers (lookup_props >> 16, glyph);
+    if (match_props & LookupFlag::UseMarkFilteringSet)
+      return gdef.mark_set_covers (match_props >> 16, glyph);
 
-    /* The second byte of lookup_props has the meaning
+    /* The second byte of match_props has the meaning
      * "ignore marks of attachment type different than
      * the attachment type specified."
      */
-    if (lookup_props & LookupFlag::MarkAttachmentType)
-      return (lookup_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
+    if (match_props & LookupFlag::MarkAttachmentType)
+      return (match_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
 
     return true;
   }
 
   inline bool
   check_glyph_property (const hb_glyph_info_t *info,
-			unsigned int  lookup_props) const
+			unsigned int  match_props) const
   {
     hb_codepoint_t glyph = info->codepoint;
     unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
 
     /* Not covered, if, for example, glyph class is ligature and
-     * lookup_props includes LookupFlags::IgnoreLigatures
+     * match_props includes LookupFlags::IgnoreLigatures
      */
-    if (glyph_props & lookup_props & LookupFlag::IgnoreFlags)
+    if (glyph_props & match_props & LookupFlag::IgnoreFlags)
       return false;
 
     if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
-      return match_properties_mark (glyph, glyph_props, lookup_props);
+      return match_properties_mark (glyph, glyph_props, match_props);
 
     return true;
   }
 
   inline void _set_glyph_props (hb_codepoint_t glyph_index,
 			  unsigned int class_guess = 0,
 			  bool ligature = false,
 			  bool component = false) const
@@ -736,19 +719,19 @@ static inline bool match_input (hb_apply
 				unsigned int *p_total_component_count = NULL)
 {
   TRACE_APPLY (NULL);
 
   if (unlikely (count > MAX_CONTEXT_LENGTH)) TRACE_RETURN (false);
 
   hb_buffer_t *buffer = c->buffer;
 
-  hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, count - 1);
+  hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+  skippy_iter.reset (buffer->idx, count - 1);
   skippy_iter.set_match_func (match_func, match_data, input);
-  if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
 
   /*
    * This is perhaps the trickiest part of OpenType...  Remarks:
    *
    * - If all components of the ligature were marks, we call this a mark ligature.
    *
    * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
    *   it as a ligature glyph.
@@ -905,19 +888,19 @@ static inline void ligate_input (hb_appl
 static inline bool match_backtrack (hb_apply_context_t *c,
 				    unsigned int count,
 				    const USHORT backtrack[],
 				    match_func_t match_func,
 				    const void *match_data)
 {
   TRACE_APPLY (NULL);
 
-  hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count, true);
+  hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
+  skippy_iter.reset (c->buffer->backtrack_len (), count);
   skippy_iter.set_match_func (match_func, match_data, backtrack);
-  if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
 
   for (unsigned int i = 0; i < count; i++)
     if (!skippy_iter.prev ())
       return TRACE_RETURN (false);
 
   return TRACE_RETURN (true);
 }
 
@@ -925,32 +908,33 @@ static inline bool match_lookahead (hb_a
 				    unsigned int count,
 				    const USHORT lookahead[],
 				    match_func_t match_func,
 				    const void *match_data,
 				    unsigned int offset)
 {
   TRACE_APPLY (NULL);
 
-  hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count, true);
+  hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
+  skippy_iter.reset (c->buffer->idx + offset - 1, count);
   skippy_iter.set_match_func (match_func, match_data, lookahead);
-  if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
 
   for (unsigned int i = 0; i < count; i++)
     if (!skippy_iter.next ())
       return TRACE_RETURN (false);
 
   return TRACE_RETURN (true);
 }
 
 
 
 struct LookupRecord
 {
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this));
   }
 
   USHORT	sequenceIndex;		/* Index into current glyph
 					 * sequence--first glyph = 0 */
   USHORT	lookupListIndex;	/* Lookup to apply to that
 					 * position--zero--based */
@@ -1163,17 +1147,18 @@ struct Rule
   inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
   {
     TRACE_APPLY (this);
     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
     return TRACE_RETURN (context_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
   }
 
   public:
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return inputCount.sanitize (c)
 	&& lookupCount.sanitize (c)
 	&& c->check_range (inputZ,
 			   inputZ[0].static_size * inputCount
 			   + lookupRecordX[0].static_size * lookupCount);
   }
 
@@ -1227,17 +1212,18 @@ struct RuleSet
     for (unsigned int i = 0; i < num_rules; i++)
     {
       if ((this+rule[i]).apply (c, lookup_context))
         return TRACE_RETURN (true);
     }
     return TRACE_RETURN (false);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (rule.sanitize (c, this));
   }
 
   protected:
   OffsetArrayOf<Rule>
 		rule;			/* Array of Rule tables
 					 * ordered by preference */
@@ -1309,17 +1295,18 @@ struct ContextFormat1
     const RuleSet &rule_set = this+ruleSet[index];
     struct ContextApplyLookupContext lookup_context = {
       {match_glyph},
       NULL
     };
     return TRACE_RETURN (rule_set.apply (c, lookup_context));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
@@ -1401,17 +1388,18 @@ struct ContextFormat2
     const RuleSet &rule_set = this+ruleSet[index];
     struct ContextApplyLookupContext lookup_context = {
       {match_class},
       &class_def
     };
     return TRACE_RETURN (rule_set.apply (c, lookup_context));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 2 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
@@ -1489,25 +1477,26 @@ struct ContextFormat3
     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
     struct ContextApplyLookupContext lookup_context = {
       {match_coverage},
       this
     };
     return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (!c->check_struct (this)) return TRACE_RETURN (false);
     unsigned int count = glyphCount;
     if (!count) return TRACE_RETURN (false); /* We want to access coverageZ[0] freely. */
     if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return TRACE_RETURN (false);
     for (unsigned int i = 0; i < count; i++)
       if (!coverageZ[i].sanitize (c, this)) return TRACE_RETURN (false);
-    LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count);
+    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count);
     return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 3 */
   USHORT	glyphCount;		/* Number of glyphs in the input glyph
 					 * sequence */
   USHORT	lookupCount;		/* Number of LookupRecords */
@@ -1521,35 +1510,25 @@ struct ContextFormat3
 };
 
 struct Context
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
     switch (u.format) {
     case 1: return TRACE_RETURN (c->dispatch (u.format1));
     case 2: return TRACE_RETURN (c->dispatch (u.format2));
     case 3: return TRACE_RETURN (c->dispatch (u.format3));
     default:return TRACE_RETURN (c->default_return_value ());
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
-    switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    case 2: return TRACE_RETURN (u.format2.sanitize (c));
-    case 3: return TRACE_RETURN (u.format3.sanitize (c));
-    default:return TRACE_RETURN (true);
-    }
-  }
-
   protected:
   union {
   USHORT		format;		/* Format identifier */
   ContextFormat1	format1;
   ContextFormat2	format2;
   ContextFormat3	format3;
   } u;
 };
@@ -1721,24 +1700,25 @@ struct ChainRule
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     return TRACE_RETURN (chain_context_apply_lookup (c,
 						     backtrack.len, backtrack.array,
 						     input.len, input.array,
 						     lookahead.len, lookahead.array, lookup.len,
 						     lookup.array, lookup_context));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (!backtrack.sanitize (c)) return TRACE_RETURN (false);
-    HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
+    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
     if (!input.sanitize (c)) return TRACE_RETURN (false);
-    ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
+    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
     if (!lookahead.sanitize (c)) return TRACE_RETURN (false);
-    ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     return TRACE_RETURN (lookup.sanitize (c));
   }
 
   protected:
   ArrayOf<USHORT>
 		backtrack;		/* Array of backtracking values
 					 * (to be matched before the input
 					 * sequence) */
@@ -1790,17 +1770,18 @@ struct ChainRuleSet
     unsigned int num_rules = rule.len;
     for (unsigned int i = 0; i < num_rules; i++)
       if ((this+rule[i]).apply (c, lookup_context))
         return TRACE_RETURN (true);
 
     return TRACE_RETURN (false);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (rule.sanitize (c, this));
   }
 
   protected:
   OffsetArrayOf<ChainRule>
 		rule;			/* Array of ChainRule tables
 					 * ordered by preference */
@@ -1869,17 +1850,18 @@ struct ChainContextFormat1
     const ChainRuleSet &rule_set = this+ruleSet[index];
     struct ChainContextApplyLookupContext lookup_context = {
       {match_glyph},
       {NULL, NULL, NULL}
     };
     return TRACE_RETURN (rule_set.apply (c, lookup_context));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
@@ -1979,17 +1961,18 @@ struct ChainContextFormat2
       {match_class},
       {&backtrack_class_def,
        &input_class_def,
        &lookahead_class_def}
     };
     return TRACE_RETURN (rule_set.apply (c, lookup_context));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (coverage.sanitize (c, this) && backtrackClassDef.sanitize (c, this) &&
 			 inputClassDef.sanitize (c, this) && lookaheadClassDef.sanitize (c, this) &&
 			 ruleSet.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 2 */
@@ -2100,25 +2083,26 @@ struct ChainContextFormat3
     };
     return TRACE_RETURN (chain_context_apply_lookup (c,
 						     backtrack.len, (const USHORT *) backtrack.array,
 						     input.len, (const USHORT *) input.array + 1,
 						     lookahead.len, (const USHORT *) lookahead.array,
 						     lookup.len, lookup.array, lookup_context));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false);
-    OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
     if (!input.sanitize (c, this)) return TRACE_RETURN (false);
     if (!input.len) return TRACE_RETURN (false); /* To be consistent with Context. */
-    OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
     if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false);
-    ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     return TRACE_RETURN (lookup.sanitize (c));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 3 */
   OffsetArrayOf<Coverage>
 		backtrack;		/* Array of coverage tables
 					 * in backtracking sequence, in  glyph
@@ -2139,53 +2123,61 @@ struct ChainContextFormat3
 };
 
 struct ChainContext
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
     switch (u.format) {
     case 1: return TRACE_RETURN (c->dispatch (u.format1));
     case 2: return TRACE_RETURN (c->dispatch (u.format2));
     case 3: return TRACE_RETURN (c->dispatch (u.format3));
     default:return TRACE_RETURN (c->default_return_value ());
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
-    switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    case 2: return TRACE_RETURN (u.format2.sanitize (c));
-    case 3: return TRACE_RETURN (u.format3.sanitize (c));
-    default:return TRACE_RETURN (true);
-    }
-  }
-
   protected:
   union {
   USHORT		format;	/* Format identifier */
   ChainContextFormat1	format1;
   ChainContextFormat2	format2;
   ChainContextFormat3	format3;
   } u;
 };
 
 
+template <typename T>
 struct ExtensionFormat1
 {
   inline unsigned int get_type (void) const { return extensionLookupType; }
-  inline unsigned int get_offset (void) const { return extensionOffset; }
+
+  template <typename X>
+  inline const X& get_subtable (void) const
+  {
+    unsigned int offset = extensionOffset;
+    if (unlikely (!offset)) return Null(typename T::LookupSubTable);
+    return StructAtOffset<typename T::LookupSubTable> (this, offset);
+  }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  template <typename context_t>
+  inline typename context_t::return_t dispatch (context_t *c) const
+  {
+    TRACE_DISPATCH (this, format);
+    if (unlikely (!c->may_dispatch (this, this))) TRACE_RETURN (c->default_return_value ());
+    return get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ());
+  }
+
+  /* This is called from may_dispatch() above with hb_sanitize_context_t. */
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this));
+    return TRACE_RETURN (c->check_struct (this) && extensionOffset != 0);
   }
 
   protected:
   USHORT	format;			/* Format identifier. Set to 1. */
   USHORT	extensionLookupType;	/* Lookup type of subtable referenced
 					 * by ExtensionOffset (i.e. the
 					 * extension subtable). */
   ULONG		extensionOffset;	/* Offset to the extension subtable,
@@ -2199,59 +2191,40 @@ struct Extension
 {
   inline unsigned int get_type (void) const
   {
     switch (u.format) {
     case 1: return u.format1.get_type ();
     default:return 0;
     }
   }
-  inline unsigned int get_offset (void) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.get_offset ();
-    default:return 0;
-    }
-  }
-
   template <typename X>
   inline const X& get_subtable (void) const
   {
-    unsigned int offset = get_offset ();
-    if (unlikely (!offset)) return Null(typename T::LookupSubTable);
-    return StructAtOffset<typename T::LookupSubTable> (this, offset);
+    switch (u.format) {
+    case 1: return u.format1.template get_subtable<typename T::LookupSubTable> ();
+    default:return Null(typename T::LookupSubTable);
+    }
   }
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
-    return get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ());
-  }
-
-  inline bool sanitize_self (hb_sanitize_context_t *c) {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
+    TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
     switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    default:return TRACE_RETURN (true);
+    case 1: return TRACE_RETURN (u.format1.dispatch (c));
+    default:return TRACE_RETURN (c->default_return_value ());
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
-    TRACE_SANITIZE (this);
-    if (!sanitize_self (c)) return TRACE_RETURN (false);
-    unsigned int offset = get_offset ();
-    if (unlikely (!offset)) return TRACE_RETURN (true);
-    return TRACE_RETURN (StructAtOffset<typename T::LookupSubTable> (this, offset).sanitize (c, get_type ()));
-  }
-
   protected:
   union {
   USHORT		format;		/* Format identifier */
-  ExtensionFormat1	format1;
+  ExtensionFormat1<T>	format1;
   } u;
 };
 
 
 /*
  * GSUB/GPOS Common
  */
 
@@ -2286,17 +2259,18 @@ struct GSUBGPOS
   inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
   { return (this+featureList).find_index (tag, index); }
 
   inline unsigned int get_lookup_count (void) const
   { return (this+lookupList).len; }
   inline const Lookup& get_lookup (unsigned int i) const
   { return (this+lookupList)[i]; }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) &&
 			 scriptList.sanitize (c, this) &&
 			 featureList.sanitize (c, this) &&
 			 lookupList.sanitize (c, this));
   }
 
   protected:
--- a/gfx/harfbuzz/src/hb-ot-layout-jstf-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-jstf-table.hh
@@ -49,17 +49,18 @@ typedef OffsetListOf<PosLookup> JstfMax;
 
 
 /*
  * JstfPriority -- Justification Priority Table
  */
 
 struct JstfPriority
 {
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) &&
 			 shrinkageEnableGSUB.sanitize (c, this) &&
 			 shrinkageDisableGSUB.sanitize (c, this) &&
 			 shrinkageEnableGPOS.sanitize (c, this) &&
 			 shrinkageDisableGPOS.sanitize (c, this) &&
 			 shrinkageJstfMax.sanitize (c, this) &&
 			 extensionEnableGSUB.sanitize (c, this) &&
@@ -118,17 +119,18 @@ struct JstfPriority
 
 /*
  * JstfLangSys -- Justification Language System Table
  */
 
 struct JstfLangSys : OffsetListOf<JstfPriority>
 {
   inline bool sanitize (hb_sanitize_context_t *c,
-			const Record<JstfLangSys>::sanitize_closure_t * = NULL) {
+			const Record<JstfLangSys>::sanitize_closure_t * = NULL) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (OffsetListOf<JstfPriority>::sanitize (c));
   }
 };
 
 
 /*
  * ExtenderGlyphs -- Extender Glyph Table
@@ -158,17 +160,18 @@ struct JstfScript
   }
   inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
   { return langSys.find_index (tag, index); }
 
   inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
   inline const JstfLangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
 
   inline bool sanitize (hb_sanitize_context_t *c,
-			const Record<JstfScript>::sanitize_closure_t * = NULL) {
+			const Record<JstfScript>::sanitize_closure_t * = NULL) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (extenderGlyphs.sanitize (c, this) &&
 			 defaultLangSys.sanitize (c, this) &&
 			 langSys.sanitize (c, this));
   }
 
   protected:
   OffsetTo<ExtenderGlyphs>
@@ -201,17 +204,18 @@ struct JSTF
 				       unsigned int *script_count /* IN/OUT */,
 				       hb_tag_t     *script_tags /* OUT */) const
   { return scriptList.get_tags (start_offset, script_count, script_tags); }
   inline const JstfScript& get_script (unsigned int i) const
   { return this+scriptList[i].offset; }
   inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
   { return scriptList.find_index (tag, index); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) &&
 			 scriptList.sanitize (c, this));
   }
 
   protected:
   FixedVersion	version;	/* Version of the JSTF table--initially set
 				 * to 0x00010000u */
--- a/gfx/harfbuzz/src/hb-ot-layout-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-private.hh
@@ -121,21 +121,25 @@ struct hb_ot_layout_lookup_accelerator_t
 {
   template <typename TLookup>
   inline void init (const TLookup &lookup)
   {
     digest.init ();
     lookup.add_coverage (&digest);
   }
 
-  template <typename TLookup>
-  inline void fini (const TLookup &lookup HB_UNUSED)
+  inline void fini (void)
   {
   }
 
+  inline bool may_have (hb_codepoint_t g) const {
+    return digest.may_have (g);
+  }
+
+  private:
   hb_set_digest_t digest;
 };
 
 struct hb_ot_layout_t
 {
   hb_blob_t *gdef_blob;
   hb_blob_t *gsub_blob;
   hb_blob_t *gpos_blob;
--- a/gfx/harfbuzz/src/hb-ot-layout.cc
+++ b/gfx/harfbuzz/src/hb-ot-layout.cc
@@ -79,19 +79,19 @@ hb_ot_layout_t *
 
   return layout;
 }
 
 void
 _hb_ot_layout_destroy (hb_ot_layout_t *layout)
 {
   for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
-    layout->gsub_accels[i].fini (layout->gsub->get_lookup (i));
+    layout->gsub_accels[i].fini ();
   for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
-    layout->gpos_accels[i].fini (layout->gpos->get_lookup (i));
+    layout->gpos_accels[i].fini ();
 
   free (layout->gsub_accels);
   free (layout->gpos_accels);
 
   hb_blob_destroy (layout->gdef_blob);
   hb_blob_destroy (layout->gsub_blob);
   hb_blob_destroy (layout->gpos_blob);
 
@@ -694,17 +694,17 @@ hb_ot_layout_lookup_would_substitute_fas
 					   unsigned int          glyphs_length,
 					   hb_bool_t             zero_context)
 {
   if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false;
   OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, zero_context);
 
   const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
 
-  return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index].digest);
+  return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index]);
 }
 
 void
 hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer)
 {
   OT::GSUB::substitute_start (font, buffer);
 }
 
@@ -824,83 +824,128 @@ struct GPOSProxy
     table (*hb_ot_layout_from_face (face)->gpos),
     accels (hb_ot_layout_from_face (face)->gpos_accels) {}
 
   const OT::GPOS &table;
   const hb_ot_layout_lookup_accelerator_t *accels;
 };
 
 
-template <typename Lookup>
-static inline bool apply_once (OT::hb_apply_context_t *c,
-			       const Lookup &lookup)
+template <typename Obj>
+static inline bool
+apply_forward (OT::hb_apply_context_t *c,
+	       const Obj &obj,
+	       const hb_ot_layout_lookup_accelerator_t &accel)
 {
-  if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props))
-    return false;
-  return lookup.dispatch (c);
+  bool ret = false;
+  hb_buffer_t *buffer = c->buffer;
+  while (buffer->idx < buffer->len)
+  {
+    if (accel.may_have (buffer->cur().codepoint) &&
+	(buffer->cur().mask & c->lookup_mask) &&
+	c->check_glyph_property (&buffer->cur(), c->lookup_props) &&
+	obj.apply (c))
+      ret = true;
+    else
+      buffer->next_glyph ();
+  }
+  return ret;
 }
 
+template <typename Obj>
+static inline bool
+apply_backward (OT::hb_apply_context_t *c,
+		const Obj &obj,
+		const hb_ot_layout_lookup_accelerator_t &accel)
+{
+  bool ret = false;
+  hb_buffer_t *buffer = c->buffer;
+  do
+  {
+    if (accel.may_have (buffer->cur().codepoint) &&
+	(buffer->cur().mask & c->lookup_mask) &&
+	c->check_glyph_property (&buffer->cur(), c->lookup_props) &&
+	obj.apply (c))
+      ret = true;
+    /* The reverse lookup doesn't "advance" cursor (for good reason). */
+    buffer->idx--;
+
+  }
+  while ((int) buffer->idx >= 0);
+  return ret;
+}
+
+struct hb_apply_forward_context_t
+{
+  inline const char *get_name (void) { return "APPLY_FORWARD"; }
+  static const unsigned int max_debug_depth = HB_DEBUG_APPLY;
+  typedef bool return_t;
+  template <typename T, typename F>
+  inline bool may_dispatch (const T *obj, const F *format) { return true; }
+  template <typename T>
+  inline return_t dispatch (const T &obj) { return apply_forward (c, obj, accel); }
+  static return_t default_return_value (void) { return false; }
+  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return true; }
+
+  hb_apply_forward_context_t (OT::hb_apply_context_t *c_,
+			      const hb_ot_layout_lookup_accelerator_t &accel_) :
+				c (c_),
+				accel (accel_),
+				debug_depth (0) {}
+
+  OT::hb_apply_context_t *c;
+  const hb_ot_layout_lookup_accelerator_t &accel;
+  unsigned int debug_depth;
+};
+
 template <typename Proxy>
-static inline bool
+static inline void
 apply_string (OT::hb_apply_context_t *c,
 	      const typename Proxy::Lookup &lookup,
 	      const hb_ot_layout_lookup_accelerator_t &accel)
 {
-  bool ret = false;
   hb_buffer_t *buffer = c->buffer;
 
   if (unlikely (!buffer->len || !c->lookup_mask))
-    return false;
+    return;
 
   c->set_lookup (lookup);
 
   if (likely (!lookup.is_reverse ()))
   {
     /* in/out forward substitution/positioning */
     if (Proxy::table_index == 0)
       buffer->clear_output ();
     buffer->idx = 0;
 
-    while (buffer->idx < buffer->len)
+    bool ret;
+    if (lookup.get_subtable_count () == 1)
     {
-      if (accel.digest.may_have (buffer->cur().codepoint) &&
-	  (buffer->cur().mask & c->lookup_mask) &&
-	  apply_once (c, lookup))
-	ret = true;
-      else
-	buffer->next_glyph ();
+      hb_apply_forward_context_t c_forward (c, accel);
+      ret = lookup.dispatch (&c_forward);
     }
+    else
+      ret = apply_forward (c, lookup, accel);
     if (ret)
     {
       if (!Proxy::inplace)
 	buffer->swap_buffers ();
       else
-        assert (!buffer->has_separate_output ());
+	assert (!buffer->has_separate_output ());
     }
   }
   else
   {
     /* in-place backward substitution/positioning */
     if (Proxy::table_index == 0)
       buffer->remove_output ();
     buffer->idx = buffer->len - 1;
-    do
-    {
-      if (accel.digest.may_have (buffer->cur().codepoint) &&
-	  (buffer->cur().mask & c->lookup_mask) &&
-	  apply_once (c, lookup))
-	ret = true;
-      /* The reverse lookup doesn't "advance" cursor (for good reason). */
-      buffer->idx--;
 
-    }
-    while ((int) buffer->idx >= 0);
+    apply_backward (c, lookup, accel);
   }
-
-  return ret;
 }
 
 template <typename Proxy>
 inline void hb_ot_map_t::apply (const Proxy &proxy,
 				const hb_ot_shape_plan_t *plan,
 				hb_font_t *font,
 				hb_buffer_t *buffer) const
 {
--- a/gfx/harfbuzz/src/hb-ot-maxp-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-maxp-table.hh
@@ -38,21 +38,23 @@ namespace OT {
  */
 
 #define HB_OT_TAG_maxp HB_TAG('m','a','x','p')
 
 struct maxp
 {
   static const hb_tag_t tableTag	= HB_OT_TAG_maxp;
 
-  inline unsigned int get_num_glyphs (void) const {
+  inline unsigned int get_num_glyphs (void) const
+  {
     return numGlyphs;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) &&
 			 likely (version.major == 1 || (version.major == 0 && version.minor == 0x5000u)));
   }
 
   /* We only implement version 0.5 as none of the extra fields in version 1.0 are useful. */
   protected:
   FixedVersion	version;		/* Version of the maxp table (0.5 or 1.0),
--- a/gfx/harfbuzz/src/hb-ot-name-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-name-table.hh
@@ -51,17 +51,18 @@ struct NameRecord
     if (ret) return ret;
     ret = b->languageID.cmp (a->languageID);
     if (ret) return ret;
     ret = b->nameID.cmp (a->nameID);
     if (ret) return ret;
     return 0;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
     TRACE_SANITIZE (this);
     /* We can check from base all the way up to the end of string... */
     return TRACE_RETURN (c->check_struct (this) && c->check_range ((char *) base, (unsigned int) length + offset));
   }
 
   USHORT	platformID;	/* Platform ID. */
   USHORT	encodingID;	/* Platform-specific encoding ID. */
   USHORT	languageID;	/* Language ID. */
@@ -96,26 +97,27 @@ struct name
     unsigned int length = MIN (buffer_length, (unsigned int) match->length);
     memcpy (buffer, (char *) this + stringOffset + match->offset, length);
     return length;
   }
 
   inline unsigned int get_size (void) const
   { return min_size + count * nameRecord[0].min_size; }
 
-  inline bool sanitize_records (hb_sanitize_context_t *c) {
+  inline bool sanitize_records (hb_sanitize_context_t *c) const {
     TRACE_SANITIZE (this);
     char *string_pool = (char *) this + stringOffset;
     unsigned int _count = count;
     for (unsigned int i = 0; i < _count; i++)
       if (!nameRecord[i].sanitize (c, string_pool)) return TRACE_RETURN (false);
     return TRACE_RETURN (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) {
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) &&
 			 likely (format == 0 || format == 1) &&
 			 c->check_array (nameRecord, nameRecord[0].static_size, count) &&
 			 sanitize_records (c));
   }
 
   /* We only implement format 0 for now. */
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh
@@ -322,17 +322,17 @@ static void
 arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
 {
   if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil)
     return;
 
   for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
     if (fallback_plan->lookup_array[i])
     {
-      fallback_plan->accel_array[i].fini (fallback_plan->lookup_array[i]);
+      fallback_plan->accel_array[i].fini ();
       if (fallback_plan->free_lookups)
 	free (fallback_plan->lookup_array[i]);
     }
 
   free (fallback_plan);
 }
 
 static void
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh
@@ -128,17 +128,16 @@
 	OT_UARRAY(Name##Glyphs, OT_LIST(Items))
 
 
 /*
  * GSUB
  */
 
 #define OT_LOOKUP_TYPE_SUBST_SINGLE	1u
-#define OT_LOOKUP_TYPE_SUBST_MULTIPLE	2u
 #define OT_LOOKUP_TYPE_SUBST_LIGATURE	4u
 
 #define OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(Name, FromGlyphs, ToGlyphs) \
 	OT_SUBLOOKUP(Name, 2, \
 		OT_OFFSET(Name, Name##Coverage) \
 		OT_LABEL_END \
 		OT_UARRAY(Name##Substitute, OT_LIST(ToGlyphs)) \
 	) \
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
@@ -1,10 +1,10 @@
 
-#line 1 "../../src/hb-ot-shape-complex-indic-machine.rl"
+#line 1 "hb-ot-shape-complex-indic-machine.rl"
 /*
  * Copyright © 2011,2012  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
  * Permission is hereby granted, without written agreement and without
  * license or royalty fees, to use, copy, modify, and distribute this
  * software and its documentation for any purpose, provided that the
@@ -27,1291 +27,1314 @@
  */
 
 #ifndef HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
 
 #include "hb-private.hh"
 
 
-#line 36 "hb-ot-shape-complex-indic-machine.hh.tmp"
+#line 36 "hb-ot-shape-complex-indic-machine.hh"
 static const unsigned char _indic_syllable_machine_trans_keys[] = {
-	1u, 16u, 13u, 13u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 
-	5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 4u, 4u, 6u, 6u, 
-	16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 
-	6u, 6u, 16u, 16u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 
-	4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 1u, 16u, 13u, 13u, 5u, 7u, 5u, 7u, 
-	7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 
-	5u, 7u, 7u, 7u, 4u, 4u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 
-	4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 14u, 4u, 14u, 
+	8u, 8u, 1u, 16u, 8u, 13u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 
+	7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 
+	6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 
+	4u, 8u, 6u, 6u, 16u, 16u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 
+	4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 8u, 8u, 1u, 16u, 8u, 13u, 
+	5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 
+	7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 
+	6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 
 	4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 
-	1u, 16u, 13u, 13u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 
-	5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 4u, 4u, 6u, 6u, 
-	16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 
-	6u, 6u, 16u, 16u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 
-	4u, 14u, 4u, 14u, 4u, 14u, 1u, 16u, 13u, 13u, 5u, 7u, 5u, 7u, 7u, 7u, 
-	5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 
-	7u, 7u, 4u, 4u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 
-	6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 14u, 4u, 14u, 4u, 14u, 
-	4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 
-	4u, 14u, 5u, 7u, 5u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 
-	7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 1u, 16u, 13u, 13u, 4u, 4u, 6u, 6u, 
-	16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 
-	6u, 6u, 16u, 16u, 1u, 31u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 
+	4u, 14u, 4u, 14u, 8u, 8u, 1u, 16u, 8u, 13u, 5u, 8u, 5u, 7u, 7u, 7u, 
+	5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 
+	7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 
+	6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 14u, 4u, 14u, 4u, 14u, 
+	4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 8u, 8u, 1u, 16u, 
+	8u, 13u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 
+	5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 
+	4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 
+	16u, 16u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 
+	4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 5u, 8u, 4u, 14u, 4u, 14u, 5u, 8u, 
+	5u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 
+	5u, 7u, 7u, 7u, 8u, 8u, 1u, 16u, 8u, 13u, 4u, 8u, 6u, 6u, 16u, 16u, 
+	4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 
+	16u, 16u, 8u, 8u, 1u, 31u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 
 	3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 
-	3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 8u, 14u, 
+	3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 5u, 14u, 
 	5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u, 
-	3u, 10u, 8u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 
+	3u, 10u, 5u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 
 	3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 
-	6u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, 
+	5u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, 
 	1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 
 	1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 
 	1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 
 	1u, 16u, 3u, 31u, 3u, 31u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 
 	3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 
-	3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 8u, 14u, 
+	3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 5u, 14u, 
 	5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u, 
-	3u, 10u, 8u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 
+	3u, 10u, 5u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 
 	3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 
-	6u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, 
+	5u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, 
 	1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 
 	1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 
 	1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 
 	4u, 14u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 
 	4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 
-	4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 8u, 14u, 5u, 10u, 
+	4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 5u, 14u, 5u, 10u, 
 	9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u, 3u, 10u, 
-	8u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 
-	4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 6u, 14u, 
+	5u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 
+	4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 
 	3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 
 	1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 
 	1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 
 	1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 
 	4u, 14u, 3u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 
 	3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 
-	3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 8u, 14u, 
+	3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 5u, 14u, 
 	5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u, 
-	3u, 10u, 8u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 
+	3u, 10u, 5u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 
 	3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 
-	6u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, 
+	5u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, 
 	1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 
 	1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 
 	1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 
-	1u, 16u, 3u, 31u, 1u, 31u, 3u, 31u, 1u, 31u, 4u, 14u, 1u, 16u, 3u, 31u, 
-	3u, 31u, 4u, 31u, 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 
-	5u, 10u, 3u, 31u, 3u, 31u, 1u, 16u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 
-	4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 8u, 14u, 
-	3u, 13u, 3u, 10u, 8u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 3u, 10u, 8u, 10u, 
+	1u, 16u, 3u, 31u, 1u, 31u, 3u, 31u, 1u, 31u, 4u, 14u, 5u, 10u, 9u, 10u, 
+	9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 1u, 16u, 3u, 31u, 3u, 31u, 
+	4u, 31u, 3u, 31u, 3u, 31u, 1u, 16u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 
+	4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 
+	3u, 13u, 3u, 10u, 5u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 3u, 10u, 5u, 10u, 
 	5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 0
 };
 
 static const char _indic_syllable_machine_key_spans[] = {
-	16, 1, 3, 3, 1, 3, 3, 1, 
-	3, 3, 1, 3, 3, 1, 1, 1, 
-	1, 4, 1, 1, 4, 1, 1, 4, 
-	1, 1, 11, 11, 11, 11, 11, 11, 
-	11, 11, 11, 11, 16, 1, 3, 3, 
-	1, 3, 3, 1, 3, 3, 1, 3, 
-	3, 1, 1, 1, 1, 4, 1, 1, 
-	4, 1, 1, 4, 1, 1, 11, 11, 
+	1, 16, 6, 4, 3, 1, 4, 3, 
+	1, 4, 3, 1, 4, 3, 1, 5, 
+	1, 1, 5, 1, 1, 5, 1, 1, 
+	5, 1, 1, 11, 11, 11, 11, 11, 
+	11, 11, 11, 11, 11, 1, 16, 6, 
+	4, 3, 1, 4, 3, 1, 4, 3, 
+	1, 4, 3, 1, 5, 1, 1, 5, 
+	1, 1, 5, 1, 1, 5, 1, 1, 
 	11, 11, 11, 11, 11, 11, 11, 11, 
-	16, 1, 3, 3, 1, 3, 3, 1, 
-	3, 3, 1, 3, 3, 1, 1, 1, 
-	1, 4, 1, 1, 4, 1, 1, 4, 
-	1, 1, 11, 11, 11, 11, 11, 11, 
-	11, 11, 11, 16, 1, 3, 3, 1, 
-	3, 3, 1, 3, 3, 1, 3, 3, 
-	1, 1, 1, 1, 4, 1, 1, 4, 
-	1, 1, 4, 1, 1, 11, 11, 11, 
-	11, 11, 11, 11, 11, 11, 11, 11, 
-	11, 3, 3, 3, 3, 1, 3, 3, 
-	1, 3, 3, 1, 16, 1, 1, 1, 
-	1, 4, 1, 1, 4, 1, 1, 4, 
+	11, 11, 1, 16, 6, 4, 3, 1, 
+	4, 3, 1, 4, 3, 1, 4, 3, 
+	1, 5, 1, 1, 5, 1, 1, 5, 
+	1, 1, 5, 1, 1, 11, 11, 11, 
+	11, 11, 11, 11, 11, 11, 1, 16, 
+	6, 4, 3, 1, 4, 3, 1, 4, 
+	3, 1, 4, 3, 1, 5, 1, 1, 
+	5, 1, 1, 5, 1, 1, 5, 1, 
+	1, 11, 11, 11, 11, 11, 11, 11, 
+	11, 11, 11, 11, 4, 11, 11, 4, 
+	3, 4, 3, 1, 4, 3, 1, 4, 
+	3, 1, 1, 16, 6, 5, 1, 1, 
+	5, 1, 1, 5, 1, 1, 5, 1, 
 	1, 1, 31, 29, 29, 28, 16, 29, 
 	29, 28, 16, 29, 29, 28, 16, 29, 
-	29, 28, 16, 29, 29, 28, 10, 7, 
+	29, 28, 16, 29, 29, 28, 10, 10, 
 	6, 2, 1, 2, 2, 1, 6, 11, 
-	8, 3, 8, 11, 12, 12, 11, 10, 
+	8, 6, 8, 11, 12, 12, 11, 10, 
 	12, 11, 10, 12, 11, 10, 12, 11, 
-	9, 12, 16, 28, 11, 29, 29, 16, 
+	10, 12, 16, 28, 11, 29, 29, 16, 
 	16, 16, 16, 16, 29, 29, 16, 16, 
 	16, 16, 16, 29, 29, 16, 16, 16, 
 	16, 16, 29, 29, 16, 16, 16, 16, 
 	16, 29, 29, 29, 29, 28, 16, 29, 
 	29, 28, 16, 29, 29, 28, 16, 29, 
-	29, 28, 16, 29, 29, 28, 10, 7, 
+	29, 28, 16, 29, 29, 28, 10, 10, 
 	6, 2, 1, 2, 2, 1, 6, 11, 
-	8, 3, 8, 11, 12, 12, 11, 10, 
+	8, 6, 8, 11, 12, 12, 11, 10, 
 	12, 11, 10, 12, 11, 10, 12, 11, 
-	9, 12, 16, 28, 11, 29, 29, 16, 
+	10, 12, 16, 28, 11, 29, 29, 16, 
 	16, 16, 16, 16, 29, 29, 16, 16, 
 	16, 16, 16, 29, 29, 16, 16, 16, 
 	16, 16, 29, 29, 16, 16, 16, 16, 
 	11, 16, 29, 29, 28, 16, 29, 29, 
 	28, 16, 29, 29, 28, 16, 29, 29, 
-	28, 16, 29, 29, 28, 10, 7, 6, 
+	28, 16, 29, 29, 28, 10, 10, 6, 
 	2, 1, 2, 2, 1, 6, 11, 8, 
-	3, 8, 11, 12, 12, 11, 10, 12, 
-	11, 10, 12, 11, 10, 12, 11, 9, 
+	6, 8, 11, 12, 12, 11, 10, 12, 
+	11, 10, 12, 11, 10, 12, 11, 10, 
 	12, 16, 28, 11, 29, 29, 16, 16, 
 	16, 16, 16, 29, 29, 16, 16, 16, 
 	16, 16, 29, 29, 16, 16, 16, 16, 
 	16, 29, 29, 16, 16, 16, 16, 16, 
 	11, 29, 11, 29, 29, 28, 16, 29, 
 	29, 28, 16, 29, 29, 28, 16, 29, 
-	29, 28, 16, 29, 29, 28, 10, 7, 
+	29, 28, 16, 29, 29, 28, 10, 10, 
 	6, 2, 1, 2, 2, 1, 6, 11, 
-	8, 3, 8, 11, 12, 12, 11, 10, 
+	8, 6, 8, 11, 12, 12, 11, 10, 
 	12, 11, 10, 12, 11, 10, 12, 11, 
-	9, 12, 16, 28, 11, 29, 29, 16, 
+	10, 12, 16, 28, 11, 29, 29, 16, 
 	16, 16, 16, 16, 29, 29, 16, 16, 
 	16, 16, 16, 29, 29, 16, 16, 16, 
 	16, 16, 29, 29, 16, 16, 16, 16, 
-	16, 29, 31, 29, 31, 11, 16, 29, 
-	29, 28, 6, 2, 1, 2, 2, 1, 
-	6, 29, 29, 16, 12, 11, 10, 12, 
-	11, 10, 12, 11, 10, 12, 11, 7, 
-	11, 8, 3, 8, 11, 16, 8, 3, 
+	16, 29, 31, 29, 31, 11, 6, 2, 
+	1, 2, 2, 1, 6, 16, 29, 29, 
+	28, 29, 29, 16, 12, 11, 10, 12, 
+	11, 10, 12, 11, 10, 12, 11, 10, 
+	11, 8, 6, 8, 11, 16, 8, 6, 
 	6, 2, 1, 2, 2, 1, 6
 };
 
 static const short _indic_syllable_machine_index_offsets[] = {
-	0, 17, 19, 23, 27, 29, 33, 37, 
-	39, 43, 47, 49, 53, 57, 59, 61, 
-	63, 65, 70, 72, 74, 79, 81, 83, 
-	88, 90, 92, 104, 116, 128, 140, 152, 
-	164, 176, 188, 200, 212, 229, 231, 235, 
-	239, 241, 245, 249, 251, 255, 259, 261, 
-	265, 269, 271, 273, 275, 277, 282, 284, 
-	286, 291, 293, 295, 300, 302, 304, 316, 
-	328, 340, 352, 364, 376, 388, 400, 412, 
-	424, 441, 443, 447, 451, 453, 457, 461, 
-	463, 467, 471, 473, 477, 481, 483, 485, 
-	487, 489, 494, 496, 498, 503, 505, 507, 
-	512, 514, 516, 528, 540, 552, 564, 576, 
-	588, 600, 612, 624, 641, 643, 647, 651, 
-	653, 657, 661, 663, 667, 671, 673, 677, 
-	681, 683, 685, 687, 689, 694, 696, 698, 
-	703, 705, 707, 712, 714, 716, 728, 740, 
-	752, 764, 776, 788, 800, 812, 824, 836, 
-	848, 860, 864, 868, 872, 876, 878, 882, 
-	886, 888, 892, 896, 898, 915, 917, 919, 
-	921, 923, 928, 930, 932, 937, 939, 941, 
-	946, 948, 950, 982, 1012, 1042, 1071, 1088, 
-	1118, 1148, 1177, 1194, 1224, 1254, 1283, 1300, 
-	1330, 1360, 1389, 1406, 1436, 1466, 1495, 1506, 
-	1514, 1521, 1524, 1526, 1529, 1532, 1534, 1541, 
-	1553, 1562, 1566, 1575, 1587, 1600, 1613, 1625, 
-	1636, 1649, 1661, 1672, 1685, 1697, 1708, 1721, 
-	1733, 1743, 1756, 1773, 1802, 1814, 1844, 1874, 
-	1891, 1908, 1925, 1942, 1959, 1989, 2019, 2036, 
-	2053, 2070, 2087, 2104, 2134, 2164, 2181, 2198, 
-	2215, 2232, 2249, 2279, 2309, 2326, 2343, 2360, 
-	2377, 2394, 2424, 2454, 2484, 2514, 2543, 2560, 
-	2590, 2620, 2649, 2666, 2696, 2726, 2755, 2772, 
-	2802, 2832, 2861, 2878, 2908, 2938, 2967, 2978, 
-	2986, 2993, 2996, 2998, 3001, 3004, 3006, 3013, 
-	3025, 3034, 3038, 3047, 3059, 3072, 3085, 3097, 
-	3108, 3121, 3133, 3144, 3157, 3169, 3180, 3193, 
-	3205, 3215, 3228, 3245, 3274, 3286, 3316, 3346, 
-	3363, 3380, 3397, 3414, 3431, 3461, 3491, 3508, 
-	3525, 3542, 3559, 3576, 3606, 3636, 3653, 3670, 
-	3687, 3704, 3721, 3751, 3781, 3798, 3815, 3832, 
-	3849, 3861, 3878, 3908, 3938, 3967, 3984, 4014, 
-	4044, 4073, 4090, 4120, 4150, 4179, 4196, 4226, 
-	4256, 4285, 4302, 4332, 4362, 4391, 4402, 4410, 
-	4417, 4420, 4422, 4425, 4428, 4430, 4437, 4449, 
-	4458, 4462, 4471, 4483, 4496, 4509, 4521, 4532, 
-	4545, 4557, 4568, 4581, 4593, 4604, 4617, 4629, 
-	4639, 4652, 4669, 4698, 4710, 4740, 4770, 4787, 
-	4804, 4821, 4838, 4855, 4885, 4915, 4932, 4949, 
-	4966, 4983, 5000, 5030, 5060, 5077, 5094, 5111, 
-	5128, 5145, 5175, 5205, 5222, 5239, 5256, 5273, 
-	5290, 5302, 5332, 5344, 5374, 5404, 5433, 5450, 
-	5480, 5510, 5539, 5556, 5586, 5616, 5645, 5662, 
-	5692, 5722, 5751, 5768, 5798, 5828, 5857, 5868, 
-	5876, 5883, 5886, 5888, 5891, 5894, 5896, 5903, 
-	5915, 5924, 5928, 5937, 5949, 5962, 5975, 5987, 
-	5998, 6011, 6023, 6034, 6047, 6059, 6070, 6083, 
-	6095, 6105, 6118, 6135, 6164, 6176, 6206, 6236, 
-	6253, 6270, 6287, 6304, 6321, 6351, 6381, 6398, 
-	6415, 6432, 6449, 6466, 6496, 6526, 6543, 6560, 
-	6577, 6594, 6611, 6641, 6671, 6688, 6705, 6722, 
-	6739, 6756, 6786, 6818, 6848, 6880, 6892, 6909, 
-	6939, 6969, 6998, 7005, 7008, 7010, 7013, 7016, 
-	7018, 7025, 7055, 7085, 7102, 7115, 7127, 7138, 
-	7151, 7163, 7174, 7187, 7199, 7210, 7223, 7235, 
-	7243, 7255, 7264, 7268, 7277, 7289, 7306, 7315, 
-	7319, 7326, 7329, 7331, 7334, 7337, 7339
+	0, 2, 19, 26, 31, 35, 37, 42, 
+	46, 48, 53, 57, 59, 64, 68, 70, 
+	76, 78, 80, 86, 88, 90, 96, 98, 
+	100, 106, 108, 110, 122, 134, 146, 158, 
+	170, 182, 194, 206, 218, 230, 232, 249, 
+	256, 261, 265, 267, 272, 276, 278, 283, 
+	287, 289, 294, 298, 300, 306, 308, 310, 
+	316, 318, 320, 326, 328, 330, 336, 338, 
+	340, 352, 364, 376, 388, 400, 412, 424, 
+	436, 448, 460, 462, 479, 486, 491, 495, 
+	497, 502, 506, 508, 513, 517, 519, 524, 
+	528, 530, 536, 538, 540, 546, 548, 550, 
+	556, 558, 560, 566, 568, 570, 582, 594, 
+	606, 618, 630, 642, 654, 666, 678, 680, 
+	697, 704, 709, 713, 715, 720, 724, 726, 
+	731, 735, 737, 742, 746, 748, 754, 756, 
+	758, 764, 766, 768, 774, 776, 778, 784, 
+	786, 788, 800, 812, 824, 836, 848, 860, 
+	872, 884, 896, 908, 920, 925, 937, 949, 
+	954, 958, 963, 967, 969, 974, 978, 980, 
+	985, 989, 991, 993, 1010, 1017, 1023, 1025, 
+	1027, 1033, 1035, 1037, 1043, 1045, 1047, 1053, 
+	1055, 1057, 1059, 1091, 1121, 1151, 1180, 1197, 
+	1227, 1257, 1286, 1303, 1333, 1363, 1392, 1409, 
+	1439, 1469, 1498, 1515, 1545, 1575, 1604, 1615, 
+	1626, 1633, 1636, 1638, 1641, 1644, 1646, 1653, 
+	1665, 1674, 1681, 1690, 1702, 1715, 1728, 1740, 
+	1751, 1764, 1776, 1787, 1800, 1812, 1823, 1836, 
+	1848, 1859, 1872, 1889, 1918, 1930, 1960, 1990, 
+	2007, 2024, 2041, 2058, 2075, 2105, 2135, 2152, 
+	2169, 2186, 2203, 2220, 2250, 2280, 2297, 2314, 
+	2331, 2348, 2365, 2395, 2425, 2442, 2459, 2476, 
+	2493, 2510, 2540, 2570, 2600, 2630, 2659, 2676, 
+	2706, 2736, 2765, 2782, 2812, 2842, 2871, 2888, 
+	2918, 2948, 2977, 2994, 3024, 3054, 3083, 3094, 
+	3105, 3112, 3115, 3117, 3120, 3123, 3125, 3132, 
+	3144, 3153, 3160, 3169, 3181, 3194, 3207, 3219, 
+	3230, 3243, 3255, 3266, 3279, 3291, 3302, 3315, 
+	3327, 3338, 3351, 3368, 3397, 3409, 3439, 3469, 
+	3486, 3503, 3520, 3537, 3554, 3584, 3614, 3631, 
+	3648, 3665, 3682, 3699, 3729, 3759, 3776, 3793, 
+	3810, 3827, 3844, 3874, 3904, 3921, 3938, 3955, 
+	3972, 3984, 4001, 4031, 4061, 4090, 4107, 4137, 
+	4167, 4196, 4213, 4243, 4273, 4302, 4319, 4349, 
+	4379, 4408, 4425, 4455, 4485, 4514, 4525, 4536, 
+	4543, 4546, 4548, 4551, 4554, 4556, 4563, 4575, 
+	4584, 4591, 4600, 4612, 4625, 4638, 4650, 4661, 
+	4674, 4686, 4697, 4710, 4722, 4733, 4746, 4758, 
+	4769, 4782, 4799, 4828, 4840, 4870, 4900, 4917, 
+	4934, 4951, 4968, 4985, 5015, 5045, 5062, 5079, 
+	5096, 5113, 5130, 5160, 5190, 5207, 5224, 5241, 
+	5258, 5275, 5305, 5335, 5352, 5369, 5386, 5403, 
+	5420, 5432, 5462, 5474, 5504, 5534, 5563, 5580, 
+	5610, 5640, 5669, 5686, 5716, 5746, 5775, 5792, 
+	5822, 5852, 5881, 5898, 5928, 5958, 5987, 5998, 
+	6009, 6016, 6019, 6021, 6024, 6027, 6029, 6036, 
+	6048, 6057, 6064, 6073, 6085, 6098, 6111, 6123, 
+	6134, 6147, 6159, 6170, 6183, 6195, 6206, 6219, 
+	6231, 6242, 6255, 6272, 6301, 6313, 6343, 6373, 
+	6390, 6407, 6424, 6441, 6458, 6488, 6518, 6535, 
+	6552, 6569, 6586, 6603, 6633, 6663, 6680, 6697, 
+	6714, 6731, 6748, 6778, 6808, 6825, 6842, 6859, 
+	6876, 6893, 6923, 6955, 6985, 7017, 7029, 7036, 
+	7039, 7041, 7044, 7047, 7049, 7056, 7073, 7103, 
+	7133, 7162, 7192, 7222, 7239, 7252, 7264, 7275, 
+	7288, 7300, 7311, 7324, 7336, 7347, 7360, 7372, 
+	7383, 7395, 7404, 7411, 7420, 7432, 7449, 7458, 
+	7465, 7472, 7475, 7477, 7480, 7483, 7485
 };
 
 static const short _indic_syllable_machine_indicies[] = {
-	1, 2, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 1, 
-	0, 3, 0, 4, 4, 5, 0, 6, 
-	6, 5, 0, 5, 0, 7, 7, 8, 
-	0, 9, 9, 8, 0, 8, 0, 10, 
-	10, 11, 0, 12, 12, 11, 0, 11, 
-	0, 13, 13, 14, 0, 15, 15, 14, 
-	0, 14, 0, 16, 0, 17, 0, 18, 
-	0, 19, 13, 13, 14, 0, 20, 0, 
-	21, 0, 22, 10, 10, 11, 0, 23, 
-	0, 24, 0, 25, 7, 7, 8, 0, 
-	26, 0, 27, 0, 28, 4, 4, 5, 
-	0, 0, 0, 0, 0, 0, 28, 0, 
-	28, 4, 4, 5, 0, 0, 0, 0, 
-	0, 29, 28, 0, 30, 4, 4, 5, 
-	0, 0, 0, 0, 0, 0, 30, 0, 
-	30, 4, 4, 5, 0, 0, 0, 0, 
-	0, 31, 30, 0, 32, 4, 4, 5, 
-	0, 0, 0, 0, 0, 0, 32, 0, 
-	32, 4, 4, 5, 0, 0, 0, 0, 
-	0, 33, 32, 0, 34, 4, 4, 5, 
-	0, 0, 0, 0, 0, 0, 34, 0, 
-	34, 4, 4, 5, 0, 0, 0, 0, 
-	0, 35, 34, 0, 36, 4, 4, 5, 
-	0, 0, 0, 0, 0, 0, 36, 0, 
-	36, 4, 4, 5, 0, 0, 0, 0, 
-	0, 37, 36, 0, 39, 40, 38, 38, 
-	38, 38, 38, 38, 38, 38, 38, 38, 
-	38, 38, 38, 39, 38, 41, 38, 42, 
-	42, 43, 38, 44, 44, 43, 38, 43, 
-	38, 45, 45, 46, 38, 47, 47, 46, 
-	38, 46, 38, 48, 48, 49, 38, 50, 
-	50, 49, 38, 49, 38, 51, 51, 52, 
-	38, 53, 53, 52, 38, 52, 38, 54, 
-	38, 55, 38, 56, 38, 57, 51, 51, 
-	52, 38, 58, 38, 59, 38, 60, 48, 
-	48, 49, 38, 61, 38, 62, 38, 63, 
-	45, 45, 46, 38, 64, 38, 65, 38, 
-	66, 42, 42, 43, 38, 38, 38, 38, 
-	38, 38, 66, 38, 66, 42, 42, 43, 
-	38, 38, 38, 38, 38, 67, 66, 38, 
-	68, 42, 42, 43, 38, 38, 38, 38, 
-	38, 38, 68, 38, 68, 42, 42, 43, 
-	38, 38, 38, 38, 38, 69, 68, 38, 
-	70, 42, 42, 43, 38, 38, 38, 38, 
-	38, 38, 70, 38, 70, 42, 42, 43, 
-	38, 38, 38, 38, 38, 71, 70, 38, 
-	72, 42, 42, 43, 38, 38, 38, 38, 
-	38, 38, 72, 38, 72, 42, 42, 43, 
-	38, 38, 38, 38, 38, 73, 72, 38, 
-	74, 42, 42, 43, 38, 38, 38, 38, 
-	38, 38, 74, 38, 74, 42, 42, 43, 
-	38, 38, 38, 38, 38, 75, 74, 38, 
-	77, 78, 76, 76, 76, 76, 76, 76, 
-	76, 76, 76, 76, 76, 76, 76, 77, 
-	76, 79, 76, 80, 80, 81, 76, 83, 
-	83, 81, 82, 81, 82, 84, 84, 85, 
-	76, 86, 86, 85, 76, 85, 76, 87, 
-	87, 88, 76, 89, 89, 88, 76, 88, 
-	76, 90, 90, 91, 76, 92, 92, 91, 
-	76, 91, 76, 93, 76, 94, 76, 95, 
-	76, 96, 90, 90, 91, 76, 97, 76, 
-	98, 76, 99, 87, 87, 88, 76, 100, 
-	76, 101, 76, 102, 84, 84, 85, 76, 
-	103, 76, 104, 76, 105, 80, 80, 81, 
-	76, 76, 76, 76, 76, 76, 105, 76, 
-	105, 80, 80, 81, 76, 76, 76, 76, 
-	76, 106, 105, 76, 107, 80, 80, 81, 
-	76, 76, 76, 76, 76, 76, 107, 76, 
-	107, 80, 80, 81, 76, 76, 76, 76, 
-	76, 108, 107, 76, 109, 80, 80, 81, 
-	76, 76, 76, 76, 76, 76, 109, 76, 
-	109, 80, 80, 81, 76, 76, 76, 76, 
-	76, 110, 109, 76, 111, 80, 80, 81, 
-	82, 82, 82, 82, 82, 82, 111, 82, 
-	111, 80, 80, 81, 76, 76, 76, 76, 
-	76, 112, 111, 76, 113, 80, 80, 81, 
-	76, 76, 76, 76, 76, 76, 113, 76, 
-	115, 116, 114, 114, 114, 114, 114, 114, 
-	114, 114, 114, 114, 114, 114, 114, 115, 
-	114, 117, 114, 118, 118, 119, 114, 120, 
-	120, 119, 114, 119, 114, 121, 121, 122, 
-	114, 123, 123, 122, 114, 122, 114, 124, 
-	124, 125, 114, 126, 126, 125, 114, 125, 
-	114, 127, 127, 128, 114, 129, 129, 128, 
-	114, 128, 114, 130, 114, 131, 114, 132, 
-	114, 133, 127, 127, 128, 114, 134, 114, 
-	135, 114, 136, 124, 124, 125, 114, 137, 
-	114, 138, 114, 139, 121, 121, 122, 114, 
-	140, 114, 141, 114, 142, 118, 118, 119, 
-	114, 114, 114, 114, 114, 114, 142, 114, 
-	142, 118, 118, 119, 114, 114, 114, 114, 
-	114, 143, 142, 114, 144, 118, 118, 119, 
-	114, 114, 114, 114, 114, 114, 144, 114, 
-	144, 118, 118, 119, 114, 114, 114, 114, 
-	114, 145, 144, 114, 146, 118, 118, 119, 
-	114, 114, 114, 114, 114, 114, 146, 114, 
-	146, 118, 118, 119, 114, 114, 114, 114, 
-	114, 147, 146, 114, 148, 118, 118, 119, 
-	114, 114, 114, 114, 114, 114, 148, 114, 
-	148, 118, 118, 119, 114, 114, 114, 114, 
-	114, 149, 148, 114, 150, 118, 118, 119, 
-	114, 114, 114, 114, 114, 114, 150, 114, 
-	150, 118, 118, 119, 114, 114, 114, 114, 
-	114, 151, 150, 114, 113, 80, 80, 81, 
-	76, 76, 76, 76, 76, 152, 113, 76, 
-	111, 80, 80, 81, 0, 0, 0, 0, 
-	0, 153, 111, 0, 154, 154, 155, 0, 
-	6, 6, 155, 0, 156, 156, 157, 0, 
-	158, 158, 157, 0, 157, 0, 159, 159, 
-	160, 0, 161, 161, 160, 0, 160, 0, 
-	162, 162, 163, 0, 164, 164, 163, 0, 
-	163, 0, 165, 166, 0, 0, 0, 0, 
+	1, 0, 2, 3, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 2, 0, 1, 0, 0, 0, 0, 
+	4, 0, 5, 5, 6, 1, 0, 7, 
+	7, 6, 0, 6, 0, 8, 8, 9, 
+	1, 0, 10, 10, 9, 0, 9, 0, 
+	11, 11, 12, 1, 0, 13, 13, 12, 
+	0, 12, 0, 14, 14, 15, 1, 0, 
+	16, 16, 15, 0, 15, 0, 17, 0, 
+	0, 0, 1, 0, 18, 0, 19, 0, 
+	20, 14, 14, 15, 1, 0, 21, 0, 
+	22, 0, 23, 11, 11, 12, 1, 0, 
+	24, 0, 25, 0, 26, 8, 8, 9, 
+	1, 0, 27, 0, 28, 0, 29, 5, 
+	5, 6, 1, 0, 0, 0, 0, 0, 
+	29, 0, 29, 5, 5, 6, 1, 0, 
+	0, 0, 0, 30, 29, 0, 31, 5, 
+	5, 6, 1, 0, 0, 0, 0, 0, 
+	31, 0, 31, 5, 5, 6, 1, 0, 
+	0, 0, 0, 32, 31, 0, 33, 5, 
+	5, 6, 1, 0, 0, 0, 0, 0, 
+	33, 0, 33, 5, 5, 6, 1, 0, 
+	0, 0, 0, 34, 33, 0, 35, 5, 
+	5, 6, 1, 0, 0, 0, 0, 0, 
+	35, 0, 35, 5, 5, 6, 1, 0, 
+	0, 0, 0, 36, 35, 0, 37, 5, 
+	5, 6, 1, 0, 0, 0, 0, 0, 
+	37, 0, 37, 5, 5, 6, 1, 0, 
+	0, 0, 0, 38, 37, 0, 40, 39, 
+	41, 42, 39, 39, 39, 39, 39, 39, 
+	39, 39, 39, 39, 39, 39, 39, 41, 
+	39, 40, 39, 39, 39, 39, 43, 39, 
+	44, 44, 45, 40, 39, 46, 46, 45, 
+	39, 45, 39, 47, 47, 48, 40, 39, 
+	49, 49, 48, 39, 48, 39, 50, 50, 
+	51, 40, 39, 52, 52, 51, 39, 51, 
+	39, 53, 53, 54, 40, 39, 55, 55, 
+	54, 39, 54, 39, 56, 39, 39, 39, 
+	40, 39, 57, 39, 58, 39, 59, 53, 
+	53, 54, 40, 39, 60, 39, 61, 39, 
+	62, 50, 50, 51, 40, 39, 63, 39, 
+	64, 39, 65, 47, 47, 48, 40, 39, 
+	66, 39, 67, 39, 68, 44, 44, 45, 
+	40, 39, 39, 39, 39, 39, 68, 39, 
+	68, 44, 44, 45, 40, 39, 39, 39, 
+	39, 69, 68, 39, 70, 44, 44, 45, 
+	40, 39, 39, 39, 39, 39, 70, 39, 
+	70, 44, 44, 45, 40, 39, 39, 39, 
+	39, 71, 70, 39, 72, 44, 44, 45, 
+	40, 39, 39, 39, 39, 39, 72, 39, 
+	72, 44, 44, 45, 40, 39, 39, 39, 
+	39, 73, 72, 39, 74, 44, 44, 45, 
+	40, 39, 39, 39, 39, 39, 74, 39, 
+	74, 44, 44, 45, 40, 39, 39, 39, 
+	39, 75, 74, 39, 76, 44, 44, 45, 
+	40, 39, 39, 39, 39, 39, 76, 39, 
+	76, 44, 44, 45, 40, 39, 39, 39, 
+	39, 77, 76, 39, 79, 78, 80, 81, 
+	78, 78, 78, 78, 78, 78, 78, 78, 
+	78, 78, 78, 78, 78, 80, 78, 79, 
+	78, 78, 78, 78, 82, 78, 83, 83, 
+	84, 79, 78, 86, 86, 84, 85, 84, 
+	85, 87, 87, 88, 79, 78, 89, 89, 
+	88, 78, 88, 78, 90, 90, 91, 79, 
+	78, 92, 92, 91, 78, 91, 78, 93, 
+	93, 94, 79, 78, 95, 95, 94, 78, 
+	94, 78, 96, 78, 78, 78, 79, 78, 
+	97, 78, 98, 78, 99, 93, 93, 94, 
+	79, 78, 100, 78, 101, 78, 102, 90, 
+	90, 91, 79, 78, 103, 78, 104, 78, 
+	105, 87, 87, 88, 79, 78, 106, 78, 
+	107, 78, 108, 83, 83, 84, 79, 78, 
+	78, 78, 78, 78, 108, 78, 108, 83, 
+	83, 84, 79, 78, 78, 78, 78, 109, 
+	108, 78, 110, 83, 83, 84, 79, 78, 
+	78, 78, 78, 78, 110, 78, 110, 83, 
+	83, 84, 79, 78, 78, 78, 78, 111, 
+	110, 78, 112, 83, 83, 84, 79, 78, 
+	78, 78, 78, 78, 112, 78, 112, 83, 
+	83, 84, 79, 78, 78, 78, 78, 113, 
+	112, 78, 114, 83, 83, 84, 79, 78, 
+	78, 78, 78, 78, 114, 78, 114, 83, 
+	83, 84, 79, 78, 78, 78, 78, 115, 
+	114, 78, 116, 83, 83, 84, 79, 78, 
+	78, 78, 78, 78, 116, 78, 118, 117, 
+	119, 120, 117, 117, 117, 117, 117, 117, 
+	117, 117, 117, 117, 117, 117, 117, 119, 
+	117, 118, 117, 117, 117, 117, 121, 117, 
+	122, 122, 123, 118, 117, 124, 124, 123, 
+	117, 123, 117, 125, 125, 126, 118, 117, 
+	127, 127, 126, 117, 126, 117, 128, 128, 
+	129, 118, 117, 130, 130, 129, 117, 129, 
+	117, 131, 131, 132, 118, 117, 133, 133, 
+	132, 117, 132, 117, 134, 117, 117, 117, 
+	118, 117, 135, 117, 136, 117, 137, 131, 
+	131, 132, 118, 117, 138, 117, 139, 117, 
+	140, 128, 128, 129, 118, 117, 141, 117, 
+	142, 117, 143, 125, 125, 126, 118, 117, 
+	144, 117, 145, 117, 146, 122, 122, 123, 
+	118, 117, 117, 117, 117, 117, 146, 117, 
+	146, 122, 122, 123, 118, 117, 117, 117, 
+	117, 147, 146, 117, 148, 122, 122, 123, 
+	118, 117, 117, 117, 117, 117, 148, 117, 
+	148, 122, 122, 123, 118, 117, 117, 117, 
+	117, 149, 148, 117, 150, 122, 122, 123, 
+	118, 117, 117, 117, 117, 117, 150, 117, 
+	150, 122, 122, 123, 118, 117, 117, 117, 
+	117, 151, 150, 117, 152, 122, 122, 123, 
+	118, 117, 117, 117, 117, 117, 152, 117, 
+	152, 122, 122, 123, 118, 117, 117, 117, 
+	117, 153, 152, 117, 154, 122, 122, 123, 
+	118, 117, 117, 117, 117, 117, 154, 117, 
+	154, 122, 122, 123, 118, 117, 117, 117, 
+	117, 155, 154, 117, 116, 83, 83, 84, 
+	79, 78, 78, 78, 78, 156, 116, 78, 
+	86, 86, 84, 1, 0, 114, 83, 83, 
+	84, 157, 0, 0, 0, 0, 0, 114, 
+	0, 114, 83, 83, 84, 157, 0, 0, 
+	0, 0, 158, 114, 0, 159, 159, 160, 
+	1, 0, 7, 7, 160, 0, 161, 161, 
+	162, 157, 0, 163, 163, 162, 0, 162, 
+	0, 164, 164, 165, 157, 0, 166, 166, 
+	165, 0, 165, 0, 167, 167, 168, 157, 
+	0, 169, 169, 168, 0, 168, 0, 157, 
+	0, 170, 171, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 165, 0, 167, 0, 168, 0, 169, 
-	0, 170, 0, 171, 162, 162, 163, 0, 
-	172, 0, 173, 0, 174, 159, 159, 160, 
-	0, 175, 0, 176, 0, 177, 156, 156, 
-	157, 0, 178, 0, 179, 0, 181, 182, 
-	183, 184, 185, 186, 81, 187, 188, 189, 
-	190, 190, 152, 191, 192, 193, 194, 195, 
-	180, 180, 180, 180, 180, 180, 180, 180, 
-	180, 180, 180, 180, 196, 180, 198, 199, 
-	200, 201, 5, 202, 203, 204, 197, 197, 
-	37, 205, 197, 197, 206, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 207, 197, 208, 199, 209, 209, 
-	5, 202, 203, 204, 197, 197, 197, 205, 
-	197, 197, 206, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	207, 197, 199, 209, 209, 5, 202, 203, 
-	204, 197, 197, 197, 205, 197, 197, 206, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 207, 197, 210, 
-	197, 197, 197, 18, 211, 197, 202, 203, 
-	204, 197, 197, 197, 212, 197, 210, 197, 
-	213, 214, 215, 216, 5, 202, 203, 204, 
-	197, 197, 35, 217, 197, 197, 206, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 207, 197, 218, 214, 
-	219, 219, 5, 202, 203, 204, 197, 197, 
-	197, 217, 197, 197, 206, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 207, 197, 214, 219, 219, 5, 
-	202, 203, 204, 197, 197, 197, 217, 197, 
-	197, 206, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 207, 
-	197, 220, 197, 197, 197, 18, 221, 197, 
-	202, 203, 204, 197, 197, 197, 212, 197, 
-	220, 197, 222, 223, 224, 225, 5, 202, 
-	203, 204, 197, 197, 33, 226, 197, 197, 
-	206, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 207, 197, 
-	227, 223, 228, 228, 5, 202, 203, 204, 
-	197, 197, 197, 226, 197, 197, 206, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 207, 197, 223, 228, 
-	228, 5, 202, 203, 204, 197, 197, 197, 
-	226, 197, 197, 206, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 207, 197, 229, 197, 197, 197, 18, 
-	230, 197, 202, 203, 204, 197, 197, 197, 
-	212, 197, 229, 197, 231, 232, 233, 234, 
-	5, 202, 203, 204, 197, 197, 31, 235, 
-	197, 197, 206, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	207, 197, 236, 232, 237, 237, 5, 202, 
-	203, 204, 197, 197, 197, 235, 197, 197, 
-	206, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 207, 197, 
-	232, 237, 237, 5, 202, 203, 204, 197, 
-	197, 197, 235, 197, 197, 206, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 207, 197, 238, 197, 197, 
-	197, 18, 239, 197, 202, 203, 204, 197, 
-	197, 197, 212, 197, 238, 197, 240, 241, 
-	242, 243, 5, 202, 203, 204, 197, 197, 
-	29, 244, 197, 197, 206, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 207, 197, 245, 241, 246, 246, 
-	5, 202, 203, 204, 197, 197, 197, 244, 
-	197, 197, 206, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	207, 197, 241, 246, 246, 5, 202, 203, 
-	204, 197, 197, 197, 244, 197, 197, 206, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 207, 197, 18, 
-	247, 197, 202, 203, 204, 197, 197, 197, 
-	212, 197, 202, 203, 204, 197, 197, 197, 
-	212, 197, 248, 197, 197, 249, 203, 204, 
-	197, 203, 204, 197, 250, 197, 203, 251, 
-	197, 203, 252, 197, 203, 197, 248, 197, 
-	197, 197, 203, 204, 197, 253, 197, 254, 
-	255, 197, 202, 203, 204, 197, 197, 3, 
-	197, 2, 197, 197, 197, 197, 202, 203, 
-	204, 197, 202, 203, 204, 197, 253, 197, 
-	197, 197, 197, 202, 203, 204, 197, 253, 
-	197, 254, 197, 197, 202, 203, 204, 197, 
-	197, 3, 197, 18, 197, 256, 256, 5, 
-	202, 203, 204, 197, 197, 197, 212, 197, 
-	257, 27, 258, 259, 8, 202, 203, 204, 
-	197, 197, 197, 212, 197, 27, 258, 259, 
-	8, 202, 203, 204, 197, 197, 197, 212, 
-	197, 258, 258, 8, 202, 203, 204, 197, 
-	197, 197, 212, 197, 260, 24, 261, 262, 
-	11, 202, 203, 204, 197, 197, 197, 212, 
-	197, 24, 261, 262, 11, 202, 203, 204, 
-	197, 197, 197, 212, 197, 261, 261, 11, 
-	202, 203, 204, 197, 197, 197, 212, 197, 
-	263, 21, 264, 265, 14, 202, 203, 204, 
-	197, 197, 197, 212, 197, 21, 264, 265, 
-	14, 202, 203, 204, 197, 197, 197, 212, 
-	197, 264, 264, 14, 202, 203, 204, 197, 
-	197, 197, 212, 197, 266, 18, 197, 267, 
-	197, 202, 203, 204, 197, 197, 197, 212, 
-	197, 18, 197, 267, 197, 202, 203, 204, 
-	197, 197, 197, 212, 197, 268, 197, 202, 
-	203, 204, 197, 197, 197, 212, 197, 18, 
-	197, 197, 197, 197, 202, 203, 204, 197, 
-	197, 197, 212, 197, 1, 2, 197, 197, 
-	18, 247, 197, 202, 203, 204, 197, 197, 
-	197, 212, 197, 1, 197, 241, 246, 246, 
-	5, 202, 203, 204, 197, 197, 197, 244, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	207, 197, 241, 246, 246, 5, 202, 203, 
-	204, 197, 197, 197, 244, 197, 240, 241, 
-	246, 246, 5, 202, 203, 204, 197, 197, 
-	197, 244, 197, 197, 206, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 207, 197, 240, 241, 242, 246, 
-	5, 202, 203, 204, 197, 197, 29, 244, 
-	197, 197, 206, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	207, 197, 238, 197, 269, 197, 256, 256, 
-	5, 202, 203, 204, 197, 197, 197, 212, 
-	197, 238, 197, 238, 197, 197, 197, 197, 
-	197, 197, 202, 203, 204, 197, 197, 197, 
-	212, 197, 238, 197, 238, 197, 197, 197, 
-	197, 270, 197, 202, 203, 204, 197, 197, 
-	197, 212, 197, 238, 197, 238, 197, 269, 
-	197, 197, 197, 197, 202, 203, 204, 197, 
-	197, 197, 212, 197, 238, 197, 238, 2, 
-	197, 197, 18, 239, 197, 202, 203, 204, 
-	197, 197, 197, 212, 197, 238, 197, 231, 
-	232, 237, 237, 5, 202, 203, 204, 197, 
-	197, 197, 235, 197, 197, 206, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 207, 197, 231, 232, 233, 
-	237, 5, 202, 203, 204, 197, 197, 31, 
-	235, 197, 197, 206, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 207, 197, 229, 197, 271, 197, 256, 
-	256, 5, 202, 203, 204, 197, 197, 197, 
-	212, 197, 229, 197, 229, 197, 197, 197, 
-	197, 197, 197, 202, 203, 204, 197, 197, 
-	197, 212, 197, 229, 197, 229, 197, 197, 
-	197, 197, 272, 197, 202, 203, 204, 197, 
-	197, 197, 212, 197, 229, 197, 229, 197, 
-	271, 197, 197, 197, 197, 202, 203, 204, 
-	197, 197, 197, 212, 197, 229, 197, 229, 
-	2, 197, 197, 18, 230, 197, 202, 203, 
-	204, 197, 197, 197, 212, 197, 229, 197, 
-	222, 223, 228, 228, 5, 202, 203, 204, 
-	197, 197, 197, 226, 197, 197, 206, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 207, 197, 222, 223, 
-	224, 228, 5, 202, 203, 204, 197, 197, 
-	33, 226, 197, 197, 206, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 207, 197, 220, 197, 273, 197, 
-	256, 256, 5, 202, 203, 204, 197, 197, 
-	197, 212, 197, 220, 197, 220, 197, 197, 
-	197, 197, 197, 197, 202, 203, 204, 197, 
-	197, 197, 212, 197, 220, 197, 220, 197, 
-	197, 197, 197, 274, 197, 202, 203, 204, 
-	197, 197, 197, 212, 197, 220, 197, 220, 
-	197, 273, 197, 197, 197, 197, 202, 203, 
-	204, 197, 197, 197, 212, 197, 220, 197, 
-	220, 2, 197, 197, 18, 221, 197, 202, 
-	203, 204, 197, 197, 197, 212, 197, 220, 
-	197, 213, 214, 219, 219, 5, 202, 203, 
-	204, 197, 197, 197, 217, 197, 197, 206, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 207, 197, 213, 
-	214, 215, 219, 5, 202, 203, 204, 197, 
-	197, 35, 217, 197, 197, 206, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 207, 197, 210, 197, 275, 
-	197, 256, 256, 5, 202, 203, 204, 197, 
-	197, 197, 212, 197, 210, 197, 210, 197, 
-	197, 197, 197, 197, 197, 202, 203, 204, 
-	197, 197, 197, 212, 197, 210, 197, 210, 
-	197, 197, 197, 197, 276, 197, 202, 203, 
-	204, 197, 197, 197, 212, 197, 210, 197, 
-	210, 197, 275, 197, 197, 197, 197, 202, 
-	203, 204, 197, 197, 197, 212, 197, 210, 
-	197, 210, 2, 197, 197, 18, 211, 197, 
-	202, 203, 204, 197, 197, 197, 212, 197, 
-	210, 197, 198, 199, 209, 209, 5, 202, 
-	203, 204, 197, 197, 197, 205, 197, 197, 
-	206, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 207, 197, 
-	198, 199, 200, 209, 5, 202, 203, 204, 
-	197, 197, 37, 205, 197, 197, 206, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 207, 197, 278, 279, 
-	280, 281, 43, 282, 283, 284, 277, 277, 
-	75, 285, 277, 277, 286, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 287, 277, 288, 279, 289, 281, 
-	43, 282, 283, 284, 277, 277, 277, 285, 
-	277, 277, 286, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	287, 277, 279, 289, 281, 43, 282, 283, 
-	284, 277, 277, 277, 285, 277, 277, 286, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 287, 277, 290, 
-	277, 277, 277, 56, 291, 277, 282, 283, 
-	284, 277, 277, 277, 292, 277, 290, 277, 
-	293, 294, 295, 296, 43, 282, 283, 284, 
-	277, 277, 73, 297, 277, 277, 286, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 287, 277, 298, 294, 
-	299, 299, 43, 282, 283, 284, 277, 277, 
-	277, 297, 277, 277, 286, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 287, 277, 294, 299, 299, 43, 
-	282, 283, 284, 277, 277, 277, 297, 277, 
-	277, 286, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 287, 
-	277, 300, 277, 277, 277, 56, 301, 277, 
-	282, 283, 284, 277, 277, 277, 292, 277, 
-	300, 277, 302, 303, 304, 305, 43, 282, 
-	283, 284, 277, 277, 71, 306, 277, 277, 
-	286, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 287, 277, 
-	307, 303, 308, 308, 43, 282, 283, 284, 
-	277, 277, 277, 306, 277, 277, 286, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 287, 277, 303, 308, 
-	308, 43, 282, 283, 284, 277, 277, 277, 
-	306, 277, 277, 286, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 287, 277, 309, 277, 277, 277, 56, 
-	310, 277, 282, 283, 284, 277, 277, 277, 
-	292, 277, 309, 277, 311, 312, 313, 314, 
-	43, 282, 283, 284, 277, 277, 69, 315, 
-	277, 277, 286, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	287, 277, 316, 312, 317, 317, 43, 282, 
-	283, 284, 277, 277, 277, 315, 277, 277, 
-	286, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 287, 277, 
-	312, 317, 317, 43, 282, 283, 284, 277, 
-	277, 277, 315, 277, 277, 286, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 287, 277, 318, 277, 277, 
-	277, 56, 319, 277, 282, 283, 284, 277, 
-	277, 277, 292, 277, 318, 277, 320, 321, 
-	322, 323, 43, 282, 283, 284, 277, 277, 
-	67, 324, 277, 277, 286, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 287, 277, 325, 321, 326, 326, 
-	43, 282, 283, 284, 277, 277, 277, 324, 
-	277, 277, 286, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	287, 277, 321, 326, 326, 43, 282, 283, 
-	284, 277, 277, 277, 324, 277, 277, 286, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 287, 277, 56, 
-	327, 277, 282, 283, 284, 277, 277, 277, 
-	292, 277, 282, 283, 284, 277, 277, 277, 
-	292, 277, 328, 277, 277, 329, 283, 284, 
-	277, 283, 284, 277, 330, 277, 283, 331, 
-	277, 283, 332, 277, 283, 277, 328, 277, 
-	277, 277, 283, 284, 277, 333, 277, 334, 
-	335, 277, 282, 283, 284, 277, 277, 41, 
-	277, 40, 277, 277, 277, 277, 282, 283, 
-	284, 277, 282, 283, 284, 277, 333, 277, 
-	277, 277, 277, 282, 283, 284, 277, 333, 
-	277, 334, 277, 277, 282, 283, 284, 277, 
-	277, 41, 277, 56, 277, 336, 336, 43, 
-	282, 283, 284, 277, 277, 277, 292, 277, 
-	337, 65, 338, 339, 46, 282, 283, 284, 
-	277, 277, 277, 292, 277, 65, 338, 339, 
-	46, 282, 283, 284, 277, 277, 277, 292, 
-	277, 338, 338, 46, 282, 283, 284, 277, 
-	277, 277, 292, 277, 340, 62, 341, 342, 
-	49, 282, 283, 284, 277, 277, 277, 292, 
-	277, 62, 341, 342, 49, 282, 283, 284, 
-	277, 277, 277, 292, 277, 341, 341, 49, 
-	282, 283, 284, 277, 277, 277, 292, 277, 
-	343, 59, 344, 345, 52, 282, 283, 284, 
-	277, 277, 277, 292, 277, 59, 344, 345, 
-	52, 282, 283, 284, 277, 277, 277, 292, 
-	277, 344, 344, 52, 282, 283, 284, 277, 
-	277, 277, 292, 277, 346, 56, 277, 347, 
-	277, 282, 283, 284, 277, 277, 277, 292, 
-	277, 56, 277, 347, 277, 282, 283, 284, 
-	277, 277, 277, 292, 277, 348, 277, 282, 
-	283, 284, 277, 277, 277, 292, 277, 56, 
-	277, 277, 277, 277, 282, 283, 284, 277, 
-	277, 277, 292, 277, 39, 40, 277, 277, 
-	56, 327, 277, 282, 283, 284, 277, 277, 
-	277, 292, 277, 39, 277, 321, 326, 326, 
-	43, 282, 283, 284, 277, 277, 277, 324, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	287, 277, 321, 326, 326, 43, 282, 283, 
-	284, 277, 277, 277, 324, 277, 320, 321, 
-	326, 326, 43, 282, 283, 284, 277, 277, 
-	277, 324, 277, 277, 286, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 287, 277, 320, 321, 322, 326, 
-	43, 282, 283, 284, 277, 277, 67, 324, 
-	277, 277, 286, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	287, 277, 318, 277, 349, 277, 336, 336, 
-	43, 282, 283, 284, 277, 277, 277, 292, 
-	277, 318, 277, 318, 277, 277, 277, 277, 
-	277, 277, 282, 283, 284, 277, 277, 277, 
-	292, 277, 318, 277, 318, 277, 277, 277, 
-	277, 350, 277, 282, 283, 284, 277, 277, 
-	277, 292, 277, 318, 277, 318, 277, 349, 
-	277, 277, 277, 277, 282, 283, 284, 277, 
-	277, 277, 292, 277, 318, 277, 318, 40, 
-	277, 277, 56, 319, 277, 282, 283, 284, 
-	277, 277, 277, 292, 277, 318, 277, 311, 
-	312, 317, 317, 43, 282, 283, 284, 277, 
-	277, 277, 315, 277, 277, 286, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 287, 277, 311, 312, 313, 
-	317, 43, 282, 283, 284, 277, 277, 69, 
-	315, 277, 277, 286, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 287, 277, 309, 277, 351, 277, 336, 
-	336, 43, 282, 283, 284, 277, 277, 277, 
-	292, 277, 309, 277, 309, 277, 277, 277, 
-	277, 277, 277, 282, 283, 284, 277, 277, 
-	277, 292, 277, 309, 277, 309, 277, 277, 
-	277, 277, 352, 277, 282, 283, 284, 277, 
-	277, 277, 292, 277, 309, 277, 309, 277, 
-	351, 277, 277, 277, 277, 282, 283, 284, 
-	277, 277, 277, 292, 277, 309, 277, 309, 
-	40, 277, 277, 56, 310, 277, 282, 283, 
-	284, 277, 277, 277, 292, 277, 309, 277, 
-	302, 303, 308, 308, 43, 282, 283, 284, 
-	277, 277, 277, 306, 277, 277, 286, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 287, 277, 302, 303, 
-	304, 308, 43, 282, 283, 284, 277, 277, 
-	71, 306, 277, 277, 286, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 287, 277, 300, 277, 353, 277, 
-	336, 336, 43, 282, 283, 284, 277, 277, 
-	277, 292, 277, 300, 277, 300, 277, 277, 
-	277, 277, 277, 277, 282, 283, 284, 277, 
-	277, 277, 292, 277, 300, 277, 300, 277, 
-	277, 277, 277, 354, 277, 282, 283, 284, 
-	277, 277, 277, 292, 277, 300, 277, 300, 
-	277, 353, 277, 277, 277, 277, 282, 283, 
-	284, 277, 277, 277, 292, 277, 300, 277, 
-	300, 40, 277, 277, 56, 301, 277, 282, 
-	283, 284, 277, 277, 277, 292, 277, 300, 
-	277, 293, 294, 299, 299, 43, 282, 283, 
-	284, 277, 277, 277, 297, 277, 277, 286, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 287, 277, 293, 
-	294, 295, 299, 43, 282, 283, 284, 277, 
-	277, 73, 297, 277, 277, 286, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 287, 277, 290, 277, 355, 
-	277, 336, 336, 43, 282, 283, 284, 277, 
-	277, 277, 292, 277, 290, 277, 290, 277, 
-	277, 277, 277, 277, 277, 282, 283, 284, 
-	277, 277, 277, 292, 277, 290, 277, 290, 
-	277, 277, 277, 277, 356, 277, 282, 283, 
-	284, 277, 277, 277, 292, 277, 290, 277, 
-	290, 277, 355, 277, 277, 277, 277, 282, 
-	283, 284, 277, 277, 277, 292, 277, 290, 
-	277, 74, 42, 42, 43, 277, 277, 277, 
-	277, 277, 277, 74, 277, 290, 40, 277, 
-	277, 56, 291, 277, 282, 283, 284, 277, 
-	277, 277, 292, 277, 290, 277, 278, 279, 
-	289, 281, 43, 282, 283, 284, 277, 277, 
-	277, 285, 277, 277, 286, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 287, 277, 358, 184, 359, 359, 
-	81, 187, 188, 189, 357, 357, 357, 191, 
-	357, 357, 194, 357, 357, 357, 357, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	196, 357, 184, 359, 359, 81, 187, 188, 
-	189, 357, 357, 357, 191, 357, 357, 194, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	357, 357, 357, 357, 357, 196, 357, 360, 
-	357, 357, 357, 95, 361, 357, 187, 188, 
-	189, 357, 357, 357, 362, 357, 360, 357, 
-	363, 364, 365, 366, 81, 187, 188, 189, 
-	357, 357, 112, 367, 357, 357, 194, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	357, 357, 357, 357, 196, 357, 368, 364, 
-	369, 369, 81, 187, 188, 189, 357, 357, 
-	357, 367, 357, 357, 194, 357, 357, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	357, 357, 196, 357, 364, 369, 369, 81, 
-	187, 188, 189, 357, 357, 357, 367, 357, 
-	357, 194, 357, 357, 357, 357, 357, 357, 
-	357, 357, 357, 357, 357, 357, 357, 196, 
-	357, 370, 357, 357, 357, 95, 371, 357, 
-	187, 188, 189, 357, 357, 357, 362, 357, 
-	370, 357, 372, 373, 374, 375, 81, 187, 
-	188, 189, 357, 357, 110, 376, 357, 357, 
-	194, 357, 357, 357, 357, 357, 357, 357, 
-	357, 357, 357, 357, 357, 357, 196, 357, 
-	377, 373, 378, 378, 81, 187, 188, 189, 
-	357, 357, 357, 376, 357, 357, 194, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	357, 357, 357, 357, 196, 357, 373, 378, 
-	378, 81, 187, 188, 189, 357, 357, 357, 
-	376, 357, 357, 194, 357, 357, 357, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	357, 196, 357, 379, 357, 357, 357, 95, 
-	380, 357, 187, 188, 189, 357, 357, 357, 
-	362, 357, 379, 357, 381, 382, 383, 384, 
-	81, 187, 188, 189, 357, 357, 108, 385, 
-	357, 357, 194, 357, 357, 357, 357, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	196, 357, 386, 382, 387, 387, 81, 187, 
-	188, 189, 357, 357, 357, 385, 357, 357, 
-	194, 357, 357, 357, 357, 357, 357, 357, 
-	357, 357, 357, 357, 357, 357, 196, 357, 
-	382, 387, 387, 81, 187, 188, 189, 357, 
-	357, 357, 385, 357, 357, 194, 357, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	357, 357, 357, 196, 357, 388, 357, 357, 
-	357, 95, 389, 357, 187, 188, 189, 357, 
-	357, 357, 362, 357, 388, 357, 390, 391, 
-	392, 393, 81, 187, 188, 189, 357, 357, 
-	106, 394, 357, 357, 194, 357, 357, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	357, 357, 196, 357, 395, 391, 396, 396, 
-	81, 187, 188, 189, 357, 357, 357, 394, 
-	357, 357, 194, 357, 357, 357, 357, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	196, 357, 391, 396, 396, 81, 187, 188, 
-	189, 357, 357, 357, 394, 357, 357, 194, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	357, 357, 357, 357, 357, 196, 357, 95, 
-	397, 357, 187, 188, 189, 357, 357, 357, 
-	362, 357, 187, 188, 189, 357, 357, 357, 
-	362, 357, 398, 357, 357, 399, 188, 189, 
-	357, 188, 189, 357, 400, 357, 188, 401, 
-	357, 188, 402, 357, 188, 357, 398, 357, 
-	357, 357, 188, 189, 357, 403, 357, 404, 
-	405, 357, 187, 188, 189, 357, 357, 79, 
-	357, 78, 357, 357, 357, 357, 187, 188, 
-	189, 357, 187, 188, 189, 357, 403, 357, 
-	357, 357, 357, 187, 188, 189, 357, 403, 
-	357, 404, 357, 357, 187, 188, 189, 357, 
-	357, 79, 357, 95, 357, 406, 406, 81, 
-	187, 188, 189, 357, 357, 357, 362, 357, 
-	407, 104, 408, 409, 85, 187, 188, 189, 
-	357, 357, 357, 362, 357, 104, 408, 409, 
-	85, 187, 188, 189, 357, 357, 357, 362, 
-	357, 408, 408, 85, 187, 188, 189, 357, 
-	357, 357, 362, 357, 410, 101, 411, 412, 
-	88, 187, 188, 189, 357, 357, 357, 362, 
-	357, 101, 411, 412, 88, 187, 188, 189, 
-	357, 357, 357, 362, 357, 411, 411, 88, 
-	187, 188, 189, 357, 357, 357, 362, 357, 
-	413, 98, 414, 415, 91, 187, 188, 189, 
-	357, 357, 357, 362, 357, 98, 414, 415, 
-	91, 187, 188, 189, 357, 357, 357, 362, 
-	357, 414, 414, 91, 187, 188, 189, 357, 
-	357, 357, 362, 357, 416, 95, 357, 417, 
-	357, 187, 188, 189, 357, 357, 357, 362, 
-	357, 95, 357, 417, 357, 187, 188, 189, 
-	357, 357, 357, 362, 357, 418, 357, 187, 
-	188, 189, 357, 357, 357, 362, 357, 95, 
-	357, 357, 357, 357, 187, 188, 189, 357, 
-	357, 357, 362, 357, 77, 78, 357, 357, 
-	95, 397, 357, 187, 188, 189, 357, 357, 
-	357, 362, 357, 77, 357, 391, 396, 396, 
-	81, 187, 188, 189, 357, 357, 357, 394, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	196, 357, 391, 396, 396, 81, 187, 188, 
-	189, 357, 357, 357, 394, 357, 390, 391, 
-	396, 396, 81, 187, 188, 189, 357, 357, 
-	357, 394, 357, 357, 194, 357, 357, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	357, 357, 196, 357, 390, 391, 392, 396, 
-	81, 187, 188, 189, 357, 357, 106, 394, 
-	357, 357, 194, 357, 357, 357, 357, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	196, 357, 388, 357, 419, 357, 406, 406, 
-	81, 187, 188, 189, 357, 357, 357, 362, 
-	357, 388, 357, 388, 357, 357, 357, 357, 
-	357, 357, 187, 188, 189, 357, 357, 357, 
-	362, 357, 388, 357, 388, 357, 357, 357, 
-	357, 420, 357, 187, 188, 189, 357, 357, 
-	357, 362, 357, 388, 357, 388, 357, 419, 
-	357, 357, 357, 357, 187, 188, 189, 357, 
-	357, 357, 362, 357, 388, 357, 388, 78, 
-	357, 357, 95, 389, 357, 187, 188, 189, 
-	357, 357, 357, 362, 357, 388, 357, 381, 
-	382, 387, 387, 81, 187, 188, 189, 357, 
-	357, 357, 385, 357, 357, 194, 357, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	357, 357, 357, 196, 357, 381, 382, 383, 
-	387, 81, 187, 188, 189, 357, 357, 108, 
-	385, 357, 357, 194, 357, 357, 357, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	357, 196, 357, 379, 357, 421, 357, 406, 
-	406, 81, 187, 188, 189, 357, 357, 357, 
-	362, 357, 379, 357, 379, 357, 357, 357, 
-	357, 357, 357, 187, 188, 189, 357, 357, 
-	357, 362, 357, 379, 357, 379, 357, 357, 
-	357, 357, 422, 357, 187, 188, 189, 357, 
-	357, 357, 362, 357, 379, 357, 379, 357, 
-	421, 357, 357, 357, 357, 187, 188, 189, 
-	357, 357, 357, 362, 357, 379, 357, 379, 
-	78, 357, 357, 95, 380, 357, 187, 188, 
-	189, 357, 357, 357, 362, 357, 379, 357, 
-	372, 373, 378, 378, 81, 187, 188, 189, 
-	357, 357, 357, 376, 357, 357, 194, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	357, 357, 357, 357, 196, 357, 372, 373, 
-	374, 378, 81, 187, 188, 189, 357, 357, 
-	110, 376, 357, 357, 194, 357, 357, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	357, 357, 196, 357, 370, 357, 423, 357, 
-	406, 406, 81, 187, 188, 189, 357, 357, 
-	357, 362, 357, 370, 357, 370, 357, 357, 
-	357, 357, 357, 357, 187, 188, 189, 357, 
-	357, 357, 362, 357, 370, 357, 370, 357, 
-	357, 357, 357, 424, 357, 187, 188, 189, 
-	357, 357, 357, 362, 357, 370, 357, 370, 
-	357, 423, 357, 357, 357, 357, 187, 188, 
-	189, 357, 357, 357, 362, 357, 370, 357, 
-	370, 78, 357, 357, 95, 371, 357, 187, 
-	188, 189, 357, 357, 357, 362, 357, 370, 
-	357, 363, 364, 369, 369, 81, 187, 188, 
-	189, 357, 357, 357, 367, 357, 357, 194, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	357, 357, 357, 357, 357, 196, 357, 363, 
-	364, 365, 369, 81, 187, 188, 189, 357, 
-	357, 112, 367, 357, 357, 194, 357, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	357, 357, 357, 196, 357, 360, 357, 425, 
-	357, 406, 406, 81, 187, 188, 189, 357, 
-	357, 357, 362, 357, 360, 357, 360, 357, 
-	357, 357, 357, 357, 357, 187, 188, 189, 
-	357, 357, 357, 362, 357, 360, 357, 360, 
-	357, 357, 357, 357, 426, 357, 187, 188, 
-	189, 357, 357, 357, 362, 357, 360, 357, 
-	360, 357, 425, 357, 357, 357, 357, 187, 
-	188, 189, 357, 357, 357, 362, 357, 360, 
-	357, 360, 78, 357, 357, 95, 361, 357, 
-	187, 188, 189, 357, 357, 357, 362, 357, 
-	360, 357, 113, 80, 80, 81, 427, 427, 
-	427, 427, 427, 152, 113, 427, 183, 184, 
-	359, 359, 81, 187, 188, 189, 357, 357, 
-	357, 191, 357, 357, 194, 357, 357, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	357, 357, 196, 357, 113, 80, 80, 81, 
-	427, 427, 427, 427, 427, 427, 113, 427, 
-	429, 430, 431, 432, 119, 433, 434, 435, 
-	428, 428, 151, 436, 428, 428, 437, 428, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 438, 428, 439, 430, 
-	432, 432, 119, 433, 434, 435, 428, 428, 
-	428, 436, 428, 428, 437, 428, 428, 428, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 438, 428, 430, 432, 432, 119, 
-	433, 434, 435, 428, 428, 428, 436, 428, 
-	428, 437, 428, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 428, 428, 428, 438, 
-	428, 440, 428, 428, 428, 132, 441, 428, 
-	433, 434, 435, 428, 428, 428, 442, 428, 
-	440, 428, 443, 444, 445, 446, 119, 433, 
-	434, 435, 428, 428, 149, 447, 428, 428, 
-	437, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 428, 428, 438, 428, 
-	448, 444, 449, 449, 119, 433, 434, 435, 
-	428, 428, 428, 447, 428, 428, 437, 428, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 438, 428, 444, 449, 
-	449, 119, 433, 434, 435, 428, 428, 428, 
-	447, 428, 428, 437, 428, 428, 428, 428, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	428, 438, 428, 450, 428, 428, 428, 132, 
-	451, 428, 433, 434, 435, 428, 428, 428, 
-	442, 428, 450, 428, 452, 453, 454, 455, 
-	119, 433, 434, 435, 428, 428, 147, 456, 
-	428, 428, 437, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	438, 428, 457, 453, 458, 458, 119, 433, 
-	434, 435, 428, 428, 428, 456, 428, 428, 
-	437, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 428, 428, 438, 428, 
-	453, 458, 458, 119, 433, 434, 435, 428, 
-	428, 428, 456, 428, 428, 437, 428, 428, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 428, 438, 428, 459, 428, 428, 
-	428, 132, 460, 428, 433, 434, 435, 428, 
-	428, 428, 442, 428, 459, 428, 461, 462, 
-	463, 464, 119, 433, 434, 435, 428, 428, 
-	145, 465, 428, 428, 437, 428, 428, 428, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 438, 428, 466, 462, 467, 467, 
-	119, 433, 434, 435, 428, 428, 428, 465, 
-	428, 428, 437, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	438, 428, 462, 467, 467, 119, 433, 434, 
-	435, 428, 428, 428, 465, 428, 428, 437, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 428, 438, 428, 468, 
-	428, 428, 428, 132, 469, 428, 433, 434, 
-	435, 428, 428, 428, 442, 428, 468, 428, 
-	470, 471, 472, 473, 119, 433, 434, 435, 
-	428, 428, 143, 474, 428, 428, 437, 428, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 438, 428, 475, 471, 
-	476, 476, 119, 433, 434, 435, 428, 428, 
-	428, 474, 428, 428, 437, 428, 428, 428, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 438, 428, 471, 476, 476, 119, 
-	433, 434, 435, 428, 428, 428, 474, 428, 
-	428, 437, 428, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 428, 428, 428, 438, 
-	428, 132, 477, 428, 433, 434, 435, 428, 
-	428, 428, 442, 428, 433, 434, 435, 428, 
-	428, 428, 442, 428, 478, 428, 428, 479, 
-	434, 435, 428, 434, 435, 428, 480, 428, 
-	434, 481, 428, 434, 482, 428, 434, 428, 
-	478, 428, 428, 428, 434, 435, 428, 483, 
-	428, 484, 485, 428, 433, 434, 435, 428, 
-	428, 117, 428, 116, 428, 428, 428, 428, 
-	433, 434, 435, 428, 433, 434, 435, 428, 
-	483, 428, 428, 428, 428, 433, 434, 435, 
-	428, 483, 428, 484, 428, 428, 433, 434, 
-	435, 428, 428, 117, 428, 132, 428, 486, 
-	486, 119, 433, 434, 435, 428, 428, 428, 
-	442, 428, 487, 141, 488, 489, 122, 433, 
-	434, 435, 428, 428, 428, 442, 428, 141, 
-	488, 489, 122, 433, 434, 435, 428, 428, 
-	428, 442, 428, 488, 488, 122, 433, 434, 
-	435, 428, 428, 428, 442, 428, 490, 138, 
-	491, 492, 125, 433, 434, 435, 428, 428, 
-	428, 442, 428, 138, 491, 492, 125, 433, 
-	434, 435, 428, 428, 428, 442, 428, 491, 
-	491, 125, 433, 434, 435, 428, 428, 428, 
-	442, 428, 493, 135, 494, 495, 128, 433, 
-	434, 435, 428, 428, 428, 442, 428, 135, 
-	494, 495, 128, 433, 434, 435, 428, 428, 
-	428, 442, 428, 494, 494, 128, 433, 434, 
-	435, 428, 428, 428, 442, 428, 496, 132, 
-	428, 497, 428, 433, 434, 435, 428, 428, 
-	428, 442, 428, 132, 428, 497, 428, 433, 
-	434, 435, 428, 428, 428, 442, 428, 498, 
-	428, 433, 434, 435, 428, 428, 428, 442, 
-	428, 132, 428, 428, 428, 428, 433, 434, 
-	435, 428, 428, 428, 442, 428, 115, 116, 
-	428, 428, 132, 477, 428, 433, 434, 435, 
-	428, 428, 428, 442, 428, 115, 428, 471, 
-	476, 476, 119, 433, 434, 435, 428, 428, 
-	428, 474, 428, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 438, 428, 471, 476, 476, 119, 
-	433, 434, 435, 428, 428, 428, 474, 428, 
-	470, 471, 476, 476, 119, 433, 434, 435, 
-	428, 428, 428, 474, 428, 428, 437, 428, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 438, 428, 470, 471, 
-	472, 476, 119, 433, 434, 435, 428, 428, 
-	143, 474, 428, 428, 437, 428, 428, 428, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 438, 428, 468, 428, 499, 428, 
-	486, 486, 119, 433, 434, 435, 428, 428, 
-	428, 442, 428, 468, 428, 468, 428, 428, 
-	428, 428, 428, 428, 433, 434, 435, 428, 
-	428, 428, 442, 428, 468, 428, 468, 428, 
-	428, 428, 428, 500, 428, 433, 434, 435, 
-	428, 428, 428, 442, 428, 468, 428, 468, 
-	428, 499, 428, 428, 428, 428, 433, 434, 
-	435, 428, 428, 428, 442, 428, 468, 428, 
-	468, 116, 428, 428, 132, 469, 428, 433, 
-	434, 435, 428, 428, 428, 442, 428, 468, 
-	428, 461, 462, 467, 467, 119, 433, 434, 
-	435, 428, 428, 428, 465, 428, 428, 437, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 428, 438, 428, 461, 
-	462, 463, 467, 119, 433, 434, 435, 428, 
-	428, 145, 465, 428, 428, 437, 428, 428, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 428, 438, 428, 459, 428, 501, 
-	428, 486, 486, 119, 433, 434, 435, 428, 
-	428, 428, 442, 428, 459, 428, 459, 428, 
-	428, 428, 428, 428, 428, 433, 434, 435, 
-	428, 428, 428, 442, 428, 459, 428, 459, 
-	428, 428, 428, 428, 502, 428, 433, 434, 
-	435, 428, 428, 428, 442, 428, 459, 428, 
-	459, 428, 501, 428, 428, 428, 428, 433, 
-	434, 435, 428, 428, 428, 442, 428, 459, 
-	428, 459, 116, 428, 428, 132, 460, 428, 
-	433, 434, 435, 428, 428, 428, 442, 428, 
-	459, 428, 452, 453, 458, 458, 119, 433, 
-	434, 435, 428, 428, 428, 456, 428, 428, 
-	437, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 428, 428, 438, 428, 
-	452, 453, 454, 458, 119, 433, 434, 435, 
-	428, 428, 147, 456, 428, 428, 437, 428, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 438, 428, 450, 428, 
-	503, 428, 486, 486, 119, 433, 434, 435, 
-	428, 428, 428, 442, 428, 450, 428, 450, 
-	428, 428, 428, 428, 428, 428, 433, 434, 
-	435, 428, 428, 428, 442, 428, 450, 428, 
-	450, 428, 428, 428, 428, 504, 428, 433, 
-	434, 435, 428, 428, 428, 442, 428, 450, 
-	428, 450, 428, 503, 428, 428, 428, 428, 
-	433, 434, 435, 428, 428, 428, 442, 428, 
-	450, 428, 450, 116, 428, 428, 132, 451, 
-	428, 433, 434, 435, 428, 428, 428, 442, 
-	428, 450, 428, 443, 444, 449, 449, 119, 
-	433, 434, 435, 428, 428, 428, 447, 428, 
-	428, 437, 428, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 428, 428, 428, 438, 
-	428, 443, 444, 445, 449, 119, 433, 434, 
-	435, 428, 428, 149, 447, 428, 428, 437, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 428, 438, 428, 440, 
-	428, 505, 428, 486, 486, 119, 433, 434, 
-	435, 428, 428, 428, 442, 428, 440, 428, 
-	440, 428, 428, 428, 428, 428, 428, 433, 
-	434, 435, 428, 428, 428, 442, 428, 440, 
-	428, 440, 428, 428, 428, 428, 506, 428, 
-	433, 434, 435, 428, 428, 428, 442, 428, 
-	440, 428, 440, 428, 505, 428, 428, 428, 
-	428, 433, 434, 435, 428, 428, 428, 442, 
-	428, 440, 428, 440, 116, 428, 428, 132, 
-	441, 428, 433, 434, 435, 428, 428, 428, 
-	442, 428, 440, 428, 429, 430, 432, 432, 
-	119, 433, 434, 435, 428, 428, 428, 436, 
-	428, 428, 437, 428, 428, 428, 428, 428, 
-	428, 428, 428, 428, 428, 428, 428, 428, 
-	438, 428, 181, 182, 183, 184, 507, 359, 
-	81, 187, 188, 189, 190, 190, 152, 191, 
-	357, 181, 194, 357, 357, 357, 357, 357, 
-	357, 357, 357, 357, 357, 357, 357, 357, 
-	196, 357, 198, 508, 200, 201, 5, 202, 
-	203, 204, 197, 197, 37, 205, 197, 197, 
-	206, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 207, 197, 
-	210, 182, 183, 184, 509, 510, 81, 511, 
-	512, 513, 197, 190, 152, 514, 197, 210, 
-	194, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 196, 197, 
-	113, 80, 80, 81, 202, 203, 204, 197, 
-	197, 152, 515, 197, 516, 2, 357, 357, 
-	357, 426, 357, 187, 188, 189, 357, 357, 
-	357, 362, 357, 516, 357, 517, 364, 518, 
-	519, 81, 511, 512, 513, 197, 197, 153, 
-	367, 197, 197, 194, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 196, 197, 520, 364, 369, 369, 81, 
-	511, 512, 513, 197, 197, 197, 367, 197, 
-	197, 194, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 196, 
-	197, 364, 369, 369, 81, 511, 512, 513, 
-	197, 197, 197, 367, 197, 197, 194, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 196, 197, 521, 197, 
-	197, 522, 512, 513, 197, 512, 513, 197, 
-	250, 197, 512, 523, 197, 512, 524, 197, 
-	512, 197, 521, 197, 197, 197, 512, 513, 
-	197, 517, 364, 369, 369, 81, 511, 512, 
-	513, 197, 197, 197, 367, 197, 197, 194, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 196, 197, 517, 
-	364, 518, 369, 81, 511, 512, 513, 197, 
-	197, 153, 367, 197, 197, 194, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 196, 197, 210, 197, 275, 
-	113, 525, 525, 155, 202, 203, 204, 197, 
-	197, 197, 515, 197, 210, 197, 526, 179, 
-	527, 528, 157, 511, 512, 513, 197, 197, 
-	197, 529, 197, 179, 527, 528, 157, 511, 
-	512, 513, 197, 197, 197, 529, 197, 527, 
-	527, 157, 511, 512, 513, 197, 197, 197, 
-	529, 197, 530, 176, 531, 532, 160, 511, 
-	512, 513, 197, 197, 197, 529, 197, 176, 
-	531, 532, 160, 511, 512, 513, 197, 197, 
-	197, 529, 197, 531, 531, 160, 511, 512, 
-	513, 197, 197, 197, 529, 197, 533, 173, 
-	534, 535, 163, 511, 512, 513, 197, 197, 
-	197, 529, 197, 173, 534, 535, 163, 511, 
-	512, 513, 197, 197, 197, 529, 197, 534, 
-	534, 163, 511, 512, 513, 197, 197, 197, 
-	529, 197, 536, 170, 197, 537, 197, 511, 
-	512, 513, 197, 197, 197, 529, 197, 170, 
-	197, 537, 197, 511, 512, 513, 197, 197, 
-	197, 529, 197, 511, 512, 513, 197, 197, 
-	197, 529, 197, 538, 197, 539, 540, 197, 
-	511, 512, 513, 197, 197, 167, 197, 166, 
-	197, 197, 197, 197, 511, 512, 513, 197, 
-	511, 512, 513, 197, 538, 197, 197, 197, 
-	197, 511, 512, 513, 197, 538, 197, 539, 
-	197, 197, 511, 512, 513, 197, 197, 167, 
-	197, 516, 166, 357, 357, 95, 361, 357, 
-	187, 188, 189, 357, 357, 357, 362, 357, 
-	516, 357, 542, 541, 541, 541, 541, 543, 
-	544, 545, 541, 543, 544, 545, 541, 546, 
-	541, 541, 547, 544, 545, 541, 544, 545, 
-	541, 548, 541, 544, 549, 541, 544, 550, 
-	541, 544, 541, 546, 541, 541, 541, 544, 
-	545, 541, 0
+	170, 0, 157, 0, 0, 0, 0, 172, 
+	0, 173, 0, 0, 0, 157, 0, 174, 
+	0, 175, 0, 176, 167, 167, 168, 157, 
+	0, 177, 0, 178, 0, 179, 164, 164, 
+	165, 157, 0, 180, 0, 181, 0, 182, 
+	161, 161, 162, 157, 0, 183, 0, 184, 
+	0, 186, 185, 188, 189, 190, 191, 192, 
+	193, 84, 79, 194, 195, 196, 196, 156, 
+	197, 198, 199, 200, 201, 187, 187, 187, 
+	187, 187, 187, 187, 187, 187, 187, 187, 
+	187, 202, 187, 204, 205, 206, 207, 6, 
+	1, 208, 209, 203, 203, 38, 210, 203, 
+	203, 211, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 212, 
+	203, 213, 205, 214, 214, 6, 1, 208, 
+	209, 203, 203, 203, 210, 203, 203, 211, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 212, 203, 205, 
+	214, 214, 6, 1, 208, 209, 203, 203, 
+	203, 210, 203, 203, 211, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 212, 203, 215, 203, 203, 203, 
+	19, 216, 203, 1, 208, 209, 203, 203, 
+	203, 217, 203, 215, 203, 218, 219, 220, 
+	221, 6, 1, 208, 209, 203, 203, 36, 
+	222, 203, 203, 211, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 212, 203, 223, 219, 224, 224, 6, 
+	1, 208, 209, 203, 203, 203, 222, 203, 
+	203, 211, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 212, 
+	203, 219, 224, 224, 6, 1, 208, 209, 
+	203, 203, 203, 222, 203, 203, 211, 203, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 212, 203, 225, 203, 
+	203, 203, 19, 226, 203, 1, 208, 209, 
+	203, 203, 203, 217, 203, 225, 203, 227, 
+	228, 229, 230, 6, 1, 208, 209, 203, 
+	203, 34, 231, 203, 203, 211, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 212, 203, 232, 228, 233, 
+	233, 6, 1, 208, 209, 203, 203, 203, 
+	231, 203, 203, 211, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 212, 203, 228, 233, 233, 6, 1, 
+	208, 209, 203, 203, 203, 231, 203, 203, 
+	211, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 212, 203, 
+	234, 203, 203, 203, 19, 235, 203, 1, 
+	208, 209, 203, 203, 203, 217, 203, 234, 
+	203, 236, 237, 238, 239, 6, 1, 208, 
+	209, 203, 203, 32, 240, 203, 203, 211, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 212, 203, 241, 
+	237, 242, 242, 6, 1, 208, 209, 203, 
+	203, 203, 240, 203, 203, 211, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 212, 203, 237, 242, 242, 
+	6, 1, 208, 209, 203, 203, 203, 240, 
+	203, 203, 211, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	212, 203, 243, 203, 203, 203, 19, 244, 
+	203, 1, 208, 209, 203, 203, 203, 217, 
+	203, 243, 203, 245, 246, 247, 248, 6, 
+	1, 208, 209, 203, 203, 30, 249, 203, 
+	203, 211, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 212, 
+	203, 250, 246, 251, 251, 6, 1, 208, 
+	209, 203, 203, 203, 249, 203, 203, 211, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 212, 203, 246, 
+	251, 251, 6, 1, 208, 209, 203, 203, 
+	203, 249, 203, 203, 211, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 212, 203, 19, 252, 203, 1, 
+	208, 209, 203, 203, 203, 217, 203, 253, 
+	253, 203, 1, 208, 209, 203, 203, 203, 
+	217, 203, 254, 203, 203, 255, 208, 209, 
+	203, 208, 209, 203, 256, 203, 208, 257, 
+	203, 208, 258, 203, 208, 203, 254, 203, 
+	203, 203, 208, 209, 203, 259, 203, 260, 
+	261, 203, 1, 208, 209, 203, 203, 4, 
+	203, 3, 203, 253, 253, 203, 1, 208, 
+	209, 203, 253, 253, 203, 1, 208, 209, 
+	203, 259, 203, 253, 253, 203, 1, 208, 
+	209, 203, 259, 203, 260, 253, 203, 1, 
+	208, 209, 203, 203, 4, 203, 19, 203, 
+	262, 262, 6, 1, 208, 209, 203, 203, 
+	203, 217, 203, 263, 28, 264, 265, 9, 
+	1, 208, 209, 203, 203, 203, 217, 203, 
+	28, 264, 265, 9, 1, 208, 209, 203, 
+	203, 203, 217, 203, 264, 264, 9, 1, 
+	208, 209, 203, 203, 203, 217, 203, 266, 
+	25, 267, 268, 12, 1, 208, 209, 203, 
+	203, 203, 217, 203, 25, 267, 268, 12, 
+	1, 208, 209, 203, 203, 203, 217, 203, 
+	267, 267, 12, 1, 208, 209, 203, 203, 
+	203, 217, 203, 269, 22, 270, 271, 15, 
+	1, 208, 209, 203, 203, 203, 217, 203, 
+	22, 270, 271, 15, 1, 208, 209, 203, 
+	203, 203, 217, 203, 270, 270, 15, 1, 
+	208, 209, 203, 203, 203, 217, 203, 272, 
+	19, 253, 273, 203, 1, 208, 209, 203, 
+	203, 203, 217, 203, 19, 253, 273, 203, 
+	1, 208, 209, 203, 203, 203, 217, 203, 
+	253, 274, 203, 1, 208, 209, 203, 203, 
+	203, 217, 203, 19, 203, 253, 253, 203, 
+	1, 208, 209, 203, 203, 203, 217, 203, 
+	2, 3, 203, 203, 19, 252, 203, 1, 
+	208, 209, 203, 203, 203, 217, 203, 2, 
+	203, 246, 251, 251, 6, 1, 208, 209, 
+	203, 203, 203, 249, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 212, 203, 246, 251, 
+	251, 6, 1, 208, 209, 203, 203, 203, 
+	249, 203, 245, 246, 251, 251, 6, 1, 
+	208, 209, 203, 203, 203, 249, 203, 203, 
+	211, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 212, 203, 
+	245, 246, 247, 251, 6, 1, 208, 209, 
+	203, 203, 30, 249, 203, 203, 211, 203, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 212, 203, 243, 203, 
+	275, 203, 262, 262, 6, 1, 208, 209, 
+	203, 203, 203, 217, 203, 243, 203, 243, 
+	203, 203, 203, 253, 253, 203, 1, 208, 
+	209, 203, 203, 203, 217, 203, 243, 203, 
+	243, 203, 203, 203, 253, 276, 203, 1, 
+	208, 209, 203, 203, 203, 217, 203, 243, 
+	203, 243, 203, 275, 203, 253, 253, 203, 
+	1, 208, 209, 203, 203, 203, 217, 203, 
+	243, 203, 243, 3, 203, 203, 19, 244, 
+	203, 1, 208, 209, 203, 203, 203, 217, 
+	203, 243, 203, 236, 237, 242, 242, 6, 
+	1, 208, 209, 203, 203, 203, 240, 203, 
+	203, 211, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 212, 
+	203, 236, 237, 238, 242, 6, 1, 208, 
+	209, 203, 203, 32, 240, 203, 203, 211, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 212, 203, 234, 
+	203, 277, 203, 262, 262, 6, 1, 208, 
+	209, 203, 203, 203, 217, 203, 234, 203, 
+	234, 203, 203, 203, 253, 253, 203, 1, 
+	208, 209, 203, 203, 203, 217, 203, 234, 
+	203, 234, 203, 203, 203, 253, 278, 203, 
+	1, 208, 209, 203, 203, 203, 217, 203, 
+	234, 203, 234, 203, 277, 203, 253, 253, 
+	203, 1, 208, 209, 203, 203, 203, 217, 
+	203, 234, 203, 234, 3, 203, 203, 19, 
+	235, 203, 1, 208, 209, 203, 203, 203, 
+	217, 203, 234, 203, 227, 228, 233, 233, 
+	6, 1, 208, 209, 203, 203, 203, 231, 
+	203, 203, 211, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	212, 203, 227, 228, 229, 233, 6, 1, 
+	208, 209, 203, 203, 34, 231, 203, 203, 
+	211, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 212, 203, 
+	225, 203, 279, 203, 262, 262, 6, 1, 
+	208, 209, 203, 203, 203, 217, 203, 225, 
+	203, 225, 203, 203, 203, 253, 253, 203, 
+	1, 208, 209, 203, 203, 203, 217, 203, 
+	225, 203, 225, 203, 203, 203, 253, 280, 
+	203, 1, 208, 209, 203, 203, 203, 217, 
+	203, 225, 203, 225, 203, 279, 203, 253, 
+	253, 203, 1, 208, 209, 203, 203, 203, 
+	217, 203, 225, 203, 225, 3, 203, 203, 
+	19, 226, 203, 1, 208, 209, 203, 203, 
+	203, 217, 203, 225, 203, 218, 219, 224, 
+	224, 6, 1, 208, 209, 203, 203, 203, 
+	222, 203, 203, 211, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 212, 203, 218, 219, 220, 224, 6, 
+	1, 208, 209, 203, 203, 36, 222, 203, 
+	203, 211, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 212, 
+	203, 215, 203, 281, 203, 262, 262, 6, 
+	1, 208, 209, 203, 203, 203, 217, 203, 
+	215, 203, 215, 203, 203, 203, 253, 253, 
+	203, 1, 208, 209, 203, 203, 203, 217, 
+	203, 215, 203, 215, 203, 203, 203, 253, 
+	282, 203, 1, 208, 209, 203, 203, 203, 
+	217, 203, 215, 203, 215, 203, 281, 203, 
+	253, 253, 203, 1, 208, 209, 203, 203, 
+	203, 217, 203, 215, 203, 215, 3, 203, 
+	203, 19, 216, 203, 1, 208, 209, 203, 
+	203, 203, 217, 203, 215, 203, 204, 205, 
+	214, 214, 6, 1, 208, 209, 203, 203, 
+	203, 210, 203, 203, 211, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 212, 203, 204, 205, 206, 214, 
+	6, 1, 208, 209, 203, 203, 38, 210, 
+	203, 203, 211, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	212, 203, 284, 285, 286, 287, 45, 40, 
+	288, 289, 283, 283, 77, 290, 283, 283, 
+	291, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 292, 283, 
+	293, 285, 294, 287, 45, 40, 288, 289, 
+	283, 283, 283, 290, 283, 283, 291, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 292, 283, 285, 294, 
+	287, 45, 40, 288, 289, 283, 283, 283, 
+	290, 283, 283, 291, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 292, 283, 295, 283, 283, 283, 58, 
+	296, 283, 40, 288, 289, 283, 283, 283, 
+	297, 283, 295, 283, 298, 299, 300, 301, 
+	45, 40, 288, 289, 283, 283, 75, 302, 
+	283, 283, 291, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	292, 283, 303, 299, 304, 304, 45, 40, 
+	288, 289, 283, 283, 283, 302, 283, 283, 
+	291, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 292, 283, 
+	299, 304, 304, 45, 40, 288, 289, 283, 
+	283, 283, 302, 283, 283, 291, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 292, 283, 305, 283, 283, 
+	283, 58, 306, 283, 40, 288, 289, 283, 
+	283, 283, 297, 283, 305, 283, 307, 308, 
+	309, 310, 45, 40, 288, 289, 283, 283, 
+	73, 311, 283, 283, 291, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 292, 283, 312, 308, 313, 313, 
+	45, 40, 288, 289, 283, 283, 283, 311, 
+	283, 283, 291, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	292, 283, 308, 313, 313, 45, 40, 288, 
+	289, 283, 283, 283, 311, 283, 283, 291, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 292, 283, 314, 
+	283, 283, 283, 58, 315, 283, 40, 288, 
+	289, 283, 283, 283, 297, 283, 314, 283, 
+	316, 317, 318, 319, 45, 40, 288, 289, 
+	283, 283, 71, 320, 283, 283, 291, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 292, 283, 321, 317, 
+	322, 322, 45, 40, 288, 289, 283, 283, 
+	283, 320, 283, 283, 291, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 292, 283, 317, 322, 322, 45, 
+	40, 288, 289, 283, 283, 283, 320, 283, 
+	283, 291, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 292, 
+	283, 323, 283, 283, 283, 58, 324, 283, 
+	40, 288, 289, 283, 283, 283, 297, 283, 
+	323, 283, 325, 326, 327, 328, 45, 40, 
+	288, 289, 283, 283, 69, 329, 283, 283, 
+	291, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 292, 283, 
+	330, 326, 331, 331, 45, 40, 288, 289, 
+	283, 283, 283, 329, 283, 283, 291, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 292, 283, 326, 331, 
+	331, 45, 40, 288, 289, 283, 283, 283, 
+	329, 283, 283, 291, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 292, 283, 58, 332, 283, 40, 288, 
+	289, 283, 283, 283, 297, 283, 333, 333, 
+	283, 40, 288, 289, 283, 283, 283, 297, 
+	283, 334, 283, 283, 335, 288, 289, 283, 
+	288, 289, 283, 336, 283, 288, 337, 283, 
+	288, 338, 283, 288, 283, 334, 283, 283, 
+	283, 288, 289, 283, 339, 283, 340, 341, 
+	283, 40, 288, 289, 283, 283, 43, 283, 
+	42, 283, 333, 333, 283, 40, 288, 289, 
+	283, 333, 333, 283, 40, 288, 289, 283, 
+	339, 283, 333, 333, 283, 40, 288, 289, 
+	283, 339, 283, 340, 333, 283, 40, 288, 
+	289, 283, 283, 43, 283, 58, 283, 342, 
+	342, 45, 40, 288, 289, 283, 283, 283, 
+	297, 283, 343, 67, 344, 345, 48, 40, 
+	288, 289, 283, 283, 283, 297, 283, 67, 
+	344, 345, 48, 40, 288, 289, 283, 283, 
+	283, 297, 283, 344, 344, 48, 40, 288, 
+	289, 283, 283, 283, 297, 283, 346, 64, 
+	347, 348, 51, 40, 288, 289, 283, 283, 
+	283, 297, 283, 64, 347, 348, 51, 40, 
+	288, 289, 283, 283, 283, 297, 283, 347, 
+	347, 51, 40, 288, 289, 283, 283, 283, 
+	297, 283, 349, 61, 350, 351, 54, 40, 
+	288, 289, 283, 283, 283, 297, 283, 61, 
+	350, 351, 54, 40, 288, 289, 283, 283, 
+	283, 297, 283, 350, 350, 54, 40, 288, 
+	289, 283, 283, 283, 297, 283, 352, 58, 
+	333, 353, 283, 40, 288, 289, 283, 283, 
+	283, 297, 283, 58, 333, 353, 283, 40, 
+	288, 289, 283, 283, 283, 297, 283, 333, 
+	354, 283, 40, 288, 289, 283, 283, 283, 
+	297, 283, 58, 283, 333, 333, 283, 40, 
+	288, 289, 283, 283, 283, 297, 283, 41, 
+	42, 283, 283, 58, 332, 283, 40, 288, 
+	289, 283, 283, 283, 297, 283, 41, 283, 
+	326, 331, 331, 45, 40, 288, 289, 283, 
+	283, 283, 329, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 292, 283, 326, 331, 331, 
+	45, 40, 288, 289, 283, 283, 283, 329, 
+	283, 325, 326, 331, 331, 45, 40, 288, 
+	289, 283, 283, 283, 329, 283, 283, 291, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 292, 283, 325, 
+	326, 327, 331, 45, 40, 288, 289, 283, 
+	283, 69, 329, 283, 283, 291, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 292, 283, 323, 283, 355, 
+	283, 342, 342, 45, 40, 288, 289, 283, 
+	283, 283, 297, 283, 323, 283, 323, 283, 
+	283, 283, 333, 333, 283, 40, 288, 289, 
+	283, 283, 283, 297, 283, 323, 283, 323, 
+	283, 283, 283, 333, 356, 283, 40, 288, 
+	289, 283, 283, 283, 297, 283, 323, 283, 
+	323, 283, 355, 283, 333, 333, 283, 40, 
+	288, 289, 283, 283, 283, 297, 283, 323, 
+	283, 323, 42, 283, 283, 58, 324, 283, 
+	40, 288, 289, 283, 283, 283, 297, 283, 
+	323, 283, 316, 317, 322, 322, 45, 40, 
+	288, 289, 283, 283, 283, 320, 283, 283, 
+	291, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 292, 283, 
+	316, 317, 318, 322, 45, 40, 288, 289, 
+	283, 283, 71, 320, 283, 283, 291, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 292, 283, 314, 283, 
+	357, 283, 342, 342, 45, 40, 288, 289, 
+	283, 283, 283, 297, 283, 314, 283, 314, 
+	283, 283, 283, 333, 333, 283, 40, 288, 
+	289, 283, 283, 283, 297, 283, 314, 283, 
+	314, 283, 283, 283, 333, 358, 283, 40, 
+	288, 289, 283, 283, 283, 297, 283, 314, 
+	283, 314, 283, 357, 283, 333, 333, 283, 
+	40, 288, 289, 283, 283, 283, 297, 283, 
+	314, 283, 314, 42, 283, 283, 58, 315, 
+	283, 40, 288, 289, 283, 283, 283, 297, 
+	283, 314, 283, 307, 308, 313, 313, 45, 
+	40, 288, 289, 283, 283, 283, 311, 283, 
+	283, 291, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 292, 
+	283, 307, 308, 309, 313, 45, 40, 288, 
+	289, 283, 283, 73, 311, 283, 283, 291, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 292, 283, 305, 
+	283, 359, 283, 342, 342, 45, 40, 288, 
+	289, 283, 283, 283, 297, 283, 305, 283, 
+	305, 283, 283, 283, 333, 333, 283, 40, 
+	288, 289, 283, 283, 283, 297, 283, 305, 
+	283, 305, 283, 283, 283, 333, 360, 283, 
+	40, 288, 289, 283, 283, 283, 297, 283, 
+	305, 283, 305, 283, 359, 283, 333, 333, 
+	283, 40, 288, 289, 283, 283, 283, 297, 
+	283, 305, 283, 305, 42, 283, 283, 58, 
+	306, 283, 40, 288, 289, 283, 283, 283, 
+	297, 283, 305, 283, 298, 299, 304, 304, 
+	45, 40, 288, 289, 283, 283, 283, 302, 
+	283, 283, 291, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	292, 283, 298, 299, 300, 304, 45, 40, 
+	288, 289, 283, 283, 75, 302, 283, 283, 
+	291, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 292, 283, 
+	295, 283, 361, 283, 342, 342, 45, 40, 
+	288, 289, 283, 283, 283, 297, 283, 295, 
+	283, 295, 283, 283, 283, 333, 333, 283, 
+	40, 288, 289, 283, 283, 283, 297, 283, 
+	295, 283, 295, 283, 283, 283, 333, 362, 
+	283, 40, 288, 289, 283, 283, 283, 297, 
+	283, 295, 283, 295, 283, 361, 283, 333, 
+	333, 283, 40, 288, 289, 283, 283, 283, 
+	297, 283, 295, 283, 76, 44, 44, 45, 
+	40, 283, 283, 283, 283, 283, 76, 283, 
+	295, 42, 283, 283, 58, 296, 283, 40, 
+	288, 289, 283, 283, 283, 297, 283, 295, 
+	283, 284, 285, 294, 287, 45, 40, 288, 
+	289, 283, 283, 283, 290, 283, 283, 291, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 292, 283, 364, 
+	191, 365, 365, 84, 79, 194, 195, 363, 
+	363, 363, 197, 363, 363, 200, 363, 363, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 202, 363, 191, 365, 365, 
+	84, 79, 194, 195, 363, 363, 363, 197, 
+	363, 363, 200, 363, 363, 363, 363, 363, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	202, 363, 366, 363, 363, 363, 98, 367, 
+	363, 79, 194, 195, 363, 363, 363, 368, 
+	363, 366, 363, 369, 370, 371, 372, 84, 
+	79, 194, 195, 363, 363, 115, 373, 363, 
+	363, 200, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 363, 363, 363, 363, 202, 
+	363, 374, 370, 375, 375, 84, 79, 194, 
+	195, 363, 363, 363, 373, 363, 363, 200, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 363, 363, 202, 363, 370, 
+	375, 375, 84, 79, 194, 195, 363, 363, 
+	363, 373, 363, 363, 200, 363, 363, 363, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 363, 202, 363, 376, 363, 363, 363, 
+	98, 377, 363, 79, 194, 195, 363, 363, 
+	363, 368, 363, 376, 363, 378, 379, 380, 
+	381, 84, 79, 194, 195, 363, 363, 113, 
+	382, 363, 363, 200, 363, 363, 363, 363, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 202, 363, 383, 379, 384, 384, 84, 
+	79, 194, 195, 363, 363, 363, 382, 363, 
+	363, 200, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 363, 363, 363, 363, 202, 
+	363, 379, 384, 384, 84, 79, 194, 195, 
+	363, 363, 363, 382, 363, 363, 200, 363, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 363, 202, 363, 385, 363, 
+	363, 363, 98, 386, 363, 79, 194, 195, 
+	363, 363, 363, 368, 363, 385, 363, 387, 
+	388, 389, 390, 84, 79, 194, 195, 363, 
+	363, 111, 391, 363, 363, 200, 363, 363, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 202, 363, 392, 388, 393, 
+	393, 84, 79, 194, 195, 363, 363, 363, 
+	391, 363, 363, 200, 363, 363, 363, 363, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 202, 363, 388, 393, 393, 84, 79, 
+	194, 195, 363, 363, 363, 391, 363, 363, 
+	200, 363, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 363, 363, 363, 202, 363, 
+	394, 363, 363, 363, 98, 395, 363, 79, 
+	194, 195, 363, 363, 363, 368, 363, 394, 
+	363, 396, 397, 398, 399, 84, 79, 194, 
+	195, 363, 363, 109, 400, 363, 363, 200, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 363, 363, 202, 363, 401, 
+	397, 402, 402, 84, 79, 194, 195, 363, 
+	363, 363, 400, 363, 363, 200, 363, 363, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 202, 363, 397, 402, 402, 
+	84, 79, 194, 195, 363, 363, 363, 400, 
+	363, 363, 200, 363, 363, 363, 363, 363, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	202, 363, 98, 403, 363, 79, 194, 195, 
+	363, 363, 363, 368, 363, 404, 404, 363, 
+	79, 194, 195, 363, 363, 363, 368, 363, 
+	405, 363, 363, 406, 194, 195, 363, 194, 
+	195, 363, 407, 363, 194, 408, 363, 194, 
+	409, 363, 194, 363, 405, 363, 363, 363, 
+	194, 195, 363, 410, 363, 411, 412, 363, 
+	79, 194, 195, 363, 363, 82, 363, 81, 
+	363, 404, 404, 363, 79, 194, 195, 363, 
+	404, 404, 363, 79, 194, 195, 363, 410, 
+	363, 404, 404, 363, 79, 194, 195, 363, 
+	410, 363, 411, 404, 363, 79, 194, 195, 
+	363, 363, 82, 363, 98, 363, 413, 413, 
+	84, 79, 194, 195, 363, 363, 363, 368, 
+	363, 414, 107, 415, 416, 88, 79, 194, 
+	195, 363, 363, 363, 368, 363, 107, 415, 
+	416, 88, 79, 194, 195, 363, 363, 363, 
+	368, 363, 415, 415, 88, 79, 194, 195, 
+	363, 363, 363, 368, 363, 417, 104, 418, 
+	419, 91, 79, 194, 195, 363, 363, 363, 
+	368, 363, 104, 418, 419, 91, 79, 194, 
+	195, 363, 363, 363, 368, 363, 418, 418, 
+	91, 79, 194, 195, 363, 363, 363, 368, 
+	363, 420, 101, 421, 422, 94, 79, 194, 
+	195, 363, 363, 363, 368, 363, 101, 421, 
+	422, 94, 79, 194, 195, 363, 363, 363, 
+	368, 363, 421, 421, 94, 79, 194, 195, 
+	363, 363, 363, 368, 363, 423, 98, 404, 
+	424, 363, 79, 194, 195, 363, 363, 363, 
+	368, 363, 98, 404, 424, 363, 79, 194, 
+	195, 363, 363, 363, 368, 363, 404, 425, 
+	363, 79, 194, 195, 363, 363, 363, 368, 
+	363, 98, 363, 404, 404, 363, 79, 194, 
+	195, 363, 363, 363, 368, 363, 80, 81, 
+	363, 363, 98, 403, 363, 79, 194, 195, 
+	363, 363, 363, 368, 363, 80, 363, 397, 
+	402, 402, 84, 79, 194, 195, 363, 363, 
+	363, 400, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 363, 202, 363, 397, 402, 402, 84, 
+	79, 194, 195, 363, 363, 363, 400, 363, 
+	396, 397, 402, 402, 84, 79, 194, 195, 
+	363, 363, 363, 400, 363, 363, 200, 363, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 363, 202, 363, 396, 397, 
+	398, 402, 84, 79, 194, 195, 363, 363, 
+	109, 400, 363, 363, 200, 363, 363, 363, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 363, 202, 363, 394, 363, 426, 363, 
+	413, 413, 84, 79, 194, 195, 363, 363, 
+	363, 368, 363, 394, 363, 394, 363, 363, 
+	363, 404, 404, 363, 79, 194, 195, 363, 
+	363, 363, 368, 363, 394, 363, 394, 363, 
+	363, 363, 404, 427, 363, 79, 194, 195, 
+	363, 363, 363, 368, 363, 394, 363, 394, 
+	363, 426, 363, 404, 404, 363, 79, 194, 
+	195, 363, 363, 363, 368, 363, 394, 363, 
+	394, 81, 363, 363, 98, 395, 363, 79, 
+	194, 195, 363, 363, 363, 368, 363, 394, 
+	363, 387, 388, 393, 393, 84, 79, 194, 
+	195, 363, 363, 363, 391, 363, 363, 200, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 363, 363, 202, 363, 387, 
+	388, 389, 393, 84, 79, 194, 195, 363, 
+	363, 111, 391, 363, 363, 200, 363, 363, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 202, 363, 385, 363, 428, 
+	363, 413, 413, 84, 79, 194, 195, 363, 
+	363, 363, 368, 363, 385, 363, 385, 363, 
+	363, 363, 404, 404, 363, 79, 194, 195, 
+	363, 363, 363, 368, 363, 385, 363, 385, 
+	363, 363, 363, 404, 429, 363, 79, 194, 
+	195, 363, 363, 363, 368, 363, 385, 363, 
+	385, 363, 428, 363, 404, 404, 363, 79, 
+	194, 195, 363, 363, 363, 368, 363, 385, 
+	363, 385, 81, 363, 363, 98, 386, 363, 
+	79, 194, 195, 363, 363, 363, 368, 363, 
+	385, 363, 378, 379, 384, 384, 84, 79, 
+	194, 195, 363, 363, 363, 382, 363, 363, 
+	200, 363, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 363, 363, 363, 202, 363, 
+	378, 379, 380, 384, 84, 79, 194, 195, 
+	363, 363, 113, 382, 363, 363, 200, 363, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 363, 202, 363, 376, 363, 
+	430, 363, 413, 413, 84, 79, 194, 195, 
+	363, 363, 363, 368, 363, 376, 363, 376, 
+	363, 363, 363, 404, 404, 363, 79, 194, 
+	195, 363, 363, 363, 368, 363, 376, 363, 
+	376, 363, 363, 363, 404, 431, 363, 79, 
+	194, 195, 363, 363, 363, 368, 363, 376, 
+	363, 376, 363, 430, 363, 404, 404, 363, 
+	79, 194, 195, 363, 363, 363, 368, 363, 
+	376, 363, 376, 81, 363, 363, 98, 377, 
+	363, 79, 194, 195, 363, 363, 363, 368, 
+	363, 376, 363, 369, 370, 375, 375, 84, 
+	79, 194, 195, 363, 363, 363, 373, 363, 
+	363, 200, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 363, 363, 363, 363, 202, 
+	363, 369, 370, 371, 375, 84, 79, 194, 
+	195, 363, 363, 115, 373, 363, 363, 200, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 363, 363, 202, 363, 366, 
+	363, 432, 363, 413, 413, 84, 79, 194, 
+	195, 363, 363, 363, 368, 363, 366, 363, 
+	366, 363, 363, 363, 404, 404, 363, 79, 
+	194, 195, 363, 363, 363, 368, 363, 366, 
+	363, 366, 363, 363, 363, 404, 433, 363, 
+	79, 194, 195, 363, 363, 363, 368, 363, 
+	366, 363, 366, 363, 432, 363, 404, 404, 
+	363, 79, 194, 195, 363, 363, 363, 368, 
+	363, 366, 363, 366, 81, 363, 363, 98, 
+	367, 363, 79, 194, 195, 363, 363, 363, 
+	368, 363, 366, 363, 116, 83, 83, 84, 
+	79, 434, 434, 434, 434, 156, 116, 434, 
+	190, 191, 365, 365, 84, 79, 194, 195, 
+	363, 363, 363, 197, 363, 363, 200, 363, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 363, 363, 363, 202, 363, 116, 83, 
+	83, 84, 79, 434, 434, 434, 434, 434, 
+	116, 434, 436, 437, 438, 439, 123, 118, 
+	440, 441, 435, 435, 155, 442, 435, 435, 
+	443, 435, 435, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 435, 435, 444, 435, 
+	445, 437, 439, 439, 123, 118, 440, 441, 
+	435, 435, 435, 442, 435, 435, 443, 435, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 444, 435, 437, 439, 
+	439, 123, 118, 440, 441, 435, 435, 435, 
+	442, 435, 435, 443, 435, 435, 435, 435, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	435, 444, 435, 446, 435, 435, 435, 136, 
+	447, 435, 118, 440, 441, 435, 435, 435, 
+	448, 435, 446, 435, 449, 450, 451, 452, 
+	123, 118, 440, 441, 435, 435, 153, 453, 
+	435, 435, 443, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	444, 435, 454, 450, 455, 455, 123, 118, 
+	440, 441, 435, 435, 435, 453, 435, 435, 
+	443, 435, 435, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 435, 435, 444, 435, 
+	450, 455, 455, 123, 118, 440, 441, 435, 
+	435, 435, 453, 435, 435, 443, 435, 435, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	435, 435, 435, 444, 435, 456, 435, 435, 
+	435, 136, 457, 435, 118, 440, 441, 435, 
+	435, 435, 448, 435, 456, 435, 458, 459, 
+	460, 461, 123, 118, 440, 441, 435, 435, 
+	151, 462, 435, 435, 443, 435, 435, 435, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	435, 435, 444, 435, 463, 459, 464, 464, 
+	123, 118, 440, 441, 435, 435, 435, 462, 
+	435, 435, 443, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	444, 435, 459, 464, 464, 123, 118, 440, 
+	441, 435, 435, 435, 462, 435, 435, 443, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 435, 444, 435, 465, 
+	435, 435, 435, 136, 466, 435, 118, 440, 
+	441, 435, 435, 435, 448, 435, 465, 435, 
+	467, 468, 469, 470, 123, 118, 440, 441, 
+	435, 435, 149, 471, 435, 435, 443, 435, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 444, 435, 472, 468, 
+	473, 473, 123, 118, 440, 441, 435, 435, 
+	435, 471, 435, 435, 443, 435, 435, 435, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	435, 435, 444, 435, 468, 473, 473, 123, 
+	118, 440, 441, 435, 435, 435, 471, 435, 
+	435, 443, 435, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 435, 435, 435, 444, 
+	435, 474, 435, 435, 435, 136, 475, 435, 
+	118, 440, 441, 435, 435, 435, 448, 435, 
+	474, 435, 476, 477, 478, 479, 123, 118, 
+	440, 441, 435, 435, 147, 480, 435, 435, 
+	443, 435, 435, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 435, 435, 444, 435, 
+	481, 477, 482, 482, 123, 118, 440, 441, 
+	435, 435, 435, 480, 435, 435, 443, 435, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 444, 435, 477, 482, 
+	482, 123, 118, 440, 441, 435, 435, 435, 
+	480, 435, 435, 443, 435, 435, 435, 435, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	435, 444, 435, 136, 483, 435, 118, 440, 
+	441, 435, 435, 435, 448, 435, 484, 484, 
+	435, 118, 440, 441, 435, 435, 435, 448, 
+	435, 485, 435, 435, 486, 440, 441, 435, 
+	440, 441, 435, 487, 435, 440, 488, 435, 
+	440, 489, 435, 440, 435, 485, 435, 435, 
+	435, 440, 441, 435, 490, 435, 491, 492, 
+	435, 118, 440, 441, 435, 435, 121, 435, 
+	120, 435, 484, 484, 435, 118, 440, 441, 
+	435, 484, 484, 435, 118, 440, 441, 435, 
+	490, 435, 484, 484, 435, 118, 440, 441, 
+	435, 490, 435, 491, 484, 435, 118, 440, 
+	441, 435, 435, 121, 435, 136, 435, 493, 
+	493, 123, 118, 440, 441, 435, 435, 435, 
+	448, 435, 494, 145, 495, 496, 126, 118, 
+	440, 441, 435, 435, 435, 448, 435, 145, 
+	495, 496, 126, 118, 440, 441, 435, 435, 
+	435, 448, 435, 495, 495, 126, 118, 440, 
+	441, 435, 435, 435, 448, 435, 497, 142, 
+	498, 499, 129, 118, 440, 441, 435, 435, 
+	435, 448, 435, 142, 498, 499, 129, 118, 
+	440, 441, 435, 435, 435, 448, 435, 498, 
+	498, 129, 118, 440, 441, 435, 435, 435, 
+	448, 435, 500, 139, 501, 502, 132, 118, 
+	440, 441, 435, 435, 435, 448, 435, 139, 
+	501, 502, 132, 118, 440, 441, 435, 435, 
+	435, 448, 435, 501, 501, 132, 118, 440, 
+	441, 435, 435, 435, 448, 435, 503, 136, 
+	484, 504, 435, 118, 440, 441, 435, 435, 
+	435, 448, 435, 136, 484, 504, 435, 118, 
+	440, 441, 435, 435, 435, 448, 435, 484, 
+	505, 435, 118, 440, 441, 435, 435, 435, 
+	448, 435, 136, 435, 484, 484, 435, 118, 
+	440, 441, 435, 435, 435, 448, 435, 119, 
+	120, 435, 435, 136, 483, 435, 118, 440, 
+	441, 435, 435, 435, 448, 435, 119, 435, 
+	477, 482, 482, 123, 118, 440, 441, 435, 
+	435, 435, 480, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	435, 435, 435, 444, 435, 477, 482, 482, 
+	123, 118, 440, 441, 435, 435, 435, 480, 
+	435, 476, 477, 482, 482, 123, 118, 440, 
+	441, 435, 435, 435, 480, 435, 435, 443, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 435, 444, 435, 476, 
+	477, 478, 482, 123, 118, 440, 441, 435, 
+	435, 147, 480, 435, 435, 443, 435, 435, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	435, 435, 435, 444, 435, 474, 435, 506, 
+	435, 493, 493, 123, 118, 440, 441, 435, 
+	435, 435, 448, 435, 474, 435, 474, 435, 
+	435, 435, 484, 484, 435, 118, 440, 441, 
+	435, 435, 435, 448, 435, 474, 435, 474, 
+	435, 435, 435, 484, 507, 435, 118, 440, 
+	441, 435, 435, 435, 448, 435, 474, 435, 
+	474, 435, 506, 435, 484, 484, 435, 118, 
+	440, 441, 435, 435, 435, 448, 435, 474, 
+	435, 474, 120, 435, 435, 136, 475, 435, 
+	118, 440, 441, 435, 435, 435, 448, 435, 
+	474, 435, 467, 468, 473, 473, 123, 118, 
+	440, 441, 435, 435, 435, 471, 435, 435, 
+	443, 435, 435, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 435, 435, 444, 435, 
+	467, 468, 469, 473, 123, 118, 440, 441, 
+	435, 435, 149, 471, 435, 435, 443, 435, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 444, 435, 465, 435, 
+	508, 435, 493, 493, 123, 118, 440, 441, 
+	435, 435, 435, 448, 435, 465, 435, 465, 
+	435, 435, 435, 484, 484, 435, 118, 440, 
+	441, 435, 435, 435, 448, 435, 465, 435, 
+	465, 435, 435, 435, 484, 509, 435, 118, 
+	440, 441, 435, 435, 435, 448, 435, 465, 
+	435, 465, 435, 508, 435, 484, 484, 435, 
+	118, 440, 441, 435, 435, 435, 448, 435, 
+	465, 435, 465, 120, 435, 435, 136, 466, 
+	435, 118, 440, 441, 435, 435, 435, 448, 
+	435, 465, 435, 458, 459, 464, 464, 123, 
+	118, 440, 441, 435, 435, 435, 462, 435, 
+	435, 443, 435, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 435, 435, 435, 444, 
+	435, 458, 459, 460, 464, 123, 118, 440, 
+	441, 435, 435, 151, 462, 435, 435, 443, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 435, 444, 435, 456, 
+	435, 510, 435, 493, 493, 123, 118, 440, 
+	441, 435, 435, 435, 448, 435, 456, 435, 
+	456, 435, 435, 435, 484, 484, 435, 118, 
+	440, 441, 435, 435, 435, 448, 435, 456, 
+	435, 456, 435, 435, 435, 484, 511, 435, 
+	118, 440, 441, 435, 435, 435, 448, 435, 
+	456, 435, 456, 435, 510, 435, 484, 484, 
+	435, 118, 440, 441, 435, 435, 435, 448, 
+	435, 456, 435, 456, 120, 435, 435, 136, 
+	457, 435, 118, 440, 441, 435, 435, 435, 
+	448, 435, 456, 435, 449, 450, 455, 455, 
+	123, 118, 440, 441, 435, 435, 435, 453, 
+	435, 435, 443, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	444, 435, 449, 450, 451, 455, 123, 118, 
+	440, 441, 435, 435, 153, 453, 435, 435, 
+	443, 435, 435, 435, 435, 435, 435, 435, 
+	435, 435, 435, 435, 435, 435, 444, 435, 
+	446, 435, 512, 435, 493, 493, 123, 118, 
+	440, 441, 435, 435, 435, 448, 435, 446, 
+	435, 446, 435, 435, 435, 484, 484, 435, 
+	118, 440, 441, 435, 435, 435, 448, 435, 
+	446, 435, 446, 435, 435, 435, 484, 513, 
+	435, 118, 440, 441, 435, 435, 435, 448, 
+	435, 446, 435, 446, 435, 512, 435, 484, 
+	484, 435, 118, 440, 441, 435, 435, 435, 
+	448, 435, 446, 435, 446, 120, 435, 435, 
+	136, 447, 435, 118, 440, 441, 435, 435, 
+	435, 448, 435, 446, 435, 436, 437, 439, 
+	439, 123, 118, 440, 441, 435, 435, 435, 
+	442, 435, 435, 443, 435, 435, 435, 435, 
+	435, 435, 435, 435, 435, 435, 435, 435, 
+	435, 444, 435, 188, 189, 190, 191, 514, 
+	365, 84, 79, 194, 195, 196, 196, 156, 
+	197, 363, 188, 200, 363, 363, 363, 363, 
+	363, 363, 363, 363, 363, 363, 363, 363, 
+	363, 202, 363, 204, 515, 206, 207, 6, 
+	1, 208, 209, 203, 203, 38, 210, 203, 
+	203, 211, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 212, 
+	203, 215, 189, 190, 191, 516, 517, 84, 
+	157, 518, 519, 203, 196, 156, 520, 203, 
+	215, 200, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 202, 
+	203, 116, 521, 521, 84, 157, 208, 209, 
+	203, 203, 156, 522, 203, 523, 203, 203, 
+	524, 518, 519, 203, 518, 519, 203, 256, 
+	203, 518, 525, 203, 518, 526, 203, 518, 
+	203, 523, 203, 203, 203, 518, 519, 203, 
+	527, 3, 363, 363, 404, 433, 363, 79, 
+	194, 195, 363, 363, 363, 368, 363, 527, 
+	363, 528, 370, 529, 530, 84, 157, 518, 
+	519, 203, 203, 158, 373, 203, 203, 200, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 202, 203, 531, 
+	370, 532, 532, 84, 157, 518, 519, 203, 
+	203, 203, 373, 203, 203, 200, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 202, 203, 370, 532, 532, 
+	84, 157, 518, 519, 203, 203, 203, 373, 
+	203, 203, 200, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	202, 203, 528, 370, 532, 532, 84, 157, 
+	518, 519, 203, 203, 203, 373, 203, 203, 
+	200, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 203, 203, 202, 203, 
+	528, 370, 529, 532, 84, 157, 518, 519, 
+	203, 203, 158, 373, 203, 203, 200, 203, 
+	203, 203, 203, 203, 203, 203, 203, 203, 
+	203, 203, 203, 203, 202, 203, 215, 203, 
+	281, 116, 533, 533, 160, 157, 208, 209, 
+	203, 203, 203, 522, 203, 215, 203, 534, 
+	184, 535, 536, 162, 157, 518, 519, 203, 
+	203, 203, 537, 203, 184, 535, 536, 162, 
+	157, 518, 519, 203, 203, 203, 537, 203, 
+	535, 535, 162, 157, 518, 519, 203, 203, 
+	203, 537, 203, 538, 181, 539, 540, 165, 
+	157, 518, 519, 203, 203, 203, 537, 203, 
+	181, 539, 540, 165, 157, 518, 519, 203, 
+	203, 203, 537, 203, 539, 539, 165, 157, 
+	518, 519, 203, 203, 203, 537, 203, 541, 
+	178, 542, 543, 168, 157, 518, 519, 203, 
+	203, 203, 537, 203, 178, 542, 543, 168, 
+	157, 518, 519, 203, 203, 203, 537, 203, 
+	542, 542, 168, 157, 518, 519, 203, 203, 
+	203, 537, 203, 544, 175, 545, 546, 203, 
+	157, 518, 519, 203, 203, 203, 537, 203, 
+	175, 545, 546, 203, 157, 518, 519, 203, 
+	203, 203, 537, 203, 545, 545, 203, 157, 
+	518, 519, 203, 203, 203, 537, 203, 547, 
+	203, 548, 549, 203, 157, 518, 519, 203, 
+	203, 172, 203, 171, 203, 545, 545, 203, 
+	157, 518, 519, 203, 545, 545, 203, 157, 
+	518, 519, 203, 547, 203, 545, 545, 203, 
+	157, 518, 519, 203, 547, 203, 548, 545, 
+	203, 157, 518, 519, 203, 203, 172, 203, 
+	527, 171, 363, 363, 98, 367, 363, 79, 
+	194, 195, 363, 363, 363, 368, 363, 527, 
+	363, 551, 550, 552, 552, 550, 186, 553, 
+	554, 550, 552, 552, 550, 186, 553, 554, 
+	550, 555, 550, 550, 556, 553, 554, 550, 
+	553, 554, 550, 557, 550, 553, 558, 550, 
+	553, 559, 550, 553, 550, 555, 550, 550, 
+	550, 553, 554, 550, 0
 };
 
 static const short _indic_syllable_machine_trans_targs[] = {
-	170, 199, 201, 202, 3, 205, 4, 6, 
-	208, 7, 9, 211, 10, 12, 214, 13, 
-	15, 16, 191, 18, 19, 213, 21, 22, 
-	210, 24, 25, 207, 216, 221, 225, 228, 
-	232, 235, 239, 242, 246, 249, 170, 279, 
-	281, 282, 39, 285, 40, 42, 288, 43, 
-	45, 291, 46, 48, 294, 49, 51, 52, 
-	271, 54, 55, 293, 57, 58, 290, 60, 
-	61, 287, 296, 301, 305, 308, 312, 315, 
-	319, 322, 326, 330, 170, 358, 360, 361, 
-	75, 364, 170, 76, 78, 367, 79, 81, 
-	370, 82, 84, 373, 85, 87, 88, 350, 
-	90, 91, 372, 93, 94, 369, 96, 97, 
-	366, 375, 380, 384, 387, 391, 394, 398, 
-	401, 405, 170, 439, 441, 442, 110, 445, 
-	111, 113, 448, 114, 116, 451, 117, 119, 
-	454, 120, 122, 123, 431, 125, 126, 453, 
-	128, 129, 450, 131, 132, 447, 456, 461, 
-	465, 468, 472, 475, 479, 482, 486, 489, 
-	409, 505, 146, 508, 148, 511, 149, 151, 
-	514, 152, 154, 517, 155, 520, 522, 523, 
-	159, 160, 519, 162, 163, 516, 165, 166, 
-	513, 168, 169, 510, 170, 171, 251, 331, 
-	333, 408, 410, 351, 353, 354, 411, 407, 
-	490, 491, 378, 526, 379, 170, 172, 174, 
-	35, 250, 192, 194, 195, 248, 219, 220, 
-	173, 34, 175, 244, 0, 176, 178, 33, 
-	243, 241, 177, 32, 179, 237, 180, 182, 
-	31, 236, 234, 181, 30, 183, 230, 184, 
-	186, 29, 229, 227, 185, 28, 187, 223, 
-	188, 190, 27, 222, 218, 189, 26, 204, 
-	193, 198, 170, 196, 197, 200, 1, 203, 
-	2, 206, 5, 23, 209, 8, 20, 212, 
-	11, 17, 215, 14, 217, 224, 226, 231, 
-	233, 238, 240, 245, 247, 170, 252, 254, 
-	71, 328, 272, 274, 275, 329, 299, 300, 
-	253, 70, 255, 324, 36, 256, 258, 69, 
-	323, 321, 257, 68, 259, 317, 260, 262, 
-	67, 316, 314, 261, 66, 263, 310, 264, 
-	266, 65, 309, 307, 265, 64, 267, 303, 
-	268, 270, 63, 302, 298, 269, 62, 284, 
-	273, 278, 170, 276, 277, 280, 37, 283, 
-	38, 286, 41, 59, 289, 44, 56, 292, 
-	47, 53, 295, 50, 297, 304, 306, 311, 
-	313, 318, 320, 325, 327, 170, 332, 106, 
-	334, 403, 72, 335, 337, 105, 402, 400, 
-	336, 104, 338, 396, 339, 341, 103, 395, 
-	393, 340, 102, 342, 389, 343, 345, 101, 
-	388, 386, 344, 100, 346, 382, 347, 349, 
-	99, 381, 377, 348, 98, 363, 352, 357, 
-	170, 355, 356, 359, 73, 362, 74, 365, 
-	77, 95, 368, 80, 92, 371, 83, 89, 
-	374, 86, 376, 383, 385, 390, 392, 397, 
-	399, 404, 406, 170, 170, 412, 414, 142, 
-	141, 432, 434, 435, 488, 459, 460, 413, 
-	415, 484, 107, 416, 418, 140, 483, 481, 
-	417, 139, 419, 477, 420, 422, 138, 476, 
-	474, 421, 137, 423, 470, 424, 426, 136, 
-	469, 467, 425, 135, 427, 463, 428, 430, 
-	134, 462, 458, 429, 133, 444, 433, 438, 
-	170, 436, 437, 440, 108, 443, 109, 446, 
-	112, 130, 449, 115, 127, 452, 118, 124, 
-	455, 121, 457, 464, 466, 471, 473, 478, 
-	480, 485, 487, 143, 492, 493, 507, 498, 
-	500, 501, 525, 494, 495, 496, 144, 506, 
-	497, 499, 504, 502, 503, 145, 509, 147, 
-	167, 156, 512, 150, 164, 515, 153, 161, 
-	518, 158, 521, 157, 524, 170, 527, 528, 
-	530, 531, 529, 534, 170, 532, 533
+	178, 200, 207, 209, 210, 4, 213, 5, 
+	7, 216, 8, 10, 219, 11, 13, 222, 
+	14, 16, 17, 199, 19, 20, 221, 22, 
+	23, 218, 25, 26, 215, 224, 229, 233, 
+	236, 240, 243, 247, 250, 254, 257, 178, 
+	280, 287, 289, 290, 41, 293, 42, 44, 
+	296, 45, 47, 299, 48, 50, 302, 51, 
+	53, 54, 279, 56, 57, 301, 59, 60, 
+	298, 62, 63, 295, 304, 309, 313, 316, 
+	320, 323, 327, 330, 334, 338, 178, 359, 
+	366, 368, 369, 78, 372, 178, 79, 81, 
+	375, 82, 84, 378, 85, 87, 381, 88, 
+	90, 91, 358, 93, 94, 380, 96, 97, 
+	377, 99, 100, 374, 383, 388, 392, 395, 
+	399, 402, 406, 409, 413, 178, 440, 447, 
+	449, 450, 114, 453, 115, 117, 456, 118, 
+	120, 459, 121, 123, 462, 124, 126, 127, 
+	439, 129, 130, 461, 132, 133, 458, 135, 
+	136, 455, 464, 469, 473, 476, 480, 483, 
+	487, 490, 494, 497, 417, 502, 513, 152, 
+	516, 154, 519, 155, 157, 522, 158, 160, 
+	525, 161, 528, 530, 531, 166, 167, 527, 
+	169, 170, 524, 172, 173, 521, 175, 176, 
+	518, 178, 536, 178, 179, 259, 339, 341, 
+	416, 418, 361, 362, 419, 415, 498, 499, 
+	386, 534, 387, 178, 180, 182, 36, 258, 
+	202, 203, 256, 227, 228, 181, 35, 183, 
+	252, 1, 184, 186, 34, 251, 249, 185, 
+	33, 187, 245, 188, 190, 32, 244, 242, 
+	189, 31, 191, 238, 192, 194, 30, 237, 
+	235, 193, 29, 195, 231, 196, 198, 28, 
+	230, 226, 197, 27, 212, 0, 201, 206, 
+	178, 204, 205, 208, 2, 211, 3, 214, 
+	6, 24, 217, 9, 21, 220, 12, 18, 
+	223, 15, 225, 232, 234, 239, 241, 246, 
+	248, 253, 255, 178, 260, 262, 73, 336, 
+	282, 283, 337, 307, 308, 261, 72, 263, 
+	332, 38, 264, 266, 71, 331, 329, 265, 
+	70, 267, 325, 268, 270, 69, 324, 322, 
+	269, 68, 271, 318, 272, 274, 67, 317, 
+	315, 273, 66, 275, 311, 276, 278, 65, 
+	310, 306, 277, 64, 292, 37, 281, 286, 
+	178, 284, 285, 288, 39, 291, 40, 294, 
+	43, 61, 297, 46, 58, 300, 49, 55, 
+	303, 52, 305, 312, 314, 319, 321, 326, 
+	328, 333, 335, 178, 340, 109, 342, 411, 
+	75, 343, 345, 108, 410, 408, 344, 107, 
+	346, 404, 347, 349, 106, 403, 401, 348, 
+	105, 350, 397, 351, 353, 104, 396, 394, 
+	352, 103, 354, 390, 355, 357, 102, 389, 
+	385, 356, 101, 371, 74, 360, 365, 178, 
+	363, 364, 367, 76, 370, 77, 373, 80, 
+	98, 376, 83, 95, 379, 86, 92, 382, 
+	89, 384, 391, 393, 398, 400, 405, 407, 
+	412, 414, 178, 178, 420, 422, 146, 145, 
+	442, 443, 496, 467, 468, 421, 423, 492, 
+	111, 424, 426, 144, 491, 489, 425, 143, 
+	427, 485, 428, 430, 142, 484, 482, 429, 
+	141, 431, 478, 432, 434, 140, 477, 475, 
+	433, 139, 435, 471, 436, 438, 138, 470, 
+	466, 437, 137, 452, 110, 441, 446, 178, 
+	444, 445, 448, 112, 451, 113, 454, 116, 
+	134, 457, 119, 131, 460, 122, 128, 463, 
+	125, 465, 472, 474, 479, 481, 486, 488, 
+	493, 495, 147, 500, 501, 515, 504, 505, 
+	533, 148, 509, 503, 508, 506, 507, 510, 
+	511, 150, 514, 512, 149, 151, 517, 153, 
+	174, 163, 520, 156, 171, 523, 159, 168, 
+	526, 162, 165, 529, 164, 532, 178, 535, 
+	177, 538, 539, 537, 542, 178, 540, 541
 };
 
 static const char _indic_syllable_machine_trans_actions[] = {
-	1, 2, 0, 0, 0, 2, 0, 0, 
+	1, 0, 2, 2, 2, 0, 2, 0, 
+	0, 2, 0, 0, 2, 0, 0, 2, 
+	0, 0, 0, 2, 0, 0, 2, 0, 
+	0, 2, 0, 0, 2, 2, 2, 2, 
+	2, 2, 2, 2, 2, 2, 2, 3, 
+	0, 2, 2, 2, 0, 2, 0, 0, 
 	2, 0, 0, 2, 0, 0, 2, 0, 
 	0, 0, 2, 0, 0, 2, 0, 0, 
 	2, 0, 0, 2, 2, 2, 2, 2, 
-	2, 2, 2, 2, 2, 2, 3, 2, 
-	0, 0, 0, 2, 0, 0, 2, 0, 
+	2, 2, 2, 2, 2, 2, 4, 0, 
+	2, 2, 2, 0, 2, 5, 0, 0, 
+	2, 0, 0, 2, 0, 0, 2, 0, 
+	0, 0, 2, 0, 0, 2, 0, 0, 
+	2, 0, 0, 2, 2, 6, 2, 6, 
+	2, 6, 2, 6, 2, 7, 0, 2, 
+	2, 2, 0, 2, 0, 0, 2, 0, 
 	0, 2, 0, 0, 2, 0, 0, 0, 
 	2, 0, 0, 2, 0, 0, 2, 0, 
 	0, 2, 2, 2, 2, 2, 2, 2, 
-	2, 2, 2, 2, 4, 2, 0, 0, 
-	0, 2, 5, 0, 0, 2, 0, 0, 
-	2, 0, 0, 2, 0, 0, 0, 2, 
-	0, 0, 2, 0, 0, 2, 0, 0, 
-	2, 2, 6, 2, 6, 2, 6, 2, 
-	6, 2, 7, 2, 0, 0, 0, 2, 
-	0, 0, 2, 0, 0, 2, 0, 0, 
-	2, 0, 0, 0, 2, 0, 0, 2, 
-	0, 0, 2, 0, 0, 2, 2, 2, 
-	2, 2, 2, 2, 2, 2, 2, 2, 
-	6, 8, 0, 2, 0, 2, 0, 0, 
-	2, 0, 0, 2, 0, 2, 0, 0, 
+	2, 2, 2, 2, 6, 0, 8, 0, 
+	2, 0, 2, 0, 0, 2, 0, 0, 
+	2, 0, 2, 2, 2, 0, 0, 2, 
 	0, 0, 2, 0, 0, 2, 0, 0, 
-	2, 0, 0, 2, 11, 2, 2, 6, 
-	2, 12, 12, 0, 0, 0, 2, 2, 
-	6, 2, 6, 0, 6, 13, 2, 2, 
-	0, 2, 0, 0, 0, 2, 2, 2, 
-	2, 0, 2, 2, 0, 2, 2, 0, 
-	2, 2, 2, 0, 2, 2, 2, 2, 
-	0, 2, 2, 2, 0, 2, 2, 2, 
-	2, 0, 2, 2, 2, 0, 2, 2, 
-	2, 2, 0, 2, 2, 2, 0, 2, 
-	0, 0, 14, 0, 0, 0, 0, 2, 
-	0, 2, 0, 0, 2, 0, 0, 2, 
-	0, 0, 2, 0, 2, 2, 2, 2, 
-	2, 2, 2, 2, 2, 15, 2, 2, 
-	0, 2, 0, 0, 0, 2, 2, 2, 
-	2, 0, 2, 2, 0, 2, 2, 0, 
-	2, 2, 2, 0, 2, 2, 2, 2, 
-	0, 2, 2, 2, 0, 2, 2, 2, 
-	2, 0, 2, 2, 2, 0, 2, 2, 
-	2, 2, 0, 2, 2, 2, 0, 2, 
-	0, 0, 16, 0, 0, 0, 0, 2, 
-	0, 2, 0, 0, 2, 0, 0, 2, 
-	0, 0, 2, 0, 2, 2, 2, 2, 
-	2, 2, 2, 2, 2, 17, 6, 0, 
-	6, 6, 0, 6, 2, 0, 6, 2, 
-	6, 0, 6, 6, 6, 2, 0, 6, 
-	2, 6, 0, 6, 6, 6, 2, 0, 
-	6, 2, 6, 0, 6, 6, 6, 2, 
-	0, 6, 2, 6, 0, 6, 0, 0, 
-	18, 0, 0, 0, 0, 2, 0, 2, 
+	2, 9, 0, 12, 2, 2, 6, 2, 
+	13, 13, 0, 0, 2, 2, 6, 2, 
+	6, 2, 6, 14, 2, 2, 0, 2, 
+	0, 0, 2, 2, 2, 2, 0, 2, 
+	2, 0, 2, 2, 0, 2, 2, 2, 
+	0, 2, 2, 2, 2, 0, 2, 2, 
+	2, 0, 2, 2, 2, 2, 0, 2, 
+	2, 2, 0, 2, 2, 2, 2, 0, 
+	2, 2, 2, 0, 2, 0, 0, 0, 
+	15, 0, 0, 2, 0, 2, 0, 2, 
+	0, 0, 2, 0, 0, 2, 0, 0, 
+	2, 0, 2, 2, 2, 2, 2, 2, 
+	2, 2, 2, 16, 2, 2, 0, 2, 
+	0, 0, 2, 2, 2, 2, 0, 2, 
+	2, 0, 2, 2, 0, 2, 2, 2, 
+	0, 2, 2, 2, 2, 0, 2, 2, 
+	2, 0, 2, 2, 2, 2, 0, 2, 
+	2, 2, 0, 2, 2, 2, 2, 0, 
+	2, 2, 2, 0, 2, 0, 0, 0, 
+	17, 0, 0, 2, 0, 2, 0, 2, 
 	0, 0, 2, 0, 0, 2, 0, 0, 
 	2, 0, 2, 2, 2, 2, 2, 2, 
-	2, 2, 2, 19, 20, 2, 2, 0, 
-	0, 0, 0, 0, 2, 2, 2, 2, 
-	2, 2, 0, 2, 2, 0, 2, 2, 
+	2, 2, 2, 18, 6, 0, 6, 6, 
+	0, 6, 2, 0, 6, 2, 6, 0, 
+	6, 6, 6, 2, 0, 6, 2, 6, 
+	0, 6, 6, 6, 2, 0, 6, 2, 
+	6, 0, 6, 6, 6, 2, 0, 6, 
+	2, 6, 0, 6, 0, 0, 0, 19, 
+	0, 0, 2, 0, 2, 0, 2, 0, 
+	0, 2, 0, 0, 2, 0, 0, 2, 
+	0, 2, 2, 2, 2, 2, 2, 2, 
+	2, 2, 20, 21, 2, 2, 0, 0, 
+	0, 0, 2, 2, 2, 2, 2, 2, 
+	0, 2, 2, 0, 2, 2, 2, 0, 
+	2, 2, 2, 2, 0, 2, 2, 2, 
+	0, 2, 2, 2, 2, 0, 2, 2, 
 	2, 0, 2, 2, 2, 2, 0, 2, 
-	2, 2, 0, 2, 2, 2, 2, 0, 
-	2, 2, 2, 0, 2, 2, 2, 2, 
-	0, 2, 2, 2, 0, 2, 0, 0, 
-	21, 0, 0, 0, 0, 2, 0, 2, 
+	2, 2, 0, 2, 0, 0, 0, 22, 
+	0, 0, 2, 0, 2, 0, 2, 0, 
+	0, 2, 0, 0, 2, 0, 0, 2, 
+	0, 2, 2, 2, 2, 2, 2, 2, 
+	2, 2, 0, 0, 8, 2, 0, 0, 
+	2, 0, 2, 0, 0, 0, 0, 8, 
+	8, 0, 8, 8, 0, 0, 2, 0, 
 	0, 0, 2, 0, 0, 2, 0, 0, 
-	2, 0, 2, 2, 2, 2, 2, 2, 
-	2, 2, 2, 0, 0, 8, 2, 0, 
-	0, 0, 2, 2, 8, 8, 0, 8, 
-	8, 0, 0, 0, 0, 0, 2, 0, 
-	0, 0, 2, 0, 0, 2, 0, 0, 
-	2, 0, 0, 0, 2, 22, 0, 0, 
-	0, 0, 0, 0, 23, 0, 0
+	2, 0, 0, 2, 0, 2, 23, 2, 
+	0, 0, 0, 0, 0, 24, 0, 0
 };
 
 static const char _indic_syllable_machine_to_state_actions[] = {
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
@@ -1326,17 +1349,18 @@ static const char _indic_syllable_machin
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 9, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 10, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
@@ -1396,17 +1420,18 @@ static const char _indic_syllable_machin
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 10, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 11, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
@@ -1449,93 +1474,94 @@ static const char _indic_syllable_machin
 	0, 0, 0, 0, 0, 0, 0
 };
 
 static const short _indic_syllable_machine_eof_trans[] = {
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 39, 39, 39, 39, 
-	39, 39, 39, 39, 39, 39, 39, 39, 
-	39, 39, 39, 39, 39, 39, 39, 39, 
-	39, 39, 39, 39, 39, 39, 39, 39, 
-	39, 39, 39, 39, 39, 39, 39, 39, 
-	77, 77, 77, 83, 83, 77, 77, 77, 
-	77, 77, 77, 77, 77, 77, 77, 77, 
-	77, 77, 77, 77, 77, 77, 77, 77, 
-	77, 77, 77, 77, 77, 77, 77, 77, 
-	83, 77, 77, 115, 115, 115, 115, 115, 
-	115, 115, 115, 115, 115, 115, 115, 115, 
-	115, 115, 115, 115, 115, 115, 115, 115, 
-	115, 115, 115, 115, 115, 115, 115, 115, 
-	115, 115, 115, 115, 115, 115, 115, 77, 
+	1, 1, 1, 1, 1, 40, 40, 40, 
+	40, 40, 40, 40, 40, 40, 40, 40, 
+	40, 40, 40, 40, 40, 40, 40, 40, 
+	40, 40, 40, 40, 40, 40, 40, 40, 
+	40, 40, 40, 40, 40, 40, 40, 40, 
+	40, 40, 79, 79, 79, 79, 86, 86, 
+	79, 79, 79, 79, 79, 79, 79, 79, 
+	79, 79, 79, 79, 79, 79, 79, 79, 
+	79, 79, 79, 79, 79, 79, 79, 79, 
+	79, 79, 79, 79, 79, 79, 118, 118, 
+	118, 118, 118, 118, 118, 118, 118, 118, 
+	118, 118, 118, 118, 118, 118, 118, 118, 
+	118, 118, 118, 118, 118, 118, 118, 118, 
+	118, 118, 118, 118, 118, 118, 118, 118, 
+	118, 118, 118, 79, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 0, 198, 198, 198, 198, 198, 
-	198, 198, 198, 198, 198, 198, 198, 198, 
-	198, 198, 198, 198, 198, 198, 198, 198, 
-	198, 198, 198, 198, 198, 198, 198, 198, 
-	198, 198, 198, 198, 198, 198, 198, 198, 
-	198, 198, 198, 198, 198, 198, 198, 198, 
-	198, 198, 198, 198, 198, 198, 198, 198, 
-	198, 198, 198, 198, 198, 198, 198, 198, 
-	198, 198, 198, 198, 198, 198, 198, 198, 
-	198, 198, 198, 198, 198, 198, 198, 198, 
-	198, 198, 198, 278, 278, 278, 278, 278, 
-	278, 278, 278, 278, 278, 278, 278, 278, 
-	278, 278, 278, 278, 278, 278, 278, 278, 
-	278, 278, 278, 278, 278, 278, 278, 278, 
-	278, 278, 278, 278, 278, 278, 278, 278, 
-	278, 278, 278, 278, 278, 278, 278, 278, 
-	278, 278, 278, 278, 278, 278, 278, 278, 
-	278, 278, 278, 278, 278, 278, 278, 278, 
-	278, 278, 278, 278, 278, 278, 278, 278, 
-	278, 278, 278, 278, 278, 278, 278, 278, 
-	278, 278, 278, 358, 358, 358, 358, 358, 
-	358, 358, 358, 358, 358, 358, 358, 358, 
-	358, 358, 358, 358, 358, 358, 358, 358, 
-	358, 358, 358, 358, 358, 358, 358, 358, 
-	358, 358, 358, 358, 358, 358, 358, 358, 
-	358, 358, 358, 358, 358, 358, 358, 358, 
-	358, 358, 358, 358, 358, 358, 358, 358, 
-	358, 358, 358, 358, 358, 358, 358, 358, 
-	358, 358, 358, 358, 358, 358, 358, 358, 
-	358, 358, 358, 358, 358, 358, 358, 358, 
-	428, 358, 428, 429, 429, 429, 429, 429, 
-	429, 429, 429, 429, 429, 429, 429, 429, 
-	429, 429, 429, 429, 429, 429, 429, 429, 
-	429, 429, 429, 429, 429, 429, 429, 429, 
-	429, 429, 429, 429, 429, 429, 429, 429, 
-	429, 429, 429, 429, 429, 429, 429, 429, 
-	429, 429, 429, 429, 429, 429, 429, 429, 
-	429, 429, 429, 429, 429, 429, 429, 429, 
-	429, 429, 429, 429, 429, 429, 429, 429, 
-	429, 429, 429, 429, 429, 429, 429, 429, 
-	429, 429, 358, 198, 198, 198, 358, 198, 
-	198, 198, 198, 198, 198, 198, 198, 198, 
-	198, 198, 198, 198, 198, 198, 198, 198, 
-	198, 198, 198, 198, 198, 198, 198, 198, 
-	198, 198, 198, 198, 198, 358, 542, 542, 
-	542, 542, 542, 542, 542, 542, 542
+	1, 186, 0, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 284, 284, 284, 284, 284, 
+	284, 284, 284, 284, 284, 284, 284, 284, 
+	284, 284, 284, 284, 284, 284, 284, 284, 
+	284, 284, 284, 284, 284, 284, 284, 284, 
+	284, 284, 284, 284, 284, 284, 284, 284, 
+	284, 284, 284, 284, 284, 284, 284, 284, 
+	284, 284, 284, 284, 284, 284, 284, 284, 
+	284, 284, 284, 284, 284, 284, 284, 284, 
+	284, 284, 284, 284, 284, 284, 284, 284, 
+	284, 284, 284, 284, 284, 284, 284, 284, 
+	284, 284, 284, 364, 364, 364, 364, 364, 
+	364, 364, 364, 364, 364, 364, 364, 364, 
+	364, 364, 364, 364, 364, 364, 364, 364, 
+	364, 364, 364, 364, 364, 364, 364, 364, 
+	364, 364, 364, 364, 364, 364, 364, 364, 
+	364, 364, 364, 364, 364, 364, 364, 364, 
+	364, 364, 364, 364, 364, 364, 364, 364, 
+	364, 364, 364, 364, 364, 364, 364, 364, 
+	364, 364, 364, 364, 364, 364, 364, 364, 
+	364, 364, 364, 364, 364, 364, 364, 364, 
+	435, 364, 435, 436, 436, 436, 436, 436, 
+	436, 436, 436, 436, 436, 436, 436, 436, 
+	436, 436, 436, 436, 436, 436, 436, 436, 
+	436, 436, 436, 436, 436, 436, 436, 436, 
+	436, 436, 436, 436, 436, 436, 436, 436, 
+	436, 436, 436, 436, 436, 436, 436, 436, 
+	436, 436, 436, 436, 436, 436, 436, 436, 
+	436, 436, 436, 436, 436, 436, 436, 436, 
+	436, 436, 436, 436, 436, 436, 436, 436, 
+	436, 436, 436, 436, 436, 436, 436, 436, 
+	436, 436, 364, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 364, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 364, 551, 551, 
+	551, 551, 551, 551, 551, 551, 551
 };
 
-static const int indic_syllable_machine_start = 170;
-static const int indic_syllable_machine_first_final = 170;
+static const int indic_syllable_machine_start = 178;
+static const int indic_syllable_machine_first_final = 178;
 static const int indic_syllable_machine_error = -1;
 
-static const int indic_syllable_machine_en_main = 170;
+static const int indic_syllable_machine_en_main = 178;
 
 
-#line 36 "../../src/hb-ot-shape-complex-indic-machine.rl"
+#line 36 "hb-ot-shape-complex-indic-machine.rl"
 
 
 
-#line 97 "../../src/hb-ot-shape-complex-indic-machine.rl"
+#line 97 "hb-ot-shape-complex-indic-machine.rl"
 
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
     if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
     for (unsigned int i = last; i < p+1; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
     last = p+1; \
@@ -1545,48 +1571,48 @@ static const int indic_syllable_machine_
 
 static void
 find_syllables (hb_buffer_t *buffer)
 {
   unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 1554 "hb-ot-shape-complex-indic-machine.hh.tmp"
+#line 1580 "hb-ot-shape-complex-indic-machine.hh"
 	{
 	cs = indic_syllable_machine_start;
 	ts = 0;
 	te = 0;
 	act = 0;
 	}
 
-#line 118 "../../src/hb-ot-shape-complex-indic-machine.rl"
+#line 118 "hb-ot-shape-complex-indic-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
   unsigned int last = 0;
   unsigned int syllable_serial = 1;
   
-#line 1571 "hb-ot-shape-complex-indic-machine.hh.tmp"
+#line 1597 "hb-ot-shape-complex-indic-machine.hh"
 	{
 	int _slen;
 	int _trans;
 	const unsigned char *_keys;
 	const short *_inds;
 	if ( p == pe )
 		goto _test_eof;
 _resume:
 	switch ( _indic_syllable_machine_from_state_actions[cs] ) {
-	case 10:
+	case 11:
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 1585 "hb-ot-shape-complex-indic-machine.hh.tmp"
+#line 1611 "hb-ot-shape-complex-indic-machine.hh"
 	}
 
 	_keys = _indic_syllable_machine_trans_keys + (cs<<1);
 	_inds = _indic_syllable_machine_indicies + _indic_syllable_machine_index_offsets[cs];
 
 	_slen = _indic_syllable_machine_key_spans[cs];
 	_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].indic_category()) &&
 		( info[p].indic_category()) <= _keys[1] ?
@@ -1598,78 +1624,82 @@ find_syllables (hb_buffer_t *buffer)
 	if ( _indic_syllable_machine_trans_actions[_trans] == 0 )
 		goto _again;
 
 	switch ( _indic_syllable_machine_trans_actions[_trans] ) {
 	case 2:
 #line 1 "NONE"
 	{te = p+1;}
 	break;
-	case 14:
-#line 88 "../../src/hb-ot-shape-complex-indic-machine.rl"
+	case 15:
+#line 88 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (consonant_syllable); }}
 	break;
-	case 16:
-#line 89 "../../src/hb-ot-shape-complex-indic-machine.rl"
+	case 17:
+#line 89 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (vowel_syllable); }}
 	break;
-	case 21:
-#line 90 "../../src/hb-ot-shape-complex-indic-machine.rl"
+	case 22:
+#line 90 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (standalone_cluster); }}
 	break;
-	case 23:
-#line 91 "../../src/hb-ot-shape-complex-indic-machine.rl"
+	case 24:
+#line 91 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (symbol_cluster); }}
 	break;
-	case 18:
-#line 92 "../../src/hb-ot-shape-complex-indic-machine.rl"
+	case 19:
+#line 92 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (broken_cluster); }}
 	break;
-	case 11:
-#line 93 "../../src/hb-ot-shape-complex-indic-machine.rl"
+	case 12:
+#line 93 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (non_indic_cluster); }}
 	break;
-	case 13:
-#line 88 "../../src/hb-ot-shape-complex-indic-machine.rl"
+	case 14:
+#line 88 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (consonant_syllable); }}
 	break;
-	case 15:
-#line 89 "../../src/hb-ot-shape-complex-indic-machine.rl"
+	case 16:
+#line 89 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (vowel_syllable); }}
 	break;
+	case 21:
+#line 90 "hb-ot-shape-complex-indic-machine.rl"
+	{te = p;p--;{ found_syllable (standalone_cluster); }}
+	break;
+	case 23:
+#line 91 "hb-ot-shape-complex-indic-machine.rl"
+	{te = p;p--;{ found_syllable (symbol_cluster); }}
+	break;
+	case 18:
+#line 92 "hb-ot-shape-complex-indic-machine.rl"
+	{te = p;p--;{ found_syllable (broken_cluster); }}
+	break;
 	case 20:
-#line 90 "../../src/hb-ot-shape-complex-indic-machine.rl"
-	{te = p;p--;{ found_syllable (standalone_cluster); }}
-	break;
-	case 22:
-#line 91 "../../src/hb-ot-shape-complex-indic-machine.rl"
-	{te = p;p--;{ found_syllable (symbol_cluster); }}
-	break;
-	case 17:
-#line 92 "../../src/hb-ot-shape-complex-indic-machine.rl"
-	{te = p;p--;{ found_syllable (broken_cluster); }}
-	break;
-	case 19:
-#line 93 "../../src/hb-ot-shape-complex-indic-machine.rl"
+#line 93 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (non_indic_cluster); }}
 	break;
 	case 1:
-#line 88 "../../src/hb-ot-shape-complex-indic-machine.rl"
+#line 88 "hb-ot-shape-complex-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (consonant_syllable); }}
 	break;
 	case 3:
-#line 89 "../../src/hb-ot-shape-complex-indic-machine.rl"
+#line 89 "hb-ot-shape-complex-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (vowel_syllable); }}
 	break;
 	case 7:
-#line 90 "../../src/hb-ot-shape-complex-indic-machine.rl"
+#line 90 "hb-ot-shape-complex-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (standalone_cluster); }}
 	break;
+	case 9:
+#line 91 "hb-ot-shape-complex-indic-machine.rl"
+	{{p = ((te))-1;}{ found_syllable (symbol_cluster); }}
+	break;
 	case 4:
-#line 92 "../../src/hb-ot-shape-complex-indic-machine.rl"
+#line 92 "hb-ot-shape-complex-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
 	break;
 	case 5:
 #line 1 "NONE"
 	{	switch( act ) {
 	case 1:
 	{{p = ((te))-1;} found_syllable (consonant_syllable); }
 	break;
@@ -1680,53 +1710,53 @@ find_syllables (hb_buffer_t *buffer)
 	{{p = ((te))-1;} found_syllable (non_indic_cluster); }
 	break;
 	}
 	}
 	break;
 	case 8:
 #line 1 "NONE"
 	{te = p+1;}
-#line 88 "../../src/hb-ot-shape-complex-indic-machine.rl"
+#line 88 "hb-ot-shape-complex-indic-machine.rl"
 	{act = 1;}
 	break;
 	case 6:
 #line 1 "NONE"
 	{te = p+1;}
-#line 92 "../../src/hb-ot-shape-complex-indic-machine.rl"
+#line 92 "hb-ot-shape-complex-indic-machine.rl"
 	{act = 5;}
 	break;
-	case 12:
+	case 13:
 #line 1 "NONE"
 	{te = p+1;}
-#line 93 "../../src/hb-ot-shape-complex-indic-machine.rl"
+#line 93 "hb-ot-shape-complex-indic-machine.rl"
 	{act = 6;}
 	break;
-#line 1704 "hb-ot-shape-complex-indic-machine.hh.tmp"
+#line 1734 "hb-ot-shape-complex-indic-machine.hh"
 	}
 
 _again:
 	switch ( _indic_syllable_machine_to_state_actions[cs] ) {
-	case 9:
+	case 10:
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 1713 "hb-ot-shape-complex-indic-machine.hh.tmp"
+#line 1743 "hb-ot-shape-complex-indic-machine.hh"
 	}
 
 	if ( ++p != pe )
 		goto _resume;
 	_test_eof: {}
 	if ( p == eof )
 	{
 	if ( _indic_syllable_machine_eof_trans[cs] > 0 ) {
 		_trans = _indic_syllable_machine_eof_trans[cs] - 1;
 		goto _eof_trans;
 	}
 	}
 
 	}
 
-#line 127 "../../src/hb-ot-shape-complex-indic-machine.rl"
+#line 127 "hb-ot-shape-complex-indic-machine.rl"
 
 }
 
 #endif /* HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH */
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
@@ -856,51 +856,51 @@ static const INDIC_TABLE_ELEMENT_TYPE in
 }; /* Table items: 4488; occupancy: 73% */
 
 INDIC_TABLE_ELEMENT_TYPE
 hb_indic_get_categories (hb_codepoint_t u)
 {
   switch (u >> 12)
   {
     case 0x0u:
-      if (hb_in_range (u, 0x0028u, 0x0040u)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
-      if (hb_in_range (u, 0x00D0u, 0x00D8u)) return indic_table[u - 0x00D0u + indic_offset_0x00d0u];
-      if (hb_in_range (u, 0x0900u, 0x0DF8u)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
+      if (hb_in_range (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
+      if (hb_in_range (u, 0x00D0u, 0x00D7u)) return indic_table[u - 0x00D0u + indic_offset_0x00d0u];
+      if (hb_in_range (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
       if (unlikely (u == 0x00A0u)) return _(CP,x);
       break;
 
     case 0x1u:
-      if (hb_in_range (u, 0x1000u, 0x10A0u)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
-      if (hb_in_range (u, 0x1700u, 0x17F0u)) return indic_table[u - 0x1700u + indic_offset_0x1700u];
-      if (hb_in_range (u, 0x1900u, 0x1AA0u)) return indic_table[u - 0x1900u + indic_offset_0x1900u];
-      if (hb_in_range (u, 0x1B00u, 0x1C50u)) return indic_table[u - 0x1B00u + indic_offset_0x1b00u];
-      if (hb_in_range (u, 0x1CD0u, 0x1CF8u)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
+      if (hb_in_range (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
+      if (hb_in_range (u, 0x1700u, 0x17EFu)) return indic_table[u - 0x1700u + indic_offset_0x1700u];
+      if (hb_in_range (u, 0x1900u, 0x1A9Fu)) return indic_table[u - 0x1900u + indic_offset_0x1900u];
+      if (hb_in_range (u, 0x1B00u, 0x1C4Fu)) return indic_table[u - 0x1B00u + indic_offset_0x1b00u];
+      if (hb_in_range (u, 0x1CD0u, 0x1CF7u)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
       break;
 
     case 0x2u:
-      if (hb_in_range (u, 0x2008u, 0x2018u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
+      if (hb_in_range (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
       if (unlikely (u == 0x25CCu)) return _(CP,x);
       break;
 
     case 0xAu:
-      if (hb_in_range (u, 0xA800u, 0xAAF8u)) return indic_table[u - 0xA800u + indic_offset_0xa800u];
-      if (hb_in_range (u, 0xABC0u, 0xAC00u)) return indic_table[u - 0xABC0u + indic_offset_0xabc0u];
+      if (hb_in_range (u, 0xA800u, 0xAAF7u)) return indic_table[u - 0xA800u + indic_offset_0xa800u];
+      if (hb_in_range (u, 0xABC0u, 0xABFFu)) return indic_table[u - 0xABC0u + indic_offset_0xabc0u];
       break;
 
     case 0x10u:
-      if (hb_in_range (u, 0x10A00u, 0x10A48u)) return indic_table[u - 0x10A00u + indic_offset_0x10a00u];
+      if (hb_in_range (u, 0x10A00u, 0x10A47u)) return indic_table[u - 0x10A00u + indic_offset_0x10a00u];
       break;
 
     case 0x11u:
-      if (hb_in_range (u, 0x11000u, 0x110C0u)) return indic_table[u - 0x11000u + indic_offset_0x11000u];
-      if (hb_in_range (u, 0x11100u, 0x11238u)) return indic_table[u - 0x11100u + indic_offset_0x11100u];
-      if (hb_in_range (u, 0x112B0u, 0x11378u)) return indic_table[u - 0x112B0u + indic_offset_0x112b0u];
-      if (hb_in_range (u, 0x11480u, 0x114E0u)) return indic_table[u - 0x11480u + indic_offset_0x11480u];
-      if (hb_in_range (u, 0x11580u, 0x115C8u)) return indic_table[u - 0x11580u + indic_offset_0x11580u];
-      if (hb_in_range (u, 0x11600u, 0x116D0u)) return indic_table[u - 0x11600u + indic_offset_0x11600u];
+      if (hb_in_range (u, 0x11000u, 0x110BFu)) return indic_table[u - 0x11000u + indic_offset_0x11000u];
+      if (hb_in_range (u, 0x11100u, 0x11237u)) return indic_table[u - 0x11100u + indic_offset_0x11100u];
+      if (hb_in_range (u, 0x112B0u, 0x11377u)) return indic_table[u - 0x112B0u + indic_offset_0x112b0u];
+      if (hb_in_range (u, 0x11480u, 0x114DFu)) return indic_table[u - 0x11480u + indic_offset_0x11480u];
+      if (hb_in_range (u, 0x11580u, 0x115C7u)) return indic_table[u - 0x11580u + indic_offset_0x11580u];
+      if (hb_in_range (u, 0x11600u, 0x116CFu)) return indic_table[u - 0x11600u + indic_offset_0x11600u];
       break;
 
     default:
       break;
   }
   return _(x,x);
 }
 
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
@@ -1,10 +1,10 @@
 
-#line 1 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
+#line 1 "hb-ot-shape-complex-myanmar-machine.rl"
 /*
  * Copyright © 2011,2012  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
  * Permission is hereby granted, without written agreement and without
  * license or royalty fees, to use, copy, modify, and distribute this
  * software and its documentation for any purpose, provided that the
@@ -27,17 +27,17 @@
  */
 
 #ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
 
 #include "hb-private.hh"
 
 
-#line 36 "hb-ot-shape-complex-myanmar-machine.hh.tmp"
+#line 36 "hb-ot-shape-complex-myanmar-machine.hh"
 static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
 	1u, 31u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 
 	3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u, 
 	3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 5u, 29u, 5u, 8u, 
 	5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 
 	3u, 30u, 3u, 29u, 1u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 
 	3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 8u, 8u, 0
 };
@@ -256,21 +256,21 @@ static const short _myanmar_syllable_mac
 
 static const int myanmar_syllable_machine_start = 0;
 static const int myanmar_syllable_machine_first_final = 0;
 static const int myanmar_syllable_machine_error = -1;
 
 static const int myanmar_syllable_machine_en_main = 0;
 
 
-#line 36 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
+#line 36 "hb-ot-shape-complex-myanmar-machine.rl"
 
 
 
-#line 93 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
+#line 93 "hb-ot-shape-complex-myanmar-machine.rl"
 
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
     if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
     for (unsigned int i = last; i < p+1; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
     last = p+1; \
@@ -280,48 +280,48 @@ static const int myanmar_syllable_machin
 
 static void
 find_syllables (hb_buffer_t *buffer)
 {
   unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 289 "hb-ot-shape-complex-myanmar-machine.hh.tmp"
+#line 289 "hb-ot-shape-complex-myanmar-machine.hh"
 	{
 	cs = myanmar_syllable_machine_start;
 	ts = 0;
 	te = 0;
 	act = 0;
 	}
 
-#line 114 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
+#line 114 "hb-ot-shape-complex-myanmar-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
   unsigned int last = 0;
   unsigned int syllable_serial = 1;
   
-#line 306 "hb-ot-shape-complex-myanmar-machine.hh.tmp"
+#line 306 "hb-ot-shape-complex-myanmar-machine.hh"
 	{
 	int _slen;
 	int _trans;
 	const unsigned char *_keys;
 	const char *_inds;
 	if ( p == pe )
 		goto _test_eof;
 _resume:
 	switch ( _myanmar_syllable_machine_from_state_actions[cs] ) {
 	case 2:
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 320 "hb-ot-shape-complex-myanmar-machine.hh.tmp"
+#line 320 "hb-ot-shape-complex-myanmar-machine.hh"
 	}
 
 	_keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
 	_inds = _myanmar_syllable_machine_indicies + _myanmar_syllable_machine_index_offsets[cs];
 
 	_slen = _myanmar_syllable_machine_key_spans[cs];
 	_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].myanmar_category()) &&
 		( info[p].myanmar_category()) <= _keys[1] ?
@@ -330,71 +330,71 @@ find_syllables (hb_buffer_t *buffer)
 _eof_trans:
 	cs = _myanmar_syllable_machine_trans_targs[_trans];
 
 	if ( _myanmar_syllable_machine_trans_actions[_trans] == 0 )
 		goto _again;
 
 	switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
 	case 7:
-#line 85 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
+#line 85 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p+1;{ found_syllable (consonant_syllable); }}
 	break;
 	case 5:
-#line 86 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
+#line 86 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p+1;{ found_syllable (non_myanmar_cluster); }}
 	break;
 	case 10:
-#line 87 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
+#line 87 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p+1;{ found_syllable (punctuation_cluster); }}
 	break;
 	case 4:
-#line 88 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
+#line 88 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p+1;{ found_syllable (broken_cluster); }}
 	break;
 	case 3:
-#line 89 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
+#line 89 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p+1;{ found_syllable (non_myanmar_cluster); }}
 	break;
 	case 6:
-#line 85 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
+#line 85 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p;p--;{ found_syllable (consonant_syllable); }}
 	break;
 	case 8:
-#line 88 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
+#line 88 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p;p--;{ found_syllable (broken_cluster); }}
 	break;
 	case 9:
-#line 89 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
+#line 89 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p;p--;{ found_syllable (non_myanmar_cluster); }}
 	break;
-#line 370 "hb-ot-shape-complex-myanmar-machine.hh.tmp"
+#line 370 "hb-ot-shape-complex-myanmar-machine.hh"
 	}
 
 _again:
 	switch ( _myanmar_syllable_machine_to_state_actions[cs] ) {
 	case 1:
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 379 "hb-ot-shape-complex-myanmar-machine.hh.tmp"
+#line 379 "hb-ot-shape-complex-myanmar-machine.hh"
 	}
 
 	if ( ++p != pe )
 		goto _resume;
 	_test_eof: {}
 	if ( p == eof )
 	{
 	if ( _myanmar_syllable_machine_eof_trans[cs] > 0 ) {
 		_trans = _myanmar_syllable_machine_eof_trans[cs] - 1;
 		goto _eof_trans;
 	}
 	}
 
 	}
 
-#line 123 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
+#line 123 "hb-ot-shape-complex-myanmar-machine.rl"
 
 }
 
 #undef found_syllable
 
 #endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH */
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh
@@ -174,19 +174,22 @@ hb_ot_shape_complex_categorize (const hb
     /* Unicode-6.0 additions */
     case HB_SCRIPT_MANDAIC:
 
     /* Unicode-7.0 additions */
     case HB_SCRIPT_MANICHAEAN:
     case HB_SCRIPT_PSALTER_PAHLAVI:
 
       /* For Arabic script, use the Arabic shaper even if no OT script tag was found.
-       * This is because we do fallback shaping for Arabic script (and not others). */
-      if (planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
-	  planner->props.script == HB_SCRIPT_ARABIC)
+       * This is because we do fallback shaping for Arabic script (and not others).
+       * But note that Arabic shaping is applicable only to horizontal layout; for
+       * vertical text, just use the generic shaper instead. */
+      if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
+	   planner->props.script == HB_SCRIPT_ARABIC) &&
+	  HB_DIRECTION_IS_HORIZONTAL(planner->props.direction))
 	return &_hb_ot_complex_shaper_arabic;
       else
 	return &_hb_ot_complex_shaper_default;
 
 
     /* Unicode-1.1 additions */
     case HB_SCRIPT_THAI:
     case HB_SCRIPT_LAO:
@@ -254,16 +257,17 @@ hb_ot_shape_complex_categorize (const hb
     case HB_SCRIPT_TAGBANWA:
 
     /* Unicode-4.0 additions */
     case HB_SCRIPT_LIMBU:
     case HB_SCRIPT_TAI_LE:
 
     /* Unicode-4.1 additions */
     case HB_SCRIPT_KHAROSHTHI:
+    case HB_SCRIPT_NEW_TAI_LUE:
     case HB_SCRIPT_SYLOTI_NAGRI:
 
     /* Unicode-5.1 additions */
     case HB_SCRIPT_KAYAH_LI:
 
     /* Unicode-5.2 additions */
     case HB_SCRIPT_TAI_VIET:
 
@@ -334,17 +338,16 @@ hb_ot_shape_complex_categorize (const hb
 	return &_hb_ot_complex_shaper_myanmar;
       else if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
 	return &_hb_ot_complex_shaper_myanmar_old;
       else
 	return &_hb_ot_complex_shaper_default;
 
     /* Unicode-4.1 additions */
     case HB_SCRIPT_BUGINESE:
-    case HB_SCRIPT_NEW_TAI_LUE:
 
     /* Unicode-5.1 additions */
     case HB_SCRIPT_CHAM:
 
     /* Unicode-5.2 additions */
     case HB_SCRIPT_TAI_THAM:
 
       /* If the designer designed the font for the 'DFLT' script,
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-sea-machine.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-sea-machine.hh
@@ -1,10 +1,10 @@
 
-#line 1 "../../src/hb-ot-shape-complex-sea-machine.rl"
+#line 1 "hb-ot-shape-complex-sea-machine.rl"
 /*
  * Copyright © 2011,2012,2013  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
  * Permission is hereby granted, without written agreement and without
  * license or royalty fees, to use, copy, modify, and distribute this
  * software and its documentation for any purpose, provided that the
@@ -27,17 +27,17 @@
  */
 
 #ifndef HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH
 
 #include "hb-private.hh"
 
 
-#line 36 "hb-ot-shape-complex-sea-machine.hh.tmp"
+#line 36 "hb-ot-shape-complex-sea-machine.hh"
 static const unsigned char _sea_syllable_machine_trans_keys[] = {
 	1u, 1u, 1u, 1u, 1u, 29u, 3u, 29u, 3u, 29u, 1u, 1u, 0
 };
 
 static const char _sea_syllable_machine_key_spans[] = {
 	1, 1, 29, 27, 27, 1
 };
 
@@ -84,21 +84,21 @@ static const char _sea_syllable_machine_
 
 static const int sea_syllable_machine_start = 2;
 static const int sea_syllable_machine_first_final = 2;
 static const int sea_syllable_machine_error = -1;
 
 static const int sea_syllable_machine_en_main = 2;
 
 
-#line 36 "../../src/hb-ot-shape-complex-sea-machine.rl"
+#line 36 "hb-ot-shape-complex-sea-machine.rl"
 
 
 
-#line 67 "../../src/hb-ot-shape-complex-sea-machine.rl"
+#line 67 "hb-ot-shape-complex-sea-machine.rl"
 
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
     if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
     for (unsigned int i = last; i < p+1; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
     last = p+1; \
@@ -108,48 +108,48 @@ static const int sea_syllable_machine_en
 
 static void
 find_syllables (hb_buffer_t *buffer)
 {
   unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 117 "hb-ot-shape-complex-sea-machine.hh.tmp"
+#line 117 "hb-ot-shape-complex-sea-machine.hh"
 	{
 	cs = sea_syllable_machine_start;
 	ts = 0;
 	te = 0;
 	act = 0;
 	}
 
-#line 88 "../../src/hb-ot-shape-complex-sea-machine.rl"
+#line 88 "hb-ot-shape-complex-sea-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
   unsigned int last = 0;
   unsigned int syllable_serial = 1;
   
-#line 134 "hb-ot-shape-complex-sea-machine.hh.tmp"
+#line 134 "hb-ot-shape-complex-sea-machine.hh"
 	{
 	int _slen;
 	int _trans;
 	const unsigned char *_keys;
 	const char *_inds;
 	if ( p == pe )
 		goto _test_eof;
 _resume:
 	switch ( _sea_syllable_machine_from_state_actions[cs] ) {
 	case 5:
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 148 "hb-ot-shape-complex-sea-machine.hh.tmp"
+#line 148 "hb-ot-shape-complex-sea-machine.hh"
 	}
 
 	_keys = _sea_syllable_machine_trans_keys + (cs<<1);
 	_inds = _sea_syllable_machine_indicies + _sea_syllable_machine_index_offsets[cs];
 
 	_slen = _sea_syllable_machine_key_spans[cs];
 	_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].sea_category()) &&
 		( info[p].sea_category()) <= _keys[1] ?
@@ -162,63 +162,63 @@ find_syllables (hb_buffer_t *buffer)
 		goto _again;
 
 	switch ( _sea_syllable_machine_trans_actions[_trans] ) {
 	case 2:
 #line 1 "NONE"
 	{te = p+1;}
 	break;
 	case 6:
-#line 63 "../../src/hb-ot-shape-complex-sea-machine.rl"
+#line 63 "hb-ot-shape-complex-sea-machine.rl"
 	{te = p+1;{ found_syllable (non_sea_cluster); }}
 	break;
 	case 7:
-#line 61 "../../src/hb-ot-shape-complex-sea-machine.rl"
+#line 61 "hb-ot-shape-complex-sea-machine.rl"
 	{te = p;p--;{ found_syllable (consonant_syllable); }}
 	break;
 	case 8:
-#line 62 "../../src/hb-ot-shape-complex-sea-machine.rl"
+#line 62 "hb-ot-shape-complex-sea-machine.rl"
 	{te = p;p--;{ found_syllable (broken_cluster); }}
 	break;
 	case 9:
-#line 63 "../../src/hb-ot-shape-complex-sea-machine.rl"
+#line 63 "hb-ot-shape-complex-sea-machine.rl"
 	{te = p;p--;{ found_syllable (non_sea_cluster); }}
 	break;
 	case 1:
-#line 61 "../../src/hb-ot-shape-complex-sea-machine.rl"
+#line 61 "hb-ot-shape-complex-sea-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (consonant_syllable); }}
 	break;
 	case 3:
-#line 62 "../../src/hb-ot-shape-complex-sea-machine.rl"
+#line 62 "hb-ot-shape-complex-sea-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
 	break;
-#line 194 "hb-ot-shape-complex-sea-machine.hh.tmp"
+#line 194 "hb-ot-shape-complex-sea-machine.hh"
 	}
 
 _again:
 	switch ( _sea_syllable_machine_to_state_actions[cs] ) {
 	case 4:
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 203 "hb-ot-shape-complex-sea-machine.hh.tmp"
+#line 203 "hb-ot-shape-complex-sea-machine.hh"
 	}
 
 	if ( ++p != pe )
 		goto _resume;
 	_test_eof: {}
 	if ( p == eof )
 	{
 	if ( _sea_syllable_machine_eof_trans[cs] > 0 ) {
 		_trans = _sea_syllable_machine_eof_trans[cs] - 1;
 		goto _eof_trans;
 	}
 	}
 
 	}
 
-#line 97 "../../src/hb-ot-shape-complex-sea-machine.rl"
+#line 97 "hb-ot-shape-complex-sea-machine.rl"
 
 }
 
 #undef found_syllable
 
 #endif /* HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH */
--- a/gfx/harfbuzz/src/hb-ot-shape-fallback.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-fallback.cc
@@ -436,23 +436,25 @@ void
 			    hb_font_t *font,
 			    hb_buffer_t  *buffer)
 {
   if (!plan->has_kern) return;
 
   OT::hb_apply_context_t c (1, font, buffer);
   c.set_lookup_mask (plan->kern_mask);
   c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
+  OT::hb_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
+  skippy_iter.init (&c);
 
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
   hb_glyph_position_t *pos = buffer->pos;
   for (unsigned int idx = 0; idx < count;)
   {
-    OT::hb_apply_context_t::skipping_forward_iterator_t skippy_iter (&c, idx, 1);
+    skippy_iter.reset (idx, 1);
     if (!skippy_iter.next ())
     {
       idx++;
       continue;
     }
 
     hb_position_t x_kern, y_kern;
     font->get_glyph_kerning_for_direction (info[idx].codepoint,
--- a/gfx/harfbuzz/src/hb-ot-shape-normalize.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-normalize.cc
@@ -192,26 +192,27 @@ decompose_compatibility (const hb_ot_sha
 
   return len;
 }
 
 static inline void
 decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shortest)
 {
   hb_buffer_t * const buffer = c->buffer;
+  hb_codepoint_t u = buffer->cur().codepoint;
   hb_codepoint_t glyph;
 
   /* Kind of a cute waterfall here... */
-  if (shortest && c->font->get_glyph (buffer->cur().codepoint, 0, &glyph))
+  if (shortest && c->font->get_glyph (u, 0, &glyph))
     next_char (buffer, glyph);
-  else if (decompose (c, shortest, buffer->cur().codepoint))
+  else if (decompose (c, shortest, u))
     skip_char (buffer);
-  else if (!shortest && c->font->get_glyph (buffer->cur().codepoint, 0, &glyph))
+  else if (!shortest && c->font->get_glyph (u, 0, &glyph))
     next_char (buffer, glyph);
-  else if (decompose_compatibility (c, buffer->cur().codepoint))
+  else if (decompose_compatibility (c, u))
     skip_char (buffer);
   else
     next_char (buffer, glyph); /* glyph is initialized in earlier branches. */
 }
 
 static inline void
 handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit)
 {
--- a/gfx/harfbuzz/src/hb-ot-shape.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape.cc
@@ -671,17 +671,17 @@ hb_ot_hide_default_ignorables (hb_ot_sha
 
       if (space_status == SPACE_AVAILABLE)
       {
 	info[i].codepoint = space;
 	pos[i].x_advance = 0;
 	pos[i].y_advance = 0;
       }
       else
-	continue; /* Delete it. */
+	continue; /* Delete it. XXX Merge clusters? */
     }
     if (j != i)
     {
       info[j] = info[i];
       pos[j] = pos[i];
     }
     j++;
   }
--- a/gfx/harfbuzz/src/hb-private.hh
+++ b/gfx/harfbuzz/src/hb-private.hh
@@ -89,30 +89,16 @@
 #ifndef HB_INTERNAL
 # if !defined(__MINGW32__) && !defined(__CYGWIN__)
 #  define HB_INTERNAL __attribute__((__visibility__("hidden")))
 # else
 #  define HB_INTERNAL
 # endif
 #endif
 
-#if defined(_MSC_VER) && _MSC_VER < 1900
-#define snprintf _snprintf
-#endif
-
-#ifdef _MSC_VER
-#undef inline
-#define inline __inline
-#endif
-