Update harfbuzz to 1.2.6 from 1.2.1
am: e9f6b1c

* commit 'e9f6b1c7f914c87661cecd99f954204a4415e0d4': (47 commits)
  1.2.6
  Blacklist another set of timesi.ttf and timesbi.ttf
  Fix when no feature is given
  1.2.5
  Add test for 6dd80faf0dcb3e8a8915c3a25da44e2a67cb0cd8
  [coretext] Clarify comment
  Fix FixedVersion::to_int()
  Hide justification behind HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
  Use standard types instead Windows favourites ones
  Limit GetJustifiedGlyphs only to scripts with custom justification character
  Add justification support
  Basic opentype features support
  Refactor and remove dupe getglyphs call
  Better glyph offset support
  Don't fail when language is not set
  Make DirectWrite backend to work with different font sizes
  1.2.4
  Synthesize GDEF glyph class for any glyph that does not have one in GDEF
  [build] Use tar-ustar instead of tar-pax
  Minor comment
  ...

Change-Id: I58c6da539823ad94e5da3f87a92cde02ad3f71dc
diff --git a/NEWS b/NEWS
index b1b63b2..721d528 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,91 @@
+Overview of changes leading to 1.2.6
+Friday, April 8, 2016
+====================================
+
+- Blacklist GDEF table of another set of Times New Roman (Bold) Italic.
+- DirectWrite backend improvements.  Note: DirectWrite backend is
+  exclusively for our internal testing and should NOT be used in any
+  production system whatsoever.
+
+
+Overview of changes leading to 1.2.5
+Monday, April 4, 2016
+====================================
+
+- Fix GDEF mark-filtering-set, which was broken in 1.2.3.
+
+
+Overview of changes leading to 1.2.4
+Thursday, March 17, 2016
+====================================
+
+- Synthesize GDEF glyph class for any glyph that does not have one in GDEF.
+  I really hope we don't discover broken fonts that shape badly with this
+  change.
+- Misc build and other minor fixes.
+- API changes:
+  - Added HB_NDEBUG.  It's fine for production systems to define this to
+    disable high-overhead debugging checks.  However, I also reduced the
+    overhead of those checks, so it's a non-issue right now.  You can
+    forget it.  Just not defining anything at all is fine.
+
+
+Overview of changes leading to 1.2.3
+Thursday, February 25, 2016
+====================================
+
+- Blacklist GDEF table of certain versions of Times New Roman (Bold) Italic,
+  due to bug in glyph class of ASCII double-quote character.  This should
+  address "regression" introduced in 1.2.0 when we switched mark zeroing
+  in most shapers from BY_UNICODE_LATE to BY_GDEF_LATE.
+  This fourth release in a week should finally stablize things...
+
+- hb-ot-font's get_glyph() implementation saw some optimizations.  Though,
+  might be really hard to measure in real-world situations.
+
+- Also, two rather small API changes:
+
+We now disable some time-consuming internal bookkeeping if built with NDEBUG
+defined.  This is a first time that we use NDEBUG to disable debug code.  If
+there exist production systems that do NOT want to enable NDEBUG, please let
+me know and I'll add HB_NDEBUG.
+
+Added get_nominal_glyph() and get_variation_glyph() instead of get_glyph()
+
+New API:
+- hb_font_get_nominal_glyph_func_t
+- hb_font_get_variation_glyph_func_t
+- hb_font_funcs_set_nominal_glyph_func()
+- hb_font_funcs_set_variation_glyph_func()
+- hb_font_get_nominal_glyph()
+- hb_font_get_variation_glyph()
+
+Deprecated API:
+- hb_font_get_glyph_func_t
+- hb_font_funcs_set_glyph_func()
+
+Clients that implement their own font-funcs are encouraged to replace
+their get_glyph() implementation with a get_nominal_glyph() and
+get_variation_glyph() pair.  The variation version can assume that
+variation_selector argument is not zero.  Old (deprecated) functions
+will continue working indefinitely using internal gymnastics; it is
+just more efficient to use the new functions.
+
+
+Overview of changes leading to 1.2.2
+Wednesday, February 24, 2016
+====================================
+
+- Fix regression with mark positioning with fonts that have
+  non-zero mark advances.  This was introduced in 1.2.0 while
+  trying to make mark and cursive attachments to work together.
+  I have partially reverted that, so this version is much more
+  like what we had before.  All clients who updated to 1.2.0
+  should update to this version.
+
+
 Overview of changes leading to 1.2.1
-Friday, February 23, 2016
+Tuesday, February 23, 2016
 ====================================
 
 - CoreText: Fix bug with wrong scale if font scale was changed later.
diff --git a/README.version b/README.version
index 65ac146..6f84cc9 100644
--- a/README.version
+++ b/README.version
@@ -1,3 +1,3 @@
-URL: http://www.freedesktop.org/software/harfbuzz/release/harfbuzz-1.2.1.tar.bz2
-Version: 1.2.1
+URL: http://www.freedesktop.org/software/harfbuzz/release/harfbuzz-1.2.6.tar.bz2
+Version: 1.2.6
 BugComponent: 25699
diff --git a/TODO b/TODO
index e1aa39c..4f37f60 100644
--- a/TODO
+++ b/TODO
@@ -9,26 +9,14 @@
 
 - mask propagation? (when ligation, "or" the masks).
 
-- Warn at compile time (and runtime with HB_DEBUG?) if no Unicode / font
-  funcs found / set.
 
-- Do proper rounding when scaling from font space?  May be a non-issue.
-
-- Misc features:
-  * init/medi/fina/isol for non-cursive scripts
-
-
-API issues to fix before 1.0:
-============================
+API issues:
+===========
 
 - API to accept a list of languages?
 
 - Add init_func to font_funcs.  Adjust ft.
 
-- hb-ft load_flags issues.
-
-- Add pkg-config files for glue codes (harfbuzz-glib, etc)
-
 - 'const' for getter APIs? (use mutable internally)
 
 - Remove hb_ot_shape_glyphs_closure()?
diff --git a/configure.ac b/configure.ac
index d12d4b8..44621c9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [1.2.1],
+        [1.2.6],
         [http://bugs.freedesktop.org/enter_bug.cgi?product=harfbuzz],
         [harfbuzz],
         [http://harfbuzz.org/])
@@ -9,7 +9,7 @@
 AC_CONFIG_SRCDIR([src/harfbuzz.pc.in])
 AC_CONFIG_HEADERS([config.h])
 
-AM_INIT_AUTOMAKE([1.11.1 gnits tar-pax dist-bzip2 no-dist-gzip -Wall no-define color-tests -Wno-portability])
+AM_INIT_AUTOMAKE([1.11.1 gnits tar-ustar dist-bzip2 no-dist-gzip -Wall no-define color-tests -Wno-portability])
 AM_CONDITIONAL(AUTOMAKE_OLDER_THAN_1_13, test $am__api_version = 1.11 -o $am__api_version = 1.12)
 AM_SILENT_RULES([yes])
 
@@ -197,17 +197,6 @@
 	AM_CONDITIONAL([HAVE_INTROSPECTION], false)
 ])
 
-dnl ===========================================================================
-
-have_ucdn=true
-if $have_glib; then
-	have_ucdn=false
-fi
-if $have_ucdn; then
-	AC_DEFINE(HAVE_UCDN, 1, [Have UCDN Unicode functions])
-fi
-AM_CONDITIONAL(HAVE_UCDN, $have_ucdn)
-
 dnl ==========================================================================
 
 AC_ARG_WITH(cairo,
@@ -256,11 +245,11 @@
 dnl ==========================================================================
 
 AC_ARG_WITH(icu,
-	[AS_HELP_STRING([--with-icu=@<:@yes/no/auto@:>@],
+	[AS_HELP_STRING([--with-icu=@<:@yes/no/builtin/auto@:>@],
 			[Use ICU @<:@default=auto@:>@])],,
 	[with_icu=auto])
 have_icu=false
-if test "x$with_icu" = "xyes" -o "x$with_icu" = "xauto"; then
+if test "x$with_icu" = "xyes" -o "x$with_icu" = "xbuiltin" -o "x$with_icu" = "xauto"; then
 	PKG_CHECK_MODULES(ICU, icu-uc, have_icu=true, :)
 
 	dnl Fallback to icu-config if ICU pkg-config files could not be found
@@ -282,14 +271,30 @@
 		fi
 	fi
 fi
-if test "x$with_icu" = "xyes" -a "x$have_icu" != "xtrue"; then
+if test \( "x$with_icu" = "xyes" -o "x$with_icu" = "xbuiltin" \) -a "x$have_icu" != "xtrue"; then
 	AC_MSG_ERROR([icu support requested but icu-uc not found])
 fi
+
 if $have_icu; then
 	CXXFLAGS="$CXXFLAGS `$PKG_CONFIG --variable=CXXFLAGS icu-uc`"
 	AC_DEFINE(HAVE_ICU, 1, [Have ICU library])
+	if test "x$with_icu" = "xbuiltin"; then
+		AC_DEFINE(HAVE_ICU_BUILTIN, 1, [Use hb-icu Unicode callbacks])
+	fi
 fi
 AM_CONDITIONAL(HAVE_ICU, $have_icu)
+AM_CONDITIONAL(HAVE_ICU_BUILTIN, $have_icu && test "x$with_icu" = "xbuiltin")
+
+dnl ===========================================================================
+
+have_ucdn=true
+if $have_glib || $have_icu && test "x$with_icu" = "xbuiltin"; then
+	have_ucdn=false
+fi
+if $have_ucdn; then
+	AC_DEFINE(HAVE_UCDN, 1, [Have UCDN Unicode functions])
+fi
+AM_CONDITIONAL(HAVE_UCDN, $have_ucdn)
 
 dnl ==========================================================================
 
diff --git a/src/Makefile.am b/src/Makefile.am
index bb085ad..8cfe4ac 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -130,6 +130,7 @@
 EXTRA_DIST += harfbuzz.pc.in
 
 FUZZING_CPPFLAGS= \
+	-DHB_NDEBUG \
 	-DHB_MAX_NESTING_LEVEL=3 \
 	-DHB_SANITIZE_MAX_EDITS=3 \
 	-DHB_BUFFER_MAX_EXPANSION_FACTOR=3 \
@@ -146,6 +147,12 @@
 CLEANFILES += libharfbuzz-fuzzing.la
 
 if HAVE_ICU
+if HAVE_ICU_BUILTIN
+HBCFLAGS += $(ICU_CFLAGS)
+HBLIBS += $(ICU_LIBS)
+HBSOURCES += $(HB_ICU_sources)
+HBHEADERS += $(HB_ICU_headers)
+else
 lib_LTLIBRARIES += libharfbuzz-icu.la
 libharfbuzz_icu_la_SOURCES = $(HB_ICU_sources)
 libharfbuzz_icu_la_CPPFLAGS = $(ICU_CFLAGS)
@@ -154,6 +161,7 @@
 pkginclude_HEADERS += $(HB_ICU_headers)
 pkgconfig_DATA += harfbuzz-icu.pc
 endif
+endif
 EXTRA_DIST += harfbuzz-icu.pc.in
 
 if HAVE_GOBJECT
diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index c8eec3c..ed592f4 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -112,10 +112,6 @@
 
   unsigned int serial;
 
-  /* These reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
-  uint8_t allocated_var_bytes[8];
-  const char *allocated_var_owner[8];
-
   /* Text before / after the main buffer contents.
    * Always in Unicode, and ordered outward.
    * Index 0 is for "pre-context", 1 for "post-context". */
@@ -123,11 +119,52 @@
   hb_codepoint_t context[2][CONTEXT_LENGTH];
   unsigned int context_len[2];
 
-  /* Debugging */
+  /* Debugging API */
   hb_buffer_message_func_t message_func;
   void *message_data;
   hb_destroy_func_t message_destroy;
 
+  /* Internal debugging. */
+  /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
+#ifndef HB_NDEBUG
+  uint8_t allocated_var_bits;
+#endif
+  inline void allocate_var (unsigned int start, unsigned int count)
+  {
+#ifndef HB_NDEBUG
+    unsigned int end = start + count;
+    assert (end <= 8);
+    unsigned int bits = (1<<end) - (1<<start);
+    assert (0 == (allocated_var_bits & bits));
+    allocated_var_bits |= bits;
+#endif
+  }
+  inline void deallocate_var (unsigned int start, unsigned int count)
+  {
+#ifndef HB_NDEBUG
+    unsigned int end = start + count;
+    assert (end <= 8);
+    unsigned int bits = (1<<end) - (1<<start);
+    assert (bits == (allocated_var_bits & bits));
+    allocated_var_bits &= ~bits;
+#endif
+  }
+  inline void assert_var (unsigned int start, unsigned int count)
+  {
+#ifndef HB_NDEBUG
+    unsigned int end = start + count;
+    assert (end <= 8);
+    unsigned int bits = (1<<end) - (1<<start);
+    assert (bits == (allocated_var_bits & bits));
+#endif
+  }
+  inline void deallocate_var_all (void)
+  {
+#ifndef HB_NDEBUG
+    allocated_var_bits = 0;
+#endif
+  }
+
 
   /* Methods */
 
@@ -140,11 +177,6 @@
   { return len - idx; }
   inline unsigned int next_serial (void) { return serial++; }
 
-  HB_INTERNAL void allocate_var (unsigned int byte_i, unsigned int count, const char *owner);
-  HB_INTERNAL void deallocate_var (unsigned int byte_i, unsigned int count, const char *owner);
-  HB_INTERNAL void assert_var (unsigned int byte_i, unsigned int count, const char *owner);
-  HB_INTERNAL void deallocate_var_all (void);
-
   HB_INTERNAL void add (hb_codepoint_t  codepoint,
 			unsigned int    cluster);
   HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
@@ -253,15 +285,12 @@
 };
 
 
-#define HB_BUFFER_XALLOCATE_VAR(b, func, var, owner) \
+#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
   b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
-	   sizeof (b->info[0].var), owner)
-#define HB_BUFFER_ALLOCATE_VAR(b, var) \
-	HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var (), #var)
-#define HB_BUFFER_DEALLOCATE_VAR(b, var) \
-	HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var (), #var)
-#define HB_BUFFER_ASSERT_VAR(b, var) \
-	HB_BUFFER_XALLOCATE_VAR (b, assert_var, var (), #var)
+	   sizeof (b->info[0].var))
+#define HB_BUFFER_ALLOCATE_VAR(b, var)		HB_BUFFER_XALLOCATE_VAR (b, allocate_var,   var ())
+#define HB_BUFFER_DEALLOCATE_VAR(b, var)	HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
+#define HB_BUFFER_ASSERT_VAR(b, var)		HB_BUFFER_XALLOCATE_VAR (b, assert_var,     var ())
 
 
 #endif /* HB_BUFFER_PRIVATE_HH */
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 5f320bd..406db9c 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -242,11 +242,11 @@
   out_info = info;
 
   serial = 0;
-  memset (allocated_var_bytes, 0, sizeof allocated_var_bytes);
-  memset (allocated_var_owner, 0, sizeof allocated_var_owner);
 
   memset (context, 0, sizeof context);
   memset (context_len, 0, sizeof context_len);
+
+  deallocate_var_all ();
 }
 
 void
