Bug 1211141 - Update to latest harfbuzz from upstream (release 1.0.5). r=jdaggett
authorJonathan Kew <jkew@mozilla.com>
Wed, 14 Oct 2015 16:00:36 +0100
changeset 267758 1540a81d3c0040562fad3969e134f2a96c4ae7fb
parent 267757 15104d2224f4d1c794994941e880d616cf9aa486
child 267759 c341ed5e63409a03a901daf9d5252ee0e57b9bdc
push id29530
push usercbook@mozilla.com
push dateThu, 15 Oct 2015 09:53:07 +0000
treeherdermozilla-central@e193b4da0a8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdaggett
bugs1211141
milestone44.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1211141 - Update to latest harfbuzz from upstream (release 1.0.5). r=jdaggett
gfx/harfbuzz/src/hb-blob.cc
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-face.cc
gfx/harfbuzz/src/hb-font-private.hh
gfx/harfbuzz/src/hb-font.cc
gfx/harfbuzz/src/hb-font.h
gfx/harfbuzz/src/hb-ft.cc
gfx/harfbuzz/src/hb-ft.h
gfx/harfbuzz/src/hb-graphite2.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-glyf-table.hh
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.cc
gfx/harfbuzz/src/hb-ot-maxp-table.hh
gfx/harfbuzz/src/hb-ot-name-table.hh
gfx/harfbuzz/src/hb-ot-shape-normalize.cc
gfx/harfbuzz/src/hb-ot-tag.cc
gfx/harfbuzz/src/hb-private.hh
gfx/harfbuzz/src/hb-set.h
gfx/harfbuzz/src/hb-shape-plan.cc
gfx/harfbuzz/src/hb-shape.cc
gfx/harfbuzz/src/hb-shaper.cc
gfx/harfbuzz/src/hb-unicode.cc
gfx/harfbuzz/src/hb-unicode.h
gfx/harfbuzz/src/hb-version.h
--- a/gfx/harfbuzz/src/hb-blob.cc
+++ b/gfx/harfbuzz/src/hb-blob.cc
@@ -86,17 +86,17 @@ static void
  * @destroy: Callback to call when @data is not needed anymore.
  *
  * Creates a new "blob" object wrapping @data.  The @mode parameter is used
  * to negotiate ownership and lifecycle of @data.
  *
  * Return value: New blob, or the empty blob if something failed or if @length is
  * zero.  Destroy with hb_blob_destroy().
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_blob_t *
 hb_blob_create (const char        *data,
 		unsigned int       length,
 		hb_memory_mode_t   mode,
 		void              *user_data,
 		hb_destroy_func_t  destroy)
 {
@@ -142,17 +142,17 @@ hb_blob_create (const char        *data,
  * is.
  *
  * Makes @parent immutable.
  *
  * Return value: New blob, or the empty blob if something failed or if
  * @length is zero or @offset is beyond the end of @parent's data.  Destroy
  * with hb_blob_destroy().
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_blob_t *
 hb_blob_create_sub_blob (hb_blob_t    *parent,
 			 unsigned int  offset,
 			 unsigned int  length)
 {
   hb_blob_t *blob;
 
@@ -174,17 +174,17 @@ hb_blob_create_sub_blob (hb_blob_t    *p
  * hb_blob_get_empty:
  *
  * Returns the singleton empty blob.
  *
  * See TODO:link object types for more information.
  *
  * Return value: (transfer full): the empty blob.
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_blob_t *
 hb_blob_get_empty (void)
 {
   static const hb_blob_t _hb_blob_nil = {
     HB_OBJECT_HEADER_STATIC,
 
     true, /* immutable */
@@ -205,17 +205,17 @@ hb_blob_get_empty (void)
  * @blob: a blob.
  *
  * Increases the reference count on @blob.
  *
  * See TODO:link object types for more information.
  *
  * Return value: @blob.
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_blob_t *
 hb_blob_reference (hb_blob_t *blob)
 {
   return hb_object_reference (blob);
 }
 
 /**
@@ -223,17 +223,17 @@ hb_blob_reference (hb_blob_t *blob)
  * @blob: a blob.
  *
  * Descreases the reference count on @blob, and if it reaches zero, destroys
  * @blob, freeing all memory, possibly calling the destroy-callback the blob
  * was created for if it has not been called already.
  *
  * See TODO:link object types for more information.
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_blob_destroy (hb_blob_t *blob)
 {
   if (!hb_object_destroy (blob)) return;
 
   _hb_blob_destroy_user_data (blob);
 
@@ -245,17 +245,17 @@ hb_blob_destroy (hb_blob_t *blob)
  * @blob: a blob.
  * @key: key for data to set.
  * @data: data to set.
  * @destroy: callback to call when @data is not needed anymore.
  * @replace: whether to replace an existing data with the same key.
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_blob_set_user_data (hb_blob_t          *blob,
 		       hb_user_data_key_t *key,
 		       void *              data,
 		       hb_destroy_func_t   destroy,
 		       hb_bool_t           replace)
 {
@@ -266,33 +266,33 @@ hb_blob_set_user_data (hb_blob_t        
  * hb_blob_get_user_data: (skip)
  * @blob: a blob.
  * @key: key for data to get.
  *
  * 
  *
  * Return value: (transfer none): 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void *
 hb_blob_get_user_data (hb_blob_t          *blob,
 		       hb_user_data_key_t *key)
 {
   return hb_object_get_user_data (blob, key);
 }
 
 
 /**
  * hb_blob_make_immutable:
  * @blob: a blob.
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_blob_make_immutable (hb_blob_t *blob)
 {
   if (hb_object_is_inert (blob))
     return;
 
   blob->immutable = true;
@@ -301,51 +301,51 @@ hb_blob_make_immutable (hb_blob_t *blob)
 /**
  * hb_blob_is_immutable:
  * @blob: a blob.
  *
  * 
  *
  * Return value: TODO
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_blob_is_immutable (hb_blob_t *blob)
 {
   return blob->immutable;
 }
 
 
 /**
  * hb_blob_get_length:
  * @blob: a blob.
  *
  * 
  *
  * Return value: the length of blob data in bytes.
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 unsigned int
 hb_blob_get_length (hb_blob_t *blob)
 {
   return blob->length;
 }
 
 /**
  * hb_blob_get_data:
  * @blob: a blob.
  * @length: (out):
  *
  * 
  *
  * Returns: (transfer none) (array length=length): 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 const char *
 hb_blob_get_data (hb_blob_t *blob, unsigned int *length)
 {
   if (length)
     *length = blob->length;
 
   return blob->data;
@@ -360,17 +360,17 @@ hb_blob_get_data (hb_blob_t *blob, unsig
  * return pointer to data.
  *
  * Fails if blob has been made immutable, or if memory allocation
  * fails.
  *
  * Returns: (transfer none) (array length=length): Writable blob data,
  * or %NULL if failed.
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 char *
 hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length)
 {
   if (!_try_writable (blob)) {
     if (length)
       *length = 0;
 
--- a/gfx/harfbuzz/src/hb-buffer-serialize.cc
+++ b/gfx/harfbuzz/src/hb-buffer-serialize.cc
@@ -35,51 +35,51 @@ static const char *serialize_formats[] =
 
 /**
  * hb_buffer_serialize_list_formats:
  *
  * 
  *
  * Return value: (transfer none):
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 const char **
 hb_buffer_serialize_list_formats (void)
 {
   return serialize_formats;
 }
 
 /**
  * hb_buffer_serialize_format_from_string:
  * @str: 
  * @len: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 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) & ~0x20202020u);
 }
 
 /**
  * hb_buffer_serialize_format_to_string:
  * @format: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 const char *
 hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format)
 {
   switch (format)
   {
     case HB_BUFFER_SERIALIZE_FORMAT_TEXT:	return serialize_formats[0];
     case HB_BUFFER_SERIALIZE_FORMAT_JSON:	return serialize_formats[1];
@@ -254,17 +254,17 @@ static unsigned int
  * @font: 
  * @format: 
  * @flags: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 unsigned int
 hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
 			    unsigned int start,
 			    unsigned int end,
 			    char *buf,
 			    unsigned int buf_size,
 			    unsigned int *buf_consumed, /* May be NULL */
@@ -361,17 +361,17 @@ parse_int (const char *pp, const char *e
  * @end_ptr: (out):
  * @font: 
  * @format: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
 			      const char *buf,
 			      int buf_len, /* -1 means nul-terminated */
 			      const char **end_ptr, /* May be NULL */
 			      hb_font_t *font, /* May be NULL */
 			      hb_buffer_serialize_format_t format)
--- a/gfx/harfbuzz/src/hb-buffer.cc
+++ b/gfx/harfbuzz/src/hb-buffer.cc
@@ -699,17 +699,17 @@ void hb_buffer_t::deallocate_var_all (vo
 
 /**
  * hb_buffer_create: (Xconstructor)
  *
  * 
  *
  * Return value: (transfer full)
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_buffer_t *
 hb_buffer_create (void)
 {
   hb_buffer_t *buffer;
 
   if (!(buffer = hb_object_create<hb_buffer_t> ()))
     return hb_buffer_get_empty ();
@@ -721,17 +721,17 @@ hb_buffer_create (void)
 
 /**
  * hb_buffer_get_empty:
  *
  * 
  *
  * Return value: (transfer full):
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 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),
@@ -754,31 +754,31 @@ hb_buffer_get_empty (void)
 /**
  * hb_buffer_reference: (skip)
  * @buffer: a buffer.
  *
  * 
  *
  * Return value: (transfer full):
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_buffer_t *
 hb_buffer_reference (hb_buffer_t *buffer)
 {
   return hb_object_reference (buffer);
 }
 
 /**
  * hb_buffer_destroy: (skip)
  * @buffer: a buffer.
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_buffer_destroy (hb_buffer_t *buffer)
 {
   if (!hb_object_destroy (buffer)) return;
 
   hb_unicode_funcs_destroy (buffer->unicode);
 
@@ -795,17 +795,17 @@ hb_buffer_destroy (hb_buffer_t *buffer)
  * @data: 
  * @destroy: 
  * @replace: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_buffer_set_user_data (hb_buffer_t        *buffer,
 			 hb_user_data_key_t *key,
 			 void *              data,
 			 hb_destroy_func_t   destroy,
 			 hb_bool_t           replace)
 {
@@ -816,17 +816,17 @@ hb_buffer_set_user_data (hb_buffer_t    
  * hb_buffer_get_user_data: (skip)
  * @buffer: a buffer.
  * @key: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void *
 hb_buffer_get_user_data (hb_buffer_t        *buffer,
 			 hb_user_data_key_t *key)
 {
   return hb_object_get_user_data (buffer, key);
 }
 
@@ -866,17 +866,17 @@ hb_buffer_get_content_type (hb_buffer_t 
 
 /**
  * hb_buffer_set_unicode_funcs:
  * @buffer: a buffer.
  * @unicode_funcs: 
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
 			     hb_unicode_funcs_t *unicode_funcs)
 {
   if (unlikely (hb_object_is_inert (buffer)))
     return;
 
@@ -892,32 +892,32 @@ hb_buffer_set_unicode_funcs (hb_buffer_t
 /**
  * hb_buffer_get_unicode_funcs:
  * @buffer: a buffer.
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_unicode_funcs_t *
 hb_buffer_get_unicode_funcs (hb_buffer_t        *buffer)
 {
   return buffer->unicode;
 }
 
 /**
  * hb_buffer_set_direction:
  * @buffer: a buffer.
  * @direction: 
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_buffer_set_direction (hb_buffer_t    *buffer,
 			 hb_direction_t  direction)
 
 {
   if (unlikely (hb_object_is_inert (buffer)))
     return;
@@ -928,32 +928,32 @@ hb_buffer_set_direction (hb_buffer_t    
 /**
  * hb_buffer_get_direction:
  * @buffer: a buffer.
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_direction_t
 hb_buffer_get_direction (hb_buffer_t    *buffer)
 {
   return buffer->props.direction;
 }
 
 /**
  * hb_buffer_set_script:
  * @buffer: a buffer.
  * @script: 
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_buffer_set_script (hb_buffer_t *buffer,
 		      hb_script_t  script)
 {
   if (unlikely (hb_object_is_inert (buffer)))
     return;
 
@@ -963,32 +963,32 @@ hb_buffer_set_script (hb_buffer_t *buffe
 /**
  * hb_buffer_get_script:
  * @buffer: a buffer.
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_script_t
 hb_buffer_get_script (hb_buffer_t *buffer)
 {
   return buffer->props.script;
 }
 
 /**
  * hb_buffer_set_language:
  * @buffer: a buffer.
  * @language: 
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_buffer_set_language (hb_buffer_t   *buffer,
 			hb_language_t  language)
 {
   if (unlikely (hb_object_is_inert (buffer)))
     return;
 
@@ -998,17 +998,17 @@ hb_buffer_set_language (hb_buffer_t   *b
 /**
  * hb_buffer_get_language:
  * @buffer: a buffer.
  *
  * 
  *
  * Return value: (transfer none):
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_language_t
 hb_buffer_get_language (hb_buffer_t *buffer)
 {
   return buffer->props.language;
 }
 
 /**
@@ -1155,17 +1155,17 @@ hb_buffer_get_replacement_codepoint (hb_
 
 
 /**
  * hb_buffer_reset:
  * @buffer: a buffer.
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_buffer_reset (hb_buffer_t *buffer)
 {
   buffer->reset ();
 }
 
 /**
@@ -1186,49 +1186,49 @@ hb_buffer_clear_contents (hb_buffer_t *b
  * hb_buffer_pre_allocate:
  * @buffer: a buffer.
  * @size: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size)
 {
   return buffer->ensure (size);
 }
 
 /**
  * hb_buffer_allocation_successful:
  * @buffer: a buffer.
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_buffer_allocation_successful (hb_buffer_t  *buffer)
 {
   return !buffer->in_error;
 }
 
 /**
  * hb_buffer_add:
  * @buffer: a buffer.
  * @codepoint: 
  * @cluster: 
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.7
  **/
 void
 hb_buffer_add (hb_buffer_t    *buffer,
 	       hb_codepoint_t  codepoint,
 	       unsigned int    cluster)
 {
   buffer->add (codepoint, cluster);
   buffer->clear_context (1);
@@ -1238,17 +1238,17 @@ hb_buffer_add (hb_buffer_t    *buffer,
  * hb_buffer_set_length:
  * @buffer: a buffer.
  * @length: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_buffer_set_length (hb_buffer_t  *buffer,
 		      unsigned int  length)
 {
   if (unlikely (hb_object_is_inert (buffer)))
     return length == 0;
 
@@ -1277,17 +1277,17 @@ hb_buffer_set_length (hb_buffer_t  *buff
 /**
  * hb_buffer_get_length:
  * @buffer: a buffer.
  *
  * Returns the number of items in the buffer.
  *
  * Return value: buffer length.
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 unsigned int
 hb_buffer_get_length (hb_buffer_t *buffer)
 {
   return buffer->len;
 }
 
 /**
@@ -1295,17 +1295,17 @@ hb_buffer_get_length (hb_buffer_t *buffe
  * @buffer: a buffer.
  * @length: (out): output array length.
  *
  * Returns buffer glyph information array.  Returned pointer
  * is valid as long as buffer contents are not modified.
  *
  * Return value: (transfer none) (array length=length): buffer glyph information array.
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_glyph_info_t *
 hb_buffer_get_glyph_infos (hb_buffer_t  *buffer,
                            unsigned int *length)
 {
   if (length)
     *length = buffer->len;
 
@@ -1317,17 +1317,17 @@ hb_buffer_get_glyph_infos (hb_buffer_t  
  * @buffer: a buffer.
  * @length: (out): output length.
  *
  * Returns buffer glyph position array.  Returned pointer
  * is valid as long as buffer contents are not modified.
  *
  * Return value: (transfer none) (array length=length): buffer glyph position array.
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_glyph_position_t *
 hb_buffer_get_glyph_positions (hb_buffer_t  *buffer,
                                unsigned int *length)
 {
   if (!buffer->have_positions)
     buffer->clear_positions ();
 
@@ -1338,50 +1338,50 @@ hb_buffer_get_glyph_positions (hb_buffer
 }
 
 /**
  * hb_buffer_reverse:
  * @buffer: a buffer.
  *
  * Reverses buffer contents.
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_buffer_reverse (hb_buffer_t *buffer)
 {
   buffer->reverse ();
 }
 
 /**
  * hb_buffer_reverse_range:
  * @buffer: a buffer.
  * @start: start index.
  * @end: end index.
  *
- * Reverses buffer contents between  start to end.
+ * Reverses buffer contents between start to end.
  *
- * Since: 1.0
+ * Since: 0.9.41
  **/
 void
 hb_buffer_reverse_range (hb_buffer_t *buffer,
 			 unsigned int start, unsigned int end)
 {
   buffer->reverse_range (start, end);
 }
 
 /**
  * hb_buffer_reverse_clusters:
  * @buffer: a buffer.
  *
  * Reverses buffer clusters.  That is, the buffer contents are
  * reversed, then each cluster (consecutive items having the
  * same cluster number) are reversed again.
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_buffer_reverse_clusters (hb_buffer_t *buffer)
 {
   buffer->reverse_clusters ();
 }
 
 /**
@@ -1488,17 +1488,17 @@ hb_buffer_add_utf (hb_buffer_t  *buffer,
  * @buffer: a buffer.
  * @text: (array length=text_length) (element-type uint8_t):
  * @text_length: 
  * @item_offset: 
  * @item_length: 
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_buffer_add_utf8 (hb_buffer_t  *buffer,
 		    const char   *text,
 		    int           text_length,
 		    unsigned int  item_offset,
 		    int           item_length)
 {
@@ -1510,17 +1510,17 @@ hb_buffer_add_utf8 (hb_buffer_t  *buffer
  * @buffer: a buffer.
  * @text: (array length=text_length):
  * @text_length: 
  * @item_offset: 
  * @item_length: 
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_buffer_add_utf16 (hb_buffer_t    *buffer,
 		     const uint16_t *text,
 		     int             text_length,
 		     unsigned int    item_offset,
 		     int             item_length)
 {
@@ -1532,17 +1532,17 @@ hb_buffer_add_utf16 (hb_buffer_t    *buf
  * @buffer: a buffer.
  * @text: (array length=text_length):
  * @text_length: 
  * @item_offset: 
  * @item_length: 
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_buffer_add_utf32 (hb_buffer_t    *buffer,
 		     const uint32_t *text,
 		     int             text_length,
 		     unsigned int    item_offset,
 		     int             item_length)
 {
--- a/gfx/harfbuzz/src/hb-buffer.h
+++ b/gfx/harfbuzz/src/hb-buffer.h
@@ -166,30 +166,36 @@ hb_buffer_set_segment_properties (hb_buf
 void
 hb_buffer_get_segment_properties (hb_buffer_t *buffer,
 				  hb_segment_properties_t *props);
 
 void
 hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
 
 
+/*
+ * Since: 0.9.20
+ */
 typedef enum { /*< flags >*/
   HB_BUFFER_FLAG_DEFAULT			= 0x00000000u,
   HB_BUFFER_FLAG_BOT				= 0x00000001u, /* Beginning-of-text */
   HB_BUFFER_FLAG_EOT				= 0x00000002u, /* End-of-text */
   HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES	= 0x00000004u
 } hb_buffer_flags_t;
 
 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);
 
+/*
+ * Since: 0.9.42
+ */
 typedef enum {
   HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES	= 0,
   HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS	= 1,
   HB_BUFFER_CLUSTER_LEVEL_CHARACTERS		= 2,
   HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES
 } hb_buffer_cluster_level_t;
 
 void
@@ -314,16 +320,19 @@ hb_buffer_get_glyph_positions (hb_buffer
 void
 hb_buffer_normalize_glyphs (hb_buffer_t *buffer);
 
 
 /*
  * Serialize
  */
 
+/*
+ * Since: 0.9.20
+ */
 typedef enum { /*< flags >*/
   HB_BUFFER_SERIALIZE_FLAG_DEFAULT		= 0x00000000u,
   HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS		= 0x00000001u,
   HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS		= 0x00000002u,
   HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES	= 0x00000004u,
   HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS	= 0x00000008u
 } hb_buffer_serialize_flags_t;
 
--- a/gfx/harfbuzz/src/hb-common.cc
+++ b/gfx/harfbuzz/src/hb-common.cc
@@ -59,17 +59,17 @@ void
  * hb_tag_from_string:
  * @str: (array length=len) (element-type uint8_t): 
  * @len: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_tag_t
 hb_tag_from_string (const char *str, int len)
 {
   char tag[4];
   unsigned int i;
 
   if (!str || !len || !*str)
@@ -117,17 +117,17 @@ const char direction_strings[][4] = {
  * hb_direction_from_string:
  * @str: (array length=len) (element-type uint8_t): 
  * @len: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_direction_t
 hb_direction_from_string (const char *str, int len)
 {
   if (unlikely (!str || !len || !*str))
     return HB_DIRECTION_INVALID;
 
   /* Lets match loosely: just match the first letter, such that
@@ -144,17 +144,17 @@ hb_direction_from_string (const char *st
 /**
  * hb_direction_to_string:
  * @direction: 
  *
  * 
  *
  * Return value: (transfer none): 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 const char *
 hb_direction_to_string (hb_direction_t direction)
 {
   if (likely ((unsigned int) (direction - HB_DIRECTION_LTR)
 	      < ARRAY_LENGTH (direction_strings)))
     return direction_strings[direction - HB_DIRECTION_LTR];
 
@@ -283,65 +283,65 @@ retry:
  * hb_language_from_string:
  * @str: (array length=len) (element-type uint8_t): 
  * @len: 
  *
  * 
  *
  * Return value: (transfer none):
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_language_t
 hb_language_from_string (const char *str, int len)
 {
-  char strbuf[64];
-
   if (!str || !len || !*str)
     return HB_LANGUAGE_INVALID;
 
+  hb_language_item_t *item = NULL;
   if (len >= 0)
   {
     /* NUL-terminate it. */
+    char strbuf[64];
     len = MIN (len, (int) sizeof (strbuf) - 1);
     memcpy (strbuf, str, len);
     strbuf[len] = '\0';
-    str = strbuf;
+    item = lang_find_or_insert (strbuf);
   }
-
-  hb_language_item_t *item = lang_find_or_insert (str);
+  else
+    item = lang_find_or_insert (str);
 
   return likely (item) ? item->lang : HB_LANGUAGE_INVALID;
 }
 
 /**
  * hb_language_to_string:
  * @language: 
  *
  * 
  *
  * Return value: (transfer none): 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 const char *
 hb_language_to_string (hb_language_t language)
 {
   /* This is actually NULL-safe! */
   return language->s;
 }
 
 /**
  * hb_language_get_default:
  *
  * 
  *
  * Return value: (transfer none):
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_language_t
 hb_language_get_default (void)
 {
   static hb_language_t default_language = HB_LANGUAGE_INVALID;
 
   hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language);
   if (unlikely (language == HB_LANGUAGE_INVALID)) {
@@ -358,17 +358,17 @@ hb_language_get_default (void)
 /**
  * hb_script_from_iso15924_tag:
  * @tag: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 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) */
@@ -403,49 +403,49 @@ hb_script_from_iso15924_tag (hb_tag_t ta
  * hb_script_from_string:
  * @s: (array length=len) (element-type uint8_t): 
  * @len: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_script_t
 hb_script_from_string (const char *s, int len)
 {
   return hb_script_from_iso15924_tag (hb_tag_from_string (s, len));
 }
 
 /**
  * hb_script_to_iso15924_tag:
  * @script: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_tag_t
 hb_script_to_iso15924_tag (hb_script_t script)
 {
   return (hb_tag_t) script;
 }
 
 /**
  * hb_script_get_horizontal_direction:
  * @script: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_direction_t
 hb_script_get_horizontal_direction (hb_script_t script)
 {
   /* http://goo.gl/x9ilM */
   switch ((hb_tag_t) script)
   {
     /* Unicode-1.1 additions */
@@ -540,17 +540,17 @@ hb_user_data_array_t::get (hb_user_data_
 /**
  * hb_version:
  * @major: (out): Library major version component.
  * @minor: (out): Library minor version component.
  * @micro: (out): Library micro version component.
  *
  * Returns library version as three integer components.
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_version (unsigned int *major,
 	    unsigned int *minor,
 	    unsigned int *micro)
 {
   *major = HB_VERSION_MAJOR;
   *minor = HB_VERSION_MINOR;
@@ -559,17 +559,17 @@ hb_version (unsigned int *major,
 
 /**
  * hb_version_string:
  *
  * Returns library version as a string with three components.
  *
  * Return value: library version string.
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 const char *
 hb_version_string (void)
 {
   return HB_VERSION_STRING;
 }
 
 /**
--- a/gfx/harfbuzz/src/hb-common.h
+++ b/gfx/harfbuzz/src/hb-common.h
@@ -267,16 +267,19 @@ 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'),
 
+  /*
+   * Since: 0.9.30
+   */
   /*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'),
--- a/gfx/harfbuzz/src/hb-coretext.cc
+++ b/gfx/harfbuzz/src/hb-coretext.cc
@@ -120,16 +120,19 @@ hb_coretext_shaper_face_data_t *
 }
 
 void
 _hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
 {
   CFRelease (data);
 }
 
+/*
+ * Since: 0.9.10
+ */
 CGFontRef
 hb_coretext_face_get_cg_font (hb_face_t *face)
 {
   if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL;
   hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
   return face_data;
 }
 
--- a/gfx/harfbuzz/src/hb-face.cc
+++ b/gfx/harfbuzz/src/hb-face.cc
@@ -72,17 +72,17 @@ const hb_face_t _hb_face_nil = {
  * @reference_table_func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data: 
  * @destroy: 
  *
  * 
  *
  * Return value: (transfer full)
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_face_t *
 hb_face_create_for_tables (hb_reference_table_func_t  reference_table_func,
 			   void                      *user_data,
 			   hb_destroy_func_t          destroy)
 {
   hb_face_t *face;
 
@@ -108,17 +108,17 @@ typedef struct hb_face_for_data_closure_
   unsigned int  index;
 } hb_face_for_data_closure_t;
 
 static hb_face_for_data_closure_t *
 _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
 {
   hb_face_for_data_closure_t *closure;
 
-  closure = (hb_face_for_data_closure_t *) malloc (sizeof (hb_face_for_data_closure_t));
+  closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t));
   if (unlikely (!closure))
     return NULL;
 
   closure->blob = blob;
   closure->index = index;
 
   return closure;
 }
@@ -152,17 +152,17 @@ static hb_blob_t *
  * hb_face_create: (Xconstructor)
  * @blob: 
  * @index: 
  *
  * 
  *
  * Return value: (transfer full):
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_face_t *
 hb_face_create (hb_blob_t    *blob,
 		unsigned int  index)
 {
   hb_face_t *face;
 
   if (unlikely (!blob))
@@ -184,48 +184,48 @@ hb_face_create (hb_blob_t    *blob,
 
 /**
  * hb_face_get_empty:
  *
  * 
  *
  * Return value: (transfer full)
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_face_t *
 hb_face_get_empty (void)
 {
   return const_cast<hb_face_t *> (&_hb_face_nil);
 }
 
 
 /**
  * hb_face_reference: (skip)
  * @face: a face.
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_face_t *
 hb_face_reference (hb_face_t *face)
 {
   return hb_object_reference (face);
 }
 
 /**
  * hb_face_destroy: (skip)
  * @face: a face.
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_face_destroy (hb_face_t *face)
 {
   if (!hb_object_destroy (face)) return;
 
   for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
   {
@@ -252,17 +252,17 @@ hb_face_destroy (hb_face_t *face)
  * @data: 
  * @destroy: 
  * @replace: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_face_set_user_data (hb_face_t          *face,
 		       hb_user_data_key_t *key,
 		       void *              data,
 		       hb_destroy_func_t   destroy,
 		       hb_bool_t           replace)
 {
@@ -273,32 +273,32 @@ hb_face_set_user_data (hb_face_t        
  * hb_face_get_user_data: (skip)
  * @face: a face.
  * @key: 
  *
  * 
  *
  * Return value: (transfer none):
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void *
 hb_face_get_user_data (hb_face_t          *face,
 		       hb_user_data_key_t *key)
 {
   return hb_object_get_user_data (face, key);
 }
 
 /**
  * hb_face_make_immutable:
  * @face: a face.
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_face_make_immutable (hb_face_t *face)
 {
   if (unlikely (hb_object_is_inert (face)))
     return;
 
   face->immutable = true;
@@ -307,17 +307,17 @@ hb_face_make_immutable (hb_face_t *face)
 /**
  * hb_face_is_immutable:
  * @face: a face.
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_face_is_immutable (hb_face_t *face)
 {
   return face->immutable;
 }
 
 
@@ -325,17 +325,17 @@ hb_face_is_immutable (hb_face_t *face)
  * hb_face_reference_table:
  * @face: a face.
  * @tag: 
  *
  * 
  *
  * Return value: (transfer full):
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_blob_t *
 hb_face_reference_table (hb_face_t *face,
 			 hb_tag_t   tag)
 {
   return face->reference_table (tag);
 }
 
@@ -412,17 +412,17 @@ hb_face_set_upem (hb_face_t    *face,
 /**
  * hb_face_get_upem:
  * @face: a face.
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 unsigned int
 hb_face_get_upem (hb_face_t *face)
 {
   return face->get_upem ();
 }
 
 void
--- a/gfx/harfbuzz/src/hb-font-private.hh
+++ b/gfx/harfbuzz/src/hb-font-private.hh
@@ -263,17 +263,17 @@ struct hb_font_t {
   }
 
   /* Internal only */
   inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
 					     hb_position_t *x, hb_position_t *y)
   {
     *x = get_glyph_h_advance (glyph) / 2;
 
-    /* TODO use font_metics.ascent */
+    /* TODO use font_metrics.ascent */
     *y = y_scale;
   }
 
   inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
 					      hb_direction_t direction,
 					      hb_position_t *x, hb_position_t *y)
   {
     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
--- a/gfx/harfbuzz/src/hb-font.cc
+++ b/gfx/harfbuzz/src/hb-font.cc
@@ -231,17 +231,17 @@ static const hb_font_funcs_t _hb_font_fu
 
 /**
  * hb_font_funcs_create: (Xconstructor)
  *
  * 
  *
  * Return value: (transfer full): 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_font_funcs_t *
 hb_font_funcs_create (void)
 {
   hb_font_funcs_t *ffuncs;
 
   if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
     return hb_font_funcs_get_empty ();
@@ -253,47 +253,47 @@ hb_font_funcs_create (void)
 
 /**
  * hb_font_funcs_get_empty:
  *
  * 
  *
  * Return value: (transfer full): 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_font_funcs_t *
 hb_font_funcs_get_empty (void)
 {
   return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil);
 }
 
 /**
  * hb_font_funcs_reference: (skip)
  * @ffuncs: font functions.
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_font_funcs_t *
 hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
 {
   return hb_object_reference (ffuncs);
 }
 
 /**
  * hb_font_funcs_destroy: (skip)
  * @ffuncs: font functions.
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
 {
   if (!hb_object_destroy (ffuncs)) return;
 
 #define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) \
   ffuncs->destroy.name (ffuncs->user_data.name);
@@ -310,17 +310,17 @@ hb_font_funcs_destroy (hb_font_funcs_t *
  * @data: 
  * @destroy: 
  * @replace: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_funcs_set_user_data (hb_font_funcs_t    *ffuncs,
 			     hb_user_data_key_t *key,
 			     void *              data,
 			     hb_destroy_func_t   destroy,
 			     hb_bool_t           replace)
 {
@@ -331,33 +331,33 @@ hb_font_funcs_set_user_data (hb_font_fun
  * hb_font_funcs_get_user_data: (skip)
  * @ffuncs: font functions.
  * @key: 
  *
  * 
  *
  * Return value: (transfer none): 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void *
 hb_font_funcs_get_user_data (hb_font_funcs_t    *ffuncs,
 			     hb_user_data_key_t *key)
 {
   return hb_object_get_user_data (ffuncs, key);
 }
 
 
 /**
  * hb_font_funcs_make_immutable:
  * @ffuncs: font functions.
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
 {
   if (unlikely (hb_object_is_inert (ffuncs)))
     return;
 
   ffuncs->immutable = true;
@@ -366,17 +366,17 @@ hb_font_funcs_make_immutable (hb_font_fu
 /**
  * hb_font_funcs_is_immutable:
  * @ffuncs: font functions.
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
 {
   return ffuncs->immutable;
 }
 
 
@@ -420,17 +420,17 @@ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
  * @unicode: 
  * @variation_selector: 
  * @glyph: (out): 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_get_glyph (hb_font_t *font,
 		   hb_codepoint_t unicode, hb_codepoint_t variation_selector,
 		   hb_codepoint_t *glyph)
 {
   return font->get_glyph (unicode, variation_selector, glyph);
 }
@@ -439,17 +439,17 @@ hb_font_get_glyph (hb_font_t *font,
  * hb_font_get_glyph_h_advance:
  * @font: a font.
  * @glyph: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_position_t
 hb_font_get_glyph_h_advance (hb_font_t *font,
 			     hb_codepoint_t glyph)
 {
   return font->get_glyph_h_advance (glyph);
 }
 
@@ -457,17 +457,17 @@ hb_font_get_glyph_h_advance (hb_font_t *
  * hb_font_get_glyph_v_advance:
  * @font: a font.
  * @glyph: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_position_t
 hb_font_get_glyph_v_advance (hb_font_t *font,
 			     hb_codepoint_t glyph)
 {
   return font->get_glyph_v_advance (glyph);
 }
 
@@ -477,17 +477,17 @@ hb_font_get_glyph_v_advance (hb_font_t *
  * @glyph: 
  * @x: (out): 
  * @y: (out): 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_get_glyph_h_origin (hb_font_t *font,
 			    hb_codepoint_t glyph,
 			    hb_position_t *x, hb_position_t *y)
 {
   return font->get_glyph_h_origin (glyph, x, y);
 }
@@ -498,17 +498,17 @@ hb_font_get_glyph_h_origin (hb_font_t *f
  * @glyph: 
  * @x: (out): 
  * @y: (out): 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_get_glyph_v_origin (hb_font_t *font,
 			    hb_codepoint_t glyph,
 			    hb_position_t *x, hb_position_t *y)
 {
   return font->get_glyph_v_origin (glyph, x, y);
 }
@@ -518,17 +518,17 @@ hb_font_get_glyph_v_origin (hb_font_t *f
  * @font: a font.
  * @left_glyph: 
  * @right_glyph: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_position_t
 hb_font_get_glyph_h_kerning (hb_font_t *font,
 			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
 {
   return font->get_glyph_h_kerning (left_glyph, right_glyph);
 }
 
@@ -537,17 +537,17 @@ hb_font_get_glyph_h_kerning (hb_font_t *
  * @font: a font.
  * @top_glyph: 
  * @bottom_glyph: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_position_t
 hb_font_get_glyph_v_kerning (hb_font_t *font,
 			     hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
 {
   return font->get_glyph_v_kerning (top_glyph, bottom_glyph);
 }
 
@@ -556,17 +556,17 @@ hb_font_get_glyph_v_kerning (hb_font_t *
  * @font: a font.
  * @glyph: 
  * @extents: (out): 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_get_glyph_extents (hb_font_t *font,
 			   hb_codepoint_t glyph,
 			   hb_glyph_extents_t *extents)
 {
   return font->get_glyph_extents (glyph, extents);
 }
@@ -578,17 +578,17 @@ hb_font_get_glyph_extents (hb_font_t *fo
  * @point_index: 
  * @x: (out): 
  * @y: (out): 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_get_glyph_contour_point (hb_font_t *font,
 				 hb_codepoint_t glyph, unsigned int point_index,
 				 hb_position_t *x, hb_position_t *y)
 {
   return font->get_glyph_contour_point (glyph, point_index, x, y);
 }
@@ -643,17 +643,17 @@ hb_font_get_glyph_from_name (hb_font_t *
  * @font: a font.
  * @glyph: 
  * @direction: 
  * @x: (out): 
  * @y: (out): 
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_get_glyph_advance_for_direction (hb_font_t *font,
 					 hb_codepoint_t glyph,
 					 hb_direction_t direction,
 					 hb_position_t *x, hb_position_t *y)
 {
   return font->get_glyph_advance_for_direction (glyph, direction, x, y);
@@ -664,17 +664,17 @@ hb_font_get_glyph_advance_for_direction 
  * @font: a font.
  * @glyph: 
  * @direction: 
  * @x: (out): 
  * @y: (out): 
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_get_glyph_origin_for_direction (hb_font_t *font,
 					hb_codepoint_t glyph,
 					hb_direction_t direction,
 					hb_position_t *x, hb_position_t *y)
 {
   return font->get_glyph_origin_for_direction (glyph, direction, x, y);
@@ -685,17 +685,17 @@ hb_font_get_glyph_origin_for_direction (
  * @font: a font.
  * @glyph: 
  * @direction: 
  * @x: (out): 
  * @y: (out): 
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_add_glyph_origin_for_direction (hb_font_t *font,
 					hb_codepoint_t glyph,
 					hb_direction_t direction,
 					hb_position_t *x, hb_position_t *y)
 {
   return font->add_glyph_origin_for_direction (glyph, direction, x, y);
@@ -706,17 +706,17 @@ hb_font_add_glyph_origin_for_direction (
  * @font: a font.
  * @glyph: 
  * @direction: 
  * @x: (out): 
  * @y: (out): 
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
 					     hb_codepoint_t glyph,
 					     hb_direction_t direction,
 					     hb_position_t *x, hb_position_t *y)
 {
   return font->subtract_glyph_origin_for_direction (glyph, direction, x, y);
@@ -728,17 +728,17 @@ hb_font_subtract_glyph_origin_for_direct
  * @first_glyph: 
  * @second_glyph: 
  * @direction: 
  * @x: (out): 
  * @y: (out): 
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
 					 hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
 					 hb_direction_t direction,
 					 hb_position_t *x, hb_position_t *y)
 {
   return font->get_glyph_kerning_for_direction (first_glyph, second_glyph, direction, x, y);
@@ -750,17 +750,17 @@ hb_font_get_glyph_kerning_for_direction 
  * @glyph: 
  * @direction: 
  * @extents: (out): 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_get_glyph_extents_for_origin (hb_font_t *font,
 				      hb_codepoint_t glyph,
 				      hb_direction_t direction,
 				      hb_glyph_extents_t *extents)
 {
   return font->get_glyph_extents_for_origin (glyph, direction, extents);
@@ -774,17 +774,17 @@ hb_font_get_glyph_extents_for_origin (hb
  * @direction: 
  * @x: (out): 
  * @y: (out): 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
 					    hb_codepoint_t glyph, unsigned int point_index,
 					    hb_direction_t direction,
 					    hb_position_t *x, hb_position_t *y)
 {
   return font->get_glyph_contour_point_for_origin (glyph, point_index, direction, x, y);
@@ -840,57 +840,58 @@ hb_font_glyph_from_string (hb_font_t *fo
 /**
  * hb_font_create: (Xconstructor)
  * @face: a face.
  *
  * 
  *
  * Return value: (transfer full): 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_font_t *
 hb_font_create (hb_face_t *face)
 {
   hb_font_t *font;
 
   if (unlikely (!face))
     face = hb_face_get_empty ();
   if (!(font = hb_object_create<hb_font_t> ()))
     return hb_font_get_empty ();
 
   hb_face_make_immutable (face);
   font->face = hb_face_reference (face);
   font->klass = hb_font_funcs_get_empty ();
 
+  font->x_scale = font->y_scale = hb_face_get_upem (face);
+
   return font;
 }
 
 /**
  * hb_font_create_sub_font:
  * @parent: parent font.
  *
  * 
  *
  * Return value: (transfer full): 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_font_t *
 hb_font_create_sub_font (hb_font_t *parent)
 {
   if (unlikely (!parent))
     parent = hb_font_get_empty ();
 
   hb_font_t *font = hb_font_create (parent->face);
 
   if (unlikely (hb_object_is_inert (font)))
     return font;
 
-  hb_font_make_immutable (parent);
   font->parent = hb_font_reference (parent);
 
   font->x_scale = parent->x_scale;
   font->y_scale = parent->y_scale;
   font->x_ppem = parent->x_ppem;
   font->y_ppem = parent->y_ppem;
 
   return font;
@@ -898,17 +899,17 @@ hb_font_create_sub_font (hb_font_t *pare
 
 /**
  * hb_font_get_empty:
  *
  * 
  *
  * Return value: (transfer full)
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_font_t *
 hb_font_get_empty (void)
 {
   static const hb_font_t _hb_font_nil = {
     HB_OBJECT_HEADER_STATIC,
 
     true, /* immutable */
@@ -939,31 +940,31 @@ hb_font_get_empty (void)
 /**
  * hb_font_reference: (skip)
  * @font: a font.
  *
  * 
  *
  * Return value: (transfer full): 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_font_t *
 hb_font_reference (hb_font_t *font)
 {
   return hb_object_reference (font);
 }
 
 /**
  * hb_font_destroy: (skip)
  * @font: a font.
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_destroy (hb_font_t *font)
 {
   if (!hb_object_destroy (font)) return;
 
 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, font);
 #include "hb-shaper-list.hh"
@@ -986,17 +987,17 @@ hb_font_destroy (hb_font_t *font)
  * @data: 
  * @destroy: 
  * @replace: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_set_user_data (hb_font_t          *font,
 		       hb_user_data_key_t *key,
 		       void *              data,
 		       hb_destroy_func_t   destroy,
 		       hb_bool_t           replace)
 {
@@ -1007,67 +1008,96 @@ hb_font_set_user_data (hb_font_t        
  * hb_font_get_user_data: (skip)
  * @font: a font.
  * @key: 
  *
  * 
  *
  * Return value: (transfer none): 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void *
 hb_font_get_user_data (hb_font_t          *font,
 		       hb_user_data_key_t *key)
 {
   return hb_object_get_user_data (font, key);
 }
 
 /**
  * hb_font_make_immutable:
  * @font: a font.
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_make_immutable (hb_font_t *font)
 {
   if (unlikely (hb_object_is_inert (font)))
     return;
 
+  if (font->parent)
+    hb_font_make_immutable (font->parent);
+
   font->immutable = true;
 }
 
 /**
  * hb_font_is_immutable:
  * @font: a font.
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_font_is_immutable (hb_font_t *font)
 {
   return font->immutable;
 }
 
 /**
+ * hb_font_set_parent:
+ * @font: a font.
+ * @parent: new parent.
+ *
+ * Sets parent font of @font.
+ *
+ * Since: 1.0.5
+ **/
+void
+hb_font_set_parent (hb_font_t *font,
+		    hb_font_t *parent)
+{
+  if (font->immutable)
+    return;
+
+  if (!parent)
+    parent = hb_font_get_empty ();
+
+  hb_font_t *old = font->parent;
+
+  font->parent = hb_font_reference (parent);
+
+  hb_font_destroy (old);
+}
+
+/**
  * hb_font_get_parent:
  * @font: a font.
  *
  * 
  *
  * Return value: (transfer none): 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_font_t *
 hb_font_get_parent (hb_font_t *font)
 {
   return font->parent;
 }
 
 /**
@@ -1156,17 +1186,17 @@ hb_font_set_funcs_data (hb_font_t       
 /**
  * hb_font_set_scale:
  * @font: a font.
  * @x_scale: 
  * @y_scale: 
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_set_scale (hb_font_t *font,
 		   int x_scale,
 		   int y_scale)
 {
   if (font->immutable)
     return;
@@ -1178,17 +1208,17 @@ hb_font_set_scale (hb_font_t *font,
 /**
  * hb_font_get_scale:
  * @font: a font.
  * @x_scale: (out): 
  * @y_scale: (out): 
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_get_scale (hb_font_t *font,
 		   int *x_scale,
 		   int *y_scale)
 {
   if (x_scale) *x_scale = font->x_scale;
   if (y_scale) *y_scale = font->y_scale;
@@ -1197,17 +1227,17 @@ hb_font_get_scale (hb_font_t *font,
 /**
  * hb_font_set_ppem:
  * @font: a font.
  * @x_ppem: 
  * @y_ppem: 
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_set_ppem (hb_font_t *font,
 		  unsigned int x_ppem,
 		  unsigned int y_ppem)
 {
   if (font->immutable)
     return;
@@ -1219,17 +1249,17 @@ hb_font_set_ppem (hb_font_t *font,
 /**
  * hb_font_get_ppem:
  * @font: a font.
  * @x_ppem: (out): 
  * @y_ppem: (out): 
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_get_ppem (hb_font_t *font,
 		  unsigned int *x_ppem,
 		  unsigned int *y_ppem)
 {
   if (x_ppem) *x_ppem = font->x_ppem;
   if (y_ppem) *y_ppem = font->y_ppem;
--- a/gfx/harfbuzz/src/hb-font.h
+++ b/gfx/harfbuzz/src/hb-font.h
@@ -144,145 +144,145 @@ typedef hb_bool_t (*hb_font_get_glyph_fr
  * hb_font_funcs_set_glyph_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 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_glyph_h_advance_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs,
 					hb_font_get_glyph_h_advance_func_t func,
 					void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_v_advance_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs,
 					hb_font_get_glyph_v_advance_func_t func,
 					void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_h_origin_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs,
 				       hb_font_get_glyph_h_origin_func_t func,
 				       void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_v_origin_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs,
 				       hb_font_get_glyph_v_origin_func_t func,
 				       void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_h_kerning_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
 					hb_font_get_glyph_h_kerning_func_t func,
 					void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_v_kerning_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs,
 					hb_font_get_glyph_v_kerning_func_t func,
 					void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_extents_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs,
 				      hb_font_get_glyph_extents_func_t func,
 				      void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_contour_point_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs,
 					    hb_font_get_glyph_contour_point_func_t func,
 					    void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_name_func:
@@ -454,16 +454,20 @@ hb_font_get_user_data (hb_font_t        
 		       hb_user_data_key_t *key);
 
 void
 hb_font_make_immutable (hb_font_t *font);
 
 hb_bool_t
 hb_font_is_immutable (hb_font_t *font);
 
+void
+hb_font_set_parent (hb_font_t *font,
+		    hb_font_t *parent);
+
 hb_font_t *
 hb_font_get_parent (hb_font_t *font);
 
 hb_face_t *
 hb_font_get_face (hb_font_t *font);
 
 
 void
--- a/gfx/harfbuzz/src/hb-ft.cc
+++ b/gfx/harfbuzz/src/hb-ft.cc
@@ -1,11 +1,12 @@
 /*
  * Copyright © 2009  Red Hat, Inc.
  * Copyright © 2009  Keith Stribley
+ * Copyright © 2015  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.
@@ -18,16 +19,17 @@
  *
  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
  */
 
 #include "hb-private.hh"
 
 #include "hb-ft.h"
 
 #include "hb-font-private.hh"
 
@@ -41,90 +43,174 @@
 #endif
 
 
 /* TODO:
  *
  * In general, this file does a fine job of what it's supposed to do.
  * There are, however, things that need more work:
  *
- *   - We don't handle any load_flags.  That definitely has API implications. :(
- *     I believe hb_ft_font_create() should take load_flags input.
- *     In particular, FT_Get_Advance() without the NO_HINTING flag seems to be
- *     buggy.
+ *   - I remember seeing FT_Get_Advance() without the NO_HINTING flag to be buggy.
+ *     Have not investigated.
  *
- *     FreeType works in 26.6 mode.  Clients can decide to use that mode, and everything
+ *   - FreeType works in 26.6 mode.  Clients can decide to use that mode, and everything
  *     would work fine.  However, we also abuse this API for performing in font-space,
  *     but don't pass the correct flags to FreeType.  We just abuse the no-hinting mode
  *     for that, such that no rounding etc happens.  As such, we don't set ppem, and
- *     pass NO_HINTING around.  This seems to work best, until we go ahead and add a full
- *     load_flags API.
+ *     pass NO_HINTING as load_flags.  Would be much better to use NO_SCALE, and scale
+ *     ourselves, like we do in uniscribe, etc.
  *
  *   - We don't handle / allow for emboldening / obliqueing.
  *
  *   - In the future, we should add constructors to create fonts in font space?
  *
  *   - FT_Load_Glyph() is exteremely costly.  Do something about it?
  */
 
 
+struct hb_ft_font_t
+{
+  FT_Face ft_face;
+  int load_flags;
+  bool unref; /* Whether to destroy ft_face when done. */
+};
+
+static hb_ft_font_t *
+_hb_ft_font_create (FT_Face ft_face, bool unref)
+{
+  hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t));
+
+  if (unlikely (!ft_font))
+    return NULL;
+
+  ft_font->ft_face = ft_face;
+  ft_font->unref = unref;
+
+  ft_font->load_flags = FT_LOAD_DEFAULT;
+
+  return ft_font;
+}
+
+static void
+_hb_ft_font_destroy (hb_ft_font_t *ft_font)
+{
+  if (ft_font->unref)
+    FT_Done_Face (ft_font->ft_face);
+
+  free (ft_font);
+}
+
+/**
+ * hb_ft_font_set_load_flags:
+ * @font:
+ * @load_flags:
+ *
+ * 
+ *
+ * Since: 1.0.5
+ **/
+void
+hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
+{
+  if (font->immutable)
+    return;
+
+  if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
+    return;
+
+  hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
+
+  ft_font->load_flags = load_flags;
+}
+
+/**
+ * hb_ft_font_get_load_flags:
+ * @font:
+ *
+ * 
+ *
+ * Return value:
+ * Since: 1.0.5
+ **/
+int
+hb_ft_font_get_load_flags (hb_font_t *font)
+{
+  if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
+    return 0;
+
+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
+
+  return ft_font->load_flags;
+}
+
+FT_Face
+hb_ft_font_get_face (hb_font_t *font)
+{
+  if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
+    return NULL;
+
+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
+
+  return ft_font->ft_face;
+}
+
+
+
 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)
 
 {
+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
   unsigned int g;
-  FT_Face ft_face = (FT_Face) font_data;
 
   if (likely (!variation_selector))
-    g = FT_Get_Char_Index (ft_face, unicode);
+    g = FT_Get_Char_Index (ft_font->ft_face, unicode);
   else
-    g = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector);
+    g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector);
 
   if (unlikely (!g))
     return false;
 
   *glyph = g;
   return true;
 }
 
 static hb_position_t
 hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
 			   void *font_data,
 			   hb_codepoint_t glyph,
 			   void *user_data HB_UNUSED)
 {
-  FT_Face ft_face = (FT_Face) font_data;
-  int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
   FT_Fixed v;
 
-  if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v)))
+  if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags, &v)))
     return 0;
 
   if (font->x_scale < 0)
     v = -v;
 
   return (v + (1<<9)) >> 10;
 }
 
 static hb_position_t
 hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
 			   void *font_data,
 			   hb_codepoint_t glyph,
 			   void *user_data HB_UNUSED)
 {
-  FT_Face ft_face = (FT_Face) font_data;
-  int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING | FT_LOAD_VERTICAL_LAYOUT;
+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
   FT_Fixed v;
 
-  if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v)))
+  if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v)))
     return 0;
 
   if (font->y_scale < 0)
     v = -v;
 
   /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
    * have a Y growing upward.  Hence the extra negation. */
   return (-v + (1<<9)) >> 10;
