Bug 1036981 - Update HarfBuzz to upstream commit d5e6147 (0.9.34). r=jfkthame a=sledru
authorBirunthan Mohanathas <birunthan@mohanathas.com>
Sun, 03 Aug 2014 10:03:46 -0700
changeset 217456 81d788a4bf74c3705e54bba090d95d60c3963cfe
parent 217455 78cc17812ef71fa8524cd5af8a8e9bd8ed6f3468
child 217457 c086369709c627d3ce9fd713eec024b7776a967c
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame, sledru
bugs1036981
milestone33.0a2
Bug 1036981 - Update HarfBuzz to upstream commit d5e6147 (0.9.34). r=jfkthame a=sledru
gfx/harfbuzz/AUTHORS
gfx/harfbuzz/COPYING
gfx/harfbuzz/src/Makefile.am
gfx/harfbuzz/src/check-exported-symbols.sh
gfx/harfbuzz/src/check-includes.sh
gfx/harfbuzz/src/check-internal-symbols.sh
gfx/harfbuzz/src/check-static-inits.sh
gfx/harfbuzz/src/check-symbols.sh
gfx/harfbuzz/src/gen-arabic-table.py
gfx/harfbuzz/src/gen-indic-table.py
gfx/harfbuzz/src/hb-atomic-private.hh
gfx/harfbuzz/src/hb-blob.cc
gfx/harfbuzz/src/hb-blob.h
gfx/harfbuzz/src/hb-buffer-private.hh
gfx/harfbuzz/src/hb-buffer-serialize.cc
gfx/harfbuzz/src/hb-buffer.cc
gfx/harfbuzz/src/hb-buffer.h
gfx/harfbuzz/src/hb-common.cc
gfx/harfbuzz/src/hb-common.h
gfx/harfbuzz/src/hb-coretext.cc
gfx/harfbuzz/src/hb-coretext.h
gfx/harfbuzz/src/hb-face.cc
gfx/harfbuzz/src/hb-fallback-shape.cc
gfx/harfbuzz/src/hb-font.cc
gfx/harfbuzz/src/hb-glib.cc
gfx/harfbuzz/src/hb-gobject-enums.cc
gfx/harfbuzz/src/hb-graphite2.cc
gfx/harfbuzz/src/hb-icu-le.cc
gfx/harfbuzz/src/hb-icu.cc
gfx/harfbuzz/src/hb-mutex-private.hh
gfx/harfbuzz/src/hb-old.cc
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-font.h
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-layout.h
gfx/harfbuzz/src/hb-ot-map-private.hh
gfx/harfbuzz/src/hb-ot-map.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-table.hh
gfx/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh
gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc
gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc
gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl
gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh
gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.hh
gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc
gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.rl
gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
gfx/harfbuzz/src/hb-ot-shape-complex-private.hh
gfx/harfbuzz/src/hb-ot-shape-complex-sea.cc
gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc
gfx/harfbuzz/src/hb-ot-shape-fallback.cc
gfx/harfbuzz/src/hb-ot-shape-normalize.cc
gfx/harfbuzz/src/hb-ot-shape-private.hh
gfx/harfbuzz/src/hb-ot-shape.cc
gfx/harfbuzz/src/hb-ot-shape.h
gfx/harfbuzz/src/hb-ot-tag.cc
gfx/harfbuzz/src/hb-ot.h
gfx/harfbuzz/src/hb-private.hh
gfx/harfbuzz/src/hb-shape-plan.cc
gfx/harfbuzz/src/hb-shape.cc
gfx/harfbuzz/src/hb-shaper-list.hh
gfx/harfbuzz/src/hb-tt-font.cc
gfx/harfbuzz/src/hb-ucdn.cc
gfx/harfbuzz/src/hb-unicode-private.hh
gfx/harfbuzz/src/hb-unicode.cc
gfx/harfbuzz/src/hb-uniscribe.cc
gfx/harfbuzz/src/hb-uniscribe.h
gfx/harfbuzz/src/hb-utf-private.hh
gfx/harfbuzz/src/hb-version.h
gfx/harfbuzz/src/hb-version.h.in
gfx/harfbuzz/src/hb-warning.cc
gfx/harfbuzz/src/indic.cc
gfx/harfbuzz/src/main.cc
gfx/harfbuzz/src/moz.build
--- a/gfx/harfbuzz/AUTHORS
+++ b/gfx/harfbuzz/AUTHORS
@@ -0,0 +1,9 @@
+Behdad Esfahbod
+Simon Hausmann
+Martin Hosken
+Jonathan Kew
+Lars Knoll
+Werner Lemberg
+Roozbeh Pournader
+Owen Taylor
+David Turner
--- a/gfx/harfbuzz/COPYING
+++ b/gfx/harfbuzz/COPYING
@@ -1,16 +1,21 @@
 HarfBuzz is licensed under the so-called "Old MIT" license.  Details follow.
+For parts of HarfBuzz that are licensed under different licenses see individual
+files names COPYING in subdirectories where applicable.
 
-Copyright © 2011 Codethink Limited
-Copyright © 2010,2011  Google, Inc.
-Copyright © 2006  Behdad Esfahbod
+Copyright © 2010,2011,2012  Google, Inc.
+Copyright © 2012  Mozilla Foundation
+Copyright © 2011  Codethink Limited
+Copyright © 2008,2010  Nokia Corporation and/or its subsidiary(-ies)
 Copyright © 2009  Keith Stribley
 Copyright © 2009  Martin Hosken and SIL International
 Copyright © 2007  Chris Wilson
+Copyright © 2006  Behdad Esfahbod
+Copyright © 2005  David Turner
 Copyright © 2004,2007,2008,2009,2010  Red Hat, Inc.
 Copyright © 1998-2004  David Turner and Werner Lemberg
 
 For full copyright notices consult the individual files in the package.
 
 
 Permission is hereby granted, without written agreement and without
 license or royalty fees, to use, copy, modify, and distribute this
--- a/gfx/harfbuzz/src/Makefile.am
+++ b/gfx/harfbuzz/src/Makefile.am
@@ -30,33 +30,33 @@ HBSOURCES =  \
 	hb-face-private.hh \
 	hb-face.cc \
 	hb-font-private.hh \
 	hb-font.cc \
 	hb-mutex-private.hh \
 	hb-object-private.hh \
 	hb-open-file-private.hh \
 	hb-open-type-private.hh \
+	hb-ot-cmap-table.hh \
 	hb-ot-head-table.hh \
 	hb-ot-hhea-table.hh \
 	hb-ot-hmtx-table.hh \
 	hb-ot-maxp-table.hh \
 	hb-ot-name-table.hh \
 	hb-ot-tag.cc \
 	hb-private.hh \
 	hb-set-private.hh \
 	hb-set.cc \
 	hb-shape.cc \
 	hb-shape-plan-private.hh \
 	hb-shape-plan.cc \
 	hb-shaper-list.hh \
 	hb-shaper-impl-private.hh \
 	hb-shaper-private.hh \
 	hb-shaper.cc \
-	hb-tt-font.cc \
 	hb-unicode-private.hh \
 	hb-unicode.cc \
 	hb-utf-private.hh \
 	hb-warning.cc \
 	$(NULL)
 HBHEADERS = \
 	hb.h \
 	hb-blob.h \
@@ -71,30 +71,32 @@ HBHEADERS = \
 	hb-unicode.h \
 	$(NULL)
 HBNODISTHEADERS = \
 	hb-version.h \
 	$(NULL)
 
 if HAVE_OT
 HBSOURCES += \
+	hb-ot-font.cc \
 	hb-ot-layout.cc \
 	hb-ot-layout-common-private.hh \
 	hb-ot-layout-gdef-table.hh \
 	hb-ot-layout-gpos-table.hh \
 	hb-ot-layout-gsubgpos-private.hh \
 	hb-ot-layout-gsub-table.hh \
 	hb-ot-layout-jstf-table.hh \
 	hb-ot-layout-private.hh \
 	hb-ot-map.cc \
 	hb-ot-map-private.hh \
 	hb-ot-shape.cc \
 	hb-ot-shape-complex-arabic.cc \
 	hb-ot-shape-complex-arabic-fallback.hh \
 	hb-ot-shape-complex-arabic-table.hh \
+	hb-ot-shape-complex-arabic-win1256.hh \
 	hb-ot-shape-complex-default.cc \
 	hb-ot-shape-complex-hangul.cc \
 	hb-ot-shape-complex-hebrew.cc \
 	hb-ot-shape-complex-indic.cc \
 	hb-ot-shape-complex-indic-machine.hh \
 	hb-ot-shape-complex-indic-private.hh \
 	hb-ot-shape-complex-indic-table.cc \
 	hb-ot-shape-complex-myanmar.cc \
@@ -107,16 +109,17 @@ HBSOURCES += \
 	hb-ot-shape-normalize-private.hh \
 	hb-ot-shape-normalize.cc \
 	hb-ot-shape-fallback-private.hh \
 	hb-ot-shape-fallback.cc \
 	hb-ot-shape-private.hh \
 	$(NULL)
 HBHEADERS += \
 	hb-ot.h \
+	hb-ot-font.h \
 	hb-ot-layout.h \
 	hb-ot-shape.h \
 	hb-ot-tag.h \
 	$(NULL)
 endif
 
 if HAVE_FALLBACK
 HBSOURCES += hb-fallback-shape.cc
@@ -274,40 +277,41 @@ EXTRA_DIST += $(GENERATORS)
 
 unicode-tables: arabic-table indic-table
 
 indic-table: gen-indic-table.py IndicSyllabicCategory.txt IndicMatraCategory.txt Blocks.txt
 	$(AM_V_GEN) $(builddir)/$^ > hb-ot-shape-complex-indic-table.cc.tmp && \
 	mv hb-ot-shape-complex-indic-table.cc.tmp $(srcdir)/hb-ot-shape-complex-indic-table.cc || \
 	($(RM) hb-ot-shape-complex-indic-table.cc.tmp; false)
 
-arabic-table: gen-arabic-table.py ArabicShaping.txt UnicodeData.txt
+arabic-table: gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt
 	$(AM_V_GEN) $(builddir)/$^ > hb-ot-shape-complex-arabic-table.hh.tmp && \
 	mv hb-ot-shape-complex-arabic-table.hh.tmp $(srcdir)/hb-ot-shape-complex-arabic-table.hh || \
 	($(RM) hb-ot-shape-complex-arabic-table.hh.tmp; false)
 
+built-sources: $(BUILT_SOURCES)
 
-.PHONY: unicode-tables arabic-table indic-table
+.PHONY: unicode-tables arabic-table indic-table built-sources
 
 BUILT_SOURCES += \
 	hb-buffer-deserialize-json.hh \
 	hb-buffer-deserialize-text.hh \
 	hb-ot-shape-complex-indic-machine.hh \
 	hb-ot-shape-complex-myanmar-machine.hh \
 	hb-ot-shape-complex-sea-machine.hh \
 	$(NULL)
 EXTRA_DIST += \
 	hb-buffer-deserialize-json.rl \
 	hb-buffer-deserialize-text.rl \
 	hb-ot-shape-complex-indic-machine.rl \
 	hb-ot-shape-complex-myanmar-machine.rl \
 	hb-ot-shape-complex-sea-machine.rl \
 	$(NULL)
 .rl.hh:
-	$(AM_V_GEN)$(top_srcdir)/missing --run ragel -e -F1 -o "$@.tmp" "$<" && \
+	$(AM_V_GEN)$(RAGEL) -e -F1 -o "$@.tmp" "$<" && \
 	mv "$@.tmp" "$@" || ( $(RM) "$@.tmp" && false )
 
 noinst_PROGRAMS = \
 	main \
 	test \
 	test-buffer-serialize \
 	test-size-params \
 	test-would-substitute \
@@ -353,16 +357,17 @@ TESTS_ENVIRONMENT = \
 	$(NULL)
 
 if HAVE_INTROSPECTION
 
 -include $(INTROSPECTION_MAKEFILE)
 INTROSPECTION_GIRS = HarfBuzz-$(HB_VERSION_MAJOR).0.gir # What does the 0 mean anyway?!
 INTROSPECTION_SCANNER_ARGS = -I$(srcdir) -n hb --identifier-prefix=hb_ --warn-all
 INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
+INTROSPECTION_SCANNER_ENV = CC="$(CC)"
 
 HarfBuzz-0.0.gir: libharfbuzz.la libharfbuzz-gobject.la
 HarfBuzz_0_0_gir_INCLUDES = GObject-2.0
 HarfBuzz_0_0_gir_CFLAGS = \
 	$(INCLUDES) \
 	$(HBCFLAGS) \
 	-DHB_H \
 	-DHB_H_IN \
deleted file mode 100644
--- a/gfx/harfbuzz/src/check-exported-symbols.sh
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/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-exported-symbols.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
-	if test -f "$so"; then
-		echo "Checking that $so has the same symbol list as $def"
-		{
-			echo EXPORTS
-			nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' T _fini\>\| T _init\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>' | cut -d' ' -f3
-			stat=1
-			# 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-exported-symbols.sh: libharfbuzz shared library not found; skipping test"
-	exit 77
-fi
-
-exit $stat
--- a/gfx/harfbuzz/src/check-includes.sh
+++ b/gfx/harfbuzz/src/check-includes.sh
@@ -22,17 +22,17 @@ grep -v 'hb-common[.]h:' |
 grep -v 'hb[.]h:' |
 grep . >&2 && stat=1
 
 
 echo 'Checking that source files #include "hb-*private.hh" first (or none)'
 
 for x in $HBSOURCES; do
 	test -f "$srcdir/$x" && x="$srcdir/$x"
-	grep '#.*\<include\>' "$x" /dev/null | head -n 1
+	grep '#.*\<include\>' "$x" /dev/null | grep -v 'include _' | head -n 1
 done |
 grep -v '"hb-.*private[.]hh"' |
 grep -v 'hb-private[.]hh:' |
 grep . >&2 && stat=1
 
 
 echo 'Checking that there is no #include <hb.*.h>'
 for x in $HBHEADERS $HBSOURCES; do
deleted file mode 100755
--- a/gfx/harfbuzz/src/check-internal-symbols.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/sh
-
-LC_ALL=C
-export LC_ALL
-
-test -z "$srcdir" && srcdir=.
-stat=0
-
-
-if which nm 2>/dev/null >/dev/null; then
-	:
-else
-	echo "check-internal-symbols.sh: 'nm' not found; skipping test"
-	exit 77
-fi
-
-tested=false
-for suffix in .so; do
-	so=`echo .libs/libharfbuzz$suffix`
-	if test -f "$so"; then
-		echo "Checking that we are not exposing internal symbols"
-		if nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' T _fini\>\| T _init\>\| T hb_\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>'; then
-			echo "Ouch, internal symbols exposed"
-			stat=1
-		fi
-		tested=true
-	fi
-done
-if ! $tested; then
-	echo "check-internal-symbols.sh: libharfbuzz shared library not found; skipping test"
-	exit 77
-fi
-
-exit $stat
--- a/gfx/harfbuzz/src/check-static-inits.sh
+++ b/gfx/harfbuzz/src/check-static-inits.sh
@@ -25,15 +25,15 @@ for obj in $OBJS; do
 	if objdump -t "$obj" | grep '[.]ctors'; then
 		echo "Ouch, $obj has static initializers"
 		stat=1
 	fi
 done
 
 echo "Checking that no object file has lazy static C++ constructors/destructors or other such stuff"
 for obj in $OBJS; do
-	if objdump -t "$obj" | grep '__c'; then
+	if objdump -t "$obj" | grep '__cxa_'; then
 		echo "Ouch, $obj has lazy static C++ constructors/destructors or other such stuff"
 		stat=1
 	fi
 done
 
 exit $stat
--- a/gfx/harfbuzz/src/check-symbols.sh
+++ b/gfx/harfbuzz/src/check-symbols.sh
@@ -13,17 +13,17 @@ else
 	echo "check-symbols.sh: 'nm' not found; skipping test"
 	exit 77
 fi
 
 echo "Checking that we are not exposing internal symbols"
 tested=false
 for so in `ls .libs/lib*.so .libs/lib*.dylib 2>/dev/null` ; do
 	
-	EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>' | cut -d' ' -f3`"
+	EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>' | cut -d' ' -f3`"
 	prefix=`basename "$so" | sed 's/libharfbuzz/hb/; s/-/_/g; s/[.].*//'`
 
 	echo "Processing $so"
 	if echo "$EXPORTED_SYMBOLS" | grep -v "^${prefix}_"; then
 		echo "Ouch, internal symbols exposed"
 		stat=1
 	fi
 
--- a/gfx/harfbuzz/src/gen-arabic-table.py
+++ b/gfx/harfbuzz/src/gen-arabic-table.py
@@ -1,85 +1,156 @@
 #!/usr/bin/python
 
 import sys
 import os.path
 
-if len (sys.argv) != 3:
-	print >>sys.stderr, "usage: ./gen-arabic-table.py ArabicShaping.txt UnicodeData.txt"
+if len (sys.argv) != 4:
+	print >>sys.stderr, "usage: ./gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt"
 	sys.exit (1)
 
 files = [file (x) for x in sys.argv[1:]]
 
-headers = [[files[0].readline (), files[0].readline ()]]
+headers = [[files[0].readline (), files[0].readline ()], [files[2].readline (), files[2].readline ()]]
 headers.append (["UnicodeData.txt does not have a header."])
 while files[0].readline ().find ('##################') < 0:
 	pass
 
+blocks = {}
+def read_blocks(f):
+	global blocks
+	for line in f:
+
+		j = line.find ('#')
+		if j >= 0:
+			line = line[:j]
+
+		fields = [x.strip () for x in line.split (';')]
+		if len (fields) == 1:
+			continue
+
+		uu = fields[0].split ('..')
+		start = int (uu[0], 16)
+		if len (uu) == 1:
+			end = start
+		else:
+			end = int (uu[1], 16)
+
+		t = fields[1]
+
+		for u in range (start, end + 1):
+			blocks[u] = t
 
 def print_joining_table(f):
 
-	print
-	print "static const uint8_t joining_table[] ="
-	print "{"
-
-	min_u = 0x110000
-	max_u = 0
-	num = 0
-	last = -1
-	block = ''
+	values = {}
 	for line in f:
 
 		if line[0] == '#':
-			if line.find (" characters"):
-				block = line[2:].strip ()
 			continue
 
 		fields = [x.strip () for x in line.split (';')]
 		if len (fields) == 1:
 			continue
 
 		u = int (fields[0], 16)
-		if u == 0x200C or u == 0x200D:
-			continue
-		if u < last:
-			raise Exception ("Input data character not sorted", u)
-		min_u = min (min_u, u)
-		max_u = max (max_u, u)
-		num += 1
-
-		if block:
-			print "\n  /* %s */\n" % block
-			block = ''
-
-		if last != -1:
-			last += 1
-			while last < u:
-				print "  JOINING_TYPE_X, /* %04X */" % last
-				last += 1
-		else:
-			last = u
 
 		if fields[3] in ["ALAPH", "DALATH RISH"]:
 			value = "JOINING_GROUP_" + fields[3].replace(' ', '_')
 		else:
 			value = "JOINING_TYPE_" + fields[2]
-		print "  %s, /* %s */" % (value, '; '.join(fields))
+		values[u] = value
+
+	short_value = {}
+	for value in set([v for v in values.values()] + ['JOINING_TYPE_X']):
+		short = ''.join(x[0] for x in value.split('_')[2:])
+		assert short not in short_value.values()
+		short_value[value] = short
+
+	print
+	for value,short in short_value.items():
+		print "#define %s	%s" % (short, value)
+
+	uu = sorted(values.keys())
+	num = len(values)
+	all_blocks = set([blocks[u] for u in uu])
+
+	last = -100000
+	ranges = []
+	for u in uu:
+		if u - last <= 1+16*5:
+			ranges[-1][-1] = u
+		else:
+			ranges.append([u,u])
+		last = u
 
 	print
-	print "};"
+	print "static const uint8_t joining_table[] ="
+	print "{"
+	last_block = None
+	offset = 0
+	for start,end in ranges:
+
+		print
+		print "#define joining_offset_0x%04xu %d" % (start, offset)
+
+		for u in range(start, end+1):
+
+			block = blocks.get(u, last_block)
+			value = values.get(u, "JOINING_TYPE_X")
+
+			if block != last_block or u == start:
+				if u != start:
+					print
+				if block in all_blocks:
+					print "\n  /* %s */" % block
+				else:
+					print "\n  /* FILLER */"
+				last_block = block
+				if u % 32 != 0:
+					print
+					print "  /* %04X */" % (u//32*32), "  " * (u % 32),
+
+			if u % 32 == 0:
+				print
+				print "  /* %04X */ " % u,
+			sys.stdout.write("%s," % short_value[value])
+		print
+
+		offset += end - start + 1
 	print
-	print "#define JOINING_TABLE_FIRST	0x%04X" % min_u
-	print "#define JOINING_TABLE_LAST	0x%04X" % max_u
+	occupancy = num * 100. / offset
+	print "}; /* Table items: %d; occupancy: %d%% */" % (offset, occupancy)
 	print
 
-	occupancy = num * 100 / (max_u - min_u + 1)
-	# Maintain at least 40% occupancy in the table */
-	if occupancy < 40:
-		raise Exception ("Table too sparse, please investigate: ", occupancy)
+	page_bits = 12;
+	print
+	print "static unsigned int"
+	print "joining_type (hb_codepoint_t u)"
+	print "{"
+	print "  switch (u >> %d)" % page_bits
+	print "  {"
+	pages = set([u>>page_bits for u in [s for s,e in ranges]+[e for s,e in ranges]])
+	for p in sorted(pages):
+		print "    case 0x%0Xu:" % p
+		for (start,end) in ranges:
+			if p not in [start>>page_bits, end>>page_bits]: continue
+			offset = "joining_offset_0x%04xu" % start
+			print "      if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return joining_table[u - 0x%04Xu + %s];" % (start, end, start, offset)
+		print "      break;"
+		print ""
+	print "    default:"
+	print "      break;"
+	print "  }"
+	print "  return X;"
+	print "}"
+	print
+	for value,short in short_value.items():
+		print "#undef %s" % (short)
+	print
 
 def print_shaping_table(f):
 
 	shapes = {}
 	ligatures = {}
 	names = {}
 	for line in f:
 
@@ -119,23 +190,23 @@ def print_shaping_table(f):
 	print "static const uint16_t shaping_table[][4] ="
 	print "{"
 
 	keys = shapes.keys ()
 	min_u, max_u = min (keys), max (keys)
 	for u in range (min_u, max_u + 1):
 		s = [shapes[u][shape] if u in shapes and shape in shapes[u] else 0
 		     for shape in  ['initial', 'medial', 'final', 'isolated']]
-		value = ', '.join ("0x%04X" % c for c in s)
+		value = ', '.join ("0x%04Xu" % c for c in s)
 		print "  {%s}, /* U+%04X %s */" % (value, u, names[u] if u in names else "")
 
 	print "};"
 	print
-	print "#define SHAPING_TABLE_FIRST	0x%04X" % min_u
-	print "#define SHAPING_TABLE_LAST	0x%04X" % max_u
+	print "#define SHAPING_TABLE_FIRST	0x%04Xu" % min_u
+	print "#define SHAPING_TABLE_LAST	0x%04Xu" % max_u
 	print
 
 	ligas = {}
 	for pair in ligatures.keys ():
 		for shape in ligatures[pair]:
 			c = ligatures[pair][shape]
 			if shape == 'isolated':
 				liga = (shapes[pair[0]]['initial'], shapes[pair[1]]['final'])
@@ -155,43 +226,44 @@ def print_shaping_table(f):
 	print "   uint16_t ligature;"
 	print " } ligatures[%d];" % max_i
 	print "} ligature_table[] ="
 	print "{"
 	keys = ligas.keys ()
 	keys.sort ()
 	for first in keys:
 
-		print "  { 0x%04X, {" % (first)
+		print "  { 0x%04Xu, {" % (first)
 		for liga in ligas[first]:
-			print "    { 0x%04X, 0x%04X }, /* %s */" % (liga[0], liga[1], names[liga[1]])
+			print "    { 0x%04Xu, 0x%04Xu }, /* %s */" % (liga[0], liga[1], names[liga[1]])
 		print "  }},"
 
 	print "};"
 	print
 
 
 
 print "/* == Start of generated table == */"
 print "/*"
 print " * The following table is generated by running:"
 print " *"
-print " *   ./gen-arabic-table.py ArabicShaping.txt UnicodeData.txt"
+print " *   ./gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt"
 print " *"
 print " * on files with these headers:"
 print " *"
 for h in headers:
 	for l in h:
 		print " * %s" % (l.strip())
 print " */"
 print
 print "#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH"
 print "#define HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH"
 print
 
+read_blocks (files[2])
 print_joining_table (files[0])
 print_shaping_table (files[1])
 
 print
 print "#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH */"
 print
 print "/* == End of generated table == */"
 
--- a/gfx/harfbuzz/src/gen-indic-table.py
+++ b/gfx/harfbuzz/src/gen-indic-table.py
@@ -1,21 +1,22 @@
 #!/usr/bin/python
 
 import sys
 
 if len (sys.argv) != 4:
 	print >>sys.stderr, "usage: ./gen-indic-table.py IndicSyllabicCategory.txt IndicMatraCategory.txt Blocks.txt"
 	sys.exit (1)
 
+BLACKLISTED_BLOCKS = ["Thai", "Lao", "Tibetan"]
+
 files = [file (x) for x in sys.argv[1:]]
 
 headers = [[f.readline () for i in range (2)] for f in files]
 
-blocks = {}
 data = [{} for f in files]
 values = [{} for f in files]
 for i, f in enumerate (files):
 	for line in f:
 
 		j = line.find ('#')
 		if j >= 0:
 			line = line[:j]
@@ -30,37 +31,39 @@ for i, f in enumerate (files):
 			end = start
 		else:
 			end = int (uu[1], 16)
 
 		t = fields[1]
 
 		for u in range (start, end + 1):
 			data[i][u] = t
-		values[i][t] = values[i].get (t, 0) + 1
-
-		if i == 2:
-			blocks[t] = (start, end)
+		values[i][t] = values[i].get (t, 0) + end - start + 1
 
 # Merge data into one dict:
 defaults = ('Other', 'Not_Applicable', 'No_Block')
 for i,v in enumerate (defaults):
 	values[i][v] = values[i].get (v, 0) + 1
 combined = {}
 for i,d in enumerate (data):
 	for u,v in d.items ():
 		if i == 2 and not u in combined:
 			continue
 		if not u in combined:
 			combined[u] = list (defaults)
 		combined[u][i] = v
+combined = {k:v for k,v in combined.items() if v[2] not in BLACKLISTED_BLOCKS}
 data = combined
 del combined
 num = len (data)
 
+for u in [0x17CD, 0x17CE, 0x17CF, 0x17D0, 0x17D3]:
+	if data[u][0] == 'Other':
+		data[u][0] = "Vowel_Dependent"
+
 # Move the outliers NO-BREAK SPACE and DOTTED CIRCLE out
 singles = {}
 for u in [0x00A0, 0x25CC]:
 	singles[u] = data[u]
 	del data[u]
 
 print "/* == Start of generated table == */"
 print "/*"
@@ -76,124 +79,150 @@ for h in headers:
 print " */"
 print
 print '#include "hb-ot-shape-complex-indic-private.hh"'
 print
 
 # Shorten values
 short = [{
 	"Bindu":		'Bi',
+	"Cantillation_Mark":	'Ca',
+	"Joiner":		'ZWJ',
+	"Non_Joiner":		'ZWNJ',
+	"Number":		'Nd',
 	"Visarga":		'Vs',
 	"Vowel":		'Vo',
 	"Vowel_Dependent":	'M',
 	"Other":		'x',
 },{
 	"Not_Applicable":	'x',
 }]
-all_shorts = [[],[]]
+all_shorts = [{},{}]
 
 # Add some of the values, to make them more readable, and to avoid duplicates
 
 
 for i in range (2):
 	for v,s in short[i].items ():
-		all_shorts[i].append (s)
+		all_shorts[i][s] = v
 
 what = ["INDIC_SYLLABIC_CATEGORY", "INDIC_MATRA_CATEGORY"]
 what_short = ["ISC", "IMC"]
 for i in range (2):
 	print
 	vv = values[i].keys ()
 	vv.sort ()
 	for v in vv:
 		v_no_and = v.replace ('_And_', '_')
 		if v in short[i]:
 			s = short[i][v]
 		else:
 			s = ''.join ([c for c in v_no_and if ord ('A') <= ord (c) <= ord ('Z')])
 			if s in all_shorts[i]:
-				raise Exception ("Duplicate short value alias", v, s)
-			all_shorts[i].append (s)
+				raise Exception ("Duplicate short value alias", v, all_shorts[i][s])
+			all_shorts[i][s] = v
 			short[i][v] = s
 		print "#define %s_%s	%s_%s	%s/* %3d chars; %s */" % \
 			(what_short[i], s, what[i], v.upper (), \
 			'	'* ((48-1 - len (what[i]) - 1 - len (v)) / 8), \
 			values[i][v], v)
 print
 print "#define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)"
 print
 print
 
 total = 0
 used = 0
+last_block = None
 def print_block (block, start, end, data):
-	print
-	print
-	print "  /* %s  (%04X..%04X) */" % (block, start, end)
+	global total, used, last_block
+	if block and block != last_block:
+		print
+		print
+		print "  /* %s */" % block
 	num = 0
+	assert start % 8 == 0
+	assert (end+1) % 8 == 0
 	for u in range (start, end+1):
 		if u % 8 == 0:
 			print
 			print "  /* %04X */" % u,
 		if u in data:
 			num += 1
 		d = data.get (u, defaults)
 		sys.stdout.write ("%9s" % ("_(%s,%s)," % (short[0][d[0]], short[1][d[1]])))
 
-	global total, used
 	total += end - start + 1
 	used += num
+	if block:
+		last_block = block
 
 uu = data.keys ()
 uu.sort ()
 
-last = -1
+last = -100000
 num = 0
 offset = 0
 starts = []
 ends = []
 print "static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {"
 for u in uu:
 	if u <= last:
 		continue
 	block = data[u][2]
-	(start, end) = blocks[block]
+
+	start = u//8*8
+	end = start+1
+	while end in uu and block == data[end][2]:
+		end += 1
+	end = (end-1)//8*8 + 7
 
 	if start != last + 1:
-		if start - last <= 33:
-			print_block ("FILLER", last+1, start-1, data)
+		if start - last <= 1+16*3:
+			print_block (None, last+1, start-1, data)
 			last = start-1
 		else:
 			if last >= 0:
 				ends.append (last + 1)
 				offset += ends[-1] - starts[-1]
 			print
 			print
-			print "#define indic_offset_0x%04x %d" % (start, offset)
+			print "#define indic_offset_0x%04xu %d" % (start, offset)
 			starts.append (start)
 
 	print_block (block, start, end, data)
 	last = end
 ends.append (last + 1)
 offset += ends[-1] - starts[-1]
 print
 print
-print "#define indic_offset_total %d" % offset
-print
 occupancy = used * 100. / total
-print "}; /* Table occupancy: %d%% */" % occupancy
+page_bits = 12
+print "}; /* Table items: %d; occupancy: %d%% */" % (offset, occupancy)
 print
 print "INDIC_TABLE_ELEMENT_TYPE"
 print "hb_indic_get_categories (hb_codepoint_t u)"
 print "{"
-for (start,end) in zip (starts, ends):
-	offset = "indic_offset_0x%04x" % start
-	print "  if (0x%04X <= u && u <= 0x%04X) return indic_table[u - 0x%04X + %s];" % (start, end, start, offset)
-for u,d in singles.items ():
-	print "  if (unlikely (u == 0x%04X)) return _(%s,%s);" % (u, short[0][d[0]], short[1][d[1]])
+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)
+	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 "  }"
 print "  return _(x,x);"
 print "}"
 print
 print "#undef _"
 for i in range (2):
 	print
 	vv = values[i].keys ()
 	vv.sort ()
--- a/gfx/harfbuzz/src/hb-atomic-private.hh
+++ b/gfx/harfbuzz/src/hb-atomic-private.hh
@@ -39,31 +39,34 @@
 
 /* We need external help for these */
 
 #if 0
 
 
 #elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
 
-#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 
-#if defined(__MINGW32__) && !defined(MemoryBarrier)
+/* MinGW has a convoluted history of supporting MemoryBarrier
+ * properly.  As such, define a function to wrap the whole
+ * thing. */
 static inline void _HBMemoryBarrier (void) {
+#if !defined(MemoryBarrier)
   long dummy = 0;
   InterlockedExchange (&dummy, 1);
+#else
+  MemoryBarrier ();
+#endif
 }
-# define MemoryBarrier _HBMemoryBarrier
-#endif
 
 typedef LONG hb_atomic_int_t;
 #define hb_atomic_int_add(AI, V)	InterlockedExchangeAdd (&(AI), (V))
 
-#define hb_atomic_ptr_get(P)		(MemoryBarrier (), (void *) *(P))
+#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))
 
 
 #elif !defined(HB_NO_MT) && defined(__APPLE__)
 
 #include <libkern/OSAtomic.h>
 #ifdef __MAC_OS_X_MIN_REQUIRED
 #include <AvailabilityMacros.h>
@@ -73,17 +76,17 @@ typedef LONG hb_atomic_int_t;
 
 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))
 #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))
 #else
-#if __ppc64__ || __x86_64__ || __arm64__
+#if __ppc64__ || __x86_64__ || __aarch64__
 #define hb_atomic_ptr_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))
 #endif
 #endif
 
 
 #elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
--- a/gfx/harfbuzz/src/hb-blob.cc
+++ b/gfx/harfbuzz/src/hb-blob.cc
@@ -20,17 +20,19 @@
  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Red Hat Author(s): Behdad Esfahbod
  */
 
 /* http://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html */
+#ifndef _POSIX_C_SOURCE
 #define _POSIX_C_SOURCE 199309L
+#endif
 
 #include "hb-private.hh"
 
 #include "hb-object-private.hh"
 
 #ifdef HAVE_SYS_MMAN_H
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
--- a/gfx/harfbuzz/src/hb-blob.h
+++ b/gfx/harfbuzz/src/hb-blob.h
@@ -42,24 +42,23 @@ HB_BEGIN_DECLS
  * - In no case shall the HarfBuzz client modify memory
  *   that is passed to HarfBuzz in a blob.  If there is
  *   any such possibility, MODE_DUPLICATE should be used
  *   such that HarfBuzz makes a copy immediately,
  *
  * - Use MODE_READONLY otherse, unless you really really
  *   really know what you are doing,
  *
- * - MODE_WRITABLE is appropriate if you relaly made a
+ * - MODE_WRITABLE is appropriate if you really made a
  *   copy of data solely for the purpose of passing to
  *   HarfBuzz and doing that just once (no reuse!),
  *
  * - If the font is mmap()ed, it's ok to use
- *   READONLY_MAY_MAKE_WRITABLE, however, there were
- *   design problems with that mode, so HarfBuzz do not
- *   really use it anymore.  If not sure, use MODE_READONLY.
+ *   READONLY_MAY_MAKE_WRITABLE, however, using that mode
+ *   correctly is very tricky.  Use MODE_READONLY instead.
  */
 typedef enum {
   HB_MEMORY_MODE_DUPLICATE,
   HB_MEMORY_MODE_READONLY,
   HB_MEMORY_MODE_WRITABLE,
   HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE
 } hb_memory_mode_t;
 
--- a/gfx/harfbuzz/src/hb-buffer-private.hh
+++ b/gfx/harfbuzz/src/hb-buffer-private.hh
@@ -47,16 +47,17 @@ struct hb_buffer_t {
   hb_object_header_t header;
   ASSERT_POD ();
 
   /* Information about how the text in the buffer should be treated */
 
   hb_unicode_funcs_t *unicode; /* Unicode functions */
   hb_segment_properties_t props; /* Script, language, direction */
   hb_buffer_flags_t flags; /* BOT / EOT / etc. */
+  hb_codepoint_t replacement; /* U+FFFD or something else. */
 
   /* Buffer contents */
 
   hb_buffer_content_type_t content_type;
 
   bool in_error; /* Allocation failed */
   bool have_output; /* Whether we have an output buffer going on */
   bool have_positions; /* Whether we have positions */
--- a/gfx/harfbuzz/src/hb-buffer-serialize.cc
+++ b/gfx/harfbuzz/src/hb-buffer-serialize.cc
@@ -58,17 +58,17 @@ hb_buffer_serialize_list_formats (void)
  * Return value: 
  *
  * Since: 1.0
  **/
 hb_buffer_serialize_format_t
 hb_buffer_serialize_format_from_string (const char *str, int len)
 {
   /* Upper-case it. */
-  return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020);
+  return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020u);
 }
 
 /**
  * hb_buffer_serialize_format_to_string:
  * @format: 
  *
  * 
  *
--- a/gfx/harfbuzz/src/hb-buffer.cc
+++ b/gfx/harfbuzz/src/hb-buffer.cc
@@ -173,16 +173,17 @@ hb_buffer_t::get_scratch_buffer (unsigne
 void
 hb_buffer_t::reset (void)
 {
   if (unlikely (hb_object_is_inert (this)))
     return;
 
   hb_unicode_funcs_destroy (unicode);
   unicode = hb_unicode_funcs_get_default ();
+  replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
 
   clear ();
 }
 
 void
 hb_buffer_t::clear (void)
 {
   if (unlikely (hb_object_is_inert (this)))
@@ -495,16 +496,20 @@ hb_buffer_t::reverse_clusters (void)
   }
   reverse_range (start, i);
 }
 
 void
 hb_buffer_t::merge_clusters (unsigned int start,
 			     unsigned int end)
 {
+#ifdef HB_NO_MERGE_CLUSTERS
+  return;
+#endif
+
   if (unlikely (end - start < 2))
     return;
 
   unsigned int cluster = info[start].cluster;
 
   for (unsigned int i = start + 1; i < end; i++)
     cluster = MIN (cluster, info[i].cluster);
 
@@ -523,16 +528,20 @@ hb_buffer_t::merge_clusters (unsigned in
 
   for (unsigned int i = start; i < end; i++)
     info[i].cluster = cluster;
 }
 void
 hb_buffer_t::merge_out_clusters (unsigned int start,
 				 unsigned int end)
 {
+#ifdef HB_NO_MERGE_CLUSTERS
+  return;
+#endif
+
   if (unlikely (end - start < 2))
     return;
 
   unsigned int cluster = out_info[start].cluster;
 
   for (unsigned int i = start + 1; i < end; i++)
     cluster = MIN (cluster, out_info[i].cluster);
 
@@ -690,16 +699,17 @@ hb_buffer_t *
 hb_buffer_get_empty (void)
 {
   static const hb_buffer_t _hb_buffer_nil = {
     HB_OBJECT_HEADER_STATIC,
 
     const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
     HB_SEGMENT_PROPERTIES_DEFAULT,
     HB_BUFFER_FLAG_DEFAULT,
+    HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
 
     HB_BUFFER_CONTENT_TYPE_INVALID,
     true, /* in_error */
     true, /* have_output */
     true  /* have_positions */
 
     /* Zero is good enough for everything else. */
   };
@@ -1035,16 +1045,52 @@ hb_buffer_set_flags (hb_buffer_t       *
 hb_buffer_flags_t
 hb_buffer_get_flags (hb_buffer_t *buffer)
 {
   return buffer->flags;
 }
 
 
 /**
+ * hb_buffer_set_replacement_codepoint:
+ * @buffer: a buffer.
+ * @replacement: 
+ *
+ * 
+ *
+ * Since: 1.0
+ **/
+void
+hb_buffer_set_replacement_codepoint (hb_buffer_t    *buffer,
+				     hb_codepoint_t  replacement)
+{
+  if (unlikely (hb_object_is_inert (buffer)))
+    return;
+
+  buffer->replacement = replacement;
+}
+
+/**
+ * hb_buffer_get_replacement_codepoint:
+ * @buffer: a buffer.
+ *
+ * 
+ *
+ * Return value: 
+ *
+ * Since: 1.0
+ **/
+hb_codepoint_t
+hb_buffer_get_replacement_codepoint (hb_buffer_t    *buffer)
+{
+  return buffer->replacement;
+}
+
+
+/**
  * hb_buffer_reset:
  * @buffer: a buffer.
  *
  * 
  *
  * Since: 1.0
  **/
 void
@@ -1277,32 +1323,35 @@ 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 <typename T>
+template <bool validate, typename T>
 static inline void
 hb_buffer_add_utf (hb_buffer_t  *buffer,
 		   const T      *text,
 		   int           text_length,
 		   unsigned int  item_offset,
 		   int           item_length)
 {
+  typedef hb_utf_t<T, true> utf_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;
 
   if (text_length == -1)
-    text_length = hb_utf_strlen (text);
+    text_length = utf_t::strlen (text);
 
   if (item_length == -1)
     item_length = text_length - item_offset;
 
   buffer->ensure (buffer->len + item_length * sizeof (T) / 4);
 
   /* If buffer is empty and pre-context provided, install it.
    * This check is written this way, to make sure people can
@@ -1315,38 +1364,38 @@ hb_buffer_add_utf (hb_buffer_t  *buffer,
   {
     /* Add pre-context */
     buffer->clear_context (0);
     const T *prev = text + item_offset;
     const T *start = text;
     while (start < prev && buffer->context_len[0] < buffer->CONTEXT_LENGTH)
     {
       hb_codepoint_t u;
-      prev = hb_utf_prev (prev, start, &u);
+      prev = utf_t::prev (prev, start, &u, replacement);
       buffer->context[0][buffer->context_len[0]++] = u;
     }
   }
 
   const T *next = text + item_offset;
   const T *end = next + item_length;
   while (next < end)
   {
     hb_codepoint_t u;
     const T *old_next = next;
-    next = hb_utf_next (next, end, &u);
+    next = utf_t::next (next, end, &u, replacement);
     buffer->add (u, old_next - (const T *) text);
   }
 
   /* Add post-context */
   buffer->clear_context (1);
   end = text + text_length;
   while (next < end && buffer->context_len[1] < buffer->CONTEXT_LENGTH)
   {
     hb_codepoint_t u;
-    next = hb_utf_next (next, end, &u);
+    next = utf_t::next (next, end, &u, replacement);
     buffer->context[1][buffer->context_len[1]++] = u;
   }
 
   buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE;
 }
 
 /**
  * hb_buffer_add_utf8:
@@ -1362,17 +1411,17 @@ hb_buffer_add_utf (hb_buffer_t  *buffer,
  **/
 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 (buffer, (const uint8_t *) text, text_length, item_offset, item_length);
+  hb_buffer_add_utf<true> (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: 
@@ -1384,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 (buffer, text, text_length, item_offset, item_length);
+  hb_buffer_add_utf<true> (buffer, text, text_length, item_offset, item_length);
 }
 
 /**
  * hb_buffer_add_utf32:
  * @buffer: a buffer.
  * @text: (array length=text_length):
  * @text_length: 
  * @item_offset: 
@@ -1406,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 (buffer, text, text_length, item_offset, item_length);
+  hb_buffer_add_utf<true> (buffer, text, text_length, item_offset, item_length);
+}
+
+/**
+ * hb_buffer_add_codepoints:
+ * @buffer: a buffer.
+ * @text: (array length=text_length):
+ * @text_length: 
+ * @item_offset: 
+ * @item_length: 
+ *
+ * 
+ *
+ * Since: 1.0
+ **/
+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);
 }
 
 
 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
@@ -181,22 +181,35 @@ typedef enum { /*< flags >*/
 void
 hb_buffer_set_flags (hb_buffer_t       *buffer,
 		     hb_buffer_flags_t  flags);
 
 hb_buffer_flags_t
 hb_buffer_get_flags (hb_buffer_t *buffer);
 
 
+
+#define HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT 0xFFFDu
+
+/* Sets codepoint used to replace invalid UTF-8/16/32 entries.
+ * Default is 0xFFFDu. */
+void
+hb_buffer_set_replacement_codepoint (hb_buffer_t    *buffer,
+				     hb_codepoint_t  replacement);
+
+hb_codepoint_t
+hb_buffer_get_replacement_codepoint (hb_buffer_t    *buffer);
+
+
 /* Resets the buffer.  Afterwards it's as if it was just created,
  * except that it has a larger buffer allocated perhaps... */
 void
 hb_buffer_reset (hb_buffer_t *buffer);
 
-/* Like reset, but does NOT clear unicode_funcs. */
+/* Like reset, but does NOT clear unicode_funcs and replacement_codepoint. */
 void
 hb_buffer_clear_contents (hb_buffer_t *buffer);
 
 /* Returns false if allocation failed */
 hb_bool_t
 hb_buffer_pre_allocate (hb_buffer_t  *buffer,
 		        unsigned int  size);
 
@@ -235,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);
 
+/* 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);
+
 
 /* Clears any new items added at the end */
 hb_bool_t
 hb_buffer_set_length (hb_buffer_t  *buffer,
 		      unsigned int  length);
 
 /* Return value valid as long as buffer not modified */
 unsigned int
--- a/gfx/harfbuzz/src/hb-common.cc
+++ b/gfx/harfbuzz/src/hb-common.cc
@@ -294,19 +294,21 @@ hb_language_from_string (const char *str
 {
   char strbuf[64];
 
   if (!str || !len || !*str)
     return HB_LANGUAGE_INVALID;
 
   if (len >= 0)
   {
+    /* NUL-terminate it. */
     len = MIN (len, (int) sizeof (strbuf) - 1);
-    str = (char *) memcpy (strbuf, str, len);
+    memcpy (strbuf, str, len);
     strbuf[len] = '\0';
+    str = strbuf;
   }
 
   hb_language_item_t *item = lang_find_or_insert (str);
 
   return likely (item) ? item->lang : HB_LANGUAGE_INVALID;
 }
 
 /**
@@ -364,17 +366,17 @@ hb_language_get_default (void)
  **/
 hb_script_t
 hb_script_from_iso15924_tag (hb_tag_t tag)
 {
   if (unlikely (tag == HB_TAG_NONE))
     return HB_SCRIPT_INVALID;
 
   /* Be lenient, adjust case (one capital letter followed by three small letters) */
-  tag = (tag & 0xDFDFDFDF) | 0x00202020;
+  tag = (tag & 0xDFDFDFDFu) | 0x00202020u;
 
   switch (tag) {
 
     /* These graduated from the 'Q' private-area codes, but
      * the old code is still aliased by Unicode, and the Qaai
      * one in use by ICU. */
     case HB_TAG('Q','a','a','i'): return HB_SCRIPT_INHERITED;
     case HB_TAG('Q','a','a','c'): return HB_SCRIPT_COPTIC;
@@ -384,17 +386,17 @@ hb_script_from_iso15924_tag (hb_tag_t ta
     case HB_TAG('L','a','t','f'): return HB_SCRIPT_LATIN;
     case HB_TAG('L','a','t','g'): return HB_SCRIPT_LATIN;
     case HB_TAG('S','y','r','e'): return HB_SCRIPT_SYRIAC;
     case HB_TAG('S','y','r','j'): return HB_SCRIPT_SYRIAC;
     case HB_TAG('S','y','r','n'): return HB_SCRIPT_SYRIAC;
   }
 
   /* If it looks right, just use the tag as a script */
-  if (((uint32_t) tag & 0xE0E0E0E0) == 0x40606060)
+  if (((uint32_t) tag & 0xE0E0E0E0u) == 0x40606060u)
     return (hb_script_t) tag;
 
   /* Otherwise, return unknown */
   return HB_SCRIPT_UNKNOWN;
 }
 
 /**
  * hb_script_from_string:
@@ -477,16 +479,24 @@ hb_script_get_horizontal_direction (hb_s
 
     /* Unicode-6.0 additions */
     case HB_SCRIPT_MANDAIC:
 
     /* Unicode-6.1 additions */
     case HB_SCRIPT_MEROITIC_CURSIVE:
     case HB_SCRIPT_MEROITIC_HIEROGLYPHS:
 
+    /* Unicode-7.0 additions */
+    case HB_SCRIPT_MANICHAEAN:
+    case HB_SCRIPT_MENDE_KIKAKUI:
+    case HB_SCRIPT_NABATAEAN:
+    case HB_SCRIPT_OLD_NORTH_ARABIAN:
+    case HB_SCRIPT_PALMYRENE:
+    case HB_SCRIPT_PSALTER_PAHLAVI:
+
       return HB_DIRECTION_RTL;
   }
 
   return HB_DIRECTION_LTR;
 }
 
 
 /* hb_user_data_array_t */
@@ -554,26 +564,26 @@ hb_version (unsigned int *major,
  **/
 const char *
 hb_version_string (void)
 {
   return HB_VERSION_STRING;
 }
 
 /**
- * hb_version_check:
+ * hb_version_atleast:
  * @major: 
  * @minor: 
  * @micro: 
  *
  * 
  *
  * Return value: 
  *
  * Since: 1.0
  **/
 hb_bool_t
-hb_version_check (unsigned int major,
-		  unsigned int minor,
-		  unsigned int micro)
+hb_version_atleast (unsigned int major,
+		    unsigned int minor,
+		    unsigned int micro)
 {
-  return HB_VERSION_CHECK (major, minor, micro);
+  return HB_VERSION_ATLEAST (major, minor, micro);
 }
--- a/gfx/harfbuzz/src/hb-common.h
+++ b/gfx/harfbuzz/src/hb-common.h
@@ -90,16 +90,17 @@ typedef union _hb_var_int_t {
 
 typedef uint32_t hb_tag_t;
 
 #define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint8_t)(c1))<<24)|(((uint8_t)(c2))<<16)|(((uint8_t)(c3))<<8)|((uint8_t)(c4))))
 #define HB_UNTAG(tag)   ((uint8_t)((tag)>>24)), ((uint8_t)((tag)>>16)), ((uint8_t)((tag)>>8)), ((uint8_t)(tag))
 
 #define HB_TAG_NONE HB_TAG(0,0,0,0)
 #define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff)
+#define HB_TAG_MAX_SIGNED HB_TAG(0x7f,0xff,0xff,0xff)
 
 /* len=-1 means str is NUL-terminated. */
 hb_tag_t
 hb_tag_from_string (const char *str, int len);
 
 /* buf should have 4 bytes. */
 void
 hb_tag_to_string (hb_tag_t tag, char *buf);
@@ -265,59 +266,62 @@ typedef enum
   /*6.1*/ HB_SCRIPT_CHAKMA			= HB_TAG ('C','a','k','m'),
   /*6.1*/ HB_SCRIPT_MEROITIC_CURSIVE		= HB_TAG ('M','e','r','c'),
   /*6.1*/ HB_SCRIPT_MEROITIC_HIEROGLYPHS	= HB_TAG ('M','e','r','o'),
   /*6.1*/ HB_SCRIPT_MIAO			= HB_TAG ('P','l','r','d'),
   /*6.1*/ HB_SCRIPT_SHARADA			= HB_TAG ('S','h','r','d'),
   /*6.1*/ HB_SCRIPT_SORA_SOMPENG		= HB_TAG ('S','o','r','a'),
   /*6.1*/ HB_SCRIPT_TAKRI			= HB_TAG ('T','a','k','r'),
 
-  /* No script set. */
-  /*---*/ HB_SCRIPT_INVALID			= HB_TAG_NONE,
-
-  /* Dummy value to ensure any hb_tag_t value can be passed/stored as hb_script_t
-   * without risking undefined behavior. */
-  /*---*/ _HB_SCRIPT_MAX_VALUE			= HB_TAG_MAX
-
-} hb_script_t;
-
-/* These are moved out of hb_script_t because glib-mkenums chokes otherwise. */
-#if 0
   /*7.0*/ HB_SCRIPT_BASSA_VAH			= HB_TAG ('B','a','s','s'),
   /*7.0*/ HB_SCRIPT_CAUCASIAN_ALBANIAN		= HB_TAG ('A','g','h','b'),
   /*7.0*/ HB_SCRIPT_DUPLOYAN			= HB_TAG ('D','u','p','l'),
   /*7.0*/ HB_SCRIPT_ELBASAN			= HB_TAG ('E','l','b','a'),
   /*7.0*/ HB_SCRIPT_GRANTHA			= HB_TAG ('G','r','a','n'),
   /*7.0*/ HB_SCRIPT_KHOJKI			= HB_TAG ('K','h','o','j'),
   /*7.0*/ HB_SCRIPT_KHUDAWADI			= HB_TAG ('S','i','n','d'),
   /*7.0*/ HB_SCRIPT_LINEAR_A			= HB_TAG ('L','i','n','a'),
   /*7.0*/ HB_SCRIPT_MAHAJANI			= HB_TAG ('M','a','h','j'),
   /*7.0*/ HB_SCRIPT_MANICHAEAN			= HB_TAG ('M','a','n','i'),
   /*7.0*/ HB_SCRIPT_MENDE_KIKAKUI		= HB_TAG ('M','e','n','d'),
-  /*7.0*/ HB_SCRIPT_MODI			= ???
+  /*7.0*/ HB_SCRIPT_MODI			= HB_TAG ('M','o','d','i'),
   /*7.0*/ HB_SCRIPT_MRO				= HB_TAG ('M','r','o','o'),
   /*7.0*/ HB_SCRIPT_NABATAEAN			= HB_TAG ('N','b','a','t'),
   /*7.0*/ HB_SCRIPT_OLD_NORTH_ARABIAN		= HB_TAG ('N','a','r','b'),
   /*7.0*/ HB_SCRIPT_OLD_PERMIC			= HB_TAG ('P','e','r','m'),
   /*7.0*/ HB_SCRIPT_PAHAWH_HMONG		= HB_TAG ('H','m','n','g'),
   /*7.0*/ HB_SCRIPT_PALMYRENE			= HB_TAG ('P','a','l','m'),
-  /*7.0*/ HB_SCRIPT_PAU_CIN_HAU			= ???
+  /*7.0*/ HB_SCRIPT_PAU_CIN_HAU			= HB_TAG ('P','a','u','c'),
   /*7.0*/ HB_SCRIPT_PSALTER_PAHLAVI		= HB_TAG ('P','h','l','p'),
-  /*7.0*/ HB_SCRIPT_SIDDHAM			= ???
+  /*7.0*/ HB_SCRIPT_SIDDHAM			= HB_TAG ('S','i','d','d'),
   /*7.0*/ HB_SCRIPT_TIRHUTA			= HB_TAG ('T','i','r','h'),
   /*7.0*/ HB_SCRIPT_WARANG_CITI			= HB_TAG ('W','a','r','a'),
-#endif
+
+  /* No script set. */
+  HB_SCRIPT_INVALID				= HB_TAG_NONE,
+
+  /* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t
+   * without risking undefined behavior.  Include both a signed and unsigned max,
+   * since technically enums are int, and indeed, hb_script_t ends up being signed.
+   * See this thread for technicalities:
+   *
+   *   http://lists.freedesktop.org/archives/harfbuzz/2014-March/004150.html
+   */
+  _HB_SCRIPT_MAX_VALUE				= HB_TAG_MAX, /*< skip >*/
+  _HB_SCRIPT_MAX_VALUE_SIGNED			= HB_TAG_MAX_SIGNED /*< skip >*/
+
+} hb_script_t;
 
 
 /* Script functions */
 
 hb_script_t
 hb_script_from_iso15924_tag (hb_tag_t tag);
 
-/* suger for tag_from_string() then script_from_iso15924_tag */
+/* sugar for tag_from_string() then script_from_iso15924_tag */
 /* len=-1 means s is NUL-terminated */
 hb_script_t
 hb_script_from_string (const char *s, int len);
 
 hb_tag_t
 hb_script_to_iso15924_tag (hb_script_t script);
 
 hb_direction_t
--- a/gfx/harfbuzz/src/hb-coretext.cc
+++ b/gfx/harfbuzz/src/hb-coretext.cc
@@ -32,16 +32,48 @@
 #include "hb-coretext.h"
 
 
 #ifndef HB_DEBUG_CORETEXT
 #define HB_DEBUG_CORETEXT (HB_DEBUG+0)
 #endif
 
 
+static void
+release_table_data (void *user_data)
+{
+  CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data);
+  CFRelease(cf_data);
+}
+
+static hb_blob_t *
+reference_table  (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
+{
+  CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data);
+  CFDataRef cf_data = CGFontCopyTableForTag (cg_font, tag);
+  if (unlikely (!cf_data))
+    return NULL;
+
+  const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data));
+  const size_t length = CFDataGetLength (cf_data);
+  if (!data || !length)
+    return NULL;
+
+  return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY,
+			 reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)),
+			 release_table_data);
+}
+
+hb_face_t *
+hb_coretext_face_create (CGFontRef cg_font)
+{
+  return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), (hb_destroy_func_t) CGFontRelease);
+}
+
+
 HB_SHAPER_DATA_ENSURE_DECLARE(coretext, face)
 HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font)
 
 
 /*
  * shaper face data
  */
 
@@ -60,25 +92,32 @@ release_data (void *info, const void *da
 
 hb_coretext_shaper_face_data_t *
 _hb_coretext_shaper_face_data_create (hb_face_t *face)
 {
   hb_coretext_shaper_face_data_t *data = (hb_coretext_shaper_face_data_t *) calloc (1, sizeof (hb_coretext_shaper_face_data_t));
   if (unlikely (!data))
     return NULL;
 
-  hb_blob_t *blob = hb_face_reference_blob (face);
-  unsigned int blob_length;
-  const char *blob_data = hb_blob_get_data (blob, &blob_length);
-  if (unlikely (!blob_length))
-    DEBUG_MSG (CORETEXT, face, "Face has empty blob");
+  if (face->destroy == (hb_destroy_func_t) CGFontRelease)
+  {
+    data->cg_font = CGFontRetain ((CGFontRef) face->user_data);
+  }
+  else
+  {
+    hb_blob_t *blob = hb_face_reference_blob (face);
+    unsigned int blob_length;
+    const char *blob_data = hb_blob_get_data (blob, &blob_length);
+    if (unlikely (!blob_length))
+      DEBUG_MSG (CORETEXT, face, "Face has empty blob");
 
-  CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data);
-  data->cg_font = CGFontCreateWithDataProvider (provider);
-  CGDataProviderRelease (provider);
+    CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data);
+    data->cg_font = CGFontCreateWithDataProvider (provider);
+    CGDataProviderRelease (provider);
+  }
 
   if (unlikely (!data->cg_font)) {
     DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed");
     free (data);
     return NULL;
   }
 
   return data;
@@ -433,17 +472,17 @@ hb_bool_t
 
       event = feature_events.push ();
       if (unlikely (!event))
 	goto fail_features;
       event->index = features[i].end;
       event->start = false;
       event->feature = feature;
     }
-    feature_events.sort ();
+    feature_events.qsort ();
     /* Add a strategic final event. */
     {
       active_feature_t feature;
       feature.rec.feature = HB_TAG_NONE;
       feature.rec.setting = 0;
       feature.order = num_features + 1;
 
       feature_event_t *event = feature_events.push ();
@@ -463,24 +502,22 @@ hb_bool_t
 
       if (event->index != last_index)
       {
         /* Save a snapshot of active features and the range. */
 	range_record_t *range = range_records.push ();
 	if (unlikely (!range))
 	  goto fail_features;
 
-	unsigned int offset = feature_records.len;
-
 	if (active_features.len)
 	{
 	  CFMutableArrayRef features_array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
 
 	  /* TODO sort and resolve conflicting features? */
-	  /* active_features.sort (); */
+	  /* active_features.qsort (); */
 	  for (unsigned int j = 0; j < active_features.len; j++)
 	  {
 	    CFStringRef keys[2] = {
 	      kCTFontFeatureTypeIdentifierKey,
 	      kCTFontFeatureSelectorIdentifierKey
 	    };
 	    CFNumberRef values[2] = {
 	      CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.feature),
@@ -568,23 +605,23 @@ hb_bool_t
 #define utf16_index() var1.u32
 
   ALLOCATE_ARRAY (UniChar, pchars, buffer->len * 2);
 
   unsigned int chars_len = 0;
   for (unsigned int i = 0; i < buffer->len; i++) {
     hb_codepoint_t c = buffer->info[i].codepoint;
     buffer->info[i].utf16_index() = chars_len;
-    if (likely (c < 0x10000))
+    if (likely (c <= 0xFFFFu))
       pchars[chars_len++] = c;
-    else if (unlikely (c >= 0x110000))
-      pchars[chars_len++] = 0xFFFD;
+    else if (unlikely (c > 0x10FFFFu))
+      pchars[chars_len++] = 0xFFFDu;
     else {
-      pchars[chars_len++] = 0xD800 + ((c - 0x10000) >> 10);
-      pchars[chars_len++] = 0xDC00 + ((c - 0x10000) & ((1 << 10) - 1));
+      pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
+      pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1));
     }
   }
 
 #undef utf16_index
 
   CFStringRef string_ref = CFStringCreateWithCharactersNoCopy (NULL,
                                                                pchars, chars_len,
                                                                kCFAllocatorNull);
@@ -600,17 +637,17 @@ hb_bool_t
 
     /* Need log_clusters to assign features. */
     chars_len = 0;
     for (unsigned int i = 0; i < buffer->len; i++)
     {
       hb_codepoint_t c = buffer->info[i].codepoint;
       unsigned int cluster = buffer->info[i].cluster;
       log_clusters[chars_len++] = cluster;
-      if (c >= 0x10000 && c < 0x110000)
+      if (hb_in_range (c, 0x10000u, 0x10FFFFu))
 	log_clusters[chars_len++] = cluster; /* Surrogates. */
     }
 
     unsigned int start = 0;
     range_record_t *last_range = &range_records[0];
     for (unsigned int k = 0; k < chars_len; k++)
     {
       range_record_t *range = last_range;
@@ -672,20 +709,20 @@ hb_bool_t
 	hb_glyph_info_t *info = buffer->info + buffer->len;
 
 	CGGlyph notdef = 0;
 	double advance = CTFontGetAdvancesForGlyphs (font_data->ct_font, kCTFontHorizontalOrientation, &notdef, NULL, 1);
 
         for (CFIndex j = range.location; j < range.location + range.length; j++)
 	{
 	    UniChar ch = CFStringGetCharacterAtIndex (string_ref, j);
-	    if (hb_in_range<UniChar> (ch, 0xDC00, 0xDFFF) && range.location < j)
+	    if (hb_in_range<UniChar> (ch, 0xDC00u, 0xDFFFu) && range.location < j)
 	    {
 	      ch = CFStringGetCharacterAtIndex (string_ref, j - 1);
-	      if (hb_in_range<UniChar> (ch, 0xD800, 0xDBFF))
+	      if (hb_in_range<UniChar> (ch, 0xD800u, 0xDBFFu))
 	        /* This is the second of a surrogate pair.  Don't need .notdef
 		 * for this one. */
 	        continue;
 	    }
 
             info->codepoint = notdef;
 	    /* TODO We have to fixup clusters later.  See vis_clusters in
 	     * hb-uniscribe.cc for example. */
@@ -805,8 +842,102 @@ hb_bool_t
     }
   }
 
   CFRelease (string_ref);
   CFRelease (line);
 
   return true;
 }
+
+
+/*
+ * AAT shaper
+ */
+
+HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, face)
+HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, font)
+
+
+/*
+ * shaper face data
+ */
+
+struct hb_coretext_aat_shaper_face_data_t {};
+
+hb_coretext_aat_shaper_face_data_t *
+_hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
+{
+  hb_blob_t *mort_blob = face->reference_table (HB_CORETEXT_TAG_MORT);
+  /* Umm, we just reference the table to check whether it exists.
+   * Maybe add better API for this? */
+  if (!hb_blob_get_length (mort_blob))
+  {
+    hb_blob_destroy (mort_blob);
+    mort_blob = face->reference_table (HB_CORETEXT_TAG_MORX);
+    if (!hb_blob_get_length (mort_blob))
+    {
+      hb_blob_destroy (mort_blob);
+      return NULL;
+    }
+  }
+  hb_blob_destroy (mort_blob);
+
+  return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL;
+}
+
+void
+_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_shaper_face_data_t *data HB_UNUSED)
+{
+}
+
+
+/*
+ * shaper font data
+ */
+
+struct hb_coretext_aat_shaper_font_data_t {};
+
+hb_coretext_aat_shaper_font_data_t *
+_hb_coretext_aat_shaper_font_data_create (hb_font_t *font)
+{
+  return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL;
+}
+
+void
+_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_shaper_font_data_t *data HB_UNUSED)
+{
+}
+
+
+/*
+ * shaper shape_plan data
+ */
+
+struct hb_coretext_aat_shaper_shape_plan_data_t {};
+
+hb_coretext_aat_shaper_shape_plan_data_t *
+_hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
+					     const hb_feature_t *user_features HB_UNUSED,
+					     unsigned int        num_user_features HB_UNUSED)
+{
+  return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+}
+
+void
+_hb_coretext_aat_shaper_shape_plan_data_destroy (hb_coretext_aat_shaper_shape_plan_data_t *data HB_UNUSED)
+{
+}
+
+
+/*
+ * shaper
+ */
+
+hb_bool_t
+_hb_coretext_aat_shape (hb_shape_plan_t    *shape_plan,
+			hb_font_t          *font,
+			hb_buffer_t        *buffer,
+			const hb_feature_t *features,
+			unsigned int        num_features)
+{
+  return _hb_coretext_shape (shape_plan, font, buffer, features, num_features);
+}
--- a/gfx/harfbuzz/src/hb-coretext.h
+++ b/gfx/harfbuzz/src/hb-coretext.h
@@ -24,21 +24,35 @@
  * Mozilla Author(s): Jonathan Kew
  */
 
 #ifndef HB_CORETEXT_H
 #define HB_CORETEXT_H
 
 #include "hb.h"
 
-#include <ApplicationServices/ApplicationServices.h>
+#include <TargetConditionals.h>
+#if TARGET_OS_IPHONE
+#  include <CoreText/CoreText.h>
+#  include <CoreGraphics/CoreGraphics.h>
+#else
+#  include <ApplicationServices/ApplicationServices.h>
+#endif
 
 HB_BEGIN_DECLS
 
 
+#define HB_CORETEXT_TAG_MORT HB_TAG('m','o','r','t')
+#define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x')
+
+
+hb_face_t *
+hb_coretext_face_create (CGFontRef cg_font);
+
+
 CGFontRef
 hb_coretext_face_get_cg_font (hb_face_t *face);
 
 CTFontRef
 hb_coretext_font_get_ct_font (hb_font_t *font);
 
 
 HB_END_DECLS
--- a/gfx/harfbuzz/src/hb-face.cc
+++ b/gfx/harfbuzz/src/hb-face.cc
@@ -293,17 +293,17 @@ hb_face_get_user_data (hb_face_t        
  *
  * 
  *
  * Since: 1.0
  **/
 void
 hb_face_make_immutable (hb_face_t *face)
 {
-  if (hb_object_is_inert (face))
+  if (unlikely (hb_object_is_inert (face)))
     return;
 
   face->immutable = true;
 }
 
 /**
  * hb_face_is_immutable:
  * @face: a face.
@@ -363,17 +363,17 @@ hb_face_reference_blob (hb_face_t *face)
  * 
  *
  * Since: 1.0
  **/
 void
 hb_face_set_index (hb_face_t    *face,
 		   unsigned int  index)
 {
-  if (hb_object_is_inert (face))
+  if (face->immutable)
     return;
 
   face->index = index;
 }
 
 /**
  * hb_face_get_index:
  * @face: a face.
@@ -398,17 +398,17 @@ hb_face_get_index (hb_face_t    *face)
  * 
  *
  * Since: 1.0
  **/
 void
 hb_face_set_upem (hb_face_t    *face,
 		  unsigned int  upem)
 {
-  if (hb_object_is_inert (face))
+  if (face->immutable)
     return;
 
   face->upem = upem;
 }
 
 /**
  * hb_face_get_upem:
  * @face: a face.
@@ -442,17 +442,17 @@ hb_face_t::load_upem (void) const
  * 
  *
  * Since: 1.0
  **/
 void
 hb_face_set_glyph_count (hb_face_t    *face,
 			 unsigned int  glyph_count)
 {
-  if (hb_object_is_inert (face))
+  if (face->immutable)
     return;
 
   face->num_glyphs = glyph_count;
 }
 
 /**
  * hb_face_get_glyph_count:
  * @face: a face.
--- a/gfx/harfbuzz/src/hb-fallback-shape.cc
+++ b/gfx/harfbuzz/src/hb-fallback-shape.cc
@@ -100,40 +100,42 @@ hb_bool_t
    * - Apply fallback kern.
    * - Handle Variation Selectors?
    * - Apply normalization?
    *
    * This will make the fallback shaper into a dumb "TrueType"
    * shaper which many people unfortunately still request.
    */
 
-  bool has_space;
   hb_codepoint_t space;
-  has_space = font->get_glyph (' ', 0, &space);
+  bool has_space = font->get_glyph (' ', 0, &space);
 
   buffer->clear_positions ();
 
+  hb_direction_t direction = buffer->props.direction;
+  hb_unicode_funcs_t *unicode = buffer->unicode;
   unsigned int count = buffer->len;
-
+  hb_glyph_info_t *info = buffer->info;
+  hb_glyph_position_t *pos = buffer->pos;
   for (unsigned int i = 0; i < count; i++)
   {
-    if (has_space && buffer->unicode->is_default_ignorable (buffer->info[i].codepoint)) {
-      buffer->info[i].codepoint = space;
-      buffer->pos[i].x_advance = 0;
-      buffer->pos[i].y_advance = 0;
+    if (has_space && unicode->is_default_ignorable (info[i].codepoint)) {
+      info[i].codepoint = space;
+      pos[i].x_advance = 0;
+      pos[i].y_advance = 0;
       continue;
     }
-    font->get_glyph (buffer->info[i].codepoint, 0, &buffer->info[i].codepoint);
-    font->get_glyph_advance_for_direction (buffer->info[i].codepoint,
-					   buffer->props.direction,
-					   &buffer->pos[i].x_advance,
-					   &buffer->pos[i].y_advance);
-    font->subtract_glyph_origin_for_direction (buffer->info[i].codepoint,
-					       buffer->props.direction,
-					       &buffer->pos[i].x_offset,
-					       &buffer->pos[i].y_offset);
+    font->get_glyph (info[i].codepoint, 0, &info[i].codepoint);
+    font->get_glyph_advance_for_direction (info[i].codepoint,
+					   direction,
+					   &pos[i].x_advance,
+					   &pos[i].y_advance);
+    font->subtract_glyph_origin_for_direction (info[i].codepoint,
+					       direction,
+					       &pos[i].x_offset,
+					       &pos[i].y_offset);
   }
 
-  if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
+  if (HB_DIRECTION_IS_BACKWARD (direction))
     hb_buffer_reverse (buffer);
 
   return true;
 }
--- a/gfx/harfbuzz/src/hb-font.cc
+++ b/gfx/harfbuzz/src/hb-font.cc
@@ -352,17 +352,17 @@ hb_font_funcs_get_user_data (hb_font_fun
  *
  * 
  *
  * Since: 1.0
  **/
 void
 hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
 {
-  if (hb_object_is_inert (ffuncs))
+  if (unlikely (hb_object_is_inert (ffuncs)))
     return;
 
   ffuncs->immutable = true;
 }
 
 /**
  * hb_font_funcs_is_immutable:
  * @ffuncs: font functions.
@@ -1029,17 +1029,17 @@ hb_font_get_user_data (hb_font_t        
  *
  * 
  *
  * Since: 1.0
  **/
 void
 hb_font_make_immutable (hb_font_t *font)
 {
-  if (hb_object_is_inert (font))
+  if (unlikely (hb_object_is_inert (font)))
     return;
 
   font->immutable = true;
 }
 
 /**
  * hb_font_is_immutable:
  * @font: a font.
--- a/gfx/harfbuzz/src/hb-glib.cc
+++ b/gfx/harfbuzz/src/hb-glib.cc
@@ -335,17 +335,17 @@ hb_glib_unicode_decompose (hb_unicode_fu
 
 static unsigned int
 hb_glib_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs HB_UNUSED,
 					 hb_codepoint_t      u,
 					 hb_codepoint_t     *decomposed,
 					 void               *user_data HB_UNUSED)
 {
 #if GLIB_CHECK_VERSION(2,29,12)
-  return g_unichar_fully_decompose (u, TRUE, decomposed, HB_UNICODE_MAX_DECOMPOSITION_LEN);
+  return g_unichar_fully_decompose (u, true, decomposed, HB_UNICODE_MAX_DECOMPOSITION_LEN);
 #endif
 
   /* If the user doesn't have GLib >= 2.29.12 we have to perform
    * a round trip to UTF-8 and the associated memory management dance. */
   gchar utf8[6];
   gchar *utf8_decomposed, *c;
   gsize utf8_len, utf8_decomposed_len, i;
 
deleted file mode 100644
--- a/gfx/harfbuzz/src/hb-gobject-enums.cc
+++ /dev/null
@@ -1,343 +0,0 @@
-
-/* Generated data (by glib-mkenums) */
-
-/*
- * Copyright © 2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.hh"
-
-/* g++ didn't like older gtype.h gcc-only code path. */
-#include <glib.h>
-#if !GLIB_CHECK_VERSION(2,29,16)
-#undef __GNUC__
-#undef __GNUC_MINOR__
-#define __GNUC__ 2
-#define __GNUC_MINOR__ 6
-#endif
-
-#include "hb-gobject.h"
-
-/* enumerations from "hb-blob.h" */
-inline static /* TODO(behdad) disable these for now until we fix them... */
-GType
-hb_memory_mode_t_hb_memory_mode_t_get_type (void)
-{
-  static volatile gsize g_define_type_id__volatile = 0;
-
-  if (g_once_init_enter (&g_define_type_id__volatile))
-    {
-      static const GEnumValue values[] = {
-        { HB_MEMORY_MODE_DUPLICATE, "HB_MEMORY_MODE_DUPLICATE", "duplicate" },
-        { HB_MEMORY_MODE_READONLY, "HB_MEMORY_MODE_READONLY", "readonly" },
-        { HB_MEMORY_MODE_WRITABLE, "HB_MEMORY_MODE_WRITABLE", "writable" },
-        { HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, "HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE", "readonly-may-make-writable" },
-        { 0, NULL, NULL }
-      };
-      GType g_define_type_id =
-        g_enum_register_static (g_intern_static_string ("hb_memory_mode_t"), values);
-      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
-    }
-
-  return g_define_type_id__volatile;
-}
-
-/* enumerations from "hb-common.h" */
-inline static /* TODO(behdad) disable these for now until we fix them... */
-GType
-hb_direction_t_hb_direction_t_get_type (void)
-{
-  static volatile gsize g_define_type_id__volatile = 0;
-
-  if (g_once_init_enter (&g_define_type_id__volatile))
-    {
-      static const GEnumValue values[] = {
-        { HB_DIRECTION_INVALID, "HB_DIRECTION_INVALID", "invalid" },
-        { HB_DIRECTION_LTR, "HB_DIRECTION_LTR", "ltr" },
-        { HB_DIRECTION_RTL, "HB_DIRECTION_RTL", "rtl" },
-        { HB_DIRECTION_TTB, "HB_DIRECTION_TTB", "ttb" },
-        { HB_DIRECTION_BTT, "HB_DIRECTION_BTT", "btt" },
-        { 0, NULL, NULL }
-      };
-      GType g_define_type_id =
-        g_enum_register_static (g_intern_static_string ("hb_direction_t"), values);
-      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
-    }
-
-  return g_define_type_id__volatile;
-}
-
-inline static /* TODO(behdad) disable these for now until we fix them... */
-GType
-hb_script_t_hb_script_t_get_type (void)
-{
-  static volatile gsize g_define_type_id__volatile = 0;
-
-  if (g_once_init_enter (&g_define_type_id__volatile))
-    {
-      static const GEnumValue values[] = {
-        { HB_SCRIPT_COMMON, "HB_SCRIPT_COMMON", "common" },
-        { HB_SCRIPT_ARABIC, "HB_SCRIPT_ARABIC", "arabic" },
-        { HB_SCRIPT_ARMENIAN, "HB_SCRIPT_ARMENIAN", "armenian" },
-        { HB_SCRIPT_BENGALI, "HB_SCRIPT_BENGALI", "bengali" },
-        { HB_SCRIPT_BOPOMOFO, "HB_SCRIPT_BOPOMOFO", "bopomofo" },
-        { HB_SCRIPT_CANADIAN_ABORIGINAL, "HB_SCRIPT_CANADIAN_ABORIGINAL", "canadian-aboriginal" },
-        { HB_SCRIPT_CHEROKEE, "HB_SCRIPT_CHEROKEE", "cherokee" },
-        { HB_SCRIPT_COPTIC, "HB_SCRIPT_COPTIC", "coptic" },
-        { HB_SCRIPT_CYRILLIC, "HB_SCRIPT_CYRILLIC", "cyrillic" },
-        { HB_SCRIPT_DEVANAGARI, "HB_SCRIPT_DEVANAGARI", "devanagari" },
-        { HB_SCRIPT_GEORGIAN, "HB_SCRIPT_GEORGIAN", "georgian" },
-        { HB_SCRIPT_GREEK, "HB_SCRIPT_GREEK", "greek" },
-        { HB_SCRIPT_GUJARATI, "HB_SCRIPT_GUJARATI", "gujarati" },
-        { HB_SCRIPT_GURMUKHI, "HB_SCRIPT_GURMUKHI", "gurmukhi" },
-        { HB_SCRIPT_HANGUL, "HB_SCRIPT_HANGUL", "hangul" },
-        { HB_SCRIPT_HAN, "HB_SCRIPT_HAN", "han" },
-        { HB_SCRIPT_HEBREW, "HB_SCRIPT_HEBREW", "hebrew" },
-        { HB_SCRIPT_HIRAGANA, "HB_SCRIPT_HIRAGANA", "hiragana" },
-        { HB_SCRIPT_INHERITED, "HB_SCRIPT_INHERITED", "inherited" },
-        { HB_SCRIPT_KANNADA, "HB_SCRIPT_KANNADA", "kannada" },
-        { HB_SCRIPT_KATAKANA, "HB_SCRIPT_KATAKANA", "katakana" },
-        { HB_SCRIPT_LAO, "HB_SCRIPT_LAO", "lao" },
-        { HB_SCRIPT_LATIN, "HB_SCRIPT_LATIN", "latin" },
-        { HB_SCRIPT_MALAYALAM, "HB_SCRIPT_MALAYALAM", "malayalam" },
-        { HB_SCRIPT_MONGOLIAN, "HB_SCRIPT_MONGOLIAN", "mongolian" },
-        { HB_SCRIPT_OGHAM, "HB_SCRIPT_OGHAM", "ogham" },
-        { HB_SCRIPT_ORIYA, "HB_SCRIPT_ORIYA", "oriya" },
-        { HB_SCRIPT_RUNIC, "HB_SCRIPT_RUNIC", "runic" },
-        { HB_SCRIPT_SYRIAC, "HB_SCRIPT_SYRIAC", "syriac" },
-        { HB_SCRIPT_TAMIL, "HB_SCRIPT_TAMIL", "tamil" },
-        { HB_SCRIPT_TELUGU, "HB_SCRIPT_TELUGU", "telugu" },
-        { HB_SCRIPT_THAI, "HB_SCRIPT_THAI", "thai" },
-        { HB_SCRIPT_YI, "HB_SCRIPT_YI", "yi" },
-        { HB_SCRIPT_TIBETAN, "HB_SCRIPT_TIBETAN", "tibetan" },
-        { HB_SCRIPT_ETHIOPIC, "HB_SCRIPT_ETHIOPIC", "ethiopic" },
-        { HB_SCRIPT_KHMER, "HB_SCRIPT_KHMER", "khmer" },
-        { HB_SCRIPT_MYANMAR, "HB_SCRIPT_MYANMAR", "myanmar" },
-        { HB_SCRIPT_SINHALA, "HB_SCRIPT_SINHALA", "sinhala" },
-        { HB_SCRIPT_THAANA, "HB_SCRIPT_THAANA", "thaana" },
-        { HB_SCRIPT_DESERET, "HB_SCRIPT_DESERET", "deseret" },
-        { HB_SCRIPT_GOTHIC, "HB_SCRIPT_GOTHIC", "gothic" },
-        { HB_SCRIPT_OLD_ITALIC, "HB_SCRIPT_OLD_ITALIC", "old-italic" },
-        { HB_SCRIPT_BUHID, "HB_SCRIPT_BUHID", "buhid" },
-        { HB_SCRIPT_HANUNOO, "HB_SCRIPT_HANUNOO", "hanunoo" },
-        { HB_SCRIPT_TAGALOG, "HB_SCRIPT_TAGALOG", "tagalog" },
-        { HB_SCRIPT_TAGBANWA, "HB_SCRIPT_TAGBANWA", "tagbanwa" },
-        { HB_SCRIPT_BRAILLE, "HB_SCRIPT_BRAILLE", "braille" },
-        { HB_SCRIPT_CYPRIOT, "HB_SCRIPT_CYPRIOT", "cypriot" },
-        { HB_SCRIPT_LIMBU, "HB_SCRIPT_LIMBU", "limbu" },
-        { HB_SCRIPT_LINEAR_B, "HB_SCRIPT_LINEAR_B", "linear-b" },
-        { HB_SCRIPT_OSMANYA, "HB_SCRIPT_OSMANYA", "osmanya" },
-        { HB_SCRIPT_SHAVIAN, "HB_SCRIPT_SHAVIAN", "shavian" },
-        { HB_SCRIPT_TAI_LE, "HB_SCRIPT_TAI_LE", "tai-le" },
-        { HB_SCRIPT_UGARITIC, "HB_SCRIPT_UGARITIC", "ugaritic" },
-        { HB_SCRIPT_BUGINESE, "HB_SCRIPT_BUGINESE", "buginese" },
-        { HB_SCRIPT_GLAGOLITIC, "HB_SCRIPT_GLAGOLITIC", "glagolitic" },
-        { HB_SCRIPT_KHAROSHTHI, "HB_SCRIPT_KHAROSHTHI", "kharoshthi" },
-        { HB_SCRIPT_NEW_TAI_LUE, "HB_SCRIPT_NEW_TAI_LUE", "new-tai-lue" },
-        { HB_SCRIPT_OLD_PERSIAN, "HB_SCRIPT_OLD_PERSIAN", "old-persian" },
-        { HB_SCRIPT_SYLOTI_NAGRI, "HB_SCRIPT_SYLOTI_NAGRI", "syloti-nagri" },
-        { HB_SCRIPT_TIFINAGH, "HB_SCRIPT_TIFINAGH", "tifinagh" },
-        { HB_SCRIPT_BALINESE, "HB_SCRIPT_BALINESE", "balinese" },
-        { HB_SCRIPT_CUNEIFORM, "HB_SCRIPT_CUNEIFORM", "cuneiform" },
-        { HB_SCRIPT_NKO, "HB_SCRIPT_NKO", "nko" },
-        { HB_SCRIPT_PHAGS_PA, "HB_SCRIPT_PHAGS_PA", "phags-pa" },
-        { HB_SCRIPT_PHOENICIAN, "HB_SCRIPT_PHOENICIAN", "phoenician" },
-        { HB_SCRIPT_UNKNOWN, "HB_SCRIPT_UNKNOWN", "unknown" },
-        { HB_SCRIPT_CARIAN, "HB_SCRIPT_CARIAN", "carian" },
-        { HB_SCRIPT_CHAM, "HB_SCRIPT_CHAM", "cham" },
-        { HB_SCRIPT_KAYAH_LI, "HB_SCRIPT_KAYAH_LI", "kayah-li" },
-        { HB_SCRIPT_LEPCHA, "HB_SCRIPT_LEPCHA", "lepcha" },
-        { HB_SCRIPT_LYCIAN, "HB_SCRIPT_LYCIAN", "lycian" },
-        { HB_SCRIPT_LYDIAN, "HB_SCRIPT_LYDIAN", "lydian" },
-        { HB_SCRIPT_OL_CHIKI, "HB_SCRIPT_OL_CHIKI", "ol-chiki" },
-        { HB_SCRIPT_REJANG, "HB_SCRIPT_REJANG", "rejang" },
-        { HB_SCRIPT_SAURASHTRA, "HB_SCRIPT_SAURASHTRA", "saurashtra" },
-        { HB_SCRIPT_SUNDANESE, "HB_SCRIPT_SUNDANESE", "sundanese" },
-        { HB_SCRIPT_VAI, "HB_SCRIPT_VAI", "vai" },
-        { HB_SCRIPT_AVESTAN, "HB_SCRIPT_AVESTAN", "avestan" },
-        { HB_SCRIPT_BAMUM, "HB_SCRIPT_BAMUM", "bamum" },
-        { HB_SCRIPT_EGYPTIAN_HIEROGLYPHS, "HB_SCRIPT_EGYPTIAN_HIEROGLYPHS", "egyptian-hieroglyphs" },
-        { HB_SCRIPT_IMPERIAL_ARAMAIC, "HB_SCRIPT_IMPERIAL_ARAMAIC", "imperial-aramaic" },
-        { HB_SCRIPT_INSCRIPTIONAL_PAHLAVI, "HB_SCRIPT_INSCRIPTIONAL_PAHLAVI", "inscriptional-pahlavi" },
-        { HB_SCRIPT_INSCRIPTIONAL_PARTHIAN, "HB_SCRIPT_INSCRIPTIONAL_PARTHIAN", "inscriptional-parthian" },
-        { HB_SCRIPT_JAVANESE, "HB_SCRIPT_JAVANESE", "javanese" },
-        { HB_SCRIPT_KAITHI, "HB_SCRIPT_KAITHI", "kaithi" },
-        { HB_SCRIPT_LISU, "HB_SCRIPT_LISU", "lisu" },
-        { HB_SCRIPT_MEETEI_MAYEK, "HB_SCRIPT_MEETEI_MAYEK", "meetei-mayek" },
-        { HB_SCRIPT_OLD_SOUTH_ARABIAN, "HB_SCRIPT_OLD_SOUTH_ARABIAN", "old-south-arabian" },
-        { HB_SCRIPT_OLD_TURKIC, "HB_SCRIPT_OLD_TURKIC", "old-turkic" },
-        { HB_SCRIPT_SAMARITAN, "HB_SCRIPT_SAMARITAN", "samaritan" },
-        { HB_SCRIPT_TAI_THAM, "HB_SCRIPT_TAI_THAM", "tai-tham" },
-        { HB_SCRIPT_TAI_VIET, "HB_SCRIPT_TAI_VIET", "tai-viet" },
-        { HB_SCRIPT_BATAK, "HB_SCRIPT_BATAK", "batak" },
-        { HB_SCRIPT_BRAHMI, "HB_SCRIPT_BRAHMI", "brahmi" },
-        { HB_SCRIPT_MANDAIC, "HB_SCRIPT_MANDAIC", "mandaic" },
-        { HB_SCRIPT_CHAKMA, "HB_SCRIPT_CHAKMA", "chakma" },
-        { HB_SCRIPT_MEROITIC_CURSIVE, "HB_SCRIPT_MEROITIC_CURSIVE", "meroitic-cursive" },
-        { HB_SCRIPT_MEROITIC_HIEROGLYPHS, "HB_SCRIPT_MEROITIC_HIEROGLYPHS", "meroitic-hieroglyphs" },
-        { HB_SCRIPT_MIAO, "HB_SCRIPT_MIAO", "miao" },
-        { HB_SCRIPT_SHARADA, "HB_SCRIPT_SHARADA", "sharada" },
-        { HB_SCRIPT_SORA_SOMPENG, "HB_SCRIPT_SORA_SOMPENG", "sora-sompeng" },
-        { HB_SCRIPT_TAKRI, "HB_SCRIPT_TAKRI", "takri" },
-        { HB_SCRIPT_INVALID, "HB_SCRIPT_INVALID", "invalid" },
-        { 0, NULL, NULL }
-      };
-      GType g_define_type_id =
-        g_enum_register_static (g_intern_static_string ("hb_script_t"), values);
-      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
-    }
-
-  return g_define_type_id__volatile;
-}
-
-/* enumerations from "hb-unicode.h" */
-inline static /* TODO(behdad) disable these for now until we fix them... */
-GType
-hb_unicode_general_category_t_hb_unicode_general_category_t_get_type (void)
-{
-  static volatile gsize g_define_type_id__volatile = 0;
-
-  if (g_once_init_enter (&g_define_type_id__volatile))
-    {
-      static const GEnumValue values[] = {
-        { HB_UNICODE_GENERAL_CATEGORY_CONTROL, "HB_UNICODE_GENERAL_CATEGORY_CONTROL", "control" },
-        { HB_UNICODE_GENERAL_CATEGORY_FORMAT, "HB_UNICODE_GENERAL_CATEGORY_FORMAT", "format" },
-        { HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED, "HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED", "unassigned" },
-        { HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE, "HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE", "private-use" },
-        { HB_UNICODE_GENERAL_CATEGORY_SURROGATE, "HB_UNICODE_GENERAL_CATEGORY_SURROGATE", "surrogate" },
-        { HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER, "HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER", "lowercase-letter" },
-        { HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER, "HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER", "modifier-letter" },
-        { HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER, "HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER", "other-letter" },
-        { HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER, "HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER", "titlecase-letter" },
-        { HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER, "HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER", "uppercase-letter" },
-        { HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK, "HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK", "spacing-mark" },
-        { HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK, "HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK", "enclosing-mark" },
-        { HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK, "HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK", "non-spacing-mark" },
-        { HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER, "HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER", "decimal-number" },
-        { HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER, "HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER", "letter-number" },
-        { HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER, "HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER", "other-number" },
-        { HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION", "connect-punctuation" },
-        { HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION", "dash-punctuation" },
-        { HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION", "close-punctuation" },
-        { HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION", "final-punctuation" },
-        { HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION", "initial-punctuation" },
-        { HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION", "other-punctuation" },
-        { HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION", "open-punctuation" },
-        { HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL, "HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL", "currency-symbol" },
-        { HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL, "HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL", "modifier-symbol" },
-        { HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL, "HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL", "math-symbol" },
-        { HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL, "HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL", "other-symbol" },
-        { HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR, "HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR", "line-separator" },
-        { HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR, "HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR", "paragraph-separator" },
-        { HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR, "HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR", "space-separator" },
-        { 0, NULL, NULL }
-      };
-      GType g_define_type_id =
-        g_enum_register_static (g_intern_static_string ("hb_unicode_general_category_t"), values);
-      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
-    }
-
-  return g_define_type_id__volatile;
-}
-
-inline static /* TODO(behdad) disable these for now until we fix them... */
-GType
-hb_unicode_combining_class_t_hb_unicode_combining_class_t_get_type (void)
-{
-  static volatile gsize g_define_type_id__volatile = 0;
-
-  if (g_once_init_enter (&g_define_type_id__volatile))
-    {
-      static const GEnumValue values[] = {
-        { HB_UNICODE_COMBINING_CLASS_NOT_REORDERED, "HB_UNICODE_COMBINING_CLASS_NOT_REORDERED", "not-reordered" },
-        { HB_UNICODE_COMBINING_CLASS_OVERLAY, "HB_UNICODE_COMBINING_CLASS_OVERLAY", "overlay" },
-        { HB_UNICODE_COMBINING_CLASS_NUKTA, "HB_UNICODE_COMBINING_CLASS_NUKTA", "nukta" },
-        { HB_UNICODE_COMBINING_CLASS_KANA_VOICING, "HB_UNICODE_COMBINING_CLASS_KANA_VOICING", "kana-voicing" },
-        { HB_UNICODE_COMBINING_CLASS_VIRAMA, "HB_UNICODE_COMBINING_CLASS_VIRAMA", "virama" },
-        { HB_UNICODE_COMBINING_CLASS_CCC10, "HB_UNICODE_COMBINING_CLASS_CCC10", "ccc10" },
-        { HB_UNICODE_COMBINING_CLASS_CCC11, "HB_UNICODE_COMBINING_CLASS_CCC11", "ccc11" },
-        { HB_UNICODE_COMBINING_CLASS_CCC12, "HB_UNICODE_COMBINING_CLASS_CCC12", "ccc12" },
-        { HB_UNICODE_COMBINING_CLASS_CCC13, "HB_UNICODE_COMBINING_CLASS_CCC13", "ccc13" },
-        { HB_UNICODE_COMBINING_CLASS_CCC14, "HB_UNICODE_COMBINING_CLASS_CCC14", "ccc14" },
-        { HB_UNICODE_COMBINING_CLASS_CCC15, "HB_UNICODE_COMBINING_CLASS_CCC15", "ccc15" },
-        { HB_UNICODE_COMBINING_CLASS_CCC16, "HB_UNICODE_COMBINING_CLASS_CCC16", "ccc16" },
-        { HB_UNICODE_COMBINING_CLASS_CCC17, "HB_UNICODE_COMBINING_CLASS_CCC17", "ccc17" },
-        { HB_UNICODE_COMBINING_CLASS_CCC18, "HB_UNICODE_COMBINING_CLASS_CCC18", "ccc18" },
-        { HB_UNICODE_COMBINING_CLASS_CCC19, "HB_UNICODE_COMBINING_CLASS_CCC19", "ccc19" },
-        { HB_UNICODE_COMBINING_CLASS_CCC20, "HB_UNICODE_COMBINING_CLASS_CCC20", "ccc20" },
-        { HB_UNICODE_COMBINING_CLASS_CCC21, "HB_UNICODE_COMBINING_CLASS_CCC21", "ccc21" },
-        { HB_UNICODE_COMBINING_CLASS_CCC22, "HB_UNICODE_COMBINING_CLASS_CCC22", "ccc22" },
-        { HB_UNICODE_COMBINING_CLASS_CCC23, "HB_UNICODE_COMBINING_CLASS_CCC23", "ccc23" },
-        { HB_UNICODE_COMBINING_CLASS_CCC24, "HB_UNICODE_COMBINING_CLASS_CCC24", "ccc24" },
-        { HB_UNICODE_COMBINING_CLASS_CCC25, "HB_UNICODE_COMBINING_CLASS_CCC25", "ccc25" },
-        { HB_UNICODE_COMBINING_CLASS_CCC26, "HB_UNICODE_COMBINING_CLASS_CCC26", "ccc26" },
-        { HB_UNICODE_COMBINING_CLASS_CCC27, "HB_UNICODE_COMBINING_CLASS_CCC27", "ccc27" },
-        { HB_UNICODE_COMBINING_CLASS_CCC28, "HB_UNICODE_COMBINING_CLASS_CCC28", "ccc28" },
-        { HB_UNICODE_COMBINING_CLASS_CCC29, "HB_UNICODE_COMBINING_CLASS_CCC29", "ccc29" },
-        { HB_UNICODE_COMBINING_CLASS_CCC30, "HB_UNICODE_COMBINING_CLASS_CCC30", "ccc30" },
-        { HB_UNICODE_COMBINING_CLASS_CCC31, "HB_UNICODE_COMBINING_CLASS_CCC31", "ccc31" },
-        { HB_UNICODE_COMBINING_CLASS_CCC32, "HB_UNICODE_COMBINING_CLASS_CCC32", "ccc32" },
-        { HB_UNICODE_COMBINING_CLASS_CCC33, "HB_UNICODE_COMBINING_CLASS_CCC33", "ccc33" },
-        { HB_UNICODE_COMBINING_CLASS_CCC34, "HB_UNICODE_COMBINING_CLASS_CCC34", "ccc34" },
-        { HB_UNICODE_COMBINING_CLASS_CCC35, "HB_UNICODE_COMBINING_CLASS_CCC35", "ccc35" },
-        { HB_UNICODE_COMBINING_CLASS_CCC36, "HB_UNICODE_COMBINING_CLASS_CCC36", "ccc36" },
-        { HB_UNICODE_COMBINING_CLASS_CCC84, "HB_UNICODE_COMBINING_CLASS_CCC84", "ccc84" },
-        { HB_UNICODE_COMBINING_CLASS_CCC91, "HB_UNICODE_COMBINING_CLASS_CCC91", "ccc91" },
-        { HB_UNICODE_COMBINING_CLASS_CCC103, "HB_UNICODE_COMBINING_CLASS_CCC103", "ccc103" },
-        { HB_UNICODE_COMBINING_CLASS_CCC107, "HB_UNICODE_COMBINING_CLASS_CCC107", "ccc107" },
-        { HB_UNICODE_COMBINING_CLASS_CCC118, "HB_UNICODE_COMBINING_CLASS_CCC118", "ccc118" },
-        { HB_UNICODE_COMBINING_CLASS_CCC122, "HB_UNICODE_COMBINING_CLASS_CCC122", "ccc122" },
-        { HB_UNICODE_COMBINING_CLASS_CCC129, "HB_UNICODE_COMBINING_CLASS_CCC129", "ccc129" },
-        { HB_UNICODE_COMBINING_CLASS_CCC130, "HB_UNICODE_COMBINING_CLASS_CCC130", "ccc130" },
-        { HB_UNICODE_COMBINING_CLASS_CCC133, "HB_UNICODE_COMBINING_CLASS_CCC133", "ccc133" },
-        { HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT, "HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT", "attached-below-left" },
-        { HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW, "HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW", "attached-below" },
-        { HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE, "HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE", "attached-above" },
-        { HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT, "HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT", "attached-above-right" },
-        { HB_UNICODE_COMBINING_CLASS_BELOW_LEFT, "HB_UNICODE_COMBINING_CLASS_BELOW_LEFT", "below-left" },
-        { HB_UNICODE_COMBINING_CLASS_BELOW, "HB_UNICODE_COMBINING_CLASS_BELOW", "below" },
-        { HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT, "HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT", "below-right" },
-        { HB_UNICODE_COMBINING_CLASS_LEFT, "HB_UNICODE_COMBINING_CLASS_LEFT", "left" },
-        { HB_UNICODE_COMBINING_CLASS_RIGHT, "HB_UNICODE_COMBINING_CLASS_RIGHT", "right" },
-        { HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT, "HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT", "above-left" },
-        { HB_UNICODE_COMBINING_CLASS_ABOVE, "HB_UNICODE_COMBINING_CLASS_ABOVE", "above" },
-        { HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT, "HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT", "above-right" },
-        { HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW, "HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW", "double-below" },
-        { HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE, "HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE", "double-above" },
-        { HB_UNICODE_COMBINING_CLASS_IOTA_SUBSCRIPT, "HB_UNICODE_COMBINING_CLASS_IOTA_SUBSCRIPT", "iota-subscript" },
-        { HB_UNICODE_COMBINING_CLASS_INVALID, "HB_UNICODE_COMBINING_CLASS_INVALID", "invalid" },
-        { 0, NULL, NULL }
-      };
-      GType g_define_type_id =
-        g_enum_register_static (g_intern_static_string ("hb_unicode_combining_class_t"), values);
-      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
-    }
-
-  return g_define_type_id__volatile;
-}
-
-
-/* Generated data ends here */
-
--- a/gfx/harfbuzz/src/hb-graphite2.cc
+++ b/gfx/harfbuzz/src/hb-graphite2.cc
@@ -204,16 +204,17 @@ void
  * shaper
  */
 
 struct hb_graphite2_cluster_t {
   unsigned int base_char;
   unsigned int num_chars;
   unsigned int base_glyph;
   unsigned int num_glyphs;
+  unsigned int cluster;
 };
 
 hb_bool_t
 _hb_graphite2_shape (hb_shape_plan_t    *shape_plan,
 		     hb_font_t          *font,
 		     hb_buffer_t        *buffer,
 		     const hb_feature_t *features,
 		     unsigned int        num_features)
@@ -294,16 +295,17 @@ hb_bool_t
   ALLOCATE_ARRAY (hb_graphite2_cluster_t, clusters, buffer->len);
   ALLOCATE_ARRAY (hb_codepoint_t, gids, glyph_count);
 
 #undef ALLOCATE_ARRAY
 
   memset (clusters, 0, sizeof (clusters[0]) * buffer->len);
 
   hb_codepoint_t *pg = gids;
+  clusters[0].cluster = buffer->info[0].cluster;
   for (is = gr_seg_first_slot (seg), ic = 0; is; is = gr_slot_next_in_segment (is), ic++)
   {
     unsigned int before = gr_slot_before (is);
     unsigned int after = gr_slot_after (is);
     *pg = gr_slot_gid (is);
     pg++;
     while (clusters[ci].base_char > before && ci)
     {
@@ -311,16 +313,17 @@ hb_bool_t
       clusters[ci-1].num_glyphs += clusters[ci].num_glyphs;
       ci--;
     }
 
     if (gr_slot_can_insert_before (is) && clusters[ci].num_chars && before >= clusters[ci].base_char + clusters[ci].num_chars)
     {
       hb_graphite2_cluster_t *c = clusters + ci + 1;
       c->base_char = clusters[ci].base_char + clusters[ci].num_chars;
+      c->cluster = buffer->info[c->base_char].cluster;
       c->num_chars = before - c->base_char;
       c->base_glyph = ic;
       c->num_glyphs = 0;
       ci++;
     }
     clusters[ci].num_glyphs++;
 
     if (clusters[ci].base_char + clusters[ci].num_chars < after + 1)
@@ -330,17 +333,17 @@ hb_bool_t
 
   //buffer->clear_output ();
   for (unsigned int i = 0; i < ci; ++i)
   {
     for (unsigned int j = 0; j < clusters[i].num_glyphs; ++j)
     {
       hb_glyph_info_t *info = &buffer->info[clusters[i].base_glyph + j];
       info->codepoint = gids[clusters[i].base_glyph + j];
-      info->cluster = gr_cinfo_base(gr_seg_cinfo(seg, clusters[i].base_char));
+      info->cluster = clusters[i].cluster;
     }
   }
   buffer->len = glyph_count;
   //buffer->swap_buffers ();
 
   if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
     curradvx = gr_seg_advance_X(seg);
 
deleted file mode 100644
--- a/gfx/harfbuzz/src/hb-icu-le.cc
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright © 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
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#define HB_SHAPER icu_le
-#define hb_icu_le_shaper_font_data_t PortableFontInstance
-#include "hb-shaper-impl-private.hh"
-
-#include "hb-icu-le/PortableFontInstance.h"
-
-#include "layout/loengine.h"
-#include "unicode/unistr.h"
-
-#include "hb-icu.h"
-
-
-/*
- * shaper face data
- */
-
-struct hb_icu_le_shaper_face_data_t {};
-
-hb_icu_le_shaper_face_data_t *
-_hb_icu_le_shaper_face_data_create (hb_face_t *face HB_UNUSED)
-{
-  return (hb_icu_le_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_icu_le_shaper_face_data_destroy (hb_icu_le_shaper_face_data_t *data HB_UNUSED)
-{
-}
-
-
-/*
- * shaper font data
- */
-
-hb_icu_le_shaper_font_data_t *
-_hb_icu_le_shaper_font_data_create (hb_font_t *font)
-{
-  LEErrorCode status = LE_NO_ERROR;
-  hb_icu_le_shaper_font_data_t *data = new PortableFontInstance (font->face,
-								 font->x_scale,
-								 font->y_scale,
-								 status);
-  if (status != LE_NO_ERROR) {
-    delete (data);
-    return NULL;
-  }
-
-  return data;
-}
-
-void
-_hb_icu_le_shaper_font_data_destroy (hb_icu_le_shaper_font_data_t *data)
-{
-  delete (data);
-}
-
-
-/*
- * shaper shape_plan data
- */
-
-struct hb_icu_le_shaper_shape_plan_data_t {};
-
-hb_icu_le_shaper_shape_plan_data_t *
-_hb_icu_le_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-					  const hb_feature_t *user_features,
-					  unsigned int        num_user_features)
-{
-  return (hb_icu_le_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_icu_le_shaper_shape_plan_data_destroy (hb_icu_le_shaper_shape_plan_data_t *data)
-{
-}
-
-
-/*
- * shaper
- */
-
-hb_bool_t
-_hb_icu_le_shape (hb_shape_plan_t    *shape_plan,
-		  hb_font_t          *font,
-		  hb_buffer_t        *buffer,
-		  const hb_feature_t *features,
-		  unsigned int        num_features)
-{
-  LEFontInstance *font_instance = HB_SHAPER_DATA_GET (font);
-  le_int32 script_code = hb_icu_script_from_script (shape_plan->props.script);
-  le_int32 language_code = -1 /* TODO */;
-  le_int32 typography_flags = 3; /* Needed for ligatures and kerning */
-  LEErrorCode status = LE_NO_ERROR;
-  le_engine *le = le_create ((const le_font *) font_instance,
-			     script_code,
-			     language_code,
-			     typography_flags,
-			     &status);
-  if (status != LE_NO_ERROR)
-  { le_close (le); return false; }
-
-retry:
-
-  unsigned int scratch_size;
-  char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
-
-#define ALLOCATE_ARRAY(Type, name, len) \
-  Type *name = (Type *) scratch; \
-  scratch += (len) * sizeof ((name)[0]); \
-  scratch_size -= (len) * sizeof ((name)[0]);
-
-  ALLOCATE_ARRAY (LEUnicode, chars, buffer->len);
-  ALLOCATE_ARRAY (unsigned int, clusters, buffer->len);
-
-  /* XXX Use UTF-16 decoder! */
-  for (unsigned int i = 0; i < buffer->len; i++) {
-    chars[i] = buffer->info[i].codepoint;
-    clusters[i] = buffer->info[i].cluster;
-  }
-
-  unsigned int glyph_count = le_layoutChars (le,
-					     chars,
-					     0,
-					     buffer->len,
-					     buffer->len,
-					     HB_DIRECTION_IS_BACKWARD (buffer->props.direction),
-					     0., 0.,
-					     &status);
-  if (status != LE_NO_ERROR)
-  { le_close (le); return false; }
-
-  unsigned int num_glyphs = scratch_size / (sizeof (LEGlyphID) +
-					    sizeof (le_int32) +
-					    sizeof (float) * 2);
-
-  if (unlikely (glyph_count >= num_glyphs || glyph_count > buffer->allocated)) {
-    buffer->ensure (buffer->allocated * 2);
-    if (buffer->in_error)
-    { le_close (le); return false; }
-    goto retry;
-  }
-
-  ALLOCATE_ARRAY (LEGlyphID, glyphs, glyph_count);
-  ALLOCATE_ARRAY (le_int32, indices, glyph_count);
-  ALLOCATE_ARRAY (float, positions, glyph_count * 2 + 2);
-
-  le_getGlyphs (le, glyphs, &status);
-  le_getCharIndices (le, indices, &status);
-  le_getGlyphPositions (le, positions, &status);
-
-#undef ALLOCATE_ARRAY
-
-  /* Ok, we've got everything we need, now compose output buffer,
-   * very, *very*, carefully! */
-
-  unsigned int j = 0;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < glyph_count; i++)
-  {
-    if (glyphs[i] >= 0xFFFE)
-	continue;
-
-    info[j].codepoint = glyphs[i];
-    info[j].cluster = clusters[indices[i]];
-
-    /* icu-le doesn't seem to have separate advance values. */
-    info[j].mask = positions[2 * i + 2] - positions[2 * i];
-    info[j].var1.u32 = 0;
-    info[j].var2.u32 = -positions[2 * i + 1];
-
-    j++;
-  }
-  buffer->len = j;
-
-  buffer->clear_positions ();
-
-  for (unsigned int i = 0; i < buffer->len; i++) {
-    hb_glyph_info_t *info = &buffer->info[i];
-    hb_glyph_position_t *pos = &buffer->pos[i];
-
-    /* TODO vertical */
-    pos->x_advance = info->mask;
-    pos->x_offset = info->var1.u32;
-    pos->y_offset = info->var2.u32;
-  }
-
-  le_close (le);
-  return true;
-}
--- a/gfx/harfbuzz/src/hb-icu.cc
+++ b/gfx/harfbuzz/src/hb-icu.cc
@@ -318,17 +318,17 @@ hb_icu_unicode_decompose_compatibility (
   UChar utf16[2], normalized[2 * HB_UNICODE_MAX_DECOMPOSITION_LEN + 1];
   unsigned int len;
   int32_t utf32_len;
   hb_bool_t err;
   UErrorCode icu_err;
 
   /* Copy @u into a UTF-16 array to be passed to ICU. */
   len = 0;
-  err = FALSE;
+  err = false;
   U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), u, err);
   if (err)
     return 0;
 
   /* Normalise the codepoint using NFKD mode. */
   icu_err = U_ZERO_ERROR;
   len = unorm_normalize (utf16, len, UNORM_NFKD, 0, normalized, ARRAY_LENGTH (normalized), &icu_err);
   if (icu_err)
--- a/gfx/harfbuzz/src/hb-mutex-private.hh
+++ b/gfx/harfbuzz/src/hb-mutex-private.hh
@@ -39,17 +39,16 @@
 
 /* We need external help for these */
 
 #if 0
 
 
 #elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
 
-#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 typedef CRITICAL_SECTION hb_mutex_impl_t;
 #define HB_MUTEX_IMPL_INIT	{ NULL, 0, 0, NULL, NULL, 0 }
 #define hb_mutex_impl_init(M)	InitializeCriticalSection (M)
 #define hb_mutex_impl_lock(M)	EnterCriticalSection (M)
 #define hb_mutex_impl_unlock(M)	LeaveCriticalSection (M)
 #define hb_mutex_impl_finish(M)	DeleteCriticalSection (M)
 
deleted file mode 100644
--- a/gfx/harfbuzz/src/hb-old.cc
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * Copyright © 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
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#define HB_SHAPER old
-#define hb_old_shaper_face_data_t HB_FaceRec_
-#define hb_old_shaper_font_data_t HB_Font_
-#include "hb-shaper-impl-private.hh"
-
-#include <harfbuzz.h>
-
-
-#ifndef HB_DEBUG_OLD
-#define HB_DEBUG_OLD (HB_DEBUG+0)
-#endif
-
-
-static HB_Script
-hb_old_script_from_script (hb_script_t script)
-{
-  switch ((hb_tag_t) script)
-  {
-    default:
-    case HB_SCRIPT_COMMON:		return HB_Script_Common;
-    case HB_SCRIPT_GREEK:		return HB_Script_Greek;
-    case HB_SCRIPT_CYRILLIC:		return HB_Script_Cyrillic;
-    case HB_SCRIPT_ARMENIAN:		return HB_Script_Armenian;
-    case HB_SCRIPT_HEBREW:		return HB_Script_Hebrew;
-    case HB_SCRIPT_ARABIC:		return HB_Script_Arabic;
-    case HB_SCRIPT_SYRIAC:		return HB_Script_Syriac;
-    case HB_SCRIPT_THAANA:		return HB_Script_Thaana;
-    case HB_SCRIPT_DEVANAGARI:		return HB_Script_Devanagari;
-    case HB_SCRIPT_BENGALI:		return HB_Script_Bengali;
-    case HB_SCRIPT_GURMUKHI:		return HB_Script_Gurmukhi;
-    case HB_SCRIPT_GUJARATI:		return HB_Script_Gujarati;
-    case HB_SCRIPT_ORIYA:		return HB_Script_Oriya;
-    case HB_SCRIPT_TAMIL:		return HB_Script_Tamil;
-    case HB_SCRIPT_TELUGU:		return HB_Script_Telugu;
-    case HB_SCRIPT_KANNADA:		return HB_Script_Kannada;
-    case HB_SCRIPT_MALAYALAM:		return HB_Script_Malayalam;
-    case HB_SCRIPT_SINHALA:		return HB_Script_Sinhala;
-    case HB_SCRIPT_THAI:		return HB_Script_Thai;
-    case HB_SCRIPT_LAO:			return HB_Script_Lao;
-    case HB_SCRIPT_TIBETAN:		return HB_Script_Tibetan;
-    case HB_SCRIPT_MYANMAR:		return HB_Script_Myanmar;
-    case HB_SCRIPT_GEORGIAN:		return HB_Script_Georgian;
-    case HB_SCRIPT_HANGUL:		return HB_Script_Hangul;
-    case HB_SCRIPT_OGHAM:		return HB_Script_Ogham;
-    case HB_SCRIPT_RUNIC:		return HB_Script_Runic;
-    case HB_SCRIPT_KHMER:		return HB_Script_Khmer;
-    case HB_SCRIPT_NKO:			return HB_Script_Nko;
-    case HB_SCRIPT_INHERITED:		return HB_Script_Inherited;
-  }
-}
-
-
-static HB_Bool
-hb_old_convertStringToGlyphIndices (HB_Font old_font,
-				    const HB_UChar16 *string,
-				    hb_uint32 length,
-				    HB_Glyph *glyphs,
-				    hb_uint32 *numGlyphs,
-				    HB_Bool rightToLeft)
-{
-  hb_font_t *font = (hb_font_t *) old_font->userData;
-
-  for (unsigned int i = 0; i < length; i++)
-  {
-    hb_codepoint_t u;
-
-    /* XXX Handle UTF-16.  Ugh */
-    u = string[i];
-
-    if (rightToLeft)
-      u = hb_unicode_funcs_get_default ()->mirroring (u);
-
-    font->get_glyph (u, 0, &u); /* TODO Variation selectors */
-
-    glyphs[i] = u;
-  }
-  *numGlyphs = length; /* XXX */
-
-  return true;
-}
-
-static void
-hb_old_getGlyphAdvances (HB_Font old_font,
-			 const HB_Glyph *glyphs,
-			 hb_uint32 numGlyphs,
-			 HB_Fixed *advances,
-			 int flags /*HB_ShaperFlag*/ HB_UNUSED)
-{
-  hb_font_t *font = (hb_font_t *) old_font->userData;
-
-  for (unsigned int i = 0; i < numGlyphs; i++)
-    advances[i] = font->get_glyph_h_advance (glyphs[i]);
-}
-
-static HB_Bool
-hb_old_canRender (HB_Font old_font,
-		  const HB_UChar16 *string,
-		  hb_uint32 length)
-{
-  return true; /* TODO */
-}
-
-static HB_Error
-hb_old_getPointInOutline (HB_Font old_font,
-			  HB_Glyph glyph,
-			  int flags /*HB_ShaperFlag*/,
-			  hb_uint32 point,
-			  HB_Fixed *xpos,
-			  HB_Fixed *ypos,
-			  hb_uint32 *nPoints)
-{
-  return HB_Err_Ok; /* TODO */
-}
-
-static void
-hb_old_getGlyphMetrics (HB_Font old_font,
-			HB_Glyph glyph,
-			HB_GlyphMetrics *metrics)
-{
-  hb_font_t *font = (hb_font_t *) old_font->userData;
-
-  hb_glyph_extents_t extents;
-
-  font->get_glyph_extents (glyph, &extents);
-
-  metrics->x       = extents.x_bearing;
-  metrics->y       = extents.y_bearing;
-  metrics->width   = extents.width;
-  metrics->height  = extents.height;
-  metrics->xOffset = font->get_glyph_h_advance (glyph);
-  metrics->yOffset = 0;
-}
-
-static HB_Fixed
-hb_old_getFontMetric (HB_Font old_font,
-		      HB_FontMetric metric)
-{
-  hb_font_t *font = (hb_font_t *) old_font->userData;
-
-  switch (metric)
-  {
-    case HB_FontAscent:
-       return font->y_scale; /* XXX We don't have ascent data yet. */
-
-    default:
-      return 0;
-  }
-}
-
-static const HB_FontClass hb_old_font_class = {
-  hb_old_convertStringToGlyphIndices,
-  hb_old_getGlyphAdvances,
-  hb_old_canRender,
-  hb_old_getPointInOutline,
-  hb_old_getGlyphMetrics,
-  hb_old_getFontMetric
-};
-
-
-
-static HB_Error
-table_func (void *font, HB_Tag tag, HB_Byte *buffer, HB_UInt *length)
-{
-  hb_face_t *face = (hb_face_t *) font;
-  hb_blob_t *blob = face->reference_table ((hb_tag_t) tag);
-  unsigned int capacity = *length;
-  *length = hb_blob_get_length (blob);
-  memcpy (buffer, hb_blob_get_data (blob, NULL), MIN (capacity, *length));
-  hb_blob_destroy (blob);
- return HB_Err_Ok;
-}
-
-
-/*
- * shaper face data
- */
-
-hb_old_shaper_face_data_t *
-_hb_old_shaper_face_data_create (hb_face_t *face)
-{
-  return HB_NewFace (face, table_func);
-}
-
-void
-_hb_old_shaper_face_data_destroy (hb_old_shaper_face_data_t *data)
-{
-  HB_FreeFace (data);
-}
-
-
-/*
- * shaper font data
- */
-
-hb_old_shaper_font_data_t *
-_hb_old_shaper_font_data_create (hb_font_t *font)
-{
-  HB_FontRec *data = (HB_FontRec *) calloc (1, sizeof (HB_FontRec));
-  if (unlikely (!data)) {
-    DEBUG_MSG (OLD, font, "malloc()ing HB_Font failed");
-    return NULL;
-  }
-
-  data->klass = &hb_old_font_class;
-  data->x_ppem = font->x_ppem;
-  data->y_ppem = font->y_ppem;
-  data->x_scale = font->x_scale; /* XXX */
-  data->y_scale = font->y_scale; /* XXX */
-  data->userData = font;
-
-  return data;
-}
-
-void
-_hb_old_shaper_font_data_destroy (hb_old_shaper_font_data_t *data)
-{
-  free (data);
-}
-
-
-/*
- * shaper shape_plan data
- */
-
-struct hb_old_shaper_shape_plan_data_t {};
-
-hb_old_shaper_shape_plan_data_t *
-_hb_old_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-				       const hb_feature_t *user_features HB_UNUSED,
-				       unsigned int        num_user_features HB_UNUSED)
-{
-  return (hb_old_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_old_shaper_shape_plan_data_destroy (hb_old_shaper_shape_plan_data_t *data HB_UNUSED)
-{
-}
-
-
-/*
- * shaper
- */
-
-hb_bool_t
-_hb_old_shape (hb_shape_plan_t    *shape_plan HB_UNUSED,
-	       hb_font_t          *font,
-	       hb_buffer_t        *buffer,
-	       const hb_feature_t *features,
-	       unsigned int        num_features)
-{
-  hb_face_t *face = font->face;
-  HB_Face old_face = HB_SHAPER_DATA_GET (face);
-  HB_Font old_font = HB_SHAPER_DATA_GET (font);
-
-  bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
-
-retry:
-
-  unsigned int scratch_size;
-  char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
-
-#define utf16_index() var1.u32
-  HB_UChar16 *pchars = (HB_UChar16 *) scratch;
-  unsigned int chars_len = 0;
-  for (unsigned int i = 0; i < buffer->len; i++) {
-    hb_codepoint_t c = buffer->info[i].codepoint;
-    buffer->info[i].utf16_index() = chars_len;
-    if (likely (c < 0x10000))
-      pchars[chars_len++] = c;
-    else if (unlikely (c >= 0x110000))
-      pchars[chars_len++] = 0xFFFD;
-    else {
-      pchars[chars_len++] = 0xD800 + ((c - 0x10000) >> 10);
-      pchars[chars_len++] = 0xDC00 + ((c - 0x10000) & ((1 << 10) - 1));
-    }
-  }
-
-
-#define ALLOCATE_ARRAY(Type, name, len) \
-  name = (Type *) scratch; \
-  scratch += (len) * sizeof ((name)[0]); \
-  scratch_size -= (len) * sizeof ((name)[0]);
-
-
-  HB_ShaperItem item = {0};
-
-  ALLOCATE_ARRAY (const HB_UChar16, item.string, chars_len);
-  ALLOCATE_ARRAY (unsigned short, item.log_clusters, chars_len + 2);
-  item.stringLength = chars_len;
-  item.item.pos = 0;
-  item.item.length = item.stringLength;
-  item.item.script = hb_old_script_from_script (buffer->props.script);
-  item.item.bidiLevel = backward ? 1 : 0;
-
-  item.font = old_font;
-  item.face = old_face;
-  item.shaperFlags = 0;
-
-  item.glyphIndicesPresent = false;
-
-  /* TODO Alignment. */
-  unsigned int num_glyphs = scratch_size / (sizeof (HB_Glyph) +
-					    sizeof (HB_GlyphAttributes) +
-					    sizeof (HB_Fixed) +
-					    sizeof (HB_FixedPoint) +
-					    sizeof (uint32_t));
-
-  item.num_glyphs = num_glyphs;
-  ALLOCATE_ARRAY (HB_Glyph, item.glyphs, num_glyphs);
-  ALLOCATE_ARRAY (HB_GlyphAttributes, item.attributes, num_glyphs);
-  ALLOCATE_ARRAY (HB_Fixed, item.advances, num_glyphs);
-  ALLOCATE_ARRAY (HB_FixedPoint, item.offsets, num_glyphs);
-  /* Apparently in some cases the offsets array will not be fully assigned to.
-   * Clear it. */
-  memset (item.offsets, 0, num_glyphs * sizeof (item.offsets[0]));
-  uint32_t *vis_clusters;
-  ALLOCATE_ARRAY (uint32_t, vis_clusters, num_glyphs);
-
-#undef ALLOCATE_ARRAY
-
-  if (!HB_ShapeItem (&item))
-  {
-    if (unlikely (item.num_glyphs > num_glyphs))
-    {
-      buffer->ensure (buffer->allocated * 2);
-      if (buffer->in_error)
-        return false;
-      goto retry;
-    }
-    return false;
-  }
-  num_glyphs = item.num_glyphs;
-
-  /* Ok, we've got everything we need, now compose output buffer,
-   * very, *very*, carefully! */
-
-  /* Calculate visual-clusters.  That's what we ship. */
-  for (unsigned int i = 0; i < num_glyphs; i++)
-    vis_clusters[i] = -1;
-  for (unsigned int i = 0; i < buffer->len; i++) {
-    uint32_t *p = &vis_clusters[item.log_clusters[buffer->info[i].utf16_index()]];
-    *p = MIN (*p, buffer->info[i].cluster);
-  }
-  for (unsigned int i = 1; i < num_glyphs; i++)
-    if (vis_clusters[i] == (uint32_t) -1)
-      vis_clusters[i] = vis_clusters[i - 1];
-
-#undef utf16_index
-
-  buffer->ensure (num_glyphs);
-  if (buffer->in_error)
-    return false;
-
-
-  buffer->len = num_glyphs;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < num_glyphs; i++)
-  {
-    info[i].codepoint = item.glyphs[i];
-    info[i].cluster = vis_clusters[i];
-
-    info[i].mask = item.advances[i];
-    info[i].var1.u32 = item.offsets[i].x;
-    info[i].var2.u32 = item.offsets[i].y;
-  }
-
-  buffer->clear_positions ();
-
-  for (unsigned int i = 0; i < num_glyphs; ++i) {
-    hb_glyph_info_t *info = &buffer->info[i];
-    hb_glyph_position_t *pos = &buffer->pos[i];
-
-    /* TODO vertical */
-    pos->x_advance = info->mask;
-    pos->x_offset = info->var1.u32;
-    pos->y_offset = info->var2.u32;
-  }
-
-  if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
-    buffer->reverse ();
-
-  return true;
-}
--- a/gfx/harfbuzz/src/hb-open-file-private.hh
+++ b/gfx/harfbuzz/src/hb-open-file-private.hh
@@ -105,19 +105,19 @@ typedef struct OffsetTable
   inline bool sanitize (hb_sanitize_context_t *c) {
     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	searchRange;	/* (Maximum power of 2 <= numTables) x 16 */
-  USHORT	entrySelector;	/* Log2(maximum power of 2 <= numTables). */
-  USHORT	rangeShift;	/* NumTables x 16-searchRange. */
+  USHORT	searchRangeZ;	/* (Maximum power of 2 <= numTables) x 16 */
+  USHORT	entrySelectorZ;	/* Log2(maximum power of 2 <= numTables). */
+  USHORT	rangeShiftZ;	/* NumTables x 16-searchRange. */
   TableRecord	tables[VAR];	/* TableRecord entries. numTables items */
   public:
   DEFINE_SIZE_ARRAY (12, tables);
 } OpenTypeFontFace;
 
 
 /*
  * TrueType Collections
@@ -133,18 +133,18 @@ struct TTCHeaderVersion1
   inline bool sanitize (hb_sanitize_context_t *c) {
     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),
-				 * 0x00010000 */
-  LongOffsetLongArrayOf<OffsetTable>
+				 * 0x00010000u */
+  ArrayOf<OffsetTo<OffsetTable, ULONG>, ULONG>
 		table;		/* Array of offsets to the OffsetTable for each font
 				 * from the beginning of the file */
   public:
   DEFINE_SIZE_ARRAY (12, table);
 };
 
 struct TTCHeader
 {
@@ -179,17 +179,17 @@ struct TTCHeader
     }
   }
 
   protected:
   union {
   struct {
   Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
   FixedVersion	version;	/* Version of the TTC Header (1.0 or 2.0),
-				 * 0x00010000 or 0x00020000 */
+				 * 0x00010000u or 0x00020000u */
   }			header;
   TTCHeaderVersion1	version1;
   } u;
 };
 
 
 /*
  * OpenType Font File
--- a/gfx/harfbuzz/src/hb-open-type-private.hh
+++ b/gfx/harfbuzz/src/hb-open-type-private.hh
@@ -37,46 +37,46 @@ namespace OT {
 
 
 /*
  * Casts
  */
 
 /* Cast to struct T, reference to reference */
 template<typename Type, typename TObject>
-inline const Type& CastR(const TObject &X)
+static inline const Type& CastR(const TObject &X)
 { return reinterpret_cast<const Type&> (X); }
 template<typename Type, typename TObject>
-inline Type& CastR(TObject &X)
+static inline Type& CastR(TObject &X)
 { return reinterpret_cast<Type&> (X); }
 
 /* Cast to struct T, pointer to pointer */
 template<typename Type, typename TObject>
-inline const Type* CastP(const TObject *X)
+static inline const Type* CastP(const TObject *X)
 { return reinterpret_cast<const Type*> (X); }
 template<typename Type, typename TObject>
-inline Type* CastP(TObject *X)
+static inline Type* CastP(TObject *X)
 { return reinterpret_cast<Type*> (X); }
 
 /* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
  * location pointed to by P plus Ofs bytes. */
 template<typename Type>
-inline const Type& StructAtOffset(const void *P, unsigned int offset)
+static inline const Type& StructAtOffset(const void *P, unsigned int offset)
 { return * reinterpret_cast<const Type*> ((const char *) P + offset); }
 template<typename Type>
-inline Type& StructAtOffset(void *P, unsigned int offset)
+static inline Type& StructAtOffset(void *P, unsigned int offset)
 { return * reinterpret_cast<Type*> ((char *) P + offset); }
 
 /* StructAfter<T>(X) returns the struct T& that is placed after X.
  * Works with X of variable size also.  X must implement get_size() */
 template<typename Type, typename TObject>
-inline const Type& StructAfter(const TObject &X)
+static inline const Type& StructAfter(const TObject &X)
 { return StructAtOffset<Type>(&X, X.get_size()); }
 template<typename Type, typename TObject>
-inline Type& StructAfter(TObject &X)
+static inline Type& StructAfter(TObject &X)
 { return StructAtOffset<Type>(&X, X.get_size()); }
 
 
 
 /*
  * Size checking
  */
 
@@ -127,30 +127,30 @@ inline Type& StructAfter(TObject &X)
 
 
 /*
  * Null objects
  */
 
 /* Global nul-content Null pool.  Enlarge as necessary. */
 /* TODO This really should be a extern HB_INTERNAL and defined somewhere... */
-static const void *_NullPool[64 / sizeof (void *)];
+static const void *_NullPool[(256+8) / sizeof (void *)];
 
 /* Generic nul-content Null objects. */
 template <typename Type>
 static inline const Type& Null (void) {
   ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool));
   return *CastP<Type> (_NullPool);
 }
 
 /* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
 #define DEFINE_NULL_DATA(Type, data) \
 static const char _Null##Type[sizeof (Type) + 1] = data; /* +1 is for nul-termination in data */ \
 template <> \
-inline const Type& Null<Type> (void) { \
+/*static*/ inline const Type& Null<Type> (void) { \
   return *CastP<Type> (_Null##Type); \
 } /* The following line really exists such that we end in a place needing semicolon */ \
 ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type))
 
 /* Accessor macro. */
 #define Null(Type) Null<Type>()
 
 
@@ -261,31 +261,40 @@ struct hb_sanitize_context_t
        this->edit_count,
        p, p + len, len,
        this->start, this->end,
        this->writable ? "GRANTED" : "DENIED");
 
     return TRACE_RETURN (this->writable);
   }
 
+  template <typename Type, typename ValueType>
+  inline bool try_set (Type *obj, const ValueType &v) {
+    if (this->may_edit (obj, obj->static_size)) {
+      obj->set (v);
+      return true;
+    }
+    return false;
+  }
+
   mutable unsigned int debug_depth;
   const char *start, *end;
   bool writable;
   unsigned int edit_count;
   hb_blob_t *blob;
 };
 
 
 
 /* Template to sanitize an object. */
 template <typename Type>
 struct Sanitizer
 {
   static hb_blob_t *sanitize (hb_blob_t *blob) {
-    hb_sanitize_context_t c[1] = {{0}};
+    hb_sanitize_context_t c[1] = {{0, NULL, NULL, false, 0, NULL}};
     bool sane;
 
     /* TODO is_sane() stuff */
 
     c->init (blob);
 
   retry:
     DEBUG_MSG_FUNC (SANITIZE, blob, "start");
@@ -567,16 +576,17 @@ struct IntType
     return TRACE_RETURN (likely (c->check_struct (this)));
   }
   protected:
   BEInt<Type, Size> v;
   public:
   DEFINE_SIZE_STATIC (Size);
 };
 
+typedef		uint8_t	     BYTE;	/* 8-bit unsigned integer. */
 typedef IntType<uint16_t, 2> USHORT;	/* 16-bit unsigned integer. */
 typedef IntType<int16_t,  2> SHORT;	/* 16-bit signed integer. */
 typedef IntType<uint32_t, 4> ULONG;	/* 32-bit unsigned integer. */
 typedef IntType<int32_t,  4> LONG;	/* 32-bit signed integer. */
 typedef IntType<uint32_t, 3> UINT24;	/* 24-bit unsigned integer. */
 
 /* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */
 typedef SHORT FWORD;
@@ -611,34 +621,27 @@ struct Tag : ULONG
 };
 DEFINE_NULL_DATA (Tag, "    ");
 
 /* Glyph index number, same as uint16 (length = 16 bits) */
 typedef USHORT GlyphID;
 
 /* Script/language-system/feature index */
 struct Index : USHORT {
-  static const unsigned int NOT_FOUND_INDEX = 0xFFFF;
+  static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
 };
 DEFINE_NULL_DATA (Index, "\xff\xff");
 
-/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */
-struct Offset : USHORT
+/* Offset, Null offset = 0 */
+template <typename Type=USHORT>
+struct Offset : Type
 {
   inline bool is_null (void) const { return 0 == *this; }
   public:
-  DEFINE_SIZE_STATIC (2);
-};
-
-/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */
-struct LongOffset : ULONG
-{
-  inline bool is_null (void) const { return 0 == *this; }
-  public:
-  DEFINE_SIZE_STATIC (4);
+  DEFINE_SIZE_STATIC (sizeof(Type));
 };
 
 
 /* CheckSum */
 struct CheckSum : ULONG
 {
   /* This is reference implementation from the spec. */
   static inline uint32_t CalcTableChecksum (const ULONG *Table, uint32_t Length)
@@ -677,22 +680,22 @@ struct FixedVersion
   USHORT minor;
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
 
 
 /*
- * Template subclasses of Offset and LongOffset that do the dereferencing.
+ * Template subclasses of Offset that do the dereferencing.
  * Use: (base+offset)
  */
 
-template <typename OffsetType, typename Type>
-struct GenericOffsetTo : OffsetType
+template <typename Type, typename OffsetType=USHORT>
+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);
   }
 
@@ -716,50 +719,35 @@ struct GenericOffsetTo : OffsetType
     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);
     return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c));
   }
 
-  inline bool try_set (hb_sanitize_context_t *c, const OffsetType &v) {
-    if (c->may_edit (this, this->static_size)) {
-      this->set (v);
-      return true;
-    }
-    return false;
-  }
   /* Set the offset to Null */
   inline bool neuter (hb_sanitize_context_t *c) {
-    if (c->may_edit (this, this->static_size)) {
-      this->set (0); /* 0 is Null offset */
-      return true;
-    }
-    return false;
+    return c->try_set (this, 0);
   }
+  DEFINE_SIZE_STATIC (sizeof(OffsetType));
 };
 template <typename Base, typename OffsetType, typename Type>
-inline const Type& operator + (const Base &base, const GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); }
+static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
 template <typename Base, typename OffsetType, typename Type>
-inline Type& operator + (Base &base, GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); }
-
-template <typename Type>
-struct OffsetTo : GenericOffsetTo<Offset, Type> {};
-
-template <typename Type>
-struct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {};
+static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); }
 
 
 /*
  * Array Types
  */
 
-template <typename LenType, typename Type>
-struct GenericArrayOf
+/* An array with a number of elements. */
+template <typename Type, typename LenType=USHORT>
+struct ArrayOf
 {
   const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
   {
     unsigned int count = len;
     if (unlikely (start_offset > count))
       count = 0;
     else
       count -= start_offset;
@@ -832,49 +820,43 @@ struct GenericArrayOf
     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);
   }
 
+  template <typename SearchType>
+  inline int lsearch (const SearchType &x) const
+  {
+    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) {
     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:
   DEFINE_SIZE_ARRAY (sizeof (LenType), array);
 };
 
-/* An array with a USHORT number of elements. */
-template <typename Type>
-struct ArrayOf : GenericArrayOf<USHORT, Type> {};
-
-/* An array with a ULONG number of elements. */
-template <typename Type>
-struct LongArrayOf : GenericArrayOf<ULONG, Type> {};
-
 /* Array of Offset's */
 template <typename Type>
 struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {};
 
-/* Array of LongOffset's */
-template <typename Type>
-struct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {};
-
-/* LongArray of LongOffset's */
-template <typename Type>
-struct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {};
-
 /* Array of offsets relative to the beginning of the array itself. */
 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];
@@ -887,19 +869,18 @@ struct OffsetListOf : OffsetArrayOf<Type
   template <typename T>
   inline bool sanitize (hb_sanitize_context_t *c, T user_data) {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data));
   }
 };
 
 
-/* An array with a USHORT number of elements,
- * starting at second element. */
-template <typename Type>
+/* An array starting at second element. */
+template <typename Type, typename LenType=USHORT>
 struct HeadlessArrayOf
 {
   inline const Type& operator [] (unsigned int i) const
   {
     if (unlikely (i >= len || !i)) return Null(Type);
     return array[i-1];
   }
   inline unsigned int get_size (void) const
@@ -936,29 +917,29 @@ struct HeadlessArrayOf
      * 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);
   }
 
-  USHORT len;
+  LenType len;
   Type array[VAR];
   public:
-  DEFINE_SIZE_ARRAY (sizeof (USHORT), array);
+  DEFINE_SIZE_ARRAY (sizeof (LenType), array);
 };
 
 
 /* An array with sorted elements.  Supports binary searching. */
-template <typename Type>
-struct SortedArrayOf : ArrayOf<Type> {
-
+template <typename Type, typename LenType=USHORT>
+struct SortedArrayOf : ArrayOf<Type, LenType>
+{
   template <typename SearchType>
-  inline int search (const SearchType &x) const
+  inline int bsearch (const SearchType &x) const
   {
     /* Hand-coded bsearch here since this is in the hot inner loop. */
     int min = 0, max = (int) this->len - 1;
     while (min <= max)
     {
       int mid = (min + max) / 2;
       int c = this->array[mid].cmp (x);
       if (c < 0)
new file mode 100644
--- /dev/null
+++ b/gfx/harfbuzz/src/hb-ot-cmap-table.hh
@@ -0,0 +1,517 @@
+/*
+ * Copyright © 2014  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_CMAP_TABLE_HH
+#define HB_OT_CMAP_TABLE_HH
+
+#include "hb-open-type-private.hh"
+
+
+namespace OT {
+
+
+/*
+ * cmap -- Character To Glyph Index Mapping Table
+ */
+
+#define HB_OT_TAG_cmap HB_TAG('c','m','a','p')
+
+
+struct CmapSubtableFormat0
+{
+  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  {
+    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) {
+    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. */
+  BYTE		glyphIdArray[256];/* An array that maps character
+				 * code to glyph index values. */
+  public:
+  DEFINE_SIZE_STATIC (6 + 256);
+};
+
+struct CmapSubtableFormat4
+{
+  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  {
+    unsigned int segCount;
+    const USHORT *endCount;
+    const USHORT *startCount;
+    const USHORT *idDelta;
+    const USHORT *idRangeOffset;
+    const USHORT *glyphIdArray;
+    unsigned int glyphIdArrayLength;
+
+    segCount = this->segCountX2 / 2;
+    endCount = this->values;
+    startCount = endCount + segCount + 1;
+    idDelta = startCount + segCount;
+    idRangeOffset = idDelta + segCount;
+    glyphIdArray = idRangeOffset + segCount;
+    glyphIdArrayLength = (this->length - 16 - 8 * segCount) / 2;
+
+    /* Custom two-array bsearch. */
+    int min = 0, max = (int) segCount - 1;
+    unsigned int i;
+    while (min <= max)
+    {
+      int mid = (min + max) / 2;
+      if (codepoint < startCount[mid])
+        max = mid - 1;
+      else if (codepoint > endCount[mid])
+        min = mid + 1;
+      else
+      {
+	i = mid;
+	goto found;
+      }
+    }
+    return false;
+
+  found:
+    hb_codepoint_t gid;
+    unsigned int rangeOffset = idRangeOffset[i];
+    if (rangeOffset == 0)
+      gid = codepoint + idDelta[i];
+    else
+    {
+      /* Somebody has been smoking... */
+      unsigned int index = rangeOffset / 2 + (codepoint - startCount[i]) + i - segCount;
+      if (unlikely (index >= glyphIdArrayLength))
+	return false;
+      gid = glyphIdArray[index];
+      if (unlikely (!gid))
+	return false;
+      gid += idDelta[i];
+    }
+
+    *glyph = gid & 0xFFFFu;
+    return true;
+  }
+
+  inline bool sanitize (hb_sanitize_context_t *c)
+  {
+    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.
+       * If that is the case, just change the value to truncate
+       * the subtable at the end of the blob. */
+      uint16_t new_length = (uint16_t) MIN ((uintptr_t) 65535,
+					    (uintptr_t) (c->end -
+							 (char *) this));
+      if (!c->try_set (&length, new_length))
+	return TRACE_RETURN (false);
+    }
+
+    return TRACE_RETURN (16 + 4 * (unsigned int) segCountX2 <= length);
+  }
+
+  protected:
+  USHORT	format;		/* Format number is set to 4. */
+  USHORT	length;		/* This is the length in bytes of the
+				 * subtable. */
+  USHORT	languageZ;	/* Ignore. */
+  USHORT	segCountX2;	/* 2 x segCount. */
+  USHORT	searchRangeZ;	/* 2 * (2**floor(log2(segCount))) */
+  USHORT	entrySelectorZ;	/* log2(searchRange/2) */
+  USHORT	rangeShiftZ;	/* 2 x segCount - searchRange */
+
+  USHORT	values[VAR];
+#if 0
+  USHORT	endCount[segCount];	/* End characterCode for each segment,
+					 * last=0xFFFFu. */
+  USHORT	reservedPad;		/* Set to 0. */
+  USHORT	startCount[segCount];	/* Start character code for each segment. */
+  SHORT		idDelta[segCount];	/* Delta for all character codes in segment. */
+  USHORT	idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */
+  USHORT	glyphIdArray[VAR];	/* Glyph index array (arbitrary length) */
+#endif
+
+  public:
+  DEFINE_SIZE_ARRAY (14, values);
+};
+
+struct CmapSubtableLongGroup
+{
+  friend struct CmapSubtableFormat12;
+  friend struct CmapSubtableFormat13;
+
+  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) {
+    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
+				 * subtable format. */
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+template <typename UINT>
+struct CmapSubtableTrimmed
+{
+  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  {
+    /* 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) {
+    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. */
+  UINT		startCharCode;	/* First character code covered. */
+  ArrayOf<GlyphID, UINT>
+		glyphIdArray;	/* Array of glyph index values for character
+				 * codes in the range. */
+  public:
+  DEFINE_SIZE_ARRAY (5 * sizeof (UINT), glyphIdArray);
+};
+
+struct CmapSubtableFormat6  : CmapSubtableTrimmed<USHORT> {};
+struct CmapSubtableFormat10 : CmapSubtableTrimmed<ULONG > {};
+
+template <typename T>
+struct CmapSubtableLongSegmented
+{
+  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  {
+    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) {
+    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. */
+  ULONG		languageZ;	/* Ignore. */
+  SortedArrayOf<CmapSubtableLongGroup, ULONG>
+		groups;		/* Groupings. */
+  public:
+  DEFINE_SIZE_ARRAY (16, groups);
+};
+
+struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
+{
+  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
+						hb_codepoint_t u)
+  { return group.glyphID + (u - group.startCharCode); }
+};
+
+struct CmapSubtableFormat13 : CmapSubtableLongSegmented<CmapSubtableFormat13>
+{
+  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
+						hb_codepoint_t u HB_UNUSED)
+  { return group.glyphID; }
+};
+
+typedef enum
+{
+  GLYPH_VARIANT_NOT_FOUND = 0,
+  GLYPH_VARIANT_FOUND = 1,
+  GLYPH_VARIANT_USE_DEFAULT = 2
+} glyph_variant_t;
+
+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) {
+    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:
+  DEFINE_SIZE_STATIC (4);
+};
+
+typedef SortedArrayOf<UnicodeValueRange, ULONG> DefaultUVS;
+
+struct UVSMapping
+{
+  inline int cmp (const hb_codepoint_t &codepoint) const
+  {
+    return unicodeValue.cmp (codepoint);
+  }
+
+  inline bool sanitize (hb_sanitize_context_t *c) {
+    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);
+};
+
+typedef SortedArrayOf<UVSMapping, ULONG> NonDefaultUVS;
+
+struct VariationSelectorRecord
+{
+  inline glyph_variant_t get_glyph (hb_codepoint_t codepoint,
+				    hb_codepoint_t *glyph,
+				    const void *base) const
+  {
+    int i;
+    const DefaultUVS &defaults = base+defaultUVS;
+    i = defaults.bsearch (codepoint);
+    if (i != -1)
+      return GLYPH_VARIANT_USE_DEFAULT;
+    const NonDefaultUVS &nonDefaults = base+nonDefaultUVS;
+    i = nonDefaults.bsearch (codepoint);
+    if (i != -1)
+    {
+      *glyph = nonDefaults[i].glyphID;
+       return GLYPH_VARIANT_FOUND;
+    }
+    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) {
+    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>
+		defaultUVS;	/* Offset to Default UVS Table. May be 0. */
+  OffsetTo<NonDefaultUVS, ULONG>
+		nonDefaultUVS;	/* Offset to Non-Default UVS Table. May be 0. */
+  public:
+  DEFINE_SIZE_STATIC (11);
+};
+
+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) {
+    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. */
+  SortedArrayOf<VariationSelectorRecord, ULONG>
+		record;		/* Variation selector records; sorted
+				 * in increasing order of `varSelector'. */
+  public:
+  DEFINE_SIZE_ARRAY (10, record);
+};
+
+struct CmapSubtable
+{
+  /* Note: We intentionally do NOT implement subtable formats 2 and 8. */
+
+  inline bool get_glyph (hb_codepoint_t codepoint,
+			 hb_codepoint_t *glyph) const
+  {
+    switch (u.format) {
+    case  0: return u.format0 .get_glyph(codepoint, glyph);
+    case  4: return u.format4 .get_glyph(codepoint, glyph);
+    case  6: return u.format6 .get_glyph(codepoint, glyph);
+    case 10: return u.format10.get_glyph(codepoint, glyph);
+    case 12: return u.format12.get_glyph(codepoint, glyph);
+    case 13: return u.format13.get_glyph(codepoint, glyph);
+    case 14:
+    default: return false;
+    }
+  }
+
+  inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
+					    hb_codepoint_t variation_selector,
+					    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) {
+    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));
+    case 13: return TRACE_RETURN (u.format13.sanitize (c));
+    case 14: return TRACE_RETURN (u.format14.sanitize (c));
+    default:return TRACE_RETURN (true);
+    }
+  }
+
+  protected:
+  union {
+  USHORT		format;		/* Format identifier */
+  CmapSubtableFormat0	format0;
+  CmapSubtableFormat4	format4;
+  CmapSubtableFormat6	format6;
+  CmapSubtableFormat10	format10;
+  CmapSubtableFormat12	format12;
+  CmapSubtableFormat13	format13;
+  CmapSubtableFormat14	format14;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+};
+
+
+struct EncodingRecord
+{
+  inline int cmp (const EncodingRecord &other) const
+  {
+    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) {
+    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>
+		subtable;	/* Byte offset from beginning of table to the subtable for this encoding. */
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct cmap
+{
+  static const hb_tag_t tableTag	= HB_OT_TAG_cmap;
+
+  inline const CmapSubtable *find_subtable (unsigned int platform_id,
+					    unsigned int encoding_id) const
+  {
+    EncodingRecord key;
+    key.platformID.set (platform_id);
+    key.encodingID.set (encoding_id);
+
+    /* Note: We can use bsearch, but since it has no performance
+     * implications, we use lsearch and as such accept fonts with
+     * 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) {
+    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>
+			encodingRecord;	/* Encoding tables. */
+  public:
+  DEFINE_SIZE_ARRAY (4, encodingRecord);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_CMAP_TABLE_HH */
new file mode 100644
--- /dev/null
+++ b/gfx/harfbuzz/src/hb-ot-font.cc
@@ -0,0 +1,289 @@
+/*
+ * Copyright © 2011,2014  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
+ */
+
+#include "hb-private.hh"
+
+#include "hb-ot.h"
+
+#include "hb-font-private.hh"
+
+#include "hb-ot-cmap-table.hh"
+#include "hb-ot-hhea-table.hh"
+#include "hb-ot-hmtx-table.hh"
+
+
+
+struct hb_ot_font_t
+{
+  unsigned int num_glyphs;
+  unsigned int num_hmetrics;
+  const OT::hmtx *hmtx;
+  hb_blob_t *hmtx_blob;
+
+  const OT::CmapSubtable *cmap;
+  const OT::CmapSubtable *cmap_uvs;
+  hb_blob_t *cmap_blob;
+};
+
+
+static hb_ot_font_t *
+_hb_ot_font_create (hb_font_t *font)
+{
+  hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
+
+  if (unlikely (!ot_font))
+    return NULL;
+
+  ot_font->num_glyphs = font->face->get_num_glyphs ();
+
+  {
+    hb_blob_t *hhea_blob = OT::Sanitizer<OT::hhea>::sanitize (font->face->reference_table (HB_OT_TAG_hhea));
+    const OT::hhea *hhea = OT::Sanitizer<OT::hhea>::lock_instance (hhea_blob);
+    ot_font->num_hmetrics = hhea->numberOfHMetrics;
+    hb_blob_destroy (hhea_blob);
+  }
+  ot_font->hmtx_blob = OT::Sanitizer<OT::hmtx>::sanitize (font->face->reference_table (HB_OT_TAG_hmtx));
+  if (unlikely (!ot_font->num_hmetrics ||
+		2 * (ot_font->num_hmetrics + ot_font->num_glyphs) < hb_blob_get_length (ot_font->hmtx_blob)))
+  {
+    hb_blob_destroy (ot_font->hmtx_blob);
+    free (ot_font);
+    return NULL;
+  }
+  ot_font->hmtx = OT::Sanitizer<OT::hmtx>::lock_instance (ot_font->hmtx_blob);
+
+  ot_font->cmap_blob = OT::Sanitizer<OT::cmap>::sanitize (font->face->reference_table (HB_OT_TAG_cmap));
+  const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (ot_font->cmap_blob);
+  const OT::CmapSubtable *subtable = NULL;
+  const OT::CmapSubtable *subtable_uvs = NULL;
+
+  /* 32-bit subtables. */
+  if (!subtable) subtable = cmap->find_subtable (0, 6);
+  if (!subtable) subtable = cmap->find_subtable (0, 4);
+  if (!subtable) subtable = cmap->find_subtable (3, 10);
+  /* 16-bit subtables. */
+  if (!subtable) subtable = cmap->find_subtable (0, 3);
+  if (!subtable) subtable = cmap->find_subtable (3, 1);
+  /* 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);
+
+  ot_font->cmap = subtable;
+  ot_font->cmap_uvs = subtable_uvs;
+
+  return ot_font;
+}
+
+static void
+_hb_ot_font_destroy (hb_ot_font_t *ot_font)
+{
+  hb_blob_destroy (ot_font->cmap_blob);
+  hb_blob_destroy (ot_font->hmtx_blob);
+
+  free (ot_font);
+}
+
+
+static hb_bool_t
+hb_ot_get_glyph (hb_font_t *font HB_UNUSED,
+		 void *font_data,
+		 hb_codepoint_t unicode,
+		 hb_codepoint_t variation_selector,
+		 hb_codepoint_t *glyph,
+		 void *user_data HB_UNUSED)
+
+{
+  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+
+  if (unlikely (variation_selector))
+  {
+    switch (ot_font->cmap_uvs->get_glyph_variant (unicode,
+						  variation_selector,
+						  glyph))
+    {
+      case OT::GLYPH_VARIANT_NOT_FOUND:		return false;
+      case OT::GLYPH_VARIANT_FOUND:		return true;
+      case OT::GLYPH_VARIANT_USE_DEFAULT:	break;
+    }
+  }
+
+  return ot_font->cmap->get_glyph (unicode, glyph);
+}
+
+static hb_position_t
+hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
+			   void *font_data,
+			   hb_codepoint_t glyph,
+			   void *user_data HB_UNUSED)
+{
+  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+
+  if (unlikely (glyph >= ot_font->num_glyphs))
+    return 0; /* Maybe better to return notdef's advance instead? */
+
+  if (glyph >= ot_font->num_hmetrics)
+    glyph = ot_font->num_hmetrics - 1;
+
+  return font->em_scale_x (ot_font->hmtx->longHorMetric[glyph].advanceWidth);
+}
+
+static hb_position_t
+hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
+			   void *font_data,
+			   hb_codepoint_t glyph,
+			   void *user_data HB_UNUSED)
+{
+  /* TODO */
+  return 0;
+}
+
+static hb_bool_t
+hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED,
+			  void *font_data HB_UNUSED,
+			  hb_codepoint_t glyph HB_UNUSED,
+			  hb_position_t *x HB_UNUSED,
+			  hb_position_t *y HB_UNUSED,
+			  void *user_data HB_UNUSED)
+{
+  /* We always work in the horizontal coordinates. */
+  return true;
+}
+
+static hb_bool_t
+hb_ot_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
+			  void *font_data,
+			  hb_codepoint_t glyph,
+			  hb_position_t *x,
+			  hb_position_t *y,
+			  void *user_data HB_UNUSED)
+{
+  /* TODO */
+  return false;
+}
+
+static hb_position_t
+hb_ot_get_glyph_h_kerning (hb_font_t *font,
+			   void *font_data,
+			   hb_codepoint_t left_glyph,
+			   hb_codepoint_t right_glyph,
+			   void *user_data HB_UNUSED)
+{
+  /* TODO */
+  return 0;
+}
+
+static hb_position_t
+hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED,
+			   void *font_data HB_UNUSED,
+			   hb_codepoint_t top_glyph HB_UNUSED,
+			   hb_codepoint_t bottom_glyph HB_UNUSED,
+			   void *user_data HB_UNUSED)
+{
+  return 0;
+}
+
+static hb_bool_t
+hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
+			 void *font_data,
+			 hb_codepoint_t glyph,
+			 hb_glyph_extents_t *extents,
+			 void *user_data HB_UNUSED)
+{
+  /* TODO */
+  return false;
+}
+
+static hb_bool_t
+hb_ot_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
+			       void *font_data,
+			       hb_codepoint_t glyph,
+			       unsigned int point_index,
+			       hb_position_t *x,
+			       hb_position_t *y,
+			       void *user_data HB_UNUSED)
+{
+  /* TODO */
+  return false;
+}
+
+static hb_bool_t
+hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
+		      void *font_data,
+		      hb_codepoint_t glyph,
+		      char *name, unsigned int size,
+		      void *user_data HB_UNUSED)
+{
+  /* TODO */
+  return false;
+}
+
+static hb_bool_t
+hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
+			   void *font_data,
+			   const char *name, int len, /* -1 means nul-terminated */
+			   hb_codepoint_t *glyph,
+			   void *user_data HB_UNUSED)
+{
+  /* TODO */
+  return false;
+}
+
+
+static hb_font_funcs_t *
+_hb_ot_get_font_funcs (void)
+{
+  static const hb_font_funcs_t ot_ffuncs = {
+    HB_OBJECT_HEADER_STATIC,
+
+    true, /* immutable */
+
+    {
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_ot_get_##name,
+      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+    }
+  };
+
+  return const_cast<hb_font_funcs_t *> (&ot_ffuncs);
+}
+
+
+void
+hb_ot_font_set_funcs (hb_font_t *font)
+{
+  hb_ot_font_t *ot_font = _hb_ot_font_create (font);
+  if (unlikely (!ot_font))
+    return;
+
+  hb_font_set_funcs (font,
+		     _hb_ot_get_font_funcs (),
+		     ot_font,
+		     (hb_destroy_func_t) _hb_ot_font_destroy);
+}
new file mode 100644
--- /dev/null
+++ b/gfx/harfbuzz/src/hb-ot-font.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2014  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
+ */
+
+#ifndef HB_OT_FONT_H
+#define HB_OT_FONT_H
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+
+
+void
+hb_ot_font_set_funcs (hb_font_t *font);
+
+
+HB_END_DECLS
+
+#endif /* HB_OT_FONT_H */
--- a/gfx/harfbuzz/src/hb-ot-head-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-head-table.hh
@@ -53,22 +53,22 @@ struct head
 
   inline bool sanitize (hb_sanitize_context_t *c) {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1));
   }
 
   protected:
   FixedVersion	version;		/* Version of the head table--currently
-					 * 0x00010000 for version 1.0. */
+					 * 0x00010000u for version 1.0. */
   FixedVersion	fontRevision;		/* Set by font manufacturer. */
   ULONG		checkSumAdjustment;	/* To compute: set it to 0, sum the
 					 * entire font as ULONG, then store
-					 * 0xB1B0AFBA - sum. */
-  ULONG		magicNumber;		/* Set to 0x5F0F3CF5. */
+					 * 0xB1B0AFBAu - sum. */
+  ULONG		magicNumber;		/* Set to 0x5F0F3CF5u. */
   USHORT	flags;			/* Bit 0: Baseline for font at y=0;
 					 * Bit 1: Left sidebearing point at x=0;
 					 * Bit 2: Instructions may depend on point size;
 					 * Bit 3: Force ppem to integer values for all
 					 *   internal scaler math; may use fractional
 					 *   ppem sizes if this bit is clear;
 					 * Bit 4: Instructions may alter advance width
 					 *   (the advance widths might not scale linearly);
--- a/gfx/harfbuzz/src/hb-ot-hhea-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-hhea-table.hh
@@ -44,18 +44,18 @@ struct hhea
 {
   static const hb_tag_t tableTag	= HB_OT_TAG_hhea;
 
   inline bool sanitize (hb_sanitize_context_t *c) {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1));
   }
 
-  protected:
-  FixedVersion	version;		/* 0x00010000 for version 1.0. */
+  public:
+  FixedVersion	version;		/* 0x00010000u for version 1.0. */
   FWORD		ascender;		/* Typographic ascent. <a
 					 * href="http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html">
 					 * (Distance from baseline of highest
 					 * ascender)</a> */
   FWORD		descender;		/* Typographic descent. <a
 					 * href="http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html">
 					 * (Distance from baseline of lowest
 					 * descender)</a> */
--- a/gfx/harfbuzz/src/hb-ot-hmtx-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-hmtx-table.hh
@@ -54,17 +54,17 @@ struct hmtx
 
   inline bool sanitize (hb_sanitize_context_t *c) {
     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);
   }
 
-  protected:
+  public:
   LongHorMetric	longHorMetric[VAR];	/* Paired advance width and left side
 					 * bearing values for each glyph. The
 					 * value numOfHMetrics comes from
 					 * the 'hhea' table. If the font is
 					 * monospaced, only one entry need
 					 * be in the array, but that entry is
 					 * required. The last entry applies to
 					 * all subsequent glyphs. */
--- a/gfx/harfbuzz/src/hb-ot-layout-common-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-common-private.hh
@@ -98,17 +98,18 @@ struct RecordArrayOf : SortedArrayOf<Rec
       unsigned int count = *record_count;
       for (unsigned int i = 0; i < count; i++)
 	record_tags[i] = arr[i].tag;
     }
     return this->len;
   }
   inline bool find_index (hb_tag_t tag, unsigned int *index) const
   {
-    int i = this->search (tag);
+    /* If we want to allow non-sorted data, we can lsearch(). */
+    int i = this->/*lsearch*/bsearch (tag);
     if (i != -1) {
         if (index) *index = i;
         return true;
     } else {
       if (index) *index = Index::NOT_FOUND_INDEX;
       return false;
     }
   }
@@ -184,35 +185,35 @@ struct LangSys
   { return featureIndex.len; }
   inline hb_tag_t get_feature_index (unsigned int i) const
   { return featureIndex[i]; }
   inline unsigned int get_feature_indexes (unsigned int start_offset,
 					   unsigned int *feature_count /* IN/OUT */,
 					   unsigned int *feature_indexes /* OUT */) const
   { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
 
-  inline bool has_required_feature (void) const { return reqFeatureIndex != 0xffff; }
+  inline bool has_required_feature (void) const { return reqFeatureIndex != 0xFFFFu; }
   inline unsigned int get_required_feature_index (void) const
   {
-    if (reqFeatureIndex == 0xffff)
+    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) {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c));
   }
 
-  Offset	lookupOrder;	/* = Null (reserved for an offset to a
+  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
-				 * = 0xFFFF */
+				 * = 0xFFFFu */
   IndexArray	featureIndex;	/* Array of indices into the FeatureList */
   public:
   DEFINE_SIZE_ARRAY (6, featureIndex);
 };
 DEFINE_NULL_DATA (LangSys, "\0\0\xFF\xFF");
 
 
 struct Script
@@ -442,19 +443,19 @@ struct FeatureParamsCharacterVariants
 };
 
 struct FeatureParams
 {
   inline bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) {
     TRACE_SANITIZE (this);
     if (tag == HB_TAG ('s','i','z','e'))
       return TRACE_RETURN (u.size.sanitize (c));
-    if ((tag & 0xFFFF0000) == HB_TAG ('s','s','\0','\0')) /* ssXX */
+    if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
       return TRACE_RETURN (u.stylisticSet.sanitize (c));
-    if ((tag & 0xFFFF0000) == HB_TAG ('c','v','\0','\0')) /* cvXX */
+    if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
       return TRACE_RETURN (u.characterVariants.sanitize (c));
     return TRACE_RETURN (true);
   }
 
   inline const FeatureParamsSize& get_size_params (hb_tag_t tag) const
   {
     if (tag == HB_TAG ('s','i','z','e'))
       return u.size;
@@ -496,35 +497,35 @@ struct Feature
      * If sanitizing "failed" for the FeatureParams subtable, try it with the
      * alternative location.  We would know sanitize "failed" if old value
      * of the offset was non-zero, but it's zeroed now.
      *
      * Only do this for the 'size' feature, since at the time of the faulty
      * Adobe tools, only the 'size' feature had FeatureParams defined.
      */
 
-    Offset orig_offset = featureParams;
+    OffsetTo<FeatureParams> orig_offset = featureParams;
     if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
       return TRACE_RETURN (false);
 
-    if (likely (!orig_offset))
+    if (likely (orig_offset.is_null ()))
       return TRACE_RETURN (true);
 
     if (featureParams == 0 && closure &&
 	closure->tag == HB_TAG ('s','i','z','e') &&
 	closure->list_base && closure->list_base < this)
     {
       unsigned int new_offset_int = (unsigned int) orig_offset -
-				    ((char *) this - (char *) closure->list_base);
+				    (((char *) this) - ((char *) closure->list_base));
 
-      Offset new_offset;
+      OffsetTo<FeatureParams> new_offset;
       /* Check that it did not overflow. */
       new_offset.set (new_offset_int);
       if (new_offset == new_offset_int &&
-	  featureParams.try_set (c, new_offset) &&
+	  c->try_set (&featureParams, new_offset) &&
 	  !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
 	return TRACE_RETURN (false);
     }
 
     return TRACE_RETURN (true);
   }
 
   OffsetTo<FeatureParams>
@@ -579,17 +580,17 @@ struct Lookup
   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);
-    lookupFlag.set (lookup_props & 0xFFFF);
+    lookupFlag.set (lookup_props & 0xFFFFu);
     if (unlikely (!subTable.serialize (c, num_subtables))) return TRACE_RETURN (false);
     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
     {
       USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
       markFilteringSet.set (lookup_props >> 16);
     }
     return TRACE_RETURN (true);
   }
@@ -603,17 +604,17 @@ struct Lookup
       USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
       if (!markFilteringSet.sanitize (c)) return TRACE_RETURN (false);
     }
     return TRACE_RETURN (true);
   }
 
   USHORT	lookupType;		/* Different enumerations for GSUB and GPOS */
   USHORT	lookupFlag;		/* Lookup qualifiers */
-  ArrayOf<Offset>
+  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:
   DEFINE_SIZE_ARRAY2 (6, subTable, markFilteringSetX);
 };
 
@@ -626,17 +627,17 @@ typedef OffsetListOf<Lookup> LookupList;
 
 struct CoverageFormat1
 {
   friend struct Coverage;
 
   private:
   inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
   {
-    int i = glyphArray.search (glyph_id);
+    int i = glyphArray.bsearch (glyph_id);
     ASSERT_STATIC (((unsigned int) -1) == NOT_COVERED);
     return i;
   }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<GlyphID> &glyphs,
 			 unsigned int num_glyphs)
   {
@@ -691,17 +692,17 @@ struct CoverageFormat1
 
 struct CoverageFormat2
 {
   friend struct Coverage;
 
   private:
   inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
   {
-    int i = rangeRecord.search (glyph_id);
+    int i = rangeRecord.bsearch (glyph_id);
     if (i != -1) {
       const RangeRecord &range = rangeRecord[i];
       return (unsigned int) range.value + (glyph_id - range.start);
     }
     return NOT_COVERED;
   }
 
   inline bool serialize (hb_serialize_context_t *c,
@@ -987,17 +988,17 @@ struct ClassDefFormat1
 
 struct ClassDefFormat2
 {
   friend struct ClassDef;
 
   private:
   inline unsigned int get_class (hb_codepoint_t glyph_id) const
   {
-    int i = rangeRecord.search (glyph_id);
+    int i = rangeRecord.bsearch (glyph_id);
     if (i != -1)
       return rangeRecord[i].value;
     return 0;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (rangeRecord.sanitize (c));
@@ -1125,17 +1126,17 @@ struct Device
 
     if (ppem_size < startSize || ppem_size > endSize)
       return 0;
 
     unsigned int s = ppem_size - startSize;
 
     unsigned int byte = deltaValue[s >> (4 - f)];
     unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
-    unsigned int mask = (0xFFFF >> (16 - (1 << f)));
+    unsigned int mask = (0xFFFFu >> (16 - (1 << f)));
 
     int delta = bits & mask;
 
     if ((unsigned int) delta >= ((mask + 1) >> 1))
       delta -= mask + 1;
 
     return delta;
   }
--- a/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh
@@ -277,17 +277,17 @@ struct MarkGlyphSetsFormat1
 
   inline bool sanitize (hb_sanitize_context_t *c) {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (coverage.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
-  LongOffsetArrayOf<Coverage>
+  ArrayOf<OffsetTo<Coverage, ULONG> >
 		coverage;		/* Array of long offsets to mark set
 					 * coverage tables */
   public:
   DEFINE_SIZE_ARRAY (4, coverage);
 };
 
 struct MarkGlyphSets
 {
@@ -355,29 +355,29 @@ struct GDEF
   inline unsigned int get_lig_carets (hb_font_t *font,
 				      hb_direction_t direction,
 				      hb_codepoint_t glyph_id,
 				      unsigned int start_offset,
 				      unsigned int *caret_count /* IN/OUT */,
 				      hb_position_t *caret_array /* OUT */) const
   { return (this+ligCaretList).get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); }
 
-  inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002 && markGlyphSetsDef[0] != 0; }
+  inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef[0] != 0; }
   inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
-  { return version.to_int () >= 0x00010002 && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); }
+  { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); }
 
   inline bool sanitize (hb_sanitize_context_t *c) {
     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 () < 0x00010002 || markGlyphSetsDef[0].sanitize (c, this)));
+			 (version.to_int () < 0x00010002u || markGlyphSetsDef[0].sanitize (c, this)));
   }
 
 
   /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
    * glyph class and other bits, and high 8-bit gthe mark attachment type (if any).
    * Not to be confused with lookup_props which is very similar. */
   inline unsigned int get_glyph_props (hb_codepoint_t glyph) const
   {
@@ -395,17 +395,17 @@ struct GDEF
 	  klass = get_mark_attachment_type (glyph);
 	  return HB_OT_LAYOUT_GLYPH_PROPS_MARK | (klass << 8);
     }
   }
 
 
   protected:
   FixedVersion	version;		/* Version of the GDEF table--currently
-					 * 0x00010002 */
+					 * 0x00010002u */
   OffsetTo<ClassDef>
 		glyphClassDef;		/* Offset to class definition table
 					 * for glyph type--from beginning of
 					 * GDEF header (may be Null) */
   OffsetTo<AttachList>
 		attachList;		/* Offset to list of glyphs with
 					 * attachment points--from beginning
 					 * of GDEF header (may be Null) */
--- a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
@@ -44,28 +44,28 @@ namespace OT {
 
 typedef USHORT Value;
 
 typedef Value ValueRecord[VAR];
 
 struct ValueFormat : USHORT
 {
   enum Flags {
-    xPlacement	= 0x0001,	/* Includes horizontal adjustment for placement */
-    yPlacement	= 0x0002,	/* Includes vertical adjustment for placement */
-    xAdvance	= 0x0004,	/* Includes horizontal adjustment for advance */
-    yAdvance	= 0x0008,	/* Includes vertical adjustment for advance */
-    xPlaDevice	= 0x0010,	/* Includes horizontal Device table for placement */
-    yPlaDevice	= 0x0020,	/* Includes vertical Device table for placement */
-    xAdvDevice	= 0x0040,	/* Includes horizontal Device table for advance */
-    yAdvDevice	= 0x0080,	/* Includes vertical Device table for advance */
-    ignored	= 0x0F00,	/* Was used in TrueType Open for MM fonts */
-    reserved	= 0xF000,	/* For future use */
+    xPlacement	= 0x0001u,	/* Includes horizontal adjustment for placement */
+    yPlacement	= 0x0002u,	/* Includes vertical adjustment for placement */
+    xAdvance	= 0x0004u,	/* Includes horizontal adjustment for advance */
+    yAdvance	= 0x0008u,	/* Includes vertical adjustment for advance */
+    xPlaDevice	= 0x0010u,	/* Includes horizontal Device table for placement */
+    yPlaDevice	= 0x0020u,	/* Includes vertical Device table for placement */
+    xAdvDevice	= 0x0040u,	/* Includes horizontal Device table for advance */
+    yAdvDevice	= 0x0080u,	/* Includes vertical Device table for advance */
+    ignored	= 0x0F00u,	/* Was used in TrueType Open for MM fonts */
+    reserved	= 0xF000u,	/* For future use */
 
-    devices	= 0x00F0	/* Mask for having any Device table */
+    devices	= 0x00F0u	/* Mask for having any Device table */
   };
 
 /* All fields are options.  Only those available advance the value pointer. */
 #if 0
   SHORT		xPlacement;		/* Horizontal adjustment for
 					 * placement--in design units */
   SHORT		yPlacement;		/* Vertical adjustment for
 					 * placement--in design units */
@@ -1584,43 +1584,43 @@ GPOS::position_start (hb_font_t *font HB
   unsigned int count = buffer->len;
   for (unsigned int i = 0; i < count; i++)
     buffer->pos[i].attach_lookback() = buffer->pos[i].cursive_chain() = 0;
 }
 
 void
 GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
 {
+  _hb_buffer_assert_gsubgpos_vars (buffer);
+
   unsigned int len;
   hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
   hb_direction_t direction = buffer->props.direction;
 
   /* Handle cursive connections */
   for (unsigned int i = 0; i < len; i++)
     fix_cursive_minor_offset (pos, i, direction);
 
   /* Handle attachments */
   for (unsigned int i = 0; i < len; i++)
     fix_mark_attachment (pos, i, direction);
-
-  _hb_buffer_deallocate_gsubgpos_vars (buffer);
 }
 
 
 /* Out-of-class implementation for methods recursing */
 
 template <typename context_t>
-inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
+/*static*/ inline typename context_t::return_t PosLookup::dispatch_recurse_func (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);
   return l.dispatch (c);
 }
 
-inline bool PosLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index)
+/*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;
   return ret;
--- a/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh
@@ -39,28 +39,28 @@ struct SingleSubstFormat1
 {
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
     Coverage::Iter iter;
     for (iter.init (this+coverage); iter.more (); iter.next ()) {
       hb_codepoint_t glyph_id = iter.get_glyph ();
       if (c->glyphs->has (glyph_id))
-	c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFF);
+	c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
     }
   }
 
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
     Coverage::Iter iter;
     for (iter.init (this+coverage); iter.more (); iter.next ()) {
       hb_codepoint_t glyph_id = iter.get_glyph ();
       c->input->add (glyph_id);
-      c->output->add ((glyph_id + deltaGlyphID) & 0xFFFF);
+      c->output->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
     }
   }
 
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
   }
 
@@ -74,17 +74,17 @@ struct SingleSubstFormat1
   {
     TRACE_APPLY (this);
     hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
     unsigned int index = (this+coverage).get_coverage (glyph_id);
     if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
 
     /* According to the Adobe Annotated OpenType Suite, result is always
      * limited to 16bit. */
-    glyph_id = (glyph_id + deltaGlyphID) & 0xFFFF;
+    glyph_id = (glyph_id + deltaGlyphID) & 0xFFFFu;
     c->replace_glyph (glyph_id);
 
     return TRACE_RETURN (true);
   }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<GlyphID> &glyphs,
 			 unsigned int num_glyphs,
@@ -265,33 +265,44 @@ struct Sequence
     unsigned int count = substitute.len;
     for (unsigned int i = 0; i < count; i++)
       c->output->add (substitute[i]);
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    if (unlikely (!substitute.len)) return TRACE_RETURN (false);
+    unsigned int count = substitute.len;
+
+    /* TODO:
+     * Testing shows that Uniscribe actually allows zero-len susbstitute,
+     * which essentially deletes a glyph.  We don't allow for now.  It
+     * can be confusing to the client since the cluster from the deleted
+     * glyph won't be merged with any output cluster...  Also, currently
+     * buffer->move_to() makes assumptions about this too.  Perhaps fix
+     * in the future after figuring out what to do with the clusters.
+     */
+    if (unlikely (!count)) return TRACE_RETURN (false);
+
+    /* Special-case to make it in-place and not consider this
+     * as a "multiplied" substitution. */
+    if (unlikely (count == 1))
+    {
+      c->replace_glyph (substitute.array[0]);
+      return TRACE_RETURN (true);
+    }
 
     unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
 			 HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
-    unsigned int count = substitute.len;
-    if (count == 1) /* Special-case to make it in-place. */
-    {
-      c->replace_glyph (substitute.array[0]);
+
+    for (unsigned int i = 0; i < count; i++) {
+      _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
+      c->output_glyph_for_component (substitute.array[i], klass);
     }
-    else
-    {
-      for (unsigned int i = 0; i < count; i++) {
-	_hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
-	c->output_glyph (substitute.array[i], klass);
-      }
-      c->buffer->skip_glyph ();
-    }
+    c->buffer->skip_glyph ();
 
     return TRACE_RETURN (true);
   }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<GlyphID> &glyphs,
 			 unsigned int num_glyphs)
   {
@@ -619,17 +630,26 @@ struct Ligature
 
     return TRACE_RETURN (true);
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int count = component.len;
-    if (unlikely (count < 1)) return TRACE_RETURN (false);
+
+    if (unlikely (!count)) return TRACE_RETURN (false);
+
+    /* Special-case to make it in-place and not consider this
+     * as a "ligated" substitution. */
+    if (unlikely (count == 1))
+    {
+      c->replace_glyph (ligGlyph);
+      return TRACE_RETURN (true);
+    }
 
     bool is_mark_ligature = false;
     unsigned int total_component_count = 0;
 
     unsigned int match_length = 0;
     unsigned int match_positions[MAX_CONTEXT_LENGTH];
 
     if (likely (!match_input (c, count,
@@ -1313,17 +1333,17 @@ struct GSUB : GSUBGPOS
   public:
   DEFINE_SIZE_STATIC (10);
 };
 
 
 void
 GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer)
 {
-  _hb_buffer_allocate_gsubgpos_vars (buffer);
+  _hb_buffer_assert_gsubgpos_vars (buffer);
 
   const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef;
   unsigned int count = buffer->len;
   for (unsigned int i = 0; i < count; i++)
   {
     _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
     _hb_glyph_info_clear_lig_props (&buffer->info[i]);
     buffer->info[i].syllable() = 0;
@@ -1333,33 +1353,33 @@ GSUB::substitute_start (hb_font_t *font,
 void
 GSUB::substitute_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED)
 {
 }
 
 
 /* Out-of-class implementation for methods recursing */
 
-inline bool ExtensionSubst::is_reverse (void) const
+/*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 SubstLookup::lookup_type_is_reverse (type);
 }
 
 template <typename context_t>
-inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
+/*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);
   return l.dispatch (c);
 }
 
-inline bool SubstLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index)
+/*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;
   return ret;
--- a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh
@@ -344,21 +344,17 @@ struct hb_apply_context_t
       SKIP_YES,
       SKIP_MAYBE
     };
 
     inline may_skip_t
     may_skip (const hb_apply_context_t *c,
 	      const hb_glyph_info_t    &info) const
     {
-      unsigned int property;
-
-      property = _hb_glyph_info_get_glyph_props (&info);
-
-      if (!c->match_properties (info.codepoint, property, lookup_props))
+      if (!c->check_glyph_property (&info, lookup_props))
 	return SKIP_YES;
 
       if (unlikely (_hb_glyph_info_is_default_ignorable (&info) &&
 		    (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
 		    (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) &&
 		    !_hb_glyph_info_ligated (&info)))
 	return SKIP_MAYBE;
 
@@ -482,17 +478,16 @@ struct hb_apply_context_t
     {
       assert (num_items > 0);
       while (!has_no_chance ())
       {
 	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))
 	{
@@ -533,52 +528,55 @@ struct hb_apply_context_t
      */
     if (lookup_props & LookupFlag::MarkAttachmentType)
       return (lookup_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
 
     return true;
   }
 
   inline bool
-  match_properties (hb_codepoint_t  glyph,
-		    unsigned int    glyph_props,
-		    unsigned int    lookup_props) const
+  check_glyph_property (const hb_glyph_info_t *info,
+			unsigned int  lookup_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
      */
     if (glyph_props & lookup_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 true;
   }
 
-  inline bool
-  check_glyph_property (hb_glyph_info_t *info,
-			unsigned int  lookup_props) const
-  {
-    unsigned int property;
-
-    property = _hb_glyph_info_get_glyph_props (info);
-
-    return match_properties (info->codepoint, property, lookup_props);
-  }
-
   inline void _set_glyph_props (hb_codepoint_t glyph_index,
 			  unsigned int class_guess = 0,
-			  bool ligature = false) const
+			  bool ligature = false,
+			  bool component = false) const
   {
     unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
 			  HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
     add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
     if (ligature)
+    {
       add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
+      /* In the only place that the MULTIPLIED bit is used, Uniscribe
+       * seems to only care about the "last" transformation between
+       * Ligature and Multiple substitions.  Ie. if you ligate, expand,
+       * and ligate again, it forgives the multiplication and acts as
+       * if only ligation happened.  As such, clear MULTIPLIED bit.
+       */
+      add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
+    }
+    if (component)
+      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
     if (likely (has_glyph_classes))
       _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
     else if (class_guess)
       _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess);
   }
 
   inline void replace_glyph (hb_codepoint_t glyph_index) const
   {
@@ -591,20 +589,20 @@ struct hb_apply_context_t
     buffer->cur().codepoint = glyph_index;
   }
   inline void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
 					   unsigned int class_guess) const
   {
     _set_glyph_props (glyph_index, class_guess, true);
     buffer->replace_glyph (glyph_index);
   }
-  inline void output_glyph (hb_codepoint_t glyph_index,
-			    unsigned int class_guess) const
+  inline void output_glyph_for_component (hb_codepoint_t glyph_index,
+					  unsigned int class_guess) const
   {
-    _set_glyph_props (glyph_index, class_guess);
+    _set_glyph_props (glyph_index, class_guess, false, true);
     buffer->output_glyph (glyph_index);
   }
 };
 
 
 
 typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
 typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
@@ -877,16 +875,17 @@ static inline void ligate_input (hb_appl
       if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) {
 	unsigned int new_lig_comp = components_so_far - last_num_components +
 				    MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->info[i]), 1u), last_num_components);
 	_hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
       } else
 	break;
     }
   }
+  TRACE_RETURN (true);
 }
 
 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)
 {
@@ -989,17 +988,19 @@ static inline bool apply_lookup (hb_appl
     unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
     int delta = new_len - orig_len;
 
     if (!delta)
         continue;
 
     /* Recursed lookup changed buffer len.  Adjust. */
 
-    /* end can't go back past the current match position. */
+    /* end can't go back past the current match position.
+     * Note: this is only true because we do NOT allow MultipleSubst
+     * with zero sequence len. */
     end = MAX ((int) match_positions[idx] + 1, int (end) + delta);
 
     unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
 
     if (delta > 0)
     {
       if (unlikely (delta + count > MAX_CONTEXT_LENGTH))
 	break;
@@ -2248,18 +2249,18 @@ struct GSUBGPOS
   { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
   inline const Script& get_script (unsigned int i) const
   { return (this+scriptList)[i]; }
   inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
   { return (this+scriptList).find_index (tag, index); }
 
   inline unsigned int get_feature_count (void) const
   { return (this+featureList).len; }
-  inline const Tag& get_feature_tag (unsigned int i) const
-  { return (this+featureList).get_tag (i); }
+  inline hb_tag_t get_feature_tag (unsigned int i) const
+  { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
   inline unsigned int get_feature_tags (unsigned int start_offset,
 					unsigned int *feature_count /* IN/OUT */,
 					hb_tag_t     *feature_tags /* OUT */) const
   { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
   inline const Feature& get_feature (unsigned int i) const
   { return (this+featureList)[i]; }
   inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
   { return (this+featureList).find_index (tag, index); }
@@ -2274,17 +2275,17 @@ struct GSUBGPOS
     return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) &&
 			 scriptList.sanitize (c, this) &&
 			 featureList.sanitize (c, this) &&
 			 lookupList.sanitize (c, this));
   }
 
   protected:
   FixedVersion	version;	/* Version of the GSUB/GPOS table--initially set
-				 * to 0x00010000 */
+				 * to 0x00010000u */
   OffsetTo<ScriptList>
 		scriptList;  	/* ScriptList table */
   OffsetTo<FeatureList>
 		featureList; 	/* FeatureList table */
   OffsetTo<LookupList>
 		lookupList; 	/* LookupList table */
   public:
   DEFINE_SIZE_STATIC (10);
--- a/gfx/harfbuzz/src/hb-ot-layout-jstf-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-jstf-table.hh
@@ -209,17 +209,17 @@ struct JSTF
   inline bool sanitize (hb_sanitize_context_t *c) {
     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 0x00010000 */
+				 * to 0x00010000u */
   RecordArrayOf<JstfScript>
 		scriptList;  	/* Array of JstfScripts--listed
 				 * alphabetically by ScriptTag */
   public:
   DEFINE_SIZE_ARRAY (6, scriptList);
 };
 
 
--- a/gfx/harfbuzz/src/hb-ot-layout-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-private.hh
@@ -45,19 +45,21 @@ typedef enum
   /* The following three match LookupFlags::Ignore* numbers. */
   HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH	= 0x02u,
   HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE	= 0x04u,
   HB_OT_LAYOUT_GLYPH_PROPS_MARK		= 0x08u,
 
   /* The following are used internally; not derived from GDEF. */
   HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED	= 0x10u,
   HB_OT_LAYOUT_GLYPH_PROPS_LIGATED	= 0x20u,
+  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED	= 0x40u,
 
   HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE     = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
-					  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED
+					  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
+					  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
 } hb_ot_layout_glyph_class_mask_t;
 
 
 /*
  * GSUB/GPOS
  */
 
 HB_INTERNAL hb_bool_t
@@ -120,17 +122,17 @@ 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)
+  inline void fini (const TLookup &lookup HB_UNUSED)
   {
   }
 
   hb_set_digest_t digest;
 };
 
 struct hb_ot_layout_t
 {
@@ -177,72 +179,72 @@ HB_INTERNAL void
 
 enum {
   MASK0_ZWJ       = 0x20u,
   MASK0_ZWNJ      = 0x40u,
   MASK0_IGNORABLE = 0x80u,
   MASK0_GEN_CAT   = 0x1Fu
 };
 
-inline void
+static inline void
 _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_unicode_funcs_t *unicode)
 {
   /* XXX This shouldn't be inlined, or at least not while is_default_ignorable() is inline. */
   info->unicode_props0() = ((unsigned int) unicode->general_category (info->codepoint)) |
 			   (unicode->is_default_ignorable (info->codepoint) ? MASK0_IGNORABLE : 0) |
-			   (info->codepoint == 0x200C ? MASK0_ZWNJ : 0) |
-			   (info->codepoint == 0x200D ? MASK0_ZWJ : 0);
+			   (info->codepoint == 0x200Cu ? MASK0_ZWNJ : 0) |
+			   (info->codepoint == 0x200Du ? MASK0_ZWJ : 0);
   info->unicode_props1() = unicode->modified_combining_class (info->codepoint);
 }
 
-inline void
+static inline void
 _hb_glyph_info_set_general_category (hb_glyph_info_t *info,
 				     hb_unicode_general_category_t gen_cat)
 {
   info->unicode_props0() = (unsigned int) gen_cat | ((info->unicode_props0()) & ~MASK0_GEN_CAT);
 }
 
-inline hb_unicode_general_category_t
+static inline hb_unicode_general_category_t
 _hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
 {
   return (hb_unicode_general_category_t) (info->unicode_props0() & MASK0_GEN_CAT);
 }
 
-inline void
+static inline void
 _hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info,
 					     unsigned int modified_class)
 {
   info->unicode_props1() = modified_class;
 }
 
-inline unsigned int
+static inline unsigned int
 _hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
 {
   return info->unicode_props1();
 }
 
-inline hb_bool_t
+static inline hb_bool_t
 _hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
 {
   return !!(info->unicode_props0() & MASK0_IGNORABLE);
 }
 
-inline hb_bool_t
+static inline hb_bool_t
 _hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
 {
   return !!(info->unicode_props0() & MASK0_ZWNJ);
 }
 
-inline hb_bool_t
+static inline hb_bool_t
 _hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
 {
   return !!(info->unicode_props0() & MASK0_ZWJ);
 }
 
-inline void
+static inline void
 _hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
 {
   info->unicode_props0() ^= MASK0_ZWNJ | MASK0_ZWJ;
 }
 
 /* lig_props: aka lig_id / lig_comp
  *
  * When a ligature is formed:
@@ -334,41 +336,41 @@ static inline uint8_t
   uint8_t lig_id = buffer->next_serial () & 0x07;
   if (unlikely (!lig_id))
     lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */
   return lig_id;
 }
 
 /* glyph_props: */
 
-inline void
+static inline void
 _hb_glyph_info_set_glyph_props (hb_glyph_info_t *info, unsigned int props)
 {
   info->glyph_props() = props;
 }
 
-inline unsigned int
+static inline unsigned int
 _hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info)
 {
   return info->glyph_props();
 }
 
-inline bool
+static inline bool
 _hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info)
 {
   return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH);
 }
 
-inline bool
+static inline bool
 _hb_glyph_info_is_ligature (const hb_glyph_info_t *info)
 {
   return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE);
 }
 
-inline bool
+static inline bool
 _hb_glyph_info_is_mark (const hb_glyph_info_t *info)
 {
   return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
 }
 
 static inline bool
 _hb_glyph_info_substituted (const hb_glyph_info_t *info)
 {
@@ -376,48 +378,83 @@ static inline bool
 }
 
 static inline bool
 _hb_glyph_info_ligated (const hb_glyph_info_t *info)
 {
   return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED);
 }
 
+static inline bool
+_hb_glyph_info_multiplied (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
+}
+
+static inline bool
+_hb_glyph_info_ligated_and_didnt_multiply (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_ligated (info) && !_hb_glyph_info_multiplied (info);
+}
+
+static inline void
+_hb_glyph_info_clear_ligated_and_multiplied (hb_glyph_info_t *info)
+{
+  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
+			   HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
+}
+
+
 /* Allocation / deallocation. */
 
-inline void
+static inline void
 _hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer)
 {
   HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props0);
   HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props1);
 }
 
-inline void
+static inline void
 _hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer)
 {
   HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props0);
   HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props1);
 }
 
-inline void
+static inline void
+_hb_buffer_assert_unicode_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_ASSERT_VAR (buffer, unicode_props0);
+  HB_BUFFER_ASSERT_VAR (buffer, unicode_props1);
+}
+
+static inline void
 _hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
 {
   HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
   HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
   HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
 }
 
-inline void
+static inline void
 _hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer)
 {
   HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
   HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
   HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
 }
 
+static inline void
+_hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_ASSERT_VAR (buffer, glyph_props);
+  HB_BUFFER_ASSERT_VAR (buffer, lig_props);
+  HB_BUFFER_ASSERT_VAR (buffer, syllable);
+}
+
 /* Make sure no one directly touches our props... */
 #undef unicode_props0
 #undef unicode_props1
 #undef lig_props
 #undef glyph_props
 
 
 #endif /* HB_OT_LAYOUT_PRIVATE_HH */
--- a/gfx/harfbuzz/src/hb-ot-layout.cc
+++ b/gfx/harfbuzz/src/hb-ot-layout.cc
@@ -322,19 +322,38 @@ hb_ot_layout_script_find_language (hb_fa
 
 hb_bool_t
 hb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
 						  hb_tag_t      table_tag,
 						  unsigned int  script_index,
 						  unsigned int  language_index,
 						  unsigned int *feature_index)
 {
-  const OT::LangSys &l = get_gsubgpos_table (face, table_tag).get_script (script_index).get_lang_sys (language_index);
+  return hb_ot_layout_language_get_required_feature (face,
+						     table_tag,
+						     script_index,
+						     language_index,
+						     feature_index,
+						     NULL);
+}
 
-  if (feature_index) *feature_index = l.get_required_feature_index ();
+hb_bool_t
+hb_ot_layout_language_get_required_feature (hb_face_t    *face,
+					    hb_tag_t      table_tag,
+					    unsigned int  script_index,
+					    unsigned int  language_index,
+					    unsigned int *feature_index,
+					    hb_tag_t     *feature_tag)
+{
+  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
+
+  unsigned int index = l.get_required_feature_index ();
+  if (feature_index) *feature_index = index;
+  if (feature_tag) *feature_tag = g.get_feature_tag (index);
 
   return l.has_required_feature ();
 }
 
 unsigned int
 hb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
 					   hb_tag_t      table_tag,
 					   unsigned int  script_index,
@@ -463,21 +482,22 @@ static void
 					unsigned int    script_index,
 					unsigned int    language_index,
 					const hb_tag_t *features,
 					hb_set_t       *lookup_indexes /* OUT */)
 {
   if (!features)
   {
     unsigned int required_feature_index;
-    if (hb_ot_layout_language_get_required_feature_index (face,
-							  table_tag,
-							  script_index,
-							  language_index,
-							  &required_feature_index))
+    if (hb_ot_layout_language_get_required_feature (face,
+						    table_tag,
+						    script_index,
+						    language_index,
+						    &required_feature_index,
+						    NULL))
       _hb_ot_layout_collect_lookups_lookups (face,
 					     table_tag,
 					     required_feature_index,
 					     lookup_indexes);
 
     /* All features */
     unsigned int feature_indices[32];
     unsigned int offset, len;
--- a/gfx/harfbuzz/src/hb-ot-layout.h
+++ b/gfx/harfbuzz/src/hb-ot-layout.h
@@ -87,19 +87,19 @@ hb_ot_layout_get_ligature_carets (hb_fon
 				  unsigned int   *caret_count /* IN/OUT */,
 				  hb_position_t  *caret_array /* OUT */);
 
 
 /*
  * GSUB/GPOS feature query and enumeration interface
  */
 
-#define HB_OT_LAYOUT_NO_SCRIPT_INDEX		((unsigned int) 0xFFFF)
-#define HB_OT_LAYOUT_NO_FEATURE_INDEX		((unsigned int) 0xFFFF)
-#define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX	((unsigned int) 0xFFFF)
+#define HB_OT_LAYOUT_NO_SCRIPT_INDEX		0xFFFFu
+#define HB_OT_LAYOUT_NO_FEATURE_INDEX		0xFFFFu
+#define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX	0xFFFFu
 
 unsigned int
 hb_ot_layout_table_get_script_tags (hb_face_t    *face,
 				    hb_tag_t      table_tag,
 				    unsigned int  start_offset,
 				    unsigned int *script_count /* IN/OUT */,
 				    hb_tag_t     *script_tags /* OUT */);
 
@@ -141,16 +141,24 @@ hb_ot_layout_script_find_language (hb_fa
 
 hb_bool_t
 hb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
 						  hb_tag_t      table_tag,
 						  unsigned int  script_index,
 						  unsigned int  language_index,
 						  unsigned int *feature_index);
 
+hb_bool_t
+hb_ot_layout_language_get_required_feature (hb_face_t    *face,
+					    hb_tag_t      table_tag,
+					    unsigned int  script_index,
+					    unsigned int  language_index,
+					    unsigned int *feature_index,
+					    hb_tag_t     *feature_tag);
+
 unsigned int
 hb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
 					   hb_tag_t      table_tag,
 					   unsigned int  script_index,
 					   unsigned int  language_index,
 					   unsigned int  start_offset,
 					   unsigned int *feature_count /* IN/OUT */,
 					   unsigned int *feature_indexes /* OUT */);
--- a/gfx/harfbuzz/src/hb-ot-map-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-map-private.hh
@@ -148,36 +148,36 @@ struct hb_ot_map_t
   hb_mask_t global_mask;
 
   hb_prealloced_array_t<feature_map_t, 8> features;
   hb_prealloced_array_t<lookup_map_t, 32> lookups[2]; /* GSUB/GPOS */
   hb_prealloced_array_t<stage_map_t, 4> stages[2]; /* GSUB/GPOS */
 };
 
 enum hb_ot_map_feature_flags_t {
-  F_NONE		= 0x0000,
-  F_GLOBAL		= 0x0001,
-  F_HAS_FALLBACK	= 0x0002,
-  F_MANUAL_ZWJ		= 0x0004
+  F_NONE		= 0x0000u,
+  F_GLOBAL		= 0x0001u,
+  F_HAS_FALLBACK	= 0x0002u,
+  F_MANUAL_ZWJ		= 0x0004u
 };
 /* Macro version for where const is desired. */
 #define F_COMBINE(l,r) (hb_ot_map_feature_flags_t ((unsigned int) (l) | (unsigned int) (r)))
-inline hb_ot_map_feature_flags_t
+static inline hb_ot_map_feature_flags_t
 operator | (hb_ot_map_feature_flags_t l, hb_ot_map_feature_flags_t r)
 { return hb_ot_map_feature_flags_t ((unsigned int) l | (unsigned int) r); }
-inline hb_ot_map_feature_flags_t
+static inline hb_ot_map_feature_flags_t
 operator & (hb_ot_map_feature_flags_t l, hb_ot_map_feature_flags_t r)
 { return hb_ot_map_feature_flags_t ((unsigned int) l & (unsigned int) r); }
-inline hb_ot_map_feature_flags_t
+static inline hb_ot_map_feature_flags_t
 operator ~ (hb_ot_map_feature_flags_t r)
 { return hb_ot_map_feature_flags_t (~(unsigned int) r); }
-inline hb_ot_map_feature_flags_t&
+static inline hb_ot_map_feature_flags_t&
 operator |= (hb_ot_map_feature_flags_t &l, hb_ot_map_feature_flags_t r)
 { l = l | r; return l; }
-inline hb_ot_map_feature_flags_t&
+static inline hb_ot_map_feature_flags_t&
 operator &= (hb_ot_map_feature_flags_t& l, hb_ot_map_feature_flags_t r)
 { l = l & r; return l; }
 
 
 struct hb_ot_map_builder_t
 {
   public:
 
--- a/gfx/harfbuzz/src/hb-ot-map.cc
+++ b/gfx/harfbuzz/src/hb-ot-map.cc
@@ -94,16 +94,17 @@ hb_ot_map_builder_t::hb_ot_map_builder_t
   }
 }
 
 void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value,
 				       hb_ot_map_feature_flags_t flags)
 {
   feature_info_t *info = feature_infos.push();
   if (unlikely (!info)) return;
+  if (unlikely (!tag)) return;
   info->tag = tag;
   info->seq = feature_infos.len;
   info->max_value = value;
   info->flags = flags;
   info->default_value = (flags & F_GLOBAL) ? value : 0;
   info->stage[0] = current_stage[0];
   info->stage[1] = current_stage[1];
 }
@@ -126,27 +127,43 @@ void hb_ot_map_builder_t::add_pause (uns
   current_stage[table_index]++;
 }
 
 void
 hb_ot_map_builder_t::compile (hb_ot_map_t &m)
 {
   m.global_mask = 1;
 
-  for (unsigned int table_index = 0; table_index < 2; table_index++) {
+  unsigned int required_feature_index[2];
+  hb_tag_t required_feature_tag[2];
+  /* We default to applying required feature in stage 0.  If the required
+   * feature has a tag that is known to the shaper, we apply required feature
+   * in the stage for that tag.
+   */
+  unsigned int required_feature_stage[2] = {0, 0};
+
+  for (unsigned int table_index = 0; table_index < 2; table_index++)
+  {
     m.chosen_script[table_index] = chosen_script[table_index];
     m.found_script[table_index] = found_script[table_index];
+
+    hb_ot_layout_language_get_required_feature (face,
+						table_tags[table_index],
+						script_index[table_index],
+						language_index[table_index],
+						&required_feature_index[table_index],
+						&required_feature_tag[table_index]);
   }
 
   if (!feature_infos.len)
     return;
 
   /* Sort features and merge duplicates */
   {
-    feature_infos.sort ();
+    feature_infos.qsort ();
     unsigned int j = 0;
     for (unsigned int i = 1; i < feature_infos.len; i++)
       if (feature_infos[i].tag != feature_infos[j].tag)
 	feature_infos[++j] = feature_infos[i];
       else {
 	if (feature_infos[i].flags & F_GLOBAL) {
 	  feature_infos[j].flags |= F_GLOBAL;
 	  feature_infos[j].max_value = feature_infos[i].max_value;
@@ -161,17 +178,18 @@ hb_ot_map_builder_t::compile (hb_ot_map_
 	feature_infos[j].stage[1] = MIN (feature_infos[j].stage[1], feature_infos[i].stage[1]);
       }
     feature_infos.shrink (j + 1);
   }
 
 
   /* Allocate bits now */
   unsigned int next_bit = 1;
-  for (unsigned int i = 0; i < feature_infos.len; i++) {
+  for (unsigned int i = 0; i < feature_infos.len; i++)
+  {
     const feature_info_t *info = &feature_infos[i];
 
     unsigned int bits_needed;
 
     if ((info->flags & F_GLOBAL) && info->max_value == 1)
       /* Uses the global bit */
       bits_needed = 0;
     else
@@ -179,22 +197,30 @@ hb_ot_map_builder_t::compile (hb_ot_map_
 
     if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
       continue; /* Feature disabled, or not enough bits. */
 
 
     hb_bool_t found = false;
     unsigned int feature_index[2];
     for (unsigned int table_index = 0; table_index < 2; table_index++)
+    {
+      if (required_feature_tag[table_index] == info->tag)
+      {
+	required_feature_stage[table_index] = info->stage[table_index];
+	found = true;
+	continue;
+      }
       found |= hb_ot_layout_language_find_feature (face,
 						   table_tags[table_index],
 						   script_index[table_index],
 						   language_index[table_index],
 						   info->tag,
 						   &feature_index[table_index]);
+    }
     if (!found && !(info->flags & F_HAS_FALLBACK))
       continue;
 
 
     hb_ot_map_t::feature_map_t *map = m.features.push ();
     if (unlikely (!map))
       break;
 
@@ -219,44 +245,42 @@ hb_ot_map_builder_t::compile (hb_ot_map_
 
   }
   feature_infos.shrink (0); /* Done with these */
 
 
   add_gsub_pause (NULL);
   add_gpos_pause (NULL);
 
-  for (unsigned int table_index = 0; table_index < 2; table_index++) {
-    hb_tag_t table_tag = table_tags[table_index];
-
+  for (unsigned int table_index = 0; table_index < 2; table_index++)
+  {
     /* Collect lookup indices for features */
 
-    unsigned int required_feature_index;
-    if (hb_ot_layout_language_get_required_feature_index (face,
-							  table_tag,
-							  script_index[table_index],
-							  language_index[table_index],
-							  &required_feature_index))
-      m.add_lookups (face, table_index, required_feature_index, 1, true);
-
     unsigned int stage_index = 0;
     unsigned int last_num_lookups = 0;
     for (unsigned stage = 0; stage < current_stage[table_index]; stage++)
     {
+      if (required_feature_index[table_index] != HB_OT_LAYOUT_NO_FEATURE_INDEX &&
+	  required_feature_stage[table_index] == stage)
+	m.add_lookups (face, table_index,
+		       required_feature_index[table_index],
+		       1 /* mask */,
+		       true /* auto_zwj */);
+
       for (unsigned i = 0; i < m.features.len; i++)
         if (m.features[i].stage[table_index] == stage)
 	  m.add_lookups (face, table_index,
 			 m.features[i].index[table_index],
 			 m.features[i].mask,
 			 m.features[i].auto_zwj);
 
       /* Sort lookups and merge duplicates */
       if (last_num_lookups < m.lookups[table_index].len)
       {
-	m.lookups[table_index].sort (last_num_lookups, m.lookups[table_index].len);
+	m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].len);
 
 	unsigned int j = last_num_lookups;
 	for (unsigned int i = j + 1; i < m.lookups[table_index].len; i++)
 	  if (m.lookups[table_index][i].index != m.lookups[table_index][j].index)
 	    m.lookups[table_index][++j] = m.lookups[table_index][i];
 	  else
 	  {
 	    m.lookups[table_index][j].mask |= m.lookups[table_index][i].mask;
--- a/gfx/harfbuzz/src/hb-ot-maxp-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-maxp-table.hh
@@ -45,23 +45,23 @@ struct maxp
 
   inline unsigned int get_num_glyphs (void) const {
     return numGlyphs;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) {
     TRACE_SANITIZE (this);
     return TRACE_RETURN (c->check_struct (this) &&
-			 likely (version.major == 1 || (version.major == 0 && version.minor == 0x5000)));
+			 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),
-					 * 0x00005000 or 0x00010000. */
+					 * 0x00005000u or 0x00010000u. */
   USHORT	numGlyphs;		/* The number of glyphs in the font. */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
 
 } /* namespace OT */
 
--- a/gfx/harfbuzz/src/hb-ot-name-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-name-table.hh
@@ -116,17 +116,17 @@ struct name
 			 likely (format == 0 || format == 1) &&
 			 c->check_array (nameRecord, nameRecord[0].static_size, count) &&
 			 sanitize_records (c));
   }
 
   /* We only implement format 0 for now. */
   USHORT	format;			/* Format selector (=0/1). */
   USHORT	count;			/* Number of name records. */
-  Offset	stringOffset;		/* Offset to start of string storage (from start of table). */
+  Offset<>	stringOffset;		/* Offset to start of string storage (from start of table). */
   NameRecord	nameRecord[VAR];	/* The name records where count is the number of records. */
   public:
   DEFINE_SIZE_ARRAY (6, nameRecord);
 };
 
 
 } /* namespace OT */
 
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh
@@ -28,35 +28,27 @@
 #define HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH
 
 #include "hb-private.hh"
 
 #include "hb-ot-shape-private.hh"
 #include "hb-ot-layout-gsub-table.hh"
 
 
+/* Features ordered the same as the entries in shaping_table rows,
+ * followed by rlig.  Don't change. */
 static const hb_tag_t arabic_fallback_features[] =
 {
   HB_TAG('i','n','i','t'),
   HB_TAG('m','e','d','i'),
   HB_TAG('f','i','n','a'),
   HB_TAG('i','s','o','l'),
   HB_TAG('r','l','i','g'),
 };
 
-/* Same order as the fallback feature array */
-enum {
-  FALLBACK_INIT,
-  FALLBACK_MEDI,
-  FALLBACK_FINA,
-  FALLBACK_ISOL,
-  FALLBACK_RLIG,
-  ARABIC_NUM_FALLBACK_FEATURES
-};
-
 static OT::SubstLookup *
 arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUSED,
 					  hb_font_t *font,
 					  unsigned int feature_index)
 {
   OT::GlyphID glyphs[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1];
   OT::GlyphID substitutes[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1];
   unsigned int num_glyphs = 0;
@@ -66,25 +58,28 @@ arabic_fallback_synthesize_lookup_single
   {
     hb_codepoint_t s = shaping_table[u - SHAPING_TABLE_FIRST][feature_index];
     hb_codepoint_t u_glyph, s_glyph;
 
     if (!s ||
 	!hb_font_get_glyph (font, u, 0, &u_glyph) ||
 	!hb_font_get_glyph (font, s, 0, &s_glyph) ||
 	u_glyph == s_glyph ||
-	u_glyph > 0xFFFF || s_glyph > 0xFFFF)
+	u_glyph > 0xFFFFu || s_glyph > 0xFFFFu)
       continue;
 
     glyphs[num_glyphs].set (u_glyph);
     substitutes[num_glyphs].set (s_glyph);
 
     num_glyphs++;
   }
 
+  if (!num_glyphs)
+    return NULL;
+
   /* Bubble-sort!
    * May not be good-enough for presidential candidate interviews, but good-enough for us... */
   hb_bubble_sort (&glyphs[0], num_glyphs, OT::GlyphID::cmp, &substitutes[0]);
 
   OT::Supplier<OT::GlyphID> glyphs_supplier      (glyphs, num_glyphs);
   OT::Supplier<OT::GlyphID> substitutes_supplier (substitutes, num_glyphs);
 
   /* Each glyph takes four bytes max, and there's some overhead. */
@@ -152,16 +147,19 @@ arabic_fallback_synthesize_lookup_ligatu
 
       ligature_list[num_ligatures].set (ligature_glyph);
       component_count_list[num_ligatures] = 2;
       component_list[num_ligatures].set (second_glyph);
       num_ligatures++;
     }
   }
 
+  if (!num_ligatures)
+    return NULL;
+
   OT::Supplier<OT::GlyphID>   first_glyphs_supplier                      (first_glyphs, num_first_glyphs);
   OT::Supplier<unsigned int > ligature_per_first_glyph_count_supplier    (ligature_per_first_glyph_count_list, num_first_glyphs);
   OT::Supplier<OT::GlyphID>   ligatures_supplier                         (ligature_list, num_ligatures);
   OT::Supplier<unsigned int > component_count_supplier                   (component_count_list, num_ligatures);
   OT::Supplier<OT::GlyphID>   component_supplier                         (component_list, num_ligatures);
 
   /* 16 bytes per ligature ought to be enough... */
   char buf[ARRAY_LENGTH_CONST (ligature_list) * 16 + 128];
@@ -188,71 +186,167 @@ arabic_fallback_synthesize_lookup (const
 				   unsigned int feature_index)
 {
   if (feature_index < 4)
     return arabic_fallback_synthesize_lookup_single (plan, font, feature_index);
   else
     return arabic_fallback_synthesize_lookup_ligature (plan, font);
 }
 
+#define ARABIC_FALLBACK_MAX_LOOKUPS 5
+
 struct arabic_fallback_plan_t
 {
   ASSERT_POD ();
 
-  hb_mask_t mask_array[ARABIC_NUM_FALLBACK_FEATURES];
-  OT::SubstLookup *lookup_array[ARABIC_NUM_FALLBACK_FEATURES];
-  hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_NUM_FALLBACK_FEATURES];
+  unsigned int num_lookups;
+  bool free_lookups;
+
+  hb_mask_t mask_array[ARABIC_FALLBACK_MAX_LOOKUPS];
+  OT::SubstLookup *lookup_array[ARABIC_FALLBACK_MAX_LOOKUPS];
+  hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
 };
 
 static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
 
+#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_WITH_WIN1256)
+#define HB_WITH_WIN1256
+#endif
+
+#ifdef HB_WITH_WIN1256
+#include "hb-ot-shape-complex-arabic-win1256.hh"
+#endif
+
+struct ManifestLookup {
+  OT::Tag tag;
+  OT::OffsetTo<OT::SubstLookup> lookupOffset;
+};
+typedef OT::ArrayOf<ManifestLookup> Manifest;
+
+static bool
+arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan,
+				   const hb_ot_shape_plan_t *plan,
+				   hb_font_t *font)
+{
+#ifdef HB_WITH_WIN1256
+  /* Does this font look like it's Windows-1256-encoded? */
+  hb_codepoint_t g;
+  if (!(hb_font_get_glyph (font, 0x0627u, 0, &g) && g == 199 /* ALEF */ &&
+	hb_font_get_glyph (font, 0x0644u, 0, &g) && g == 225 /* LAM */ &&
+	hb_font_get_glyph (font, 0x0649u, 0, &g) && g == 236 /* ALEF MAKSURA */ &&
+	hb_font_get_glyph (font, 0x064Au, 0, &g) && g == 237 /* YEH */ &&
+	hb_font_get_glyph (font, 0x0652u, 0, &g) && g == 250 /* SUKUN */))
+    return false;
+
+  const Manifest &manifest = reinterpret_cast<const Manifest&> (arabic_win1256_gsub_lookups.manifest);
+  ASSERT_STATIC (sizeof (arabic_win1256_gsub_lookups.manifestData) / sizeof (ManifestLookup)
+		 <= ARABIC_FALLBACK_MAX_LOOKUPS);
+  /* TODO sanitize the table? */
+
+  unsigned j = 0;
+  unsigned int count = manifest.len;
+  for (unsigned int i = 0; i < count; i++)
+  {
+    fallback_plan->mask_array[j] = plan->map.get_1_mask (manifest[i].tag);
+    if (fallback_plan->mask_array[j])
+    {
+      fallback_plan->lookup_array[j] = const_cast<OT::SubstLookup*> (&(&manifest+manifest[i].lookupOffset));
+      if (fallback_plan->lookup_array[j])
+      {
+	fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]);
+	j++;
+      }
+    }
+  }
+
+  fallback_plan->num_lookups = j;
+  fallback_plan->free_lookups = false;
+
+  return j > 0;
+#else
+  return false;
+#endif
+}
+
+static bool
+arabic_fallback_plan_init_unicode (arabic_fallback_plan_t *fallback_plan,
+				   const hb_ot_shape_plan_t *plan,
+				   hb_font_t *font)
+{
+  ASSERT_STATIC (ARRAY_LENGTH_CONST(arabic_fallback_features) <= ARABIC_FALLBACK_MAX_LOOKUPS);
+  unsigned int j = 0;
+  for (unsigned int i = 0; i < ARRAY_LENGTH(arabic_fallback_features) ; i++)
+  {
+    fallback_plan->mask_array[j] = plan->map.get_1_mask (arabic_fallback_features[i]);
+    if (fallback_plan->mask_array[j])
+    {
+      fallback_plan->lookup_array[j] = arabic_fallback_synthesize_lookup (plan, font, i);
+      if (fallback_plan->lookup_array[j])
+      {
+	fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]);
+	j++;
+      }
+    }
+  }
+
+  fallback_plan->num_lookups = j;
+  fallback_plan->free_lookups = true;
+
+  return j > 0;
+}
+
 static arabic_fallback_plan_t *
 arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
 			     hb_font_t *font)
 {
   arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) calloc (1, sizeof (arabic_fallback_plan_t));
   if (unlikely (!fallback_plan))
     return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
 
-  for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++)
-  {
-    fallback_plan->mask_array[i] = plan->map.get_1_mask (arabic_fallback_features[i]);
-    if (fallback_plan->mask_array[i]) {
-      fallback_plan->lookup_array[i] = arabic_fallback_synthesize_lookup (plan, font, i);
-      if (fallback_plan->lookup_array[i])
-	fallback_plan->accel_array[i].init (*fallback_plan->lookup_array[i]);
-    }
-  }
+  fallback_plan->num_lookups = 0;
+  fallback_plan->free_lookups = false;
+
+  /* Try synthesizing GSUB table using Unicode Arabic Presentation Forms,
+   * in case the font has cmap entries for the presentation-forms characters. */
+  if (arabic_fallback_plan_init_unicode (fallback_plan, plan, font))
+    return fallback_plan;
 
-  return fallback_plan;
+  /* See if this looks like a Windows-1256-encoded font.  If it does, use a
+   * hand-coded GSUB table. */
+  if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font))
+    return fallback_plan;
+
+  free (fallback_plan);
+  return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
 }
 
 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 < ARABIC_NUM_FALLBACK_FEATURES; i++)
+  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]);
-      free (fallback_plan->lookup_array[i]);
+      if (fallback_plan->free_lookups)
+	free (fallback_plan->lookup_array[i]);
     }
 
   free (fallback_plan);
 }
 
 static void
 arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan,
 			    hb_font_t *font,
 			    hb_buffer_t *buffer)
 {
   OT::hb_apply_context_t c (0, font, buffer);
-  for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++)
+  for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
     if (fallback_plan->lookup_array[i]) {
       c.set_lookup_mask (fallback_plan->mask_array[i]);
       hb_ot_layout_substitute_lookup (&c,
 				      *fallback_plan->lookup_array[i],
 				      fallback_plan->accel_array[i]);
     }
 }
 
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh
@@ -1,942 +1,383 @@
 /* == Start of generated table == */
 /*
  * The following table is generated by running:
  *
- *   ./gen-arabic-table.py ArabicShaping.txt UnicodeData.txt
+ *   ./gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt
  *
  * on files with these headers:
  *
- * # ArabicShaping-6.2.0.txt
- * # Date: 2012-05-15, 21:05:00 GMT [KW]
+ * # ArabicShaping-7.0.0.txt
+ * # Date: 2014-02-14, 21:00:00 GMT [RP, KW, LI]
+ * # Blocks-7.0.0.txt
+ * # Date: 2014-04-03, 23:23:00 GMT [RP, KW]
  * UnicodeData.txt does not have a header.
  */
 
 #ifndef HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
 #define HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
 
 
+#define X	JOINING_TYPE_X
+#define R	JOINING_TYPE_R
+#define U	JOINING_TYPE_U
+#define A	JOINING_GROUP_ALAPH
+#define DR	JOINING_GROUP_DALATH_RISH
+#define L	JOINING_TYPE_L
+#define C	JOINING_TYPE_C
+#define D	JOINING_TYPE_D
+
 static const uint8_t joining_table[] =
 {
 
-  /* Arabic Characters */
+#define joining_offset_0x0600u 0
+
+  /* Arabic */
+
+  /* 0600 */ U,U,U,U,U,U,X,X,U,X,X,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+  /* 0620 */ D,U,R,R,R,R,D,R,D,R,D,D,D,D,D,R,R,R,R,D,D,D,D,D,D,D,D,D,D,D,D,D,
+  /* 0640 */ C,D,D,D,D,D,D,D,R,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+  /* 0660 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,D,D,X,R,R,R,U,R,R,R,D,D,D,D,D,D,D,D,
+  /* 0680 */ D,D,D,D,D,D,D,D,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,D,D,D,D,D,D,
+  /* 06A0 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+  /* 06C0 */ R,D,D,R,R,R,R,R,R,R,R,R,D,R,D,R,D,D,R,R,X,R,X,X,X,X,X,X,X,U,X,X,
+  /* 06E0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,R,R,X,X,X,X,X,X,X,X,X,X,D,D,D,X,X,D,
+
+  /* Syriac */
+
+  /* 0700 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,A,X,D,D,D,DR,DR,R,R,R,D,D,D,D,R,D,
+  /* 0720 */ D,D,D,D,D,D,D,D,R,D,DR,D,R,D,D,DR,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+  /* 0740 */ X,X,X,X,X,X,X,X,X,X,X,X,X,R,D,D,
+
+  /* Arabic Supplement */
+
+  /* 0740 */                                 D,D,D,D,D,D,D,D,D,R,R,R,D,D,D,D,
+  /* 0760 */ D,D,D,D,D,D,D,D,D,D,D,R,R,D,D,D,D,R,D,R,R,D,D,D,R,R,D,D,D,D,D,D,
+
+  /* FILLER */
+
+  /* 0780 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+  /* 07A0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+
+  /* NKo */
+
+  /* 07C0 */ X,X,X,X,X,X,X,X,X,X,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+  /* 07E0 */ D,D,D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,C,X,X,X,X,X,
 
-  JOINING_TYPE_U, /* 0600; ARABIC NUMBER SIGN; U; No_Joining_Group */
-  JOINING_TYPE_U, /* 0601; ARABIC SIGN SANAH; U; No_Joining_Group */
-  JOINING_TYPE_U, /* 0602; ARABIC FOOTNOTE MARKER; U; No_Joining_Group */
-  JOINING_TYPE_U, /* 0603; ARABIC SIGN SAFHA; U; No_Joining_Group */
-  JOINING_TYPE_U, /* 0604; ARABIC SIGN SAMVAT; U; No_Joining_Group */
-  JOINING_TYPE_X, /* 0605 */
-  JOINING_TYPE_X, /* 0606 */
-  JOINING_TYPE_X, /* 0607 */
-  JOINING_TYPE_U, /* 0608; ARABIC RAY; U; No_Joining_Group */
-  JOINING_TYPE_X, /* 0609 */
-  JOINING_TYPE_X, /* 060A */
-  JOINING_TYPE_U, /* 060B; AFGHANI SIGN; U; No_Joining_Group */
-  JOINING_TYPE_X, /* 060C */
-  JOINING_TYPE_X, /* 060D */
-  JOINING_TYPE_X, /* 060E */
-  JOINING_TYPE_X, /* 060F */
-  JOINING_TYPE_X, /* 0610 */
-  JOINING_TYPE_X, /* 0611 */
-  JOINING_TYPE_X, /* 0612 */
-  JOINING_TYPE_X, /* 0613 */
-  JOINING_TYPE_X, /* 0614 */
-  JOINING_TYPE_X, /* 0615 */
-  JOINING_TYPE_X, /* 0616 */
-  JOINING_TYPE_X, /* 0617 */
-  JOINING_TYPE_X, /* 0618 */
-  JOINING_TYPE_X, /* 0619 */
-  JOINING_TYPE_X, /* 061A */
-  JOINING_TYPE_X, /* 061B */
-  JOINING_TYPE_X, /* 061C */
-  JOINING_TYPE_X, /* 061D */
-  JOINING_TYPE_X, /* 061E */
-  JOINING_TYPE_X, /* 061F */
-  JOINING_TYPE_D, /* 0620; DOTLESS YEH WITH SEPARATE RING BELOW; D; YEH */
-  JOINING_TYPE_U, /* 0621; HAMZA; U; No_Joining_Group */
-  JOINING_TYPE_R, /* 0622; ALEF WITH MADDA ABOVE; R; ALEF */
-  JOINING_TYPE_R, /* 0623; ALEF WITH HAMZA ABOVE; R; ALEF */
-  JOINING_TYPE_R, /* 0624; WAW WITH HAMZA ABOVE; R; WAW */
-  JOINING_TYPE_R, /* 0625; ALEF WITH HAMZA BELOW; R; ALEF */
-  JOINING_TYPE_D, /* 0626; DOTLESS YEH WITH HAMZA ABOVE; D; YEH */
-  JOINING_TYPE_R, /* 0627; ALEF; R; ALEF */
-  JOINING_TYPE_D, /* 0628; BEH; D; BEH */
-  JOINING_TYPE_R, /* 0629; TEH MARBUTA; R; TEH MARBUTA */
-  JOINING_TYPE_D, /* 062A; DOTLESS BEH WITH 2 DOTS ABOVE; D; BEH */
-  JOINING_TYPE_D, /* 062B; DOTLESS BEH WITH 3 DOTS ABOVE; D; BEH */
-  JOINING_TYPE_D, /* 062C; HAH WITH DOT BELOW; D; HAH */
-  JOINING_TYPE_D, /* 062D; HAH; D; HAH */
-  JOINING_TYPE_D, /* 062E; HAH WITH DOT ABOVE; D; HAH */
-  JOINING_TYPE_R, /* 062F; DAL; R; DAL */
-  JOINING_TYPE_R, /* 0630; DAL WITH DOT ABOVE; R; DAL */
-  JOINING_TYPE_R, /* 0631; REH; R; REH */
-  JOINING_TYPE_R, /* 0632; REH WITH DOT ABOVE; R; REH */
-  JOINING_TYPE_D, /* 0633; SEEN; D; SEEN */
-  JOINING_TYPE_D, /* 0634; SEEN WITH 3 DOTS ABOVE; D; SEEN */
-  JOINING_TYPE_D, /* 0635; SAD; D; SAD */
-  JOINING_TYPE_D, /* 0636; SAD WITH DOT ABOVE; D; SAD */
-  JOINING_TYPE_D, /* 0637; TAH; D; TAH */
-  JOINING_TYPE_D, /* 0638; TAH WITH DOT ABOVE; D; TAH */
-  JOINING_TYPE_D, /* 0639; AIN; D; AIN */
-  JOINING_TYPE_D, /* 063A; AIN WITH DOT ABOVE; D; AIN */
-  JOINING_TYPE_D, /* 063B; KEHEH WITH 2 DOTS ABOVE; D; GAF */
-  JOINING_TYPE_D, /* 063C; KEHEH WITH 3 DOTS BELOW; D; GAF */
-  JOINING_TYPE_D, /* 063D; FARSI YEH WITH INVERTED V ABOVE; D; FARSI YEH */
-  JOINING_TYPE_D, /* 063E; FARSI YEH WITH 2 DOTS ABOVE; D; FARSI YEH */
-  JOINING_TYPE_D, /* 063F; FARSI YEH WITH 3 DOTS ABOVE; D; FARSI YEH */
-  JOINING_TYPE_C, /* 0640; TATWEEL; C; No_Joining_Group */
-  JOINING_TYPE_D, /* 0641; FEH; D; FEH */
-  JOINING_TYPE_D, /* 0642; QAF; D; QAF */
-  JOINING_TYPE_D, /* 0643; KAF; D; KAF */
-  JOINING_TYPE_D, /* 0644; LAM; D; LAM */
-  JOINING_TYPE_D, /* 0645; MEEM; D; MEEM */
-  JOINING_TYPE_D, /* 0646; NOON; D; NOON */
-  JOINING_TYPE_D, /* 0647; HEH; D; HEH */
-  JOINING_TYPE_R, /* 0648; WAW; R; WAW */
-  JOINING_TYPE_D, /* 0649; DOTLESS YEH; D; YEH */
-  JOINING_TYPE_D, /* 064A; YEH; D; YEH */
-  JOINING_TYPE_X, /* 064B */
-  JOINING_TYPE_X, /* 064C */
-  JOINING_TYPE_X, /* 064D */
-  JOINING_TYPE_X, /* 064E */
-  JOINING_TYPE_X, /* 064F */
-  JOINING_TYPE_X, /* 0650 */
-  JOINING_TYPE_X, /* 0651 */
-  JOINING_TYPE_X, /* 0652 */
-  JOINING_TYPE_X, /* 0653 */
-  JOINING_TYPE_X, /* 0654 */
-  JOINING_TYPE_X, /* 0655 */
-  JOINING_TYPE_X, /* 0656 */
-  JOINING_TYPE_X, /* 0657 */
-  JOINING_TYPE_X, /* 0658 */
-  JOINING_TYPE_X, /* 0659 */
-  JOINING_TYPE_X, /* 065A */
-  JOINING_TYPE_X, /* 065B */
-  JOINING_TYPE_X, /* 065C */
-  JOINING_TYPE_X, /* 065D */
-  JOINING_TYPE_X, /* 065E */
-  JOINING_TYPE_X, /* 065F */
-  JOINING_TYPE_X, /* 0660 */
-  JOINING_TYPE_X, /* 0661 */
-  JOINING_TYPE_X, /* 0662 */
-  JOINING_TYPE_X, /* 0663 */
-  JOINING_TYPE_X, /* 0664 */
-  JOINING_TYPE_X, /* 0665 */
-  JOINING_TYPE_X, /* 0666 */
-  JOINING_TYPE_X, /* 0667 */
-  JOINING_TYPE_X, /* 0668 */
-  JOINING_TYPE_X, /* 0669 */
-  JOINING_TYPE_X, /* 066A */
-  JOINING_TYPE_X, /* 066B */
-  JOINING_TYPE_X, /* 066C */
-  JOINING_TYPE_X, /* 066D */
-  JOINING_TYPE_D, /* 066E; DOTLESS BEH; D; BEH */
-  JOINING_TYPE_D, /* 066F; DOTLESS QAF; D; QAF */
-  JOINING_TYPE_X, /* 0670 */
-  JOINING_TYPE_R, /* 0671; ALEF WITH WASLA ABOVE; R; ALEF */
-  JOINING_TYPE_R, /* 0672; ALEF WITH WAVY HAMZA ABOVE; R; ALEF */
-  JOINING_TYPE_R, /* 0673; ALEF WITH WAVY HAMZA BELOW; R; ALEF */
-  JOINING_TYPE_U, /* 0674; HIGH HAMZA; U; No_Joining_Group */
-  JOINING_TYPE_R, /* 0675; HIGH HAMZA ALEF; R; ALEF */
-  JOINING_TYPE_R, /* 0676; HIGH HAMZA WAW; R; WAW */
-  JOINING_TYPE_R, /* 0677; HIGH HAMZA WAW WITH DAMMA ABOVE; R; WAW */
-  JOINING_TYPE_D, /* 0678; HIGH HAMZA DOTLESS YEH; D; YEH */
-  JOINING_TYPE_D, /* 0679; DOTLESS BEH WITH TAH ABOVE; D; BEH */
-  JOINING_TYPE_D, /* 067A; DOTLESS BEH WITH VERTICAL 2 DOTS ABOVE; D; BEH */
-  JOINING_TYPE_D, /* 067B; DOTLESS BEH WITH VERTICAL 2 DOTS BELOW; D; BEH */
-  JOINING_TYPE_D, /* 067C; DOTLESS BEH WITH ATTACHED RING BELOW AND 2 DOTS ABOVE; D; BEH */
-  JOINING_TYPE_D, /* 067D; DOTLESS BEH WITH INVERTED 3 DOTS ABOVE; D; BEH */
-  JOINING_TYPE_D, /* 067E; DOTLESS BEH WITH 3 DOTS BELOW; D; BEH */
-  JOINING_TYPE_D, /* 067F; DOTLESS BEH WITH 4 DOTS ABOVE; D; BEH */
-  JOINING_TYPE_D, /* 0680; DOTLESS BEH WITH 4 DOTS BELOW; D; BEH */
-  JOINING_TYPE_D, /* 0681; HAH WITH HAMZA ABOVE; D; HAH */
-  JOINING_TYPE_D, /* 0682; HAH WITH VERTICAL 2 DOTS ABOVE; D; HAH */
-  JOINING_TYPE_D, /* 0683; HAH WITH 2 DOTS BELOW; D; HAH */
-  JOINING_TYPE_D, /* 0684; HAH WITH VERTICAL 2 DOTS BELOW; D; HAH */
-  JOINING_TYPE_D, /* 0685; HAH WITH 3 DOTS ABOVE; D; HAH */
-  JOINING_TYPE_D, /* 0686; HAH WITH 3 DOTS BELOW; D; HAH */
-  JOINING_TYPE_D, /* 0687; HAH WITH 4 DOTS BELOW; D; HAH */
-  JOINING_TYPE_R, /* 0688; DAL WITH TAH ABOVE; R; DAL */
-  JOINING_TYPE_R, /* 0689; DAL WITH ATTACHED RING BELOW; R; DAL */
-  JOINING_TYPE_R, /* 068A; DAL WITH DOT BELOW; R; DAL */
-  JOINING_TYPE_R, /* 068B; DAL WITH DOT BELOW AND TAH ABOVE; R; DAL */
-  JOINING_TYPE_R, /* 068C; DAL WITH 2 DOTS ABOVE; R; DAL */
-  JOINING_TYPE_R, /* 068D; DAL WITH 2 DOTS BELOW; R; DAL */
-  JOINING_TYPE_R, /* 068E; DAL WITH 3 DOTS ABOVE; R; DAL */
-  JOINING_TYPE_R, /* 068F; DAL WITH INVERTED 3 DOTS ABOVE; R; DAL */
-  JOINING_TYPE_R, /* 0690; DAL WITH 4 DOTS ABOVE; R; DAL */
-  JOINING_TYPE_R, /* 0691; REH WITH TAH ABOVE; R; REH */
-  JOINING_TYPE_R, /* 0692; REH WITH V ABOVE; R; REH */
-  JOINING_TYPE_R, /* 0693; REH WITH ATTACHED RING BELOW; R; REH */
-  JOINING_TYPE_R, /* 0694; REH WITH DOT BELOW; R; REH */
-  JOINING_TYPE_R, /* 0695; REH WITH V BELOW; R; REH */
-  JOINING_TYPE_R, /* 0696; REH WITH DOT BELOW AND DOT WITHIN; R; REH */
-  JOINING_TYPE_R, /* 0697; REH WITH 2 DOTS ABOVE; R; REH */
-  JOINING_TYPE_R, /* 0698; REH WITH 3 DOTS ABOVE; R; REH */
-  JOINING_TYPE_R, /* 0699; REH WITH 4 DOTS ABOVE; R; REH */
-  JOINING_TYPE_D, /* 069A; SEEN WITH DOT BELOW AND DOT ABOVE; D; SEEN */
-  JOINING_TYPE_D, /* 069B; SEEN WITH 3 DOTS BELOW; D; SEEN */
-  JOINING_TYPE_D, /* 069C; SEEN WITH 3 DOTS BELOW AND 3 DOTS ABOVE; D; SEEN */
-  JOINING_TYPE_D, /* 069D; SAD WITH 2 DOTS BELOW; D; SAD */
-  JOINING_TYPE_D, /* 069E; SAD WITH 3 DOTS ABOVE; D; SAD */
-  JOINING_TYPE_D, /* 069F; TAH WITH 3 DOTS ABOVE; D; TAH */
-  JOINING_TYPE_D, /* 06A0; AIN WITH 3 DOTS ABOVE; D; AIN */
-  JOINING_TYPE_D, /* 06A1; DOTLESS FEH; D; FEH */
-  JOINING_TYPE_D, /* 06A2; DOTLESS FEH WITH DOT BELOW; D; FEH */
-  JOINING_TYPE_D, /* 06A3; FEH WITH DOT BELOW; D; FEH */
-  JOINING_TYPE_D, /* 06A4; DOTLESS FEH WITH 3 DOTS ABOVE; D; FEH */
-  JOINING_TYPE_D, /* 06A5; DOTLESS FEH WITH 3 DOTS BELOW; D; FEH */
-  JOINING_TYPE_D, /* 06A6; DOTLESS FEH WITH 4 DOTS ABOVE; D; FEH */
-  JOINING_TYPE_D, /* 06A7; DOTLESS QAF WITH DOT ABOVE; D; QAF */
-  JOINING_TYPE_D, /* 06A8; DOTLESS QAF WITH 3 DOTS ABOVE; D; QAF */
-  JOINING_TYPE_D, /* 06A9; KEHEH; D; GAF */
-  JOINING_TYPE_D, /* 06AA; SWASH KAF; D; SWASH KAF */
-  JOINING_TYPE_D, /* 06AB; KEHEH WITH ATTACHED RING BELOW; D; GAF */
-  JOINING_TYPE_D, /* 06AC; KAF WITH DOT ABOVE; D; KAF */
-  JOINING_TYPE_D, /* 06AD; KAF WITH 3 DOTS ABOVE; D; KAF */
-  JOINING_TYPE_D, /* 06AE; KAF WITH 3 DOTS BELOW; D; KAF */
-  JOINING_TYPE_D, /* 06AF; GAF; D; GAF */
-  JOINING_TYPE_D, /* 06B0; GAF WITH ATTACHED RING BELOW; D; GAF */
-  JOINING_TYPE_D, /* 06B1; GAF WITH 2 DOTS ABOVE; D; GAF */
-  JOINING_TYPE_D, /* 06B2; GAF WITH 2 DOTS BELOW; D; GAF */
-  JOINING_TYPE_D, /* 06B3; GAF WITH VERTICAL 2 DOTS BELOW; D; GAF */
-  JOINING_TYPE_D, /* 06B4; GAF WITH 3 DOTS ABOVE; D; GAF */
-  JOINING_TYPE_D, /* 06B5; LAM WITH V ABOVE; D; LAM */
-  JOINING_TYPE_D, /* 06B6; LAM WITH DOT ABOVE; D; LAM */
-  JOINING_TYPE_D, /* 06B7; LAM WITH 3 DOTS ABOVE; D; LAM */
-  JOINING_TYPE_D, /* 06B8; LAM WITH 3 DOTS BELOW; D; LAM */
-  JOINING_TYPE_D, /* 06B9; NOON WITH DOT BELOW; D; NOON */
-  JOINING_TYPE_D, /* 06BA; DOTLESS NOON; D; NOON */
-  JOINING_TYPE_D, /* 06BB; DOTLESS NOON WITH TAH ABOVE; D; NOON */
-  JOINING_TYPE_D, /* 06BC; NOON WITH ATTACHED RING BELOW; D; NOON */
-  JOINING_TYPE_D, /* 06BD; NYA; D; NYA */
-  JOINING_TYPE_D, /* 06BE; KNOTTED HEH; D; KNOTTED HEH */
-  JOINING_TYPE_D, /* 06BF; HAH WITH 3 DOTS BELOW AND DOT ABOVE; D; HAH */
-  JOINING_TYPE_R, /* 06C0; DOTLESS TEH MARBUTA WITH HAMZA ABOVE; R; TEH MARBUTA */
-  JOINING_TYPE_D, /* 06C1; HEH GOAL; D; HEH GOAL */
-  JOINING_TYPE_D, /* 06C2; HEH GOAL WITH HAMZA ABOVE; D; HEH GOAL */
-  JOINING_TYPE_R, /* 06C3; TEH MARBUTA GOAL; R; TEH MARBUTA GOAL */
-  JOINING_TYPE_R, /* 06C4; WAW WITH ATTACHED RING WITHIN; R; WAW */
-  JOINING_TYPE_R, /* 06C5; WAW WITH BAR; R; WAW */
-  JOINING_TYPE_R, /* 06C6; WAW WITH V ABOVE; R; WAW */
-  JOINING_TYPE_R, /* 06C7; WAW WITH DAMMA ABOVE; R; WAW */
-  JOINING_TYPE_R, /* 06C8; WAW WITH ALEF ABOVE; R; WAW */
-  JOINING_TYPE_R, /* 06C9; WAW WITH INVERTED V ABOVE; R; WAW */
-  JOINING_TYPE_R, /* 06CA; WAW WITH 2 DOTS ABOVE; R; WAW */
-  JOINING_TYPE_R, /* 06CB; WAW WITH 3 DOTS ABOVE; R; WAW */
-  JOINING_TYPE_D, /* 06CC; FARSI YEH; D; FARSI YEH */
-  JOINING_TYPE_R, /* 06CD; YEH WITH TAIL; R; YEH WITH TAIL */
-  JOINING_TYPE_D, /* 06CE; FARSI YEH WITH V ABOVE; D; FARSI YEH */
-  JOINING_TYPE_R, /* 06CF; WAW WITH DOT ABOVE; R; WAW */
-  JOINING_TYPE_D, /* 06D0; DOTLESS YEH WITH VERTICAL 2 DOTS BELOW; D; YEH */
-  JOINING_TYPE_D, /* 06D1; DOTLESS YEH WITH 3 DOTS BELOW; D; YEH */
-  JOINING_TYPE_R, /* 06D2; YEH BARREE; R; YEH BARREE */
-  JOINING_TYPE_R, /* 06D3; YEH BARREE WITH HAMZA ABOVE; R; YEH BARREE */
-  JOINING_TYPE_X, /* 06D4 */
-  JOINING_TYPE_R, /* 06D5; DOTLESS TEH MARBUTA; R; TEH MARBUTA */
-  JOINING_TYPE_X, /* 06D6 */
-  JOINING_TYPE_X, /* 06D7 */
-  JOINING_TYPE_X, /* 06D8 */
-  JOINING_TYPE_X, /* 06D9 */
-  JOINING_TYPE_X, /* 06DA */
-  JOINING_TYPE_X, /* 06DB */
-  JOINING_TYPE_X, /* 06DC */
-  JOINING_TYPE_U, /* 06DD; ARABIC END OF AYAH; U; No_Joining_Group */
-  JOINING_TYPE_X, /* 06DE */
-  JOINING_TYPE_X, /* 06DF */
-  JOINING_TYPE_X, /* 06E0 */
-  JOINING_TYPE_X, /* 06E1 */
-  JOINING_TYPE_X, /* 06E2 */
-  JOINING_TYPE_X, /* 06E3 */
-  JOINING_TYPE_X, /* 06E4 */
-  JOINING_TYPE_X, /* 06E5 */
-  JOINING_TYPE_X, /* 06E6 */
-  JOINING_TYPE_X, /* 06E7 */
-  JOINING_TYPE_X, /* 06E8 */
-  JOINING_TYPE_X, /* 06E9 */
-  JOINING_TYPE_X, /* 06EA */
-  JOINING_TYPE_X, /* 06EB */
-  JOINING_TYPE_X, /* 06EC */
-  JOINING_TYPE_X, /* 06ED */
-  JOINING_TYPE_R, /* 06EE; DAL WITH INVERTED V ABOVE; R; DAL */
-  JOINING_TYPE_R, /* 06EF; REH WITH INVERTED V ABOVE; R; REH */
-  JOINING_TYPE_X, /* 06F0 */
-  JOINING_TYPE_X, /* 06F1 */
-  JOINING_TYPE_X, /* 06F2 */
-  JOINING_TYPE_X, /* 06F3 */
-  JOINING_TYPE_X, /* 06F4 */
-  JOINING_TYPE_X, /* 06F5 */
-  JOINING_TYPE_X, /* 06F6 */
-  JOINING_TYPE_X, /* 06F7 */
-  JOINING_TYPE_X, /* 06F8 */
-  JOINING_TYPE_X, /* 06F9 */
-  JOINING_TYPE_D, /* 06FA; SEEN WITH DOT BELOW AND 3 DOTS ABOVE; D; SEEN */
-  JOINING_TYPE_D, /* 06FB; SAD WITH DOT BELOW AND DOT ABOVE; D; SAD */
-  JOINING_TYPE_D, /* 06FC; AIN WITH DOT BELOW AND DOT ABOVE; D; AIN */
-  JOINING_TYPE_X, /* 06FD */
-  JOINING_TYPE_X, /* 06FE */
-  JOINING_TYPE_D, /* 06FF; KNOTTED HEH WITH INVERTED V ABOVE; D; KNOTTED HEH */
+  /* FILLER */
+
+  /* 0800 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+  /* 0820 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+
+  /* Mandaic */
+
+  /* 0840 */ R,D,D,D,D,D,R,D,D,R,D,D,D,D,D,R,D,D,D,D,R,D,U,U,U,X,X,X,X,X,X,X,
+  /* 0860 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+  /* 0880 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+
+  /* Arabic Extended-A */
+
+  /* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,
+
+#define joining_offset_0x1806u 691
 
-  /* Syriac Characters */
+  /* Mongolian */
 
-  JOINING_TYPE_X, /* 0700 */
-  JOINING_TYPE_X, /* 0701 */
-  JOINING_TYPE_X, /* 0702 */
-  JOINING_TYPE_X, /* 0703 */
-  JOINING_TYPE_X, /* 0704 */
-  JOINING_TYPE_X, /* 0705 */
-  JOINING_TYPE_X, /* 0706 */
-  JOINING_TYPE_X, /* 0707 */
-  JOINING_TYPE_X, /* 0708 */
-  JOINING_TYPE_X, /* 0709 */
-  JOINING_TYPE_X, /* 070A */
-  JOINING_TYPE_X, /* 070B */
-  JOINING_TYPE_X, /* 070C */
-  JOINING_TYPE_X, /* 070D */
-  JOINING_TYPE_X, /* 070E */
-  JOINING_TYPE_X, /* 070F */
-  JOINING_GROUP_ALAPH, /* 0710; ALAPH; R; ALAPH */
-  JOINING_TYPE_X, /* 0711 */
-  JOINING_TYPE_D, /* 0712; BETH; D; BETH */
-  JOINING_TYPE_D, /* 0713; GAMAL; D; GAMAL */
-  JOINING_TYPE_D, /* 0714; GAMAL GARSHUNI; D; GAMAL */
-  JOINING_GROUP_DALATH_RISH, /* 0715; DALATH; R; DALATH RISH */
-  JOINING_GROUP_DALATH_RISH, /* 0716; DOTLESS DALATH RISH; R; DALATH RISH */
-  JOINING_TYPE_R, /* 0717; HE; R; HE */
-  JOINING_TYPE_R, /* 0718; WAW; R; SYRIAC WAW */
-  JOINING_TYPE_R, /* 0719; ZAIN; R; ZAIN */
-  JOINING_TYPE_D, /* 071A; HETH; D; HETH */
-  JOINING_TYPE_D, /* 071B; TETH; D; TETH */
-  JOINING_TYPE_D, /* 071C; TETH GARSHUNI; D; TETH */
-  JOINING_TYPE_D, /* 071D; YUDH; D; YUDH */
-  JOINING_TYPE_R, /* 071E; YUDH HE; R; YUDH HE */
-  JOINING_TYPE_D, /* 071F; KAPH; D; KAPH */
-  JOINING_TYPE_D, /* 0720; LAMADH; D; LAMADH */
-  JOINING_TYPE_D, /* 0721; MIM; D; MIM */
-  JOINING_TYPE_D, /* 0722; NUN; D; NUN */
-  JOINING_TYPE_D, /* 0723; SEMKATH; D; SEMKATH */
-  JOINING_TYPE_D, /* 0724; FINAL SEMKATH; D; FINAL SEMKATH */
-  JOINING_TYPE_D, /* 0725; E; D; E */
-  JOINING_TYPE_D, /* 0726; PE; D; PE */
-  JOINING_TYPE_D, /* 0727; REVERSED PE; D; REVERSED PE */
-  JOINING_TYPE_R, /* 0728; SADHE; R; SADHE */
-  JOINING_TYPE_D, /* 0729; QAPH; D; QAPH */
-  JOINING_GROUP_DALATH_RISH, /* 072A; RISH; R; DALATH RISH */
-  JOINING_TYPE_D, /* 072B; SHIN; D; SHIN */
-  JOINING_TYPE_R, /* 072C; TAW; R; TAW */
-  JOINING_TYPE_D, /* 072D; PERSIAN BHETH; D; BETH */
-  JOINING_TYPE_D, /* 072E; PERSIAN GHAMAL; D; GAMAL */
-  JOINING_GROUP_DALATH_RISH, /* 072F; PERSIAN DHALATH; R; DALATH RISH */
-  JOINING_TYPE_X, /* 0730 */
-  JOINING_TYPE_X, /* 0731 */
-  JOINING_TYPE_X, /* 0732 */
-  JOINING_TYPE_X, /* 0733 */
-  JOINING_TYPE_X, /* 0734 */
-  JOINING_TYPE_X, /* 0735 */
-  JOINING_TYPE_X, /* 0736 */
-  JOINING_TYPE_X, /* 0737 */
-  JOINING_TYPE_X, /* 0738 */
-  JOINING_TYPE_X, /* 0739 */
-  JOINING_TYPE_X, /* 073A */
-  JOINING_TYPE_X, /* 073B */
-  JOINING_TYPE_X, /* 073C */
-  JOINING_TYPE_X, /* 073D */
-  JOINING_TYPE_X, /* 073E */
-  JOINING_TYPE_X, /* 073F */
-  JOINING_TYPE_X, /* 0740 */
-  JOINING_TYPE_X, /* 0741 */
-  JOINING_TYPE_X, /* 0742 */
-  JOINING_TYPE_X, /* 0743 */
-  JOINING_TYPE_X, /* 0744 */
-  JOINING_TYPE_X, /* 0745 */
-  JOINING_TYPE_X, /* 0746 */
-  JOINING_TYPE_X, /* 0747 */
-  JOINING_TYPE_X, /* 0748 */
-  JOINING_TYPE_X, /* 0749 */
-  JOINING_TYPE_X, /* 074A */
-  JOINING_TYPE_X, /* 074B */
-  JOINING_TYPE_X, /* 074C */
-  JOINING_TYPE_R, /* 074D; SOGDIAN ZHAIN; R; ZHAIN */
-  JOINING_TYPE_D, /* 074E; SOGDIAN KHAPH; D; KHAPH */
-  JOINING_TYPE_D, /* 074F; SOGDIAN FE; D; FE */
+  /* 1800 */             U,D,X,X,C,X,X,X,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+  /* 1820 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+  /* 1840 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+  /* 1860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,
+  /* 1880 */ U,U,U,U,U,U,U,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+  /* 18A0 */ D,D,D,D,D,D,D,D,D,X,D,
 
-  /* Arabic Supplement Characters */
+#define joining_offset_0x200cu 856
+
+  /* General Punctuation */
+
+  /* 2000 */                         U,C,
+
+#define joining_offset_0x2066u 858
 
-  JOINING_TYPE_D, /* 0750; DOTLESS BEH WITH HORIZONTAL 3 DOTS BELOW; D; BEH */
-  JOINING_TYPE_D, /* 0751; BEH WITH 3 DOTS ABOVE; D; BEH */
-  JOINING_TYPE_D, /* 0752; DOTLESS BEH WITH INVERTED 3 DOTS BELOW; D; BEH */
-  JOINING_TYPE_D, /* 0753; DOTLESS BEH WITH INVERTED 3 DOTS BELOW AND 2 DOTS ABOVE; D; BEH */
-  JOINING_TYPE_D, /* 0754; DOTLESS BEH WITH 2 DOTS BELOW AND DOT ABOVE; D; BEH */
-  JOINING_TYPE_D, /* 0755; DOTLESS BEH WITH INVERTED V BELOW; D; BEH */
-  JOINING_TYPE_D, /* 0756; DOTLESS BEH WITH V ABOVE; D; BEH */
-  JOINING_TYPE_D, /* 0757; HAH WITH 2 DOTS ABOVE; D; HAH */
-  JOINING_TYPE_D, /* 0758; HAH WITH INVERTED 3 DOTS BELOW; D; HAH */
-  JOINING_TYPE_R, /* 0759; DAL WITH VERTICAL 2 DOTS BELOW AND TAH ABOVE; R; DAL */
-  JOINING_TYPE_R, /* 075A; DAL WITH INVERTED V BELOW; R; DAL */
-  JOINING_TYPE_R, /* 075B; REH WITH BAR; R; REH */
-  JOINING_TYPE_D, /* 075C; SEEN WITH 4 DOTS ABOVE; D; SEEN */
-  JOINING_TYPE_D, /* 075D; AIN WITH 2 DOTS ABOVE; D; AIN */
-  JOINING_TYPE_D, /* 075E; AIN WITH INVERTED 3 DOTS ABOVE; D; AIN */
-  JOINING_TYPE_D, /* 075F; AIN WITH VERTICAL 2 DOTS ABOVE; D; AIN */
-  JOINING_TYPE_D, /* 0760; DOTLESS FEH WITH 2 DOTS BELOW; D; FEH */
-  JOINING_TYPE_D, /* 0761; DOTLESS FEH WITH INVERTED 3 DOTS BELOW; D; FEH */
-  JOINING_TYPE_D, /* 0762; KEHEH WITH DOT ABOVE; D; GAF */
-  JOINING_TYPE_D, /* 0763; KEHEH WITH 3 DOTS ABOVE; D; GAF */
-  JOINING_TYPE_D, /* 0764; KEHEH WITH INVERTED 3 DOTS BELOW; D; GAF */
-  JOINING_TYPE_D, /* 0765; MEEM WITH DOT ABOVE; D; MEEM */
-  JOINING_TYPE_D, /* 0766; MEEM WITH DOT BELOW; D; MEEM */
-  JOINING_TYPE_D, /* 0767; NOON WITH 2 DOTS BELOW; D; NOON */
-  JOINING_TYPE_D, /* 0768; NOON WITH TAH ABOVE; D; NOON */
-  JOINING_TYPE_D, /* 0769; NOON WITH V ABOVE; D; NOON */
-  JOINING_TYPE_D, /* 076A; LAM WITH BAR; D; LAM */
-  JOINING_TYPE_R, /* 076B; REH WITH VERTICAL 2 DOTS ABOVE; R; REH */
-  JOINING_TYPE_R, /* 076C; REH WITH HAMZA ABOVE; R; REH */
-  JOINING_TYPE_D, /* 076D; SEEN WITH VERTICAL 2 DOTS ABOVE; D; SEEN */
-  JOINING_TYPE_D, /* 076E; HAH WITH TAH BELOW; D; HAH */
-  JOINING_TYPE_D, /* 076F; HAH WITH TAH AND 2 DOTS BELOW; D; HAH */
-  JOINING_TYPE_D, /* 0770; SEEN WITH 2 DOTS AND TAH ABOVE; D; SEEN */
-  JOINING_TYPE_R, /* 0771; REH WITH 2 DOTS AND TAH ABOVE; R; REH */
-  JOINING_TYPE_D, /* 0772; HAH WITH TAH ABOVE; D; HAH */
-  JOINING_TYPE_R, /* 0773; ALEF WITH DIGIT TWO ABOVE; R; ALEF */
-  JOINING_TYPE_R, /* 0774; ALEF WITH DIGIT THREE ABOVE; R; ALEF */
-  JOINING_TYPE_D, /* 0775; FARSI YEH WITH DIGIT TWO ABOVE; D; FARSI YEH */
-  JOINING_TYPE_D, /* 0776; FARSI YEH WITH DIGIT THREE ABOVE; D; FARSI YEH */
-  JOINING_TYPE_D, /* 0777; DOTLESS YEH WITH DIGIT FOUR BELOW; D; YEH */
-  JOINING_TYPE_R, /* 0778; WAW WITH DIGIT TWO ABOVE; R; WAW */
-  JOINING_TYPE_R, /* 0779; WAW WITH DIGIT THREE ABOVE; R; WAW */
-  JOINING_TYPE_D, /* 077A; BURUSHASKI YEH BARREE WITH DIGIT TWO ABOVE; D; BURUSHASKI YEH BARREE */
-  JOINING_TYPE_D, /* 077B; BURUSHASKI YEH BARREE WITH DIGIT THREE ABOVE; D; BURUSHASKI YEH BARREE */
-  JOINING_TYPE_D, /* 077C; HAH WITH DIGIT FOUR BELOW; D; HAH */
-  JOINING_TYPE_D, /* 077D; SEEN WITH DIGIT FOUR ABOVE; D; SEEN */
-  JOINING_TYPE_D, /* 077E; SEEN WITH INVERTED V ABOVE; D; SEEN */
-  JOINING_TYPE_D, /* 077F; KAF WITH 2 DOTS ABOVE; D; KAF */
+  /* General Punctuation */
+
+  /* 2060 */             U,U,U,U,
+
+#define joining_offset_0xa840u 862
 
-  /* N'Ko Characters */
+  /* Phags-pa */
+
+  /* A840 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+  /* A860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,L,U,
+
+#define joining_offset_0x10ac0u 914
 
-  JOINING_TYPE_X, /* 0780 */
-  JOINING_TYPE_X, /* 0781 */
-  JOINING_TYPE_X, /* 0782 */
-  JOINING_TYPE_X, /* 0783 */
-  JOINING_TYPE_X, /* 0784 */
-  JOINING_TYPE_X, /* 0785 */
-  JOINING_TYPE_X, /* 0786 */
-  JOINING_TYPE_X, /* 0787 */
-  JOINING_TYPE_X, /* 0788 */
-  JOINING_TYPE_X, /* 0789 */
-  JOINING_TYPE_X, /* 078A */
-  JOINING_TYPE_X, /* 078B */
-  JOINING_TYPE_X, /* 078C */
-  JOINING_TYPE_X, /* 078D */
-  JOINING_TYPE_X, /* 078E */
-  JOINING_TYPE_X, /* 078F */
-  JOINING_TYPE_X, /* 0790 */
-  JOINING_TYPE_X, /* 0791 */
-  JOINING_TYPE_X, /* 0792 */
-  JOINING_TYPE_X, /* 0793 */
-  JOINING_TYPE_X, /* 0794 */
-  JOINING_TYPE_X, /* 0795 */
-  JOINING_TYPE_X, /* 0796 */
-  JOINING_TYPE_X, /* 0797 */
-  JOINING_TYPE_X, /* 0798 */
-  JOINING_TYPE_X, /* 0799 */
-  JOINING_TYPE_X, /* 079A */
-  JOINING_TYPE_X, /* 079B */
-  JOINING_TYPE_X, /* 079C */
-  JOINING_TYPE_X, /* 079D */
-  JOINING_TYPE_X, /* 079E */
-  JOINING_TYPE_X, /* 079F */
-  JOINING_TYPE_X, /* 07A0 */
-  JOINING_TYPE_X, /* 07A1 */
-  JOINING_TYPE_X, /* 07A2 */
-  JOINING_TYPE_X, /* 07A3 */
-  JOINING_TYPE_X, /* 07A4 */
-  JOINING_TYPE_X, /* 07A5 */
-  JOINING_TYPE_X, /* 07A6 */
-  JOINING_TYPE_X, /* 07A7 */
-  JOINING_TYPE_X, /* 07A8 */
-  JOINING_TYPE_X, /* 07A9 */
-  JOINING_TYPE_X, /* 07AA */
-  JOINING_TYPE_X, /* 07AB */
-  JOINING_TYPE_X, /* 07AC */
-  JOINING_TYPE_X, /* 07AD */
-  JOINING_TYPE_X, /* 07AE */
-  JOINING_TYPE_X, /* 07AF */
-  JOINING_TYPE_X, /* 07B0 */
-  JOINING_TYPE_X, /* 07B1 */
-  JOINING_TYPE_X, /* 07B2 */
-  JOINING_TYPE_X, /* 07B3 */
-  JOINING_TYPE_X, /* 07B4 */
-  JOINING_TYPE_X, /* 07B5 */
-  JOINING_TYPE_X, /* 07B6 */
-  JOINING_TYPE_X, /* 07B7 */
-  JOINING_TYPE_X, /* 07B8 */
-  JOINING_TYPE_X, /* 07B9 */
-  JOINING_TYPE_X, /* 07BA */
-  JOINING_TYPE_X, /* 07BB */
-  JOINING_TYPE_X, /* 07BC */
-  JOINING_TYPE_X, /* 07BD */
-  JOINING_TYPE_X, /* 07BE */
-  JOINING_TYPE_X, /* 07BF */
-  JOINING_TYPE_X, /* 07C0 */
-  JOINING_TYPE_X, /* 07C1 */
-  JOINING_TYPE_X, /* 07C2 */
-  JOINING_TYPE_X, /* 07C3 */
-  JOINING_TYPE_X, /* 07C4 */
-  JOINING_TYPE_X, /* 07C5 */
-  JOINING_TYPE_X, /* 07C6 */
-  JOINING_TYPE_X, /* 07C7 */
-  JOINING_TYPE_X, /* 07C8 */
-  JOINING_TYPE_X, /* 07C9 */
-  JOINING_TYPE_D, /* 07CA; NKO A; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07CB; NKO EE; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07CC; NKO I; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07CD; NKO E; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07CE; NKO U; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07CF; NKO OO; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07D0; NKO O; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07D1; NKO DAGBASINNA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07D2; NKO N; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07D3; NKO BA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07D4; NKO PA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07D5; NKO TA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07D6; NKO JA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07D7; NKO CHA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07D8; NKO DA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07D9; NKO RA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07DA; NKO RRA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07DB; NKO SA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07DC; NKO GBA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07DD; NKO FA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07DE; NKO KA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07DF; NKO LA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07E0; NKO NA WOLOSO; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07E1; NKO MA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07E2; NKO NYA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07E3; NKO NA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07E4; NKO HA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07E5; NKO WA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07E6; NKO YA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07E7; NKO NYA WOLOSO; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07E8; NKO JONA JA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07E9; NKO JONA CHA; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 07EA; NKO JONA RA; D; No_Joining_Group */
-  JOINING_TYPE_X, /* 07EB */
-  JOINING_TYPE_X, /* 07EC */
-  JOINING_TYPE_X, /* 07ED */
-  JOINING_TYPE_X, /* 07EE */
-  JOINING_TYPE_X, /* 07EF */
-  JOINING_TYPE_X, /* 07F0 */
-  JOINING_TYPE_X, /* 07F1 */
-  JOINING_TYPE_X, /* 07F2 */
-  JOINING_TYPE_X, /* 07F3 */
-  JOINING_TYPE_X, /* 07F4 */
-  JOINING_TYPE_X, /* 07F5 */
-  JOINING_TYPE_X, /* 07F6 */
-  JOINING_TYPE_X, /* 07F7 */
-  JOINING_TYPE_X, /* 07F8 */
-  JOINING_TYPE_X, /* 07F9 */
-  JOINING_TYPE_C, /* 07FA; NKO LAJANYALAN; C; No_Joining_Group */
+  /* Manichaean */
+
+  /* 10AC0 */ D,D,D,D,D,R,U,R,U,R,R,U,U,L,R,R,R,R,R,D,D,D,D,L,D,D,D,D,D,R,D,D,
+  /* 10AE0 */ D,R,U,U,R,X,X,X,X,X,X,D,D,D,D,R,
+
+#define joining_offset_0x10b80u 962
 
-  /* Mandaic Characters */
+  /* Psalter Pahlavi */
+
+  /* 10B80 */ D,R,D,R,R,R,D,D,D,R,D,D,R,D,R,R,D,R,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+  /* 10BA0 */ X,X,X,X,X,X,X,X,X,R,R,R,R,D,D,U,
+
+}; /* Table items: 1010; occupancy: 57% */
+
 
-  JOINING_TYPE_X, /* 07FB */
-  JOINING_TYPE_X, /* 07FC */
-  JOINING_TYPE_X, /* 07FD */
-  JOINING_TYPE_X, /* 07FE */
-  JOINING_TYPE_X, /* 07FF */
-  JOINING_TYPE_X, /* 0800 */
-  JOINING_TYPE_X, /* 0801 */
-  JOINING_TYPE_X, /* 0802 */
-  JOINING_TYPE_X, /* 0803 */
-  JOINING_TYPE_X, /* 0804 */
-  JOINING_TYPE_X, /* 0805 */
-  JOINING_TYPE_X, /* 0806 */
-  JOINING_TYPE_X, /* 0807 */
-  JOINING_TYPE_X, /* 0808 */
-  JOINING_TYPE_X, /* 0809 */
-  JOINING_TYPE_X, /* 080A */
-  JOINING_TYPE_X, /* 080B */
-  JOINING_TYPE_X, /* 080C */
-  JOINING_TYPE_X, /* 080D */
-  JOINING_TYPE_X, /* 080E */
-  JOINING_TYPE_X, /* 080F */
-  JOINING_TYPE_X, /* 0810 */
-  JOINING_TYPE_X, /* 0811 */
-  JOINING_TYPE_X, /* 0812 */
-  JOINING_TYPE_X, /* 0813 */
-  JOINING_TYPE_X, /* 0814 */
-  JOINING_TYPE_X, /* 0815 */
-  JOINING_TYPE_X, /* 0816 */
-  JOINING_TYPE_X, /* 0817 */
-  JOINING_TYPE_X, /* 0818 */
-  JOINING_TYPE_X, /* 0819 */
-  JOINING_TYPE_X, /* 081A */
-  JOINING_TYPE_X, /* 081B */
-  JOINING_TYPE_X, /* 081C */
-  JOINING_TYPE_X, /* 081D */
-  JOINING_TYPE_X, /* 081E */
-  JOINING_TYPE_X, /* 081F */
-  JOINING_TYPE_X, /* 0820 */
-  JOINING_TYPE_X, /* 0821 */
-  JOINING_TYPE_X, /* 0822 */
-  JOINING_TYPE_X, /* 0823 */
-  JOINING_TYPE_X, /* 0824 */
-  JOINING_TYPE_X, /* 0825 */
-  JOINING_TYPE_X, /* 0826 */
-  JOINING_TYPE_X, /* 0827 */
-  JOINING_TYPE_X, /* 0828 */
-  JOINING_TYPE_X, /* 0829 */
-  JOINING_TYPE_X, /* 082A */
-  JOINING_TYPE_X, /* 082B */
-  JOINING_TYPE_X, /* 082C */
-  JOINING_TYPE_X, /* 082D */
-  JOINING_TYPE_X, /* 082E */
-  JOINING_TYPE_X, /* 082F */
-  JOINING_TYPE_X, /* 0830 */
-  JOINING_TYPE_X, /* 0831 */
-  JOINING_TYPE_X, /* 0832 */
-  JOINING_TYPE_X, /* 0833 */
-  JOINING_TYPE_X, /* 0834 */
-  JOINING_TYPE_X, /* 0835 */
-  JOINING_TYPE_X, /* 0836 */
-  JOINING_TYPE_X, /* 0837 */
-  JOINING_TYPE_X, /* 0838 */
-  JOINING_TYPE_X, /* 0839 */
-  JOINING_TYPE_X, /* 083A */
-  JOINING_TYPE_X, /* 083B */
-  JOINING_TYPE_X, /* 083C */
-  JOINING_TYPE_X, /* 083D */
-  JOINING_TYPE_X, /* 083E */
-  JOINING_TYPE_X, /* 083F */
-  JOINING_TYPE_R, /* 0840; MANDAIC HALQA; R; No_Joining_Group */
-  JOINING_TYPE_D, /* 0841; MANDAIC AB; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 0842; MANDAIC AG; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 0843; MANDAIC AD; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 0844; MANDAIC AH; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 0845; MANDAIC USHENNA; D; No_Joining_Group */
-  JOINING_TYPE_R, /* 0846; MANDAIC AZ; R; No_Joining_Group */
-  JOINING_TYPE_D, /* 0847; MANDAIC IT; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 0848; MANDAIC ATT; D; No_Joining_Group */
-  JOINING_TYPE_R, /* 0849; MANDAIC AKSA; R; No_Joining_Group */
-  JOINING_TYPE_D, /* 084A; MANDAIC AK; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 084B; MANDAIC AL; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 084C; MANDAIC AM; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 084D; MANDAIC AN; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 084E; MANDAIC AS; D; No_Joining_Group */
-  JOINING_TYPE_R, /* 084F; MANDAIC IN; R; No_Joining_Group */
-  JOINING_TYPE_D, /* 0850; MANDAIC AP; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 0851; MANDAIC ASZ; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 0852; MANDAIC AQ; D; No_Joining_Group */
-  JOINING_TYPE_D, /* 0853; MANDAIC AR; D; No_Joining_Group */
-  JOINING_TYPE_R, /* 0854; MANDAIC ASH; R; No_Joining_Group */
-  JOINING_TYPE_D, /* 0855; MANDAIC AT; D; No_Joining_Group */
-  JOINING_TYPE_U, /* 0856; MANDAIC DUSHENNA; U; No_Joining_Group */
-  JOINING_TYPE_U, /* 0857; MANDAIC KAD; U; No_Joining_Group */
-  JOINING_TYPE_U, /* 0858; MANDAIC AIN; U; No_Joining_Group */
+static unsigned int
+joining_type (hb_codepoint_t u)
+{
+  switch (u >> 12)
+  {
+    case 0x0u:
+      if (hb_in_range (u, 0x0600u, 0x08B2u)) return joining_table[u - 0x0600u + joining_offset_0x0600u];
+      break;
+
+    case 0x1u:
+      if (hb_in_range (u, 0x1806u, 0x18AAu)) return joining_table[u - 0x1806u + joining_offset_0x1806u];
+      break;
+
+    case 0x2u:
+      if (hb_in_range (u, 0x200Cu, 0x200Du)) return joining_table[u - 0x200Cu + joining_offset_0x200cu];
+      if (hb_in_range (u, 0x2066u, 0x2069u)) return joining_table[u - 0x2066u + joining_offset_0x2066u];
+      break;
 
-  /* Arabic Extended-A Characters */
+    case 0xAu:
+      if (hb_in_range (u, 0xA840u, 0xA873u)) return joining_table[u - 0xA840u + joining_offset_0xa840u];
+      break;
+
+    case 0x10u:
+      if (hb_in_range (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u];
+      if (hb_in_range (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u];
+      break;
 
-  JOINING_TYPE_X, /* 0859 */
-  JOINING_TYPE_X, /* 085A */
-  JOINING_TYPE_X, /* 085B */
-  JOINING_TYPE_X, /* 085C */
-  JOINING_TYPE_X, /* 085D */
-  JOINING_TYPE_X, /* 085E */
-  JOINING_TYPE_X, /* 085F */
-  JOINING_TYPE_X, /* 0860 */
-  JOINING_TYPE_X, /* 0861 */
-  JOINING_TYPE_X, /* 0862 */
-  JOINING_TYPE_X, /* 0863 */
-  JOINING_TYPE_X, /* 0864 */
-  JOINING_TYPE_X, /* 0865 */
-  JOINING_TYPE_X, /* 0866 */
-  JOINING_TYPE_X, /* 0867 */
-  JOINING_TYPE_X, /* 0868 */
-  JOINING_TYPE_X, /* 0869 */
-  JOINING_TYPE_X, /* 086A */
-  JOINING_TYPE_X, /* 086B */
-  JOINING_TYPE_X, /* 086C */
-  JOINING_TYPE_X, /* 086D */
-  JOINING_TYPE_X, /* 086E */
-  JOINING_TYPE_X, /* 086F */
-  JOINING_TYPE_X, /* 0870 */
-  JOINING_TYPE_X, /* 0871 */
-  JOINING_TYPE_X, /* 0872 */
-  JOINING_TYPE_X, /* 0873 */
-  JOINING_TYPE_X, /* 0874 */
-  JOINING_TYPE_X, /* 0875 */
-  JOINING_TYPE_X, /* 0876 */
-  JOINING_TYPE_X, /* 0877 */
-  JOINING_TYPE_X, /* 0878 */
-  JOINING_TYPE_X, /* 0879 */
-  JOINING_TYPE_X, /* 087A */
-  JOINING_TYPE_X, /* 087B */
-  JOINING_TYPE_X, /* 087C */
-  JOINING_TYPE_X, /* 087D */
-  JOINING_TYPE_X, /* 087E */
-  JOINING_TYPE_X, /* 087F */
-  JOINING_TYPE_X, /* 0880 */
-  JOINING_TYPE_X, /* 0881 */
-  JOINING_TYPE_X, /* 0882 */
-  JOINING_TYPE_X, /* 0883 */
-  JOINING_TYPE_X, /* 0884 */
-  JOINING_TYPE_X, /* 0885 */
-  JOINING_TYPE_X, /* 0886 */
-  JOINING_TYPE_X, /* 0887 */
-  JOINING_TYPE_X, /* 0888 */
-  JOINING_TYPE_X, /* 0889 */
-  JOINING_TYPE_X, /* 088A */
-  JOINING_TYPE_X, /* 088B */
-  JOINING_TYPE_X, /* 088C */
-  JOINING_TYPE_X, /* 088D */
-  JOINING_TYPE_X, /* 088E */
-  JOINING_TYPE_X, /* 088F */
-  JOINING_TYPE_X, /* 0890 */
-  JOINING_TYPE_X, /* 0891 */
-  JOINING_TYPE_X, /* 0892 */
-  JOINING_TYPE_X, /* 0893 */
-  JOINING_TYPE_X, /* 0894 */
-  JOINING_TYPE_X, /* 0895 */
-  JOINING_TYPE_X, /* 0896 */
-  JOINING_TYPE_X, /* 0897 */
-  JOINING_TYPE_X, /* 0898 */
-  JOINING_TYPE_X, /* 0899 */
-  JOINING_TYPE_X, /* 089A */
-  JOINING_TYPE_X, /* 089B */
-  JOINING_TYPE_X, /* 089C */
-  JOINING_TYPE_X, /* 089D */
-  JOINING_TYPE_X, /* 089E */
-  JOINING_TYPE_X, /* 089F */
-  JOINING_TYPE_D, /* 08A0; DOTLESS BEH WITH V BELOW; D; BEH */
-  JOINING_TYPE_X, /* 08A1 */
-  JOINING_TYPE_D, /* 08A2; HAH WITH DOT BELOW AND 2 DOTS ABOVE; D; HAH */
-  JOINING_TYPE_D, /* 08A3; TAH WITH 2 DOTS ABOVE; D; TAH */
-  JOINING_TYPE_D, /* 08A4; DOTLESS FEH WITH DOT BELOW AND 3 DOTS ABOVE; D; FEH */
-  JOINING_TYPE_D, /* 08A5; QAF WITH DOT BELOW; D; QAF */
-  JOINING_TYPE_D, /* 08A6; LAM WITH DOUBLE BAR; D; LAM */
-  JOINING_TYPE_D, /* 08A7; MEEM WITH 3 DOTS ABOVE; D; MEEM */
-  JOINING_TYPE_D, /* 08A8; YEH WITH HAMZA ABOVE; D; YEH */
-  JOINING_TYPE_D, /* 08A9; YEH WITH DOT ABOVE; D; YEH */
-  JOINING_TYPE_R, /* 08AA; REH WITH LOOP; R; REH */
-  JOINING_TYPE_R, /* 08AB; WAW WITH DOT WITHIN; R; WAW */
-  JOINING_TYPE_R, /* 08AC; ROHINGYA YEH; R; ROHINGYA YEH */
+    default:
+      break;
+  }
+  return X;
+}
 
-};
-
-#define JOINING_TABLE_FIRST	0x0600
-#define JOINING_TABLE_LAST	0x08AC
+#undef X
+#undef R
+#undef U
+#undef A
+#undef DR
+#undef L
+#undef C
+#undef D
 
 
 static const uint16_t shaping_table[][4] =
 {
-  {0x0000, 0x0000, 0x0000, 0xFE80}, /* U+0621 ARABIC LETTER HAMZA ISOLATED FORM */
-  {0x0000, 0x0000, 0xFE82, 0xFE81}, /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */
-  {0x0000, 0x0000, 0xFE84, 0xFE83}, /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */
-  {0x0000, 0x0000, 0xFE86, 0xFE85}, /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */
-  {0x0000, 0x0000, 0xFE88, 0xFE87}, /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */
-  {0xFE8B, 0xFE8C, 0xFE8A, 0xFE89}, /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */
-  {0x0000, 0x0000, 0xFE8E, 0xFE8D}, /* U+0627 ARABIC LETTER ALEF */
-  {0xFE91, 0xFE92, 0xFE90, 0xFE8F}, /* U+0628 ARABIC LETTER BEH */
-  {0x0000, 0x0000, 0xFE94, 0xFE93}, /* U+0629 ARABIC LETTER TEH MARBUTA */
-  {0xFE97, 0xFE98, 0xFE96, 0xFE95}, /* U+062A ARABIC LETTER TEH */
-  {0xFE9B, 0xFE9C, 0xFE9A, 0xFE99}, /* U+062B ARABIC LETTER THEH */
-  {0xFE9F, 0xFEA0, 0xFE9E, 0xFE9D}, /* U+062C ARABIC LETTER JEEM */
-  {0xFEA3, 0xFEA4, 0xFEA2, 0xFEA1}, /* U+062D ARABIC LETTER HAH */
-  {0xFEA7, 0xFEA8, 0xFEA6, 0xFEA5}, /* U+062E ARABIC LETTER KHAH */
-  {0x0000, 0x0000, 0xFEAA, 0xFEA9}, /* U+062F ARABIC LETTER DAL */
-  {0x0000, 0x0000, 0xFEAC, 0xFEAB}, /* U+0630 ARABIC LETTER THAL */
-  {0x0000, 0x0000, 0xFEAE, 0xFEAD}, /* U+0631 ARABIC LETTER REH */
-  {0x0000, 0x0000, 0xFEB0, 0xFEAF}, /* U+0632 ARABIC LETTER ZAIN */
-  {0xFEB3, 0xFEB4, 0xFEB2, 0xFEB1}, /* U+0633 ARABIC LETTER SEEN */
-  {0xFEB7, 0xFEB8, 0xFEB6, 0xFEB5}, /* U+0634 ARABIC LETTER SHEEN */
-  {0xFEBB, 0xFEBC, 0xFEBA, 0xFEB9}, /* U+0635 ARABIC LETTER SAD */
-  {0xFEBF, 0xFEC0, 0xFEBE, 0xFEBD}, /* U+0636 ARABIC LETTER DAD */
-  {0xFEC3, 0xFEC4, 0xFEC2, 0xFEC1}, /* U+0637 ARABIC LETTER TAH */
-  {0xFEC7, 0xFEC8, 0xFEC6, 0xFEC5}, /* U+0638 ARABIC LETTER ZAH */
-  {0xFECB, 0xFECC, 0xFECA, 0xFEC9}, /* U+0639 ARABIC LETTER AIN */
-  {0xFECF, 0xFED0, 0xFECE, 0xFECD}, /* U+063A ARABIC LETTER GHAIN */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+063B  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+063C  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+063D  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+063E  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+063F  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0640  */
-  {0xFED3, 0xFED4, 0xFED2, 0xFED1}, /* U+0641 ARABIC LETTER FEH */
-  {0xFED7, 0xFED8, 0xFED6, 0xFED5}, /* U+0642 ARABIC LETTER QAF */
-  {0xFEDB, 0xFEDC, 0xFEDA, 0xFED9}, /* U+0643 ARABIC LETTER KAF */
-  {0xFEDF, 0xFEE0, 0xFEDE, 0xFEDD}, /* U+0644 ARABIC LETTER LAM */
-  {0xFEE3, 0xFEE4, 0xFEE2, 0xFEE1}, /* U+0645 ARABIC LETTER MEEM */
-  {0xFEE7, 0xFEE8, 0xFEE6, 0xFEE5}, /* U+0646 ARABIC LETTER NOON */
-  {0xFEEB, 0xFEEC, 0xFEEA, 0xFEE9}, /* U+0647 ARABIC LETTER HEH */
-  {0x0000, 0x0000, 0xFEEE, 0xFEED}, /* U+0648 ARABIC LETTER WAW */
-  {0xFBE8, 0xFBE9, 0xFEF0, 0xFEEF}, /* U+0649 ARABIC LETTER */
-  {0xFEF3, 0xFEF4, 0xFEF2, 0xFEF1}, /* U+064A ARABIC LETTER YEH */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+064B  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+064C  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+064D  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+064E  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+064F  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0650  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0651  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0652  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0653  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0654  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0655  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0656  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0657  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0658  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0659  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065A  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065B  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065C  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065D  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065E  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065F  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0660  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0661  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0662  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0663  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0664  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0665  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0666  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0667  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0668  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0669  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066A  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066B  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066C  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066D  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066E  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066F  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0670  */
-  {0x0000, 0x0000, 0xFB51, 0xFB50}, /* U+0671 ARABIC LETTER ALEF WASLA */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0672  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0673  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0674  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0675  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0676  */
-  {0x0000, 0x0000, 0x0000, 0xFBDD}, /* U+0677 ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0678  */
-  {0xFB68, 0xFB69, 0xFB67, 0xFB66}, /* U+0679 ARABIC LETTER TTEH */
-  {0xFB60, 0xFB61, 0xFB5F, 0xFB5E}, /* U+067A ARABIC LETTER TTEHEH */
-  {0xFB54, 0xFB55, 0xFB53, 0xFB52}, /* U+067B ARABIC LETTER BEEH */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+067C  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+067D  */
-  {0xFB58, 0xFB59, 0xFB57, 0xFB56}, /* U+067E ARABIC LETTER PEH */
-  {0xFB64, 0xFB65, 0xFB63, 0xFB62}, /* U+067F ARABIC LETTER TEHEH */
-  {0xFB5C, 0xFB5D, 0xFB5B, 0xFB5A}, /* U+0680 ARABIC LETTER BEHEH */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0681  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0682  */
-  {0xFB78, 0xFB79, 0xFB77, 0xFB76}, /* U+0683 ARABIC LETTER NYEH */
-  {0xFB74, 0xFB75, 0xFB73, 0xFB72}, /* U+0684 ARABIC LETTER DYEH */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0685  */
-  {0xFB7C, 0xFB7D, 0xFB7B, 0xFB7A}, /* U+0686 ARABIC LETTER TCHEH */
-  {0xFB80, 0xFB81, 0xFB7F, 0xFB7E}, /* U+0687 ARABIC LETTER TCHEHEH */
-  {0x0000, 0x0000, 0xFB89, 0xFB88}, /* U+0688 ARABIC LETTER DDAL */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0689  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+068A  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+068B  */
-  {0x0000, 0x0000, 0xFB85, 0xFB84}, /* U+068C ARABIC LETTER DAHAL */
-  {0x0000, 0x0000, 0xFB83, 0xFB82}, /* U+068D ARABIC LETTER DDAHAL */
-  {0x0000, 0x0000, 0xFB87, 0xFB86}, /* U+068E ARABIC LETTER DUL */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+068F  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0690  */
-  {0x0000, 0x0000, 0xFB8D, 0xFB8C}, /* U+0691 ARABIC LETTER RREH */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0692  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0693  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0694  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0695  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0696  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0697  */
-  {0x0000, 0x0000, 0xFB8B, 0xFB8A}, /* U+0698 ARABIC LETTER JEH */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0699  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069A  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069B  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069C  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069D  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069E  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069F  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A0  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A1  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A2  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A3  */
-  {0xFB6C, 0xFB6D, 0xFB6B, 0xFB6A}, /* U+06A4 ARABIC LETTER VEH */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A5  */
-  {0xFB70, 0xFB71, 0xFB6F, 0xFB6E}, /* U+06A6 ARABIC LETTER PEHEH */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A7  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A8  */
-  {0xFB90, 0xFB91, 0xFB8F, 0xFB8E}, /* U+06A9 ARABIC LETTER KEHEH */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06AA  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06AB  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06AC  */
-  {0xFBD5, 0xFBD6, 0xFBD4, 0xFBD3}, /* U+06AD ARABIC LETTER NG */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06AE  */
-  {0xFB94, 0xFB95, 0xFB93, 0xFB92}, /* U+06AF ARABIC LETTER GAF */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B0  */
-  {0xFB9C, 0xFB9D, 0xFB9B, 0xFB9A}, /* U+06B1 ARABIC LETTER NGOEH */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B2  */
-  {0xFB98, 0xFB99, 0xFB97, 0xFB96}, /* U+06B3 ARABIC LETTER GUEH */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B4  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B5  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B6  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B7  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B8  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B9  */
-  {0x0000, 0x0000, 0xFB9F, 0xFB9E}, /* U+06BA ARABIC LETTER NOON GHUNNA */
-  {0xFBA2, 0xFBA3, 0xFBA1, 0xFBA0}, /* U+06BB ARABIC LETTER RNOON */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06BC  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06BD  */
-  {0xFBAC, 0xFBAD, 0xFBAB, 0xFBAA}, /* U+06BE ARABIC LETTER HEH DOACHASHMEE */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06BF  */
-  {0x0000, 0x0000, 0xFBA5, 0xFBA4}, /* U+06C0 ARABIC LETTER HEH WITH YEH ABOVE */
-  {0xFBA8, 0xFBA9, 0xFBA7, 0xFBA6}, /* U+06C1 ARABIC LETTER HEH GOAL */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06C2  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06C3  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06C4  */
-  {0x0000, 0x0000, 0xFBE1, 0xFBE0}, /* U+06C5 ARABIC LETTER KIRGHIZ OE */
-  {0x0000, 0x0000, 0xFBDA, 0xFBD9}, /* U+06C6 ARABIC LETTER OE */
-  {0x0000, 0x0000, 0xFBD8, 0xFBD7}, /* U+06C7 ARABIC LETTER U */
-  {0x0000, 0x0000, 0xFBDC, 0xFBDB}, /* U+06C8 ARABIC LETTER YU */
-  {0x0000, 0x0000, 0xFBE3, 0xFBE2}, /* U+06C9 ARABIC LETTER KIRGHIZ YU */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06CA  */
-  {0x0000, 0x0000, 0xFBDF, 0xFBDE}, /* U+06CB ARABIC LETTER VE */
-  {0xFBFE, 0xFBFF, 0xFBFD, 0xFBFC}, /* U+06CC ARABIC LETTER FARSI YEH */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06CD  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06CE  */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06CF  */
-  {0xFBE6, 0xFBE7, 0xFBE5, 0xFBE4}, /* U+06D0 ARABIC LETTER E */
-  {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06D1  */
-  {0x0000, 0x0000, 0xFBAF, 0xFBAE}, /* U+06D2 ARABIC LETTER YEH BARREE */
-  {0x0000, 0x0000, 0xFBB1, 0xFBB0}, /* U+06D3 ARABIC LETTER YEH BARREE WITH HAMZA ABOVE */
+  {0x0000u, 0x0000u, 0x0000u, 0xFE80u}, /* U+0621 ARABIC LETTER HAMZA ISOLATED FORM */
+  {0x0000u, 0x0000u, 0xFE82u, 0xFE81u}, /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */
+  {0x0000u, 0x0000u, 0xFE84u, 0xFE83u}, /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */
+  {0x0000u, 0x0000u, 0xFE86u, 0xFE85u}, /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */
+  {0x0000u, 0x0000u, 0xFE88u, 0xFE87u}, /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */
+  {0xFE8Bu, 0xFE8Cu, 0xFE8Au, 0xFE89u}, /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */
+  {0x0000u, 0x0000u, 0xFE8Eu, 0xFE8Du}, /* U+0627 ARABIC LETTER ALEF */
+  {0xFE91u, 0xFE92u, 0xFE90u, 0xFE8Fu}, /* U+0628 ARABIC LETTER BEH */
+  {0x0000u, 0x0000u, 0xFE94u, 0xFE93u}, /* U+0629 ARABIC LETTER TEH MARBUTA */
+  {0xFE97u, 0xFE98u, 0xFE96u, 0xFE95u}, /* U+062A ARABIC LETTER TEH */
+  {0xFE9Bu, 0xFE9Cu, 0xFE9Au, 0xFE99u}, /* U+062B ARABIC LETTER THEH */
+  {0xFE9Fu, 0xFEA0u, 0xFE9Eu, 0xFE9Du}, /* U+062C ARABIC LETTER JEEM */
+  {0xFEA3u, 0xFEA4u, 0xFEA2u, 0xFEA1u}, /* U+062D ARABIC LETTER HAH */
+  {0xFEA7u, 0xFEA8u, 0xFEA6u, 0xFEA5u}, /* U+062E ARABIC LETTER KHAH */
+  {0x0000u, 0x0000u, 0xFEAAu, 0xFEA9u}, /* U+062F ARABIC LETTER DAL */
+  {0x0000u, 0x0000u, 0xFEACu, 0xFEABu}, /* U+0630 ARABIC LETTER THAL */
+  {0x0000u, 0x0000u, 0xFEAEu, 0xFEADu}, /* U+0631 ARABIC LETTER REH */
+  {0x0000u, 0x0000u, 0xFEB0u, 0xFEAFu}, /* U+0632 ARABIC LETTER ZAIN */
+  {0xFEB3u, 0xFEB4u, 0xFEB2u, 0xFEB1u}, /* U+0633 ARABIC LETTER SEEN */
+  {0xFEB7u, 0xFEB8u, 0xFEB6u, 0xFEB5u}, /* U+0634 ARABIC LETTER SHEEN */
+  {0xFEBBu, 0xFEBCu, 0xFEBAu, 0xFEB9u}, /* U+0635 ARABIC LETTER SAD */
+  {0xFEBFu, 0xFEC0u, 0xFEBEu, 0xFEBDu}, /* U+0636 ARABIC LETTER DAD */
+  {0xFEC3u, 0xFEC4u, 0xFEC2u, 0xFEC1u}, /* U+0637 ARABIC LETTER TAH */
+  {0xFEC7u, 0xFEC8u, 0xFEC6u, 0xFEC5u}, /* U+0638 ARABIC LETTER ZAH */
+  {0xFECBu, 0xFECCu, 0xFECAu, 0xFEC9u}, /* U+0639 ARABIC LETTER AIN */
+  {0xFECFu, 0xFED0u, 0xFECEu, 0xFECDu}, /* U+063A ARABIC LETTER GHAIN */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063B  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063C  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063D  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063E  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063F  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0640  */
+  {0xFED3u, 0xFED4u, 0xFED2u, 0xFED1u}, /* U+0641 ARABIC LETTER FEH */
+  {0xFED7u, 0xFED8u, 0xFED6u, 0xFED5u}, /* U+0642 ARABIC LETTER QAF */
+  {0xFEDBu, 0xFEDCu, 0xFEDAu, 0xFED9u}, /* U+0643 ARABIC LETTER KAF */
+  {0xFEDFu, 0xFEE0u, 0xFEDEu, 0xFEDDu}, /* U+0644 ARABIC LETTER LAM */
+  {0xFEE3u, 0xFEE4u, 0xFEE2u, 0xFEE1u}, /* U+0645 ARABIC LETTER MEEM */
+  {0xFEE7u, 0xFEE8u, 0xFEE6u, 0xFEE5u}, /* U+0646 ARABIC LETTER NOON */
+  {0xFEEBu, 0xFEECu, 0xFEEAu, 0xFEE9u}, /* U+0647 ARABIC LETTER HEH */
+  {0x0000u, 0x0000u, 0xFEEEu, 0xFEEDu}, /* U+0648 ARABIC LETTER WAW */
+  {0xFBE8u, 0xFBE9u, 0xFEF0u, 0xFEEFu}, /* U+0649 ARABIC LETTER */
+  {0xFEF3u, 0xFEF4u, 0xFEF2u, 0xFEF1u}, /* U+064A ARABIC LETTER YEH */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064B  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064C  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064D  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064E  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064F  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0650  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0651  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0652  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0653  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0654  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0655  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0656  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0657  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0658  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0659  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065A  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065B  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065C  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065D  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065E  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065F  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0660  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0661  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0662  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0663  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0664  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0665  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0666  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0667  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0668  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0669  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066A  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066B  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066C  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066D  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066E  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066F  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0670  */
+  {0x0000u, 0x0000u, 0xFB51u, 0xFB50u}, /* U+0671 ARABIC LETTER ALEF WASLA */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0672  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0673  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0674  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0675  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0676  */
+  {0x0000u, 0x0000u, 0x0000u, 0xFBDDu}, /* U+0677 ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0678  */
+  {0xFB68u, 0xFB69u, 0xFB67u, 0xFB66u}, /* U+0679 ARABIC LETTER TTEH */
+  {0xFB60u, 0xFB61u, 0xFB5Fu, 0xFB5Eu}, /* U+067A ARABIC LETTER TTEHEH */
+  {0xFB54u, 0xFB55u, 0xFB53u, 0xFB52u}, /* U+067B ARABIC LETTER BEEH */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+067C  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+067D  */
+  {0xFB58u, 0xFB59u, 0xFB57u, 0xFB56u}, /* U+067E ARABIC LETTER PEH */
+  {0xFB64u, 0xFB65u, 0xFB63u, 0xFB62u}, /* U+067F ARABIC LETTER TEHEH */
+  {0xFB5Cu, 0xFB5Du, 0xFB5Bu, 0xFB5Au}, /* U+0680 ARABIC LETTER BEHEH */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0681  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0682  */
+  {0xFB78u, 0xFB79u, 0xFB77u, 0xFB76u}, /* U+0683 ARABIC LETTER NYEH */
+  {0xFB74u, 0xFB75u, 0xFB73u, 0xFB72u}, /* U+0684 ARABIC LETTER DYEH */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0685  */
+  {0xFB7Cu, 0xFB7Du, 0xFB7Bu, 0xFB7Au}, /* U+0686 ARABIC LETTER TCHEH */
+  {0xFB80u, 0xFB81u, 0xFB7Fu, 0xFB7Eu}, /* U+0687 ARABIC LETTER TCHEHEH */
+  {0x0000u, 0x0000u, 0xFB89u, 0xFB88u}, /* U+0688 ARABIC LETTER DDAL */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0689  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+068A  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+068B  */
+  {0x0000u, 0x0000u, 0xFB85u, 0xFB84u}, /* U+068C ARABIC LETTER DAHAL */
+  {0x0000u, 0x0000u, 0xFB83u, 0xFB82u}, /* U+068D ARABIC LETTER DDAHAL */
+  {0x0000u, 0x0000u, 0xFB87u, 0xFB86u}, /* U+068E ARABIC LETTER DUL */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+068F  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0690  */
+  {0x0000u, 0x0000u, 0xFB8Du, 0xFB8Cu}, /* U+0691 ARABIC LETTER RREH */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0692  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0693  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0694  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0695  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0696  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0697  */
+  {0x0000u, 0x0000u, 0xFB8Bu, 0xFB8Au}, /* U+0698 ARABIC LETTER JEH */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0699  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069A  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069B  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069C  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069D  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069E  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069F  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A0  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A1  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A2  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A3  */
+  {0xFB6Cu, 0xFB6Du, 0xFB6Bu, 0xFB6Au}, /* U+06A4 ARABIC LETTER VEH */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A5  */
+  {0xFB70u, 0xFB71u, 0xFB6Fu, 0xFB6Eu}, /* U+06A6 ARABIC LETTER PEHEH */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A7  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A8  */
+  {0xFB90u, 0xFB91u, 0xFB8Fu, 0xFB8Eu}, /* U+06A9 ARABIC LETTER KEHEH */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AA  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AB  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AC  */
+  {0xFBD5u, 0xFBD6u, 0xFBD4u, 0xFBD3u}, /* U+06AD ARABIC LETTER NG */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AE  */
+  {0xFB94u, 0xFB95u, 0xFB93u, 0xFB92u}, /* U+06AF ARABIC LETTER GAF */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B0  */
+  {0xFB9Cu, 0xFB9Du, 0xFB9Bu, 0xFB9Au}, /* U+06B1 ARABIC LETTER NGOEH */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B2  */
+  {0xFB98u, 0xFB99u, 0xFB97u, 0xFB96u}, /* U+06B3 ARABIC LETTER GUEH */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B4  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B5  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B6  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B7  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B8  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B9  */
+  {0x0000u, 0x0000u, 0xFB9Fu, 0xFB9Eu}, /* U+06BA ARABIC LETTER NOON GHUNNA */
+  {0xFBA2u, 0xFBA3u, 0xFBA1u, 0xFBA0u}, /* U+06BB ARABIC LETTER RNOON */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06BC  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06BD  */
+  {0xFBACu, 0xFBADu, 0xFBABu, 0xFBAAu}, /* U+06BE ARABIC LETTER HEH DOACHASHMEE */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06BF  */
+  {0x0000u, 0x0000u, 0xFBA5u, 0xFBA4u}, /* U+06C0 ARABIC LETTER HEH WITH YEH ABOVE */
+  {0xFBA8u, 0xFBA9u, 0xFBA7u, 0xFBA6u}, /* U+06C1 ARABIC LETTER HEH GOAL */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06C2  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06C3  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06C4  */
+  {0x0000u, 0x0000u, 0xFBE1u, 0xFBE0u}, /* U+06C5 ARABIC LETTER KIRGHIZ OE */
+  {0x0000u, 0x0000u, 0xFBDAu, 0xFBD9u}, /* U+06C6 ARABIC LETTER OE */
+  {0x0000u, 0x0000u, 0xFBD8u, 0xFBD7u}, /* U+06C7 ARABIC LETTER U */
+  {0x0000u, 0x0000u, 0xFBDCu, 0xFBDBu}, /* U+06C8 ARABIC LETTER YU */
+  {0x0000u, 0x0000u, 0xFBE3u, 0xFBE2u}, /* U+06C9 ARABIC LETTER KIRGHIZ YU */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CA  */
+  {0x0000u, 0x0000u, 0xFBDFu, 0xFBDEu}, /* U+06CB ARABIC LETTER VE */
+  {0xFBFEu, 0xFBFFu, 0xFBFDu, 0xFBFCu}, /* U+06CC ARABIC LETTER FARSI YEH */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CD  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CE  */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CF  */
+  {0xFBE6u, 0xFBE7u, 0xFBE5u, 0xFBE4u}, /* U+06D0 ARABIC LETTER E */
+  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06D1  */
+  {0x0000u, 0x0000u, 0xFBAFu, 0xFBAEu}, /* U+06D2 ARABIC LETTER YEH BARREE */
+  {0x0000u, 0x0000u, 0xFBB1u, 0xFBB0u}, /* U+06D3 ARABIC LETTER YEH BARREE WITH HAMZA ABOVE */
 };
 
-#define SHAPING_TABLE_FIRST	0x0621
-#define SHAPING_TABLE_LAST	0x06D3
+#define SHAPING_TABLE_FIRST	0x0621u
+#define SHAPING_TABLE_LAST	0x06D3u
 
 
 static const struct ligature_set_t {
  uint16_t first;
  struct ligature_pairs_t {
    uint16_t second;
    uint16_t ligature;
  } ligatures[4];
 } ligature_table[] =
 {
-  { 0xFEDF, {
-    { 0xFE88, 0xFEF9 }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */
-    { 0xFE82, 0xFEF5 }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */
-    { 0xFE8E, 0xFEFB }, /* ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */
-    { 0xFE84, 0xFEF7 }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */
+  { 0xFEDFu, {
+    { 0xFE88u, 0xFEF9u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */
+    { 0xFE82u, 0xFEF5u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */
+    { 0xFE8Eu, 0xFEFBu }, /* ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */
+    { 0xFE84u, 0xFEF7u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */
   }},
-  { 0xFEE0, {
-    { 0xFE88, 0xFEFA }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */
-    { 0xFE82, 0xFEF6 }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */
-    { 0xFE8E, 0xFEFC }, /* ARABIC LIGATURE LAM WITH ALEF FINAL FORM */
-    { 0xFE84, 0xFEF8 }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */
+  { 0xFEE0u, {
+    { 0xFE88u, 0xFEFAu }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */
+    { 0xFE82u, 0xFEF6u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */
+    { 0xFE8Eu, 0xFEFCu }, /* ARABIC LIGATURE LAM WITH ALEF FINAL FORM */
+    { 0xFE84u, 0xFEF8u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */
   }},
 };
 
 
 #endif /* HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH */
 
 /* == End of generated table == */
new file mode 100644
--- /dev/null
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh
@@ -0,0 +1,321 @@
+/*
+ * Copyright © 2014  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH
+
+
+/*
+ * The macros in the first part of this file are generic macros that can
+ * be used to define the bytes for OpenType table data in code in a
+ * readable manner.  We can move the macros to reside with their respective
+ * struct types, but since we only use these to define one data table, the
+ * Windows-1256 Arabic shaping table in this file, we keep them here.
+ */
+
+
+/* First we measure, then we cut. */
+#ifndef OT_MEASURE
+#define OT_MEASURE
+#define OT_TABLE_START			static const struct TABLE_NAME {
+#define OT_TABLE_END			}
+#define OT_LABEL_START(Name)		unsigned char Name[
+#define OT_LABEL_END			];
+#define OT_BYTE(u8)			+1/*byte*/
+#define OT_USHORT(u16)			+2/*bytes*/
+#else
+#undef  OT_MEASURE
+#define OT_TABLE_START			TABLE_NAME = {
+#define OT_TABLE_END			};
+#define OT_LABEL_START(Name)		{
+#define OT_LABEL_END			},
+#define OT_BYTE(u8)			(u8),
+#define OT_USHORT(u16)			(unsigned char)((u16)>>8), (unsigned char)((u16)&0xFFu),
+#define OT_COUNT(Name, ItemSize)	((unsigned int) sizeof(((struct TABLE_NAME*)0)->Name) \
+					 / (unsigned int)(ItemSize) \
+					 /* OT_ASSERT it's divisible (and positive). */)
+#define OT_DISTANCE(From,To)		((unsigned int) \
+					 ((char*)(&((struct TABLE_NAME*)0)->To) - \
+					  (char*)(&((struct TABLE_NAME*)0)->From)) \
+					 /* OT_ASSERT it's positive. */)
+#endif
+
+
+#define OT_LABEL(Name) \
+	OT_LABEL_END \
+	OT_LABEL_START(Name)
+
+/* Whenever we receive an argument that is a list, it will expand to
+ * contain commas.  That cannot be passed to another macro because the
+ * commas will throw off the preprocessor.  The solution is to wrap
+ * the passed-in argument in OT_LIST() before passing to the next macro.
+ * Unfortunately this trick requires vararg macros. */
+#define OT_LIST(...) __VA_ARGS__
+
+
+/*
+ * Basic Types
+ */
+
+#define OT_TAG(a,b,c,d) \
+	OT_BYTE(a) OT_BYTE(b) OT_BYTE(c) OT_BYTE(d)
+
+#define OT_OFFSET(From, To) /* Offset from From to To in bytes */ \
+	OT_USHORT(OT_DISTANCE(From, To))
+
+#define OT_GLYPHID /* GlyphID */ \
+	OT_USHORT
+
+#define OT_UARRAY(Name, Items) \
+	OT_LABEL_START(Name) \
+	OT_USHORT(OT_COUNT(Name##Data, 2)) \
+	OT_LABEL(Name##Data) \
+	Items \
+	OT_LABEL_END
+
+#define OT_UHEADLESSARRAY(Name, Items) \
+	OT_LABEL_START(Name) \
+	OT_USHORT(OT_COUNT(Name##Data, 2) + 1) \
+	OT_LABEL(Name##Data) \
+	Items \
+	OT_LABEL_END
+
+
+/*
+ * Common Types
+ */
+
+#define OT_LOOKUP_FLAG_IGNORE_MARKS	0x08u
+
+#define OT_LOOKUP(Name, LookupType, LookupFlag, SubLookupOffsets) \
+	OT_LABEL_START(Name) \
+	OT_USHORT(LookupType) \
+	OT_USHORT(LookupFlag) \
+	OT_LABEL_END \
+	OT_UARRAY(Name##SubLookupOffsetsArray, OT_LIST(SubLookupOffsets))
+
+#define OT_SUBLOOKUP(Name, SubFormat, Items) \
+	OT_LABEL_START(Name) \
+	OT_USHORT(SubFormat) \
+	Items
+
+#define OT_COVERAGE1(Name, Items) \
+	OT_LABEL_START(Name) \
+	OT_USHORT(1) \
+	OT_LABEL_END \
+	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)) \
+	) \
+	OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \
+	/* ASSERT_STATIC_EXPR len(FromGlyphs) == len(ToGlyphs) */
+
+#define OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(Name, FirstGlyphs, LigatureSetOffsets) \
+	OT_SUBLOOKUP(Name, 1, \
+		OT_OFFSET(Name, Name##Coverage) \
+		OT_LABEL_END \
+		OT_UARRAY(Name##LigatureSetOffsetsArray, OT_LIST(LigatureSetOffsets)) \
+	) \
+	OT_COVERAGE1(Name##Coverage, OT_LIST(FirstGlyphs)) \
+	/* ASSERT_STATIC_EXPR len(FirstGlyphs) == len(LigatureSetOffsets) */
+
+#define OT_LIGATURE_SET(Name, LigatureSetOffsets) \
+	OT_UARRAY(Name, OT_LIST(LigatureSetOffsets))
+
+#define OT_LIGATURE(Name, Components, LigGlyph) \
+	OT_LABEL_START(Name) \
+	LigGlyph \
+	OT_LABEL_END \
+	OT_UHEADLESSARRAY(Name##ComponentsArray, OT_LIST(Components))
+
+/*
+ *
+ * Start of Windows-1256 shaping table.
+ *
+ */
+
+/* Table name. */
+#define TABLE_NAME arabic_win1256_gsub_lookups
+
+/* Table manifest. */
+#define MANIFEST(Items) \
+	OT_LABEL_START(manifest) \
+	OT_USHORT(OT_COUNT(manifestData, 6)) \
+	OT_LABEL(manifestData) \
+	Items \
+	OT_LABEL_END
+
+#define MANIFEST_LOOKUP(Tag, Name) \
+	Tag \
+	OT_OFFSET(manifest, Name)
+
+/* Shorthand. */
+#define G	OT_GLYPHID
+
+/*
+ * Table Start
+ */
+OT_TABLE_START
+
+
+/*
+ * Manifest
+ */
+MANIFEST(
+	MANIFEST_LOOKUP(OT_TAG('r','l','i','g'), rligLookup)
+	MANIFEST_LOOKUP(OT_TAG('i','n','i','t'), initLookup)
+	MANIFEST_LOOKUP(OT_TAG('m','e','d','i'), mediLookup)
+	MANIFEST_LOOKUP(OT_TAG('f','i','n','a'), finaLookup)
+	MANIFEST_LOOKUP(OT_TAG('r','l','i','g'), rligMarksLookup)
+)
+
+/*
+ * Lookups
+ */
+OT_LOOKUP(initLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS,
+	OT_OFFSET(initLookup, initmediSubLookup)
+	OT_OFFSET(initLookup, initSubLookup)
+)
+OT_LOOKUP(mediLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS,
+	OT_OFFSET(mediLookup, initmediSubLookup)
+	OT_OFFSET(mediLookup, mediSubLookup)
+	OT_OFFSET(mediLookup, medifinaLamAlefSubLookup)
+)
+OT_LOOKUP(finaLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS,
+	OT_OFFSET(finaLookup, finaSubLookup)
+	/* We don't need this one currently as the sequence inherits masks
+	 * from the first item.  Just in case we change that in the future
+	 * to be smart about Arabic masks when ligating... */
+	OT_OFFSET(finaLookup, medifinaLamAlefSubLookup)
+)
+OT_LOOKUP(rligLookup, OT_LOOKUP_TYPE_SUBST_LIGATURE, OT_LOOKUP_FLAG_IGNORE_MARKS,
+	OT_OFFSET(rligLookup, lamAlefLigaturesSubLookup)
+)
+OT_LOOKUP(rligMarksLookup, OT_LOOKUP_TYPE_SUBST_LIGATURE, 0,
+	OT_OFFSET(rligMarksLookup, shaddaLigaturesSubLookup)
+)
+
+/*
+ * init/medi/fina forms
+ */
+OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(initmediSubLookup,
+	G(198)	G(200)	G(201)	G(202)	G(203)	G(204)	G(205)	G(206)	G(211)
+	G(212)	G(213)	G(214)	G(223)	G(225)	G(227)	G(228)	G(236)	G(237),
+	G(162)	G(4)	G(5)	G(5)	G(6)	G(7)	G(9)	G(11)	G(13)
+	G(14)	G(15)	G(26)	G(140)	G(141)	G(142)	G(143)	G(154)	G(154)
+)
+OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(initSubLookup,
+	G(218)	G(219)	G(221)	G(222)	G(229),
+	G(27)	G(30)	G(128)	G(131)	G(144)
+)
+OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(mediSubLookup,
+	G(218)	G(219)	G(221)	G(222)	G(229),
+	G(28)	G(31)	G(129)	G(138)	G(149)
+)
+OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(finaSubLookup,
+	G(194)	G(195)	G(197)	G(198)	G(199)	G(201)	G(204)	G(205)	G(206)
+	G(218)	G(219)	G(229)	G(236)	G(237),
+	G(2)	G(1)	G(3)	G(181)	G(0)	G(159)	G(8)	G(10)	G(12)
+	G(29)	G(127)	G(152) G(160)	G(156)
+)
+OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(medifinaLamAlefSubLookup,
+	G(165)	G(178)	G(180)	G(252),
+	G(170)	G(179)	G(185)	G(255)
+)
+
+/*
+ * Lam+Alef ligatures
+ */
+OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(lamAlefLigaturesSubLookup,
+	G(225),
+	OT_OFFSET(lamAlefLigaturesSubLookup, lamLigatureSet)
+)
+OT_LIGATURE_SET(lamLigatureSet,
+	OT_OFFSET(lamLigatureSet, lamInitLigature1)
+	OT_OFFSET(lamLigatureSet, lamInitLigature2)
+	OT_OFFSET(lamLigatureSet, lamInitLigature3)
+	OT_OFFSET(lamLigatureSet, lamInitLigature4)
+)
+OT_LIGATURE(lamInitLigature1, G(199), G(165))
+OT_LIGATURE(lamInitLigature2, G(195), G(178))
+OT_LIGATURE(lamInitLigature3, G(194), G(180))
+OT_LIGATURE(lamInitLigature4, G(197), G(252))
+
+/*
+ * Shadda ligatures
+ */
+OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(shaddaLigaturesSubLookup,
+	G(248),
+	OT_OFFSET(shaddaLigaturesSubLookup, shaddaLigatureSet)
+)
+OT_LIGATURE_SET(shaddaLigatureSet,
+	OT_OFFSET(shaddaLigatureSet, shaddaLigature1)
+	OT_OFFSET(shaddaLigatureSet, shaddaLigature2)
+	OT_OFFSET(shaddaLigatureSet, shaddaLigature3)
+)
+OT_LIGATURE(shaddaLigature1, G(243), G(172))
+OT_LIGATURE(shaddaLigature2, G(245), G(173))
+OT_LIGATURE(shaddaLigature3, G(246), G(175))
+
+/*
+ * Table end
+ */
+OT_TABLE_END
+
+
+/*
+ * Clean up
+ */
+#undef OT_TABLE_START
+#undef OT_TABLE_END
+#undef OT_LABEL_START
+#undef OT_LABEL_END
+#undef OT_BYTE
+#undef OT_USHORT
+#undef OT_DISTANCE
+#undef OT_COUNT
+
+/*
+ * Include a second time to get the table data...
+ */
+#ifdef OT_MEASURE
+#include __FILE__
+#endif
+
+#define HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH
+#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH */
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc
@@ -52,78 +52,51 @@ enum {
 /*
  * Joining types:
  */
 
 #include "hb-ot-shape-complex-arabic-table.hh"
 
 static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_category_t gen_cat)
 {
-  if (likely (hb_in_range<hb_codepoint_t> (u, JOINING_TABLE_FIRST, JOINING_TABLE_LAST))) {
-    unsigned int j_type = joining_table[u - JOINING_TABLE_FIRST];
-    if (likely (j_type != JOINING_TYPE_X))
-      return j_type;
-  }
-
-  /* Mongolian joining data is not in ArabicJoining.txt yet. */
-  if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1800, 0x18AF)))
-  {
-    if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1880, 0x1886)))
-      return JOINING_TYPE_U;
+  unsigned int j_type = joining_type(u);
+  if (likely (j_type != JOINING_TYPE_X))
+    return j_type;
 
-    /* All letters, SIBE SYLLABLE BOUNDARY MARKER, and NIRUGU are D */
-    if ((FLAG(gen_cat) & (FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER) |
-			  FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER)))
-	|| u == 0x1807 || u == 0x180A)
-      return JOINING_TYPE_D;
-  }
+  return (FLAG(gen_cat) &
+	  (FLAG(HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) |
+	   FLAG(HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
+	   FLAG(HB_UNICODE_GENERAL_CATEGORY_FORMAT))
+	 ) ?  JOINING_TYPE_T : JOINING_TYPE_U;
+}
 
-  /* 'Phags-pa joining data is not in ArabicJoining.txt yet. */
-  if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xA840, 0xA872)))
-  {
-      if (unlikely (u == 0xA872))
-	return JOINING_TYPE_L;
-
-      return JOINING_TYPE_D;
-  }
-
-  if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x200C, 0x200D)))
-  {
-    return u == 0x200C ? JOINING_TYPE_U : JOINING_TYPE_C;
-  }
-
-  return (FLAG(gen_cat) & (FLAG(HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | FLAG(HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | FLAG(HB_UNICODE_GENERAL_CATEGORY_FORMAT))) ?
-	 JOINING_TYPE_T : JOINING_TYPE_U;
-}
+#define FEATURE_IS_SYRIAC(tag) hb_in_range<unsigned char> ((unsigned char) (tag), '2', '3')
 
 static const hb_tag_t arabic_features[] =
 {
-  HB_TAG('i','n','i','t'),
-  HB_TAG('m','e','d','i'),
+  HB_TAG('i','s','o','l'),
   HB_TAG('f','i','n','a'),
-  HB_TAG('i','s','o','l'),
-  /* Syriac */
-  HB_TAG('m','e','d','2'),
   HB_TAG('f','i','n','2'),
   HB_TAG('f','i','n','3'),
+  HB_TAG('m','e','d','i'),
+  HB_TAG('m','e','d','2'),
+  HB_TAG('i','n','i','t'),
   HB_TAG_NONE
 };
 
 
 /* Same order as the feature array */
 enum {
-  INIT,
-  MEDI,
+  ISOL,
   FINA,
-  ISOL,
-
-  /* Syriac */
-  MED2,
   FIN2,
   FIN3,
+  MEDI,
+  MED2,
+  INIT,
 
   NONE,
 
   ARABIC_NUM_FEATURES = NONE
 };
 
 static const struct arabic_state_table_entry {
 	uint8_t prev_action;
@@ -166,44 +139,65 @@ arabic_fallback_shape (const hb_ot_shape
 		       hb_font_t *font,
 		       hb_buffer_t *buffer);
 
 static void
 collect_features_arabic (hb_ot_shape_planner_t *plan)
 {
   hb_ot_map_builder_t *map = &plan->map;
 
-  /* For Language forms (in ArabicOT speak), we do the iso/fina/medi/init together,
-   * then rlig and calt each in their own stage.  This makes IranNastaliq's ALLAH
-   * ligature work correctly. It's unfortunate though...
+  /* We apply features according to the Arabic spec, with pauses
+   * in between most.
    *
-   * This also makes Arial Bold in Windows7 work.  See:
+   * The pause between init/medi/... and rlig is required.  See eg:
    * https://bugzilla.mozilla.org/show_bug.cgi?id=644184
    *
-   * TODO: Add test cases for these two.
+   * The pauses between init/medi/... themselves are not necessarily
+   * needed as only one of those features is applied to any character.
+   * The only difference it makes is when fonts have contextual
+   * substitutions.  We now follow the order of the spec, which makes
+   * for better experience if that's what Uniscribe is doing.
+   *
+   * At least for Arabic, looks like Uniscribe has a pause between
+   * rlig and calt.  Otherwise the IranNastaliq's ALLAH ligature won't
+   * work.  However, testing shows that rlig and calt are applied
+   * together for Mongolian in Uniscribe.  As such, we only add a
+   * pause for Arabic, not other scripts.
    */
 
   map->add_gsub_pause (nuke_joiners);
 
   map->add_global_bool_feature (HB_TAG('c','c','m','p'));
   map->add_global_bool_feature (HB_TAG('l','o','c','l'));
 
   map->add_gsub_pause (NULL);
 
   for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++)
-    map->add_feature (arabic_features[i], 1, i < 4 ? F_HAS_FALLBACK : F_NONE); /* The first four features have fallback. */
-
-  map->add_gsub_pause (NULL);
+  {
+    bool has_fallback = plan->props.script == HB_SCRIPT_ARABIC && !FEATURE_IS_SYRIAC (arabic_features[i]);
+    map->add_feature (arabic_features[i], 1, has_fallback ? F_HAS_FALLBACK : F_NONE);
+    map->add_gsub_pause (NULL);
+  }
 
   map->add_feature (HB_TAG('r','l','i','g'), 1, F_GLOBAL|F_HAS_FALLBACK);
-  map->add_gsub_pause (arabic_fallback_shape);
+  if (plan->props.script == HB_SCRIPT_ARABIC)
+    map->add_gsub_pause (arabic_fallback_shape);
 
   map->add_global_bool_feature (HB_TAG('c','a','l','t'));
   map->add_gsub_pause (NULL);
 
+  /* The spec includes 'cswh'.  Earlier versions of Windows
+   * used to enable this by default, but testing suggests
+   * that Windows 8 and later do not enable it by default,
+   * and spec now says 'Off by default'.
+   * We disabled this in ae23c24c32.
+   * Note that IranNastaliq uses this feature extensively
+   * to fixup broken glyph sequences.  Oh well...
+   * Test case: U+0643,U+0640,U+0631. */
+  //map->add_global_bool_feature (HB_TAG('c','s','w','h'));
   map->add_global_bool_feature (HB_TAG('m','s','e','t'));
 }
 
 #include "hb-ot-shape-complex-arabic-fallback.hh"
 
 struct arabic_shape_plan_t
 {
   ASSERT_POD ();
@@ -223,18 +217,19 @@ data_create_arabic (const hb_ot_shape_pl
 {
   arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) calloc (1, sizeof (arabic_shape_plan_t));
   if (unlikely (!arabic_plan))
     return NULL;
 
   arabic_plan->do_fallback = plan->props.script == HB_SCRIPT_ARABIC;
   for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) {
     arabic_plan->mask_array[i] = plan->map.get_1_mask (arabic_features[i]);
-    if (i < 4)
-      arabic_plan->do_fallback = arabic_plan->do_fallback && plan->map.needs_fallback (arabic_features[i]);
+    arabic_plan->do_fallback = arabic_plan->do_fallback &&
+			       (FEATURE_IS_SYRIAC (arabic_features[i]) ||
+			        plan->map.needs_fallback (arabic_features[i]));
   }
 
   return arabic_plan;
 }
 
 static void
 data_destroy_arabic (void *data)
 {
@@ -244,96 +239,109 @@ data_destroy_arabic (void *data)
 
   free (data);
 }
 
 static void
 arabic_joining (hb_buffer_t *buffer)
 {
   unsigned int count = buffer->len;
+  hb_glyph_info_t *info = buffer->info;
   unsigned int prev = (unsigned int) -1, state = 0;
 
-  HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action);
-
   /* Check pre-context */
-  if (!(buffer->flags & HB_BUFFER_FLAG_BOT))
-    for (unsigned int i = 0; i < buffer->context_len[0]; i++)
-    {
-      unsigned int this_type = get_joining_type (buffer->context[0][i], buffer->unicode->general_category (buffer->context[0][i]));
+  for (unsigned int i = 0; i < buffer->context_len[0]; i++)
+  {
+    unsigned int this_type = get_joining_type (buffer->context[0][i], buffer->unicode->general_category (buffer->context[0][i]));
 
-      if (unlikely (this_type == JOINING_TYPE_T))
-	continue;
+    if (unlikely (this_type == JOINING_TYPE_T))
+      continue;
 
-      const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
-      state = entry->next_state;
-      break;
-    }
+    const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
+    state = entry->next_state;
+    break;
+  }
 
   for (unsigned int i = 0; i < count; i++)
   {
-    unsigned int this_type = get_joining_type (buffer->info[i].codepoint, _hb_glyph_info_get_general_category (&buffer->info[i]));
+    unsigned int this_type = get_joining_type (info[i].codepoint, _hb_glyph_info_get_general_category (&info[i]));
 
     if (unlikely (this_type == JOINING_TYPE_T)) {
-      buffer->info[i].arabic_shaping_action() = NONE;
+      info[i].arabic_shaping_action() = NONE;
       continue;
     }
 
     const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
 
     if (entry->prev_action != NONE && prev != (unsigned int) -1)
-      for (; prev < i; prev++)
-	buffer->info[prev].arabic_shaping_action() = entry->prev_action;
+      info[prev].arabic_shaping_action() = entry->prev_action;
 
-    buffer->info[i].arabic_shaping_action() = entry->curr_action;
+    info[i].arabic_shaping_action() = entry->curr_action;
 
     prev = i;
     state = entry->next_state;
   }
 
-  if (!(buffer->flags & HB_BUFFER_FLAG_EOT))
-    for (unsigned int i = 0; i < buffer->context_len[1]; i++)
-    {
-      unsigned int this_type = get_joining_type (buffer->context[1][i], buffer->unicode->general_category (buffer->context[1][i]));
+  for (unsigned int i = 0; i < buffer->context_len[1]; i++)
+  {
+    unsigned int this_type = get_joining_type (buffer->context[1][i], buffer->unicode->general_category (buffer->context[1][i]));
 
-      if (unlikely (this_type == JOINING_TYPE_T))
-	continue;
+    if (unlikely (this_type == JOINING_TYPE_T))
+      continue;
 
-      const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
-      if (entry->prev_action != NONE && prev != (unsigned int) -1)
-	buffer->info[prev].arabic_shaping_action() = entry->prev_action;
-      break;
-    }
+    const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
+    if (entry->prev_action != NONE && prev != (unsigned int) -1)
+      info[prev].arabic_shaping_action() = entry->prev_action;
+    break;
+  }
+}
 
-
-  HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
+static void
+mongolian_variation_selectors (hb_buffer_t *buffer)
+{
+  /* Copy arabic_shaping_action() from base to Mongolian variation selectors. */
+  unsigned int count = buffer->len;
+  hb_glyph_info_t *info = buffer->info;
+  for (unsigned int i = 1; i < count; i++)
+    if (unlikely (hb_in_range (info[i].codepoint, 0x180Bu, 0x180Du)))
+      info[i].arabic_shaping_action() = info[i - 1].arabic_shaping_action();
 }
 
 static void
 setup_masks_arabic (const hb_ot_shape_plan_t *plan,
 		    hb_buffer_t              *buffer,
 		    hb_font_t                *font HB_UNUSED)
 {
+  HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action);
+
   const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
 
   arabic_joining (buffer);
+  if (plan->props.script == HB_SCRIPT_MONGOLIAN)
+    mongolian_variation_selectors (buffer);
+
   unsigned int count = buffer->len;
+  hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = 0; i < count; i++)
-    buffer->info[i].mask |= arabic_plan->mask_array[buffer->info[i].arabic_shaping_action()];
+    info[i].mask |= arabic_plan->mask_array[info[i].arabic_shaping_action()];
+
+  HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
 }
 
 
 static void
 nuke_joiners (const hb_ot_shape_plan_t *plan HB_UNUSED,
 	      hb_font_t *font HB_UNUSED,
 	      hb_buffer_t *buffer)
 {
   unsigned int count = buffer->len;
+  hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = 0; i < count; i++)
-    if (_hb_glyph_info_is_zwj (&buffer->info[i]))
-      _hb_glyph_info_flip_joiners (&buffer->info[i]);
+    if (_hb_glyph_info_is_zwj (&info[i]))
+      _hb_glyph_info_flip_joiners (&info[i]);
 }
 
 static void
 arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
 		       hb_font_t *font,
 		       hb_buffer_t *buffer)
 {
   const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc
@@ -54,16 +54,25 @@ static void
 collect_features_hangul (hb_ot_shape_planner_t *plan)
 {
   hb_ot_map_builder_t *map = &plan->map;
 
   for (unsigned int i = FIRST_HANGUL_FEATURE; i < HANGUL_FEATURE_COUNT; i++)
     map->add_feature (hangul_features[i], 1, F_NONE);
 }
 
+static void
+override_features_hangul (hb_ot_shape_planner_t *plan)
+{
+  /* Uniscribe does not apply 'calt' for Hangul, and certain fonts
+   * (Noto Sans CJK, Source Sans Han, etc) apply all of jamo lookups
+   * in calt, which is not desirable. */
+  plan->map.add_feature (HB_TAG('c','a','l','t'), 0, F_GLOBAL);
+}
+
 struct hangul_shape_plan_t
 {
   ASSERT_POD ();
 
   hb_mask_t mask_array[HANGUL_FEATURE_COUNT];
 };
 
 static void *
@@ -81,36 +90,36 @@ data_create_hangul (const hb_ot_shape_pl
 
 static void
 data_destroy_hangul (void *data)
 {
   free (data);
 }
 
 /* Constants for algorithmic hangul syllable [de]composition. */
-#define LBase 0x1100
-#define VBase 0x1161
-#define TBase 0x11A7
-#define LCount 19
-#define VCount 21
-#define TCount 28
-#define SBase 0xAC00
+#define LBase 0x1100u
+#define VBase 0x1161u
+#define TBase 0x11A7u
+#define LCount 19u
+#define VCount 21u
+#define TCount 28u
+#define SBase 0xAC00u
 #define NCount (VCount * TCount)
 #define SCount (LCount * NCount)
 
-#define isCombiningL(u) (hb_in_range<hb_codepoint_t> ((u), LBase, LBase+LCount-1))
-#define isCombiningV(u) (hb_in_range<hb_codepoint_t> ((u), VBase, VBase+VCount-1))
-#define isCombiningT(u) (hb_in_range<hb_codepoint_t> ((u), TBase+1, TBase+TCount-1))
-#define isCombinedS(u) (hb_in_range<hb_codepoint_t> ((u), SBase, SBase+SCount-1))
+#define isCombiningL(u) (hb_in_range ((u), LBase, LBase+LCount-1))
+#define isCombiningV(u) (hb_in_range ((u), VBase, VBase+VCount-1))
+#define isCombiningT(u) (hb_in_range ((u), TBase+1, TBase+TCount-1))
+#define isCombinedS(u) (hb_in_range ((u), SBase, SBase+SCount-1))
 
-#define isL(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1100, 0x115F, 0xA960, 0xA97C))
-#define isV(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1160, 0x11A7, 0xD7B0, 0xD7C6))
-#define isT(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x11A8, 0x11FF, 0xD7CB, 0xD7FB))
+#define isL(u) (hb_in_ranges ((u), 0x1100u, 0x115Fu, 0xA960u, 0xA97Cu))
+#define isV(u) (hb_in_ranges ((u), 0x1160u, 0x11A7u, 0xD7B0u, 0xD7C6u))
+#define isT(u) (hb_in_ranges ((u), 0x11A8u, 0x11FFu, 0xD7CBu, 0xD7FBu))
 
-#define isHangulTone(u) (hb_in_range<hb_codepoint_t> ((u), 0x302e, 0x302f))
+#define isHangulTone(u) (hb_in_range ((u), 0x302Eu, 0x302Fu))
 
 /* buffer var allocations */
 #define hangul_shaping_feature() complex_var_u8_0() /* hangul jamo shaping feature */
 
 static bool
 is_zero_width_char (hb_font_t *font,
 		    hb_codepoint_t unicode)
 {
@@ -206,24 +215,24 @@ preprocess_text_hangul (const hb_ot_shap
 	 * so that clustering behavior isn't dependent on how the tone mark
 	 * is handled by the font.
 	 */
 	buffer->merge_out_clusters (start, end + 1);
       }
       else
       {
 	/* No valid syllable as base for tone mark; try to insert dotted circle. */
-	if (font->has_glyph (0x25cc))
+	if (font->has_glyph (0x25CCu))
 	{
 	  hb_codepoint_t chars[2];
 	  if (!is_zero_width_char (font, u)) {
 	    chars[0] = u;
-	    chars[1] = 0x25cc;
+	    chars[1] = 0x25CCu;
 	  } else {
-	    chars[0] = 0x25cc;
+	    chars[0] = 0x25CCu;
 	    chars[1] = u;
 	  }
 	  buffer->replace_glyphs (1, 2, chars);
 	}
 	else
 	{
 	  /* No dotted circle available in the font; just leave tone mark untouched. */
 	  buffer->next_glyph ();
@@ -399,17 +408,17 @@ setup_masks_hangul (const hb_ot_shape_pl
   HB_BUFFER_DEALLOCATE_VAR (buffer, hangul_shaping_feature);
 }
 
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul =
 {
   "hangul",
   collect_features_hangul,
-  NULL, /* override_features */
+  override_features_hangul,
   data_create_hangul, /* data_create */
   data_destroy_hangul, /* data_destroy */
   preprocess_text_hangul,
   HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
   NULL, /* decompose */
   NULL, /* compose */
   setup_masks_hangul, /* setup_masks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
@@ -30,126 +30,126 @@
 static bool
 compose_hebrew (const hb_ot_shape_normalize_context_t *c,
 		hb_codepoint_t  a,
 		hb_codepoint_t  b,
 		hb_codepoint_t *ab)
 {
   /* Hebrew presentation-form shaping.
    * https://bugzilla.mozilla.org/show_bug.cgi?id=728866
-   * Hebrew presentation forms with dagesh, for characters 0x05D0..0x05EA;
+   * Hebrew presentation forms with dagesh, for characters U+05D0..05EA;
    * Note that some letters do not have a dagesh presForm encoded.
    */
-  static const hb_codepoint_t sDageshForms[0x05EA - 0x05D0 + 1] = {
-    0xFB30, /* ALEF */
-    0xFB31, /* BET */
-    0xFB32, /* GIMEL */
-    0xFB33, /* DALET */
-    0xFB34, /* HE */
-    0xFB35, /* VAV */
-    0xFB36, /* ZAYIN */
-    0x0000, /* HET */
-    0xFB38, /* TET */
-    0xFB39, /* YOD */
-    0xFB3A, /* FINAL KAF */
-    0xFB3B, /* KAF */
-    0xFB3C, /* LAMED */
-    0x0000, /* FINAL MEM */
-    0xFB3E, /* MEM */
-    0x0000, /* FINAL NUN */
-    0xFB40, /* NUN */
-    0xFB41, /* SAMEKH */
-    0x0000, /* AYIN */
-    0xFB43, /* FINAL PE */
-    0xFB44, /* PE */
-    0x0000, /* FINAL TSADI */
-    0xFB46, /* TSADI */
-    0xFB47, /* QOF */
-    0xFB48, /* RESH */
-    0xFB49, /* SHIN */
-    0xFB4A /* TAV */
+  static const hb_codepoint_t sDageshForms[0x05EAu - 0x05D0u + 1] = {
+    0xFB30u, /* ALEF */
+    0xFB31u, /* BET */
+    0xFB32u, /* GIMEL */
+    0xFB33u, /* DALET */
+    0xFB34u, /* HE */
+    0xFB35u, /* VAV */
+    0xFB36u, /* ZAYIN */
+    0x0000u, /* HET */
+    0xFB38u, /* TET */
+    0xFB39u, /* YOD */
+    0xFB3Au, /* FINAL KAF */
+    0xFB3Bu, /* KAF */
+    0xFB3Cu, /* LAMED */
+    0x0000u, /* FINAL MEM */
+    0xFB3Eu, /* MEM */
+    0x0000u, /* FINAL NUN */
+    0xFB40u, /* NUN */
+    0xFB41u, /* SAMEKH */
+    0x0000u, /* AYIN */
+    0xFB43u, /* FINAL PE */
+    0xFB44u, /* PE */
+    0x0000u, /* FINAL TSADI */
+    0xFB46u, /* TSADI */
+    0xFB47u, /* QOF */
+    0xFB48u, /* RESH */
+    0xFB49u, /* SHIN */
+    0xFB4Au /* TAV */
   };
 
   bool found = c->unicode->compose (a, b, ab);
 
-  if (!found)
+  if (!found && !c->plan->has_mark)
   {
       /* Special-case Hebrew presentation forms that are excluded from
        * standard normalization, but wanted for old fonts. */
       switch (b) {
-      case 0x05B4: /* HIRIQ */
-	  if (a == 0x05D9) { /* YOD */
-	      *ab = 0xFB1D;
+      case 0x05B4u: /* HIRIQ */
+	  if (a == 0x05D9u) { /* YOD */
+	      *ab = 0xFB1Du;
 	      found = true;
 	  }
 	  break;
-      case 0x05B7: /* patah */
-	  if (a == 0x05F2) { /* YIDDISH YOD YOD */
-	      *ab = 0xFB1F;
+      case 0x05B7u: /* patah */
+	  if (a == 0x05F2u) { /* YIDDISH YOD YOD */
+	      *ab = 0xFB1Fu;
 	      found = true;
-	  } else if (a == 0x05D0) { /* ALEF */
-	      *ab = 0xFB2E;
+	  } else if (a == 0x05D0u) { /* ALEF */
+	      *ab = 0xFB2Eu;
 	      found = true;
 	  }
 	  break;
-      case 0x05B8: /* QAMATS */
-	  if (a == 0x05D0) { /* ALEF */
-	      *ab = 0xFB2F;
+      case 0x05B8u: /* QAMATS */
+	  if (a == 0x05D0u) { /* ALEF */
+	      *ab = 0xFB2Fu;
 	      found = true;
 	  }
 	  break;
-      case 0x05B9: /* HOLAM */
-	  if (a == 0x05D5) { /* VAV */
-	      *ab = 0xFB4B;
+      case 0x05B9u: /* HOLAM */
+	  if (a == 0x05D5u) { /* VAV */
+	      *ab = 0xFB4Bu;
 	      found = true;
 	  }
 	  break;
-      case 0x05BC: /* DAGESH */
-	  if (a >= 0x05D0 && a <= 0x05EA) {
-	      *ab = sDageshForms[a - 0x05D0];
+      case 0x05BCu: /* DAGESH */
+	  if (a >= 0x05D0u && a <= 0x05EAu) {
+	      *ab = sDageshForms[a - 0x05D0u];
 	      found = (*ab != 0);
-	  } else if (a == 0xFB2A) { /* SHIN WITH SHIN DOT */
-	      *ab = 0xFB2C;
+	  } else if (a == 0xFB2Au) { /* SHIN WITH SHIN DOT */
+	      *ab = 0xFB2Cu;
 	      found = true;
-	  } else if (a == 0xFB2B) { /* SHIN WITH SIN DOT */
-	      *ab = 0xFB2D;
+	  } else if (a == 0xFB2Bu) { /* SHIN WITH SIN DOT */
+	      *ab = 0xFB2Du;
 	      found = true;
 	  }
 	  break;
-      case 0x05BF: /* RAFE */
+      case 0x05BFu: /* RAFE */
 	  switch (a) {
-	  case 0x05D1: /* BET */
-	      *ab = 0xFB4C;
+	  case 0x05D1u: /* BET */
+	      *ab = 0xFB4Cu;
 	      found = true;
 	      break;
-	  case 0x05DB: /* KAF */
-	      *ab = 0xFB4D;
+	  case 0x05DBu: /* KAF */
+	      *ab = 0xFB4Du;
 	      found = true;
 	      break;
-	  case 0x05E4: /* PE */
-	      *ab = 0xFB4E;
+	  case 0x05E4u: /* PE */
+	      *ab = 0xFB4Eu;
 	      found = true;
 	      break;
 	  }
 	  break;
-      case 0x05C1: /* SHIN DOT */
-	  if (a == 0x05E9) { /* SHIN */
-	      *ab = 0xFB2A;
+      case 0x05C1u: /* SHIN DOT */
+	  if (a == 0x05E9u) { /* SHIN */
+	      *ab = 0xFB2Au;
 	      found = true;
-	  } else if (a == 0xFB49) { /* SHIN WITH DAGESH */
-	      *ab = 0xFB2C;
+	  } else if (a == 0xFB49u) { /* SHIN WITH DAGESH */
+	      *ab = 0xFB2Cu;
 	      found = true;
 	  }
 	  break;
-      case 0x05C2: /* SIN DOT */
-	  if (a == 0x05E9) { /* SHIN */
-	      *ab = 0xFB2B;
+      case 0x05C2u: /* SIN DOT */
+	  if (a == 0x05E9u) { /* SHIN */
+	      *ab = 0xFB2Bu;
 	      found = true;
-	  } else if (a == 0xFB49) { /* SHIN WITH DAGESH */
-	      *ab = 0xFB2D;
+	  } else if (a == 0xFB49u) { /* SHIN WITH DAGESH */
+	      *ab = 0xFB2Du;
 	      found = true;
 	  }
 	  break;
       }
   }
 
   return found;
 }
@@ -162,11 +162,11 @@ const hb_ot_complex_shaper_t _hb_ot_comp
   NULL, /* override_features */
   NULL, /* data_create */
   NULL, /* data_destroy */
   NULL, /* preprocess_text */
   HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
   NULL, /* decompose */
   compose_hebrew,
   NULL, /* setup_masks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT,
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
 };
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
@@ -27,17 +27,17 @@
  */
 
 #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 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp"
 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, 
@@ -50,62 +50,62 @@ static const unsigned char _indic_syllab
 	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, 18u, 3u, 31u, 
-	3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 
-	3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 18u, 8u, 18u, 
-	5u, 10u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 18u, 3u, 18u, 8u, 18u, 
-	3u, 10u, 8u, 10u, 3u, 18u, 3u, 18u, 3u, 18u, 3u, 18u, 4u, 18u, 5u, 18u, 
-	3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u, 
-	6u, 18u, 3u, 18u, 1u, 18u, 4u, 31u, 4u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 
-	1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 
-	1u, 18u, 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u, 
-	1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u, 
-	1u, 18u, 3u, 31u, 3u, 31u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 
-	3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 
-	3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 18u, 8u, 18u, 
-	5u, 10u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 18u, 3u, 18u, 8u, 18u, 
-	3u, 10u, 8u, 10u, 3u, 18u, 3u, 18u, 3u, 18u, 3u, 18u, 4u, 18u, 5u, 18u, 
-	3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u, 
-	6u, 18u, 3u, 18u, 1u, 18u, 4u, 31u, 4u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 
-	1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 
-	1u, 18u, 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u, 
-	1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u, 
-	4u, 14u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 
-	4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 
-	4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 18u, 8u, 18u, 5u, 10u, 
-	9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 18u, 3u, 18u, 8u, 18u, 3u, 10u, 
-	8u, 10u, 3u, 18u, 3u, 18u, 3u, 18u, 3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 
-	4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u, 6u, 18u, 
-	3u, 18u, 1u, 18u, 4u, 31u, 4u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 
-	1u, 18u, 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u, 
-	1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u, 
-	1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u, 
-	4u, 14u, 3u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 
-	3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 
-	3u, 31u, 4u, 31u, 1u, 18u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 18u, 8u, 18u, 
-	5u, 10u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 18u, 3u, 18u, 8u, 18u, 
-	3u, 10u, 8u, 10u, 3u, 18u, 3u, 18u, 3u, 18u, 3u, 18u, 4u, 18u, 5u, 18u, 
-	3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u, 
-	6u, 18u, 3u, 18u, 1u, 18u, 4u, 31u, 4u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 
-	1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 
-	1u, 18u, 1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u, 
-	1u, 18u, 1u, 18u, 3u, 31u, 3u, 31u, 1u, 18u, 1u, 18u, 1u, 18u, 1u, 18u, 
-	1u, 18u, 3u, 31u, 1u, 31u, 3u, 31u, 1u, 31u, 4u, 18u, 1u, 18u, 3u, 31u, 
-	3u, 31u, 4u, 31u, 5u, 10u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 10u, 
-	8u, 10u, 3u, 31u, 3u, 31u, 1u, 18u, 3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 
-	4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u, 5u, 18u, 3u, 18u, 4u, 18u, 8u, 18u, 
-	3u, 18u, 3u, 18u, 8u, 18u, 3u, 18u, 3u, 18u, 1u, 18u, 3u, 10u, 8u, 10u, 
-	5u, 10u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 0
+	6u, 6u, 16u, 16u, 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, 
+	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, 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, 
+	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, 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, 
+	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, 
+	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, 
+	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, 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, 
+	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, 
@@ -120,62 +120,62 @@ static const char _indic_syllable_machin
 	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, 
-	1, 1, 31, 29, 29, 28, 18, 29, 
-	29, 28, 18, 29, 29, 28, 18, 29, 
-	29, 28, 18, 29, 29, 28, 14, 11, 
-	6, 2, 2, 1, 6, 16, 16, 11, 
-	8, 3, 16, 16, 16, 16, 15, 14, 
-	16, 15, 14, 16, 15, 14, 16, 15, 
-	13, 16, 18, 28, 15, 29, 29, 18, 
-	18, 18, 18, 18, 29, 29, 18, 18, 
-	18, 18, 18, 29, 29, 18, 18, 18, 
-	18, 18, 29, 29, 18, 18, 18, 18, 
-	18, 29, 29, 29, 29, 28, 18, 29, 
-	29, 28, 18, 29, 29, 28, 18, 29, 
-	29, 28, 18, 29, 29, 28, 14, 11, 
-	6, 2, 2, 1, 6, 16, 16, 11, 
-	8, 3, 16, 16, 16, 16, 15, 14, 
-	16, 15, 14, 16, 15, 14, 16, 15, 
-	13, 16, 18, 28, 15, 29, 29, 18, 
-	18, 18, 18, 18, 29, 29, 18, 18, 
-	18, 18, 18, 29, 29, 18, 18, 18, 
-	18, 18, 29, 29, 18, 18, 18, 18, 
-	11, 18, 29, 29, 28, 18, 29, 29, 
-	28, 18, 29, 29, 28, 18, 29, 29, 
-	28, 18, 29, 29, 28, 14, 11, 6, 
-	2, 2, 1, 6, 16, 16, 11, 8, 
-	3, 16, 16, 16, 16, 15, 14, 16, 
-	15, 14, 16, 15, 14, 16, 15, 13, 
-	16, 18, 28, 15, 29, 29, 18, 18, 
-	18, 18, 18, 29, 29, 18, 18, 18, 
-	18, 18, 29, 29, 18, 18, 18, 18, 
-	18, 29, 29, 18, 18, 18, 18, 18, 
-	11, 29, 11, 29, 29, 28, 18, 29, 
-	29, 28, 18, 29, 29, 28, 18, 29, 
-	29, 28, 18, 29, 29, 28, 14, 11, 
-	6, 2, 2, 1, 6, 16, 16, 11, 
-	8, 3, 16, 16, 16, 16, 15, 14, 
-	16, 15, 14, 16, 15, 14, 16, 15, 
-	13, 16, 18, 28, 15, 29, 29, 18, 
-	18, 18, 18, 18, 29, 29, 18, 18, 
-	18, 18, 18, 29, 29, 18, 18, 18, 
-	18, 18, 29, 29, 18, 18, 18, 18, 
-	18, 29, 31, 29, 31, 15, 18, 29, 
-	29, 28, 6, 2, 2, 1, 6, 8, 
-	3, 29, 29, 18, 16, 15, 14, 16, 
-	15, 14, 16, 15, 14, 16, 15, 11, 
-	16, 16, 11, 16, 16, 18, 8, 3, 
-	6, 2, 2, 1, 6
+	1, 1, 31, 29, 29, 28, 16, 29, 
+	29, 28, 16, 29, 29, 28, 16, 29, 
+	29, 28, 16, 29, 29, 28, 10, 7, 
+	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, 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, 
+	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, 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, 
+	2, 1, 2, 2, 1, 6, 11, 8, 
+	3, 8, 11, 12, 12, 11, 10, 12, 
+	11, 10, 12, 11, 10, 12, 11, 9, 
+	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, 
+	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, 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, 
+	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, 
@@ -190,62 +190,62 @@ static const short _indic_syllable_machi
 	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, 1090, 
-	1120, 1150, 1179, 1198, 1228, 1258, 1287, 1306, 
-	1336, 1366, 1395, 1414, 1444, 1474, 1503, 1518, 
-	1530, 1537, 1540, 1543, 1545, 1552, 1569, 1586, 
-	1598, 1607, 1611, 1628, 1645, 1662, 1679, 1695, 
-	1710, 1727, 1743, 1758, 1775, 1791, 1806, 1823, 
-	1839, 1853, 1870, 1889, 1918, 1934, 1964, 1994, 
-	2013, 2032, 2051, 2070, 2089, 2119, 2149, 2168, 
-	2187, 2206, 2225, 2244, 2274, 2304, 2323, 2342, 
-	2361, 2380, 2399, 2429, 2459, 2478, 2497, 2516, 
-	2535, 2554, 2584, 2614, 2644, 2674, 2703, 2722, 
-	2752, 2782, 2811, 2830, 2860, 2890, 2919, 2938, 
-	2968, 2998, 3027, 3046, 3076, 3106, 3135, 3150, 
-	3162, 3169, 3172, 3175, 3177, 3184, 3201, 3218, 
-	3230, 3239, 3243, 3260, 3277, 3294, 3311, 3327, 
-	3342, 3359, 3375, 3390, 3407, 3423, 3438, 3455, 
-	3471, 3485, 3502, 3521, 3550, 3566, 3596, 3626, 
-	3645, 3664, 3683, 3702, 3721, 3751, 3781, 3800, 
-	3819, 3838, 3857, 3876, 3906, 3936, 3955, 3974, 
-	3993, 4012, 4031, 4061, 4091, 4110, 4129, 4148, 
-	4167, 4179, 4198, 4228, 4258, 4287, 4306, 4336, 
-	4366, 4395, 4414, 4444, 4474, 4503, 4522, 4552, 
-	4582, 4611, 4630, 4660, 4690, 4719, 4734, 4746, 
-	4753, 4756, 4759, 4761, 4768, 4785, 4802, 4814, 
-	4823, 4827, 4844, 4861, 4878, 4895, 4911, 4926, 
-	4943, 4959, 4974, 4991, 5007, 5022, 5039, 5055, 
-	5069, 5086, 5105, 5134, 5150, 5180, 5210, 5229, 
-	5248, 5267, 5286, 5305, 5335, 5365, 5384, 5403, 
-	5422, 5441, 5460, 5490, 5520, 5539, 5558, 5577, 
-	5596, 5615, 5645, 5675, 5694, 5713, 5732, 5751, 
-	5770, 5782, 5812, 5824, 5854, 5884, 5913, 5932, 
-	5962, 5992, 6021, 6040, 6070, 6100, 6129, 6148, 
-	6178, 6208, 6237, 6256, 6286, 6316, 6345, 6360, 
-	6372, 6379, 6382, 6385, 6387, 6394, 6411, 6428, 
-	6440, 6449, 6453, 6470, 6487, 6504, 6521, 6537, 
-	6552, 6569, 6585, 6600, 6617, 6633, 6648, 6665, 
-	6681, 6695, 6712, 6731, 6760, 6776, 6806, 6836, 
-	6855, 6874, 6893, 6912, 6931, 6961, 6991, 7010, 
-	7029, 7048, 7067, 7086, 7116, 7146, 7165, 7184, 
-	7203, 7222, 7241, 7271, 7301, 7320, 7339, 7358, 
-	7377, 7396, 7426, 7458, 7488, 7520, 7536, 7555, 
-	7585, 7615, 7644, 7651, 7654, 7657, 7659, 7666, 
-	7675, 7679, 7709, 7739, 7758, 7775, 7791, 7806, 
-	7823, 7839, 7854, 7871, 7887, 7902, 7919, 7935, 
-	7947, 7964, 7981, 7993, 8010, 8027, 8046, 8055, 
-	8059, 8066, 8069, 8072, 8074
+	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
 };
 
 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, 
@@ -363,975 +363,883 @@ static const short _indic_syllable_machi
 	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, 207, 197, 197, 
+	37, 205, 197, 197, 206, 197, 197, 197, 
 	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 208, 197, 209, 199, 210, 210, 
+	197, 197, 207, 197, 208, 199, 209, 209, 
 	5, 202, 203, 204, 197, 197, 197, 205, 
-	197, 197, 206, 207, 197, 197, 197, 197, 
+	197, 197, 206, 197, 197, 197, 197, 197, 
 	197, 197, 197, 197, 197, 197, 197, 197, 
-	208, 197, 199, 210, 210, 5, 202, 203, 
+	207, 197, 199, 209, 209, 5, 202, 203, 
 	204, 197, 197, 197, 205, 197, 197, 206, 
-	207, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 208, 197, 211, 
-	197, 197, 197, 18, 212, 197, 202, 203, 
-	204, 197, 197, 197, 213, 197, 211, 197, 
-	207, 197, 214, 215, 216, 217, 5, 202, 
-	203, 204, 197, 197, 35, 218, 197, 197, 
-	206, 207, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 208, 197, 
-	219, 215, 220, 220, 5, 202, 203, 204, 
-	197, 197, 197, 218, 197, 197, 206, 207, 
+	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, 208, 197, 215, 220, 
-	220, 5, 202, 203, 204, 197, 197, 197, 
-	218, 197, 197, 206, 207, 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, 
-	197, 208, 197, 221, 197, 197, 197, 18, 
-	222, 197, 202, 203, 204, 197, 197, 197, 
-	213, 197, 221, 197, 207, 197, 223, 224, 
-	225, 226, 5, 202, 203, 204, 197, 197, 
-	33, 227, 197, 197, 206, 207, 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, 208, 197, 228, 224, 229, 229, 
-	5, 202, 203, 204, 197, 197, 197, 227, 
-	197, 197, 206, 207, 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, 
-	208, 197, 224, 229, 229, 5, 202, 203, 
-	204, 197, 197, 197, 227, 197, 197, 206, 
-	207, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 208, 197, 230, 
-	197, 197, 197, 18, 231, 197, 202, 203, 
-	204, 197, 197, 197, 213, 197, 230, 197, 
-	207, 197, 232, 233, 234, 235, 5, 202, 
-	203, 204, 197, 197, 31, 236, 197, 197, 
-	206, 207, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 208, 197, 
-	237, 233, 238, 238, 5, 202, 203, 204, 
-	197, 197, 197, 236, 197, 197, 206, 207, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 208, 197, 233, 238, 
-	238, 5, 202, 203, 204, 197, 197, 197, 
-	236, 197, 197, 206, 207, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 208, 197, 239, 197, 197, 197, 18, 
-	240, 197, 202, 203, 204, 197, 197, 197, 
-	213, 197, 239, 197, 207, 197, 241, 242, 
-	243, 244, 5, 202, 203, 204, 197, 197, 
-	29, 245, 197, 197, 206, 207, 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, 208, 197, 246, 242, 247, 247, 
-	5, 202, 203, 204, 197, 197, 197, 245, 
-	197, 197, 206, 207, 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, 
-	208, 197, 242, 247, 247, 5, 202, 203, 
-	204, 197, 197, 197, 245, 197, 197, 206, 
-	207, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 208, 197, 18, 
-	248, 197, 202, 203, 204, 197, 197, 197, 
-	213, 197, 197, 197, 207, 197, 202, 203, 
-	204, 197, 197, 197, 213, 197, 197, 197, 
-	207, 197, 249, 197, 197, 250, 203, 204, 
-	197, 203, 204, 197, 203, 251, 197, 203, 
-	197, 249, 197, 197, 197, 203, 204, 197, 
-	252, 197, 253, 254, 197, 202, 203, 204, 
-	197, 197, 3, 197, 197, 197, 197, 207, 
-	197, 2, 197, 197, 197, 197, 202, 203, 
-	204, 197, 197, 197, 197, 197, 197, 197, 
-	207, 197, 202, 203, 204, 197, 197, 197, 
-	197, 197, 197, 197, 207, 197, 255, 197, 
-	197, 197, 197, 202, 203, 204, 197, 202, 
-	203, 204, 197, 252, 197, 197, 197, 197, 
-	202, 203, 204, 197, 197, 197, 197, 197, 
-	197, 197, 207, 197, 252, 197, 253, 197, 
-	197, 202, 203, 204, 197, 197, 3, 197, 
-	197, 197, 197, 207, 197, 18, 197, 256, 
+	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, 
-	213, 197, 197, 197, 207, 197, 257, 27, 
-	258, 259, 8, 202, 203, 204, 197, 197, 
-	197, 213, 197, 197, 197, 207, 197, 27, 
-	258, 259, 8, 202, 203, 204, 197, 197, 
-	197, 213, 197, 197, 197, 207, 197, 258, 
-	258, 8, 202, 203, 204, 197, 197, 197, 
-	213, 197, 197, 197, 207, 197, 260, 24, 
-	261, 262, 11, 202, 203, 204, 197, 197, 
-	197, 213, 197, 197, 197, 207, 197, 24, 
-	261, 262, 11, 202, 203, 204, 197, 197, 
-	197, 213, 197, 197, 197, 207, 197, 261, 
-	261, 11, 202, 203, 204, 197, 197, 197, 
-	213, 197, 197, 197, 207, 197, 263, 21, 
-	264, 265, 14, 202, 203, 204, 197, 197, 
-	197, 213, 197, 197, 197, 207, 197, 21, 
-	264, 265, 14, 202, 203, 204, 197, 197, 
-	197, 213, 197, 197, 197, 207, 197, 264, 
-	264, 14, 202, 203, 204, 197, 197, 197, 
-	213, 197, 197, 197, 207, 197, 266, 18, 
-	197, 267, 197, 202, 203, 204, 197, 197, 
-	197, 213, 197, 197, 197, 207, 197, 18, 
-	197, 267, 197, 202, 203, 204, 197, 197, 
-	197, 213, 197, 197, 197, 207, 197, 268, 
-	197, 202, 203, 204, 197, 197, 197, 213, 
-	197, 197, 197, 207, 197, 18, 197, 197, 
-	197, 197, 202, 203, 204, 197, 197, 197, 
-	213, 197, 197, 197, 207, 197, 1, 2, 
-	197, 197, 18, 248, 197, 202, 203, 204, 
-	197, 197, 197, 213, 197, 1, 197, 207, 
-	197, 242, 247, 247, 5, 202, 203, 204, 
-	197, 197, 197, 245, 197, 197, 197, 207, 
+	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, 208, 197, 242, 247, 
-	247, 5, 202, 203, 204, 197, 197, 197, 
-	245, 197, 197, 197, 207, 197, 241, 242, 
-	247, 247, 5, 202, 203, 204, 197, 197, 
-	197, 245, 197, 197, 206, 207, 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, 208, 197, 241, 242, 243, 247, 
-	5, 202, 203, 204, 197, 197, 29, 245, 
-	197, 197, 206, 207, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	208, 197, 239, 197, 269, 197, 256, 256, 
-	5, 202, 203, 204, 197, 197, 197, 213, 
-	197, 239, 197, 207, 197, 239, 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, 213, 197, 239, 197, 207, 197, 
-	239, 197, 197, 197, 197, 270, 197, 202, 
-	203, 204, 197, 197, 197, 213, 197, 239, 
-	197, 207, 197, 239, 197, 269, 197, 197, 
-	197, 197, 202, 203, 204, 197, 197, 197, 
-	213, 197, 239, 197, 207, 197, 239, 2, 
-	197, 197, 18, 240, 197, 202, 203, 204, 
-	197, 197, 197, 213, 197, 239, 197, 207, 
-	197, 232, 233, 238, 238, 5, 202, 203, 
-	204, 197, 197, 197, 236, 197, 197, 206, 
-	207, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 208, 197, 232, 
-	233, 234, 238, 5, 202, 203, 204, 197, 
-	197, 31, 236, 197, 197, 206, 207, 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, 208, 197, 230, 197, 271, 
-	197, 256, 256, 5, 202, 203, 204, 197, 
-	197, 197, 213, 197, 230, 197, 207, 197, 
-	230, 197, 197, 197, 197, 197, 197, 202, 
-	203, 204, 197, 197, 197, 213, 197, 230, 
-	197, 207, 197, 230, 197, 197, 197, 197, 
-	272, 197, 202, 203, 204, 197, 197, 197, 
-	213, 197, 230, 197, 207, 197, 230, 197, 
-	271, 197, 197, 197, 197, 202, 203, 204, 
-	197, 197, 197, 213, 197, 230, 197, 207, 
-	197, 230, 2, 197, 197, 18, 231, 197, 
-	202, 203, 204, 197, 197, 197, 213, 197, 
-	230, 197, 207, 197, 223, 224, 229, 229, 
-	5, 202, 203, 204, 197, 197, 197, 227, 
-	197, 197, 206, 207, 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, 
-	208, 197, 223, 224, 225, 229, 5, 202, 
-	203, 204, 197, 197, 33, 227, 197, 197, 
-	206, 207, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 208, 197, 
-	221, 197, 273, 197, 256, 256, 5, 202, 
-	203, 204, 197, 197, 197, 213, 197, 221, 
-	197, 207, 197, 221, 197, 197, 197, 197, 
-	197, 197, 202, 203, 204, 197, 197, 197, 
-	213, 197, 221, 197, 207, 197, 221, 197, 
-	197, 197, 197, 274, 197, 202, 203, 204, 
-	197, 197, 197, 213, 197, 221, 197, 207, 
-	197, 221, 197, 273, 197, 197, 197, 197, 
-	202, 203, 204, 197, 197, 197, 213, 197, 
-	221, 197, 207, 197, 221, 2, 197, 197, 
-	18, 222, 197, 202, 203, 204, 197, 197, 
-	197, 213, 197, 221, 197, 207, 197, 214, 
-	215, 220, 220, 5, 202, 203, 204, 197, 
-	197, 197, 218, 197, 197, 206, 207, 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, 208, 197, 214, 215, 216, 
-	220, 5, 202, 203, 204, 197, 197, 35, 
-	218, 197, 197, 206, 207, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 208, 197, 211, 197, 275, 197, 256, 
-	256, 5, 202, 203, 204, 197, 197, 197, 
-	213, 197, 211, 197, 207, 197, 211, 197, 
-	197, 197, 197, 197, 197, 202, 203, 204, 
-	197, 197, 197, 213, 197, 211, 197, 207, 
-	197, 211, 197, 197, 197, 197, 276, 197, 
-	202, 203, 204, 197, 197, 197, 213, 197, 
-	211, 197, 207, 197, 211, 197, 275, 197, 
-	197, 197, 197, 202, 203, 204, 197, 197, 
-	197, 213, 197, 211, 197, 207, 197, 211, 
-	2, 197, 197, 18, 212, 197, 202, 203, 
-	204, 197, 197, 197, 213, 197, 211, 197, 
-	207, 197, 198, 199, 210, 210, 5, 202, 
-	203, 204, 197, 197, 197, 205, 197, 197, 
-	206, 207, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 208, 197, 
-	198, 199, 200, 210, 5, 202, 203, 204, 
-	197, 197, 37, 205, 197, 197, 206, 207, 
-	197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 208, 197, 278, 279, 
+	197, 197, 197, 197, 207, 197, 278, 279, 
 	280, 281, 43, 282, 283, 284, 277, 277, 
-	75, 285, 277, 277, 286, 287, 277, 277, 
+	75, 285, 277, 277, 286, 277, 277, 277, 
 	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 288, 277, 289, 279, 290, 281, 
+	277, 277, 287, 277, 288, 279, 289, 281, 
 	43, 282, 283, 284, 277, 277, 277, 285, 
-	277, 277, 286, 287, 277, 277, 277, 277, 
+	277, 277, 286, 277, 277, 277, 277, 277, 
 	277, 277, 277, 277, 277, 277, 277, 277, 
-	288, 277, 279, 290, 281, 43, 282, 283, 
+	287, 277, 279, 289, 281, 43, 282, 283, 
 	284, 277, 277, 277, 285, 277, 277, 286, 
-	287, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 288, 277, 291, 
-	277, 277, 277, 56, 292, 277, 282, 283, 
-	284, 277, 277, 277, 293, 277, 291, 277, 
-	287, 277, 294, 295, 296, 297, 43, 282, 
-	283, 284, 277, 277, 73, 298, 277, 277, 
-	286, 287, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 288, 277, 
-	299, 295, 300, 300, 43, 282, 283, 284, 
-	277, 277, 277, 298, 277, 277, 286, 287, 
+	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, 288, 277, 295, 300, 
-	300, 43, 282, 283, 284, 277, 277, 277, 
-	298, 277, 277, 286, 287, 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, 
-	277, 288, 277, 301, 277, 277, 277, 56, 
-	302, 277, 282, 283, 284, 277, 277, 277, 
-	293, 277, 301, 277, 287, 277, 303, 304, 
-	305, 306, 43, 282, 283, 284, 277, 277, 
-	71, 307, 277, 277, 286, 287, 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, 288, 277, 308, 304, 309, 309, 
-	43, 282, 283, 284, 277, 277, 277, 307, 
-	277, 277, 286, 287, 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, 
-	288, 277, 304, 309, 309, 43, 282, 283, 
-	284, 277, 277, 277, 307, 277, 277, 286, 
-	287, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 288, 277, 310, 
-	277, 277, 277, 56, 311, 277, 282, 283, 
-	284, 277, 277, 277, 293, 277, 310, 277, 
-	287, 277, 312, 313, 314, 315, 43, 282, 
-	283, 284, 277, 277, 69, 316, 277, 277, 
-	286, 287, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 288, 277, 
-	317, 313, 318, 318, 43, 282, 283, 284, 
-	277, 277, 277, 316, 277, 277, 286, 287, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 288, 277, 313, 318, 
-	318, 43, 282, 283, 284, 277, 277, 277, 
-	316, 277, 277, 286, 287, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	277, 288, 277, 319, 277, 277, 277, 56, 
-	320, 277, 282, 283, 284, 277, 277, 277, 
-	293, 277, 319, 277, 287, 277, 321, 322, 
-	323, 324, 43, 282, 283, 284, 277, 277, 
-	67, 325, 277, 277, 286, 287, 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, 288, 277, 326, 322, 327, 327, 
-	43, 282, 283, 284, 277, 277, 277, 325, 
-	277, 277, 286, 287, 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, 
-	288, 277, 322, 327, 327, 43, 282, 283, 
-	284, 277, 277, 277, 325, 277, 277, 286, 
-	287, 277, 277, 277, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 288, 277, 56, 
-	328, 277, 282, 283, 284, 277, 277, 277, 
-	293, 277, 277, 277, 287, 277, 282, 283, 
-	284, 277, 277, 277, 293, 277, 277, 277, 
-	287, 277, 329, 277, 277, 330, 283, 284, 
-	277, 283, 284, 277, 283, 331, 277, 283, 
-	277, 329, 277, 277, 277, 283, 284, 277, 
-	332, 277, 333, 334, 277, 282, 283, 284, 
-	277, 277, 41, 277, 277, 277, 277, 287, 
-	277, 40, 277, 277, 277, 277, 282, 283, 
-	284, 277, 277, 277, 277, 277, 277, 277, 
-	287, 277, 282, 283, 284, 277, 277, 277, 
-	277, 277, 277, 277, 287, 277, 335, 277, 
-	277, 277, 277, 282, 283, 284, 277, 282, 
-	283, 284, 277, 332, 277, 277, 277, 277, 
-	282, 283, 284, 277, 277, 277, 277, 277, 
-	277, 277, 287, 277, 332, 277, 333, 277, 
-	277, 282, 283, 284, 277, 277, 41, 277, 
-	277, 277, 277, 287, 277, 56, 277, 336, 
+	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, 
-	293, 277, 277, 277, 287, 277, 337, 65, 
-	338, 339, 46, 282, 283, 284, 277, 277, 
-	277, 293, 277, 277, 277, 287, 277, 65, 
-	338, 339, 46, 282, 283, 284, 277, 277, 
-	277, 293, 277, 277, 277, 287, 277, 338, 
-	338, 46, 282, 283, 284, 277, 277, 277, 
-	293, 277, 277, 277, 287, 277, 340, 62, 
-	341, 342, 49, 282, 283, 284, 277, 277, 
-	277, 293, 277, 277, 277, 287, 277, 62, 
-	341, 342, 49, 282, 283, 284, 277, 277, 
-	277, 293, 277, 277, 277, 287, 277, 341, 
-	341, 49, 282, 283, 284, 277, 277, 277, 
-	293, 277, 277, 277, 287, 277, 343, 59, 
-	344, 345, 52, 282, 283, 284, 277, 277, 
-	277, 293, 277, 277, 277, 287, 277, 59, 
-	344, 345, 52, 282, 283, 284, 277, 277, 
-	277, 293, 277, 277, 277, 287, 277, 344, 
-	344, 52, 282, 283, 284, 277, 277, 277, 
-	293, 277, 277, 277, 287, 277, 346, 56, 
-	277, 347, 277, 282, 283, 284, 277, 277, 
-	277, 293, 277, 277, 277, 287, 277, 56, 
-	277, 347, 277, 282, 283, 284, 277, 277, 
-	277, 293, 277, 277, 277, 287, 277, 348, 
-	277, 282, 283, 284, 277, 277, 277, 293, 
-	277, 277, 277, 287, 277, 56, 277, 277, 
-	277, 277, 282, 283, 284, 277, 277, 277, 
-	293, 277, 277, 277, 287, 277, 39, 40, 
-	277, 277, 56, 328, 277, 282, 283, 284, 
-	277, 277, 277, 293, 277, 39, 277, 287, 
-	277, 322, 327, 327, 43, 282, 283, 284, 
-	277, 277, 277, 325, 277, 277, 277, 287, 
+	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, 288, 277, 322, 327, 
-	327, 43, 282, 283, 284, 277, 277, 277, 
-	325, 277, 277, 277, 287, 277, 321, 322, 
-	327, 327, 43, 282, 283, 284, 277, 277, 
-	277, 325, 277, 277, 286, 287, 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, 288, 277, 321, 322, 323, 327, 
-	43, 282, 283, 284, 277, 277, 67, 325, 
-	277, 277, 286, 287, 277, 277, 277, 277, 
-	277, 277, 277, 277, 277, 277, 277, 277, 
-	288, 277, 319, 277, 349, 277, 336, 336, 
-	43, 282, 283, 284, 277, 277, 277, 293, 
-	277, 319, 277, 287, 277, 319, 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, 293, 277, 319, 277, 287, 277, 
-	319, 277, 277, 277, 277, 350, 277, 282, 
-	283, 284, 277, 277, 277, 293, 277, 319, 
-	277, 287, 277, 319, 277, 349, 277, 277,