@@ -661,74 +661,6 @@
 }
 
 
-static inline void
-dump_var_allocation (const hb_buffer_t *buffer)
-{
-  char buf[80];
-  for (unsigned int i = 0; i < 8; i++)
-    buf[i] = '0' + buffer->allocated_var_bytes[7 - i];
-  buf[8] = '\0';
-  DEBUG_MSG (BUFFER, buffer,
-	     "Current var allocation: %s",
-	     buf);
-}
-
-void hb_buffer_t::allocate_var (unsigned int byte_i, unsigned int count, const char *owner)
-{
-  assert (byte_i < 8 && byte_i + count <= 8);
-
-  if (DEBUG_ENABLED (BUFFER))
-    dump_var_allocation (this);
-  DEBUG_MSG (BUFFER, this,
-	     "Allocating var bytes %d..%d for %s",
-	     byte_i, byte_i + count - 1, owner);
-
-  for (unsigned int i = byte_i; i < byte_i + count; i++) {
-    assert (!allocated_var_bytes[i]);
-    allocated_var_bytes[i]++;
-    allocated_var_owner[i] = owner;
-  }
-}
-
-void hb_buffer_t::deallocate_var (unsigned int byte_i, unsigned int count, const char *owner)
-{
-  if (DEBUG_ENABLED (BUFFER))
-    dump_var_allocation (this);
-
-  DEBUG_MSG (BUFFER, this,
-	     "Deallocating var bytes %d..%d for %s",
-	     byte_i, byte_i + count - 1, owner);
-
-  assert (byte_i < 8 && byte_i + count <= 8);
-  for (unsigned int i = byte_i; i < byte_i + count; i++) {
-    assert (allocated_var_bytes[i]);
-    assert (0 == strcmp (allocated_var_owner[i], owner));
-    allocated_var_bytes[i]--;
-  }
-}
-
-void hb_buffer_t::assert_var (unsigned int byte_i, unsigned int count, const char *owner)
-{
-  if (DEBUG_ENABLED (BUFFER))
-    dump_var_allocation (this);
-
-  DEBUG_MSG (BUFFER, this,
-	     "Asserting var bytes %d..%d for %s",
-	     byte_i, byte_i + count - 1, owner);
-
-  assert (byte_i < 8 && byte_i + count <= 8);
-  for (unsigned int i = byte_i; i < byte_i + count; i++) {
-    assert (allocated_var_bytes[i]);
-    assert (0 == strcmp (allocated_var_owner[i], owner));
-  }
-}
-
-void hb_buffer_t::deallocate_var_all (void)
-{
-  memset (allocated_var_bytes, 0, sizeof (allocated_var_bytes));
-  memset (allocated_var_owner, 0, sizeof (allocated_var_owner));
-}
-
 /* Public API */
 
 /**
diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc
index 90c6653..e64d265 100644
--- a/src/hb-coretext.cc
+++ b/src/hb-coretext.cc
@@ -904,13 +904,11 @@
 	 * backend.
 	 *
 	 * However, even that wouldn't work if we were passed in the CGFont to
-	 * begin with.
-	 *
-	 * We might switch to checking PS name against "LastResort".  That would
-	 * be safe for all fonts except for those named "Last Resort".  Might be
-	 * better than what we have right now.
+	 * construct a hb_face to begin with.
 	 *
 	 * See: http://github.com/behdad/harfbuzz/pull/36
+	 *
+	 * Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098
 	 */
 	bool matched = false;
 	for (unsigned int i = 0; i < range_records.len; i++)
diff --git a/src/hb-deprecated.h b/src/hb-deprecated.h
index 30ae4b1..0398dfa 100644
--- a/src/hb-deprecated.h
+++ b/src/hb-deprecated.h
@@ -44,6 +44,16 @@
 #define HB_BUFFER_FLAGS_DEFAULT			HB_BUFFER_FLAG_DEFAULT
 #define HB_BUFFER_SERIALIZE_FLAGS_DEFAULT	HB_BUFFER_SERIALIZE_FLAG_DEFAULT
 
+typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data,
+					       hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+					       hb_codepoint_t *glyph,
+					       void *user_data);
+
+HB_EXTERN void
+hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
+			      hb_font_get_glyph_func_t func,
+			      void *user_data, hb_destroy_func_t destroy);
+
 #endif
 
 HB_END_DECLS
diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc
index af0fd3d..96d1870 100644
--- a/src/hb-directwrite.cc
+++ b/src/hb-directwrite.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2015  Ebrahim Byagowi
+ * Copyright © 2015-2016  Ebrahim Byagowi
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -25,7 +25,11 @@
 #define HB_SHAPER directwrite
 #include "hb-shaper-impl-private.hh"
 
-#include <dwrite.h>
+#ifndef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
+  #include <DWrite.h>
+#else
+  #include <DWrite_1.h>
+#endif
 
 #include "hb-directwrite.h"
 