@@ -145,20 +231,20 @@ hb_ft_get_glyph_h_origin (hb_font_t *fon
 static hb_bool_t
 hb_ft_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)
 {
-  FT_Face ft_face = (FT_Face) font_data;
-  int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  FT_Face ft_face = ft_font->ft_face;
 
-  if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
+  if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
     return false;
 
   /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
    * have a Y growing upward.  Hence the extra negation. */
   *x = ft_face->glyph->metrics.horiBearingX -   ft_face->glyph->metrics.vertBearingX;
   *y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY);
 
   if (font->x_scale < 0)
@@ -171,21 +257,21 @@ hb_ft_get_glyph_v_origin (hb_font_t *fon
 
 static hb_position_t
 hb_ft_get_glyph_h_kerning (hb_font_t *font,
 			   void *font_data,
 			   hb_codepoint_t left_glyph,
 			   hb_codepoint_t right_glyph,
 			   void *user_data HB_UNUSED)
 {
-  FT_Face ft_face = (FT_Face) font_data;
+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
   FT_Vector kerningv;
 
   FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED;
-  if (FT_Get_Kerning (ft_face, left_glyph, right_glyph, mode, &kerningv))
+  if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv))
     return 0;
 
   return kerningv.x;
 }
 
 static hb_position_t
 hb_ft_get_glyph_v_kerning (hb_font_t *font HB_UNUSED,
 			   void *font_data HB_UNUSED,
@@ -199,20 +285,20 @@ hb_ft_get_glyph_v_kerning (hb_font_t *fo
 
 static hb_bool_t
 hb_ft_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)
 {
-  FT_Face ft_face = (FT_Face) font_data;
-  int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  FT_Face ft_face = ft_font->ft_face;
 
-  if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
+  if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
     return false;
 
   extents->x_bearing = ft_face->glyph->metrics.horiBearingX;
   extents->y_bearing = ft_face->glyph->metrics.horiBearingY;
   extents->width = ft_face->glyph->metrics.width;
   extents->height = -ft_face->glyph->metrics.height;
   return true;
 }
@@ -221,20 +307,20 @@ static hb_bool_t
 hb_ft_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)
 {
-  FT_Face ft_face = (FT_Face) font_data;
-  int load_flags = FT_LOAD_DEFAULT;
+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  FT_Face ft_face = ft_font->ft_face;
 
-  if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
+  if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
       return false;
 
   if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE))
       return false;
 
   if (unlikely (point_index >= (unsigned int) ft_face->glyph->outline.n_points))
       return false;
 
@@ -246,33 +332,34 @@ hb_ft_get_glyph_contour_point (hb_font_t
 
 static hb_bool_t
 hb_ft_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)
 {
-  FT_Face ft_face = (FT_Face) font_data;
+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
 
-  hb_bool_t ret = !FT_Get_Glyph_Name (ft_face, glyph, name, size);
+  hb_bool_t ret = !FT_Get_Glyph_Name (ft_font->ft_face, glyph, name, size);
   if (ret && (size && !*name))
     ret = false;
 
   return ret;
 }
 
 static hb_bool_t
 hb_ft_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)
 {
-  FT_Face ft_face = (FT_Face) font_data;
+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  FT_Face ft_face = ft_font->ft_face;
 
   if (len < 0)
     *glyph = FT_Get_Name_Index (ft_face, (FT_String *) name);
   else {
     /* Make a nul-terminated version. */
     char buf[128];
     len = MIN (len, (int) sizeof (buf) - 1);
     strncpy (buf, name, len);
@@ -288,32 +375,35 @@ hb_ft_get_glyph_from_name (hb_font_t *fo
         len < 0 ? !strcmp (buf, name) : !strncmp (buf, name, len))
       return true;
   }
 
   return *glyph != 0;
 }
 
 
-static hb_font_funcs_t *
-_hb_ft_get_font_funcs (void)
+static void
+_hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
 {
   static const hb_font_funcs_t ft_ffuncs = {
     HB_OBJECT_HEADER_STATIC,
 
     true, /* immutable */
 
     {
 #define HB_FONT_FUNC_IMPLEMENT(name) hb_ft_get_##name,
       HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 #undef HB_FONT_FUNC_IMPLEMENT
     }
   };
 
-  return const_cast<hb_font_funcs_t *> (&ft_ffuncs);
+  hb_font_set_funcs (font,
+		     const_cast<hb_font_funcs_t *> (&ft_ffuncs),
+		     _hb_ft_font_create (ft_face, unref),
+		     (hb_destroy_func_t) _hb_ft_font_destroy);
 }
 
 
 static hb_blob_t *
 reference_table  (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
 {
   FT_Face ft_face = (FT_Face) user_data;
   FT_Byte *buffer;
@@ -342,17 +432,17 @@ reference_table  (hb_face_t *face HB_UNU
 /**
  * hb_ft_face_create:
  * @ft_face: (destroy destroy) (scope notified): 
  * @destroy:
  *
  * 
  *
  * Return value: (transfer full): 
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_face_t *
 hb_ft_face_create (FT_Face           ft_face,
 		   hb_destroy_func_t destroy)
 {
   hb_face_t *face;
 
   if (ft_face->stream->read == NULL) {
@@ -398,62 +488,55 @@ hb_ft_face_finalize (FT_Face ft_face)
 
 /**
  * hb_ft_face_create_cached:
  * @ft_face: 
  *
  * 
  *
  * Return value: (transfer full): 
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_face_t *
 hb_ft_face_create_cached (FT_Face ft_face)
 {
   if (unlikely (!ft_face->generic.data || ft_face->generic.finalizer != (FT_Generic_Finalizer) hb_ft_face_finalize))
   {
     if (ft_face->generic.finalizer)
       ft_face->generic.finalizer (ft_face);
 
     ft_face->generic.data = hb_ft_face_create (ft_face, NULL);
     ft_face->generic.finalizer = (FT_Generic_Finalizer) hb_ft_face_finalize;
   }
 
   return hb_face_reference ((hb_face_t *) ft_face->generic.data);
 }
 
-static void
-_do_nothing (void)
-{
-}
-
 
 /**
  * hb_ft_font_create:
  * @ft_face: (destroy destroy) (scope notified): 
  * @destroy:
  *
  * 
  *
  * Return value: (transfer full): 
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_font_t *
 hb_ft_font_create (FT_Face           ft_face,
 		   hb_destroy_func_t destroy)
 {
   hb_font_t *font;
   hb_face_t *face;
 
   face = hb_ft_face_create (ft_face, destroy);
   font = hb_font_create (face);
   hb_face_destroy (face);
-  hb_font_set_funcs (font,
-		     _hb_ft_get_font_funcs (),
-		     ft_face, (hb_destroy_func_t) _do_nothing);
+  _hb_ft_font_set_funcs (font, ft_face, false);
   hb_font_set_scale (font,
 		     (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16),
 		     (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16));
 #if 0 /* hb-ft works in no-hinting model */
   hb_font_set_ppem (font,
 		    ft_face->size->metrics.x_ppem,
 		    ft_face->size->metrics.y_ppem);
 #endif
@@ -557,23 +640,11 @@ hb_ft_font_set_funcs (hb_font_t *font)
     FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0,
 			  0, font->y_scale < 0 ? -1 : +1};
     FT_Set_Transform (ft_face, &matrix, NULL);
   }
 
   ft_face->generic.data = blob;
   ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;
 
-  hb_font_set_funcs (font,
-		     _hb_ft_get_font_funcs (),
-		     ft_face,
-		     (hb_destroy_func_t) FT_Done_Face);
+  _hb_ft_font_set_funcs (font, ft_face, true);
+  hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING);
 }
-
-FT_Face
-hb_ft_font_get_face (hb_font_t *font)
-{
-  if (font->destroy == (hb_destroy_func_t) FT_Done_Face ||
-      font->destroy == (hb_destroy_func_t) _do_nothing)
-    return (FT_Face) font->user_data;
-
-  return NULL;
-}
--- a/gfx/harfbuzz/src/hb-ft.h
+++ b/gfx/harfbuzz/src/hb-ft.h
@@ -1,10 +1,11 @@
 /*
  * Copyright © 2009  Red Hat, Inc.
+ * Copyright © 2015  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.
@@ -17,16 +18,17 @@
  *
  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
  */
 
 #ifndef HB_FT_H
 #define HB_FT_H
 
 #include "hb.h"
 
 #include <ft2build.h>
@@ -100,20 +102,25 @@ hb_font_t *
 hb_ft_font_create (FT_Face           ft_face,
 		   hb_destroy_func_t destroy);
 
 /* See notes on hb_ft_face_create_referenced() re lifecycle-management
  * issues. */
 hb_font_t *
 hb_ft_font_create_referenced (FT_Face ft_face);
 
+FT_Face
+hb_ft_font_get_face (hb_font_t *font);
+
+void
+hb_ft_font_set_load_flags (hb_font_t *font, int load_flags);
+
+int
+hb_ft_font_get_load_flags (hb_font_t *font);
 
 /* Makes an hb_font_t use FreeType internally to implement font functions. */
 void
 hb_ft_font_set_funcs (hb_font_t *font);
 
-FT_Face
-hb_ft_font_get_face (hb_font_t *font);
-
 
 HB_END_DECLS
 
 #endif /* HB_FT_H */
--- a/gfx/harfbuzz/src/hb-graphite2.cc
+++ b/gfx/harfbuzz/src/hb-graphite2.cc
@@ -133,16 +133,19 @@ void
     free (old);
   }
 
   gr_face_destroy (data->grface);
 
   free (data);
 }
 
+/*
+ * Since: 0.9.10
+ */
 gr_face *
 hb_graphite2_face_get_gr_face (hb_face_t *face)
 {
   if (unlikely (!hb_graphite2_shaper_face_data_ensure (face))) return NULL;
   return HB_SHAPER_DATA_GET (face)->grface;
 }
 
 
@@ -167,16 +170,19 @@ hb_graphite2_shaper_font_data_t *
 }
 
 void
 _hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data)
 {
   gr_font_destroy (data);
 }
 
+/*
+ * Since: 0.9.10
+ */
 gr_font *
 hb_graphite2_font_get_gr_font (hb_font_t *font)
 {
   if (unlikely (!hb_graphite2_shaper_font_data_ensure (font))) return NULL;
   return HB_SHAPER_DATA_GET (font);
 }
 
 
--- a/gfx/harfbuzz/src/hb-open-file-private.hh
+++ b/gfx/harfbuzz/src/hb-open-file-private.hh
@@ -51,17 +51,17 @@ struct OffsetTable;
 struct TTCHeader;
 
 
 typedef struct TableRecord
 {
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this));
+    return_trace (c->check_struct (this));
   }
 
   Tag		tag;		/* 4-byte identifier. */
   CheckSum	checkSum;	/* CheckSum for this table. */
   ULONG		offset;		/* Offset from beginning of TrueType font
 				 * file. */
   ULONG		length;		/* Length of this table. */
   public:
@@ -101,17 +101,17 @@ typedef struct OffsetTable
     find_table_index (tag, &table_index);
     return get_table (table_index);
   }
 
   public:
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables));
+    return_trace (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables));
   }
 
   protected:
   Tag		sfnt_version;	/* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
   USHORT	numTables;	/* Number of tables. */
   USHORT	searchRangeZ;	/* (Maximum power of 2 <= numTables) x 16 */
   USHORT	entrySelectorZ;	/* Log2(maximum power of 2 <= numTables). */
   USHORT	rangeShiftZ;	/* NumTables x 16-searchRange. */
@@ -130,17 +130,17 @@ struct TTCHeaderVersion1
   friend struct TTCHeader;
 
   inline unsigned int get_face_count (void) const { return table.len; }
   inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (table.sanitize (c, this));
+    return_trace (table.sanitize (c, this));
   }
 
   protected:
   Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
   FixedVersion	version;	/* Version of the TTC Header (1.0),
 				 * 0x00010000u */
   ArrayOf<OffsetTo<OffsetTable, ULONG>, ULONG>
 		table;		/* Array of offsets to the OffsetTable for each font
@@ -170,21 +170,21 @@ struct TTCHeader
     case 1: return u.version1.get_face (i);
     default:return Null(OpenTypeFontFace);
     }
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!u.header.version.sanitize (c))) return TRACE_RETURN (false);
+    if (unlikely (!u.header.version.sanitize (c))) return_trace (false);
     switch (u.header.version.major) {
     case 2: /* version 2 is compatible with version 1 */
-    case 1: return TRACE_RETURN (u.version1.sanitize (c));
-    default:return TRACE_RETURN (true);
+    case 1: return_trace (u.version1.sanitize (c));
+    default:return_trace (true);
     }
   }
 
   protected:
   union {
   struct {
   Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
   FixedVersion	version;	/* Version of the TTC Header (1.0 or 2.0),
@@ -235,24 +235,24 @@ struct OpenTypeFontFile
     case TTCTag:	return u.ttcHeader.get_face (i);
     default:		return Null(OpenTypeFontFace);
     }
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!u.tag.sanitize (c))) return TRACE_RETURN (false);
+    if (unlikely (!u.tag.sanitize (c))) return_trace (false);
     switch (u.tag) {
     case CFFTag:	/* All the non-collection tags */
     case TrueTag:
     case Typ1Tag:
-    case TrueTypeTag:	return TRACE_RETURN (u.fontFace.sanitize (c));
-    case TTCTag:	return TRACE_RETURN (u.ttcHeader.sanitize (c));
-    default:		return TRACE_RETURN (true);
+    case TrueTypeTag:	return_trace (u.fontFace.sanitize (c));
+    case TTCTag:	return_trace (u.ttcHeader.sanitize (c));
+    default:		return_trace (true);
     }
   }
 
   protected:
   union {
   Tag			tag;		/* 4-byte identifier. */
   OpenTypeFontFace	fontFace;
   TTCHeader		ttcHeader;
--- a/gfx/harfbuzz/src/hb-open-type-private.hh
+++ b/gfx/harfbuzz/src/hb-open-type-private.hh
@@ -149,16 +149,30 @@ template <> \
   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>()
 
 
+/*
+ * Dispatch
+ */
+
+template <typename Context, typename Return, unsigned int MaxDebugDepth>
+struct hb_dispatch_context_t
+{
+  static const unsigned int max_debug_depth = MaxDebugDepth;
+  typedef Return return_t;
+  template <typename T, typename F>
+  inline bool may_dispatch (const T *obj, const F *format) { return true; }
+  static return_t no_dispatch_return_value (void) { return Context::default_return_value (); }
+};
+
 
 /*
  * Sanitize
  */
 
 #ifndef HB_DEBUG_SANITIZE
 #define HB_DEBUG_SANITIZE (HB_DEBUG+0)
 #endif
@@ -169,27 +183,33 @@ ASSERT_STATIC (Type::min_size + 1 <= siz
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
 	 "");
 
 /* This limits sanitizing time on really broken fonts. */
 #ifndef HB_SANITIZE_MAX_EDITS
 #define HB_SANITIZE_MAX_EDITS 100
 #endif
 
-struct hb_sanitize_context_t
+struct hb_sanitize_context_t :
+       hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
 {
+  inline hb_sanitize_context_t (void) :
+	debug_depth (0),
+	start (NULL), end (NULL),
+	writable (false), edit_count (0),
+	blob (NULL) {}
+
   inline const char *get_name (void) { return "SANITIZE"; }
-  static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE;
-  typedef bool return_t;
   template <typename T, typename F>
   inline bool may_dispatch (const T *obj, const F *format)
   { return format->sanitize (this); }
   template <typename T>
   inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
   static return_t default_return_value (void) { return true; }
+  static return_t no_dispatch_return_value (void) { return false; }
   bool stop_sublookup_iteration (const return_t r) const { return !r; }
 
   inline void init (hb_blob_t *b)
   {
     this->blob = hb_blob_reference (b);
     this->writable = false;
   }
 
@@ -290,17 +310,17 @@ struct hb_sanitize_context_t
 
 
 
 /* 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, NULL, NULL, false, 0, NULL}};
+    hb_sanitize_context_t c[1];
     bool sane;
 
     /* TODO is_sane() stuff */
 
     c->init (blob);
 
   retry:
     DEBUG_MSG_FUNC (SANITIZE, c->start, "start");
@@ -619,17 +639,17 @@ struct IntType
     if (sizeof (Type) < sizeof (int))
       return (int) a - (int) b;
     else
       return a < b ? -1 : a == b ? 0 : +1;
   }
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (likely (c->check_struct (this)));
+    return_trace (likely (c->check_struct (this)));
   }
   protected:
   BEInt<Type, Size> v;
   public:
   DEFINE_SIZE_STATIC (Size);
 };
 
 typedef	IntType<uint8_t	, 1> BYTE;	/* 8-bit unsigned integer. */
@@ -647,17 +667,17 @@ typedef USHORT UFWORD;
 
 /* Date represented in number of seconds since 12:00 midnight, January 1,
  * 1904. The value is represented as a signed 64-bit integer. */
 struct LONGDATETIME
 {
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (likely (c->check_struct (this)));
+    return_trace (likely (c->check_struct (this)));
   }
   protected:
   LONG major;
   ULONG minor;
   public:
   DEFINE_SIZE_STATIC (8);
 };
 
@@ -724,17 +744,17 @@ struct CheckSum : ULONG
 
 struct FixedVersion
 {
   inline uint32_t to_int (void) const { return (major << 16) + minor; }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this));
+    return_trace (c->check_struct (this));
   }
 
   USHORT major;
   USHORT minor;
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
@@ -760,31 +780,31 @@ struct OffsetTo : Offset<OffsetType>
     Type *t = c->start_embed<Type> ();
     this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
     return *t;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
+    if (unlikely (!c->check_struct (this))) return_trace (false);
     unsigned int offset = *this;
-    if (unlikely (!offset)) return TRACE_RETURN (true);
+    if (unlikely (!offset)) return_trace (true);
     const Type &obj = StructAtOffset<Type> (base, offset);
-    return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c));
+    return_trace (likely (obj.sanitize (c)) || neuter (c));
   }
   template <typename T>
   inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
+    if (unlikely (!c->check_struct (this))) return_trace (false);
     unsigned int offset = *this;
-    if (unlikely (!offset)) return TRACE_RETURN (true);
+    if (unlikely (!offset)) return_trace (true);
     const Type &obj = StructAtOffset<Type> (base, offset);
-    return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c));
+    return_trace (likely (obj.sanitize (c, user_data)) || neuter (c));
   }
 
   /* Set the offset to Null */
   inline bool neuter (hb_sanitize_context_t *c) const {
     return c->try_set (this, 0);
   }
   DEFINE_SIZE_STATIC (sizeof(OffsetType));
 };
@@ -825,87 +845,87 @@ struct ArrayOf
   }
   inline unsigned int get_size (void) const
   { return len.static_size + len * Type::static_size; }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 unsigned int items_len)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
     len.set (items_len); /* TODO(serialize) Overflow? */
-    if (unlikely (!c->extend (*this))) return TRACE_RETURN (false);
-    return TRACE_RETURN (true);
+    if (unlikely (!c->extend (*this))) return_trace (false);
+    return_trace (true);
   }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<Type> &items,
 			 unsigned int items_len)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!serialize (c, items_len))) return TRACE_RETURN (false);
+    if (unlikely (!serialize (c, items_len))) return_trace (false);
     for (unsigned int i = 0; i < items_len; i++)
       array[i] = items[i];
     items.advance (items_len);
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
 
     /* Note: for structs that do not reference other structs,
      * we do not need to call their sanitize() as we already did
      * a bound check on the aggregate array size.  We just include
      * a small unreachable expression to make sure the structs
      * pointed to do have a simple sanitize(), ie. they do not
      * reference other structs via offsets.
      */
     (void) (false && array[0].sanitize (c));
 
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
     unsigned int count = len;
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!array[i].sanitize (c, base)))
-        return TRACE_RETURN (false);
-    return TRACE_RETURN (true);
+        return_trace (false);
+    return_trace (true);
   }
   template <typename T>
   inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
+    if (unlikely (!sanitize_shallow (c))) return_trace (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);
+        return_trace (false);
+    return_trace (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) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len));
+    return_trace (c->check_struct (this) && c->check_array (array, Type::static_size, len));
   }
 
   public:
   LenType len;
   Type array[VAR];
   public:
   DEFINE_SIZE_ARRAY (sizeof (LenType), array);
 };
@@ -922,23 +942,23 @@ struct OffsetListOf : OffsetArrayOf<Type
   {
     if (unlikely (i >= this->len)) return Null(Type);
     return this+this->array[i];
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this));
+    return_trace (OffsetArrayOf<Type>::sanitize (c, this));
   }
   template <typename T>
   inline bool sanitize (hb_sanitize_context_t *c, T user_data) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data));
+    return_trace (OffsetArrayOf<Type>::sanitize (c, this, user_data));
   }
 };
 
 
 /* An array starting at second element. */
 template <typename Type, typename LenType=USHORT>
 struct HeadlessArrayOf
 {
@@ -950,47 +970,47 @@ struct HeadlessArrayOf
   inline unsigned int get_size (void) const
   { return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<Type> &items,
 			 unsigned int items_len)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
     len.set (items_len); /* TODO(serialize) Overflow? */
-    if (unlikely (!items_len)) return TRACE_RETURN (true);
-    if (unlikely (!c->extend (*this))) return TRACE_RETURN (false);
+    if (unlikely (!items_len)) return_trace (true);
+    if (unlikely (!c->extend (*this))) return_trace (false);
     for (unsigned int i = 0; i < items_len - 1; i++)
       array[i] = items[i];
     items.advance (items_len - 1);
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool sanitize_shallow (hb_sanitize_context_t *c) const
   {
     return c->check_struct (this)
 	&& c->check_array (this, Type::static_size, len);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
 
     /* Note: for structs that do not reference other structs,
      * we do not need to call their sanitize() as we already did
      * a bound check on the aggregate array size.  We just include
      * a small unreachable expression to make sure the structs
      * pointed to do have a simple sanitize(), ie. they do not
      * reference other structs via offsets.
      */
     (void) (false && array[0].sanitize (c));
 
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   LenType len;
   Type array[VAR];
   public:
   DEFINE_SIZE_ARRAY (sizeof (LenType), array);
 };
 
--- a/gfx/harfbuzz/src/hb-ot-cmap-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-cmap-table.hh
@@ -49,17 +49,17 @@ struct CmapSubtableFormat0
       return false;
     *glyph = gid;
     return true;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this));
+    return_trace (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. */
@@ -125,31 +125,31 @@ struct CmapSubtableFormat4
     *glyph = gid & 0xFFFFu;
     return true;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
-      return TRACE_RETURN (false);
+      return_trace (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 (false);
     }
 
-    return TRACE_RETURN (16 + 4 * (unsigned int) segCountX2 <= length);
+    return_trace (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. */
@@ -182,17 +182,17 @@ struct CmapSubtableLongGroup
     if (codepoint < startCharCode) return -1;
     if (codepoint > endCharCode)   return +1;
     return 0;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this));
+    return_trace (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:
@@ -210,17 +210,17 @@ struct CmapSubtableTrimmed
       return false;
     *glyph = gid;
     return true;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && glyphIdArray.sanitize (c));
+    return_trace (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>
@@ -243,17 +243,17 @@ struct CmapSubtableLongSegmented
       return false;
     *glyph = T::group_get_glyph (groups[i], codepoint);
     return true;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && groups.sanitize (c));
+    return_trace (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>
@@ -290,17 +290,17 @@ struct UnicodeValueRange
     if (codepoint < startUnicodeValue) return -1;
     if (codepoint > startUnicodeValue + additionalCount) return +1;
     return 0;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this));
+    return_trace (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);
 };
@@ -312,17 +312,17 @@ struct UVSMapping
   inline int cmp (const hb_codepoint_t &codepoint) const
   {
     return unicodeValue.cmp (codepoint);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this));
+    return_trace (c->check_struct (this));
   }
 
   UINT24	unicodeValue;	/* Base Unicode value of the UVS */
   GlyphID	glyphID;	/* Glyph ID of the UVS */
   public:
   DEFINE_SIZE_STATIC (5);
 };
 
@@ -352,19 +352,19 @@ struct VariationSelectorRecord
   inline int cmp (const hb_codepoint_t &variation_selector) const
   {
     return varSelector.cmp (variation_selector);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) &&
-			 defaultUVS.sanitize (c, base) &&
-			 nonDefaultUVS.sanitize (c, base));
+    return_trace (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:
@@ -378,18 +378,18 @@ struct CmapSubtableFormat14
 					    hb_codepoint_t *glyph) const
   {
     return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) &&
-			 record.sanitize (c, this));
+    return_trace (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'. */
@@ -424,26 +424,26 @@ struct CmapSubtable
     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);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
+    if (!u.format.sanitize (c)) return_trace (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);
+    case  0: return_trace (u.format0 .sanitize (c));
+    case  4: return_trace (u.format4 .sanitize (c));
+    case  6: return_trace (u.format6 .sanitize (c));
+    case 10: return_trace (u.format10.sanitize (c));
+    case 12: return_trace (u.format12.sanitize (c));
+    case 13: return_trace (u.format13.sanitize (c));
+    case 14: return_trace (u.format14.sanitize (c));
+    default:return_trace (true);
     }
   }
 
   protected:
   union {
   USHORT		format;		/* Format identifier */
   CmapSubtableFormat0	format0;
   CmapSubtableFormat4	format4;
@@ -468,18 +468,18 @@ struct EncodingRecord
     ret = encodingID.cmp (other.encodingID);
     if (ret) return ret;
     return 0;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) &&
-			 subtable.sanitize (c, base));
+    return_trace (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);
@@ -504,19 +504,19 @@ struct cmap
       return NULL;
 
     return &(this+encodingRecord[result].subtable);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) &&
-			 likely (version == 0) &&
-			 encodingRecord.sanitize (c, this));
+    return_trace (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);
 };
--- a/gfx/harfbuzz/src/hb-ot-font.cc
+++ b/gfx/harfbuzz/src/hb-ot-font.cc
@@ -233,20 +233,19 @@ struct hb_ot_font_t
   hb_ot_face_cmap_accelerator_t cmap;
   hb_ot_face_metrics_accelerator_t h_metrics;
   hb_ot_face_metrics_accelerator_t v_metrics;
   hb_ot_face_glyf_accelerator_t glyf;
 };
 
 
 static hb_ot_font_t *