@@ -176,7 +180,8 @@
 hb_directwrite_shaper_face_data_t *
 _hb_directwrite_shaper_face_data_create(hb_face_t *face)
 {
-  hb_directwrite_shaper_face_data_t *data = (hb_directwrite_shaper_face_data_t *)calloc(1, sizeof (hb_directwrite_shaper_face_data_t));
+  hb_directwrite_shaper_face_data_t *data =
+    (hb_directwrite_shaper_face_data_t *) calloc (1, sizeof (hb_directwrite_shaper_face_data_t));
   if (unlikely (!data))
     return NULL;
 
@@ -244,26 +249,30 @@
 {
   if (unlikely (!hb_directwrite_shaper_face_data_ensure (font->face))) return NULL;
 
-  hb_directwrite_shaper_font_data_t *data = (hb_directwrite_shaper_font_data_t *) calloc (1, sizeof (hb_directwrite_shaper_font_data_t));
+  hb_directwrite_shaper_font_data_t *data =
+    (hb_directwrite_shaper_font_data_t *) calloc (1, sizeof (hb_directwrite_shaper_font_data_t));
   if (unlikely (!data))
     return NULL;
 
   data->hdc = GetDC (NULL);
 
-  if (unlikely (!populate_log_font (&data->log_font, font))) {
+  if (unlikely (!populate_log_font (&data->log_font, font)))
+  {
     DEBUG_MSG (DIRECTWRITE, font, "Font populate_log_font() failed");
     _hb_directwrite_shaper_font_data_destroy (data);
     return NULL;
   }
 
   data->hfont = CreateFontIndirectW (&data->log_font);
-  if (unlikely (!data->hfont)) {
+  if (unlikely (!data->hfont))
+  {
     DEBUG_MSG (DIRECTWRITE, font, "Font CreateFontIndirectW() failed");
     _hb_directwrite_shaper_font_data_destroy (data);
      return NULL;
   }
 
-  if (!SelectObject (data->hdc, data->hfont)) {
+  if (!SelectObject (data->hdc, data->hfont))
+  {
     DEBUG_MSG (DIRECTWRITE, font, "Font SelectObject() failed");
     _hb_directwrite_shaper_font_data_destroy (data);
      return NULL;
@@ -333,16 +342,16 @@
   // results.
   struct Run
   {
-    UINT32 mTextStart;   // starting text position of this run
-    UINT32 mTextLength;  // number of contiguous code units covered
-    UINT32 mGlyphStart;  // starting glyph in the glyphs array
-    UINT32 mGlyphCount;  // number of glyphs associated with this run of 
+    uint32_t mTextStart;   // starting text position of this run
+    uint32_t mTextLength;  // number of contiguous code units covered
+    uint32_t mGlyphStart;  // starting glyph in the glyphs array
+    uint32_t mGlyphCount;  // number of glyphs associated with this run of 
     // text
     DWRITE_SCRIPT_ANALYSIS mScript;
-    UINT8 mBidiLevel;
+    uint8_t mBidiLevel;
     bool mIsSideways;
 
-    inline bool ContainsTextPosition(UINT32 aTextPosition) const
+    inline bool ContainsTextPosition(uint32_t aTextPosition) const
     {
       return aTextPosition >= mTextStart
         && aTextPosition <  mTextStart + mTextLength;
@@ -353,7 +362,7 @@
 
 public:
   TextAnalysis(const wchar_t* text,
-    UINT32 textLength,
+    uint32_t textLength,
     const wchar_t* localeName,
     DWRITE_READING_DIRECTION readingDirection)
     : mText(text)
@@ -367,7 +376,7 @@
     for (Run *run = mRunHead.nextRun; run;) {
       Run *origRun = run;
       run = run->nextRun;
-      delete origRun;
+      free (origRun);
     }
   }
 
@@ -388,10 +397,7 @@
     mCurrentRun = &mRunHead;
 
     // Call each of the analyzers in sequence, recording their results.
-    if (SUCCEEDED(hr = textAnalyzer->AnalyzeScript(this,
-      0,
-      mTextLength,
-      this))) {
+    if (SUCCEEDED (hr = textAnalyzer->AnalyzeScript (this, 0, mTextLength, this))) {
       *runHead = &mRunHead;
     }
 
@@ -400,9 +406,9 @@
 
   // IDWriteTextAnalysisSource implementation
 
-  IFACEMETHODIMP GetTextAtPosition(UINT32 textPosition,
-    OUT WCHAR const** textString,
-    OUT UINT32* textLength)
+  IFACEMETHODIMP GetTextAtPosition(uint32_t textPosition,
+    OUT wchar_t const** textString,
+    OUT uint32_t* textLength)
   {
     if (textPosition >= mTextLength) {
       // No text at this position, valid query though.
@@ -416,9 +422,9 @@
     return S_OK;
   }
 
-  IFACEMETHODIMP GetTextBeforePosition(UINT32 textPosition,
-    OUT WCHAR const** textString,
-    OUT UINT32* textLength)
+  IFACEMETHODIMP GetTextBeforePosition(uint32_t textPosition,
+    OUT wchar_t const** textString,
+    OUT uint32_t* textLength)
   {
     if (textPosition == 0 || textPosition > mTextLength) {
       // Either there is no text before here (== 0), or this
@@ -436,15 +442,15 @@
   IFACEMETHODIMP_(DWRITE_READING_DIRECTION)
     GetParagraphReadingDirection() { return mReadingDirection; }
 
-  IFACEMETHODIMP GetLocaleName(UINT32 textPosition,
-    UINT32* textLength,
-    WCHAR const** localeName) {
+  IFACEMETHODIMP GetLocaleName(uint32_t textPosition,
+    uint32_t* textLength,
+    wchar_t const** localeName) {
     return S_OK;
   }
 
   IFACEMETHODIMP
-    GetNumberSubstitution(UINT32 textPosition,
-    OUT UINT32* textLength,
+    GetNumberSubstitution(uint32_t textPosition,
+    OUT uint32_t* textLength,
     OUT IDWriteNumberSubstitution** numberSubstitution)
   {
     // We do not support number substitution.
@@ -457,8 +463,8 @@
   // IDWriteTextAnalysisSink implementation
 
   IFACEMETHODIMP
-    SetScriptAnalysis(UINT32 textPosition,
-    UINT32 textLength,
+    SetScriptAnalysis(uint32_t textPosition,
+    uint32_t textLength,
     DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis)
   {
     SetCurrentRun(textPosition);
@@ -472,22 +478,22 @@
   }
 
   IFACEMETHODIMP
-    SetLineBreakpoints(UINT32 textPosition,
-    UINT32 textLength,
+    SetLineBreakpoints(uint32_t textPosition,
+    uint32_t textLength,
     const DWRITE_LINE_BREAKPOINT* lineBreakpoints) { return S_OK; }
 
-  IFACEMETHODIMP SetBidiLevel(UINT32 textPosition,
-    UINT32 textLength,
-    UINT8 explicitLevel,
-    UINT8 resolvedLevel) { return S_OK; }
+  IFACEMETHODIMP SetBidiLevel(uint32_t textPosition,
+    uint32_t textLength,
+    uint8_t explicitLevel,
+    uint8_t resolvedLevel) { return S_OK; }
 
   IFACEMETHODIMP
-    SetNumberSubstitution(UINT32 textPosition,
-    UINT32 textLength,
+    SetNumberSubstitution(uint32_t textPosition,
+    uint32_t textLength,
     IDWriteNumberSubstitution* numberSubstitution) { return S_OK; }
 
 protected:
-  Run *FetchNextRun(IN OUT UINT32* textLength)
+  Run *FetchNextRun(IN OUT uint32_t* textLength)
   {
     // Used by the sink setters, this returns a reference to the next run.
     // Position and length are adjusted to now point after the current run
@@ -509,7 +515,7 @@
     return origRun;
   }
 
-  void SetCurrentRun(UINT32 textPosition)
+  void SetCurrentRun(uint32_t textPosition)
   {
     // Move the current run to the given position.
     // Since the analyzers generally return results in a forward manner,
@@ -530,7 +536,7 @@
             //                of our runs");
   }
 
-  void SplitCurrentRun(UINT32 splitPosition)
+  void SplitCurrentRun(uint32_t splitPosition)
   {
     if (!mCurrentRun) {
       //NS_ASSERTION(false, "SplitCurrentRun called without current run.");
@@ -543,7 +549,7 @@
       // or before it. Usually the first.
       return;
     }
-    Run *newRun = new Run;
+    Run *newRun = (Run*) malloc (sizeof (Run));
 
     *newRun = *mCurrentRun;
 
@@ -552,7 +558,7 @@
     mCurrentRun->nextRun = newRun;
 
     // Adjust runs' text positions and lengths.
-    UINT32 splitPoint = splitPosition - mCurrentRun->mTextStart;
+    uint32_t splitPoint = splitPosition - mCurrentRun->mTextStart;
     newRun->mTextStart += splitPoint;
     newRun->mTextLength -= splitPoint;
     mCurrentRun->mTextLength = splitPoint;
@@ -563,9 +569,9 @@
   // Input
   // (weak references are fine here, since this class is a transient
   //  stack-based helper that doesn't need to copy data)
-  UINT32 mTextLength;
-  const WCHAR* mText;
-  const WCHAR* mLocaleName;
+  uint32_t mTextLength;
+  const wchar_t* mText;
+  const wchar_t* mLocaleName;
   DWRITE_READING_DIRECTION mReadingDirection;
 
   // Current processing state.
@@ -575,6 +581,10 @@
   Run  mRunHead;
 };
 
+static inline uint16_t hb_uint16_swap (const uint16_t v)
+{ return (v >> 8) | (v << 8); }
+static inline uint32_t hb_uint32_swap (const uint32_t v)
+{ return (hb_uint16_swap(v) << 16) | hb_uint16_swap(v >> 16); }
 
 /*
  * shaper
@@ -592,20 +602,30 @@
   hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
 
   // factory probably should be cached
+#ifndef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
   IDWriteFactory* dwriteFactory;
-  DWriteCreateFactory(
+#else
+  IDWriteFactory1* dwriteFactory;
+#endif
+  DWriteCreateFactory (
     DWRITE_FACTORY_TYPE_SHARED,
-    __uuidof(IDWriteFactory),
-    reinterpret_cast<IUnknown**>(&dwriteFactory)
-    );
+    __uuidof (IDWriteFactory),
+    (IUnknown**) &dwriteFactory
+  );
 
   IDWriteGdiInterop *gdiInterop;
   dwriteFactory->GetGdiInterop (&gdiInterop);
   IDWriteFontFace* fontFace;
   gdiInterop->CreateFontFaceFromHdc (font_data->hdc, &fontFace);
 
+#ifndef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
   IDWriteTextAnalyzer* analyzer;
-  dwriteFactory->CreateTextAnalyzer (&analyzer);
+  dwriteFactory->CreateTextAnalyzer(&analyzer);
+#else
+  IDWriteTextAnalyzer* analyzer0;
+  dwriteFactory->CreateTextAnalyzer (&analyzer0);
+  IDWriteTextAnalyzer1* analyzer = (IDWriteTextAnalyzer1*) analyzer0;
+#endif
 
   unsigned int scratch_size;
   hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
@@ -620,7 +640,7 @@
 
 #define utf16_index() var1.u32
 
-  ALLOCATE_ARRAY(WCHAR, pchars, buffer->len * 2);
+  ALLOCATE_ARRAY(wchar_t, textString, buffer->len * 2);
 
   unsigned int chars_len = 0;
   for (unsigned int i = 0; i < buffer->len; i++)
@@ -628,17 +648,17 @@
     hb_codepoint_t c = buffer->info[i].codepoint;
     buffer->info[i].utf16_index() = chars_len;
     if (likely(c <= 0xFFFFu))
-      pchars[chars_len++] = c;
+      textString[chars_len++] = c;
     else if (unlikely(c > 0x10FFFFu))
-      pchars[chars_len++] = 0xFFFDu;
+      textString[chars_len++] = 0xFFFDu;
     else {
-      pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
-      pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1));
+      textString[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
+      textString[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1));
     }
   }
 
   ALLOCATE_ARRAY(WORD, log_clusters, chars_len);
-  if (num_features)
+  // if (num_features)
   {
     /* Need log_clusters to assign features. */
     chars_len = 0;
@@ -664,164 +684,287 @@
   * but we never attempt to shape a word longer than 64K characters
   * in a single gfxShapedWord, so we cannot exceed that limit.
   */
-  UINT32 length = buffer->len;
+  uint32_t textLength = buffer->len;
 
-  TextAnalysis analysis(pchars, length, NULL, readingDirection);
+  TextAnalysis analysis(textString, textLength, NULL, readingDirection);
   TextAnalysis::Run *runHead;
   hr = analysis.GenerateResults(analyzer, &runHead);
 
-  if (FAILED(hr)) {
-    //NS_WARNING("Analyzer failed to generate results.");
+#define FAIL(...) \
+  HB_STMT_START { \
+    DEBUG_MSG (DIRECTWRITE, NULL, __VA_ARGS__); \
+    return false; \
+  } HB_STMT_END;
+
+  if (FAILED (hr))
+  {
+    FAIL ("Analyzer failed to generate results.");
     return false;
   }
 
-  UINT32 maxGlyphs = 3 * length / 2 + 16;
+  uint32_t maxGlyphCount = 3 * textLength / 2 + 16;
+  uint32_t glyphCount;
+  bool isRightToLeft = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
 
-#define INITIAL_GLYPH_SIZE 400
-  UINT16* clusters = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16));
-  UINT16* glyphs = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16));
+  const wchar_t localeName[20] = {0};
+  if (buffer->props.language != NULL)
+  {
+    mbstowcs ((wchar_t*) localeName,
+      hb_language_to_string (buffer->props.language), 20);
+  }
+
+  DWRITE_TYPOGRAPHIC_FEATURES singleFeatures;
+  singleFeatures.featureCount = num_features;
+  if (num_features)
+  {
+    DWRITE_FONT_FEATURE* dwfeatureArray = (DWRITE_FONT_FEATURE*)
+      malloc (sizeof (DWRITE_FONT_FEATURE) * num_features);
+    for (unsigned int i = 0; i < num_features; ++i)
+    {
+      dwfeatureArray[i].nameTag = (DWRITE_FONT_FEATURE_TAG)
+        hb_uint32_swap (features[i].tag);
+      dwfeatureArray[i].parameter = features[i].value;
+    }
+    singleFeatures.features = dwfeatureArray;
+  }
+  const DWRITE_TYPOGRAPHIC_FEATURES* dwFeatures =
+    (const DWRITE_TYPOGRAPHIC_FEATURES*) &singleFeatures;
+  const uint32_t featureRangeLengths[] = { textLength };
+
+retry_getglyphs:
+  uint16_t* clusterMap = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t));
+  uint16_t* glyphIndices = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t));
   DWRITE_SHAPING_TEXT_PROPERTIES* textProperties = (DWRITE_SHAPING_TEXT_PROPERTIES*)
-    malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_TEXT_PROPERTIES));
+    malloc (maxGlyphCount * sizeof (DWRITE_SHAPING_TEXT_PROPERTIES));
   DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*)
-    malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES));
+    malloc (maxGlyphCount * sizeof (DWRITE_SHAPING_GLYPH_PROPERTIES));
 
-  UINT32 actualGlyphs;
+  hr = analyzer->GetGlyphs (textString, textLength, fontFace, FALSE,
+    isRightToLeft, &runHead->mScript, localeName, NULL, &dwFeatures,
+    featureRangeLengths, 1, maxGlyphCount, clusterMap, textProperties, glyphIndices,
+    glyphProperties, &glyphCount);
 
-  bool backward = HB_DIRECTION_IS_BACKWARD(buffer->props.direction);
+  if (unlikely (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)))
+  {
+    free (clusterMap);
+    free (glyphIndices);
+    free (textProperties);
+    free (glyphProperties);
 
-  wchar_t lang[4];
-  mbstowcs(lang, hb_language_to_string(buffer->props.language), 4);
-  hr = analyzer->GetGlyphs(pchars, length,
-    fontFace, FALSE,
-    buffer->props.direction,
-    &runHead->mScript, (const wchar_t*)lang, NULL, NULL, NULL, 0,
-    maxGlyphs, clusters, textProperties,
-    glyphs, glyphProperties, &actualGlyphs);
+    maxGlyphCount *= 2;
 
-  if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) {
-    free(clusters);
-    free(glyphs);
-    free(textProperties);
-    free(glyphProperties);
-
-    clusters = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16));
-    glyphs = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16));
-    textProperties = (DWRITE_SHAPING_TEXT_PROPERTIES*)
-      malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_TEXT_PROPERTIES));
-    glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*)
-      malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES));
-
-    hr = analyzer->GetGlyphs(pchars, length,
-      fontFace, FALSE,
-      buffer->props.direction,
-      &runHead->mScript, (const wchar_t*)lang, NULL, NULL, NULL, 0,
-      maxGlyphs, clusters, textProperties,
-      glyphs, glyphProperties, &actualGlyphs);
+    goto retry_getglyphs;
   }