-_hb_ot_font_create (hb_font_t *font)
+_hb_ot_font_create (hb_face_t *face)
 {
   hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
-  hb_face_t *face = font->face;
 
   if (unlikely (!ot_font))
     return NULL;
 
   unsigned int upem = face->get_upem ();
 
   ot_font->cmap.init (face);
   ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1);
@@ -257,16 +256,17 @@ static hb_ot_font_t *
 }
 
 static void
 _hb_ot_font_destroy (hb_ot_font_t *ot_font)
 {
   ot_font->cmap.fini ();
   ot_font->h_metrics.fini ();
   ot_font->v_metrics.fini ();
+  ot_font->glyf.fini ();
 
   free (ot_font);
 }
 
 
 static hb_bool_t
 hb_ot_get_glyph (hb_font_t *font HB_UNUSED,
 		 void *font_data,
@@ -418,17 +418,17 @@ static hb_font_funcs_t *
 
 
 /**
  * Since: 0.9.28
  **/
 void
 hb_ot_font_set_funcs (hb_font_t *font)
 {
-  hb_ot_font_t *ot_font = _hb_ot_font_create (font);
+  hb_ot_font_t *ot_font = _hb_ot_font_create (font->face);
   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-glyf-table.hh
@@ -0,0 +1,104 @@
+/*
+ * Copyright © 2015  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_GLYF_TABLE_HH
+#define HB_OT_GLYF_TABLE_HH
+
+#include "hb-open-type-private.hh"
+
+
+namespace OT {
+
+
+/*
+ * loca -- Index to Location
+ */
+
+#define HB_OT_TAG_loca HB_TAG('l','o','c','a')
+
+
+struct loca
+{
+  static const hb_tag_t tableTag = HB_OT_TAG_loca;
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (true);
+  }
+
+  public:
+  union {
+    USHORT	shortsZ[VAR];		/* Location offset divided by 2. */
+    ULONG	longsZ[VAR];		/* Location offset. */
+  } u;
+  DEFINE_SIZE_ARRAY (0, u.longsZ);
+};
+
+
+/*
+ * glyf -- TrueType Glyph Data
+ */
+
+#define HB_OT_TAG_glyf HB_TAG('g','l','y','f')
+
+
+struct glyf
+{
+  static const hb_tag_t tableTag = HB_OT_TAG_glyf;
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    /* We don't check for anything specific here.  The users of the
+     * struct do all the hard work... */
+    return_trace (true);
+  }
+
+  public:
+  BYTE		dataX[VAR];		/* Glyphs data. */
+
+  DEFINE_SIZE_ARRAY (0, dataX);
+};
+
+struct glyfGlyphHeader
+{
+  SHORT		numberOfContours;	/* If the number of contours is
+					 * 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. */
+
+  DEFINE_SIZE_STATIC (10);
+};
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_GLYF_TABLE_HH */
--- a/gfx/harfbuzz/src/hb-ot-head-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-head-table.hh
@@ -50,17 +50,17 @@ struct head
     unsigned int upem = unitsPerEm;
     /* If no valid head table found, assume 1000, which matches typical Type1 usage. */
     return 16 <= upem && upem <= 16384 ? upem : 1000;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1));
+    return_trace (c->check_struct (this) && likely (version.major == 1));
   }
 
   protected:
   FixedVersion	version;		/* Version of the head table--currently
 					 * 0x00010000u for version 1.0. */
   FixedVersion	fontRevision;		/* Set by font manufacturer. */
   ULONG		checkSumAdjustment;	/* To compute: set it to 0, sum the
 					 * entire font as ULONG, then store
--- a/gfx/harfbuzz/src/hb-ot-hhea-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-hhea-table.hh
@@ -47,17 +47,17 @@ struct _hea
   static const hb_tag_t tableTag = HB_TAG('_','h','e','a');
 
   static const hb_tag_t hheaTag	= HB_OT_TAG_hhea;
   static const hb_tag_t vheaTag	= HB_OT_TAG_vhea;
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1));
+    return_trace (c->check_struct (this) && likely (version.major == 1));
   }
 
   public:
   FixedVersion	version;		/* 0x00010000u for version 1.0. */
   FWORD		ascender;		/* Typographic ascent. */
   FWORD		descender;		/* Typographic descent. */
   FWORD		lineGap;		/* Typographic line gap. */
   UFWORD	advanceMax;		/* Maximum advance width/height value in
--- a/gfx/harfbuzz/src/hb-ot-hmtx-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-hmtx-table.hh
@@ -57,17 +57,17 @@ struct _mtx
   static const hb_tag_t hmtxTag	= HB_OT_TAG_hmtx;
   static const hb_tag_t vmtxTag	= HB_OT_TAG_vmtx;
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     /* We don't check for anything specific here.  The users of the
      * struct do all the hard work... */
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   public:
   LongMetric	longMetric[VAR];	/* Paired advance width and leading
 					 * bearing values for each glyph. The
 					 * value numOfHMetrics comes from
 					 * the 'hhea' table. If the font is
 					 * monospaced, only one entry need
--- a/gfx/harfbuzz/src/hb-ot-layout-common-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-common-private.hh
@@ -39,17 +39,17 @@ namespace OT {
 
 #define TRACE_DISPATCH(this, format) \
 	hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
 	 "format %d", (int) format);
 
 
 #define NOT_COVERED		((unsigned int) -1)
-#define MAX_NESTING_LEVEL	8
+#define MAX_NESTING_LEVEL	6
 #define MAX_CONTEXT_LENGTH	64
 
 
 
 /*
  *
  * OpenType Layout Common Table Formats
  *
@@ -70,17 +70,17 @@ struct Record
   struct sanitize_closure_t {
     hb_tag_t tag;
     const void *list_base;
   };
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     const sanitize_closure_t closure = {tag, base};
-    return TRACE_RETURN (c->check_struct (this) && offset.sanitize (c, base, &closure));
+    return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
   }
 
   Tag		tag;		/* 4-byte Tag identifier */
   OffsetTo<Type>
 		offset;		/* Offset from beginning of object holding
 				 * the Record */
   public:
   DEFINE_SIZE_STATIC (6);
@@ -126,31 +126,31 @@ template <typename Type>
 struct RecordListOf : RecordArrayOf<Type>
 {
   inline const Type& operator [] (unsigned int i) const
   { return this+RecordArrayOf<Type>::operator [](i).offset; }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (RecordArrayOf<Type>::sanitize (c, this));
+    return_trace (RecordArrayOf<Type>::sanitize (c, this));
   }
 };
 
 
 struct RangeRecord
 {
   inline int cmp (hb_codepoint_t g) const {
     return g < start ? -1 : g <= end ? 0 : +1 ;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this));
+    return_trace (c->check_struct (this));
   }
 
   inline bool intersects (const hb_set_t *glyphs) const {
     return glyphs->intersects (start, end);
   }
 
   template <typename set_t>
   inline void add_coverage (set_t *glyphs) const {
@@ -206,17 +206,17 @@ struct LangSys
       return Index::NOT_FOUND_INDEX;
    return reqFeatureIndex;;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c,
 			const Record<LangSys>::sanitize_closure_t * = NULL) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c));
+    return_trace (c->check_struct (this) && featureIndex.sanitize (c));
   }
 
   Offset<>	lookupOrderZ;	/* = Null (reserved for an offset to a
 				 * reordering table) */
   USHORT	reqFeatureIndex;/* Index of a feature required for this
 				 * language system--if no required features
 				 * = 0xFFFFu */
   IndexArray	featureIndex;	/* Array of indices into the FeatureList */
@@ -246,17 +246,17 @@ struct Script
 
   inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
   inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
 
   inline bool sanitize (hb_sanitize_context_t *c,
 			const Record<Script>::sanitize_closure_t * = NULL) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
+    return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
   }
 
   protected:
   OffsetTo<LangSys>
 		defaultLangSys;	/* Offset to DefaultLangSys table--from
 				 * beginning of Script table--may be Null */
   RecordArrayOf<LangSys>
 		langSys;	/* Array of LangSysRecords--listed
@@ -269,17 +269,17 @@ typedef RecordListOf<Script> ScriptList;
 
 
 /* http://www.microsoft.com/typography/otspec/features_pt.htm#size */
 struct FeatureParamsSize
 {
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
+    if (unlikely (!c->check_struct (this))) return_trace (false);
 
     /* This subtable has some "history", if you will.  Some earlier versions of
      * Adobe tools calculated the offset of the FeatureParams sutable from the
      * beginning of the FeatureList table!  Now, that is dealt with in the
      * Feature implementation.  But we still need to be able to tell junk from
      * real data.  Note: We don't check that the nameID actually exists.
      *
      * Read Roberts wrote on 9/15/06 on opentype-list@indx.co.uk :
@@ -321,29 +321,29 @@ struct FeatureParamsSize
      *     "menu name ID"  > 32767 or
      *     menu name ID is not a name ID which is actually in the name table)
      *     fails test
      * Else
      *     passes test.
      */
 
     if (!designSize)
-      return TRACE_RETURN (false);
+      return_trace (false);
     else if (subfamilyID == 0 &&
 	     subfamilyNameID == 0 &&
 	     rangeStart == 0 &&
 	     rangeEnd == 0)
-      return TRACE_RETURN (true);
+      return_trace (true);
     else if (designSize < rangeStart ||
 	     designSize > rangeEnd ||
 	     subfamilyNameID < 256 ||
 	     subfamilyNameID > 32767)
-      return TRACE_RETURN (false);
+      return_trace (false);
     else
-      return TRACE_RETURN (true);
+      return_trace (true);
   }
 
   USHORT	designSize;	/* Represents the design size in 720/inch
 				 * units (decipoints).  The design size entry
 				 * must be non-zero.  When there is a design
 				 * size but no recommended size range, the
 				 * rest of the array will consist of zeros. */
   USHORT	subfamilyID;	/* Has no independent meaning, but serves
@@ -383,17 +383,17 @@ struct FeatureParamsSize
 /* http://www.microsoft.com/typography/otspec/features_pt.htm#ssxx */
 struct FeatureParamsStylisticSet
 {
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     /* Right now minorVersion is at zero.  Which means, any table supports
      * the uiNameID field. */
-    return TRACE_RETURN (c->check_struct (this));
+    return_trace (c->check_struct (this));
   }
 
   USHORT	version;	/* (set to 0): This corresponds to a “minor”
 				 * version number. Additional data may be
 				 * added to the end of this Feature Parameters
 				 * table in the future. */
 
   USHORT	uiNameID;	/* The 'name' table name ID that specifies a
@@ -415,18 +415,18 @@ struct FeatureParamsStylisticSet
 };
 
 /* http://www.microsoft.com/typography/otspec/features_ae.htm#cv01-cv99 */
 struct FeatureParamsCharacterVariants
 {
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) &&
-			 characters.sanitize (c));
+    return_trace (c->check_struct (this) &&
+		  characters.sanitize (c));
   }
 
   USHORT	format;			/* Format number is set to 0. */
   USHORT	featUILableNameID;	/* The ‘name’ table name ID that
 					 * specifies a string (or strings,
 					 * for multiple languages) for a
 					 * user-interface label for this
 					 * feature. (May be NULL.) */
@@ -457,22 +457,22 @@ struct FeatureParamsCharacterVariants
 };
 
 struct FeatureParams
 {
   inline bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) const
   {
     TRACE_SANITIZE (this);
     if (tag == HB_TAG ('s','i','z','e'))
-      return TRACE_RETURN (u.size.sanitize (c));
+      return_trace (u.size.sanitize (c));
     if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
-      return TRACE_RETURN (u.stylisticSet.sanitize (c));
+      return_trace (u.stylisticSet.sanitize (c));
     if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
-      return TRACE_RETURN (u.characterVariants.sanitize (c));
-    return TRACE_RETURN (true);
+      return_trace (u.characterVariants.sanitize (c));
+    return_trace (true);
   }
 
   inline const FeatureParamsSize& get_size_params (hb_tag_t tag) const
   {
     if (tag == HB_TAG ('s','i','z','e'))
       return u.size;
     return Null(FeatureParamsSize);
   }
@@ -500,53 +500,53 @@ struct Feature
   inline const FeatureParams &get_feature_params (void) const
   { return this+featureParams; }
 
   inline bool sanitize (hb_sanitize_context_t *c,
 			const Record<Feature>::sanitize_closure_t *closure) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
-      return TRACE_RETURN (false);
+      return_trace (false);
 
     /* Some earlier versions of Adobe tools calculated the offset of the
      * FeatureParams subtable from the beginning of the FeatureList table!
      *
      * If sanitizing "failed" for the FeatureParams subtable, try it with the
      * 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.
      */
 
     OffsetTo<FeatureParams> orig_offset = featureParams;
     if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
-      return TRACE_RETURN (false);
+      return_trace (false);
 
     if (likely (orig_offset.is_null ()))
-      return TRACE_RETURN (true);
+      return_trace (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));
 
       OffsetTo<FeatureParams> new_offset;
       /* Check that it did not overflow. */
       new_offset.set (new_offset_int);
       if (new_offset == new_offset_int &&
 	  c->try_set (&featureParams, new_offset) &&
 	  !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
-	return TRACE_RETURN (false);
+	return_trace (false);
     }
 
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   OffsetTo<FeatureParams>
 		 featureParams;	/* Offset to Feature Parameters table (if one
 				 * has been defined for the feature), relative
 				 * to the beginning of the Feature Table; = Null
 				 * if not required */
   IndexArray	 lookupIndex;	/* Array of LookupList indices */
@@ -608,50 +608,50 @@ struct Lookup
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     unsigned int lookup_type = get_type ();
     TRACE_DISPATCH (this, lookup_type);
     unsigned int count = get_subtable_count ();
     for (unsigned int i = 0; i < count; i++) {
       typename context_t::return_t r = get_subtable<SubTableType> (i).dispatch (c, lookup_type);
       if (c->stop_sublookup_iteration (r))
-        return TRACE_RETURN (r);
+        return_trace (r);
     }
-    return TRACE_RETURN (c->default_return_value ());
+    return_trace (c->default_return_value ());
   }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 unsigned int lookup_type,
 			 uint32_t lookup_props,
 			 unsigned int num_subtables)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
     lookupType.set (lookup_type);
     lookupFlag.set (lookup_props & 0xFFFFu);
-    if (unlikely (!subTable.serialize (c, num_subtables))) return TRACE_RETURN (false);
+    if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
     {
       USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
       markFilteringSet.set (lookup_props >> 16);
     }
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     /* Real sanitize of the subtables is done by GSUB/GPOS/... */
-    if (!(c->check_struct (this) && subTable.sanitize (c))) return TRACE_RETURN (false);
+    if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
     {
       const USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
-      if (!markFilteringSet.sanitize (c)) return TRACE_RETURN (false);
+      if (!markFilteringSet.sanitize (c)) return_trace (false);
     }
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   private:
   USHORT	lookupType;		/* Different enumerations for GSUB and GPOS */
   USHORT	lookupFlag;		/* Lookup qualifiers */
   ArrayOf<Offset<> >
 		subTable;		/* Array of SubTables */
   USHORT	markFilteringSetX[VAR];	/* Index (base 0) into GDEF mark glyph sets
@@ -680,29 +680,29 @@ struct CoverageFormat1
     return i;
   }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<GlyphID> &glyphs,
 			 unsigned int num_glyphs)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
     glyphArray.len.set (num_glyphs);
-    if (unlikely (!c->extend (glyphArray))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend (glyphArray))) return_trace (false);
     for (unsigned int i = 0; i < num_glyphs; i++)
       glyphArray[i] = glyphs[i];
     glyphs.advance (num_glyphs);
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (glyphArray.sanitize (c));
+    return_trace (glyphArray.sanitize (c));
   }
 
   inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
     return glyphs->has (glyphArray[index]);
   }
 
   template <typename set_t>
   inline void add_coverage (set_t *glyphs) const {
@@ -749,47 +749,47 @@ struct CoverageFormat2
     return NOT_COVERED;
   }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<GlyphID> &glyphs,
 			 unsigned int num_glyphs)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
 
-    if (unlikely (!num_glyphs)) return TRACE_RETURN (true);
+    if (unlikely (!num_glyphs)) return_trace (true);
 
     unsigned int num_ranges = 1;
     for (unsigned int i = 1; i < num_glyphs; i++)
       if (glyphs[i - 1] + 1 != glyphs[i])
         num_ranges++;
     rangeRecord.len.set (num_ranges);
-    if (unlikely (!c->extend (rangeRecord))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend (rangeRecord))) return_trace (false);
 
     unsigned int range = 0;
     rangeRecord[range].start = glyphs[0];
     rangeRecord[range].value.set (0);
     for (unsigned int i = 1; i < num_glyphs; i++)
       if (glyphs[i - 1] + 1 != glyphs[i]) {
 	range++;
 	rangeRecord[range].start = glyphs[i];
 	rangeRecord[range].value.set (i);
         rangeRecord[range].end = glyphs[i];
       } else {
         rangeRecord[range].end = glyphs[i];
       }
     glyphs.advance (num_glyphs);
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (rangeRecord.sanitize (c));
+    return_trace (rangeRecord.sanitize (c));
   }
 
   inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
     unsigned int i;
     unsigned int count = rangeRecord.len;
     for (i = 0; i < count; i++) {
       const RangeRecord &range = rangeRecord[i];
       if (range.value <= index &&
@@ -859,37 +859,37 @@ struct Coverage
     }
   }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<GlyphID> &glyphs,
 			 unsigned int num_glyphs)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
     unsigned int num_ranges = 1;
     for (unsigned int i = 1; i < num_glyphs; i++)
       if (glyphs[i - 1] + 1 != glyphs[i])
         num_ranges++;
     u.format.set (num_glyphs * 2 < num_ranges * 3 ? 1 : 2);
     switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, num_glyphs));
-    case 2: return TRACE_RETURN (u.format2.serialize (c, glyphs, num_glyphs));
-    default:return TRACE_RETURN (false);
+    case 1: return_trace (u.format1.serialize (c, glyphs, num_glyphs));
+    case 2: return_trace (u.format2.serialize (c, glyphs, num_glyphs));
+    default:return_trace (false);
     }
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
+    if (!u.format.sanitize (c)) return_trace (false);
     switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    case 2: return TRACE_RETURN (u.format2.sanitize (c));
-    default:return TRACE_RETURN (true);
+    case 1: return_trace (u.format1.sanitize (c));
+    case 2: return_trace (u.format2.sanitize (c));
+    default:return_trace (true);
     }
   }
 
   inline bool intersects (const hb_set_t *glyphs) const {
     /* TODO speed this up */
     Coverage::Iter iter;
     for (iter.init (*this); iter.more (); iter.next ()) {
       if (glyphs->has (iter.get_glyph ()))
@@ -988,17 +988,17 @@ struct ClassDefFormat1
     if (unlikely (i < classValue.len))
       return classValue[i];
     return 0;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && classValue.sanitize (c));
+    return_trace (c->check_struct (this) && classValue.sanitize (c));
   }
 
   template <typename set_t>
   inline void add_class (set_t *glyphs, unsigned int klass) const {
     unsigned int count = classValue.len;
     for (unsigned int i = 0; i < count; i++)
       if (classValue[i] == klass)
         glyphs->add (startGlyph + i);
@@ -1045,17 +1045,17 @@ struct ClassDefFormat2
     if (unlikely (i != -1))
       return rangeRecord[i].value;
     return 0;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (rangeRecord.sanitize (c));
+    return_trace (rangeRecord.sanitize (c));
   }
 
   template <typename set_t>
   inline void add_class (set_t *glyphs, unsigned int klass) const {
     unsigned int count = rangeRecord.len;
     for (unsigned int i = 0; i < count; i++)
       if (rangeRecord[i].value == klass)
         rangeRecord[i].add_coverage (glyphs);
@@ -1103,21 +1103,21 @@ struct ClassDef
     case 2: return u.format2.get_class(glyph_id);
     default:return 0;
     }
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
+    if (!u.format.sanitize (c)) return_trace (false);
     switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    case 2: return TRACE_RETURN (u.format2.sanitize (c));
-    default:return TRACE_RETURN (true);
+    case 1: return_trace (u.format1.sanitize (c));
+    case 2: return_trace (u.format2.sanitize (c));
+    default:return_trace (true);
     }
   }
 
   inline void add_class (hb_set_t *glyphs, unsigned int klass) const {
     switch (u.format) {
     case 1: u.format1.add_class (glyphs, klass); return;
     case 2: u.format2.add_class (glyphs, klass); return;
     default:return;
@@ -1196,17 +1196,17 @@ struct Device
     unsigned int f = deltaFormat;
     if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::static_size;
     return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f)));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && c->check_range (this, this->get_size ()));
+    return_trace (c->check_struct (this) && c->check_range (this, this->get_size ()));
   }
 
   protected:
   USHORT	startSize;		/* Smallest size to correct--in ppem */
   USHORT	endSize;		/* Largest size to correct--in ppem */
   USHORT	deltaFormat;		/* Format of DeltaValue array data: 1, 2, or 3
 					 * 1	Signed 2-bit value, 8 values per uint16
 					 * 2	Signed 4-bit value, 4 values per uint16
--- a/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh
@@ -69,17 +69,17 @@ struct AttachList
     }
 
     return points.len;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (coverage.sanitize (c, this) && attachPoint.sanitize (c, this));
+    return_trace (coverage.sanitize (c, this) && attachPoint.sanitize (c, this));
   }
 
   protected:
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table -- from
 					 * beginning of AttachList table */
   OffsetArrayOf<AttachPoint>
 		attachPoint;		/* Array of AttachPoint tables
@@ -100,17 +100,17 @@ struct CaretValueFormat1
   inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const
   {
     return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this));
+    return_trace (c->check_struct (this));
   }
 
   protected:
   USHORT	caretValueFormat;	/* Format identifier--format = 1 */
   SHORT		coordinate;		/* X or Y value, in design units */
   public:
   DEFINE_SIZE_STATIC (4);
 };
@@ -127,17 +127,17 @@ struct CaretValueFormat2
       return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
     else
       return 0;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this));
+    return_trace (c->check_struct (this));
   }
 
   protected:
   USHORT	caretValueFormat;	/* Format identifier--format = 2 */
   USHORT	caretValuePoint;	/* Contour point index on glyph */
   public:
   DEFINE_SIZE_STATIC (4);
 };
@@ -151,17 +151,17 @@ struct CaretValueFormat3
     return HB_DIRECTION_IS_HORIZONTAL (direction) ?
            font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font) :
            font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && deviceTable.sanitize (c, this));
+    return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
   }
 
   protected:
   USHORT	caretValueFormat;	/* Format identifier--format = 3 */
   SHORT		coordinate;		/* X or Y value, in design units */
   OffsetTo<Device>
 		deviceTable;		/* Offset to Device table for X or Y
 					 * value--from beginning of CaretValue
@@ -180,22 +180,22 @@ struct CaretValue
     case 3: return u.format3.get_caret_value (font, direction, glyph_id);
     default:return 0;
     }
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
+    if (!u.format.sanitize (c)) return_trace (false);
     switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    case 2: return TRACE_RETURN (u.format2.sanitize (c));
-    case 3: return TRACE_RETURN (u.format3.sanitize (c));
-    default:return TRACE_RETURN (true);
+    case 1: return_trace (u.format1.sanitize (c));
+    case 2: return_trace (u.format2.sanitize (c));
+    case 3: return_trace (u.format3.sanitize (c));
+    default:return_trace (true);
     }
   }
 
   protected:
   union {
   USHORT		format;		/* Format identifier */
   CaretValueFormat1	format1;
   CaretValueFormat2	format2;
@@ -222,17 +222,17 @@ struct LigGlyph
     }
 
     return carets.len;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (carets.sanitize (c, this));
+    return_trace (carets.sanitize (c, this));
   }
 
   protected:
   OffsetArrayOf<CaretValue>
 		carets;			/* Offset array of CaretValue tables
 					 * --from beginning of LigGlyph table
 					 * --in increasing coordinate order */
   public:
@@ -257,17 +257,17 @@ struct LigCaretList
     }
     const LigGlyph &lig_glyph = this+ligGlyph[index];
     return lig_glyph.get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this));
+    return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this));
   }
 
   protected:
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of LigCaretList table */
   OffsetArrayOf<LigGlyph>
 		ligGlyph;		/* Array of LigGlyph tables
@@ -280,17 +280,17 @@ struct LigCaretList
 struct MarkGlyphSetsFormat1
 {
   inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
   { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (coverage.sanitize (c, this));
+    return_trace (coverage.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   ArrayOf<OffsetTo<Coverage, ULONG> >
 		coverage;		/* Array of long offsets to mark set
 					 * coverage tables */
   public:
@@ -305,20 +305,20 @@ struct MarkGlyphSets
     case 1: return u.format1.covers (set_index, glyph_id);
     default:return false;
     }
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
+    if (!u.format.sanitize (c)) return_trace (false);
     switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    default:return TRACE_RETURN (true);
+    case 1: return_trace (u.format1.sanitize (c));
+    default:return_trace (true);
     }
   }
 
   protected:
   union {
   USHORT		format;		/* Format identifier */
   MarkGlyphSetsFormat1	format1;
   } u;
@@ -371,23 +371,23 @@ struct GDEF
 
   inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef[0] != 0; }
   inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
   { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (version.sanitize (c) &&
-			 likely (version.major == 1) &&
-			 glyphClassDef.sanitize (c, this) &&
-			 attachList.sanitize (c, this) &&
-			 ligCaretList.sanitize (c, this) &&
-			 markAttachClassDef.sanitize (c, this) &&
-			 (version.to_int () < 0x00010002u || markGlyphSetsDef[0].sanitize (c, this)));
+    return_trace (version.sanitize (c) &&
+		  likely (version.major == 1) &&
+		  glyphClassDef.sanitize (c, this) &&
+		  attachList.sanitize (c, this) &&
+		  ligCaretList.sanitize (c, this) &&
+		  markAttachClassDef.sanitize (c, this) &&
+		  (version.to_int () < 0x00010002u || markGlyphSetsDef[0].sanitize (c, this)));
   }
 
 
   /* 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
   {
--- a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
@@ -176,68 +176,68 @@ struct ValueFormat : USHORT
   inline bool has_device (void) const {
     unsigned int format = *this;
     return (format & devices) != 0;
   }
 
   inline bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
+    return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
   }
 
   inline bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
   {
     TRACE_SANITIZE (this);
     unsigned int len = get_len ();
 
-    if (!c->check_array (values, get_size (), count)) return TRACE_RETURN (false);
+    if (!c->check_array (values, get_size (), count)) return_trace (false);
 
-    if (!has_device ()) return TRACE_RETURN (true);
+    if (!has_device ()) return_trace (true);
 
     for (unsigned int i = 0; i < count; i++) {
       if (!sanitize_value_devices (c, base, values))
-        return TRACE_RETURN (false);
+        return_trace (false);
       values += len;
     }
 
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   /* Just sanitize referenced Device tables.  Doesn't check the values themselves. */
   inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
   {
     TRACE_SANITIZE (this);
 
-    if (!has_device ()) return TRACE_RETURN (true);
+    if (!has_device ()) return_trace (true);
 
     for (unsigned int i = 0; i < count; i++) {
       if (!sanitize_value_devices (c, base, values))
-        return TRACE_RETURN (false);
+        return_trace (false);
       values += stride;
     }
 
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 };
 
 
 struct AnchorFormat1
 {
   inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
 			  hb_position_t *x, hb_position_t *y) const
   {
       *x = font->em_scale_x (xCoordinate);
       *y = font->em_scale_y (yCoordinate);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this));
+    return_trace (c->check_struct (this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   SHORT		xCoordinate;		/* Horizontal value--in design units */
   SHORT		yCoordinate;		/* Vertical value--in design units */
   public:
   DEFINE_SIZE_STATIC (6);
@@ -257,17 +257,17 @@ struct AnchorFormat2
              font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
       *x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate);
       *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this));
+    return_trace (c->check_struct (this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 2 */
   SHORT		xCoordinate;		/* Horizontal value--in design units */
   SHORT		yCoordinate;		/* Vertical value--in design units */
   USHORT	anchorPoint;		/* Index to glyph contour point */
   public:
@@ -286,17 +286,17 @@ struct AnchorFormat3
 	*x += (this+xDeviceTable).get_x_delta (font);
       if (font->y_ppem)
 	*y += (this+yDeviceTable).get_x_delta (font);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
+    return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 3 */
   SHORT		xCoordinate;		/* Horizontal value--in design units */
   SHORT		yCoordinate;		/* Vertical value--in design units */
   OffsetTo<Device>
 		xDeviceTable;		/* Offset to Device table for X
@@ -322,22 +322,22 @@ struct Anchor
     case 3: u.format3.get_anchor (font, glyph_id, x, y); return;
     default:						 return;
     }
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
+    if (!u.format.sanitize (c)) return_trace (false);
     switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.sanitize (c));
-    case 2: return TRACE_RETURN (u.format2.sanitize (c));
-    case 3: return TRACE_RETURN (u.format3.sanitize (c));
-    default:return TRACE_RETURN (true);
+    case 1: return_trace (u.format1.sanitize (c));
+    case 2: return_trace (u.format2.sanitize (c));
+    case 3: return_trace (u.format3.sanitize (c));
+    default:return_trace (true);
     }
   }
 
   protected:
   union {
   USHORT		format;		/* Format identifier */
   AnchorFormat1		format1;
   AnchorFormat2		format2;
@@ -355,23 +355,23 @@ struct AnchorMatrix
     if (unlikely (row >= rows || col >= cols)) return Null(Anchor);
     *found = !matrixZ[row * cols + col].is_null ();
     return this+matrixZ[row * cols + col];
   }
 
   inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
   {
     TRACE_SANITIZE (this);
-    if (!c->check_struct (this)) return TRACE_RETURN (false);
-    if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return TRACE_RETURN (false);
+    if (!c->check_struct (this)) return_trace (false);
+    if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return_trace (false);
     unsigned int count = rows * cols;
-    if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return TRACE_RETURN (false);
+    if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return_trace (false);
     for (unsigned int i = 0; i < count; i++)
-      if (!matrixZ[i].sanitize (c, this)) return TRACE_RETURN (false);
-    return TRACE_RETURN (true);
+      if (!matrixZ[i].sanitize (c, this)) return_trace (false);
+    return_trace (true);
   }
 
   USHORT	rows;			/* Number of rows */
   protected:
   OffsetTo<Anchor>
 		matrixZ[VAR];		/* Matrix of offsets to Anchor tables--
 					 * from beginning of AnchorMatrix table */
   public:
@@ -381,17 +381,17 @@ struct AnchorMatrix
 
 struct MarkRecord
 {
   friend struct MarkArray;
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && markAnchor.sanitize (c, base));
+    return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
   }
 
   protected:
   USHORT	klass;			/* Class defined for this mark */
   OffsetTo<Anchor>
 		markAnchor;		/* Offset to Anchor table--from
 					 * beginning of MarkArray table */
   public:
@@ -410,36 +410,36 @@ struct MarkArray : ArrayOf<MarkRecord>	/
     const MarkRecord &record = ArrayOf<MarkRecord>::operator[](mark_index);
     unsigned int mark_class = record.klass;
 
     const Anchor& mark_anchor = this + record.markAnchor;
     bool found;
     const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found);
     /* If this subtable doesn't have an anchor for this base and this class,
      * return false such that the subsequent subtables have a chance at it. */
-    if (unlikely (!found)) return TRACE_RETURN (false);
+    if (unlikely (!found)) return_trace (false);
 
     hb_position_t mark_x, mark_y, base_x, base_y;
 
     mark_anchor.get_anchor (c->font, buffer->cur().codepoint, &mark_x, &mark_y);
     glyph_anchor.get_anchor (c->font, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
 
     hb_glyph_position_t &o = buffer->cur_pos();
     o.x_offset = base_x - mark_x;
     o.y_offset = base_y - mark_y;
     o.attach_lookback() = buffer->idx - glyph_pos;
 
     buffer->idx++;
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (ArrayOf<MarkRecord>::sanitize (c, this));
+    return_trace (ArrayOf<MarkRecord>::sanitize (c, this));
   }
 };
 
 
 /* Lookups */
 
 struct SinglePosFormat1
 {
@@ -454,31 +454,31 @@ struct SinglePosFormat1
     return this+coverage;
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
+    if (likely (index == NOT_COVERED)) return_trace (false);
 
     valueFormat.apply_value (c->font, c->direction, this,
 			     values, buffer->cur_pos());
 
     buffer->idx++;
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this)
-        && coverage.sanitize (c, this)
-	&& valueFormat.sanitize_value (c, this, values));
+    return_trace (c->check_struct (this) &&
+		  coverage.sanitize (c, this) &&
+		  valueFormat.sanitize_value (c, this, values));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
   ValueFormat	valueFormat;		/* Defines the types of data in the
@@ -503,34 +503,34 @@ struct SinglePosFormat2
     return this+coverage;
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
+    if (likely (index == NOT_COVERED)) return_trace (false);
 
-    if (likely (index >= valueCount)) return TRACE_RETURN (false);
+    if (likely (index >= valueCount)) return_trace (false);
 
     valueFormat.apply_value (c->font, c->direction, this,
 			     &values[index * valueFormat.get_len ()],
 			     buffer->cur_pos());
 
     buffer->idx++;
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this)
-	&& coverage.sanitize (c, this)
-	&& valueFormat.sanitize_values (c, this, values, valueCount));
+    return_trace (c->check_struct (this) &&
+		  coverage.sanitize (c, this) &&
+		  valueFormat.sanitize_values (c, this, values, valueCount));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 2 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
   ValueFormat	valueFormat;		/* Defines the types of data in the
@@ -543,21 +543,21 @@ struct SinglePosFormat2
 };
 
 struct SinglePos
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return TRACE_RETURN (c->dispatch (u.format1));
-    case 2: return TRACE_RETURN (c->dispatch (u.format2));
-    default:return TRACE_RETURN (c->default_return_value ());
+    case 1: return_trace (c->dispatch (u.format1));
+    case 2: return_trace (c->dispatch (u.format2));
+    default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
   USHORT		format;		/* Format identifier */
   SinglePosFormat1	format1;
   SinglePosFormat2	format2;
@@ -610,17 +610,17 @@ struct PairSet
     unsigned int len2 = valueFormats[1].get_len ();
     unsigned int record_size = USHORT::static_size * (1 + len1 + len2);
 
     const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ);
     unsigned int count = len;
 
     /* Hand-coded bsearch. */
     if (unlikely (!count))
-      return TRACE_RETURN (false);
+      return_trace (false);
     hb_codepoint_t x = buffer->info[pos].codepoint;
     int min = 0, max = (int) count - 1;
     while (min <= max)
     {
       int mid = (min + max) / 2;
       const PairValueRecord *record = &StructAtOffset<PairValueRecord> (record_array, record_size * mid);
       hb_codepoint_t mid_x = record->secondGlyph;
       if (x < mid_x)
@@ -631,40 +631,40 @@ struct PairSet
       {
 	valueFormats[0].apply_value (c->font, c->direction, this,
 				     &record->values[0], buffer->cur_pos());
 	valueFormats[1].apply_value (c->font, c->direction, this,
 				     &record->values[len1], buffer->pos[pos]);
 	if (len2)
 	  pos++;
 	buffer->idx = pos;
-	return TRACE_RETURN (true);
+	return_trace (true);
       }
     }
 
-    return TRACE_RETURN (false);
+    return_trace (false);
   }
 
   struct sanitize_closure_t {
     const void *base;
     const ValueFormat *valueFormats;
     unsigned int len1; /* valueFormats[0].get_len() */
     unsigned int stride; /* 1 + len1 + len2 */
   };
 
   inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
   {
     TRACE_SANITIZE (this);
     if (!(c->check_struct (this)
-       && c->check_array (arrayZ, USHORT::static_size * closure->stride, len))) return TRACE_RETURN (false);
+       && c->check_array (arrayZ, USHORT::static_size * closure->stride, len))) return_trace (false);
 
     unsigned int count = len;
     const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
-    return TRACE_RETURN (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride)
-		      && closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
+    return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride) &&
+		  closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
   }
 
   protected:
   USHORT	len;			/* Number of PairValueRecords */
   USHORT	arrayZ[VAR];		/* Array of PairValueRecords--ordered
 					 * by GlyphID of the second glyph */
   public:
   DEFINE_SIZE_ARRAY (2, arrayZ);
@@ -686,39 +686,41 @@ struct PairPosFormat1
     return this+coverage;
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
+    if (likely (index == NOT_COVERED)) return_trace (false);
 
     hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
-    if (!skippy_iter.next ()) return TRACE_RETURN (false);
+    if (!skippy_iter.next ()) return_trace (false);
 
-    return TRACE_RETURN ((this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx));
+    return_trace ((this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
 
+    if (!c->check_struct (this)) return_trace (false);
+
     unsigned int len1 = valueFormat1.get_len ();
     unsigned int len2 = valueFormat2.get_len ();
     PairSet::sanitize_closure_t closure = {
       this,
       &valueFormat1,
       len1,
       1 + len1 + len2
     };
 
-    return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
+    return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
   ValueFormat	valueFormat1;		/* Defines the types of data in
@@ -757,59 +759,59 @@ struct PairPosFormat2
     return this+coverage;
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
+    if (likely (index == NOT_COVERED)) return_trace (false);
 
     hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
-    if (!skippy_iter.next ()) return TRACE_RETURN (false);
+    if (!skippy_iter.next ()) return_trace (false);
 
     unsigned int len1 = valueFormat1.get_len ();
     unsigned int len2 = valueFormat2.get_len ();
     unsigned int record_len = len1 + len2;
 
     unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
     unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
-    if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return TRACE_RETURN (false);
+    if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false);
 
     const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
     valueFormat1.apply_value (c->font, c->direction, this,
 			      v, buffer->cur_pos());
     valueFormat2.apply_value (c->font, c->direction, this,
 			      v + len1, buffer->pos[skippy_iter.idx]);
 
     buffer->idx = skippy_iter.idx;
     if (len2)
       buffer->idx++;
 
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!(c->check_struct (this)
        && coverage.sanitize (c, this)
        && classDef1.sanitize (c, this)
-       && classDef2.sanitize (c, this))) return TRACE_RETURN (false);
+       && classDef2.sanitize (c, this))) return_trace (false);
 
     unsigned int len1 = valueFormat1.get_len ();
     unsigned int len2 = valueFormat2.get_len ();
     unsigned int stride = len1 + len2;
     unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
     unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
-    return TRACE_RETURN (c->check_array (values, record_size, count) &&
-			 valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
-			 valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
+    return_trace (c->check_array (values, record_size, count) &&
+		  valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
+		  valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 2 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
   ValueFormat	valueFormat1;		/* ValueRecord definition--for the
@@ -838,21 +840,21 @@ struct PairPosFormat2
 };
 
 struct PairPos
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return TRACE_RETURN (c->dispatch (u.format1));
-    case 2: return TRACE_RETURN (c->dispatch (u.format2));
-    default:return TRACE_RETURN (c->default_return_value ());
+    case 1: return_trace (c->dispatch (u.format1));
+    case 2: return_trace (c->dispatch (u.format2));
+    default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
   USHORT		format;		/* Format identifier */
   PairPosFormat1	format1;
   PairPosFormat2	format2;
@@ -862,17 +864,17 @@ struct PairPos
 
 struct EntryExitRecord
 {
   friend struct CursivePosFormat1;
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
+    return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
   }
 
   protected:
   OffsetTo<Anchor>
 		entryAnchor;		/* Offset to EntryAnchor table--from
 					 * beginning of CursivePos
 					 * subtable--may be NULL */
   OffsetTo<Anchor>
@@ -900,27 +902,27 @@ struct CursivePosFormat1
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
 
     /* We don't handle mark glyphs here. */
-    if (unlikely (_hb_glyph_info_is_mark (&buffer->cur()))) return TRACE_RETURN (false);
+    if (unlikely (_hb_glyph_info_is_mark (&buffer->cur()))) return_trace (false);
 
     const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage  (buffer->cur().codepoint)];
-    if (!this_record.exitAnchor) return TRACE_RETURN (false);
+    if (!this_record.exitAnchor) return_trace (false);
 
     hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
-    if (!skippy_iter.next ()) return TRACE_RETURN (false);
+    if (!skippy_iter.next ()) return_trace (false);
 
     const EntryExitRecord &next_record = entryExitRecord[(this+coverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint)];
-    if (!next_record.entryAnchor) return TRACE_RETURN (false);
+    if (!next_record.entryAnchor) return_trace (false);
 
     unsigned int i = buffer->idx;
     unsigned int j = skippy_iter.idx;
 
     hb_position_t entry_x, entry_y, exit_x, exit_y;
     (this+this_record.exitAnchor).get_anchor (c->font, buffer->info[i].codepoint, &exit_x, &exit_y);
     (this+next_record.entryAnchor).get_anchor (c->font, buffer->info[j].codepoint, &entry_x, &entry_y);
 
@@ -992,23 +994,23 @@ struct CursivePosFormat1
 
     pos[child].cursive_chain() = parent - child;
     if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
       pos[child].y_offset = y_offset;
     else
       pos[child].x_offset = x_offset;
 
     buffer->idx = j;
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
+    return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
   ArrayOf<EntryExitRecord>
@@ -1019,20 +1021,20 @@ struct CursivePosFormat1
 };
 
 struct CursivePos
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return TRACE_RETURN (c->dispatch (u.format1));
-    default:return TRACE_RETURN (c->default_return_value ());
+    case 1: return_trace (c->dispatch (u.format1));
+    default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
   USHORT		format;		/* Format identifier */
   CursivePosFormat1	format1;
   } u;
@@ -1058,43 +1060,46 @@ struct MarkBasePosFormat1
     return this+markCoverage;
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
     unsigned int mark_index = (this+markCoverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false);
+    if (likely (mark_index == NOT_COVERED)) return_trace (false);
 
     /* now we search backwards for a non-mark glyph */
     hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
     skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
     do {
-      if (!skippy_iter.prev ()) return TRACE_RETURN (false);
+      if (!skippy_iter.prev ()) return_trace (false);
       /* We only want to attach to the first of a MultipleSubst sequence.  Reject others. */
       if (0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx])) break;
       skippy_iter.reject ();
     } while (1);
 
     /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
-    if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { /*return TRACE_RETURN (false);*/ }
+    if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { /*return_trace (false);*/ }
 
     unsigned int base_index = (this+baseCoverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint);
-    if (base_index == NOT_COVERED) return TRACE_RETURN (false);
+    if (base_index == NOT_COVERED) return_trace (false);
 
-    return TRACE_RETURN ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
+    return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, this) && baseCoverage.sanitize (c, this) &&
-			 markArray.sanitize (c, this) && baseArray.sanitize (c, this, (unsigned int) classCount));
+    return_trace (c->check_struct (this) &&
+		  markCoverage.sanitize (c, this) &&
+		  baseCoverage.sanitize (c, this) &&
+		  markArray.sanitize (c, this) &&
+		  baseArray.sanitize (c, this, (unsigned int) classCount));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		markCoverage;		/* Offset to MarkCoverage table--from
 					 * beginning of MarkBasePos subtable */
   OffsetTo<Coverage>
@@ -1112,20 +1117,20 @@ struct MarkBasePosFormat1
 };
 
 struct MarkBasePos
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return TRACE_RETURN (c->dispatch (u.format1));
-    default:return TRACE_RETURN (c->default_return_value ());
+    case 1: return_trace (c->dispatch (u.format1));
+    default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
   USHORT		format;		/* Format identifier */
   MarkBasePosFormat1	format1;
   } u;
@@ -1156,59 +1161,62 @@ struct MarkLigPosFormat1
     return this+markCoverage;
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
     unsigned int mark_index = (this+markCoverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false);
+    if (likely (mark_index == NOT_COVERED)) return_trace (false);
 
     /* now we search backwards for a non-mark glyph */
     hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
     skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
-    if (!skippy_iter.prev ()) return TRACE_RETURN (false);
+    if (!skippy_iter.prev ()) return_trace (false);
 
     /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
-    if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { /*return TRACE_RETURN (false);*/ }
+    if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { /*return_trace (false);*/ }
 
     unsigned int j = skippy_iter.idx;
     unsigned int lig_index = (this+ligatureCoverage).get_coverage  (buffer->info[j].codepoint);
-    if (lig_index == NOT_COVERED) return TRACE_RETURN (false);
+    if (lig_index == NOT_COVERED) return_trace (false);
 
     const LigatureArray& lig_array = this+ligatureArray;
     const LigatureAttach& lig_attach = lig_array[lig_index];
 
     /* Find component to attach to */
     unsigned int comp_count = lig_attach.rows;
-    if (unlikely (!comp_count)) return TRACE_RETURN (false);
+    if (unlikely (!comp_count)) return_trace (false);
 
     /* We must now check whether the ligature ID of the current mark glyph
      * is identical to the ligature ID of the found ligature.  If yes, we
      * can directly use the component index.  If not, we attach the mark
      * glyph to the last component of the ligature. */
     unsigned int comp_index;
     unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[j]);
     unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
     unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
     if (lig_id && lig_id == mark_id && mark_comp > 0)
       comp_index = MIN (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
     else
       comp_index = comp_count - 1;
 
-    return TRACE_RETURN ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
+    return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, this) && ligatureCoverage.sanitize (c, this) &&
-			 markArray.sanitize (c, this) && ligatureArray.sanitize (c, this, (unsigned int) classCount));
+    return_trace (c->check_struct (this) &&
+		  markCoverage.sanitize (c, this) &&
+		  ligatureCoverage.sanitize (c, this) &&
+		  markArray.sanitize (c, this) &&
+		  ligatureArray.sanitize (c, this, (unsigned int) classCount));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		markCoverage;		/* Offset to Mark Coverage table--from
 					 * beginning of MarkLigPos subtable */
   OffsetTo<Coverage>
@@ -1227,20 +1235,20 @@ struct MarkLigPosFormat1
 };
 
 struct MarkLigPos
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return TRACE_RETURN (c->dispatch (u.format1));
-    default:return TRACE_RETURN (c->default_return_value ());
+    case 1: return_trace (c->dispatch (u.format1));
+    default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
   USHORT		format;		/* Format identifier */
   MarkLigPosFormat1	format1;
   } u;
@@ -1266,25 +1274,25 @@ struct MarkMarkPosFormat1
     return this+mark1Coverage;
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
     unsigned int mark1_index = (this+mark1Coverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (mark1_index == NOT_COVERED)) return TRACE_RETURN (false);
+    if (likely (mark1_index == NOT_COVERED)) return_trace (false);
 
     /* now we search backwards for a suitable mark glyph until a non-mark glyph */
     hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
     skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags);
-    if (!skippy_iter.prev ()) return TRACE_RETURN (false);
+    if (!skippy_iter.prev ()) return_trace (false);
 
-    if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) { return TRACE_RETURN (false); }
+    if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) { return_trace (false); }
 
     unsigned int j = skippy_iter.idx;
 
     unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur());
     unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]);
     unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur());
     unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]);
 
@@ -1296,31 +1304,33 @@ struct MarkMarkPosFormat1
     } else {
       /* If ligature ids don't match, it may be the case that one of the marks
        * itself is a ligature.  In which case match. */
       if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2))
 	goto good;
     }
 
     /* Didn't match. */
-    return TRACE_RETURN (false);
+    return_trace (false);
 
     good:
     unsigned int mark2_index = (this+mark2Coverage).get_coverage  (buffer->info[j].codepoint);
-    if (mark2_index == NOT_COVERED) return TRACE_RETURN (false);
+    if (mark2_index == NOT_COVERED) return_trace (false);
 
-    return TRACE_RETURN ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
+    return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && mark1Coverage.sanitize (c, this) &&
-			 mark2Coverage.sanitize (c, this) && mark1Array.sanitize (c, this)
-			 && mark2Array.sanitize (c, this, (unsigned int) classCount));
+    return_trace (c->check_struct (this) &&
+		  mark1Coverage.sanitize (c, this) &&
+		  mark2Coverage.sanitize (c, this) &&
+		  mark1Array.sanitize (c, this) &&
+		  mark2Array.sanitize (c, this, (unsigned int) classCount));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		mark1Coverage;		/* Offset to Combining Mark1 Coverage
 					 * table--from beginning of MarkMarkPos
 					 * subtable */
@@ -1340,20 +1350,20 @@ struct MarkMarkPosFormat1
 };
 
 struct MarkMarkPos
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return TRACE_RETURN (c->dispatch (u.format1));
-    default:return TRACE_RETURN (c->default_return_value ());
+    case 1: return_trace (c->dispatch (u.format1));
+    default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
   USHORT		format;		/* Format identifier */
   MarkMarkPosFormat1	format1;
   } u;
@@ -1391,29 +1401,28 @@ struct PosLookupSubTable
     ChainContext	= 8,
     Extension		= 9
   };
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
   {
     TRACE_DISPATCH (this, lookup_type);
-    /* The sub_format passed to may_dispatch is unnecessary but harmless. */
-    if (unlikely (!c->may_dispatch (this, &u.sub_format))) TRACE_RETURN (c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace (c->no_dispatch_return_value ());
     switch (lookup_type) {
-    case Single:		return TRACE_RETURN (u.single.dispatch (c));
-    case Pair:			return TRACE_RETURN (u.pair.dispatch (c));
-    case Cursive:		return TRACE_RETURN (u.cursive.dispatch (c));
-    case MarkBase:		return TRACE_RETURN (u.markBase.dispatch (c));
-    case MarkLig:		return TRACE_RETURN (u.markLig.dispatch (c));
-    case MarkMark:		return TRACE_RETURN (u.markMark.dispatch (c));
-    case Context:		return TRACE_RETURN (u.context.dispatch (c));
-    case ChainContext:		return TRACE_RETURN (u.chainContext.dispatch (c));
-    case Extension:		return TRACE_RETURN (u.extension.dispatch (c));
-    default:			return TRACE_RETURN (c->default_return_value ());
+    case Single:		return_trace (u.single.dispatch (c));
+    case Pair:			return_trace (u.pair.dispatch (c));
+    case Cursive:		return_trace (u.cursive.dispatch (c));
+    case MarkBase:		return_trace (u.markBase.dispatch (c));
+    case MarkLig:		return_trace (u.markLig.dispatch (c));
+    case MarkMark:		return_trace (u.markMark.dispatch (c));
+    case Context:		return_trace (u.context.dispatch (c));
+    case ChainContext:		return_trace (u.chainContext.dispatch (c));
+    case Extension:		return_trace (u.extension.dispatch (c));
+    default:			return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
   USHORT		sub_format;
   SinglePos		single;
   PairPos		pair;
@@ -1438,23 +1447,23 @@ struct PosLookup : Lookup
   inline bool is_reverse (void) const
   {
     return false;
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    return TRACE_RETURN (dispatch (c));
+    return_trace (dispatch (c));
   }
 
   inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
-    return TRACE_RETURN (dispatch (c));
+    return_trace (dispatch (c));
   }
 
   template <typename set_t>
   inline void add_coverage (set_t *glyphs) const
   {
     hb_add_coverage_context_t<set_t> c (glyphs);
     dispatch (&c);
   }
@@ -1466,18 +1475,18 @@ struct PosLookup : Lookup
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   { return Lookup::dispatch<PosLookupSubTable> (c); }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false);
-    return TRACE_RETURN (dispatch (c));
+    if (unlikely (!Lookup::sanitize (c))) return_trace (false);
+    return_trace (dispatch (c));
   }
 };
 
 typedef OffsetListOf<PosLookup> PosLookupList;
 
 /*
  * GPOS -- The Glyph Positioning Table
  */
@@ -1490,19 +1499,19 @@ struct GPOS : GSUBGPOS
   { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); }
 
   static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
   static inline void position_finish (hb_font_t *font, hb_buffer_t *buffer);
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false);
+    if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false);
     const OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList);