-  if (FAILED(hr)) {
-    //NS_WARNING("Analyzer failed to get glyphs.");
+  if (FAILED (hr))
+  {
+    FAIL ("Analyzer failed to get glyphs.");
     return false;
   }
 
-  FLOAT advances[400];
-  DWRITE_GLYPH_OFFSET offsets[400];
-
+  float* glyphAdvances = (float*) malloc (maxGlyphCount * sizeof (float));
+  DWRITE_GLYPH_OFFSET* glyphOffsets = (DWRITE_GLYPH_OFFSET*)
+    malloc(maxGlyphCount * sizeof (DWRITE_GLYPH_OFFSET));
 
   /* The -2 in the following is to compensate for possible
    * alignment needed after the WORD array.  sizeof(WORD) == 2. */
-  unsigned int glyphs_size = (scratch_size * sizeof (int)-2)
-    / (sizeof (WORD) +
-    4 + // sizeof (SCRIPT_GLYPHPROP) +
-    sizeof (int) +
-    8 + // sizeof (GOFFSET) +
-    sizeof (uint32_t));
-  ALLOCATE_ARRAY(uint32_t, vis_clusters, glyphs_size);
+  unsigned int glyphs_size = (scratch_size * sizeof(int) - 2)
+         / (sizeof(WORD) +
+            sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES) +
+            sizeof(int) +
+            sizeof(DWRITE_GLYPH_OFFSET) +
+            sizeof(uint32_t));
+  ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
 
 #undef ALLOCATE_ARRAY
 
-  hr = analyzer->GetGlyphPlacements(pchars,
-    clusters,
-    textProperties,
-    length,
-    glyphs,
-    glyphProperties,
-    actualGlyphs,
-    fontFace,
-    face->get_upem(),
-    FALSE,
-    FALSE,
-    &runHead->mScript,
-    NULL,
-    NULL,
-    NULL,
-    0,
-    advances,
-    offsets);
+  int fontEmSize = font->face->get_upem();
+  if (fontEmSize < 0)
+    fontEmSize = -fontEmSize;
 
-  if (FAILED(hr)) {
-    //NS_WARNING("Analyzer failed to get glyph placements.");
+  if (fontEmSize < 0)
+    fontEmSize = -fontEmSize;
+  double x_mult = (double) font->x_scale / fontEmSize;
+  double y_mult = (double) font->y_scale / fontEmSize;
+
+  hr = analyzer->GetGlyphPlacements (textString,
+    clusterMap, textProperties, textLength, glyphIndices,
+    glyphProperties, glyphCount, fontFace, fontEmSize,
+    FALSE, isRightToLeft, &runHead->mScript, localeName,
+    &dwFeatures, featureRangeLengths, 1,
+    glyphAdvances, glyphOffsets);
+
+  if (FAILED (hr))
+  {
+    FAIL ("Analyzer failed to get glyph placements.");
     return false;
   }
 
-  unsigned int glyphs_len = actualGlyphs;
+#ifdef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
+
+  DWRITE_JUSTIFICATION_OPPORTUNITY* justificationOpportunities =
+    (DWRITE_JUSTIFICATION_OPPORTUNITY*)
+    malloc (maxGlyphCount * sizeof (DWRITE_JUSTIFICATION_OPPORTUNITY));
+  hr = analyzer->GetJustificationOpportunities (fontFace, fontEmSize,
+    runHead->mScript, textLength, glyphCount, textString, clusterMap,
+    glyphProperties, justificationOpportunities);
+
+  if (FAILED (hr))
+  {
+    FAIL ("Analyzer failed to get justification opportunities.");
+    return false;
+  }
+
+  // TODO: get lineWith from somewhere
+  float lineWidth = 60000;
+
+  float* justifiedGlyphAdvances =
+    (float*) malloc (maxGlyphCount * sizeof (float));
+  DWRITE_GLYPH_OFFSET* justifiedGlyphOffsets = (DWRITE_GLYPH_OFFSET*)
+    malloc (glyphCount * sizeof (DWRITE_GLYPH_OFFSET));
+  hr = analyzer->JustifyGlyphAdvances (lineWidth, glyphCount, justificationOpportunities,
+    glyphAdvances, glyphOffsets, justifiedGlyphAdvances, justifiedGlyphOffsets);
+
+  if (FAILED (hr))
+  {
+    FAIL ("Analyzer failed to get justified glyph advances.");
+    return false;
+  }
+
+  DWRITE_SCRIPT_PROPERTIES scriptProperties;
+  hr = analyzer->GetScriptProperties (runHead->mScript, &scriptProperties);
+  if (FAILED (hr))
+  {
+    FAIL ("Analyzer failed to get script properties.");
+    return false;
+  }
+  uint32_t justificationCharacter = scriptProperties.justificationCharacter;
+
+  // if a script justificationCharacter is not space, it can have GetJustifiedGlyphs
+  if (justificationCharacter != 32)
+  {
+retry_getjustifiedglyphs:
+    uint16_t* modifiedClusterMap = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t));
+    uint16_t* modifiedGlyphIndices = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t));
+    float* modifiedGlyphAdvances = (float*) malloc (maxGlyphCount * sizeof (float));
+    DWRITE_GLYPH_OFFSET* modifiedGlyphOffsets = (DWRITE_GLYPH_OFFSET*)
+      malloc (maxGlyphCount * sizeof (DWRITE_GLYPH_OFFSET));
+    uint32_t actualGlyphsCount;
+    hr = analyzer->GetJustifiedGlyphs (fontFace, fontEmSize, runHead->mScript,
+        textLength, glyphCount, maxGlyphCount, clusterMap, glyphIndices,
+        glyphAdvances, justifiedGlyphAdvances, justifiedGlyphOffsets,
+        glyphProperties, &actualGlyphsCount, modifiedClusterMap, modifiedGlyphIndices,
+        modifiedGlyphAdvances, modifiedGlyphOffsets);
+
+    if (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER))
+    {
+      maxGlyphCount = actualGlyphsCount;
+      free (modifiedClusterMap);
+      free (modifiedGlyphIndices);
+      free (modifiedGlyphAdvances);
+      free (modifiedGlyphOffsets);
+
+      maxGlyphCount = actualGlyphsCount;
+
+      goto retry_getjustifiedglyphs;
+    }
+    if (FAILED (hr))
+    {
+      FAIL ("Analyzer failed to get justified glyphs.");
+      return false;
+    }
+
+    free (clusterMap);
+    free (glyphIndices);
+    free (glyphAdvances);
+    free (glyphOffsets);
+
+    glyphCount = actualGlyphsCount;
+    clusterMap = modifiedClusterMap;
+    glyphIndices = modifiedGlyphIndices;
+    glyphAdvances = modifiedGlyphAdvances;
+    glyphOffsets = modifiedGlyphOffsets;
+
+    free(justifiedGlyphAdvances);
+    free(justifiedGlyphOffsets);
+  }
+  else
+  {
+    free(glyphAdvances);
+    free(glyphOffsets);
+
+    glyphAdvances = justifiedGlyphAdvances;
+    glyphOffsets = justifiedGlyphOffsets;
+  }
+
+  free(justificationOpportunities);
+
+#endif
 
   /* 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 < glyphs_len; i++)
+  for (unsigned int i = 0; i < glyphCount; i++)
     vis_clusters[i] = -1;
-  for (unsigned int i = 0; i < buffer->len; i++) {
-    uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]];
-    //*p = MIN (*p, buffer->info[i].cluster);
+  for (unsigned int i = 0; i < buffer->len; i++)
+  {
+    uint32_t *p =
+      &vis_clusters[log_clusters[buffer->info[i].utf16_index()]];
+    *p = MIN (*p, buffer->info[i].cluster);
   }
-  for (unsigned int i = 1; i < glyphs_len; i++)
+  for (unsigned int i = 1; i < glyphCount; i++)
     if (vis_clusters[i] == -1)
       vis_clusters[i] = vis_clusters[i - 1];
 
 #undef utf16_index
 
-  //if (unlikely (!buffer->ensure (glyphs_len)))
-  //  FAIL ("Buffer in error");
+  if (unlikely (!buffer->ensure (glyphCount)))
+    FAIL ("Buffer in error");
 
 #undef FAIL
 
   /* Set glyph infos */
   buffer->len = 0;
-  for (unsigned int i = 0; i < glyphs_len; i++)
+  for (unsigned int i = 0; i < glyphCount; i++)
   {
     hb_glyph_info_t *info = &buffer->info[buffer->len++];
 
-    info->codepoint = glyphs[i];
+    info->codepoint = glyphIndices[i];
     info->cluster = vis_clusters[i];
 
     /* The rest is crap.  Let's store position info there for now. */
-    info->mask = advances[i];
-    info->var1.u32 = offsets[i].ascenderOffset;
-    info->var2.u32 = -offsets[i].advanceOffset;
+    info->mask = glyphAdvances[i];
+    info->var1.i32 = glyphOffsets[i].advanceOffset;
+    info->var2.i32 = glyphOffsets[i].ascenderOffset;
   }
 
-  free(clusters);
-  free(glyphs);
-  free(textProperties);
-  free(glyphProperties);
-
   /* Set glyph positions */
   buffer->clear_positions ();
-  for (unsigned int i = 0; i < glyphs_len; i++)
+  for (unsigned int i = 0; i < glyphCount; 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 = backward ? -info->var1.u32 : info->var1.u32;
-    pos->y_offset = info->var2.u32;
+    pos->x_advance = x_mult * (int32_t) info->mask;
+    pos->x_offset =
+      x_mult * (isRightToLeft ? -info->var1.i32 : info->var1.i32);
+    pos->y_offset = y_mult * info->var2.i32;
   }
 
-  if (backward)
+  if (isRightToLeft)
     hb_buffer_reverse (buffer);
 
+  free (clusterMap);
+  free (glyphIndices);
+  free (textProperties);
+  free (glyphProperties);
+  free (glyphAdvances);
+  free (glyphOffsets);
+
+  if (num_features)
+    free (singleFeatures.features);
+
   /* Wow, done! */
   return true;
 }
diff --git a/src/hb-fallback-shape.cc b/src/hb-fallback-shape.cc
index b5ebfc0..e2ad240 100644
--- a/src/hb-fallback-shape.cc
+++ b/src/hb-fallback-shape.cc
@@ -106,7 +106,7 @@
    */
 
   hb_codepoint_t space;