-    return TRACE_RETURN (list.sanitize (c, this));
+    return_trace (list.sanitize (c, this));
   }
   public:
   DEFINE_SIZE_STATIC (10);
 };
 
 
 static void
 reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent)
--- a/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh
@@ -62,50 +62,50 @@ struct SingleSubstFormat1
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
   }
 
   inline bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
-    return TRACE_RETURN (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
+    return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     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);
+    if (likely (index == NOT_COVERED)) return_trace (false);
 
     /* According to the Adobe Annotated OpenType Suite, result is always
      * limited to 16bit. */
     glyph_id = (glyph_id + deltaGlyphID) & 0xFFFFu;
     c->replace_glyph (glyph_id);
 
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<GlyphID> &glyphs,
 			 unsigned int num_glyphs,
 			 int delta)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
     deltaGlyphID.set (delta); /* TODO(serilaize) overflow? */
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
+    return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
   SHORT		deltaGlyphID;		/* Add to original GlyphID to get
@@ -139,50 +139,50 @@ struct SingleSubstFormat2
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
   }
 
   inline bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
-    return TRACE_RETURN (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
+    return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     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);
+    if (likely (index == NOT_COVERED)) return_trace (false);
 
-    if (unlikely (index >= substitute.len)) return TRACE_RETURN (false);
+    if (unlikely (index >= substitute.len)) return_trace (false);
 
     glyph_id = substitute[index];
     c->replace_glyph (glyph_id);
 
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<GlyphID> &glyphs,
 			 Supplier<GlyphID> &substitutes,
 			 unsigned int num_glyphs)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
-    if (unlikely (!substitute.serialize (c, substitutes, num_glyphs))) return TRACE_RETURN (false);
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
-    return TRACE_RETURN (true);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (unlikely (!substitute.serialize (c, substitutes, num_glyphs))) return_trace (false);
+    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
+    return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (coverage.sanitize (c, this) && substitute.sanitize (c));
+    return_trace (coverage.sanitize (c, this) && substitute.sanitize (c));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 2 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
   ArrayOf<GlyphID>
@@ -195,46 +195,46 @@ struct SingleSubstFormat2
 struct SingleSubst
 {
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<GlyphID> &glyphs,
 			 Supplier<GlyphID> &substitutes,
 			 unsigned int num_glyphs)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend_min (u.format))) return_trace (false);
     unsigned int format = 2;
     int delta = 0;
     if (num_glyphs) {
       format = 1;
       /* TODO(serialize) check for wrap-around */
       delta = substitutes[0] - glyphs[0];
       for (unsigned int i = 1; i < num_glyphs; i++)
 	if (delta != substitutes[i] - glyphs[i]) {
 	  format = 2;
 	  break;
 	}
     }
     u.format.set (format);
     switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, num_glyphs, delta));
-    case 2: return TRACE_RETURN (u.format2.serialize (c, glyphs, substitutes, num_glyphs));
-    default:return TRACE_RETURN (false);
+    case 1: return_trace (u.format1.serialize (c, glyphs, num_glyphs, delta));
+    case 2: return_trace (u.format2.serialize (c, glyphs, substitutes, num_glyphs));
+    default:return_trace (false);
     }
   }
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return TRACE_RETURN (c->dispatch (u.format1));
-    case 2: return TRACE_RETURN (c->dispatch (u.format2));
-    default:return TRACE_RETURN (c->default_return_value ());
+    case 1: return_trace (c->dispatch (u.format1));
+    case 2: return_trace (c->dispatch (u.format2));
+    default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
   USHORT		format;		/* Format identifier */
   SingleSubstFormat1	format1;
   SingleSubstFormat2	format2;
@@ -268,52 +268,52 @@ struct Sequence
     /* 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);
+    if (unlikely (!count)) return_trace (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);
+      return_trace (true);
     }
 
     unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
 			 HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 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);
     }
     c->buffer->skip_glyph ();
 
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<GlyphID> &glyphs,
 			 unsigned int num_glyphs)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
-    if (unlikely (!substitute.serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
-    return TRACE_RETURN (true);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (unlikely (!substitute.serialize (c, glyphs, num_glyphs))) return_trace (false);
+    return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (substitute.sanitize (c));
+    return_trace (substitute.sanitize (c));
   }
 
   protected:
   ArrayOf<GlyphID>
 		substitute;		/* String of GlyphIDs to substitute */
   public:
   DEFINE_SIZE_ARRAY (2, substitute);
 };
@@ -342,51 +342,51 @@ struct MultipleSubstFormat1
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
   }
 
   inline bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
-    return TRACE_RETURN (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
+    return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
+    if (likely (index == NOT_COVERED)) return_trace (false);
 
-    return TRACE_RETURN ((this+sequence[index]).apply (c));
+    return_trace ((this+sequence[index]).apply (c));
   }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<GlyphID> &glyphs,
 			 Supplier<unsigned int> &substitute_len_list,
 			 unsigned int num_glyphs,
 			 Supplier<GlyphID> &substitute_glyphs_list)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
-    if (unlikely (!sequence.serialize (c, num_glyphs))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (unlikely (!sequence.serialize (c, num_glyphs))) return_trace (false);
     for (unsigned int i = 0; i < num_glyphs; i++)
       if (unlikely (!sequence[i].serialize (c, this).serialize (c,
 								substitute_glyphs_list,
-								substitute_len_list[i]))) return TRACE_RETURN (false);
+								substitute_len_list[i]))) return_trace (false);
     substitute_len_list.advance (num_glyphs);
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
-    return TRACE_RETURN (true);
+    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
+    return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (coverage.sanitize (c, this) && sequence.sanitize (c, this));
+    return_trace (coverage.sanitize (c, this) && sequence.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
   OffsetArrayOf<Sequence>
@@ -400,33 +400,33 @@ struct MultipleSubst
 {
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<GlyphID> &glyphs,
 			 Supplier<unsigned int> &substitute_len_list,
 			 unsigned int num_glyphs,
 			 Supplier<GlyphID> &substitute_glyphs_list)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend_min (u.format))) return_trace (false);
     unsigned int format = 1;
     u.format.set (format);
     switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, substitute_len_list, num_glyphs, substitute_glyphs_list));
-    default:return TRACE_RETURN (false);
+    case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, num_glyphs, substitute_glyphs_list));
+    default:return_trace (false);
     }
   }
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return TRACE_RETURN (c->dispatch (u.format1));
-    default:return TRACE_RETURN (c->default_return_value ());
+    case 1: return_trace (c->dispatch (u.format1));
+    default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
   USHORT		format;		/* Format identifier */
   MultipleSubstFormat1	format1;
   } u;
@@ -468,69 +468,69 @@ struct AlternateSubstFormat1
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
   }
 
   inline bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
-    return TRACE_RETURN (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
+    return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     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);
+    if (likely (index == NOT_COVERED)) return_trace (false);
 
     const AlternateSet &alt_set = this+alternateSet[index];
 
-    if (unlikely (!alt_set.len)) return TRACE_RETURN (false);
+    if (unlikely (!alt_set.len)) return_trace (false);
 
     hb_mask_t glyph_mask = c->buffer->cur().mask;
     hb_mask_t lookup_mask = c->lookup_mask;
 
     /* Note: This breaks badly if two features enabled this lookup together. */
     unsigned int shift = _hb_ctz (lookup_mask);
     unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
 
-    if (unlikely (alt_index > alt_set.len || alt_index == 0)) return TRACE_RETURN (false);
+    if (unlikely (alt_index > alt_set.len || alt_index == 0)) return_trace (false);
 
     glyph_id = alt_set[alt_index - 1];
 
     c->replace_glyph (glyph_id);
 
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<GlyphID> &glyphs,
 			 Supplier<unsigned int> &alternate_len_list,
 			 unsigned int num_glyphs,
 			 Supplier<GlyphID> &alternate_glyphs_list)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
-    if (unlikely (!alternateSet.serialize (c, num_glyphs))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (unlikely (!alternateSet.serialize (c, num_glyphs))) return_trace (false);
     for (unsigned int i = 0; i < num_glyphs; i++)
       if (unlikely (!alternateSet[i].serialize (c, this).serialize (c,
 								    alternate_glyphs_list,
-								    alternate_len_list[i]))) return TRACE_RETURN (false);
+								    alternate_len_list[i]))) return_trace (false);
     alternate_len_list.advance (num_glyphs);
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
-    return TRACE_RETURN (true);
+    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
+    return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
+    return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
   OffsetArrayOf<AlternateSet>
@@ -544,33 +544,33 @@ struct AlternateSubst
 {
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<GlyphID> &glyphs,
 			 Supplier<unsigned int> &alternate_len_list,
 			 unsigned int num_glyphs,
 			 Supplier<GlyphID> &alternate_glyphs_list)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend_min (u.format))) return_trace (false);
     unsigned int format = 1;
     u.format.set (format);
     switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, alternate_len_list, num_glyphs, alternate_glyphs_list));
-    default:return TRACE_RETURN (false);
+    case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, num_glyphs, alternate_glyphs_list));
+    default:return_trace (false);
     }
   }
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return TRACE_RETURN (c->dispatch (u.format1));
-    default:return TRACE_RETURN (c->default_return_value ());
+    case 1: return_trace (c->dispatch (u.format1));
+    default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
   USHORT		format;		/* Format identifier */
   AlternateSubstFormat1	format1;
   } u;
@@ -597,84 +597,84 @@ struct Ligature
       c->input->add (component[i]);
     c->output->add (ligGlyph);
   }
 
   inline bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     if (c->len != component.len)
-      return TRACE_RETURN (false);
+      return_trace (false);
 
     for (unsigned int i = 1; i < c->len; i++)
       if (likely (c->glyphs[i] != component[i]))
-	return TRACE_RETURN (false);
+	return_trace (false);
 
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int count = component.len;
 
-    if (unlikely (!count)) return TRACE_RETURN (false);
+    if (unlikely (!count)) return_trace (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);
+      return_trace (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,
 			      &component[1],
 			      match_glyph,
 			      NULL,
 			      &match_length,
 			      match_positions,
 			      &is_mark_ligature,
 			      &total_component_count)))
-      return TRACE_RETURN (false);
+      return_trace (false);
 
     ligate_input (c,
 		  count,
 		  match_positions,
 		  match_length,
 		  ligGlyph,
 		  is_mark_ligature,
 		  total_component_count);
 
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 GlyphID ligature,
 			 Supplier<GlyphID> &components, /* Starting from second */
 			 unsigned int num_components /* Including first component */)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
     ligGlyph = ligature;
-    if (unlikely (!component.serialize (c, components, num_components))) return TRACE_RETURN (false);
-    return TRACE_RETURN (true);
+    if (unlikely (!component.serialize (c, components, num_components))) return_trace (false);
+    return_trace (true);
   }
 
   public:
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (ligGlyph.sanitize (c) && component.sanitize (c));
+    return_trace (ligGlyph.sanitize (c) && component.sanitize (c));
   }
 
   protected:
   GlyphID	ligGlyph;		/* GlyphID of ligature to substitute */
   HeadlessArrayOf<GlyphID>
 		component;		/* Array of component GlyphIDs--start
 					 * with the second  component--ordered
 					 * in writing direction */
@@ -703,57 +703,57 @@ struct LigatureSet
   inline bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     unsigned int num_ligs = ligature.len;
     for (unsigned int i = 0; i < num_ligs; i++)
     {
       const Ligature &lig = this+ligature[i];
       if (lig.would_apply (c))
-        return TRACE_RETURN (true);
+        return_trace (true);
     }
-    return TRACE_RETURN (false);
+    return_trace (false);
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int num_ligs = ligature.len;
     for (unsigned int i = 0; i < num_ligs; i++)
     {
       const Ligature &lig = this+ligature[i];
-      if (lig.apply (c)) return TRACE_RETURN (true);
+      if (lig.apply (c)) return_trace (true);
     }
 
-    return TRACE_RETURN (false);
+    return_trace (false);
   }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<GlyphID> &ligatures,
 			 Supplier<unsigned int> &component_count_list,
 			 unsigned int num_ligatures,
 			 Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
-    if (unlikely (!ligature.serialize (c, num_ligatures))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (unlikely (!ligature.serialize (c, num_ligatures))) return_trace (false);
     for (unsigned int i = 0; i < num_ligatures; i++)
       if (unlikely (!ligature[i].serialize (c, this).serialize (c,
 								ligatures[i],
 								component_list,
-								component_count_list[i]))) return TRACE_RETURN (false);
+								component_count_list[i]))) return_trace (false);
     ligatures.advance (num_ligatures);
     component_count_list.advance (num_ligatures);
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (ligature.sanitize (c, this));
+    return_trace (ligature.sanitize (c, this));
   }
 
   protected:
   OffsetArrayOf<Ligature>
 		ligature;		/* Array LigatureSet tables
 					 * ordered by preference */
   public:
   DEFINE_SIZE_ARRAY (2, ligature);
@@ -785,60 +785,60 @@ struct LigatureSubstFormat1
   {
     return this+coverage;
   }
 
   inline bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     unsigned int index = (this+coverage).get_coverage (c->glyphs[0]);
-    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
+    if (likely (index == NOT_COVERED)) return_trace (false);
 
     const LigatureSet &lig_set = this+ligatureSet[index];
-    return TRACE_RETURN (lig_set.would_apply (c));
+    return_trace (lig_set.would_apply (c));
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     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);
+    if (likely (index == NOT_COVERED)) return_trace (false);
 
     const LigatureSet &lig_set = this+ligatureSet[index];
-    return TRACE_RETURN (lig_set.apply (c));
+    return_trace (lig_set.apply (c));
   }
 
   inline bool serialize (hb_serialize_context_t *c,
 			 Supplier<GlyphID> &first_glyphs,
 			 Supplier<unsigned int> &ligature_per_first_glyph_count_list,
 			 unsigned int num_first_glyphs,
 			 Supplier<GlyphID> &ligatures_list,
 			 Supplier<unsigned int> &component_count_list,
 			 Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
-    if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return_trace (false);
     for (unsigned int i = 0; i < num_first_glyphs; i++)
       if (unlikely (!ligatureSet[i].serialize (c, this).serialize (c,
 								   ligatures_list,
 								   component_count_list,
 								   ligature_per_first_glyph_count_list[i],
-								   component_list))) return TRACE_RETURN (false);
+								   component_list))) return_trace (false);
     ligature_per_first_glyph_count_list.advance (num_first_glyphs);
-    if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_first_glyphs))) return TRACE_RETURN (false);
-    return TRACE_RETURN (true);
+    if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_first_glyphs))) return_trace (false);
+    return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
+    return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
   OffsetArrayOf<LigatureSet>
@@ -854,34 +854,39 @@ struct LigatureSubst
 			 Supplier<GlyphID> &first_glyphs,
 			 Supplier<unsigned int> &ligature_per_first_glyph_count_list,
 			 unsigned int num_first_glyphs,
 			 Supplier<GlyphID> &ligatures_list,
 			 Supplier<unsigned int> &component_count_list,
 			 Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
+    if (unlikely (!c->extend_min (u.format))) return_trace (false);
     unsigned int format = 1;
     u.format.set (format);
     switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.serialize (c, first_glyphs, ligature_per_first_glyph_count_list, num_first_glyphs,
-						      ligatures_list, component_count_list, component_list));
-    default:return TRACE_RETURN (false);
+    case 1: return_trace (u.format1.serialize (c,
+					       first_glyphs,
+					       ligature_per_first_glyph_count_list,
+					       num_first_glyphs,
+					       ligatures_list,
+					       component_count_list,
+					       component_list));
+    default:return_trace (false);
     }
   }
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return TRACE_RETURN (c->dispatch (u.format1));
-    default:return TRACE_RETURN (c->default_return_value ());
+    case 1: return_trace (c->dispatch (u.format1));
+    default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
   USHORT		format;		/* Format identifier */
   LigatureSubstFormat1	format1;
   } u;
@@ -954,59 +959,59 @@ struct ReverseChainSingleSubstFormat1
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
   }
 
   inline bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
-    return TRACE_RETURN (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
+    return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     if (unlikely (c->nesting_level_left != MAX_NESTING_LEVEL))
-      return TRACE_RETURN (false); /* No chaining to this type */
+      return_trace (false); /* No chaining to this type */
 
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
+    if (likely (index == NOT_COVERED)) return_trace (false);
 
     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
     const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
 
     if (match_backtrack (c,
 			 backtrack.len, (USHORT *) backtrack.array,
 			 match_coverage, this) &&
         match_lookahead (c,
 			 lookahead.len, (USHORT *) lookahead.array,
 			 match_coverage, this,
 			 1))
     {
       c->replace_glyph_inplace (substitute[index]);
       /* Note: We DON'T decrease buffer->idx.  The main loop does it
        * for us.  This is useful for preventing surprises if someone
        * calls us through a Context lookup. */
-      return TRACE_RETURN (true);
+      return_trace (true);
     }
 
-    return TRACE_RETURN (false);
+    return_trace (false);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
-      return TRACE_RETURN (false);
+      return_trace (false);
     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
     if (!lookahead.sanitize (c, this))
-      return TRACE_RETURN (false);
+      return_trace (false);
     const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
-    return TRACE_RETURN (substitute.sanitize (c));
+    return_trace (substitute.sanitize (c));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
   OffsetArrayOf<Coverage>
@@ -1025,20 +1030,20 @@ struct ReverseChainSingleSubstFormat1
 };
 
 struct ReverseChainSingleSubst
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return TRACE_RETURN (c->dispatch (u.format1));
-    default:return TRACE_RETURN (c->default_return_value ());
+    case 1: return_trace (c->dispatch (u.format1));
+    default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
   USHORT				format;		/* Format identifier */
   ReverseChainSingleSubstFormat1	format1;
   } u;
@@ -1064,28 +1069,27 @@ struct SubstLookupSubTable
     Extension		= 7,
     ReverseChainSingle	= 8
   };
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
   {
     TRACE_DISPATCH (this, lookup_type);
-    /* The sub_format passed to may_dispatch is unnecessary but harmless. */
-    if (unlikely (!c->may_dispatch (this, &u.sub_format))) TRACE_RETURN (c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace (c->no_dispatch_return_value ());
     switch (lookup_type) {
-    case Single:		return TRACE_RETURN (u.single.dispatch (c));
-    case Multiple:		return TRACE_RETURN (u.multiple.dispatch (c));
-    case Alternate:		return TRACE_RETURN (u.alternate.dispatch (c));
-    case Ligature:		return TRACE_RETURN (u.ligature.dispatch (c));
-    case Context:		return TRACE_RETURN (u.context.dispatch (c));
-    case ChainContext:		return TRACE_RETURN (u.chainContext.dispatch (c));
-    case Extension:		return TRACE_RETURN (u.extension.dispatch (c));
-    case ReverseChainSingle:	return TRACE_RETURN (u.reverseChainContextSingle.dispatch (c));
-    default:			return TRACE_RETURN (c->default_return_value ());
+    case Single:		return_trace (u.single.dispatch (c));
+    case Multiple:		return_trace (u.multiple.dispatch (c));
+    case Alternate:		return_trace (u.alternate.dispatch (c));
+    case Ligature:		return_trace (u.ligature.dispatch (c));
+    case Context:		return_trace (u.context.dispatch (c));
+    case ChainContext:		return_trace (u.chainContext.dispatch (c));
+    case Extension:		return_trace (u.extension.dispatch (c));
+    case ReverseChainSingle:	return_trace (u.reverseChainContextSingle.dispatch (c));
+    default:			return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
   USHORT			sub_format;
   SingleSubst			single;
   MultipleSubst			multiple;
@@ -1115,132 +1119,143 @@ struct SubstLookup : Lookup
     if (unlikely (type == SubstLookupSubTable::Extension))
       return CastR<ExtensionSubst> (get_subtable(0)).is_reverse ();
     return lookup_type_is_reverse (type);
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    return TRACE_RETURN (dispatch (c));
+    return_trace (dispatch (c));
   }
 
   inline hb_closure_context_t::return_t closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
     c->set_recurse_func (dispatch_recurse_func<hb_closure_context_t>);
-    return TRACE_RETURN (dispatch (c));
+    return_trace (dispatch (c));
   }
 
   inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
     c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
-    return TRACE_RETURN (dispatch (c));
+    return_trace (dispatch (c));
   }
 
   template <typename set_t>
   inline void add_coverage (set_t *glyphs) const
   {
     hb_add_coverage_context_t<set_t> c (glyphs);
     dispatch (&c);
   }
 
   inline bool would_apply (hb_would_apply_context_t *c,
 			   const hb_ot_layout_lookup_accelerator_t *accel) const
   {
     TRACE_WOULD_APPLY (this);
-    if (unlikely (!c->len))  return TRACE_RETURN (false);
-    if (!accel->may_have (c->glyphs[0]))  return TRACE_RETURN (false);
-      return TRACE_RETURN (dispatch (c));
+    if (unlikely (!c->len))  return_trace (false);
+    if (!accel->may_have (c->glyphs[0]))  return_trace (false);
+      return_trace (dispatch (c));
   }
 
   static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index);
 
   inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c,
 						  unsigned int i)
   { return get_subtables<SubstLookupSubTable> ()[i].serialize (c, this); }
 
   inline bool serialize_single (hb_serialize_context_t *c,
 				uint32_t lookup_props,
 			        Supplier<GlyphID> &glyphs,
 			        Supplier<GlyphID> &substitutes,
 			        unsigned int num_glyphs)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Single, lookup_props, 1))) return TRACE_RETURN (false);
-    return TRACE_RETURN (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes, num_glyphs));
+    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Single, lookup_props, 1))) return_trace (false);
+    return_trace (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes, num_glyphs));
   }
 
   inline bool serialize_multiple (hb_serialize_context_t *c,
 				  uint32_t lookup_props,
 				  Supplier<GlyphID> &glyphs,
 				  Supplier<unsigned int> &substitute_len_list,
 				  unsigned int num_glyphs,
 				  Supplier<GlyphID> &substitute_glyphs_list)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Multiple, lookup_props, 1))) return TRACE_RETURN (false);
-    return TRACE_RETURN (serialize_subtable (c, 0).u.multiple.serialize (c, glyphs, substitute_len_list, num_glyphs,
-									 substitute_glyphs_list));
+    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Multiple, lookup_props, 1))) return_trace (false);
+    return_trace (serialize_subtable (c, 0).u.multiple.serialize (c,
+								  glyphs,
+								  substitute_len_list,
+								  num_glyphs,
+								  substitute_glyphs_list));
   }
 
   inline bool serialize_alternate (hb_serialize_context_t *c,
 				   uint32_t lookup_props,
 				   Supplier<GlyphID> &glyphs,
 				   Supplier<unsigned int> &alternate_len_list,
 				   unsigned int num_glyphs,
 				   Supplier<GlyphID> &alternate_glyphs_list)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Alternate, lookup_props, 1))) return TRACE_RETURN (false);
-    return TRACE_RETURN (serialize_subtable (c, 0).u.alternate.serialize (c, glyphs, alternate_len_list, num_glyphs,
-									  alternate_glyphs_list));
+    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Alternate, lookup_props, 1))) return_trace (false);
+    return_trace (serialize_subtable (c, 0).u.alternate.serialize (c,
+								   glyphs,
+								   alternate_len_list,
+								   num_glyphs,
+								   alternate_glyphs_list));
   }
 
   inline bool serialize_ligature (hb_serialize_context_t *c,
 				  uint32_t lookup_props,
 				  Supplier<GlyphID> &first_glyphs,
 				  Supplier<unsigned int> &ligature_per_first_glyph_count_list,
 				  unsigned int num_first_glyphs,
 				  Supplier<GlyphID> &ligatures_list,
 				  Supplier<unsigned int> &component_count_list,
 				  Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Ligature, lookup_props, 1))) return TRACE_RETURN (false);
-    return TRACE_RETURN (serialize_subtable (c, 0).u.ligature.serialize (c, first_glyphs, ligature_per_first_glyph_count_list, num_first_glyphs,
-									 ligatures_list, component_count_list, component_list));
+    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Ligature, lookup_props, 1))) return_trace (false);
+    return_trace (serialize_subtable (c, 0).u.ligature.serialize (c,
+								  first_glyphs,
+								  ligature_per_first_glyph_count_list,
+								  num_first_glyphs,
+								  ligatures_list,
+								  component_count_list,
+								  component_list));
   }
 
   template <typename context_t>
   static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   { return Lookup::dispatch<SubstLookupSubTable> (c); }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false);
-    if (unlikely (!dispatch (c))) return TRACE_RETURN (false);
+    if (unlikely (!Lookup::sanitize (c))) return_trace (false);
+    if (unlikely (!dispatch (c))) return_trace (false);
 
     if (unlikely (get_type () == SubstLookupSubTable::Extension))
     {
       /* The spec says all subtables of an Extension lookup should
        * have the same type.  This is specially important if one has
        * a reverse type! */
       unsigned int type = get_subtable (0).u.extension.get_type ();
       unsigned int count = get_subtable_count ();
       for (unsigned int i = 1; i < count; i++)
         if (get_subtable (i).u.extension.get_type () != type)
-	  return TRACE_RETURN (false);
+	  return_trace (false);
     }
-    return TRACE_RETURN (true);
+    return_trace (true);
   }
 };
 
 typedef OffsetListOf<SubstLookup> SubstLookupList;
 
 /*
  * GSUB -- The Glyph Substitution Table
  */
@@ -1253,19 +1268,19 @@ struct GSUB : GSUBGPOS
   { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
 
   static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer);
   static inline void substitute_finish (hb_font_t *font, hb_buffer_t *buffer);
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false);
+    if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false);
     const OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupList);
-    return TRACE_RETURN (list.sanitize (c, this));
+    return_trace (list.sanitize (c, this));
   }
   public:
   DEFINE_SIZE_STATIC (10);
 };
 
 
 void
 GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer)
--- a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh
@@ -41,24 +41,21 @@ namespace OT {
 #define HB_DEBUG_CLOSURE (HB_DEBUG+0)
 #endif
 
 #define TRACE_CLOSURE(this) \
 	hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
 	 "");
 
-struct hb_closure_context_t
+struct hb_closure_context_t :
+       hb_dispatch_context_t<hb_closure_context_t, hb_void_t, HB_DEBUG_CLOSURE>
 {
   inline const char *get_name (void) { return "CLOSURE"; }
-  static const unsigned int max_debug_depth = HB_DEBUG_CLOSURE;
-  typedef hb_void_t return_t;
   typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format) { return true; }
   template <typename T>
   inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
   static return_t default_return_value (void) { return HB_VOID; }
   bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
   return_t recurse (unsigned int lookup_index)
   {
     if (unlikely (nesting_level_left == 0 || !recurse_func))
       return default_return_value ();
@@ -93,23 +90,20 @@ struct hb_closure_context_t
 #define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
 #endif
 
 #define TRACE_WOULD_APPLY(this) \
 	hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
 	 "%d glyphs", c->len);
 
-struct hb_would_apply_context_t
+struct hb_would_apply_context_t :
+       hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY>
 {
   inline const char *get_name (void) { return "WOULD_APPLY"; }
-  static const unsigned int max_debug_depth = HB_DEBUG_WOULD_APPLY;
-  typedef bool return_t;
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format) { return true; }
   template <typename T>
   inline return_t dispatch (const T &obj) { return obj.would_apply (this); }
   static return_t default_return_value (void) { return false; }
   bool stop_sublookup_iteration (return_t r) const { return r; }
 
   hb_face_t *face;
   const hb_codepoint_t *glyphs;
   unsigned int len;
@@ -133,24 +127,21 @@ struct hb_would_apply_context_t
 #define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0)
 #endif
 
 #define TRACE_COLLECT_GLYPHS(this) \
 	hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, hb_void_t> trace \
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
 	 "");
 
-struct hb_collect_glyphs_context_t
+struct hb_collect_glyphs_context_t :
+       hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, HB_DEBUG_COLLECT_GLYPHS>
 {
   inline const char *get_name (void) { return "COLLECT_GLYPHS"; }
-  static const unsigned int max_debug_depth = HB_DEBUG_COLLECT_GLYPHS;
-  typedef hb_void_t return_t;
   typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format) { return true; }
   template <typename T>
   inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
   static return_t default_return_value (void) { return HB_VOID; }
   bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
   return_t recurse (unsigned int lookup_index)
   {
     if (unlikely (nesting_level_left == 0 || !recurse_func))
       return default_return_value ();
@@ -227,24 +218,24 @@ struct hb_collect_glyphs_context_t
 };
 
 
 
 #ifndef HB_DEBUG_GET_COVERAGE
 #define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0)
 #endif
 
+/* XXX Can we remove this? */
+
 template <typename set_t>
-struct hb_add_coverage_context_t
+struct hb_add_coverage_context_t :
+       hb_dispatch_context_t<hb_add_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE>
 {
   inline const char *get_name (void) { return "GET_COVERAGE"; }
-  static const unsigned int max_debug_depth = HB_DEBUG_GET_COVERAGE;
   typedef const Coverage &return_t;
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format) { return true; }
   template <typename T>
   inline return_t dispatch (const T &obj) { return obj.get_coverage (); }
   static return_t default_return_value (void) { return Null(Coverage); }
   bool stop_sublookup_iteration (return_t r) const
   {
     r.add_coverage (set);
     return false;
   }
@@ -264,17 +255,18 @@ struct hb_add_coverage_context_t
 #endif
 
 #define TRACE_APPLY(this) \
 	hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
 	 "idx %d gid %u lookup %d", \
 	 c->buffer->idx, c->buffer->cur().codepoint, (int) c->lookup_index);
 
-struct hb_apply_context_t
+struct hb_apply_context_t :
+       hb_dispatch_context_t<hb_apply_context_t, bool, HB_DEBUG_APPLY>
 {
   struct matcher_t
   {
     inline matcher_t (void) :
 	     lookup_props (0),
 	     ignore_zwnj (false),
 	     ignore_zwj (false),
 	     mask (-1),
@@ -444,21 +436,17 @@ struct hb_apply_context_t
     const USHORT *match_glyph_data;
 
     unsigned int num_items;
     unsigned int end;
   };
 
 
   inline const char *get_name (void) { return "APPLY"; }
-  static const unsigned int max_debug_depth = HB_DEBUG_APPLY;
-  typedef bool return_t;
   typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format) { return true; }
   template <typename T>
   inline return_t dispatch (const T &obj) { return obj.apply (this); }
   static return_t default_return_value (void) { return false; }
   bool stop_sublookup_iteration (return_t r) const { return r; }
   return_t recurse (unsigned int lookup_index)
   {
     if (unlikely (nesting_level_left == 0 || !recurse_func))
       return default_return_value ();
@@ -717,17 +705,17 @@ static inline bool match_input (hb_apply
 				const void *match_data,
 				unsigned int *end_offset,
 				unsigned int match_positions[MAX_CONTEXT_LENGTH],
 				bool *p_is_mark_ligature = NULL,
 				unsigned int *p_total_component_count = NULL)
 {
   TRACE_APPLY (NULL);
 
-  if (unlikely (count > MAX_CONTEXT_LENGTH)) return TRACE_RETURN (false);
+  if (unlikely (count > MAX_CONTEXT_LENGTH)) return_trace (false);
 
   hb_buffer_t *buffer = c->buffer;
 
   hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
   skippy_iter.reset (buffer->idx, count - 1);
   skippy_iter.set_match_func (match_func, match_data, input);
 
   /*
@@ -754,52 +742,52 @@ static inline bool match_input (hb_apply
   total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
 
   unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
   unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
 
   match_positions[0] = buffer->idx;
   for (unsigned int i = 1; i < count; i++)
   {
-    if (!skippy_iter.next ()) return TRACE_RETURN (false);
+    if (!skippy_iter.next ()) return_trace (false);
 
     match_positions[i] = skippy_iter.idx;
 
     unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
     unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
 
     if (first_lig_id && first_lig_comp) {
       /* If first component was attached to a previous ligature component,
        * all subsequent components should be attached to the same ligature
        * component, otherwise we shouldn't ligate them. */
       if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
-	return TRACE_RETURN (false);
+	return_trace (false);
     } else {
       /* If first component was NOT attached to a previous ligature component,
        * all subsequent components should also NOT be attached to any ligature
        * component, unless they are attached to the first component itself! */
       if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
-	return TRACE_RETURN (false);
+	return_trace (false);
     }
 
     is_mark_ligature = is_mark_ligature && _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]);
     total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]);
   }
 
   *end_offset = skippy_iter.idx - buffer->idx + 1;
 
   if (p_is_mark_ligature)
     *p_is_mark_ligature = is_mark_ligature;
 
   if (p_total_component_count)
     *p_total_component_count = total_component_count;
 
-  return TRACE_RETURN (true);
+  return_trace (true);
 }
-static inline void ligate_input (hb_apply_context_t *c,
+static inline bool ligate_input (hb_apply_context_t *c,
 				 unsigned int count, /* Including the first glyph */
 				 unsigned int match_positions[MAX_CONTEXT_LENGTH], /* Including the first glyph */
 				 unsigned int match_length,
 				 hb_codepoint_t lig_glyph,
 				 bool is_mark_ligature,
 				 unsigned int total_component_count)
 {
   TRACE_APPLY (NULL);
@@ -879,36 +867,36 @@ 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);
+  return_trace (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)
 {
   TRACE_APPLY (NULL);
 
   hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
   skippy_iter.reset (c->buffer->backtrack_len (), count);
   skippy_iter.set_match_func (match_func, match_data, backtrack);
 
   for (unsigned int i = 0; i < count; i++)
     if (!skippy_iter.prev ())
-      return TRACE_RETURN (false);
+      return_trace (false);
 
-  return TRACE_RETURN (true);
+  return_trace (true);
 }
 
 static inline bool match_lookahead (hb_apply_context_t *c,
 				    unsigned int count,
 				    const USHORT lookahead[],
 				    match_func_t match_func,
 				    const void *match_data,
 				    unsigned int offset)
@@ -916,29 +904,29 @@ static inline bool match_lookahead (hb_a
   TRACE_APPLY (NULL);
 
   hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
   skippy_iter.reset (c->buffer->idx + offset - 1, count);
   skippy_iter.set_match_func (match_func, match_data, lookahead);
 
   for (unsigned int i = 0; i < count; i++)
     if (!skippy_iter.next ())
-      return TRACE_RETURN (false);
+      return_trace (false);
 
-  return TRACE_RETURN (true);
+  return_trace (true);
 }
 
 
 
 struct LookupRecord
 {
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this));
+    return_trace (c->check_struct (this));
   }
 
   USHORT	sequenceIndex;		/* Index into current glyph
 					 * sequence--first glyph = 0 */
   USHORT	lookupListIndex;	/* Lookup to apply to that
 					 * position--zero--based */
   public:
   DEFINE_SIZE_STATIC (4);
@@ -1029,17 +1017,17 @@ static inline bool apply_lookup (hb_appl
 
     /* And fixup the rest. */
     for (; next < count; next++)
       match_positions[next] += delta;
   }
 
   buffer->move_to (end);
 
-  return TRACE_RETURN (true);
+  return_trace (true);
 }
 
 
 
 /* Contextual lookups */
 
 struct ContextClosureLookupContext
 {
@@ -1138,24 +1126,24 @@ struct Rule
 				   lookupCount, lookupRecord,
 				   lookup_context);
   }
 
   inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
   {
     TRACE_WOULD_APPLY (this);
     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    return TRACE_RETURN (context_would_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
+    return_trace (context_would_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
   }
 
   inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
   {
     TRACE_APPLY (this);
     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    return TRACE_RETURN (context_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
+    return_trace (context_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
   }
 
   public:
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return inputCount.sanitize (c)
 	&& lookupCount.sanitize (c)
@@ -1197,37 +1185,37 @@ struct RuleSet
 
   inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
   {
     TRACE_WOULD_APPLY (this);
     unsigned int num_rules = rule.len;
     for (unsigned int i = 0; i < num_rules; i++)
     {
       if ((this+rule[i]).would_apply (c, lookup_context))
-        return TRACE_RETURN (true);
+        return_trace (true);
     }
-    return TRACE_RETURN (false);
+    return_trace (false);
   }
 
   inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
   {
     TRACE_APPLY (this);
     unsigned int num_rules = rule.len;
     for (unsigned int i = 0; i < num_rules; i++)
     {
       if ((this+rule[i]).apply (c, lookup_context))
-        return TRACE_RETURN (true);
+        return_trace (true);
     }
-    return TRACE_RETURN (false);
+    return_trace (false);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (rule.sanitize (c, this));
+    return_trace (rule.sanitize (c, this));
   }
 
   protected:
   OffsetArrayOf<Rule>
 		rule;			/* Array of Rule tables
 					 * ordered by preference */
   public:
   DEFINE_SIZE_ARRAY (2, rule);
@@ -1274,43 +1262,43 @@ struct ContextFormat1
   {
     TRACE_WOULD_APPLY (this);
 
     const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
     struct ContextApplyLookupContext lookup_context = {
       {match_glyph},
       NULL
     };
-    return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
+    return_trace (rule_set.would_apply (c, lookup_context));
   }
 
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
     if (likely (index == NOT_COVERED))
-      return TRACE_RETURN (false);
+      return_trace (false);
 
     const RuleSet &rule_set = this+ruleSet[index];
     struct ContextApplyLookupContext lookup_context = {
       {match_glyph},
       NULL
     };
-    return TRACE_RETURN (rule_set.apply (c, lookup_context));
+    return_trace (rule_set.apply (c, lookup_context));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
+    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
   OffsetArrayOf<RuleSet>
@@ -1366,44 +1354,44 @@ struct ContextFormat2
 
     const ClassDef &class_def = this+classDef;
     unsigned int index = class_def.get_class (c->glyphs[0]);
     const RuleSet &rule_set = this+ruleSet[index];
     struct ContextApplyLookupContext lookup_context = {
       {match_class},
       &class_def
     };
-    return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
+    return_trace (rule_set.would_apply (c, lookup_context));
   }
 
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
+    if (likely (index == NOT_COVERED)) return_trace (false);
 
     const ClassDef &class_def = this+classDef;
     index = class_def.get_class (c->buffer->cur().codepoint);
     const RuleSet &rule_set = this+ruleSet[index];
     struct ContextApplyLookupContext lookup_context = {
       {match_class},
       &class_def
     };
-    return TRACE_RETURN (rule_set.apply (c, lookup_context));
+    return_trace (rule_set.apply (c, lookup_context));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
+    return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 2 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
   OffsetTo<ClassDef>
@@ -1457,49 +1445,49 @@ struct ContextFormat3
   {
     TRACE_WOULD_APPLY (this);
 
     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
     struct ContextApplyLookupContext lookup_context = {
       {match_coverage},
       this
     };
-    return TRACE_RETURN (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
+    return_trace (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
   }
 
   inline const Coverage &get_coverage (void) const
   {
     return this+coverageZ[0];
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
+    if (likely (index == NOT_COVERED)) return_trace (false);
 
     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
     struct ContextApplyLookupContext lookup_context = {
       {match_coverage},
       this
     };
-    return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
+    return_trace (context_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!c->check_struct (this)) return TRACE_RETURN (false);
+    if (!c->check_struct (this)) return_trace (false);
     unsigned int count = glyphCount;
-    if (!count) return TRACE_RETURN (false); /* We want to access coverageZ[0] freely. */
-    if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return TRACE_RETURN (false);
+    if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */
+    if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return_trace (false);
     for (unsigned int i = 0; i < count; i++)
-      if (!coverageZ[i].sanitize (c, this)) return TRACE_RETURN (false);
+      if (!coverageZ[i].sanitize (c, this)) return_trace (false);
     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count);
-    return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
+    return_trace (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 3 */
   USHORT	glyphCount;		/* Number of glyphs in the input glyph
 					 * sequence */
   USHORT	lookupCount;		/* Number of LookupRecords */
   OffsetTo<Coverage>
@@ -1512,22 +1500,22 @@ struct ContextFormat3
 };
 
 struct Context
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return TRACE_RETURN (c->dispatch (u.format1));
-    case 2: return TRACE_RETURN (c->dispatch (u.format2));
-    case 3: return TRACE_RETURN (c->dispatch (u.format3));
-    default:return TRACE_RETURN (c->default_return_value ());
+    case 1: return_trace (c->dispatch (u.format1));
+    case 2: return_trace (c->dispatch (u.format2));
+    case 3: return_trace (c->dispatch (u.format3));
+    default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
   USHORT		format;		/* Format identifier */
   ContextFormat1	format1;
   ContextFormat2	format2;
@@ -1682,46 +1670,46 @@ struct ChainRule
   }
 
   inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
   {
     TRACE_WOULD_APPLY (this);
     const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
     const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return TRACE_RETURN (chain_context_would_apply_lookup (c,
-							   backtrack.len, backtrack.array,
-							   input.len, input.array,
-							   lookahead.len, lookahead.array, lookup.len,
-							   lookup.array, lookup_context));
+    return_trace (chain_context_would_apply_lookup (c,
+						    backtrack.len, backtrack.array,
+						    input.len, input.array,
+						    lookahead.len, lookahead.array, lookup.len,
+						    lookup.array, lookup_context));
   }
 
   inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
   {
     TRACE_APPLY (this);
     const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
     const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return TRACE_RETURN (chain_context_apply_lookup (c,
-						     backtrack.len, backtrack.array,
-						     input.len, input.array,
-						     lookahead.len, lookahead.array, lookup.len,
-						     lookup.array, lookup_context));
+    return_trace (chain_context_apply_lookup (c,
+					      backtrack.len, backtrack.array,
+					      input.len, input.array,
+					      lookahead.len, lookahead.array, lookup.len,
+					      lookup.array, lookup_context));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!backtrack.sanitize (c)) return TRACE_RETURN (false);
+    if (!backtrack.sanitize (c)) return_trace (false);
     const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
-    if (!input.sanitize (c)) return TRACE_RETURN (false);
+    if (!input.sanitize (c)) return_trace (false);
     const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
-    if (!lookahead.sanitize (c)) return TRACE_RETURN (false);
+    if (!lookahead.sanitize (c)) return_trace (false);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return TRACE_RETURN (lookup.sanitize (c));
+    return_trace (lookup.sanitize (c));
   }
 
   protected:
   ArrayOf<USHORT>
 		backtrack;		/* Array of backtracking values
 					 * (to be matched before the input
 					 * sequence) */
   HeadlessArrayOf<USHORT>
@@ -1756,36 +1744,36 @@ struct ChainRuleSet
   }
 
   inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
   {
     TRACE_WOULD_APPLY (this);
     unsigned int num_rules = rule.len;
     for (unsigned int i = 0; i < num_rules; i++)
       if ((this+rule[i]).would_apply (c, lookup_context))
-        return TRACE_RETURN (true);
+        return_trace (true);
 
-    return TRACE_RETURN (false);
+    return_trace (false);
   }
 
   inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
   {
     TRACE_APPLY (this);
     unsigned int num_rules = rule.len;
     for (unsigned int i = 0; i < num_rules; i++)
       if ((this+rule[i]).apply (c, lookup_context))
-        return TRACE_RETURN (true);
+        return_trace (true);
 
-    return TRACE_RETURN (false);
+    return_trace (false);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (rule.sanitize (c, this));
+    return_trace (rule.sanitize (c, this));
   }
 
   protected:
   OffsetArrayOf<ChainRule>
 		rule;			/* Array of ChainRule tables
 					 * ordered by preference */
   public:
   DEFINE_SIZE_ARRAY (2, rule);
@@ -1830,42 +1818,42 @@ struct ChainContextFormat1
   {
     TRACE_WOULD_APPLY (this);
 
     const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
     struct ChainContextApplyLookupContext lookup_context = {
       {match_glyph},
       {NULL, NULL, NULL}
     };
-    return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
+    return_trace (rule_set.would_apply (c, lookup_context));
   }
 
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
+    if (likely (index == NOT_COVERED)) return_trace (false);
 
     const ChainRuleSet &rule_set = this+ruleSet[index];
     struct ChainContextApplyLookupContext lookup_context = {
       {match_glyph},
       {NULL, NULL, NULL}
     };
-    return TRACE_RETURN (rule_set.apply (c, lookup_context));
+    return_trace (rule_set.apply (c, lookup_context));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
+    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
   OffsetArrayOf<ChainRuleSet>
@@ -1934,51 +1922,53 @@ struct ChainContextFormat2
     unsigned int index = input_class_def.get_class (c->glyphs[0]);
     const ChainRuleSet &rule_set = this+ruleSet[index];
     struct ChainContextApplyLookupContext lookup_context = {
       {match_class},
       {&backtrack_class_def,
        &input_class_def,
        &lookahead_class_def}
     };
-    return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
+    return_trace (rule_set.would_apply (c, lookup_context));
   }
 
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
+    if (likely (index == NOT_COVERED)) return_trace (false);
 
     const ClassDef &backtrack_class_def = this+backtrackClassDef;
     const ClassDef &input_class_def = this+inputClassDef;
     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
 
     index = input_class_def.get_class (c->buffer->cur().codepoint);
     const ChainRuleSet &rule_set = this+ruleSet[index];
     struct ChainContextApplyLookupContext lookup_context = {
       {match_class},
       {&backtrack_class_def,
        &input_class_def,
        &lookahead_class_def}
     };
-    return TRACE_RETURN (rule_set.apply (c, lookup_context));
+    return_trace (rule_set.apply (c, lookup_context));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (coverage.sanitize (c, this) && backtrackClassDef.sanitize (c, this) &&
-			 inputClassDef.sanitize (c, this) && lookaheadClassDef.sanitize (c, this) &&
-			 ruleSet.sanitize (c, this));
+    return_trace (coverage.sanitize (c, this) &&
+		  backtrackClassDef.sanitize (c, this) &&
+		  inputClassDef.sanitize (c, this) &&
+		  lookaheadClassDef.sanitize (c, this) &&
+		  ruleSet.sanitize (c, this));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 2 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
   OffsetTo<ClassDef>
@@ -2051,61 +2041,61 @@ struct ChainContextFormat3
 
     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     struct ChainContextApplyLookupContext lookup_context = {
       {match_coverage},
       {this, this, this}
     };
-    return TRACE_RETURN (chain_context_would_apply_lookup (c,
-							   backtrack.len, (const USHORT *) backtrack.array,
-							   input.len, (const USHORT *) input.array + 1,
-							   lookahead.len, (const USHORT *) lookahead.array,
-							   lookup.len, lookup.array, lookup_context));
+    return_trace (chain_context_would_apply_lookup (c,
+						    backtrack.len, (const USHORT *) backtrack.array,
+						    input.len, (const USHORT *) input.array + 1,
+						    lookahead.len, (const USHORT *) lookahead.array,
+						    lookup.len, lookup.array, lookup_context));
   }
 
   inline const Coverage &get_coverage (void) const
   {
     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
     return this+input[0];
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
 
     unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
+    if (likely (index == NOT_COVERED)) return_trace (false);
 
     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     struct ChainContextApplyLookupContext lookup_context = {
       {match_coverage},
       {this, this, this}
     };
-    return TRACE_RETURN (chain_context_apply_lookup (c,
-						     backtrack.len, (const USHORT *) backtrack.array,
-						     input.len, (const USHORT *) input.array + 1,
-						     lookahead.len, (const USHORT *) lookahead.array,
-						     lookup.len, lookup.array, lookup_context));
+    return_trace (chain_context_apply_lookup (c,
+					      backtrack.len, (const USHORT *) backtrack.array,
+					      input.len, (const USHORT *) input.array + 1,
+					      lookahead.len, (const USHORT *) lookahead.array,
+					      lookup.len, lookup.array, lookup_context));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false);
+    if (!backtrack.sanitize (c, this)) return_trace (false);
     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    if (!input.sanitize (c, this)) return TRACE_RETURN (false);
-    if (!input.len) return TRACE_RETURN (false); /* To be consistent with Context. */
+    if (!input.sanitize (c, this)) return_trace (false);
+    if (!input.len) return_trace (false); /* To be consistent with Context. */
     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false);
+    if (!lookahead.sanitize (c, this)) return_trace (false);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return TRACE_RETURN (lookup.sanitize (c));
+    return_trace (lookup.sanitize (c));
   }
 
   protected:
   USHORT	format;			/* Format identifier--format = 3 */
   OffsetArrayOf<Coverage>
 		backtrack;		/* Array of coverage tables
 					 * in backtracking sequence, in  glyph
 					 * sequence order */
@@ -2125,22 +2115,22 @@ struct ChainContextFormat3
 };
 
 struct ChainContext
 {
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return TRACE_RETURN (c->dispatch (u.format1));
-    case 2: return TRACE_RETURN (c->dispatch (u.format2));
-    case 3: return TRACE_RETURN (c->dispatch (u.format3));
-    default:return TRACE_RETURN (c->default_return_value ());
+    case 1: return_trace (c->dispatch (u.format1));
+    case 2: return_trace (c->dispatch (u.format2));
+    case 3: return_trace (c->dispatch (u.format3));
+    default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
   USHORT		format;	/* Format identifier */
   ChainContextFormat1	format1;
   ChainContextFormat2	format2;
@@ -2161,25 +2151,25 @@ struct ExtensionFormat1
     if (unlikely (!offset)) return Null(typename T::LookupSubTable);
     return StructAtOffset<typename T::LookupSubTable> (this, offset);
   }
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, format);
-    if (unlikely (!c->may_dispatch (this, this))) TRACE_RETURN (c->default_return_value ());
-    return TRACE_RETURN (get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ()));
+    if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ());
+    return_trace (get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ()));
   }
 
   /* This is called from may_dispatch() above with hb_sanitize_context_t. */
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) && extensionOffset != 0);
+    return_trace (c->check_struct (this) && extensionOffset != 0);
   }
 
   protected:
   USHORT	format;			/* Format identifier. Set to 1. */
   USHORT	extensionLookupType;	/* Lookup type of subtable referenced
 					 * by ExtensionOffset (i.e. the
 					 * extension subtable). */
   ULONG		extensionOffset;	/* Offset to the extension subtable,
@@ -2206,20 +2196,20 @@ struct Extension
     default:return Null(typename T::LookupSubTable);
     }
   }
 
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return TRACE_RETURN (u.format1.dispatch (c));
-    default:return TRACE_RETURN (c->default_return_value ());
+    case 1: return_trace (u.format1.dispatch (c));
+    default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
   USHORT		format;		/* Format identifier */
   ExtensionFormat1<T>	format1;
   } u;
@@ -2264,20 +2254,21 @@ struct GSUBGPOS
   inline unsigned int get_lookup_count (void) const
   { return (this+lookupList).len; }
   inline const Lookup& get_lookup (unsigned int i) const
   { return (this+lookupList)[i]; }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) &&
-			 scriptList.sanitize (c, this) &&
-			 featureList.sanitize (c, this) &&
-			 lookupList.sanitize (c, this));
+    return_trace (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 0x00010000u */
   OffsetTo<ScriptList>
 		scriptList;  	/* ScriptList table */
   OffsetTo<FeatureList>
--- a/gfx/harfbuzz/src/hb-ot-layout-jstf-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-jstf-table.hh
@@ -52,27 +52,27 @@ typedef OffsetListOf<PosLookup> JstfMax;
  * JstfPriority -- Justification Priority Table
  */
 
 struct JstfPriority
 {
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) &&
-			 shrinkageEnableGSUB.sanitize (c, this) &&
-			 shrinkageDisableGSUB.sanitize (c, this) &&
-			 shrinkageEnableGPOS.sanitize (c, this) &&
-			 shrinkageDisableGPOS.sanitize (c, this) &&
-			 shrinkageJstfMax.sanitize (c, this) &&
-			 extensionEnableGSUB.sanitize (c, this) &&
-			 extensionDisableGSUB.sanitize (c, this) &&
-			 extensionEnableGPOS.sanitize (c, this) &&
-			 extensionDisableGPOS.sanitize (c, this) &&
-			 extensionJstfMax.sanitize (c, this));
+    return_trace (c->check_struct (this) &&
+		  shrinkageEnableGSUB.sanitize (c, this) &&
+		  shrinkageDisableGSUB.sanitize (c, this) &&
+		  shrinkageEnableGPOS.sanitize (c, this) &&
+		  shrinkageDisableGPOS.sanitize (c, this) &&
+		  shrinkageJstfMax.sanitize (c, this) &&
+		  extensionEnableGSUB.sanitize (c, this) &&
+		  extensionDisableGSUB.sanitize (c, this) &&
+		  extensionEnableGPOS.sanitize (c, this) &&
+		  extensionDisableGPOS.sanitize (c, this) &&
+		  extensionJstfMax.sanitize (c, this));
   }
 
   protected:
   OffsetTo<JstfModList>
 		shrinkageEnableGSUB;	/* Offset to Shrinkage Enable GSUB
 					 * JstfModList table--from beginning of
 					 * JstfPriority table--may be NULL */
   OffsetTo<JstfModList>