-  bool has_space = (bool) font->get_glyph (' ', 0, &space);
+  bool has_space = (bool) font->get_nominal_glyph (' ', &space);
 
   buffer->clear_positions ();
 
@@ -123,7 +123,7 @@
       pos[i].y_advance = 0;
       continue;
     }
-    font->get_glyph (info[i].codepoint, 0, &info[i].codepoint);
+    font->get_nominal_glyph (info[i].codepoint, &info[i].codepoint);
     font->get_glyph_advance_for_direction (info[i].codepoint,
 					   direction,
 					   &pos[i].x_advance,
diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index 9138c23..8da40a9 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -44,7 +44,8 @@
 #define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
   HB_FONT_FUNC_IMPLEMENT (font_h_extents) \
   HB_FONT_FUNC_IMPLEMENT (font_v_extents) \
-  HB_FONT_FUNC_IMPLEMENT (glyph) \
+  HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \
+  HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
   HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
   HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
   HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
@@ -180,16 +181,25 @@
   inline bool has_glyph (hb_codepoint_t unicode)
   {
     hb_codepoint_t glyph;
-    return get_glyph (unicode, 0, &glyph);
+    return get_nominal_glyph (unicode, &glyph);
   }
 
-  inline hb_bool_t get_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
-			      hb_codepoint_t *glyph)
+  inline hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
+				      hb_codepoint_t *glyph)
   {
     *glyph = 0;
-    return klass->get.f.glyph (this, user_data,
-			       unicode, variation_selector, glyph,
-			       klass->user_data.glyph);
+    return klass->get.f.nominal_glyph (this, user_data,
+				       unicode, glyph,
+				       klass->user_data.nominal_glyph);
+  }
+
+  inline hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+					hb_codepoint_t *glyph)
+  {
+    *glyph = 0;
+    return klass->get.f.variation_glyph (this, user_data,
+					 unicode, variation_selector, glyph,
+					 klass->user_data.variation_glyph);
   }
 
   inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
@@ -487,7 +497,7 @@
       hb_codepoint_t unichar;
       if (0 == strncmp (s, "uni", 3) &&
 	  hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
-	  get_glyph (unichar, 0, glyph))
+	  get_nominal_glyph (unichar, glyph))
 	return true;
     }
 
diff --git a/src/hb-font.cc b/src/hb-font.cc
index c038b10..6a4823a 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -93,27 +93,48 @@
 }
 
 static hb_bool_t
-hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
-		       void *font_data HB_UNUSED,
-		       hb_codepoint_t unicode,
-		       hb_codepoint_t variation_selector,
-		       hb_codepoint_t *glyph,
-		       void *user_data HB_UNUSED)
+hb_font_get_nominal_glyph_nil (hb_font_t *font HB_UNUSED,
+			       void *font_data HB_UNUSED,
+			       hb_codepoint_t unicode,
+			       hb_codepoint_t *glyph,
+			       void *user_data HB_UNUSED)
 {
   *glyph = 0;
   return false;
 }
 static hb_bool_t
-hb_font_get_glyph_parent (hb_font_t *font,
-			  void *font_data HB_UNUSED,
-			  hb_codepoint_t unicode,
-			  hb_codepoint_t variation_selector,
-			  hb_codepoint_t *glyph,
-			  void *user_data HB_UNUSED)
+hb_font_get_nominal_glyph_parent (hb_font_t *font,
+				  void *font_data HB_UNUSED,
+				  hb_codepoint_t unicode,
+				  hb_codepoint_t *glyph,
+				  void *user_data HB_UNUSED)
 {
-  return font->parent->get_glyph (unicode, variation_selector, glyph);
+  return font->parent->get_nominal_glyph (unicode, glyph);
 }
 
+static hb_bool_t
+hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED,
+				 void *font_data HB_UNUSED,
+				 hb_codepoint_t unicode,
+				 hb_codepoint_t variation_selector,
+				 hb_codepoint_t *glyph,
+				 void *user_data HB_UNUSED)
+{
+  *glyph = 0;
+  return false;
+}
+static hb_bool_t
+hb_font_get_variation_glyph_parent (hb_font_t *font,
+				    void *font_data HB_UNUSED,
+				    hb_codepoint_t unicode,
+				    hb_codepoint_t variation_selector,
+				    hb_codepoint_t *glyph,
+				    void *user_data HB_UNUSED)
+{
+  return font->parent->get_variation_glyph (unicode, variation_selector, glyph);
+}
+
+
 static hb_position_t
 hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED,
 				 void *font_data HB_UNUSED,
@@ -622,7 +643,50 @@
 		   hb_codepoint_t unicode, hb_codepoint_t variation_selector,
 		   hb_codepoint_t *glyph)
 {
-  return font->get_glyph (unicode, variation_selector, glyph);
+  if (unlikely (variation_selector))
+    return font->get_variation_glyph (unicode, variation_selector, glyph);
+  return font->get_nominal_glyph (unicode, glyph);
+}
+
+/**
+ * hb_font_get_nominal_glyph:
+ * @font: a font.
+ * @unicode: 
+ * @glyph: (out): 
+ *
+ * 
+ *
+ * Return value: 
+ *
+ * Since: 1.2.3
+ **/
+hb_bool_t
+hb_font_get_nominal_glyph (hb_font_t *font,
+			   hb_codepoint_t unicode,
+			   hb_codepoint_t *glyph)
+{
+  return font->get_nominal_glyph (unicode, glyph);
+}
+
+/**
+ * hb_font_get_variation_glyph:
+ * @font: a font.
+ * @unicode: 
+ * @variation_selector: 
+ * @glyph: (out): 
+ *
+ * 
+ *
+ * Return value: 
+ *
+ * Since: 1.2.3
+ **/
+hb_bool_t
+hb_font_get_variation_glyph (hb_font_t *font,
+			     hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+			     hb_codepoint_t *glyph)
+{
+  return font->get_variation_glyph (unicode, variation_selector, glyph);
 }
 
 /**
@@ -1472,3 +1536,131 @@
   if (x_ppem) *x_ppem = font->x_ppem;
   if (y_ppem) *y_ppem = font->y_ppem;
 }
+
+
+#ifndef HB_DISABLE_DEPRECATED
+
+/*
+ * Deprecated get_glyph_func():
+ */
+
+struct hb_trampoline_closure_t
+{
+  void *user_data;
+  hb_destroy_func_t destroy;
+  unsigned int ref_count;
+};
+
+template <typename FuncType>
+struct hb_trampoline_t
+{
+  hb_trampoline_closure_t closure; /* Must be first. */
+  FuncType func;
+};
+
+template <typename FuncType>
+static hb_trampoline_t<FuncType> *
+trampoline_create (FuncType           func,
+		   void              *user_data,
+		   hb_destroy_func_t  destroy)
+{
+  typedef hb_trampoline_t<FuncType> trampoline_t;
+
+  trampoline_t *trampoline = (trampoline_t *) calloc (1, sizeof (trampoline_t));
+
+  if (unlikely (!trampoline))
+    return NULL;
+
+  trampoline->closure.user_data = user_data;
+  trampoline->closure.destroy = destroy;
+  trampoline->closure.ref_count = 1;
+  trampoline->func = func;
+
+  return trampoline;
+}
+
+static void
+trampoline_reference (hb_trampoline_closure_t *closure)
+{
+  closure->ref_count++;
+}
+
+static void
+trampoline_destroy (void *user_data)
+{
+  hb_trampoline_closure_t *closure = (hb_trampoline_closure_t *) user_data;
+
+  if (--closure->ref_count)
+    return;
+
+  if (closure->destroy)
+    closure->destroy (closure->user_data);
+  free (closure);
+}
+
+typedef hb_trampoline_t<hb_font_get_glyph_func_t> hb_font_get_glyph_trampoline_t;
+
+static hb_bool_t
+hb_font_get_nominal_glyph_trampoline (hb_font_t *font,
+				      void *font_data,
+				      hb_codepoint_t unicode,
+				      hb_codepoint_t *glyph,
+				      void *user_data)
+{
+  hb_font_get_glyph_trampoline_t *trampoline = (hb_font_get_glyph_trampoline_t *) user_data;
+  return trampoline->func (font, font_data, unicode, 0, glyph, trampoline->closure.user_data);
+}
+
+static hb_bool_t
+hb_font_get_variation_glyph_trampoline (hb_font_t *font,
+					void *font_data,
+					hb_codepoint_t unicode,
+					hb_codepoint_t variation_selector,
+					hb_codepoint_t *glyph,
+					void *user_data)
+{
+  hb_font_get_glyph_trampoline_t *trampoline = (hb_font_get_glyph_trampoline_t *) user_data;
+  return trampoline->func (font, font_data, unicode, variation_selector, glyph, trampoline->closure.user_data);
+}
+
+/**
+ * hb_font_funcs_set_glyph_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ * Deprecated.  Use hb_font_funcs_set_nominal_glyph_func() and
+ * hb_font_funcs_set_variation_glyph_func() instead.
+ *
+ * Since: 0.9.2
+ * Deprecated: 1.2.3
+ **/
+void
+hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
+			      hb_font_get_glyph_func_t func,
+			      void *user_data, hb_destroy_func_t destroy)
+{
+  hb_font_get_glyph_trampoline_t *trampoline;
+
+  trampoline = trampoline_create (func, user_data, destroy);
+  if (unlikely (!trampoline))
+  {
+    if (destroy)
+      destroy (user_data);
+    return;
+  }
+
+  hb_font_funcs_set_nominal_glyph_func (ffuncs,
+					hb_font_get_nominal_glyph_trampoline,
+					trampoline,
+					trampoline_destroy);
+
+  trampoline_reference (&trampoline->closure);
+  hb_font_funcs_set_variation_glyph_func (ffuncs,
+					  hb_font_get_variation_glyph_trampoline,
+					  trampoline,
+					  trampoline_destroy);
+}
+
+#endif /* HB_DISABLE_DEPRECATED */
diff --git a/src/hb-font.h b/src/hb-font.h
index 82d056c..2b6ab50 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -116,10 +116,14 @@
 typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t;
 
 
-typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data,
-					       hb_codepoint_t unicode, hb_codepoint_t variation_selector,
-					       hb_codepoint_t *glyph,
-					       void *user_data);
+typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *font_data,
+						       hb_codepoint_t unicode,
+						       hb_codepoint_t *glyph,
+						       void *user_data);
+typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void *font_data,
+							 hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+							 hb_codepoint_t *glyph,
+							 void *user_data);
 
 
 typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data,
@@ -197,7 +201,7 @@
 				       void *user_data, hb_destroy_func_t destroy);
 
 /**
- * hb_font_funcs_set_glyph_func:
+ * hb_font_funcs_set_nominal_glyph_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
@@ -205,12 +209,28 @@
  *
  * 
  *
- * Since: 0.9.2
+ * Since: 1.2.3
  **/
 HB_EXTERN void
-hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
-			      hb_font_get_glyph_func_t func,
-			      void *user_data, hb_destroy_func_t destroy);
+hb_font_funcs_set_nominal_glyph_func (hb_font_funcs_t *ffuncs,
+				      hb_font_get_nominal_glyph_func_t func,
+				      void *user_data, hb_destroy_func_t destroy);
+
+/**
+ * hb_font_funcs_set_variation_glyph_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ * 
+ *
+ * Since: 1.2.3
+ **/
+HB_EXTERN void
+hb_font_funcs_set_variation_glyph_func (hb_font_funcs_t *ffuncs,
+					hb_font_get_variation_glyph_func_t func,
+					void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_h_advance_func:
@@ -382,9 +402,13 @@
 		       hb_font_extents_t *extents);
 
 HB_EXTERN hb_bool_t