@@ -122,17 +122,17 @@ struct JstfPriority
  */
 
 struct JstfLangSys : OffsetListOf<JstfPriority>
 {
   inline bool sanitize (hb_sanitize_context_t *c,
 			const Record<JstfLangSys>::sanitize_closure_t * = NULL) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (OffsetListOf<JstfPriority>::sanitize (c));
+    return_trace (OffsetListOf<JstfPriority>::sanitize (c));
   }
 };
 
 
 /*
  * ExtenderGlyphs -- Extender Glyph Table
  */
 
@@ -163,19 +163,19 @@ struct JstfScript
 
   inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
   inline const JstfLangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
 
   inline bool sanitize (hb_sanitize_context_t *c,
 			const Record<JstfScript>::sanitize_closure_t * = NULL) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (extenderGlyphs.sanitize (c, this) &&
-			 defaultLangSys.sanitize (c, this) &&
-			 langSys.sanitize (c, this));
+    return_trace (extenderGlyphs.sanitize (c, this) &&
+		  defaultLangSys.sanitize (c, this) &&
+		  langSys.sanitize (c, this));
   }
 
   protected:
   OffsetTo<ExtenderGlyphs>
 		extenderGlyphs;	/* Offset to ExtenderGlyph table--from beginning
 				 * of JstfScript table-may be NULL */
   OffsetTo<JstfLangSys>
 		defaultLangSys;	/* Offset to DefaultJstfLangSys table--from
@@ -207,18 +207,19 @@ struct JSTF
   inline const JstfScript& get_script (unsigned int i) const
   { return this+scriptList[i].offset; }
   inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
   { return scriptList.find_index (tag, index); }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) &&
-			 scriptList.sanitize (c, this));
+    return_trace (version.sanitize (c) &&
+		  likely (version.major == 1) &&
+		  scriptList.sanitize (c, this));
   }
 
   protected:
   FixedVersion	version;	/* Version of the JSTF table--initially set
 				 * to 0x00010000u */
   RecordArrayOf<JstfScript>
 		scriptList;  	/* Array of JstfScripts--listed
 				 * alphabetically by ScriptTag */
--- a/gfx/harfbuzz/src/hb-ot-layout.cc
+++ b/gfx/harfbuzz/src/hb-ot-layout.cc
@@ -23,16 +23,17 @@
  * 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
  * Google Author(s): Behdad Esfahbod
  */
 
+#include "hb-open-type-private.hh"
 #include "hb-ot-layout-private.hh"
 
 #include "hb-ot-layout-gdef-table.hh"
 #include "hb-ot-layout-gsub-table.hh"
 #include "hb-ot-layout-gpos-table.hh"
 #include "hb-ot-layout-jstf-table.hh"
 
 #include "hb-ot-map-private.hh"
@@ -793,17 +794,17 @@ hb_ot_layout_position_start (hb_font_t *
 
 void
 hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer)
 {
   OT::GPOS::position_finish (font, buffer);
 }
 
 /**
- * Since: 0.9.8
+ * Since: 0.9.10
  **/
 hb_bool_t
 hb_ot_layout_get_size_params (hb_face_t    *face,
 			      unsigned int *design_size,       /* OUT.  May be NULL */
 			      unsigned int *subfamily_id,      /* OUT.  May be NULL */
 			      unsigned int *subfamily_name_id, /* OUT.  May be NULL */
 			      unsigned int *range_start,       /* OUT.  May be NULL */
 			      unsigned int *range_end          /* OUT.  May be NULL */)
@@ -920,23 +921,20 @@ apply_backward (OT::hb_apply_context_t *
     /* The reverse lookup doesn't "advance" cursor (for good reason). */
     buffer->idx--;
 
   }
   while ((int) buffer->idx >= 0);
   return ret;
 }
 
-struct hb_apply_forward_context_t
+struct hb_apply_forward_context_t :
+       OT::hb_dispatch_context_t<hb_apply_forward_context_t, bool, HB_DEBUG_APPLY>
 {
   inline const char *get_name (void) { return "APPLY_FWD"; }
-  static const unsigned int max_debug_depth = HB_DEBUG_APPLY;
-  typedef bool return_t;
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format) { return true; }
   template <typename T>
   inline return_t dispatch (const T &obj) { return apply_forward (c, obj, accel); }
   static return_t default_return_value (void) { return false; }
   bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return true; }
 
   hb_apply_forward_context_t (OT::hb_apply_context_t *c_,
 			      const hb_ot_layout_lookup_accelerator_t &accel_) :
 				c (c_),
--- a/gfx/harfbuzz/src/hb-ot-maxp-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-maxp-table.hh
@@ -46,18 +46,19 @@ struct maxp
   inline unsigned int get_num_glyphs (void) const
   {
     return numGlyphs;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) &&
-			 likely (version.major == 1 || (version.major == 0 && version.minor == 0x5000u)));
+    return_trace (c->check_struct (this) &&
+		  likely (version.major == 1 ||
+			  (version.major == 0 && version.minor == 0x5000u)));
   }
 
   /* We only implement version 0.5 as none of the extra fields in version 1.0 are useful. */
   protected:
   FixedVersion	version;		/* Version of the maxp table (0.5 or 1.0),
 					 * 0x00005000u or 0x00010000u. */
   USHORT	numGlyphs;		/* The number of glyphs in the font. */
   public:
--- a/gfx/harfbuzz/src/hb-ot-name-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-name-table.hh
@@ -55,17 +55,17 @@ struct NameRecord
     if (ret) return ret;
     return 0;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     /* We can check from base all the way up to the end of string... */
-    return TRACE_RETURN (c->check_struct (this) && c->check_range ((char *) base, (unsigned int) length + offset));
+    return_trace (c->check_struct (this) && c->check_range ((char *) base, (unsigned int) length + offset));
   }
 
   USHORT	platformID;	/* Platform ID. */
   USHORT	encodingID;	/* Platform-specific encoding ID. */
   USHORT	languageID;	/* Language ID. */
   USHORT	nameID;		/* Name ID. */
   USHORT	length;		/* String length (in bytes). */
   USHORT	offset;		/* String offset from start of storage area (in bytes). */
@@ -102,27 +102,27 @@ struct name
   inline unsigned int get_size (void) const
   { return min_size + count * nameRecord[0].min_size; }
 
   inline bool sanitize_records (hb_sanitize_context_t *c) const {
     TRACE_SANITIZE (this);
     char *string_pool = (char *) this + stringOffset;
     unsigned int _count = count;
     for (unsigned int i = 0; i < _count; i++)
-      if (!nameRecord[i].sanitize (c, string_pool)) return TRACE_RETURN (false);
-    return TRACE_RETURN (true);
+      if (!nameRecord[i].sanitize (c, string_pool)) return_trace (false);
+    return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return TRACE_RETURN (c->check_struct (this) &&
-			 likely (format == 0 || format == 1) &&
-			 c->check_array (nameRecord, nameRecord[0].static_size, count) &&
-			 sanitize_records (c));
+    return_trace (c->check_struct (this) &&
+		  likely (format == 0 || format == 1) &&
+		  c->check_array (nameRecord, nameRecord[0].static_size, count) &&
+		  sanitize_records (c));
   }
 
   /* We only implement format 0 for now. */
   USHORT	format;			/* Format selector (=0/1). */
   USHORT	count;			/* Number of name records. */
   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:
--- a/gfx/harfbuzz/src/hb-ot-shape-normalize.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-normalize.cc
@@ -285,16 +285,18 @@ compare_combining_class (const hb_glyph_
 }
 
 
 void
 _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
 			hb_buffer_t *buffer,
 			hb_font_t *font)
 {
+  if (unlikely (!buffer->len)) return;
+
   _hb_buffer_assert_unicode_vars (buffer);
 
   hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference;
   const hb_ot_shape_normalize_context_t c = {
     plan,
     buffer,
     font,
     buffer->unicode,
--- a/gfx/harfbuzz/src/hb-ot-tag.cc
+++ b/gfx/harfbuzz/src/hb-ot-tag.cc
@@ -728,17 +728,16 @@ static const LangTag ot_languages[] = {
 /*{"krc",	HB_TAG('B','A','L',' ')},*/	/* Balkar */
 /*{"??",	HB_TAG('B','C','R',' ')},*/	/* Bible Cree */
 /*{"zh?",	HB_TAG('C','H','N',' ')},*/	/* Chinese (seen in Microsoft fonts) */
 /*{"acf/gcf?",	HB_TAG('F','A','N',' ')},*/	/* French Antillean */
 /*{"enf?/yrk?",	HB_TAG('F','N','E',' ')},*/	/* Forest Nenets */
 /*{"fuf?",	HB_TAG('F','T','A',' ')},*/	/* Futa */
 /*{"ar-Syrc?",	HB_TAG('G','A','R',' ')},*/	/* Garshuni */
 /*{"cfm/rnl?",	HB_TAG('H','A','L',' ')},*/	/* Halam */
-/*{"fonipa",	HB_TAG('I','P','P','H')},*/	/* Phonetic transcription—IPA conventions */
 /*{"ga-Latg?/Latg?",	HB_TAG('I','R','T',' ')},*/	/* Irish Traditional */
 /*{"krc",	HB_TAG('K','A','R',' ')},*/	/* Karachay */
 /*{"alw?/ktb?",	HB_TAG('K','E','B',' ')},*/	/* Kebena */
 /*{"Geok",	HB_TAG('K','G','E',' ')},*/	/* Khutsuri Georgian */
 /*{"kca",	HB_TAG('K','H','K',' ')},*/	/* Khanty-Kazim */
 /*{"kca",	HB_TAG('K','H','S',' ')},*/	/* Khanty-Shurishkar */
 /*{"kca",	HB_TAG('K','H','V',' ')},*/	/* Khanty-Vakhi */
 /*{"guz?/kqs?/kss?",	HB_TAG('K','I','S',' ')},*/	/* Kisii */
@@ -827,16 +826,24 @@ hb_ot_tag_from_language (hb_language_t l
       tag[i] = TOUPPER (s[i]);
     if (i) {
       for (; i < 4; i++)
 	tag[i] = ' ';
       return HB_TAG_CHAR4 (tag);
     }
   }
 
+  /*
+   * The International Phonetic Alphabet is a variant tag in BCP-47,
+   * which can be applied to any language.
+   */
+  if (strstr (lang_str, "-fonipa")) {
+    return HB_TAG('I','P','P','H');  /* Phonetic transcription—IPA conventions */
+  }
+
   /* Find a language matching in the first component */
   {
     const LangTag *lang_tag;
     lang_tag = (LangTag *) bsearch (lang_str, ot_languages,
 				    ARRAY_LENGTH (ot_languages), sizeof (LangTag),
 				    (hb_compare_func_t) lang_compare_first_component);
     if (lang_tag)
       return lang_tag->tag;
@@ -872,17 +879,17 @@ hb_ot_tag_from_language (hb_language_t l
 
 /**
  * hb_ot_tag_to_language:
  *
  * 
  *
  * Return value: (transfer none):
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_language_t
 hb_ot_tag_to_language (hb_tag_t tag)
 {
   unsigned int i;
 
   if (tag == HB_OT_TAG_DEFAULT_LANGUAGE)
     return NULL;
@@ -896,16 +903,22 @@ hb_ot_tag_to_language (hb_tag_t tag)
     switch (tag) {
       case HB_TAG('Z','H','H',' '): return hb_language_from_string ("zh-hk", -1); /* Hong Kong */
       case HB_TAG('Z','H','S',' '): return hb_language_from_string ("zh-Hans", -1); /* Simplified */
       case HB_TAG('Z','H','T',' '): return hb_language_from_string ("zh-Hant", -1); /* Traditional */
       default: break; /* Fall through */
     }
   }
 
+  /* struct LangTag has only room for 3-letter language tags. */
+  switch (tag) {
+  case HB_TAG('I','P','P','H'):  /* Phonetic transcription—IPA conventions */
+    return hb_language_from_string ("und-fonipa", -1);
+  }
+
   /* Else return a custom language in the form of "x-hbotABCD" */
   {
     unsigned char buf[11] = "x-hbot";
     buf[6] = tag >> 24;
     buf[7] = (tag >> 16) & 0xFF;
     buf[8] = (tag >> 8) & 0xFF;
     buf[9] = tag & 0xFF;
     if (buf[9] == 0x20)
--- a/gfx/harfbuzz/src/hb-private.hh
+++ b/gfx/harfbuzz/src/hb-private.hh
@@ -49,16 +49,33 @@
  * always seen by the compiler (and optimized out in non-debug builds.
  * If including these becomes a problem, we can start thinking about
  * someway around that. */
 #include <stdio.h>
 #include <errno.h>
 #include <stdarg.h>
 
 
+/* Compile-time custom allocator support. */
+
+#if defined(hb_malloc_impl) \
+ && defined(hb_calloc_impl) \
+ && defined(hb_realloc_impl) \
+ && defined(hb_free_impl)
+extern "C" void* hb_malloc_impl(size_t size);
+extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
+extern "C" void* hb_realloc_impl(void *ptr, size_t size);
+extern "C" void  hb_free_impl(void *ptr);
+#define malloc hb_malloc_impl
+#define calloc hb_calloc_impl
+#define realloc hb_realloc_impl
+#define free hb_free_impl
+#endif
+
+
 /* Compiler attributes */
 
 
 #if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
 #define _HB_BOOLEAN_EXPR(expr) ((expr) ? 1 : 0)
 #define likely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 1))
 #define unlikely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 0))
 #else
@@ -735,17 +752,17 @@ struct hb_printer_t<hb_void_t> {
 /*
  * Trace
  */
 
 template <typename T>
 static inline void _hb_warn_no_return (bool returned)
 {
   if (unlikely (!returned)) {
-    fprintf (stderr, "OUCH, returned with no call to TRACE_RETURN.  This is a bug, please report.\n");
+    fprintf (stderr, "OUCH, returned with no call to return_trace().  This is a bug, please report.\n");
   }
 }
 template <>
 /*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
 {}
 
 template <int max_level, typename ret_t>
 struct hb_auto_trace_t {
@@ -770,17 +787,17 @@ struct hb_auto_trace_t {
       _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1, " ");
     }
     if (plevel) --*plevel;
   }
 
   inline ret_t ret (ret_t v, unsigned int line = 0)
   {
     if (unlikely (returned)) {
-      fprintf (stderr, "OUCH, double calls to TRACE_RETURN.  This is a bug, please report.\n");
+      fprintf (stderr, "OUCH, double calls to return_trace().  This is a bug, please report.\n");
       return v;
     }
 
     _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1,
 			      "return %s (line %d)",
 			      hb_printer_t<ret_t>().print (v), line);
     if (plevel) --*plevel;
     plevel = NULL;
@@ -801,17 +818,17 @@ struct hb_auto_trace_t<0, ret_t> {
 				   const void *obj HB_UNUSED,
 				   const char *func HB_UNUSED,
 				   const char *message HB_UNUSED,
 				   ...) {}
 
   inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
 };
 
-#define TRACE_RETURN(RET) trace.ret (RET, __LINE__)
+#define return_trace(RET) return trace.ret (RET, __LINE__)
 
 /* Misc */
 
 template <typename T> class hb_assert_unsigned_t;
 template <> class hb_assert_unsigned_t<unsigned char> {};
 template <> class hb_assert_unsigned_t<unsigned short> {};
 template <> class hb_assert_unsigned_t<unsigned int> {};
 template <> class hb_assert_unsigned_t<unsigned long> {};
--- a/gfx/harfbuzz/src/hb-set.h
+++ b/gfx/harfbuzz/src/hb-set.h
@@ -31,16 +31,19 @@
 #ifndef HB_SET_H
 #define HB_SET_H
 
 #include "hb-common.h"
 
 HB_BEGIN_DECLS
 
 
+/*
+ * Since: 0.9.21
+ */
 #define HB_SET_VALUE_INVALID ((hb_codepoint_t) -1)
 
 typedef struct hb_set_t hb_set_t;
 
 
 hb_set_t *
 hb_set_create (void);
 
--- a/gfx/harfbuzz/src/hb-shape-plan.cc
+++ b/gfx/harfbuzz/src/hb-shape-plan.cc
@@ -123,17 +123,17 @@ hb_shape_plan_create (hb_face_t         
 
   hb_shape_plan_t *shape_plan;
   hb_feature_t *features = NULL;
 
   if (unlikely (!face))
     face = hb_face_get_empty ();
   if (unlikely (!props))
     return hb_shape_plan_get_empty ();
-  if (num_user_features && !(features = (hb_feature_t *) malloc (num_user_features * sizeof (hb_feature_t))))
+  if (num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t))))
     return hb_shape_plan_get_empty ();
   if (!(shape_plan = hb_object_create<hb_shape_plan_t> ())) {
     free (features);
     return hb_shape_plan_get_empty ();
   }
 
   assert (props->direction != HB_DIRECTION_INVALID);
 
@@ -288,18 +288,23 @@ hb_shape_plan_execute (hb_shape_plan_t  
 		       const hb_feature_t *features,
 		       unsigned int        num_features)
 {
   DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
 		  "num_features=%d shaper_func=%p",
 		  num_features,
 		  shape_plan->shaper_func);
 
-  if (unlikely (hb_object_is_inert (shape_plan) ||
-		hb_object_is_inert (buffer)))
+  if (unlikely (!buffer->len))
+    return true;
+
+  assert (!hb_object_is_inert (buffer));
+  assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE);
+
+  if (unlikely (hb_object_is_inert (shape_plan)))
     return false;
 
   assert (shape_plan->face_unsafe == font->face);
   assert (hb_segment_properties_equal (&shape_plan->props, &buffer->props));
 
 #define HB_SHAPER_EXECUTE(shaper) \
 	HB_STMT_START { \
 	  return HB_SHAPER_DATA (shaper, shape_plan) && \
--- a/gfx/harfbuzz/src/hb-shape.cc
+++ b/gfx/harfbuzz/src/hb-shape.cc
@@ -366,21 +366,16 @@ retry:
  **/
 hb_bool_t
 hb_shape_full (hb_font_t          *font,
 	       hb_buffer_t        *buffer,
 	       const hb_feature_t *features,
 	       unsigned int        num_features,
 	       const char * const *shaper_list)
 {
-  if (unlikely (!buffer->len))
-    return true;
-
-  assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE);
-
   hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list);
   hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features);
   hb_shape_plan_destroy (shape_plan);
 
   if (res)
     buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
   return res;
 }
@@ -394,17 +389,17 @@ hb_shape_full (hb_font_t          *font,
  * @num_features: the length of @features array
  *
  * Shapes @buffer using @font turning its Unicode characters content to
  * positioned glyphs. If @features is not %NULL, it will be used to control the
  * features applied during shaping.
  *
  * Return value: %FALSE if all shapers failed, %TRUE otherwise
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_shape (hb_font_t           *font,
 	  hb_buffer_t         *buffer,
 	  const hb_feature_t  *features,
 	  unsigned int         num_features)
 {
   hb_shape_full (font, buffer, features, num_features, NULL);
--- a/gfx/harfbuzz/src/hb-shaper.cc
+++ b/gfx/harfbuzz/src/hb-shaper.cc
@@ -59,17 +59,17 @@ retry:
   {
     char *env = getenv ("HB_SHAPER_LIST");
     if (!env || !*env) {
       (void) hb_atomic_ptr_cmpexch (&static_shapers, NULL, &all_shapers[0]);
       return (const hb_shaper_pair_t *) all_shapers;
     }
 
     /* Not found; allocate one. */
-    shapers = (hb_shaper_pair_t *) malloc (sizeof (all_shapers));
+    shapers = (hb_shaper_pair_t *) calloc (1, sizeof (all_shapers));
     if (unlikely (!shapers)) {
       (void) hb_atomic_ptr_cmpexch (&static_shapers, NULL, &all_shapers[0]);
       return (const hb_shaper_pair_t *) all_shapers;
     }
 
     memcpy (shapers, all_shapers, sizeof (all_shapers));
 
      /* Reorder shaper list to prefer requested shapers. */
--- a/gfx/harfbuzz/src/hb-unicode.cc
+++ b/gfx/harfbuzz/src/hb-unicode.cc
@@ -153,17 +153,17 @@ hb_unicode_funcs_get_default (void)
 /**
  * hb_unicode_funcs_create: (Xconstructor)
  * @parent: (nullable):
  *
  * 
  *
  * Return value: (transfer full):
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_unicode_funcs_t *
 hb_unicode_funcs_create (hb_unicode_funcs_t *parent)
 {
   hb_unicode_funcs_t *ufuncs;
 
   if (!(ufuncs = hb_object_create<hb_unicode_funcs_t> ()))
     return hb_unicode_funcs_get_empty ();
@@ -199,47 +199,47 @@ const hb_unicode_funcs_t _hb_unicode_fun
 
 /**
  * hb_unicode_funcs_get_empty:
  *
  * 
  *
  * Return value: (transfer full):
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_unicode_funcs_t *
 hb_unicode_funcs_get_empty (void)
 {
   return const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil);
 }
 
 /**
  * hb_unicode_funcs_reference: (skip)
  * @ufuncs: Unicode functions.
  *
  * 
  *
  * Return value: (transfer full):
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_unicode_funcs_t *
 hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs)
 {
   return hb_object_reference (ufuncs);
 }
 
 /**
  * hb_unicode_funcs_destroy: (skip)
  * @ufuncs: Unicode functions.
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs)
 {
   if (!hb_object_destroy (ufuncs)) return;
 
 #define HB_UNICODE_FUNC_IMPLEMENT(name) \
   if (ufuncs->destroy.name) ufuncs->destroy.name (ufuncs->user_data.name);
@@ -258,17 +258,17 @@ hb_unicode_funcs_destroy (hb_unicode_fun
  * @data: 
  * @destroy: 
  * @replace: 
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
 			        hb_user_data_key_t *key,
 			        void *              data,
 			        hb_destroy_func_t   destroy,
 				hb_bool_t           replace)
 {
@@ -279,33 +279,33 @@ hb_unicode_funcs_set_user_data (hb_unico
  * hb_unicode_funcs_get_user_data: (skip)
  * @ufuncs: Unicode functions.
  * @key: 
  *
  * 
  *
  * Return value: (transfer none):
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void *
 hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
 			        hb_user_data_key_t *key)
 {
   return hb_object_get_user_data (ufuncs, key);
 }
 
 
 /**
  * hb_unicode_funcs_make_immutable:
  * @ufuncs: Unicode functions.
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
 {
   if (unlikely (hb_object_is_inert (ufuncs)))
     return;
 
   ufuncs->immutable = true;
@@ -314,33 +314,33 @@ hb_unicode_funcs_make_immutable (hb_unic
 /**
  * hb_unicode_funcs_is_immutable:
  * @ufuncs: Unicode functions.
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_bool_t
 hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs)
 {
   return ufuncs->immutable;
 }
 
 /**
  * hb_unicode_funcs_get_parent:
  * @ufuncs: Unicode functions.
  *
  * 
  *
  * Return value: 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 hb_unicode_funcs_t *
 hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs)
 {
   return ufuncs->parent ? ufuncs->parent : hb_unicode_funcs_get_empty ();
 }
 
 
--- a/gfx/harfbuzz/src/hb-unicode.h
+++ b/gfx/harfbuzz/src/hb-unicode.h
@@ -278,81 +278,81 @@ typedef unsigned int			(*hb_unicode_deco
  * hb_unicode_funcs_set_combining_class_func:
  * @ufuncs: a Unicode function structure
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs,
 					   hb_unicode_combining_class_func_t func,
 					   void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_unicode_funcs_set_eastasian_width_func:
  * @ufuncs: a Unicode function structure
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
 					   hb_unicode_eastasian_width_func_t func,
 					   void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_unicode_funcs_set_general_category_func:
  * @ufuncs: a Unicode function structure
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs,
 					    hb_unicode_general_category_func_t func,
 					    void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_unicode_funcs_set_mirroring_func:
  * @ufuncs: a Unicode function structure
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs,
 				     hb_unicode_mirroring_func_t func,
 				     void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_unicode_funcs_set_script_func:
  * @ufuncs: a Unicode function structure
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
  * 
  *
- * Since: 1.0
+ * Since: 0.9.2
  **/
 void
 hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs,
 				  hb_unicode_script_func_t func,
 				  void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_unicode_funcs_set_compose_func:
--- a/gfx/harfbuzz/src/hb-version.h
+++ b/gfx/harfbuzz/src/hb-version.h
@@ -33,19 +33,19 @@
 
 #include "hb-common.h"
 
 HB_BEGIN_DECLS
 
 
 #define HB_VERSION_MAJOR 1
 #define HB_VERSION_MINOR 0
-#define HB_VERSION_MICRO 3
+#define HB_VERSION_MICRO 5
 
-#define HB_VERSION_STRING "1.0.3"
+#define HB_VERSION_STRING "1.0.5"
 
 #define HB_VERSION_ATLEAST(major,minor,micro) \
 	((major)*10000+(minor)*100+(micro) <= \
 	 HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO)
 
 
 void
 hb_version (unsigned int *major,