-hb_font_get_glyph (hb_font_t *font,
-		   hb_codepoint_t unicode, hb_codepoint_t variation_selector,
-		   hb_codepoint_t *glyph);
+hb_font_get_nominal_glyph (hb_font_t *font,
+			   hb_codepoint_t unicode,
+			   hb_codepoint_t *glyph);
+HB_EXTERN hb_bool_t
+hb_font_get_variation_glyph (hb_font_t *font,
+			     hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+			     hb_codepoint_t *glyph);
 
 HB_EXTERN hb_position_t
 hb_font_get_glyph_h_advance (hb_font_t *font,
@@ -431,6 +455,13 @@
 
 /* high-level funcs, with fallback */
 
+/* Calls either hb_font_get_nominal_glyph() if variation_selector is 0,
+ * otherwise callse hb_font_get_variation_glyph(). */
+HB_EXTERN hb_bool_t
+hb_font_get_glyph (hb_font_t *font,
+		   hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+		   hb_codepoint_t *glyph);
+
 HB_EXTERN void
 hb_font_get_extents_for_direction (hb_font_t *font,
 				   hb_direction_t direction,
diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index eed1787..2cad8c2 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -155,21 +155,32 @@
 
 
 static hb_bool_t
-hb_ft_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)
-
+hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED,
+			 void *font_data,
+			 hb_codepoint_t unicode,
+			 hb_codepoint_t *glyph,
+			 void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-  unsigned int g;
+  unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode);
 
-  if (likely (!variation_selector))
-    g = FT_Get_Char_Index (ft_font->ft_face, unicode);
-  else
-    g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector);
+  if (unlikely (!g))
+    return false;
+
+  *glyph = g;
+  return true;
+}
+
+static hb_bool_t
+hb_ft_get_variation_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_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  unsigned int g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector);
 
   if (unlikely (!g))
     return false;
@@ -408,7 +419,8 @@
 
     hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, NULL, NULL);
     //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, NULL, NULL);
-    hb_font_funcs_set_glyph_func (funcs, hb_ft_get_glyph, NULL, NULL);
+    hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, NULL, NULL);
+    hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, NULL, NULL);
     hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, NULL, NULL);
     hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, NULL, NULL);
     //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, NULL, NULL);
diff --git a/src/hb-icu.cc b/src/hb-icu.cc
index 24cec9d..ee54721 100644
--- a/src/hb-icu.cc
+++ b/src/hb-icu.cc
@@ -36,6 +36,7 @@
 #include <unicode/uchar.h>
 #include <unicode/unorm.h>
 #include <unicode/ustring.h>
+#include <unicode/utf16.h>
 #include <unicode/uversion.h>
 
 
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 6a52000..80ad687 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -662,6 +662,15 @@
 /* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
 typedef USHORT UFWORD;
 
+/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
+struct F2DOT14 : SHORT
+{
+  //inline float to_float (void) const { return ???; }
+  //inline void set_float (float f) { v.set (f * ???); }
+  public:
+  DEFINE_SIZE_STATIC (2);
+};
+
 /* Date represented in number of seconds since 12:00 midnight, January 1,
  * 1904. The value is represented as a signed 64-bit integer. */
 struct LONGDATETIME
@@ -742,7 +751,7 @@
 template <typename FixedType=USHORT>
 struct FixedVersion
 {
-  inline uint32_t to_int (void) const { return (major << sizeof(FixedType)) + minor; }
+  inline uint32_t to_int (void) const { return (major << (sizeof(FixedType) * 8)) + minor; }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index c9161f0..d7a94a1 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -69,61 +69,78 @@
 
 struct CmapSubtableFormat4
 {
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  struct accelerator_t
   {
-    unsigned int segCount;
+    inline void init (const CmapSubtableFormat4 *subtable)
+    {
+      segCount = subtable->segCountX2 / 2;
+      endCount = subtable->values;
+      startCount = endCount + segCount + 1;
+      idDelta = startCount + segCount;
+      idRangeOffset = idDelta + segCount;
+      glyphIdArray = idRangeOffset + segCount;
+      glyphIdArrayLength = (subtable->length - 16 - 8 * segCount) / 2;
+    }
+
+    static inline bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
+    {
+      const accelerator_t *thiz = (const accelerator_t *) obj;
+
+      /* Custom two-array bsearch. */
+      int min = 0, max = (int) thiz->segCount - 1;
+      const USHORT *startCount = thiz->startCount;
+      const USHORT *endCount = thiz->endCount;
+      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 = thiz->idRangeOffset[i];
+      if (rangeOffset == 0)
+	gid = codepoint + thiz->idDelta[i];
+      else
+      {
+	/* Somebody has been smoking... */
+	unsigned int index = rangeOffset / 2 + (codepoint - thiz->startCount[i]) + i - thiz->segCount;
+	if (unlikely (index >= thiz->glyphIdArrayLength))
+	  return false;
+	gid = thiz->glyphIdArray[index];
+	if (unlikely (!gid))
+	  return false;
+	gid += thiz->idDelta[i];
+      }
+
+      *glyph = gid & 0xFFFFu;
+      return true;
+    }
+
     const USHORT *endCount;
     const USHORT *startCount;
     const USHORT *idDelta;
     const USHORT *idRangeOffset;
     const USHORT *glyphIdArray;
+    unsigned int segCount;
     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 get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  {
+    accelerator_t accel;
+    accel.init (this);
+    return accel.get_glyph_func (&accel, codepoint, glyph);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -388,7 +405,7 @@
   }
 
   protected:
-  USHORT	format;		/* Format number is set to 0. */
+  USHORT	format;		/* Format number is set to 14. */
   ULONG		lengthZ;	/* Byte length of this subtable. */
   SortedArrayOf<VariationSelectorRecord, ULONG>
 		record;		/* Variation selector records; sorted
@@ -416,16 +433,6 @@
     }
   }
 
-  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) const
   {
     TRACE_SANITIZE (this);
@@ -442,7 +449,7 @@
     }
   }
 
-  protected:
+  public:
   union {
   USHORT		format;		/* Format identifier */
   CmapSubtableFormat0	format0;
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index e7b57b8..61c7036 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -201,10 +201,26 @@
   }
 };
 
+typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
+					  hb_codepoint_t codepoint,
+					  hb_codepoint_t *glyph);
+
+template <typename Type>
+static inline bool get_glyph_from (const void *obj,
+				   hb_codepoint_t codepoint,
+				   hb_codepoint_t *glyph)
+{
+  const Type *typed_obj = (const Type *) obj;
+  return typed_obj->get_glyph (codepoint, glyph);
+}
+
 struct hb_ot_face_cmap_accelerator_t
 {
-  const OT::CmapSubtable *table;
-  const OT::CmapSubtable *uvs_table;
+  hb_cmap_get_glyph_func_t get_glyph_func;
+  const void *get_glyph_data;
+  OT::CmapSubtableFormat4::accelerator_t format4_accel;
+
+  const OT::CmapSubtableFormat14 *uvs_table;
   hb_blob_t *blob;
 
   inline void init (hb_face_t *face)
@@ -212,7 +228,7 @@
     this->blob = OT::Sanitizer<OT::cmap>::sanitize (face->reference_table (HB_OT_TAG_cmap));
     const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob);
     const OT::CmapSubtable *subtable = NULL;
-    const OT::CmapSubtable *subtable_uvs = NULL;
+    const OT::CmapSubtableFormat14 *subtable_uvs = NULL;
 
     /* 32-bit subtables. */
     if (!subtable) subtable = cmap->find_subtable (3, 10);
@@ -229,12 +245,30 @@
     if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
 
     /* UVS subtable. */
-    if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5);
+    if (!subtable_uvs)
+    {
+      const OT::CmapSubtable *st = cmap->find_subtable (0, 5);
+      if (st && st->u.format == 14)
+        subtable_uvs = &st->u.format14;
+    }
     /* Meh. */
-    if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable);
+    if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtableFormat14);
 
-    this->table = subtable;
     this->uvs_table = subtable_uvs;
+
+    this->get_glyph_data = subtable;
+    switch (subtable->u.format) {
+    /* Accelerate format 4 and format 12. */
+    default: this->get_glyph_func = get_glyph_from<OT::CmapSubtable>;		break;
+    case 12: this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>;	break;
+    case  4:
+      {
+        this->format4_accel.init (&subtable->u.format4);
+	this->get_glyph_data = &this->format4_accel;
+        this->get_glyph_func = this->format4_accel.get_glyph_func;
+      }
+      break;
+    }
   }
 
   inline void fini (void)
@@ -242,23 +276,26 @@
     hb_blob_destroy (this->blob);
   }
 
-  inline bool get_glyph (hb_codepoint_t  unicode,
-			 hb_codepoint_t  variation_selector,
-			 hb_codepoint_t *glyph) const
+  inline bool get_nominal_glyph (hb_codepoint_t  unicode,
+				 hb_codepoint_t *glyph) const
   {
-    if (unlikely (variation_selector))
+    return this->get_glyph_func (this->get_glyph_data, unicode, glyph);
+  }
+
+  inline bool get_variation_glyph (hb_codepoint_t  unicode,
+				   hb_codepoint_t  variation_selector,
+				   hb_codepoint_t *glyph) const
+  {
+    switch (this->uvs_table->get_glyph_variant (unicode,
+						variation_selector,
+						glyph))
     {
-      switch (this->uvs_table->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;
-      }
+      case OT::GLYPH_VARIANT_NOT_FOUND:		return false;
+      case OT::GLYPH_VARIANT_FOUND:		return true;
+      case OT::GLYPH_VARIANT_USE_DEFAULT:	break;
     }
 
-    return this->table->get_glyph (unicode, glyph);
+    return get_nominal_glyph (unicode, glyph);
   }
 };
 
@@ -301,16 +338,27 @@
 
 
 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)
+hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
+			 void *font_data,
+			 hb_codepoint_t unicode,
+			 hb_codepoint_t *glyph,
+			 void *user_data HB_UNUSED)
 
 {
   const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return ot_font->cmap.get_glyph (unicode, variation_selector, glyph);
+  return ot_font->cmap.get_nominal_glyph (unicode, glyph);
+}
+
+static hb_bool_t
+hb_ot_get_variation_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;
+  return ot_font->cmap.get_variation_glyph (unicode, variation_selector, glyph);
 }
 
 static hb_position_t
@@ -397,7 +445,8 @@
 
     hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, NULL, NULL);
     hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, NULL, NULL);
-    hb_font_funcs_set_glyph_func (funcs, hb_ot_get_glyph, NULL, NULL);
+    hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, NULL, NULL);
+    hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, NULL, NULL);
     hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, NULL, NULL);
     hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, NULL, NULL);
     //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, NULL, NULL);
diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh
index 9e5af6d..dc7aa84 100644
--- a/src/hb-ot-glyf-table.hh
+++ b/src/hb-ot-glyf-table.hh
@@ -90,10 +90,10 @@
 					 * greater than or equal to zero,
 					 * this is a simple glyph; if negative,
 					 * this is a composite glyph. */
-  SHORT		xMin;			/* Minimum x for coordinate data. */
-  SHORT		yMin;			/* Minimum y for coordinate data. */
-  SHORT		xMax;			/* Maximum x for coordinate data. */
-  SHORT		yMax;			/* Maximum y for coordinate data. */
+  FWORD		xMin;			/* Minimum x for coordinate data. */
+  FWORD		yMin;			/* Minimum y for coordinate data. */
+  FWORD		xMax;			/* Maximum x for coordinate data. */
+  FWORD		yMax;			/* Maximum y for coordinate data. */
 
   DEFINE_SIZE_STATIC (10);
 };
diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh
index 49056e6..a9606b3 100644
--- a/src/hb-ot-hmtx-table.hh
+++ b/src/hb-ot-hmtx-table.hh
@@ -44,8 +44,8 @@
 
 struct LongMetric
 {
-  USHORT	advance; /* Advance width/height. */
-  SHORT		lsb; /* Leading (left/top) side bearing. */
+  UFWORD	advance; /* Advance width/height. */
+  FWORD		lsb; /* Leading (left/top) side bearing. */
   public:
   DEFINE_SIZE_STATIC (4);
 };
@@ -74,7 +74,7 @@
 					 * be in the array, but that entry is
 					 * required. The last entry applies to
 					 * all subsequent glyphs. */
-  SHORT		leadingBearingX[VAR];	/* Here the advance is assumed
+  FWORD		leadingBearingX[VAR];	/* Here the advance is assumed
 					 * to be the same as the advance
 					 * for the last entry above. The
 					 * number of entries in this array is
diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index 59dddcf..bbe390c 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -437,22 +437,6 @@
     o.attach_type() = ATTACH_TYPE_MARK;
     o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
     buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
-    {
-      unsigned int i = buffer->idx;
-      unsigned int j = glyph_pos;
-      hb_glyph_position_t *pos = buffer->pos;
-      assert (j < i);
-      if (HB_DIRECTION_IS_FORWARD (c->direction))
-	for (unsigned int k = j; k < i; k++) {
-	  pos[i].x_offset -= pos[k].x_advance;
-	  pos[i].y_offset -= pos[k].y_advance;
-	}
-      else
-	for (unsigned int k = j + 1; k < i + 1; k++) {
-	  pos[i].x_offset += pos[k].x_advance;
-	  pos[i].y_offset += pos[k].y_advance;
-	}
-    }
 
     buffer->idx++;
     return_trace (true);
@@ -1593,6 +1577,18 @@
   {
     pos[i].x_offset += pos[j].x_offset;
     pos[i].y_offset += pos[j].y_offset;
+
+    assert (j < i);
+    if (HB_DIRECTION_IS_FORWARD (direction))
+      for (unsigned int k = j; k < i; k++) {
+	pos[i].x_offset -= pos[k].x_advance;
+	pos[i].y_offset -= pos[k].y_advance;
+      }
+    else
+      for (unsigned int k = j + 1; k < i + 1; k++) {
+	pos[i].x_offset += pos[k].x_advance;
+	pos[i].y_offset += pos[k].y_advance;
+      }
   }
 }
 
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index 38c2c64..7de56cf 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -1288,10 +1288,28 @@
 
   const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef;
   unsigned int count = buffer->len;
+  hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = 0; i < count; i++)
   {
-    _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
-    _hb_glyph_info_clear_lig_props (&buffer->info[i]);
+    unsigned int props = gdef.get_glyph_props (info[i].codepoint);
+    if (!props)
+    {
+      /* Never mark default-ignorables as marks.
+       * They won't get in the way of lookups anyway,
+       * but having them as mark will cause them to be skipped
+       * over if the lookup-flag says so, but at least for the
+       * Mongolian variation selectors, looks like Uniscribe
+       * marks them as non-mark.  Some Mongolian fonts without
+       * GDEF rely on this.  Another notable character that
+       * this applies to is COMBINING GRAPHEME JOINER. */
+      props = (_hb_glyph_info_get_general_category (&info[i]) !=
+	       HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
+	       _hb_glyph_info_is_default_ignorable (&info[i])) ?
+	      HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
+	      HB_OT_LAYOUT_GLYPH_PROPS_MARK;
+    }
+    _hb_glyph_info_set_glyph_props (&info[i], props);
+    _hb_glyph_info_clear_lig_props (&info[i]);
     buffer->info[i].syllable() = 0;
   }
 }
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index adf232b..5628ac3 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -60,6 +60,35 @@
   layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (HB_OT_TAG_GPOS));
   layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob);
 
+  {
+    /*
+     * The ugly business of blacklisting individual fonts' tables happen here!
+     * See this thread for why we finally had to bend in and do this:
+     * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
+     */
+    unsigned int gdef_len = hb_blob_get_length (layout->gdef_blob);
+    unsigned int gsub_len = hb_blob_get_length (layout->gsub_blob);
+    unsigned int gpos_len = hb_blob_get_length (layout->gpos_blob);
+    if (0
+      || (442 == gdef_len && 42038 == gpos_len && 2874 == gsub_len) /* Windows 7 timesi.ttf */
+      || (430 == gdef_len && 40662 == gpos_len && 2874 == gsub_len) /* Windows 7 timesbi.ttf */
+      || (442 == gdef_len && 39116 == gpos_len && 2874 == gsub_len) /* Windows ??? timesi.ttf */
+      || (430 == gdef_len && 39374 == gpos_len && 2874 == gsub_len) /* Windows ??? timesbi.ttf */
+      || (490 == gdef_len && 41638 == gpos_len && 3046 == gsub_len) /* OS X 10.11.3 Times New Roman Italic.ttf */
+      || (478 == gdef_len && 41902 == gpos_len && 3046 == gsub_len) /* OS X 10.11.3 Times New Roman Bold Italic.ttf */
+    )
+    {
+      /* In certain versions of Times New Roman Italic and Bold Italic,
+       * ASCII double quotation mark U+0022, mapped to glyph 5, has wrong
+       * glyph class 3 (mark) in GDEF.  Nuke the GDEF to avoid zero-width
+       * double-quote.  See:
+       * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
+       */
+     if (3 == layout->gdef->get_glyph_class (5))
+       layout->gdef = &OT::Null(OT::GDEF);
+    }
+  }
+
   layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
   layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
 
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index 7bdeddb..7822cef 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -204,11 +204,8 @@
     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],
diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index 21256de..1e151a7 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -493,12 +493,12 @@
     hb_codepoint_t glyph = virama_glyph;
     if (unlikely (virama_glyph == (hb_codepoint_t) -1))
     {
-      if (!config->virama || !font->get_glyph (config->virama, 0, &glyph))
+      if (!config->virama || !font->get_nominal_glyph (config->virama, &glyph))
 	glyph = 0;
       /* Technically speaking, the spec says we should apply 'locl' to virama too.
        * Maybe one day... */
 
-      /* Our get_glyph() function needs a font, so we can't get the virama glyph
+      /* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph
        * during shape planning...  Instead, overwrite it here.  It's safe.  Don't worry! */
       (const_cast<indic_shape_plan_t *> (this))->virama_glyph = glyph;
     }
@@ -742,10 +742,6 @@
 
     switch (indic_plan->config->base_pos)
     {
-      default:
-        assert (false);
-	HB_FALLTHROUGH;
-
       case BASE_POS_LAST:
       {
 	/* -> starting from the end of the syllable, move backwards */
@@ -1219,7 +1215,7 @@
 
 
   hb_codepoint_t dottedcircle_glyph;
-  if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph))
+  if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
     return;
 
   hb_glyph_info_t dottedcircle = {0};
@@ -1803,7 +1799,7 @@
     hb_codepoint_t glyph;
 
     if (hb_options ().uniscribe_bug_compatible ||
-	(c->font->get_glyph (ab, 0, &glyph) &&
+	(c->font->get_nominal_glyph (ab, &glyph) &&
 	 indic_plan->pstf.would_substitute (&glyph, 1, c->font->face)))
     {
       /* Ok, safe to use Uniscribe-style decomposition. */
diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc
index 7b04344..545765d 100644
--- a/src/hb-ot-shape-complex-myanmar.cc
+++ b/src/hb-ot-shape-complex-myanmar.cc
@@ -439,7 +439,7 @@
 
 
   hb_codepoint_t dottedcircle_glyph;
-  if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph))
+  if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
     return;
 
   hb_glyph_info_t dottedcircle = {0};
diff --git a/src/hb-ot-shape-complex-thai.cc b/src/hb-ot-shape-complex-thai.cc
index 58392b6..4322b0d 100644
--- a/src/hb-ot-shape-complex-thai.cc
+++ b/src/hb-ot-shape-complex-thai.cc
@@ -139,7 +139,6 @@
   };
 
   switch (action) {
-    default: assert (false); HB_FALLTHROUGH;
     case NOP: return u;
     case SD:  pua_mappings = SD_mappings; break;
     case SDL: pua_mappings = SDL_mappings; break;
diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc
index 6fbfe2b..d2b6e63 100644
--- a/src/hb-ot-shape-complex-use.cc
+++ b/src/hb-ot-shape-complex-use.cc
@@ -499,7 +499,7 @@
     return;
 
   hb_glyph_info_t dottedcircle = {0};
-  if (!font->get_glyph (0x25CCu, 0, &dottedcircle.codepoint))
+  if (!font->get_nominal_glyph (0x25CCu, &dottedcircle.codepoint))
     return;
   dottedcircle.use_category() = hb_use_get_categories (0x25CC);
 
diff --git a/src/hb-ot-shape-fallback.cc b/src/hb-ot-shape-fallback.cc
index c9cf737..ea8312b 100644
--- a/src/hb-ot-shape-fallback.cc
+++ b/src/hb-ot-shape-fallback.cc
@@ -526,7 +526,7 @@
 
 	case t::SPACE_FIGURE:
 	  for (char u = '0'; u <= '9'; u++)
-	    if (font->get_glyph (u, 0, &glyph))
+	    if (font->get_nominal_glyph (u, &glyph))
 	    {
 	      pos[i].x_advance = font->get_glyph_h_advance (glyph);
 	      break;
@@ -534,9 +534,9 @@
 	  break;
 
 	case t::SPACE_PUNCTUATION:
-	  if (font->get_glyph ('.', 0, &glyph))
+	  if (font->get_nominal_glyph ('.', &glyph))
 	    pos[i].x_advance = font->get_glyph_h_advance (glyph);
-	  else if (font->get_glyph (',', 0, &glyph))
+	  else if (font->get_nominal_glyph (',', &glyph))
 	    pos[i].x_advance = font->get_glyph_h_advance (glyph);
 	  break;
 
diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc
index 3f00b8e..107617e 100644
--- a/src/hb-ot-shape-normalize.cc
+++ b/src/hb-ot-shape-normalize.cc
@@ -91,7 +91,7 @@
 static inline void
 set_glyph (hb_glyph_info_t &info, hb_font_t *font)
 {
-  font->get_glyph (info.codepoint, 0, &info.glyph_index());
+  font->get_nominal_glyph (info.codepoint, &info.glyph_index());
 }
 
 static inline void
@@ -124,10 +124,10 @@
   hb_font_t * const font = c->font;
 
   if (!c->decompose (c, ab, &a, &b) ||
-      (b && !font->get_glyph (b, 0, &b_glyph)))
+      (b && !font->get_nominal_glyph (b, &b_glyph)))
     return 0;
 
-  bool has_a = (bool) font->get_glyph (a, 0, &a_glyph);
+  bool has_a = (bool) font->get_nominal_glyph (a, &a_glyph);
   if (shortest && has_a) {
     /* Output a and b */
     output_char (buffer, a, a_glyph);
@@ -166,7 +166,7 @@
   hb_codepoint_t u = buffer->cur().codepoint;
   hb_codepoint_t glyph;
 
-  if (shortest && c->font->get_glyph (u, 0, &glyph))
+  if (shortest && c->font->get_nominal_glyph (u, &glyph))
   {
     next_char (buffer, glyph);
     return;
@@ -178,7 +178,7 @@
     return;
   }
 
-  if (!shortest && c->font->get_glyph (u, 0, &glyph))
+  if (!shortest && c->font->get_nominal_glyph (u, &glyph))
   {
     next_char (buffer, glyph);
     return;
@@ -188,7 +188,7 @@
   {
     hb_codepoint_t space_glyph;
     hb_unicode_funcs_t::space_t space_type = buffer->unicode->space_fallback_type (u);
-    if (space_type != hb_unicode_funcs_t::NOT_SPACE && c->font->get_glyph (0x0020u, 0, &space_glyph))
+    if (space_type != hb_unicode_funcs_t::NOT_SPACE && c->font->get_nominal_glyph (0x0020u, &space_glyph))
     {
       _hb_glyph_info_set_unicode_space_fallback_type (&buffer->cur(), space_type);
       next_char (buffer, space_glyph);
@@ -202,7 +202,7 @@
     /* U+2011 is the only sensible character that is a no-break version of another character
      * and not a space.  The space ones are handled already.  Handle this lone one. */
     hb_codepoint_t other_glyph;
-    if (c->font->get_glyph (0x2010u, 0, &other_glyph))
+    if (c->font->get_nominal_glyph (0x2010u, &other_glyph))
     {
       next_char (buffer, other_glyph);
       return;
@@ -221,7 +221,7 @@
   for (; buffer->idx < end - 1 && !buffer->in_error;) {
     if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) {
       /* The next two lines are some ugly lines... But work. */
-      if (font->get_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index()))
+      if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index()))
       {
 	buffer->replace_glyphs (2, 1, &buffer->cur().codepoint);
       }
@@ -388,7 +388,7 @@
 		   buffer->cur().codepoint,
 		   &composed) &&
 	/* And the font has glyph for the composite. */
-	font->get_glyph (composed, 0, &glyph))
+	font->get_nominal_glyph (composed, &glyph))
     {
       /* Composes. */
       buffer->next_glyph (); /* Copy to out-buffer. */
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 42b921c..7811cb7 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -456,7 +456,7 @@
     return;
 
   hb_codepoint_t space;
-  if (c->font->get_glyph (' ', 0, &space))
+  if (c->font->get_nominal_glyph (' ', &space))
   {
     /* Replace default-ignorables with a zero-advance space glyph. */
     for (/*continue*/; i < count; i++)
@@ -524,32 +524,6 @@
 }
 
 static inline void
-hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
-{
-  unsigned int count = c->buffer->len;
-  hb_glyph_info_t *info = c->buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-  {
-    hb_ot_layout_glyph_props_flags_t klass;
-
-    /* Never mark default-ignorables as marks.
-     * They won't get in the way of lookups anyway,
-     * but having them as mark will cause them to be skipped
-     * over if the lookup-flag says so, but at least for the
-     * Mongolian variation selectors, looks like Uniscribe
-     * marks them as non-mark.  Some Mongolian fonts without
-     * GDEF rely on this.  Another notable character that
-     * this applies to is COMBINING GRAPHEME JOINER. */
-    klass = (_hb_glyph_info_get_general_category (&info[i]) !=
-	     HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
-	     _hb_glyph_info_is_default_ignorable (&info[i])) ?
-	    HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
-	    HB_OT_LAYOUT_GLYPH_PROPS_MARK;
-    _hb_glyph_info_set_glyph_props (&info[i], klass);
-  }
-}
-
-static inline void
 hb_ot_substitute_default (hb_ot_shape_context_t *c)
 {
   hb_buffer_t *buffer = c->buffer;
@@ -580,9 +554,6 @@
 
   hb_ot_layout_substitute_start (c->font, buffer);
 
-  if (!hb_ot_layout_has_glyph_classes (c->face))
-    hb_synthesize_glyph_classes (c);
-
   c->plan->substitute (c->font, buffer);
 
   return;
@@ -848,12 +819,12 @@
 	  hb_set_t           *glyphs)
 {
   hb_codepoint_t glyph;
-  if (font->get_glyph (u, 0, &glyph))
+  if (font->get_nominal_glyph (u, &glyph))
     glyphs->add (glyph);
   if (mirror)
   {
     hb_codepoint_t m = unicode->mirroring (u);
-    if (m != u && font->get_glyph (m, 0, &glyph))
+    if (m != u && font->get_nominal_glyph (m, &glyph))
       glyphs->add (glyph);
   }
 }
diff --git a/src/hb-private.hh b/src/hb-private.hh
index 7afb258..179e4e9 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -611,6 +611,15 @@
 /* Debug */
 
 
+/* HB_NDEBUG disables some sanity checks that are very safe to disable and
+ * should be disabled in production systems.  If NDEBUG is defined, enable
+ * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
+ * light-weight) to be enabled, then HB_DEBUG can be defined to disable
+ * the costlier checks. */
+#ifdef NDEBUG
+#define HB_NDEBUG
+#endif
+
 #ifndef HB_DEBUG
 #define HB_DEBUG 0
 #endif
diff --git a/src/hb-unicode-private.hh b/src/hb-unicode-private.hh
index 44fbe58..ed45374 100644
--- a/src/hb-unicode-private.hh
+++ b/src/hb-unicode-private.hh
@@ -224,7 +224,7 @@
     switch (u)
     {
       /* All GC=Zs chars that can use a fallback. */
-      default:	    return NOT_SPACE;	/* Shouldn't happen. */
+      default:	    return NOT_SPACE;	/* U+1680 OGHAM SPACE MARK */
       case 0x0020u: return SPACE;	/* U+0020 SPACE */
       case 0x00A0u: return SPACE;	/* U+00A0 NO-BREAK SPACE */
       case 0x2000u: return SPACE_EM_2;	/* U+2000 EN QUAD */
diff --git a/src/hb-version.h b/src/hb-version.h
index 3456e7d..c5692d2 100644
--- a/src/hb-version.h
+++ b/src/hb-version.h
@@ -38,9 +38,9 @@
 
 #define HB_VERSION_MAJOR 1
 #define HB_VERSION_MINOR 2
-#define HB_VERSION_MICRO 1
+#define HB_VERSION_MICRO 6
 
-#define HB_VERSION_STRING "1.2.1"
+#define HB_VERSION_STRING "1.2.6"
 
 #define HB_VERSION_ATLEAST(major,minor,micro) \
 	((major)*10000+(minor)*100+(micro) <= \
diff --git a/test/api/test-shape.c b/test/api/test-shape.c
index eb24407..c274f0f 100644
--- a/test/api/test-shape.c
+++ b/test/api/test-shape.c
@@ -101,7 +101,7 @@
 
   ffuncs = hb_font_funcs_create ();
   hb_font_funcs_set_glyph_h_advance_func (ffuncs, glyph_h_advance_func, NULL, NULL);
-  hb_font_funcs_set_glyph_func (ffuncs, glyph_func, NULL, NULL);
+  hb_font_funcs_set_glyph_func (ffuncs, glyph_func, malloc (10), free);
   hb_font_funcs_set_glyph_h_kerning_func (ffuncs, glyph_h_kerning_func, NULL, NULL);
   hb_font_set_funcs (font, ffuncs, NULL, NULL);
   hb_font_funcs_destroy (ffuncs);
diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am
index e70dff7..6320b02 100644
--- a/test/shaping/Makefile.am
+++ b/test/shaping/Makefile.am
@@ -54,6 +54,7 @@
 	tests/indic-old-spec.tests \
 	tests/indic-pref-blocking.tests \
 	tests/ligature-id.tests \
+	tests/mark-filtering-sets.tests \
 	tests/mongolian-variation-selector.tests \
 	tests/spaces.tests \
 	tests/simple.tests \
diff --git a/test/shaping/fonts/sha1sum/07f054357ff8638bac3711b422a1e31180bba863.ttf b/test/shaping/fonts/sha1sum/07f054357ff8638bac3711b422a1e31180bba863.ttf
new file mode 100644
index 0000000..fcd4f32
--- /dev/null
+++ b/test/shaping/fonts/sha1sum/07f054357ff8638bac3711b422a1e31180bba863.ttf
Binary files differ
diff --git a/test/shaping/fonts/sha1sum/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf b/test/shaping/fonts/sha1sum/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf
new file mode 100644
index 0000000..1dbadde
--- /dev/null
+++ b/test/shaping/fonts/sha1sum/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf
Binary files differ
diff --git a/test/shaping/run-tests.sh b/test/shaping/run-tests.sh
index 668bb8c..021c6f8 100755
--- a/test/shaping/run-tests.sh
+++ b/test/shaping/run-tests.sh
@@ -18,10 +18,13 @@
 	set /dev/stdin
 fi
 
-IFS=:
 for f in "$@"; do
 	$reference || echo "Running tests in $f"
-	while read fontfile options unicodes glyphs_expected; do
+	while IFS=: read fontfile options unicodes glyphs_expected; do
+		if echo "$fontfile" | grep -q '^#'; then
+			$reference || echo "Skipping $fontfile:$unicodes"
+			continue
+		fi
 		$reference || echo "Testing $fontfile:$unicodes"
 		glyphs=`$srcdir/hb-unicode-encode "$unicodes" | $hb_shape $options "$srcdir/$fontfile"`
 		if test $? != 0; then
diff --git a/test/shaping/tests/cursive-positioning.tests b/test/shaping/tests/cursive-positioning.tests
index 503554f..ce63bd1 100644
--- a/test/shaping/tests/cursive-positioning.tests
+++ b/test/shaping/tests/cursive-positioning.tests
@@ -1,3 +1,4 @@
 fonts/sha1sum/c4e48b0886ef460f532fb49f00047ec92c432ec0.ttf::U+0643,U+0645,U+0645,U+062B,U+0644:[gid8=4+738|gid5=3@441,1197+0|gid6=3@0,432+405|gid9=2@0,477+452|gid9=1@0,977+452|gid10=0@20,1577+207]
 fonts/sha1sum/298c9e1d955f10f6f72c6915c3c6ff9bf9695cec.ttf::U+0643,U+0645,U+0645,U+062B,U+0644:[gid8=4+738|gid5=3@441,1197+0|gid6=3@0,432+405|gid9=2@0,477+500|gid9=1@0,577+452|gid10=0@20,1177+207]
-fonts/sha1sum/706c5d7b625f207bc0d874c67237aad6f1e9cd6f.ttf::U+0B1F,U+0B4D,U+0B1A,U+0B4D,U+0B1A:[ttaorya=0+1307|casubscriptorya=0@-242,104+-231|casubscriptnarroworya=0@20,104+507]
+#fonts/sha1sum/706c5d7b625f207bc0d874c67237aad6f1e9cd6f.ttf::U+0B1F,U+0B4D,U+0B1A,U+0B4D,U+0B1A:[ttaorya=0+1307|casubscriptorya=0@-242,104+-231|casubscriptnarroworya=0@20,104+507]
+fonts/sha1sum/07f054357ff8638bac3711b422a1e31180bba863.ttf:--font-funcs=ot --no-glyph-names:U+0606,U+06E1:[2=0@40,502+0|1=0+1000]
diff --git a/test/shaping/tests/mark-filtering-sets.tests b/test/shaping/tests/mark-filtering-sets.tests
new file mode 100644
index 0000000..7b5c910
--- /dev/null
+++ b/test/shaping/tests/mark-filtering-sets.tests
@@ -0,0 +1,5 @@
+fonts/sha1sum/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf::U+062A,U+062E,U+062A,U+0629:[glyph837=3@299,1170+0|uni06C1.1=3+502|glyph837=2@149,690+0|uni0628.8=2+532|glyph836=1@-51,1259+0|glyph514=1+196|glyph837=0@655,1751+0|glyph112=0@0,-358+905]
+fonts/sha1sum/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf::U+062A,U+062E,U+0646,U+0629:[glyph837=3@299,1170+0|uni06C1.1=3+502|glyph836=2@149,690+0|uni0628.8=2+532|glyph836=1@-51,1259+0|glyph514=1+196|glyph837=0@655,1751+0|glyph112=0@0,-358+905]
+fonts/sha1sum/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf::U+062A,U+062E,U+0626,U+0629:[glyph837=3@299,1170+0|uni06C1.1=3+502|glyph847=2@149,690+0|uni0628.8=2+532|glyph836=1@-51,1259+0|glyph514=1+196|glyph837=0@655,1751+0|glyph112=0@0,-358+905]
+fonts/sha1sum/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf::U+062A,U+062E,U+062B,U+0629:[glyph837=3@299,1520+0|uni06C1.1=3+502|glyph838=2@149,690+0|uni0628.8=2+532|glyph836=1@-51,1259+0|glyph514=1+196|glyph837=0@655,1751+0|glyph112=0@0,-358+905]
+fonts/sha1sum/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf::U+062A,U+062E,U+0679,U+0629:[glyph837=3@299,1520+0|uni06C1.1=3+502|glyph842=2@149,690+0|uni0628.8=2+532|glyph836=1@-51,1259+0|glyph514=1+196|glyph837=0@655,1751+0|glyph112=0@0,-358+905]