Sophie

Sophie

distrib > Mageia > 5 > i586 > by-pkgid > d7ab807fc4d28d44a4c5b8b9292a3311 > files > 21

firefox-45.5.1-1.mga5.src.rpm

--- firefox-45.3.0esr/gfx/harfbuzz/src/Makefile.am.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/Makefile.am	2016-08-05 14:37:07.926011597 +0300
@@ -48,6 +48,7 @@
 	hb-ot-hmtx-table.hh \
 	hb-ot-maxp-table.hh \
 	hb-ot-name-table.hh \
+	hb-ot-os2-table.hh \
 	hb-ot-tag.cc \
 	hb-private.hh \
 	hb-set-private.hh \
@@ -392,7 +393,14 @@
 	check-symbols.sh \
 	$(NULL)
 
-TESTS = $(dist_check_SCRIPTS)
+check_PROGRAMS = \
+	test-ot-tag \
+	$(NULL)
+test_ot_tag_SOURCES = hb-ot-tag.cc
+test_ot_tag_CPPFLAGS = $(HBCFLAGS) -DMAIN
+test_ot_tag_LDADD = libharfbuzz.la $(HBLIBS)
+
+TESTS = $(dist_check_SCRIPTS) $(check_PROGRAMS)
 TESTS_ENVIRONMENT = \
 	srcdir="$(srcdir)" \
 	MAKE="$(MAKE) $(AM_MAKEFLAGS)" \
@@ -419,6 +427,7 @@
 	-DHB_OT_H_IN \
 	-DHB_GOBJECT_H \
 	-DHB_GOBJECT_H_IN \
+	-DHB_EXTERN= \
 	$(NULL)
 HarfBuzz_0_0_gir_LIBS = \
 	libharfbuzz.la \
--- firefox-45.3.0esr/gfx/harfbuzz/src/check-header-guards.sh.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/check-header-guards.sh	2016-08-05 14:37:07.926011597 +0300
@@ -9,13 +9,12 @@
 test "x$HBHEADERS" = x && HBHEADERS=`cd "$srcdir"; find . -maxdepth 1 -name 'hb*.h'`
 test "x$HBSOURCES" = x && HBSOURCES=`cd "$srcdir"; find . -maxdepth 1 -name 'hb-*.cc' -or -name 'hb-*.hh'`
 
-
 for x in $HBHEADERS $HBSOURCES; do
 	test -f "$srcdir/$x" && x="$srcdir/$x"
-	echo "$x" | grep '[^h]$' -q && continue;
+	echo "$x" | grep -q '[^h]$' && continue;
 	xx=`echo "$x" | sed 's@.*/@@'`
 	tag=`echo "$xx" | tr 'a-z.-' 'A-Z_'`
-	lines=`grep "\<$tag\>" "$x" | wc -l | sed 's/[ 	]*//g'`
+	lines=`grep -w "$tag" "$x" | wc -l | sed 's/[ 	]*//g'`
 	if test "x$lines" != x3; then
 		echo "Ouch, header file $x does not have correct preprocessor guards"
 		stat=1
--- firefox-45.3.0esr/gfx/harfbuzz/src/gen-indic-table.py.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/gen-indic-table.py	2016-08-05 14:37:07.927011589 +0300
@@ -91,6 +91,7 @@
 	"Visarga":		'Vs',
 	"Vowel":		'Vo',
 	"Vowel_Dependent":	'M',
+	"Consonant_Prefixed":	'CPrf',
 	"Other":		'x',
 },{
 	"Not_Applicable":	'x',
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-atomic-private.hh.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-atomic-private.hh	2016-08-05 14:37:07.927011589 +0300
@@ -119,6 +119,31 @@
 #define hb_atomic_ptr_impl_cmpexch(P,O,N)	( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false)
 
 
+#elif !defined(HB_NO_MT) && defined(_AIX) && defined(__IBMCPP__)
+
+#include <builtins.h>
+
+
+static inline int hb_fetch_and_add(volatile int* AI, unsigned int V) {
+  __lwsync();
+  int result = __fetch_and_add(AI, V);
+  __isync();
+  return result;
+}
+static inline int hb_compare_and_swaplp(volatile long* P, long O, long N) {
+  __sync();
+  int result = __compare_and_swaplp (P, &O, N);
+  __sync();
+  return result;
+}
+
+typedef int hb_atomic_int_impl_t;
+#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
+#define hb_atomic_int_impl_add(AI, V)           hb_fetch_and_add (&(AI), (V))
+
+#define hb_atomic_ptr_impl_get(P)               (__sync(), (void *) *(P))
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N))
+
 #elif !defined(HB_NO_MT)
 
 #define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-blob.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-blob.h	2016-08-05 14:37:07.927011589 +0300
@@ -64,7 +64,7 @@
 
 typedef struct hb_blob_t hb_blob_t;
 
-hb_blob_t *
+HB_EXTERN hb_blob_t *
 hb_blob_create (const char        *data,
 		unsigned int       length,
 		hb_memory_mode_t   mode,
@@ -77,21 +77,21 @@
  * modify the parent data as that data may be
  * shared among multiple sub-blobs.
  */
-hb_blob_t *
+HB_EXTERN hb_blob_t *
 hb_blob_create_sub_blob (hb_blob_t    *parent,
 			 unsigned int  offset,
 			 unsigned int  length);
 
-hb_blob_t *
+HB_EXTERN hb_blob_t *
 hb_blob_get_empty (void);
 
-hb_blob_t *
+HB_EXTERN hb_blob_t *
 hb_blob_reference (hb_blob_t *blob);
 
-void
+HB_EXTERN void
 hb_blob_destroy (hb_blob_t *blob);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_blob_set_user_data (hb_blob_t          *blob,
 		       hb_user_data_key_t *key,
 		       void *              data,
@@ -99,25 +99,25 @@
 		       hb_bool_t           replace);
 
 
-void *
+HB_EXTERN void *
 hb_blob_get_user_data (hb_blob_t          *blob,
 		       hb_user_data_key_t *key);
 
 
-void
+HB_EXTERN void
 hb_blob_make_immutable (hb_blob_t *blob);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_blob_is_immutable (hb_blob_t *blob);
 
 
-unsigned int
+HB_EXTERN unsigned int
 hb_blob_get_length (hb_blob_t *blob);
 
-const char *
+HB_EXTERN const char *
 hb_blob_get_data (hb_blob_t *blob, unsigned int *length);
 
-char *
+HB_EXTERN char *
 hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length);
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-buffer-private.hh.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-buffer-private.hh	2016-08-05 14:37:07.927011589 +0300
@@ -124,6 +124,11 @@
   hb_codepoint_t context[2][CONTEXT_LENGTH];
   unsigned int context_len[2];
 
+  /* Debugging */
+  hb_buffer_message_func_t message_func;
+  void *message_data;
+  hb_destroy_func_t message_destroy;
+
 
   /* Methods */
 
@@ -174,13 +179,12 @@
     if (have_output)
     {
       if (unlikely (out_info != info || out_len != idx)) {
-	if (unlikely (!make_room_for (1, 1)))
-	  goto done;
+	if (unlikely (!make_room_for (1, 1))) return;
 	out_info[out_len] = info[idx];
       }
       out_len++;
     }
-  done:
+
     idx++;
   }
 
@@ -234,6 +238,19 @@
   inline void clear_context (unsigned int side) { context_len[side] = 0; }
 
   HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *));
+
+  inline bool messaging (void) { return unlikely (message_func); }
+  inline bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
+  {
+    if (!messaging ())
+      return true;
+    va_list ap;
+    va_start (ap, fmt);
+    bool ret = message_impl (font, fmt, ap);
+    va_end (ap);
+    return ret;
+  }
+  HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
 };
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-buffer-serialize.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-buffer-serialize.cc	2016-08-05 14:37:07.928011582 +0300
@@ -36,11 +36,12 @@
 /**
  * hb_buffer_serialize_list_formats:
  *
- * 
+ * Returns a list of supported buffer serialization formats.
  *
  * Return value: (transfer none):
+ * A string array of buffer serialization formats. Should not be freed.
  *
- * Since: 0.9.2
+ * Since: 0.9.7
  **/
 const char **
 hb_buffer_serialize_list_formats (void)
@@ -50,14 +51,17 @@
 
 /**
  * hb_buffer_serialize_format_from_string:
- * @str: 
- * @len: 
+ * @str: (array length=len) (element-type uint8_t): a string to parse
+ * @len: length of @str, or -1 if string is %NULL terminated
  *
- * 
+ * Parses a string into an #hb_buffer_serialize_format_t. Does not check if
+ * @str is a valid buffer serialization format, use
+ * hb_buffer_serialize_list_formats() to get the list of supported formats.
  *
  * Return value: 
+ * The parsed #hb_buffer_serialize_format_t.
  *
- * Since: 0.9.2
+ * Since: 0.9.7
  **/
 hb_buffer_serialize_format_t
 hb_buffer_serialize_format_from_string (const char *str, int len)
@@ -68,13 +72,15 @@
 
 /**
  * hb_buffer_serialize_format_to_string:
- * @format: 
+ * @format: an #hb_buffer_serialize_format_t to convert.
  *
- * 
+ * Converts @format to the string corresponding it, or %NULL if it is not a valid
+ * #hb_buffer_serialize_format_t.
  *
- * Return value: 
+ * Return value: (transfer none):
+ * A %NULL terminated string corresponding to @format. Should not be freed.
  *
- * Since: 0.9.2
+ * Since: 0.9.7
  **/
 const char *
 hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format)
@@ -242,24 +248,51 @@
   return end - start;
 }
 
-/* Returns number of items, starting at start, that were serialized. */
 /**
  * hb_buffer_serialize_glyphs:
- * @buffer: a buffer.
- * @start: 
- * @end: 
- * @buf: (array length=buf_size):
- * @buf_size: 
- * @buf_consumed: (out):
- * @font: 
- * @format: 
- * @flags: 
+ * @buffer: an #hb_buffer_t buffer.
+ * @start: the first item in @buffer to serialize.
+ * @end: the last item in @buffer to serialize.
+ * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
+ *       write serialized buffer into.
+ * @buf_size: the size of @buf.
+ * @buf_consumed: (out) (allow-none): if not %NULL, will be set to the number of byes written into @buf.
+ * @font: (allow-none): the #hb_font_t used to shape this buffer, needed to
+ *        read glyph names and extents. If %NULL, and empty font will be used.
+ * @format: the #hb_buffer_serialize_format_t to use for formatting the output.
+ * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
+ *         to serialize.
+ *
+ * Serializes @buffer into a textual representation of its glyph content,
+ * useful for showing the contents of the buffer, for example during debugging.
+ * There are currently two supported serialization formats:
+ *
+ * ## text
+ * A human-readable, plain text format.
+ * The serialized glyphs will look something like:
+ *
+ * ```
+ * [uni0651=0@518,0+0|uni0628=0+1897]
+ * ```
+ * - The serialized glyphs are delimited with `[` and `]`.
+ * - Glyphs are separated with `|`
+ * - Each glyph starts with glyph name, or glyph index if
+ *   #HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES flag is set. Then,
+ *   - If #HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS is not set, `=` then #hb_glyph_info_t.cluster.
+ *   - If #HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS is not set, the #hb_glyph_position_t in the format:
+ *     - If both #hb_glyph_position_t.x_offset and #hb_glyph_position_t.y_offset are not 0, `@x_offset,y_offset`. Then,
+ *     - `+x_advance`, then `,y_advance` if #hb_glyph_position_t.y_advance is not 0. Then,
+ *   - If #HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS is set, the
+ *     #hb_glyph_extents_t in the format
+ *     `&lt;x_bearing,y_bearing,width,height&gt;`
  *
- * 
+ * ## json
+ * TODO.
  *
  * Return value: 
+ * The number of serialized items.
  *
- * Since: 0.9.2
+ * Since: 0.9.7
  **/
 unsigned int
 hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
@@ -267,8 +300,8 @@
 			    unsigned int end,
 			    char *buf,
 			    unsigned int buf_size,
-			    unsigned int *buf_consumed, /* May be NULL */
-			    hb_font_t *font, /* May be NULL */
+			    unsigned int *buf_consumed,
+			    hb_font_t *font,
 			    hb_buffer_serialize_format_t format,
 			    hb_buffer_serialize_flags_t flags)
 {
@@ -282,6 +315,9 @@
   assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
 	  buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
 
+  if (!buffer->have_positions)
+    flags |= HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS;
+
   if (unlikely (start == end))
     return 0;
 
@@ -355,7 +391,7 @@
 
 /**
  * hb_buffer_deserialize_glyphs:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t buffer.
  * @buf: (array length=buf_len):
  * @buf_len: 
  * @end_ptr: (out):
@@ -366,7 +402,7 @@
  *
  * Return value: 
  *
- * Since: 0.9.2
+ * Since: 0.9.7
  **/
 hb_bool_t
 hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-buffer.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-buffer.cc	2016-08-05 14:37:07.929011574 +0300
@@ -35,8 +35,26 @@
 #define HB_DEBUG_BUFFER (HB_DEBUG+0)
 #endif
 
+/**
+ * SECTION: hb-buffer
+ * @title: Buffers
+ * @short_description: Input and output buffers
+ * @include: hb.h
+ *
+ * Buffers serve dual role in HarfBuzz; they hold the input characters that are
+ * passed hb_shape(), and after shaping they hold the output glyphs.
+ **/
 
 /**
+ * hb_segment_properties_equal:
+ * @a: first #hb_segment_properties_t to compare.
+ * @b: second #hb_segment_properties_t to compare.
+ *
+ * Checks the equality of two #hb_segment_properties_t's.
+ *
+ * Return value: (transfer full):
+ * %true if all properties of @a equal those of @b, false otherwise.
+ *
  * Since: 0.9.7
  **/
 hb_bool_t
@@ -52,6 +70,14 @@
 }
 
 /**
+ * hb_segment_properties_hash:
+ * @p: #hb_segment_properties_t to hash.
+ *
+ * Creates a hash representing @p.
+ *
+ * Return value:
+ * A hash of @p.
+ *
  * Since: 0.9.7
  **/
 unsigned int
@@ -324,9 +350,7 @@
 			     unsigned int num_out,
 			     const uint32_t *glyph_data)
 {
-  if (unlikely (!make_room_for (num_in, num_out)))
-    goto done;
-  {
+  if (unlikely (!make_room_for (num_in, num_out))) return;
 
   merge_clusters (idx, idx + num_in);
 
@@ -339,50 +363,39 @@
     pinfo++;
   }
 
-  out_len += num_out;
-  }
-done:
   idx  += num_in;
+  out_len += num_out;
 }
 
 void
 hb_buffer_t::output_glyph (hb_codepoint_t glyph_index)
 {
-  if (unlikely (!make_room_for (0, 1)))
-    goto done;
+  if (unlikely (!make_room_for (0, 1))) return;
 
   out_info[out_len] = info[idx];
   out_info[out_len].codepoint = glyph_index;
 
   out_len++;
-done:
-  ;
 }
 
 void
 hb_buffer_t::output_info (const hb_glyph_info_t &glyph_info)
 {
-  if (unlikely (!make_room_for (0, 1)))
-    goto done;
+  if (unlikely (!make_room_for (0, 1))) return;
 
   out_info[out_len] = glyph_info;
 
   out_len++;
-done:
-  ;
 }
 
 void
 hb_buffer_t::copy_glyph (void)
 {
-  if (unlikely (!make_room_for (0, 1)))
-    goto done;
+  if (unlikely (!make_room_for (0, 1))) return;
 
   out_info[out_len] = info[idx];
 
   out_len++;
-done:
-  ;
 }
 
 bool
@@ -400,7 +413,7 @@
   if (out_len < i)
   {
     unsigned int count = i - out_len;
-    if (unlikely (!make_room_for (count, count))) return false; // XXX verify bailout
+    if (unlikely (!make_room_for (count, count))) return false;
 
     memmove (out_info + out_len, info + idx, count * sizeof (out_info[0]));
     idx += count;
@@ -427,15 +440,13 @@
 hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index)
 {
   if (unlikely (out_info != info || out_len != idx)) {
-    if (unlikely (!make_room_for (1, 1)))
-      goto out;
+    if (unlikely (!make_room_for (1, 1))) return;
     out_info[out_len] = info[idx];
   }
   out_info[out_len].codepoint = glyph_index;
 
-  out_len++;
-out:
   idx++;
+  out_len++;
 }
 
 
@@ -721,9 +732,14 @@
 /**
  * hb_buffer_create: (Xconstructor)
  *
- * 
+ * Creates a new #hb_buffer_t with all properties to defaults.
  *
- * Return value: (transfer full)
+ * Return value: (transfer full):
+ * A newly allocated #hb_buffer_t with a reference count of 1. The initial
+ * reference count should be released with hb_buffer_destroy() when you are done
+ * using the #hb_buffer_t. This function never returns %NULL. If memory cannot
+ * be allocated, a special #hb_buffer_t object will be returned on which
+ * hb_buffer_allocation_successful() returns %false.
  *
  * Since: 0.9.2
  **/
@@ -778,11 +794,13 @@
 
 /**
  * hb_buffer_reference: (skip)
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
- * 
+ * Increases the reference count on @buffer by one. This prevents @buffer from
+ * being destroyed until a matching call to hb_buffer_destroy() is made.
  *
  * Return value: (transfer full):
+ * The referenced #hb_buffer_t.
  *
  * Since: 0.9.2
  **/
@@ -794,9 +812,11 @@
 
 /**
  * hb_buffer_destroy: (skip)
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
- * 
+ * Deallocate the @buffer.
+ * Decreases the reference count on @buffer by one. If the result is zero, then
+ * @buffer and all associated resources are freed. See hb_buffer_reference().
  *
  * Since: 0.9.2
  **/
@@ -809,13 +829,15 @@
 
   free (buffer->info);
   free (buffer->pos);
+  if (buffer->message_destroy)
+    buffer->message_destroy (buffer->message_data);
 
   free (buffer);
 }
 
 /**
  * hb_buffer_set_user_data: (skip)
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  * @key: 
  * @data: 
  * @destroy: 
@@ -839,7 +861,7 @@
 
 /**
  * hb_buffer_get_user_data: (skip)
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  * @key: 
  *
  * 
@@ -858,10 +880,11 @@
 
 /**
  * hb_buffer_set_content_type:
- * @buffer: a buffer.
- * @content_type: 
+ * @buffer: an #hb_buffer_t.
+ * @content_type: the type of buffer contents to set
  *
- * 
+ * Sets the type of @buffer contents, buffers are either empty, contain
+ * characters (before shaping) or glyphs (the result of shaping).
  *
  * Since: 0.9.5
  **/
@@ -874,11 +897,12 @@
 
 /**
  * hb_buffer_get_content_type:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
- * 
+ * see hb_buffer_set_content_type().
  *
- * Return value: 
+ * Return value:
+ * The type of @buffer contents.
  *
  * Since: 0.9.5
  **/
@@ -891,7 +915,7 @@
 
 /**
  * hb_buffer_set_unicode_funcs:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  * @unicode_funcs: 
  *
  * 
@@ -916,7 +940,7 @@
 
 /**
  * hb_buffer_get_unicode_funcs:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
  * 
  *
@@ -932,10 +956,16 @@
 
 /**
  * hb_buffer_set_direction:
- * @buffer: a buffer.
- * @direction: 
+ * @buffer: an #hb_buffer_t.
+ * @direction: the #hb_direction_t of the @buffer
  *
- * 
+ * Set the text flow direction of the buffer. No shaping can happen without
+ * setting @buffer direction, and it controls the visual direction for the
+ * output glyphs; for RTL direction the glyphs will be reversed. Many layout
+ * features depend on the proper setting of the direction, for example,
+ * reversing RTL text before shaping, then shaping with LTR direction is not
+ * the same as keeping the text in logical order and shaping with RTL
+ * direction.
  *
  * Since: 0.9.2
  **/
@@ -952,11 +982,12 @@
 
 /**
  * hb_buffer_get_direction:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
- * 
+ * See hb_buffer_set_direction()
  *
- * Return value: 
+ * Return value:
+ * The direction of the @buffer.
  *
  * Since: 0.9.2
  **/
@@ -968,10 +999,18 @@
 
 /**
  * hb_buffer_set_script:
- * @buffer: a buffer.
- * @script: 
+ * @buffer: an #hb_buffer_t.
+ * @script: an #hb_script_t to set.
  *
- * 
+ * Sets the script of @buffer to @script.
+ *
+ * Script is crucial for choosing the proper shaping behaviour for scripts that
+ * require it (e.g. Arabic) and the which OpenType features defined in the font
+ * to be applied.
+ *
+ * You can pass one of the predefined #hb_script_t values, or use
+ * hb_script_from_string() or hb_script_from_iso15924_tag() to get the
+ * corresponding script from an ISO 15924 script tag.
  *
  * Since: 0.9.2
  **/
@@ -987,11 +1026,12 @@
 
 /**
  * hb_buffer_get_script:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
- * 
+ * See hb_buffer_set_script().
  *
- * Return value: 
+ * Return value:
+ * The #hb_script_t of the @buffer.
  *
  * Since: 0.9.2
  **/
@@ -1003,10 +1043,18 @@
 
 /**
  * hb_buffer_set_language:
- * @buffer: a buffer.
- * @language: 
+ * @buffer: an #hb_buffer_t.
+ * @language: an hb_language_t to set.
  *
- * 
+ * Sets the language of @buffer to @language.
+ *
+ * Languages are crucial for selecting which OpenType feature to apply to the
+ * buffer which can result in applying language-specific behaviour. Languages
+ * are orthogonal to the scripts, and though they are related, they are
+ * different concepts and should not be confused with each other.
+ *
+ * Use hb_language_from_string() to convert from ISO 639 language codes to
+ * #hb_language_t.
  *
  * Since: 0.9.2
  **/
@@ -1022,11 +1070,12 @@
 
 /**
  * hb_buffer_get_language:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
- * 
+ * See hb_buffer_set_language().
  *
  * Return value: (transfer none):
+ * The #hb_language_t of the buffer. Must not be freed by the caller.
  *
  * Since: 0.9.2
  **/
@@ -1038,10 +1087,12 @@
 
 /**
  * hb_buffer_set_segment_properties:
- * @buffer: a buffer.
- * @props: 
+ * @buffer: an #hb_buffer_t.
+ * @props: an #hb_segment_properties_t to use.
  *
- * 
+ * Sets the segment properties of the buffer, a shortcut for calling
+ * hb_buffer_set_direction(), hb_buffer_set_script() and
+ * hb_buffer_set_language() individually.
  *
  * Since: 0.9.7
  **/
@@ -1057,10 +1108,10 @@
 
 /**
  * hb_buffer_get_segment_properties:
- * @buffer: a buffer.
- * @props: (out):
+ * @buffer: an #hb_buffer_t.
+ * @props: (out): the output #hb_segment_properties_t.
  *
- * 
+ * Sets @props to the #hb_segment_properties_t of @buffer.
  *
  * Since: 0.9.7
  **/
@@ -1074,10 +1125,10 @@
 
 /**
  * hb_buffer_set_flags:
- * @buffer: a buffer.
- * @flags: 
+ * @buffer: an #hb_buffer_t.
+ * @flags: the buffer flags to set.
  *
- * 
+ * Sets @buffer flags to @flags. See #hb_buffer_flags_t.
  *
  * Since: 0.9.7
  **/
@@ -1093,11 +1144,12 @@
 
 /**
  * hb_buffer_get_flags:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
- * 
+ * See hb_buffer_set_flags().
  *
  * Return value: 
+ * The @buffer flags.
  *
  * Since: 0.9.7
  **/
@@ -1109,7 +1161,7 @@
 
 /**
  * hb_buffer_set_cluster_level:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  * @cluster_level: 
  *
  * 
@@ -1128,7 +1180,7 @@
 
 /**
  * hb_buffer_get_cluster_level:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
  * 
  *
@@ -1145,10 +1197,13 @@
 
 /**
  * hb_buffer_set_replacement_codepoint:
- * @buffer: a buffer.
- * @replacement: 
+ * @buffer: an #hb_buffer_t.
+ * @replacement: the replacement #hb_codepoint_t
  *
- * 
+ * Sets the #hb_codepoint_t that replaces invalid entries for a given encoding
+ * when adding text to @buffer.
+ *
+ * Default is %HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT.
  *
  * Since: 0.9.31
  **/
@@ -1164,11 +1219,12 @@
 
 /**
  * hb_buffer_get_replacement_codepoint:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
- * 
+ * See hb_buffer_set_replacement_codepoint().
  *
  * Return value: 
+ * The @buffer replacement #hb_codepoint_t.
  *
  * Since: 0.9.31
  **/
@@ -1181,9 +1237,10 @@
 
 /**
  * hb_buffer_reset:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
- * 
+ * Resets the buffer to its initial status, as if it was just newly created
+ * with hb_buffer_create().
  *
  * Since: 0.9.2
  **/
@@ -1195,9 +1252,10 @@
 
 /**
  * hb_buffer_clear_contents:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
- * 
+ * Similar to hb_buffer_reset(), but does not clear the Unicode functions and
+ * the replacement code point.
  *
  * Since: 0.9.11
  **/
@@ -1209,12 +1267,13 @@
 
 /**
  * hb_buffer_pre_allocate:
- * @buffer: a buffer.
- * @size: 
+ * @buffer: an #hb_buffer_t.
+ * @size: number of items to pre allocate.
  *
- * 
+ * Pre allocates memory for @buffer to fit at least @size number of items.
  *
- * Return value: 
+ * Return value:
+ * %true if @buffer memory allocation succeeded, %false otherwise.
  *
  * Since: 0.9.2
  **/
@@ -1226,11 +1285,12 @@
 
 /**
  * hb_buffer_allocation_successful:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
- * 
+ * Check if allocating memory for the buffer succeeded.
  *
- * Return value: 
+ * Return value:
+ * %true if @buffer memory allocation succeeded, %false otherwise.
  *
  * Since: 0.9.2
  **/
@@ -1242,11 +1302,18 @@
 
 /**
  * hb_buffer_add:
- * @buffer: a buffer.
- * @codepoint: 
- * @cluster: 
+ * @buffer: an #hb_buffer_t.
+ * @codepoint: a Unicode code point.
+ * @cluster: the cluster value of @codepoint.
+ *
+ * Appends a character with the Unicode value of @codepoint to @buffer, and
+ * gives it the initial cluster value of @cluster. Clusters can be any thing
+ * the client wants, they are usually used to refer to the index of the
+ * character in the input text stream and are output in
+ * #hb_glyph_info_t.cluster field.
  *
- * 
+ * This function does not check the validity of @codepoint, it is up to the
+ * caller to ensure it is a valid Unicode code point.
  *
  * Since: 0.9.7
  **/
@@ -1261,12 +1328,14 @@
 
 /**
  * hb_buffer_set_length:
- * @buffer: a buffer.
- * @length: 
+ * @buffer: an #hb_buffer_t.
+ * @length: the new length of @buffer.
  *
- * 
+ * Similar to hb_buffer_pre_allocate(), but clears any new items added at the
+ * end.
  *
  * Return value: 
+ * %true if @buffer memory allocation succeeded, %false otherwise.
  *
  * Since: 0.9.2
  **/
@@ -1301,11 +1370,13 @@
 
 /**
  * hb_buffer_get_length:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
  * Returns the number of items in the buffer.
  *
- * Return value: buffer length.
+ * Return value:
+ * The @buffer length.
+ * The value valid as long as buffer has not been modified.
  *
  * Since: 0.9.2
  **/
@@ -1317,13 +1388,15 @@
 
 /**
  * hb_buffer_get_glyph_infos:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  * @length: (out): output array length.
  *
- * Returns buffer glyph information array.  Returned pointer
- * is valid as long as buffer contents are not modified.
+ * 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.
+ * Return value: (transfer none) (array length=length):
+ * The @buffer glyph information array.
+ * The value valid as long as buffer has not been modified.
  *
  * Since: 0.9.2
  **/
@@ -1339,13 +1412,15 @@
 
 /**
  * hb_buffer_get_glyph_positions:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  * @length: (out): output length.
  *
- * Returns buffer glyph position array.  Returned pointer
- * is valid as long as buffer contents are not modified.
+ * 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.
+ * Return value: (transfer none) (array length=length):
+ * The @buffer glyph position array.
+ * The value valid as long as buffer has not been modified.
  *
  * Since: 0.9.2
  **/
@@ -1364,7 +1439,7 @@
 
 /**
  * hb_buffer_reverse:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
  * Reverses buffer contents.
  *
@@ -1378,7 +1453,7 @@
 
 /**
  * hb_buffer_reverse_range:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  * @start: start index.
  * @end: end index.
  *
@@ -1395,7 +1470,7 @@
 
 /**
  * hb_buffer_reverse_clusters:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
  * Reverses buffer clusters.  That is, the buffer contents are
  * reversed, then each cluster (consecutive items having the
@@ -1411,7 +1486,7 @@
 
 /**
  * hb_buffer_guess_segment_properties:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
  * Sets unset buffer segment properties based on buffer Unicode
  * contents.  If buffer is not empty, it must have content type
@@ -1510,13 +1585,18 @@
 
 /**
  * hb_buffer_add_utf8:
- * @buffer: a buffer.
- * @text: (array length=text_length) (element-type uint8_t):
- * @text_length: 
- * @item_offset: 
- * @item_length: 
+ * @buffer: an #hb_buffer_t.
+ * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8
+ *               characters to append.
+ * @text_length: the length of the @text, or -1 if it is %NULL terminated.
+ * @item_offset: the offset of the first character to add to the @buffer.
+ * @item_length: the number of characters to add to the @buffer, or -1 for the
+ *               end of @text (assuming it is %NULL terminated).
  *
- * 
+ * See hb_buffer_add_codepoints().
+ *
+ * Replaces invalid UTF-8 characters with the @buffer replacement code point,
+ * see hb_buffer_set_replacement_codepoint().
  *
  * Since: 0.9.2
  **/
@@ -1532,13 +1612,17 @@
 
 /**
  * hb_buffer_add_utf16:
- * @buffer: a buffer.
- * @text: (array length=text_length):
- * @text_length: 
- * @item_offset: 
- * @item_length: 
+ * @buffer: an #hb_buffer_t.
+ * @text: (array length=text_length): an array of UTF-16 characters to append.
+ * @text_length: the length of the @text, or -1 if it is %NULL terminated.
+ * @item_offset: the offset of the first character to add to the @buffer.
+ * @item_length: the number of characters to add to the @buffer, or -1 for the
+ *               end of @text (assuming it is %NULL terminated).
  *
- * 
+ * See hb_buffer_add_codepoints().
+ *
+ * Replaces invalid UTF-16 characters with the @buffer replacement code point,
+ * see hb_buffer_set_replacement_codepoint().
  *
  * Since: 0.9.2
  **/
@@ -1554,13 +1638,17 @@
 
 /**
  * hb_buffer_add_utf32:
- * @buffer: a buffer.
- * @text: (array length=text_length):
- * @text_length: 
- * @item_offset: 
- * @item_length: 
+ * @buffer: an #hb_buffer_t.
+ * @text: (array length=text_length): an array of UTF-32 characters to append.
+ * @text_length: the length of the @text, or -1 if it is %NULL terminated.
+ * @item_offset: the offset of the first character to add to the @buffer.
+ * @item_length: the number of characters to add to the @buffer, or -1 for the
+ *               end of @text (assuming it is %NULL terminated).
  *
- * 
+ * See hb_buffer_add_codepoints().
+ *
+ * Replaces invalid UTF-32 characters with the @buffer replacement code point,
+ * see hb_buffer_set_replacement_codepoint().
  *
  * Since: 0.9.2
  **/
@@ -1576,13 +1664,18 @@
 
 /**
  * hb_buffer_add_latin1:
- * @buffer: a buffer.
- * @text: (array length=text_length) (element-type uint8_t):
- * @text_length: 
- * @item_offset: 
- * @item_length: 
+ * @buffer: an #hb_buffer_t.
+ * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8
+ *               characters to append.
+ * @text_length: the length of the @text, or -1 if it is %NULL terminated.
+ * @item_offset: the offset of the first character to add to the @buffer.
+ * @item_length: the number of characters to add to the @buffer, or -1 for the
+ *               end of @text (assuming it is %NULL terminated).
  *
- * 
+ * Similar to hb_buffer_add_codepoints(), but allows only access to first 256
+ * Unicode code points that can fit in 8-bit strings.
+ *
+ * <note>Has nothing to do with non-Unicode Latin-1 encoding.</note>
  *
  * Since: 0.9.39
  **/
@@ -1598,13 +1691,25 @@
 
 /**
  * hb_buffer_add_codepoints:
- * @buffer: a buffer.
- * @text: (array length=text_length):
- * @text_length: 
- * @item_offset: 
- * @item_length: 
+ * @buffer: a #hb_buffer_t to append characters to.
+ * @text: (array length=text_length): an array of Unicode code points to append.
+ * @text_length: the length of the @text, or -1 if it is %NULL terminated.
+ * @item_offset: the offset of the first code point to add to the @buffer.
+ * @item_length: the number of code points to add to the @buffer, or -1 for the
+ *               end of @text (assuming it is %NULL terminated).
+ *
+ * Appends characters from @text array to @buffer. The @item_offset is the
+ * position of the first character from @text that will be appended, and
+ * @item_length is the number of character. When shaping part of a larger text
+ * (e.g. a run of text from a paragraph), instead of passing just the substring
+ * corresponding to the run, it is preferable to pass the whole
+ * paragraph and specify the run start and length as @item_offset and
+ * @item_length, respectively, to give HarfBuzz the full context to be able,
+ * for example, to do cross-run Arabic shaping or properly handle combining
+ * marks at stat of run.
  *
- * 
+ * This function does not check the validity of @text, it is up to the caller
+ * to ensure it contains a valid Unicode code points.
  *
  * Since: 0.9.31
  **/
@@ -1676,9 +1781,12 @@
 
 /**
  * hb_buffer_normalize_glyphs:
- * @buffer: a buffer.
+ * @buffer: an #hb_buffer_t.
  *
- * 
+ * Reorders a glyph buffer to have canonical in-cluster glyph order / position.
+ * The resulting clusters should behave identical to pre-reordering clusters.
+ *
+ * <note>This has nothing to do with Unicode normalization.</note>
  *
  * Since: 0.9.2
  **/
@@ -1724,3 +1832,45 @@
     }
   }
 }
+
+/*
+ * Debugging.
+ */
+
+/**
+ * hb_buffer_set_message_func:
+ * @buffer: an #hb_buffer_t.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ * 
+ *
+ * Since: 1.1.3
+ **/
+void
+hb_buffer_set_message_func (hb_buffer_t *buffer,
+			    hb_buffer_message_func_t func,
+			    void *user_data, hb_destroy_func_t destroy)
+{
+  if (buffer->message_destroy)
+    buffer->message_destroy (buffer->message_data);
+
+  if (func) {
+    buffer->message_func = func;
+    buffer->message_data = user_data;
+    buffer->message_destroy = destroy;
+  } else {
+    buffer->message_func = NULL;
+    buffer->message_data = NULL;
+    buffer->message_destroy = NULL;
+  }
+}
+
+bool
+hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap)
+{
+  char buf[100];
+  vsnprintf (buf, sizeof (buf),  fmt, ap);
+  return (bool) this->message_func (this, font, buf, this->message_data);
+}
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-buffer.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-buffer.h	2016-08-05 14:37:07.930011566 +0300
@@ -40,7 +40,27 @@
 
 HB_BEGIN_DECLS
 
-
+/**
+ * hb_glyph_info_t:
+ * @codepoint: either a Unicode code point (before shaping) or a glyph index
+ *             (after shaping).
+ * @mask: 
+ * @cluster: the index of the character in the original text that corresponds
+ *           to this #hb_glyph_info_t, or whatever the client passes to
+ *           hb_buffer_add(). More than one #hb_glyph_info_t can have the same
+ *           @cluster value, if they resulted from the same character (e.g. one
+ *           to many glyph substitution), and when more than one character gets
+ *           merged in the same glyph (e.g. many to one glyph substitution) the
+ *           #hb_glyph_info_t will have the smallest cluster value of them.
+ *           By default some characters are merged into the same cluster
+ *           (e.g. combining marks have the same cluster as their bases)
+ *           even if they are separate glyphs, hb_buffer_set_cluster_level()
+ *           allow selecting more fine-grained cluster handling.
+ *
+ * The #hb_glyph_info_t is the structure that holds information about the
+ * glyphs and their relation to input text.
+ *
+ */
 typedef struct hb_glyph_info_t {
   hb_codepoint_t codepoint;
   hb_mask_t      mask;
@@ -51,6 +71,22 @@
   hb_var_int_t   var2;
 } hb_glyph_info_t;
 
+/**
+ * hb_glyph_position_t:
+ * @x_advance: how much the line advances after drawing this glyph when setting
+ *             text in horizontal direction.
+ * @y_advance: how much the line advances after drawing this glyph when setting
+ *             text in vertical direction.
+ * @x_offset: how much the glyph moves on the X-axis before drawing it, this
+ *            should not affect how much the line advances.
+ * @y_offset: how much the glyph moves on the Y-axis before drawing it, this
+ *            should not affect how much the line advances.
+ *
+ * The #hb_glyph_position_t is the structure that holds the positions of the
+ * glyph in both horizontal and vertical directions. All positions in
+ * #hb_glyph_position_t are relative to the current point.
+ *
+ */
 typedef struct hb_glyph_position_t {
   hb_position_t  x_advance;
   hb_position_t  y_advance;
@@ -61,7 +97,16 @@
   hb_var_int_t   var;
 } hb_glyph_position_t;
 
-
+/**
+ * hb_segment_properties_t:
+ * @direction: the #hb_direction_t of the buffer, see hb_buffer_set_direction().
+ * @script: the #hb_script_t of the buffer, see hb_buffer_set_script().
+ * @language: the #hb_language_t of the buffer, see hb_buffer_set_language().
+ *
+ * The structure that holds various text properties of an #hb_buffer_t. Can be
+ * set and retrieved using hb_buffer_set_segment_properties() and
+ * hb_buffer_get_segment_properties(), respectively.
+ */
 typedef struct hb_segment_properties_t {
   hb_direction_t  direction;
   hb_script_t     script;
@@ -77,101 +122,125 @@
 				       NULL, \
 				       NULL}
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_segment_properties_equal (const hb_segment_properties_t *a,
 			     const hb_segment_properties_t *b);
 
-unsigned int
+HB_EXTERN unsigned int
 hb_segment_properties_hash (const hb_segment_properties_t *p);
 
 
 
-/*
- * hb_buffer_t
+/**
+ * hb_buffer_t:
+ *
+ * The main structure holding the input text and its properties before shaping,
+ * and output glyphs and their information after shaping.
  */
 
 typedef struct hb_buffer_t hb_buffer_t;
 
-hb_buffer_t *
+HB_EXTERN hb_buffer_t *
 hb_buffer_create (void);
 
-hb_buffer_t *
+HB_EXTERN hb_buffer_t *
 hb_buffer_get_empty (void);
 
-hb_buffer_t *
+HB_EXTERN hb_buffer_t *
 hb_buffer_reference (hb_buffer_t *buffer);
 
-void
+HB_EXTERN void
 hb_buffer_destroy (hb_buffer_t *buffer);
 
-hb_bool_t
+HB_EXTERN 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);
 
-void *
+HB_EXTERN void *
 hb_buffer_get_user_data (hb_buffer_t        *buffer,
 			 hb_user_data_key_t *key);
 
-
+/**
+ * hb_buffer_content_type_t:
+ * @HB_BUFFER_CONTENT_TYPE_INVALID: Initial value for new buffer.
+ * @HB_BUFFER_CONTENT_TYPE_UNICODE: The buffer contains input characters (before shaping).
+ * @HB_BUFFER_CONTENT_TYPE_GLYPHS: The buffer contains output glyphs (after shaping).
+ */
 typedef enum {
   HB_BUFFER_CONTENT_TYPE_INVALID = 0,
   HB_BUFFER_CONTENT_TYPE_UNICODE,
   HB_BUFFER_CONTENT_TYPE_GLYPHS
 } hb_buffer_content_type_t;
 
-void
+HB_EXTERN void
 hb_buffer_set_content_type (hb_buffer_t              *buffer,
 			    hb_buffer_content_type_t  content_type);
 
-hb_buffer_content_type_t
+HB_EXTERN hb_buffer_content_type_t
 hb_buffer_get_content_type (hb_buffer_t *buffer);
 
 
-void
+HB_EXTERN void
 hb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
 			     hb_unicode_funcs_t *unicode_funcs);
 
-hb_unicode_funcs_t *
+HB_EXTERN hb_unicode_funcs_t *
 hb_buffer_get_unicode_funcs (hb_buffer_t        *buffer);
 
-void
+HB_EXTERN void
 hb_buffer_set_direction (hb_buffer_t    *buffer,
 			 hb_direction_t  direction);
 
-hb_direction_t
+HB_EXTERN hb_direction_t
 hb_buffer_get_direction (hb_buffer_t *buffer);
 
-void
+HB_EXTERN void
 hb_buffer_set_script (hb_buffer_t *buffer,
 		      hb_script_t  script);
 
-hb_script_t
+HB_EXTERN hb_script_t
 hb_buffer_get_script (hb_buffer_t *buffer);
 
-void
+HB_EXTERN void
 hb_buffer_set_language (hb_buffer_t   *buffer,
 			hb_language_t  language);
 
 
-hb_language_t
+HB_EXTERN hb_language_t
 hb_buffer_get_language (hb_buffer_t *buffer);
 
-void
+HB_EXTERN void
 hb_buffer_set_segment_properties (hb_buffer_t *buffer,
 				  const hb_segment_properties_t *props);
 
-void
+HB_EXTERN void
 hb_buffer_get_segment_properties (hb_buffer_t *buffer,
 				  hb_segment_properties_t *props);
 
-void
+HB_EXTERN void
 hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
 
 
-/*
+/**
+ * hb_buffer_flags_t:
+ * @HB_BUFFER_FLAG_DEFAULT: the default buffer flag.
+ * @HB_BUFFER_FLAG_BOT: flag indicating that special handling of the beginning
+ *                      of text paragraph can be applied to this buffer. Should usually
+ *                      be set, unless you are passing to the buffer only part
+ *                      of the text without the full context.
+ * @HB_BUFFER_FLAG_EOT: flag indicating that special handling of the end of text
+ *                      paragraph can be applied to this buffer, similar to
+ *                      @HB_BUFFER_FLAG_EOT.
+ * @HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES:
+ *                      flag indication that character with Default_Ignorable
+ *                      Unicode property should use the corresponding glyph
+ *                      from the font, instead of hiding them (currently done
+ *                      by replacing them with the space glyph and zeroing the
+ *                      advance width.)
+ *
  * Since: 0.9.20
  */
 typedef enum { /*< flags >*/
@@ -181,11 +250,11 @@
   HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES	= 0x00000004u
 } hb_buffer_flags_t;
 
-void
+HB_EXTERN void
 hb_buffer_set_flags (hb_buffer_t       *buffer,
 		     hb_buffer_flags_t  flags);
 
-hb_buffer_flags_t
+HB_EXTERN hb_buffer_flags_t
 hb_buffer_get_flags (hb_buffer_t *buffer);
 
 /*
@@ -198,93 +267,92 @@
   HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES
 } hb_buffer_cluster_level_t;
 
-void
+HB_EXTERN void
 hb_buffer_set_cluster_level (hb_buffer_t               *buffer,
 			     hb_buffer_cluster_level_t  cluster_level);
 
-hb_buffer_cluster_level_t
+HB_EXTERN hb_buffer_cluster_level_t
 hb_buffer_get_cluster_level (hb_buffer_t *buffer);
 
+/**
+ * HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT:
+ *
+ * The default code point for replacing invalid characters in a given encoding.
+ * Set to U+FFFD REPLACEMENT CHARACTER.
+ *
+ * Since: 0.9.31
+ */
 #define HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT 0xFFFDu
 
-/* Sets codepoint used to replace invalid UTF-8/16/32 entries.
- * Default is 0xFFFDu. */
-void
+HB_EXTERN void
 hb_buffer_set_replacement_codepoint (hb_buffer_t    *buffer,
 				     hb_codepoint_t  replacement);
 
-hb_codepoint_t
+HB_EXTERN hb_codepoint_t
 hb_buffer_get_replacement_codepoint (hb_buffer_t    *buffer);
 
 
-/* Resets the buffer.  Afterwards it's as if it was just created,
- * except that it has a larger buffer allocated perhaps... */
-void
+HB_EXTERN void
 hb_buffer_reset (hb_buffer_t *buffer);
 
-/* Like reset, but does NOT clear unicode_funcs and replacement_codepoint. */
-void
+HB_EXTERN void
 hb_buffer_clear_contents (hb_buffer_t *buffer);
 
-/* Returns false if allocation failed */
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_buffer_pre_allocate (hb_buffer_t  *buffer,
 		        unsigned int  size);
 
 
-/* Returns false if allocation has failed before */
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_buffer_allocation_successful (hb_buffer_t  *buffer);
 
-void
+HB_EXTERN void
 hb_buffer_reverse (hb_buffer_t *buffer);
 
-void
+HB_EXTERN void
 hb_buffer_reverse_range (hb_buffer_t *buffer,
 			 unsigned int start, unsigned int end);
 
-void
+HB_EXTERN void
 hb_buffer_reverse_clusters (hb_buffer_t *buffer);
 
 
 /* Filling the buffer in */
 
-void
+HB_EXTERN void
 hb_buffer_add (hb_buffer_t    *buffer,
 	       hb_codepoint_t  codepoint,
 	       unsigned int    cluster);
 
-void
+HB_EXTERN void
 hb_buffer_add_utf8 (hb_buffer_t  *buffer,
 		    const char   *text,
 		    int           text_length,
 		    unsigned int  item_offset,
 		    int           item_length);
 
-void
+HB_EXTERN void
 hb_buffer_add_utf16 (hb_buffer_t    *buffer,
 		     const uint16_t *text,
 		     int             text_length,
 		     unsigned int    item_offset,
 		     int             item_length);
 
-void
+HB_EXTERN void
 hb_buffer_add_utf32 (hb_buffer_t    *buffer,
 		     const uint32_t *text,
 		     int             text_length,
 		     unsigned int    item_offset,
 		     int             item_length);
 
-/* Allows only access to first 256 Unicode codepoints. */
-void
+HB_EXTERN void
 hb_buffer_add_latin1 (hb_buffer_t   *buffer,
 		      const uint8_t *text,
 		      int            text_length,
 		      unsigned int   item_offset,
 		      int            item_length);
 
-/* Like add_utf32 but does NOT check for invalid Unicode codepoints. */
-void
+HB_EXTERN void
 hb_buffer_add_codepoints (hb_buffer_t          *buffer,
 			  const hb_codepoint_t *text,
 			  int                   text_length,
@@ -292,32 +360,25 @@
 			  int                   item_length);
 
 
-/* Clears any new items added at the end */
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_buffer_set_length (hb_buffer_t  *buffer,
 		      unsigned int  length);
 
-/* Return value valid as long as buffer not modified */
-unsigned int
+HB_EXTERN unsigned int
 hb_buffer_get_length (hb_buffer_t *buffer);
 
 /* Getting glyphs out of the buffer */
 
-/* Return value valid as long as buffer not modified */
-hb_glyph_info_t *
+HB_EXTERN hb_glyph_info_t *
 hb_buffer_get_glyph_infos (hb_buffer_t  *buffer,
                            unsigned int *length);
 
-/* Return value valid as long as buffer not modified */
-hb_glyph_position_t *
+HB_EXTERN hb_glyph_position_t *
 hb_buffer_get_glyph_positions (hb_buffer_t  *buffer,
                                unsigned int *length);
 
 
-/* Reorders a glyph buffer to have canonical in-cluster glyph order / position.
- * The resulting clusters should behave identical to pre-reordering clusters.
- * NOTE: This has nothing to do with Unicode normalization. */
-void
+HB_EXTERN void
 hb_buffer_normalize_glyphs (hb_buffer_t *buffer);
 
 
@@ -325,7 +386,16 @@
  * Serialize
  */
 
-/*
+/**
+ * hb_buffer_serialize_flags_t:
+ * @HB_BUFFER_SERIALIZE_FLAG_DEFAULT: serialize glyph names, clusters and positions.
+ * @HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS: do not serialize glyph cluster.
+ * @HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS: do not serialize glyph position information.
+ * @HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES: do no serialize glyph name.
+ * @HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS: serialize glyph extents.
+ *
+ * Flags that control what glyph information are serialized in hb_buffer_serialize_glyphs().
+ *
  * Since: 0.9.20
  */
 typedef enum { /*< flags >*/
@@ -336,43 +406,67 @@
   HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS	= 0x00000008u
 } hb_buffer_serialize_flags_t;
 
+/**
+ * hb_buffer_serialize_format_t:
+ * @HB_BUFFER_SERIALIZE_FORMAT_TEXT: a human-readable, plain text format.
+ * @HB_BUFFER_SERIALIZE_FORMAT_JSON: a machine-readable JSON format.
+ * @HB_BUFFER_SERIALIZE_FORMAT_INVALID: invalid format.
+ *
+ * The buffer serialization and de-serialization format used in
+ * hb_buffer_serialize_glyphs() and hb_buffer_deserialize_glyphs().
+ *
+ * Since: 0.9.2
+ */
 typedef enum {
   HB_BUFFER_SERIALIZE_FORMAT_TEXT	= HB_TAG('T','E','X','T'),
   HB_BUFFER_SERIALIZE_FORMAT_JSON	= HB_TAG('J','S','O','N'),
   HB_BUFFER_SERIALIZE_FORMAT_INVALID	= HB_TAG_NONE
 } hb_buffer_serialize_format_t;
 
-/* len=-1 means str is NUL-terminated. */
-hb_buffer_serialize_format_t
+HB_EXTERN hb_buffer_serialize_format_t
 hb_buffer_serialize_format_from_string (const char *str, int len);
 
-const char *
+HB_EXTERN const char *
 hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format);
 
-const char **
+HB_EXTERN const char **
 hb_buffer_serialize_list_formats (void);
 
-/* Returns number of items, starting at start, that were serialized. */
-unsigned int
+HB_EXTERN 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 */
-			    hb_font_t *font, /* May be NULL */
+			    unsigned int *buf_consumed,
+			    hb_font_t *font,
 			    hb_buffer_serialize_format_t format,
 			    hb_buffer_serialize_flags_t flags);
 
-hb_bool_t
+HB_EXTERN 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 */
+			      int buf_len,
+			      const char **end_ptr,
+			      hb_font_t *font,
 			      hb_buffer_serialize_format_t format);
 
 
+/*
+ * Debugging.
+ */
+
+typedef hb_bool_t	(*hb_buffer_message_func_t)	(hb_buffer_t *buffer,
+							 hb_font_t   *font,
+							 const char  *message,
+							 void        *user_data);
+
+HB_EXTERN void
+hb_buffer_set_message_func (hb_buffer_t *buffer,
+			    hb_buffer_message_func_t func,
+			    void *user_data, hb_destroy_func_t destroy);
+
+
 HB_END_DECLS
 
 #endif /* HB_BUFFER_H */
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-common.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-common.cc	2016-08-05 14:37:07.930011566 +0300
@@ -281,12 +281,15 @@
 
 /**
  * hb_language_from_string:
- * @str: (array length=len) (element-type uint8_t): 
- * @len: 
+ * @str: (array length=len) (element-type uint8_t): a string representing
+ *       ISO 639 language code
+ * @len: length of the @str, or -1 if it is %NULL-terminated.
  *
- * 
+ * Converts @str representing an ISO 639 language code to the corresponding
+ * #hb_language_t.
  *
  * Return value: (transfer none):
+ * The #hb_language_t corresponding to the ISO 639 language code.
  *
  * Since: 0.9.2
  **/
@@ -314,11 +317,13 @@
 
 /**
  * hb_language_to_string:
- * @language: 
+ * @language: an #hb_language_t to convert.
  *
- * 
+ * See hb_language_from_string().
  *
- * Return value: (transfer none): 
+ * Return value: (transfer none):
+ * A %NULL-terminated string representing the @language. Must not be freed by
+ * the caller.
  *
  * Since: 0.9.2
  **/
@@ -357,11 +362,12 @@
 
 /**
  * hb_script_from_iso15924_tag:
- * @tag: 
+ * @tag: an #hb_tag_t representing an ISO 15924 tag.
  *
- * 
+ * Converts an ISO 15924 script tag to a corresponding #hb_script_t.
  *
  * Return value: 
+ * An #hb_script_t corresponding to the ISO 15924 tag.
  *
  * Since: 0.9.2
  **/
@@ -401,28 +407,33 @@
 
 /**
  * hb_script_from_string:
- * @s: (array length=len) (element-type uint8_t): 
- * @len: 
- *
- * 
+ * @str: (array length=len) (element-type uint8_t): a string representing an
+ *       ISO 15924 tag.
+ * @len: length of the @str, or -1 if it is %NULL-terminated.
+ *
+ * Converts a string @str representing an ISO 15924 script tag to a
+ * corresponding #hb_script_t. Shorthand for hb_tag_from_string() then
+ * hb_script_from_iso15924_tag().
  *
  * Return value: 
+ * An #hb_script_t corresponding to the ISO 15924 tag.
  *
  * Since: 0.9.2
  **/
 hb_script_t
-hb_script_from_string (const char *s, int len)
+hb_script_from_string (const char *str, int len)
 {
-  return hb_script_from_iso15924_tag (hb_tag_from_string (s, len));
+  return hb_script_from_iso15924_tag (hb_tag_from_string (str, len));
 }
 
 /**
  * hb_script_to_iso15924_tag:
- * @script: 
+ * @script: an #hb_script_ to convert.
  *
- * 
+ * See hb_script_from_iso15924_tag().
  *
- * Return value: 
+ * Return value:
+ * An #hb_tag_t representing an ISO 15924 script tag.
  *
  * Since: 0.9.2
  **/
@@ -521,7 +532,7 @@
     }
   }
   hb_user_data_item_t item = {key, data, destroy};
-  bool ret = !!items.replace_or_insert (item, lock, replace);
+  bool ret = !!items.replace_or_insert (item, lock, (bool) replace);
 
   return ret;
 }
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-common.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-common.h	2016-08-05 14:37:07.931011559 +0300
@@ -98,16 +98,22 @@
 #define HB_TAG_MAX_SIGNED HB_TAG(0x7f,0xff,0xff,0xff)
 
 /* len=-1 means str is NUL-terminated. */
-hb_tag_t
+HB_EXTERN hb_tag_t
 hb_tag_from_string (const char *str, int len);
 
 /* buf should have 4 bytes. */
-void
+HB_EXTERN void
 hb_tag_to_string (hb_tag_t tag, char *buf);
 
 
-/* hb_direction_t */
-
+/**
+ * hb_direction_t:
+ * @HB_DIRECTION_INVALID: Initial, unset direction.
+ * @HB_DIRECTION_LTR: Text is set horizontally from left to right.
+ * @HB_DIRECTION_RTL: Text is set horizontally from right to left.
+ * @HB_DIRECTION_TTB: Text is set vertically from top to bottom.
+ * @HB_DIRECTION_BTT: Text is set vertically from bottom to top.
+ */
 typedef enum {
   HB_DIRECTION_INVALID = 0,
   HB_DIRECTION_LTR = 4,
@@ -117,10 +123,10 @@
 } hb_direction_t;
 
 /* len=-1 means str is NUL-terminated */
-hb_direction_t
+HB_EXTERN hb_direction_t
 hb_direction_from_string (const char *str, int len);
 
-const char *
+HB_EXTERN const char *
 hb_direction_to_string (hb_direction_t direction);
 
 #define HB_DIRECTION_IS_VALID(dir)	((((unsigned int) (dir)) & ~3U) == 4)
@@ -136,16 +142,15 @@
 
 typedef const struct hb_language_impl_t *hb_language_t;
 
-/* len=-1 means str is NUL-terminated */
-hb_language_t
+HB_EXTERN hb_language_t
 hb_language_from_string (const char *str, int len);
 
-const char *
+HB_EXTERN const char *
 hb_language_to_string (hb_language_t language);
 
 #define HB_LANGUAGE_INVALID ((hb_language_t) NULL)
 
-hb_language_t
+HB_EXTERN hb_language_t
 hb_language_get_default (void);
 
 
@@ -324,18 +329,16 @@
 
 /* Script functions */
 
-hb_script_t
+HB_EXTERN hb_script_t
 hb_script_from_iso15924_tag (hb_tag_t tag);
 
-/* sugar for tag_from_string() then script_from_iso15924_tag */
-/* len=-1 means s is NUL-terminated */
-hb_script_t
-hb_script_from_string (const char *s, int len);
+HB_EXTERN hb_script_t
+hb_script_from_string (const char *str, int len);
 
-hb_tag_t
+HB_EXTERN hb_tag_t
 hb_script_to_iso15924_tag (hb_script_t script);
 
-hb_direction_t
+HB_EXTERN hb_direction_t
 hb_script_get_horizontal_direction (hb_script_t script);
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-coretext.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-coretext.cc	2016-08-05 14:37:07.931011559 +0300
@@ -176,6 +176,43 @@
     return NULL;
   }
 
+  /* Create font copy with cascade list that has LastResort first; this speeds up CoreText
+   * font fallback which we don't need anyway. */
+  {
+    // TODO Handle allocation failures?
+    CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize(CFSTR("LastResort"), 0);
+    CFArrayRef cascade_list = CFArrayCreate (kCFAllocatorDefault,
+					     (const void **) &last_resort,
+					     1,
+					     &kCFTypeArrayCallBacks);
+    CFRelease (last_resort);
+    CFDictionaryRef attributes = CFDictionaryCreate (kCFAllocatorDefault,
+						     (const void **) &kCTFontCascadeListAttribute,
+						     (const void **) &cascade_list,
+						     1,
+						     &kCFTypeDictionaryKeyCallBacks,
+						     &kCFTypeDictionaryValueCallBacks);
+    CFRelease (cascade_list);
+
+    CTFontDescriptorRef new_font_desc = CTFontDescriptorCreateWithAttributes (attributes);
+    CFRelease (attributes);
+
+    CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (data->ct_font, 0.0, NULL, new_font_desc);
+    if (new_ct_font)
+    {
+      CFRelease (data->ct_font);
+      data->ct_font = new_ct_font;
+    }
+    else
+      DEBUG_MSG (CORETEXT, font, "Font copy with empty cascade list failed");
+  }
+
+  if (unlikely (!data->ct_font)) {
+    DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed");
+    free (data);
+    return NULL;
+  }
+
   return data;
 }
 
@@ -693,7 +730,6 @@
     scratch += old_scratch_used;
     scratch_size -= old_scratch_used;
   }
-retry:
   {
     string_ref = CFStringCreateWithCharactersNoCopy (NULL,
 						     pchars, chars_len,
@@ -848,11 +884,9 @@
 	 * However, even that wouldn't work if we were passed in the CGFont to
 	 * begin with.
 	 *
-	 * Webkit uses a slightly different approach: it installs LastResort
-	 * as fallback chain, and then checks PS name of used font against
-	 * LastResort.  That one is safe for any font except for LastResort,
-	 * as opposed to ours, which can fail if we are using any uninstalled
-	 * font that has the same name as an installed font.
+	 * We might switch to checking PS name against "LastResort".  That would
+	 * be safe for all fonts except for those named "Last Resort".  Might be
+	 * better than what we have right now.
 	 *
 	 * See: http://github.com/behdad/harfbuzz/pull/36
 	 */
@@ -1129,10 +1163,6 @@
  * AAT shaper
  */
 
-HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, face)
-HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, font)
-
-
 /*
  * shaper face data
  */
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-coretext.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-coretext.h	2016-08-05 14:37:07.931011559 +0300
@@ -44,14 +44,14 @@
 #define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x')
 
 
-hb_face_t *
+HB_EXTERN hb_face_t *
 hb_coretext_face_create (CGFontRef cg_font);
 
 
-CGFontRef
+HB_EXTERN CGFontRef
 hb_coretext_face_get_cg_font (hb_face_t *face);
 
-CTFontRef
+HB_EXTERN CTFontRef
 hb_coretext_font_get_ct_font (hb_font_t *font);
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-directwrite.cc.1228540	2016-08-05 14:37:07.932011551 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-directwrite.cc	2016-08-05 14:37:07.932011551 +0300
@@ -0,0 +1,827 @@
+/*
+ * Copyright © 2015  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#define HB_SHAPER directwrite
+#include "hb-shaper-impl-private.hh"
+
+#include <dwrite.h>
+
+#include "hb-directwrite.h"
+
+#include "hb-open-file-private.hh"
+#include "hb-ot-name-table.hh"
+#include "hb-ot-tag.h"
+
+
+#ifndef HB_DEBUG_DIRECTWRITE
+#define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0)
+#endif
+
+HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, face)
+HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, font)
+
+/*
+* shaper face data
+*/
+
+struct hb_directwrite_shaper_face_data_t {
+  HANDLE fh;
+  wchar_t face_name[LF_FACESIZE];
+};
+
+/* face_name should point to a wchar_t[LF_FACESIZE] object. */
+static void
+_hb_generate_unique_face_name(wchar_t *face_name, unsigned int *plen)
+{
+  /* We'll create a private name for the font from a UUID using a simple,
+  * somewhat base64-like encoding scheme */
+  const char *enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";
+  UUID id;
+  UuidCreate ((UUID*)&id);
+  ASSERT_STATIC (2 + 3 * (16 / 2) < LF_FACESIZE);
+  unsigned int name_str_len = 0;
+  face_name[name_str_len++] = 'F';
+  face_name[name_str_len++] = '_';
+  unsigned char *p = (unsigned char *)&id;
+  for (unsigned int i = 0; i < 16; i += 2)
+  {
+    /* Spread the 16 bits from two bytes of the UUID across three chars of face_name,
+    * using the bits in groups of 5,5,6 to select chars from enc.
+    * This will generate 24 characters; with the 'F_' prefix we already provided,
+    * the name will be 26 chars (plus the NUL terminator), so will always fit within
+    * face_name (LF_FACESIZE = 32). */
+    face_name[name_str_len++] = enc[p[i] >> 3];
+    face_name[name_str_len++] = enc[((p[i] << 2) | (p[i + 1] >> 6)) & 0x1f];
+    face_name[name_str_len++] = enc[p[i + 1] & 0x3f];
+  }
+  face_name[name_str_len] = 0;
+  if (plen)
+    *plen = name_str_len;
+}
+
+/* Destroys blob. */
+static hb_blob_t *
+_hb_rename_font(hb_blob_t *blob, wchar_t *new_name)
+{
+  /* Create a copy of the font data, with the 'name' table replaced by a
+   * table that names the font with our private F_* name created above.
+   * For simplicity, we just append a new 'name' table and update the
+   * sfnt directory; the original table is left in place, but unused.
+   *
+   * The new table will contain just 5 name IDs: family, style, unique,
+   * full, PS. All of them point to the same name data with our unique name.
+   */
+
+  blob = OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (blob);
+
+  unsigned int length, new_length, name_str_len;
+  const char *orig_sfnt_data = hb_blob_get_data (blob, &length);
+
+  _hb_generate_unique_face_name (new_name, &name_str_len);
+
+  static const uint16_t name_IDs[] = { 1, 2, 3, 4, 6 };
+
+  unsigned int name_table_length = OT::name::min_size +
+    ARRAY_LENGTH(name_IDs) * OT::NameRecord::static_size +
+    name_str_len * 2; /* for name data in UTF16BE form */
+  unsigned int name_table_offset = (length + 3) & ~3;
+
+  new_length = name_table_offset + ((name_table_length + 3) & ~3);
+  void *new_sfnt_data = calloc(1, new_length);
+  if (!new_sfnt_data)
+  {
+    hb_blob_destroy (blob);
+    return NULL;
+  }
+
+  memcpy(new_sfnt_data, orig_sfnt_data, length);
+
+  OT::name &name = OT::StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
+  name.format.set (0);
+  name.count.set (ARRAY_LENGTH (name_IDs));
+  name.stringOffset.set (name.get_size());
+  for (unsigned int i = 0; i < ARRAY_LENGTH (name_IDs); i++)
+  {
+    OT::NameRecord &record = name.nameRecord[i];
+    record.platformID.set(3);
+    record.encodingID.set(1);
+    record.languageID.set(0x0409u); /* English */
+    record.nameID.set(name_IDs[i]);
+    record.length.set(name_str_len * 2);
+    record.offset.set(0);
+  }
+
+  /* Copy string data from new_name, converting wchar_t to UTF16BE. */
+  unsigned char *p = &OT::StructAfter<unsigned char>(name);
+  for (unsigned int i = 0; i < name_str_len; i++)
+  {
+    *p++ = new_name[i] >> 8;
+    *p++ = new_name[i] & 0xff;
+  }
+
+  /* Adjust name table entry to point to new name table */
+  const OT::OpenTypeFontFile &file = *(OT::OpenTypeFontFile *) (new_sfnt_data);
+  unsigned int face_count = file.get_face_count ();
+  for (unsigned int face_index = 0; face_index < face_count; face_index++)
+  {
+    /* Note: doing multiple edits (ie. TTC) can be unsafe.  There may be
+    * toe-stepping.  But we don't really care. */
+    const OT::OpenTypeFontFace &face = file.get_face (face_index);
+    unsigned int index;
+    if (face.find_table_index (HB_OT_TAG_name, &index))
+    {
+      OT::TableRecord &record = const_cast<OT::TableRecord &> (face.get_table (index));
+      record.checkSum.set_for_data (&name, name_table_length);
+      record.offset.set (name_table_offset);
+      record.length.set (name_table_length);
+    }
+    else if (face_index == 0) /* Fail if first face doesn't have 'name' table. */
+    {
+      free (new_sfnt_data);
+      hb_blob_destroy (blob);
+      return NULL;
+    }
+  }
+
+  /* The checkSumAdjustment field in the 'head' table is now wrong,
+  * but that doesn't actually seem to cause any problems so we don't
+  * bother. */
+
+  hb_blob_destroy (blob);
+  return hb_blob_create ((const char *)new_sfnt_data, new_length,
+    HB_MEMORY_MODE_WRITABLE, NULL, free);
+}
+
+hb_directwrite_shaper_face_data_t *
+_hb_directwrite_shaper_face_data_create(hb_face_t *face)
+{
+  hb_directwrite_shaper_face_data_t *data = (hb_directwrite_shaper_face_data_t *)calloc(1, sizeof (hb_directwrite_shaper_face_data_t));
+  if (unlikely (!data))
+    return NULL;
+
+  hb_blob_t *blob = hb_face_reference_blob (face);
+  if (unlikely (!hb_blob_get_length (blob)))
+    DEBUG_MSG(DIRECTWRITE, face, "Face has empty blob");
+
+  blob = _hb_rename_font (blob, data->face_name);
+  if (unlikely (!blob))
+  {
+    free(data);
+    return NULL;
+  }
+
+  DWORD num_fonts_installed;
+  data->fh = AddFontMemResourceEx ((void *)hb_blob_get_data(blob, NULL),
+    hb_blob_get_length (blob),
+    0, &num_fonts_installed);
+  if (unlikely (!data->fh))
+  {
+    DEBUG_MSG (DIRECTWRITE, face, "Face AddFontMemResourceEx() failed");
+    free (data);
+    return NULL;
+  }
+
+  return data;
+}
+
+void
+_hb_directwrite_shaper_face_data_destroy(hb_directwrite_shaper_face_data_t *data)
+{
+  RemoveFontMemResourceEx(data->fh);
+  free(data);
+}
+
+
+/*
+ * shaper font data
+ */
+
+struct hb_directwrite_shaper_font_data_t {
+  HDC hdc;
+  LOGFONTW log_font;
+  HFONT hfont;
+};
+
+static bool
+populate_log_font (LOGFONTW  *lf,
+       hb_font_t *font)
+{
+  memset (lf, 0, sizeof (*lf));
+  lf->lfHeight = -font->y_scale;
+  lf->lfCharSet = DEFAULT_CHARSET;
+
+  hb_face_t *face = font->face;
+  hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
+
+  memcpy (lf->lfFaceName, face_data->face_name, sizeof (lf->lfFaceName));
+
+  return true;
+}
+
+hb_directwrite_shaper_font_data_t *
+_hb_directwrite_shaper_font_data_create (hb_font_t *font)
+{
+  if (unlikely (!hb_directwrite_shaper_face_data_ensure (font->face))) return NULL;
+
+  hb_directwrite_shaper_font_data_t *data = (hb_directwrite_shaper_font_data_t *) calloc (1, sizeof (hb_directwrite_shaper_font_data_t));
+  if (unlikely (!data))
+    return NULL;
+
+  data->hdc = GetDC (NULL);
+
+  if (unlikely (!populate_log_font (&data->log_font, font))) {
+    DEBUG_MSG (DIRECTWRITE, font, "Font populate_log_font() failed");
+    _hb_directwrite_shaper_font_data_destroy (data);
+    return NULL;
+  }
+
+  data->hfont = CreateFontIndirectW (&data->log_font);
+  if (unlikely (!data->hfont)) {
+    DEBUG_MSG (DIRECTWRITE, font, "Font CreateFontIndirectW() failed");
+    _hb_directwrite_shaper_font_data_destroy (data);
+     return NULL;
+  }
+
+  if (!SelectObject (data->hdc, data->hfont)) {
+    DEBUG_MSG (DIRECTWRITE, font, "Font SelectObject() failed");
+    _hb_directwrite_shaper_font_data_destroy (data);
+     return NULL;
+  }
+
+  return data;
+}
+
+void
+_hb_directwrite_shaper_font_data_destroy (hb_directwrite_shaper_font_data_t *data)
+{
+  if (data->hdc)
+    ReleaseDC (NULL, data->hdc);
+  if (data->hfont)
+    DeleteObject (data->hfont);
+  free (data);
+}
+
+LOGFONTW *
+hb_directwrite_font_get_logfontw (hb_font_t *font)
+{
+  if (unlikely (!hb_directwrite_shaper_font_data_ensure (font))) return NULL;
+  hb_directwrite_shaper_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
+  return &font_data->log_font;
+}
+
+HFONT
+hb_directwrite_font_get_hfont (hb_font_t *font)
+{
+  if (unlikely (!hb_directwrite_shaper_font_data_ensure (font))) return NULL;
+  hb_directwrite_shaper_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
+  return font_data->hfont;
+}
+
+
+/*
+ * shaper shape_plan data
+ */
+
+struct hb_directwrite_shaper_shape_plan_data_t {};
+
+hb_directwrite_shaper_shape_plan_data_t *
+_hb_directwrite_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
+               const hb_feature_t *user_features HB_UNUSED,
+               unsigned int        num_user_features HB_UNUSED)
+{
+  return (hb_directwrite_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+}
+
+void
+_hb_directwrite_shaper_shape_plan_data_destroy (hb_directwrite_shaper_shape_plan_data_t *data HB_UNUSED)
+{
+}
+
+// Most of here TextAnalysis is originally written by Bas Schouten for Mozilla project
+// but now is relicensed to MIT for HarfBuzz use
+class TextAnalysis
+  : public IDWriteTextAnalysisSource, public IDWriteTextAnalysisSink
+{
+public:
+
+  IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) { return S_OK; }
+  IFACEMETHOD_(ULONG, AddRef)() { return 1; }
+  IFACEMETHOD_(ULONG, Release)() { return 1; }
+
+  // A single contiguous run of characters containing the same analysis 
+  // results.
+  struct Run
+  {
+    UINT32 mTextStart;   // starting text position of this run
+    UINT32 mTextLength;  // number of contiguous code units covered
+    UINT32 mGlyphStart;  // starting glyph in the glyphs array
+    UINT32 mGlyphCount;  // number of glyphs associated with this run of 
+    // text
+    DWRITE_SCRIPT_ANALYSIS mScript;
+    UINT8 mBidiLevel;
+    bool mIsSideways;
+
+    inline bool ContainsTextPosition(UINT32 aTextPosition) const
+    {
+      return aTextPosition >= mTextStart
+        && aTextPosition <  mTextStart + mTextLength;
+    }
+
+    Run *nextRun;
+  };
+
+public:
+  TextAnalysis(const wchar_t* text,
+    UINT32 textLength,
+    const wchar_t* localeName,
+    DWRITE_READING_DIRECTION readingDirection)
+    : mText(text)
+    , mTextLength(textLength)
+    , mLocaleName(localeName)
+    , mReadingDirection(readingDirection)
+    , mCurrentRun(NULL) { };
+
+  ~TextAnalysis() {
+    // delete runs, except mRunHead which is part of the TextAnalysis object
+    for (Run *run = mRunHead.nextRun; run;) {
+      Run *origRun = run;
+      run = run->nextRun;
+      delete origRun;
+    }
+  }
+
+  STDMETHODIMP GenerateResults(IDWriteTextAnalyzer* textAnalyzer,
+    Run **runHead) {
+    // Analyzes the text using the script analyzer and returns
+    // the result as a series of runs.
+
+    HRESULT hr = S_OK;
+
+    // Initially start out with one result that covers the entire range.
+    // This result will be subdivided by the analysis processes.
+    mRunHead.mTextStart = 0;
+    mRunHead.mTextLength = mTextLength;
+    mRunHead.mBidiLevel =
+      (mReadingDirection == DWRITE_READING_DIRECTION_RIGHT_TO_LEFT);
+    mRunHead.nextRun = NULL;
+    mCurrentRun = &mRunHead;
+
+    // Call each of the analyzers in sequence, recording their results.
+    if (SUCCEEDED(hr = textAnalyzer->AnalyzeScript(this,
+      0,
+      mTextLength,
+      this))) {
+      *runHead = &mRunHead;
+    }
+
+    return hr;
+  }
+
+  // IDWriteTextAnalysisSource implementation
+
+  IFACEMETHODIMP GetTextAtPosition(UINT32 textPosition,
+    OUT WCHAR const** textString,
+    OUT UINT32* textLength)
+  {
+    if (textPosition >= mTextLength) {
+      // No text at this position, valid query though.
+      *textString = NULL;
+      *textLength = 0;
+    }
+    else {
+      *textString = mText + textPosition;
+      *textLength = mTextLength - textPosition;
+    }
+    return S_OK;
+  }
+
+  IFACEMETHODIMP GetTextBeforePosition(UINT32 textPosition,
+    OUT WCHAR const** textString,
+    OUT UINT32* textLength)
+  {
+    if (textPosition == 0 || textPosition > mTextLength) {
+      // Either there is no text before here (== 0), or this
+      // is an invalid position. The query is considered valid thouh.
+      *textString = NULL;
+      *textLength = 0;
+    }
+    else {
+      *textString = mText;
+      *textLength = textPosition;
+    }
+    return S_OK;
+  }
+
+  IFACEMETHODIMP_(DWRITE_READING_DIRECTION)
+    GetParagraphReadingDirection() { return mReadingDirection; }
+
+  IFACEMETHODIMP GetLocaleName(UINT32 textPosition,
+    UINT32* textLength,
+    WCHAR const** localeName) {
+    return S_OK;
+  }
+
+  IFACEMETHODIMP
+    GetNumberSubstitution(UINT32 textPosition,
+    OUT UINT32* textLength,
+    OUT IDWriteNumberSubstitution** numberSubstitution)
+  {
+    // We do not support number substitution.
+    *numberSubstitution = NULL;
+    *textLength = mTextLength - textPosition;
+
+    return S_OK;
+  }
+
+  // IDWriteTextAnalysisSink implementation
+
+  IFACEMETHODIMP
+    SetScriptAnalysis(UINT32 textPosition,
+    UINT32 textLength,
+    DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis)
+  {
+    SetCurrentRun(textPosition);
+    SplitCurrentRun(textPosition);
+    while (textLength > 0) {
+      Run *run = FetchNextRun(&textLength);
+      run->mScript = *scriptAnalysis;
+    }
+
+    return S_OK;
+  }
+
+  IFACEMETHODIMP
+    SetLineBreakpoints(UINT32 textPosition,
+    UINT32 textLength,
+    const DWRITE_LINE_BREAKPOINT* lineBreakpoints) { return S_OK; }
+
+  IFACEMETHODIMP SetBidiLevel(UINT32 textPosition,
+    UINT32 textLength,
+    UINT8 explicitLevel,
+    UINT8 resolvedLevel) { return S_OK; }
+
+  IFACEMETHODIMP
+    SetNumberSubstitution(UINT32 textPosition,
+    UINT32 textLength,
+    IDWriteNumberSubstitution* numberSubstitution) { return S_OK; }
+
+protected:
+  Run *FetchNextRun(IN OUT UINT32* textLength)
+  {
+    // Used by the sink setters, this returns a reference to the next run.
+    // Position and length are adjusted to now point after the current run
+    // being returned.
+
+    Run *origRun = mCurrentRun;
+    // Split the tail if needed (the length remaining is less than the
+    // current run's size).
+    if (*textLength < mCurrentRun->mTextLength) {
+      SplitCurrentRun(mCurrentRun->mTextStart + *textLength);
+    }
+    else {
+      // Just advance the current run.
+      mCurrentRun = mCurrentRun->nextRun;
+    }
+    *textLength -= origRun->mTextLength;
+
+    // Return a reference to the run that was just current.
+    return origRun;
+  }
+
+  void SetCurrentRun(UINT32 textPosition)
+  {
+    // Move the current run to the given position.
+    // Since the analyzers generally return results in a forward manner,
+    // this will usually just return early. If not, find the
+    // corresponding run for the text position.
+
+    if (mCurrentRun && mCurrentRun->ContainsTextPosition(textPosition)) {
+      return;
+    }
+
+    for (Run *run = &mRunHead; run; run = run->nextRun) {
+      if (run->ContainsTextPosition(textPosition)) {
+        mCurrentRun = run;
+        return;
+      }
+    }
+    //NS_NOTREACHED("We should always be able to find the text position in one \
+            //                of our runs");
+  }
+
+  void SplitCurrentRun(UINT32 splitPosition)
+  {
+    if (!mCurrentRun) {
+      //NS_ASSERTION(false, "SplitCurrentRun called without current run.");
+      // Shouldn't be calling this when no current run is set!
+      return;
+    }
+    // Split the current run.
+    if (splitPosition <= mCurrentRun->mTextStart) {
+      // No need to split, already the start of a run
+      // or before it. Usually the first.
+      return;
+    }
+    Run *newRun = new Run;
+
+    *newRun = *mCurrentRun;
+
+    // Insert the new run in our linked list.
+    newRun->nextRun = mCurrentRun->nextRun;
+    mCurrentRun->nextRun = newRun;
+
+    // Adjust runs' text positions and lengths.
+    UINT32 splitPoint = splitPosition - mCurrentRun->mTextStart;
+    newRun->mTextStart += splitPoint;
+    newRun->mTextLength -= splitPoint;
+    mCurrentRun->mTextLength = splitPoint;
+    mCurrentRun = newRun;
+  }
+
+protected:
+  // Input
+  // (weak references are fine here, since this class is a transient
+  //  stack-based helper that doesn't need to copy data)
+  UINT32 mTextLength;
+  const WCHAR* mText;
+  const WCHAR* mLocaleName;
+  DWRITE_READING_DIRECTION mReadingDirection;
+
+  // Current processing state.
+  Run *mCurrentRun;
+
+  // Output is a list of runs starting here
+  Run  mRunHead;
+};
+
+
+/*
+ * shaper
+ */
+
+hb_bool_t
+_hb_directwrite_shape(hb_shape_plan_t    *shape_plan,
+  hb_font_t          *font,
+  hb_buffer_t        *buffer,
+  const hb_feature_t *features,
+  unsigned int        num_features)
+{
+  hb_face_t *face = font->face;
+  hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
+  hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
+
+  // factory probably should be cached
+  IDWriteFactory* dwriteFactory;
+  DWriteCreateFactory(
+    DWRITE_FACTORY_TYPE_SHARED,
+    __uuidof(IDWriteFactory),
+    reinterpret_cast<IUnknown**>(&dwriteFactory)
+    );
+
+  IDWriteGdiInterop *gdiInterop;
+  dwriteFactory->GetGdiInterop (&gdiInterop);
+  IDWriteFontFace* fontFace;
+  gdiInterop->CreateFontFaceFromHdc (font_data->hdc, &fontFace);
+
+  IDWriteTextAnalyzer* analyzer;
+  dwriteFactory->CreateTextAnalyzer (&analyzer);
+
+  unsigned int scratch_size;
+  hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
+#define ALLOCATE_ARRAY(Type, name, len) \
+  Type *name = (Type *) scratch; \
+  { \
+    unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
+    assert (_consumed <= scratch_size); \
+    scratch += _consumed; \
+    scratch_size -= _consumed; \
+  }
+
+#define utf16_index() var1.u32
+
+  ALLOCATE_ARRAY(WCHAR, pchars, buffer->len * 2);
+
+  unsigned int chars_len = 0;
+  for (unsigned int i = 0; i < buffer->len; i++)
+  {
+    hb_codepoint_t c = buffer->info[i].codepoint;
+    buffer->info[i].utf16_index() = chars_len;
+    if (likely(c <= 0xFFFFu))
+      pchars[chars_len++] = c;
+    else if (unlikely(c > 0x10FFFFu))
+      pchars[chars_len++] = 0xFFFDu;
+    else {
+      pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
+      pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1));
+    }
+  }
+
+  ALLOCATE_ARRAY(WORD, log_clusters, chars_len);
+  if (num_features)
+  {
+    /* Need log_clusters to assign features. */
+    chars_len = 0;
+    for (unsigned int i = 0; i < buffer->len; i++)
+    {
+      hb_codepoint_t c = buffer->info[i].codepoint;
+      unsigned int cluster = buffer->info[i].cluster;
+      log_clusters[chars_len++] = cluster;
+      if (hb_in_range(c, 0x10000u, 0x10FFFFu))
+        log_clusters[chars_len++] = cluster; /* Surrogates. */
+    }
+  }
+
+  HRESULT hr;
+  // TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES
+
+  DWRITE_READING_DIRECTION readingDirection = buffer->props.direction ? 
+    DWRITE_READING_DIRECTION_RIGHT_TO_LEFT :
+    DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
+
+  /*
+  * There's an internal 16-bit limit on some things inside the analyzer,
+  * but we never attempt to shape a word longer than 64K characters
+  * in a single gfxShapedWord, so we cannot exceed that limit.
+  */
+  UINT32 length = buffer->len;
+
+  TextAnalysis analysis(pchars, length, NULL, readingDirection);
+  TextAnalysis::Run *runHead;
+  hr = analysis.GenerateResults(analyzer, &runHead);
+
+  if (FAILED(hr)) {
+    //NS_WARNING("Analyzer failed to generate results.");
+    return false;
+  }
+
+  UINT32 maxGlyphs = 3 * length / 2 + 16;
+
+#define INITIAL_GLYPH_SIZE 400
+  UINT16* clusters = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16));
+  UINT16* glyphs = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16));
+  DWRITE_SHAPING_TEXT_PROPERTIES* textProperties = (DWRITE_SHAPING_TEXT_PROPERTIES*)
+    malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_TEXT_PROPERTIES));
+  DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*)
+    malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES));
+
+  UINT32 actualGlyphs;
+
+  bool backward = HB_DIRECTION_IS_BACKWARD(buffer->props.direction);
+
+  wchar_t lang[4];
+  mbstowcs(lang, hb_language_to_string(buffer->props.language), 4);
+  hr = analyzer->GetGlyphs(pchars, length,
+    fontFace, FALSE,
+    buffer->props.direction,
+    &runHead->mScript, (const wchar_t*)lang, NULL, NULL, NULL, 0,
+    maxGlyphs, clusters, textProperties,
+    glyphs, glyphProperties, &actualGlyphs);
+
+  if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) {
+    free(clusters);
+    free(glyphs);
+    free(textProperties);
+    free(glyphProperties);
+
+    clusters = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16));
+    glyphs = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16));
+    textProperties = (DWRITE_SHAPING_TEXT_PROPERTIES*)
+      malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_TEXT_PROPERTIES));
+    glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*)
+      malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES));
+
+    hr = analyzer->GetGlyphs(pchars, length,
+      fontFace, FALSE,
+      buffer->props.direction,
+      &runHead->mScript, (const wchar_t*)lang, NULL, NULL, NULL, 0,
+      maxGlyphs, clusters, textProperties,
+      glyphs, glyphProperties, &actualGlyphs);
+  }
+  if (FAILED(hr)) {
+    //NS_WARNING("Analyzer failed to get glyphs.");
+    return false;
+  }
+
+  FLOAT advances[400];
+  DWRITE_GLYPH_OFFSET offsets[400];
+
+
+  /* The -2 in the following is to compensate for possible
+   * alignment needed after the WORD array.  sizeof(WORD) == 2. */
+  unsigned int glyphs_size = (scratch_size * sizeof (int)-2)
+    / (sizeof (WORD) +
+    4 + // sizeof (SCRIPT_GLYPHPROP) +
+    sizeof (int) +
+    8 + // sizeof (GOFFSET) +
+    sizeof (uint32_t));
+  ALLOCATE_ARRAY(uint32_t, vis_clusters, glyphs_size);
+
+#undef ALLOCATE_ARRAY
+
+  hr = analyzer->GetGlyphPlacements(pchars,
+    clusters,
+    textProperties,
+    length,
+    glyphs,
+    glyphProperties,
+    actualGlyphs,
+    fontFace,
+    face->get_upem(),
+    FALSE,
+    FALSE,
+    &runHead->mScript,
+    NULL,
+    NULL,
+    NULL,
+    0,
+    advances,
+    offsets);
+
+  if (FAILED(hr)) {
+    //NS_WARNING("Analyzer failed to get glyph placements.");
+    return false;
+  }
+
+  unsigned int glyphs_len = actualGlyphs;
+
+  /* Ok, we've got everything we need, now compose output buffer,
+   * very, *very*, carefully! */
+
+  /* Calculate visual-clusters.  That's what we ship. */
+  for (unsigned int i = 0; i < glyphs_len; i++)
+    vis_clusters[i] = -1;
+  for (unsigned int i = 0; i < buffer->len; i++) {
+    uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]];
+    //*p = MIN (*p, buffer->info[i].cluster);
+  }
+  for (unsigned int i = 1; i < glyphs_len; i++)
+    if (vis_clusters[i] == -1)
+      vis_clusters[i] = vis_clusters[i - 1];
+
+#undef utf16_index
+
+  //if (unlikely (!buffer->ensure (glyphs_len)))
+  //  FAIL ("Buffer in error");
+
+#undef FAIL
+
+  /* Set glyph infos */
+  buffer->len = 0;
+  for (unsigned int i = 0; i < glyphs_len; i++)
+  {
+    hb_glyph_info_t *info = &buffer->info[buffer->len++];
+
+    info->codepoint = glyphs[i];
+    info->cluster = vis_clusters[i];
+
+    /* The rest is crap.  Let's store position info there for now. */
+    info->mask = advances[i];
+    info->var1.u32 = offsets[i].ascenderOffset;
+    info->var2.u32 = -offsets[i].advanceOffset;
+  }
+
+  free(clusters);
+  free(glyphs);
+  free(textProperties);
+  free(glyphProperties);
+
+  /* Set glyph positions */
+  buffer->clear_positions ();
+  for (unsigned int i = 0; i < glyphs_len; i++)
+  {
+    hb_glyph_info_t *info = &buffer->info[i];
+    hb_glyph_position_t *pos = &buffer->pos[i];
+
+    /* TODO vertical */
+    pos->x_advance = info->mask;
+    pos->x_offset = backward ? -info->var1.u32 : info->var1.u32;
+    pos->y_offset = info->var2.u32;
+  }
+
+  if (backward)
+    hb_buffer_reverse (buffer);
+
+  /* Wow, done! */
+  return true;
+}
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-directwrite.h.1228540	2016-08-05 14:37:07.932011551 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-directwrite.h	2016-08-05 14:37:07.932011551 +0300
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2015  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_DIRECTWRITE_H
+#define HB_DIRECTWRITE_H
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+
+HB_END_DECLS
+
+#endif /* HB_UNISCRIBE_H */
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-face.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-face.h	2016-08-05 14:37:07.933011544 +0300
@@ -43,28 +43,28 @@
 
 typedef struct hb_face_t hb_face_t;
 
-hb_face_t *
+HB_EXTERN hb_face_t *
 hb_face_create (hb_blob_t    *blob,
 		unsigned int  index);
 
 typedef hb_blob_t * (*hb_reference_table_func_t)  (hb_face_t *face, hb_tag_t tag, void *user_data);
 
 /* calls destroy() when not needing user_data anymore */
-hb_face_t *
+HB_EXTERN 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 *
+HB_EXTERN hb_face_t *
 hb_face_get_empty (void);
 
-hb_face_t *
+HB_EXTERN hb_face_t *
 hb_face_reference (hb_face_t *face);
 
-void
+HB_EXTERN void
 hb_face_destroy (hb_face_t *face);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_face_set_user_data (hb_face_t          *face,
 		       hb_user_data_key_t *key,
 		       void *              data,
@@ -72,43 +72,43 @@
 		       hb_bool_t           replace);
 
 
-void *
+HB_EXTERN void *
 hb_face_get_user_data (hb_face_t          *face,
 		       hb_user_data_key_t *key);
 
-void
+HB_EXTERN void
 hb_face_make_immutable (hb_face_t *face);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_face_is_immutable (hb_face_t *face);
 
 
-hb_blob_t *
+HB_EXTERN hb_blob_t *
 hb_face_reference_table (hb_face_t *face,
 			 hb_tag_t   tag);
 
-hb_blob_t *
+HB_EXTERN hb_blob_t *
 hb_face_reference_blob (hb_face_t *face);
 
-void
+HB_EXTERN void
 hb_face_set_index (hb_face_t    *face,
 		   unsigned int  index);
 
-unsigned int
+HB_EXTERN unsigned int
 hb_face_get_index (hb_face_t    *face);
 
-void
+HB_EXTERN void
 hb_face_set_upem (hb_face_t    *face,
 		  unsigned int  upem);
 
-unsigned int
+HB_EXTERN unsigned int
 hb_face_get_upem (hb_face_t *face);
 
-void
+HB_EXTERN void
 hb_face_set_glyph_count (hb_face_t    *face,
 			 unsigned int  glyph_count);
 
-unsigned int
+HB_EXTERN unsigned int
 hb_face_get_glyph_count (hb_face_t *face);
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-fallback-shape.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-fallback-shape.cc	2016-08-05 14:37:07.933011544 +0300
@@ -106,7 +106,7 @@
    */
 
   hb_codepoint_t space;
-  bool has_space = font->get_glyph (' ', 0, &space);
+  bool has_space = (bool) font->get_glyph (' ', 0, &space);
 
   buffer->clear_positions ();
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-font-private.hh.1228540	2016-06-04 03:12:40.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-font-private.hh	2016-08-05 14:37:07.933011544 +0300
@@ -42,6 +42,8 @@
  */
 
 #define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
+  HB_FONT_FUNC_IMPLEMENT (font_h_extents) \
+  HB_FONT_FUNC_IMPLEMENT (font_v_extents) \
   HB_FONT_FUNC_IMPLEMENT (glyph) \
   HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
   HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
@@ -160,7 +162,22 @@
   HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 #undef HB_FONT_FUNC_IMPLEMENT
 
-  inline hb_bool_t has_glyph (hb_codepoint_t unicode)
+  inline hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
+  {
+    memset (extents, 0, sizeof (*extents));
+    return klass->get.f.font_h_extents (this, user_data,
+					extents,
+					klass->user_data.font_h_extents);
+  }
+  inline hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
+  {
+    memset (extents, 0, sizeof (*extents));
+    return klass->get.f.font_v_extents (this, user_data,
+					extents,
+					klass->user_data.font_v_extents);
+  }
+
+  inline bool has_glyph (hb_codepoint_t unicode)
   {
     hb_codepoint_t glyph;
     return get_glyph (unicode, 0, &glyph);
@@ -265,6 +282,26 @@
 
   /* A bit higher-level, and with fallback */
 
+  inline void get_extents_for_direction (hb_direction_t direction,
+					 hb_font_extents_t *extents)
+  {
+    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
+      if (!get_font_h_extents (extents))
+      {
+	extents->ascender = y_scale * .8;
+	extents->descender = y_scale - extents->ascender;
+	extents->line_gap = 0;
+      }
+    } else {
+      if (!get_font_v_extents (extents))
+      {
+	extents->ascender = x_scale / 2;
+	extents->descender = x_scale - extents->ascender;
+	extents->line_gap = 0;
+      }
+    }
+  }
+
   inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
 					       hb_direction_t direction,
 					       hb_position_t *x, hb_position_t *y)
@@ -284,7 +321,7 @@
   {
     *x = get_glyph_h_advance (glyph) / 2;
 
-    /* TODO use font_metrics.ascent */
+    /* TODO use font_extents.ascender */
     *y = y_scale;
   }
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-font.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-font.cc	2016-08-05 14:37:07.934011536 +0300
@@ -45,6 +45,54 @@
  */
 
 static hb_bool_t
+hb_font_get_font_h_extents_nil (hb_font_t *font,
+				void *font_data HB_UNUSED,
+				hb_font_extents_t *metrics,
+				void *user_data HB_UNUSED)
+{
+  memset (metrics, 0, sizeof (*metrics));
+  return false;
+}
+static hb_bool_t
+hb_font_get_font_h_extents_parent (hb_font_t *font,
+				   void *font_data HB_UNUSED,
+				   hb_font_extents_t *metrics,
+				   void *user_data HB_UNUSED)
+{
+  hb_bool_t ret = font->parent->get_font_h_extents (metrics);
+  if (ret) {
+    metrics->ascender = font->parent_scale_y_distance (metrics->ascender);
+    metrics->descender = font->parent_scale_y_distance (metrics->descender);
+    metrics->line_gap = font->parent_scale_y_distance (metrics->line_gap);
+  }
+  return ret;
+}
+
+static hb_bool_t
+hb_font_get_font_v_extents_nil (hb_font_t *font,
+				void *font_data HB_UNUSED,
+				hb_font_extents_t *metrics,
+				void *user_data HB_UNUSED)
+{
+  memset (metrics, 0, sizeof (*metrics));
+  return false;
+}
+static hb_bool_t
+hb_font_get_font_v_extents_parent (hb_font_t *font,
+				   void *font_data HB_UNUSED,
+				   hb_font_extents_t *metrics,
+				   void *user_data HB_UNUSED)
+{
+  hb_bool_t ret = font->parent->get_font_v_extents (metrics);
+  if (ret) {
+    metrics->ascender = font->parent_scale_x_distance (metrics->ascender);
+    metrics->descender = font->parent_scale_x_distance (metrics->descender);
+    metrics->line_gap = font->parent_scale_x_distance (metrics->line_gap);
+  }
+  return ret;
+}
+
+static hb_bool_t
 hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
 		       void *font_data HB_UNUSED,
 		       hb_codepoint_t unicode,
@@ -109,7 +157,7 @@
 				void *user_data HB_UNUSED)
 {
   *x = *y = 0;
-  return false;
+  return true;
 }
 static hb_bool_t
 hb_font_get_glyph_h_origin_parent (hb_font_t *font,
@@ -280,7 +328,6 @@
   return font->parent->get_glyph_from_name (name, len, glyph);
 }
 
-
 static const hb_font_funcs_t _hb_font_funcs_nil = {
   HB_OBJECT_HEADER_STATIC,
 
@@ -522,6 +569,42 @@
 /* Public getters */
 
 /**
+ * hb_font_get_h_extents:
+ * @font: a font.
+ * @extents: (out):
+ *
+ *
+ *
+ * Return value:
+ *
+ * Since: 1.1.3
+ **/
+hb_bool_t
+hb_font_get_h_extents (hb_font_t *font,
+		       hb_font_extents_t *extents)
+{
+  return font->get_font_h_extents (extents);
+}
+
+/**
+ * hb_font_get_v_extents:
+ * @font: a font.
+ * @extents: (out):
+ *
+ *
+ *
+ * Return value:
+ *
+ * Since: 1.1.3
+ **/
+hb_bool_t
+hb_font_get_v_extents (hb_font_t *font,
+		       hb_font_extents_t *extents)
+{
+  return font->get_font_v_extents (extents);
+}
+
+/**
  * hb_font_get_glyph:
  * @font: a font.
  * @unicode: 
@@ -746,6 +829,23 @@
 /* A bit higher-level, and with fallback */
 
 /**
+ * hb_font_get_extents_for_direction:
+ * @font: a font.
+ * @direction:
+ * @extents:
+ *
+ *
+ *
+ * Since: 1.1.3
+ **/
+void
+hb_font_get_extents_for_direction (hb_font_t *font,
+				   hb_direction_t direction,
+				   hb_font_extents_t *extents)
+{
+  return font->get_extents_for_direction (direction, extents);
+}
+/**
  * hb_font_get_glyph_advance_for_direction:
  * @font: a font.
  * @glyph: 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-font.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-font.h	2016-08-05 14:37:07.935011529 +0300
@@ -46,19 +46,19 @@
 
 typedef struct hb_font_funcs_t hb_font_funcs_t;
 
-hb_font_funcs_t *
+HB_EXTERN hb_font_funcs_t *
 hb_font_funcs_create (void);
 
-hb_font_funcs_t *
+HB_EXTERN hb_font_funcs_t *
 hb_font_funcs_get_empty (void);
 
-hb_font_funcs_t *
+HB_EXTERN hb_font_funcs_t *
 hb_font_funcs_reference (hb_font_funcs_t *ffuncs);
 
-void
+HB_EXTERN void
 hb_font_funcs_destroy (hb_font_funcs_t *ffuncs);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_font_funcs_set_user_data (hb_font_funcs_t    *ffuncs,
 			     hb_user_data_key_t *key,
 			     void *              data,
@@ -66,19 +66,37 @@
 			     hb_bool_t           replace);
 
 
-void *
+HB_EXTERN void *
 hb_font_funcs_get_user_data (hb_font_funcs_t    *ffuncs,
 			     hb_user_data_key_t *key);
 
 
-void
+HB_EXTERN void
 hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs);
 
 
-/* glyph extents */
+/* font and glyph extents */
+
+/* Note that typically ascender is positive and descender negative in coordinate systems that grow up. */
+typedef struct hb_font_extents_t
+{
+  hb_position_t ascender; /* typographic ascender. */
+  hb_position_t descender; /* typographic descender. */
+  hb_position_t line_gap; /* suggested line spacing gap. */
+  /*< private >*/
+  hb_position_t reserved9;
+  hb_position_t reserved8;
+  hb_position_t reserved7;
+  hb_position_t reserved6;
+  hb_position_t reserved5;
+  hb_position_t reserved4;
+  hb_position_t reserved3;
+  hb_position_t reserved2;
+  hb_position_t reserved1;
+} hb_font_extents_t;
 
 /* Note that height is negative in coordinate systems that grow up. */
 typedef struct hb_glyph_extents_t
@@ -89,9 +107,15 @@
   hb_position_t height; /* distance from top to bottom side. */
 } hb_glyph_extents_t;
 
-
 /* func types */
 
+typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *font_data,
+						       hb_font_extents_t *metrics,
+						       void *user_data);
+typedef hb_font_get_font_extents_func_t hb_font_get_font_h_extents_func_t;
+typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t;
+
+
 typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data,
 					       hb_codepoint_t unicode, hb_codepoint_t variation_selector,
 					       hb_codepoint_t *glyph,
@@ -141,6 +165,38 @@
 /* func setters */
 
 /**
+ * hb_font_funcs_set_font_h_extents_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 1.1.2
+ **/
+HB_EXTERN void
+hb_font_funcs_set_font_h_extents_func (hb_font_funcs_t *ffuncs,
+				       hb_font_get_font_h_extents_func_t func,
+				       void *user_data, hb_destroy_func_t destroy);
+
+/**
+ * hb_font_funcs_set_font_v_extents_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 1.1.2
+ **/
+HB_EXTERN void
+hb_font_funcs_set_font_v_extents_func (hb_font_funcs_t *ffuncs,
+				       hb_font_get_font_v_extents_func_t func,
+				       void *user_data, hb_destroy_func_t destroy);
+
+/**
  * hb_font_funcs_set_glyph_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
@@ -151,7 +207,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN void
 hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
 			      hb_font_get_glyph_func_t func,
 			      void *user_data, hb_destroy_func_t destroy);
@@ -167,7 +223,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN 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);
@@ -183,7 +239,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN 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);
@@ -199,7 +255,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN 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);
@@ -215,7 +271,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN 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);
@@ -231,7 +287,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN 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);
@@ -247,7 +303,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN 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);
@@ -263,7 +319,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN 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);
@@ -279,7 +335,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN 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);
@@ -295,7 +351,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN void
 hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs,
 				   hb_font_get_glyph_name_func_t func,
 				   void *user_data, hb_destroy_func_t destroy);
@@ -311,57 +367,63 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN void
 hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs,
 					hb_font_get_glyph_from_name_func_t func,
 					void *user_data, hb_destroy_func_t destroy);
 
-
 /* func dispatch */
 
-hb_bool_t
+HB_EXTERN hb_bool_t
+hb_font_get_h_extents (hb_font_t *font,
+		       hb_font_extents_t *extents);
+HB_EXTERN hb_bool_t
+hb_font_get_v_extents (hb_font_t *font,
+		       hb_font_extents_t *extents);
+
+HB_EXTERN hb_bool_t
 hb_font_get_glyph (hb_font_t *font,
 		   hb_codepoint_t unicode, hb_codepoint_t variation_selector,
 		   hb_codepoint_t *glyph);
 
-hb_position_t
+HB_EXTERN hb_position_t
 hb_font_get_glyph_h_advance (hb_font_t *font,
 			     hb_codepoint_t glyph);
-hb_position_t
+HB_EXTERN hb_position_t
 hb_font_get_glyph_v_advance (hb_font_t *font,
 			     hb_codepoint_t glyph);
 
-hb_bool_t
+HB_EXTERN 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);
-hb_bool_t
+HB_EXTERN 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);
 
-hb_position_t
+HB_EXTERN hb_position_t
 hb_font_get_glyph_h_kerning (hb_font_t *font,
 			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
-hb_position_t
+HB_EXTERN hb_position_t
 hb_font_get_glyph_v_kerning (hb_font_t *font,
 			     hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_font_get_glyph_extents (hb_font_t *font,
 			   hb_codepoint_t glyph,
 			   hb_glyph_extents_t *extents);
 
-hb_bool_t
+HB_EXTERN 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);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_font_get_glyph_name (hb_font_t *font,
 			hb_codepoint_t glyph,
 			char *name, unsigned int size);
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_font_get_glyph_from_name (hb_font_t *font,
 			     const char *name, int len, /* -1 means nul-terminated */
 			     hb_codepoint_t *glyph);
@@ -369,52 +431,56 @@
 
 /* high-level funcs, with fallback */
 
-void
+HB_EXTERN void
+hb_font_get_extents_for_direction (hb_font_t *font,
+				   hb_direction_t direction,
+				   hb_font_extents_t *extents);
+HB_EXTERN 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);
-void
+HB_EXTERN 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);
-void
+HB_EXTERN 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);
-void
+HB_EXTERN 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);
 
-void
+HB_EXTERN 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);
 
-hb_bool_t
+HB_EXTERN 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);
 
-hb_bool_t
+HB_EXTERN 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);
 
 /* Generates gidDDD if glyph has no name. */
-void
+HB_EXTERN void
 hb_font_glyph_to_string (hb_font_t *font,
 			 hb_codepoint_t glyph,
 			 char *s, unsigned int size);
 /* Parses gidDDD and uniUUUU strings automatically. */
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_font_glyph_from_string (hb_font_t *font,
 			   const char *s, int len, /* -1 means nul-terminated */
 			   hb_codepoint_t *glyph);
@@ -426,22 +492,22 @@
 
 /* Fonts are very light-weight objects */
 
-hb_font_t *
+HB_EXTERN hb_font_t *
 hb_font_create (hb_face_t *face);
 
-hb_font_t *
+HB_EXTERN hb_font_t *
 hb_font_create_sub_font (hb_font_t *parent);
 
-hb_font_t *
+HB_EXTERN hb_font_t *
 hb_font_get_empty (void);
 
-hb_font_t *
+HB_EXTERN hb_font_t *
 hb_font_reference (hb_font_t *font);
 
-void
+HB_EXTERN void
 hb_font_destroy (hb_font_t *font);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_font_set_user_data (hb_font_t          *font,
 		       hb_user_data_key_t *key,
 		       void *              data,
@@ -449,46 +515,46 @@
 		       hb_bool_t           replace);
 
 
-void *
+HB_EXTERN void *
 hb_font_get_user_data (hb_font_t          *font,
 		       hb_user_data_key_t *key);
 
-void
+HB_EXTERN void
 hb_font_make_immutable (hb_font_t *font);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_font_is_immutable (hb_font_t *font);
 
-void
+HB_EXTERN void
 hb_font_set_parent (hb_font_t *font,
 		    hb_font_t *parent);
 
-hb_font_t *
+HB_EXTERN hb_font_t *
 hb_font_get_parent (hb_font_t *font);
 
-hb_face_t *
+HB_EXTERN hb_face_t *
 hb_font_get_face (hb_font_t *font);
 
 
-void
+HB_EXTERN void
 hb_font_set_funcs (hb_font_t         *font,
 		   hb_font_funcs_t   *klass,
 		   void              *font_data,
 		   hb_destroy_func_t  destroy);
 
 /* Be *very* careful with this function! */
-void
+HB_EXTERN void
 hb_font_set_funcs_data (hb_font_t         *font,
 		        void              *font_data,
 		        hb_destroy_func_t  destroy);
 
 
-void
+HB_EXTERN void
 hb_font_set_scale (hb_font_t *font,
 		   int x_scale,
 		   int y_scale);
 
-void
+HB_EXTERN void
 hb_font_get_scale (hb_font_t *font,
 		   int *x_scale,
 		   int *y_scale);
@@ -496,12 +562,12 @@
 /*
  * A zero value means "no hinting in that direction"
  */
-void
+HB_EXTERN void
 hb_font_set_ppem (hb_font_t *font,
 		  unsigned int x_ppem,
 		  unsigned int y_ppem);
 
-void
+HB_EXTERN void
 hb_font_get_ppem (hb_font_t *font,
 		  unsigned int *x_ppem,
 		  unsigned int *y_ppem);
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ft.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ft.cc	2016-08-05 14:37:07.935011529 +0300
@@ -366,6 +366,25 @@
   return *glyph != 0;
 }
 
+static hb_bool_t
+hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
+			  void *font_data,
+			  hb_font_extents_t *metrics,
+			  void *user_data HB_UNUSED)
+{
+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  FT_Face ft_face = ft_font->ft_face;
+  metrics->ascender = ft_face->size->metrics.ascender;
+  metrics->descender = ft_face->size->metrics.descender;
+  metrics->line_gap = ft_face->size->metrics.height - (ft_face->size->metrics.ascender - ft_face->size->metrics.descender);
+  if (font->y_scale < 0)
+  {
+    metrics->ascender = -metrics->ascender;
+    metrics->descender = -metrics->descender;
+    metrics->line_gap = -metrics->line_gap;
+  }
+  return true;
+}
 
 static hb_font_funcs_t *static_ft_funcs = NULL;
 
@@ -387,6 +406,8 @@
   {
     funcs = hb_font_funcs_create ();
 
+    hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, NULL, NULL);
+    //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, NULL, NULL);
     hb_font_funcs_set_glyph_func (funcs, hb_ft_get_glyph, NULL, NULL);
     hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, NULL, NULL);
     hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, NULL, NULL);
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ft.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ft.h	2016-08-05 14:37:07.935011529 +0300
@@ -59,7 +59,7 @@
  * probably should use (the more recent) hb_ft_face_create_referenced()
  * instead.
  */
-hb_face_t *
+HB_EXTERN hb_face_t *
 hb_ft_face_create (FT_Face           ft_face,
 		   hb_destroy_func_t destroy);
 
@@ -71,7 +71,7 @@
  * Client is still responsible for making sure that ft-face is destroyed
  * after hb-face is.
  */
-hb_face_t *
+HB_EXTERN hb_face_t *
 hb_ft_face_create_cached (FT_Face ft_face);
 
 /* This version is like hb_ft_face_create(), except that it calls
@@ -81,7 +81,7 @@
  * This is the most convenient version to use.  Use it unless you have
  * very good reasons not to.
  */
-hb_face_t *
+HB_EXTERN hb_face_t *
 hb_ft_face_create_referenced (FT_Face ft_face);
 
 
@@ -98,26 +98,26 @@
 
 /* See notes on hb_ft_face_create().  Same issues re lifecycle-management
  * apply here.  Use hb_ft_font_create_referenced() if you can. */
-hb_font_t *
+HB_EXTERN 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_EXTERN hb_font_t *
 hb_ft_font_create_referenced (FT_Face ft_face);
 
-FT_Face
+HB_EXTERN FT_Face
 hb_ft_font_get_face (hb_font_t *font);
 
-void
+HB_EXTERN void
 hb_ft_font_set_load_flags (hb_font_t *font, int load_flags);
 
-int
+HB_EXTERN 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_EXTERN void
 hb_ft_font_set_funcs (hb_font_t *font);
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-glib.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-glib.cc	2016-08-05 14:37:07.936011521 +0300
@@ -383,6 +383,8 @@
 }
 
 /**
+ * hb_glib_blob_create:
+ *
  * Since: 0.9.38
  **/
 hb_blob_t *
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-glib.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-glib.h	2016-08-05 14:37:07.936011521 +0300
@@ -36,17 +36,17 @@
 HB_BEGIN_DECLS
 
 
-hb_script_t
+HB_EXTERN hb_script_t
 hb_glib_script_to_script (GUnicodeScript script);
 
-GUnicodeScript
+HB_EXTERN GUnicodeScript
 hb_glib_script_from_script (hb_script_t script);
 
 
-hb_unicode_funcs_t *
+HB_EXTERN hb_unicode_funcs_t *
 hb_glib_get_unicode_funcs (void);
 
-hb_blob_t *
+HB_EXTERN hb_blob_t *
 hb_glib_blob_create (GBytes *gbytes);
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-gobject-enums.h.tmpl.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-gobject-enums.h.tmpl	2016-08-05 14:37:07.936011521 +0300
@@ -42,7 +42,7 @@
 /*** END file-header ***/
 
 /*** BEGIN value-header ***/
-GType @enum_name@_get_type (void) G_GNUC_CONST;
+HB_EXTERN GType @enum_name@_get_type (void) G_GNUC_CONST;
 #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
 
 /*** END value-header ***/
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-gobject-structs.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-gobject-structs.h	2016-08-05 14:37:07.936011521 +0300
@@ -43,60 +43,60 @@
 /**
  * Since: 0.9.2
  **/
-GType hb_gobject_blob_get_type (void);
+HB_EXTERN GType hb_gobject_blob_get_type (void);
 #define HB_GOBJECT_TYPE_BLOB (hb_gobject_blob_get_type ())
 
 /**
  * Since: 0.9.2
  **/
-GType hb_gobject_buffer_get_type (void);
+HB_EXTERN GType hb_gobject_buffer_get_type (void);
 #define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ())
 
 /**
  * Since: 0.9.2
  **/
-GType hb_gobject_face_get_type (void);
+HB_EXTERN GType hb_gobject_face_get_type (void);
 #define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ())
 
 /**
  * Since: 0.9.2
  **/
-GType hb_gobject_font_get_type (void);
+HB_EXTERN GType hb_gobject_font_get_type (void);
 #define HB_GOBJECT_TYPE_FONT (hb_gobject_font_get_type ())
 
 /**
  * Since: 0.9.2
  **/
-GType hb_gobject_font_funcs_get_type (void);
+HB_EXTERN GType hb_gobject_font_funcs_get_type (void);
 #define HB_GOBJECT_TYPE_FONT_FUNCS (hb_gobject_font_funcs_get_type ())
 
-GType hb_gobject_set_get_type (void);
+HB_EXTERN GType hb_gobject_set_get_type (void);
 #define HB_GOBJECT_TYPE_SET (hb_gobject_set_get_type ())
 
-GType hb_gobject_shape_plan_get_type (void);
+HB_EXTERN GType hb_gobject_shape_plan_get_type (void);
 #define HB_GOBJECT_TYPE_SHAPE_PLAN (hb_gobject_shape_plan_get_type ())
 
 /**
  * Since: 0.9.2
  **/
-GType hb_gobject_unicode_funcs_get_type (void);
+HB_EXTERN GType hb_gobject_unicode_funcs_get_type (void);
 #define HB_GOBJECT_TYPE_UNICODE_FUNCS (hb_gobject_unicode_funcs_get_type ())
 
 /* Value types */
 
-GType hb_gobject_feature_get_type (void);
+HB_EXTERN GType hb_gobject_feature_get_type (void);
 #define HB_GOBJECT_TYPE_FEATURE (hb_gobject_feature_get_type ())
 
-GType hb_gobject_glyph_info_get_type (void);
+HB_EXTERN GType hb_gobject_glyph_info_get_type (void);
 #define HB_GOBJECT_TYPE_GLYPH_INFO (hb_gobject_glyph_info_get_type ())
 
-GType hb_gobject_glyph_position_get_type (void);
+HB_EXTERN GType hb_gobject_glyph_position_get_type (void);
 #define HB_GOBJECT_TYPE_GLYPH_POSITION (hb_gobject_glyph_position_get_type ())
 
-GType hb_gobject_segment_properties_get_type (void);
+HB_EXTERN GType hb_gobject_segment_properties_get_type (void);
 #define HB_GOBJECT_TYPE_SEGMENT_PROPERTIES (hb_gobject_segment_properties_get_type ())
 
-GType hb_gobject_user_data_key_get_type (void);
+HB_EXTERN GType hb_gobject_user_data_key_get_type (void);
 #define HB_GOBJECT_TYPE_USER_DATA_KEY (hb_gobject_user_data_key_get_type ())
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-graphite2.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-graphite2.cc	2016-08-05 14:37:07.936011521 +0300
@@ -351,6 +351,7 @@
   }
   buffer->len = glyph_count;
 
+  float yscale = font->y_scale / font->x_scale;
   /* Positioning. */
   if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
   {
@@ -359,9 +360,9 @@
          is; pPos++, is = gr_slot_next_in_segment (is))
     {
       pPos->x_offset = gr_slot_origin_X (is) - curradvx;
-      pPos->y_offset = gr_slot_origin_Y (is) - curradvy;
+      pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy;
       pPos->x_advance = gr_slot_advance_X (is, grface, grfont);
-      pPos->y_advance = gr_slot_advance_Y (is, grface, grfont);
+      pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale;
       curradvx += pPos->x_advance;
       curradvy += pPos->y_advance;
     }
@@ -387,17 +388,17 @@
         for (tis = is, tinfo = info; tis && tinfo->cluster == currclus; tis = gr_slot_prev_in_segment (tis), tinfo--)
         {
           clusx += gr_slot_advance_X (tis, grface, grfont);
-          clusy += gr_slot_advance_Y (tis, grface, grfont);
+          clusy += gr_slot_advance_Y (tis, grface, grfont) * yscale;
         }
         curradvx += clusx;
         curradvy += clusy;
       }
       pPos->x_advance = gr_slot_advance_X (is, grface, grfont);
-      pPos->y_advance = gr_slot_advance_Y (is, grface, grfont);
+      pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale;
       curradvx -= pPos->x_advance;
       curradvy -= pPos->y_advance;
       pPos->x_offset = gr_slot_origin_X (is) - curradvx;
-      pPos->y_offset = gr_slot_origin_Y (is) - curradvy;
+      pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy;
     }
     hb_buffer_reverse_clusters (buffer);
   }
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-graphite2.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-graphite2.h	2016-08-05 14:37:07.937011514 +0300
@@ -36,10 +36,10 @@
 #define HB_GRAPHITE2_TAG_SILF HB_TAG('S','i','l','f')
 
 
-gr_face *
+HB_EXTERN gr_face *
 hb_graphite2_face_get_gr_face (hb_face_t *face);
 
-gr_font *
+HB_EXTERN gr_font *
 hb_graphite2_font_get_gr_font (hb_font_t *font);
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-icu.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-icu.h	2016-08-05 14:37:07.937011514 +0300
@@ -36,14 +36,14 @@
 HB_BEGIN_DECLS
 
 
-hb_script_t
+HB_EXTERN hb_script_t
 hb_icu_script_to_script (UScriptCode script);
 
-UScriptCode
+HB_EXTERN UScriptCode
 hb_icu_script_from_script (hb_script_t script);
 
 
-hb_unicode_funcs_t *
+HB_EXTERN hb_unicode_funcs_t *
 hb_icu_get_unicode_funcs (void);
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-font.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-font.cc	2016-08-05 14:37:07.938011506 +0300
@@ -35,6 +35,7 @@
 #include "hb-ot-head-table.hh"
 #include "hb-ot-hhea-table.hh"
 #include "hb-ot-hmtx-table.hh"
+#include "hb-ot-os2-table.hh"
 
 
 struct hb_ot_face_metrics_accelerator_t
@@ -42,17 +43,45 @@
   unsigned int num_metrics;
   unsigned int num_advances;
   unsigned int default_advance;
+  unsigned short ascender;
+  unsigned short descender;
+  unsigned short line_gap;
+
   const OT::_mtx *table;
   hb_blob_t *blob;
 
   inline void init (hb_face_t *face,
-		    hb_tag_t _hea_tag, hb_tag_t _mtx_tag)
+		    hb_tag_t _hea_tag,
+		    hb_tag_t _mtx_tag,
+		    hb_tag_t os2_tag)
   {
     this->default_advance = face->get_upem ();
 
+    bool got_font_extents = false;
+    if (os2_tag)
+    {
+      hb_blob_t *os2_blob = OT::Sanitizer<OT::os2>::sanitize (face->reference_table (os2_tag));
+      const OT::os2 *os2 = OT::Sanitizer<OT::os2>::lock_instance (os2_blob);
+#define USE_TYPO_METRICS (1u<<7)
+      if (0 != (os2->fsSelection & USE_TYPO_METRICS))
+      {
+	this->ascender = os2->sTypoAscender;
+	this->descender = os2->sTypoDescender;
+	this->line_gap = os2->sTypoLineGap;
+	got_font_extents = (this->ascender | this->descender) != 0;
+      }
+      hb_blob_destroy (os2_blob);
+    }
+
     hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag));
     const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob);
     this->num_advances = _hea->numberOfLongMetrics;
+    if (!got_font_extents)
+    {
+      this->ascender = _hea->ascender;
+      this->descender = _hea->descender;
+      this->line_gap = _hea->lineGap;
+    }
     hb_blob_destroy (_hea_blob);
 
     this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag));
@@ -252,8 +281,8 @@
     return NULL;
 
   ot_font->cmap.init (face);
-  ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx);
-  ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx); /* TODO Can we do this lazily? */
+  ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_os2);
+  ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE); /* TODO Can we do this lazily? */
   ot_font->glyf.init (face);
 
   return ot_font;
@@ -320,6 +349,31 @@
   return ret;
 }
 
+static hb_bool_t
+hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED,
+			  void *font_data,
+			  hb_font_extents_t *metrics,
+			  void *user_data HB_UNUSED)
+{
+  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+  metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender);
+  metrics->descender = font->em_scale_y (ot_font->h_metrics.descender);
+  metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap);
+  return true;
+}
+
+static hb_bool_t
+hb_ot_get_font_v_extents (hb_font_t *font HB_UNUSED,
+			  void *font_data,
+			  hb_font_extents_t *metrics,
+			  void *user_data HB_UNUSED)
+{
+  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+  metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender);
+  metrics->descender = font->em_scale_x (ot_font->v_metrics.descender);
+  metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap);
+  return true;
+}
 
 static hb_font_funcs_t *static_ot_funcs = NULL;
 
@@ -341,6 +395,8 @@
   {
     funcs = hb_font_funcs_create ();
 
+    hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, NULL, NULL);
+    hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, NULL, NULL);
     hb_font_funcs_set_glyph_func (funcs, hb_ot_get_glyph, NULL, NULL);
     hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, NULL, NULL);
     hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, NULL, NULL);
@@ -370,6 +426,8 @@
 
 
 /**
+ * hb_ot_font_set_funcs:
+ *
  * Since: 0.9.28
  **/
 void
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-font.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-font.h	2016-08-05 14:37:07.938011506 +0300
@@ -36,7 +36,7 @@
 HB_BEGIN_DECLS
 
 
-void
+HB_EXTERN void
 hb_ot_font_set_funcs (hb_font_t *font);
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-head-table.hh.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-head-table.hh	2016-08-05 14:37:07.938011506 +0300
@@ -55,7 +55,9 @@
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && likely (version.major == 1));
+    return_trace (c->check_struct (this) &&
+		  version.major == 1 &&
+		  magicNumber == 0x5F0F3CF5u);
   }
 
   protected:
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-layout-common-private.hh.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-layout-common-private.hh	2016-08-05 14:37:07.938011506 +0300
@@ -545,6 +545,9 @@
 	  c->try_set (&featureParams, new_offset) &&
 	  !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
 	return_trace (false);
+
+      if (c->edit_count > 1)
+        c->edit_count--; /* This was a "legitimate" edit; don't contribute to error count. */
     }
 
     return_trace (true);
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh	2016-08-05 14:37:07.939011499 +0300
@@ -742,7 +742,7 @@
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
-    /* (this+coverage).add_coverage (c->input); // Don't need this. */
+    (this+coverage).add_coverage (c->input);
 
     unsigned int count1 = class1Count;
     const ClassDef &klass1 = this+classDef1;
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh	2016-08-05 14:37:07.939011499 +0300
@@ -845,9 +845,12 @@
     while (buffer->idx < match_positions[i] && !buffer->in_error)
     {
       if (!is_mark_ligature) {
+        unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
+	if (this_comp == 0)
+	  this_comp = last_num_components;
 	unsigned int new_lig_comp = components_so_far - last_num_components +
-				    MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->cur()), 1u), last_num_components);
-	_hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
+				    MIN (this_comp, last_num_components);
+	  _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
       }
       buffer->next_glyph ();
     }
@@ -864,8 +867,11 @@
     /* Re-adjust components for any marks following. */
     for (unsigned int i = buffer->idx; i < buffer->len; i++) {
       if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) {
+        unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
+	if (!this_comp)
+	  break;
 	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);
+				    MIN (this_comp, last_num_components);
 	_hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
       } else
 	break;
@@ -971,6 +977,11 @@
     if (idx >= count)
       continue;
 
+    /* Don't recurse to ourself at same position.
+     * Note that this test is too naive, it doesn't catch longer loops. */
+    if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)
+      continue;
+
     buffer->move_to (match_positions[idx]);
 
     unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-layout-private.hh.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-layout-private.hh	2016-08-05 14:37:07.940011491 +0300
@@ -517,11 +517,9 @@
 }
 
 static inline void
-_hb_glyph_info_clear_substituted_and_ligated_and_multiplied (hb_glyph_info_t *info)
+_hb_glyph_info_clear_substituted (hb_glyph_info_t *info)
 {
-  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
-			   HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
-			   HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
+  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
 }
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-layout.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-layout.cc	2016-08-05 14:37:07.940011491 +0300
@@ -130,6 +130,8 @@
 }
 
 /**
+ * hb_ot_layout_get_glyph_class:
+ *
  * Since: 0.9.7
  **/
 hb_ot_layout_glyph_class_t
@@ -140,6 +142,8 @@
 }
 
 /**
+ * hb_ot_layout_get_glyphs_in_class:
+ *
  * Since: 0.9.7
  **/
 void
@@ -365,6 +369,8 @@
 }
 
 /**
+ * hb_ot_layout_language_get_required_feature:
+ *
  * Since: 0.9.30
  **/
 hb_bool_t
@@ -452,6 +458,8 @@
 }
 
 /**
+ * hb_ot_layout_feature_get_lookups:
+ *
  * Since: 0.9.7
  **/
 unsigned int
@@ -469,6 +477,8 @@
 }
 
 /**
+ * hb_ot_layout_table_get_lookup_count:
+ *
  * Since: 0.9.22
  **/
 unsigned int
@@ -629,6 +639,8 @@
 }
 
 /**
+ * hb_ot_layout_collect_lookups:
+ *
  * Since: 0.9.8
  **/
 void
@@ -673,6 +685,8 @@
 }
 
 /**
+ * hb_ot_layout_lookup_collect_glyphs:
+ *
  * Since: 0.9.7
  **/
 void
@@ -721,6 +735,8 @@
 }
 
 /**
+ * hb_ot_layout_lookup_would_substitute:
+ *
  * Since: 0.9.7
  **/
 hb_bool_t
@@ -742,7 +758,7 @@
 					   hb_bool_t             zero_context)
 {
   if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false;
-  OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, zero_context);
+  OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context);
 
   const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
 
@@ -762,6 +778,8 @@
 }
 
 /**
+ * hb_ot_layout_lookup_substitute_closure:
+ *
  * Since: 0.9.7
  **/
 void
@@ -799,6 +817,8 @@
 }
 
 /**
+ * hb_ot_layout_get_size_params:
+ *
  * Since: 0.9.10
  **/
 hb_bool_t
@@ -1008,25 +1028,15 @@
     const stage_map_t *stage = &stages[table_index][stage_index];
     for (; i < stage->last_lookup; i++)
     {
-#if 0
-      char buf[4096];
-      hb_buffer_serialize_glyphs (buffer, 0, buffer->len,
-				  buf, sizeof (buf), NULL,
-				  font,
-				  HB_BUFFER_SERIALIZE_FORMAT_TEXT,
-				  Proxy::table_index == 0 ?
-				  HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS :
-				  HB_BUFFER_SERIALIZE_FLAG_DEFAULT);
-      printf ("buf: [%s]\n", buf);
-#endif
-
       unsigned int lookup_index = lookups[table_index][i].index;
+      if (!buffer->message (font, "start lookup %d", lookup_index)) continue;
       c.set_lookup_index (lookup_index);
       c.set_lookup_mask (lookups[table_index][i].mask);
       c.set_auto_zwj (lookups[table_index][i].auto_zwj);
       apply_string<Proxy> (&c,
 			   proxy.table.get_lookup (lookup_index),
 			   proxy.accels[lookup_index]);
+      (void) buffer->message (font, "end lookup %d", lookup_index);
     }
 
     if (stage->pause_func)
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-layout.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-layout.h	2016-08-05 14:37:07.941011484 +0300
@@ -48,7 +48,7 @@
  * GDEF
  */
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_ot_layout_has_glyph_classes (hb_face_t *face);
 
 typedef enum {
@@ -59,11 +59,11 @@
   HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT	= 4
 } hb_ot_layout_glyph_class_t;
 
-hb_ot_layout_glyph_class_t
+HB_EXTERN hb_ot_layout_glyph_class_t
 hb_ot_layout_get_glyph_class (hb_face_t      *face,
 			      hb_codepoint_t  glyph);
 
-void
+HB_EXTERN void
 hb_ot_layout_get_glyphs_in_class (hb_face_t                  *face,
 				  hb_ot_layout_glyph_class_t  klass,
 				  hb_set_t                   *glyphs /* OUT */);
@@ -71,7 +71,7 @@
 
 /* Not that useful.  Provides list of attach points for a glyph that a
  * client may want to cache */
-unsigned int
+HB_EXTERN unsigned int
 hb_ot_layout_get_attach_points (hb_face_t      *face,
 				hb_codepoint_t  glyph,
 				unsigned int    start_offset,
@@ -79,7 +79,7 @@
 				unsigned int   *point_array /* OUT */);
 
 /* Ligature caret positions */
-unsigned int
+HB_EXTERN unsigned int
 hb_ot_layout_get_ligature_carets (hb_font_t      *font,
 				  hb_direction_t  direction,
 				  hb_codepoint_t  glyph,
@@ -96,35 +96,35 @@
 #define HB_OT_LAYOUT_NO_FEATURE_INDEX		0xFFFFu
 #define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX	0xFFFFu
 
-unsigned int
+HB_EXTERN unsigned int
 hb_ot_layout_table_get_script_tags (hb_face_t    *face,
 				    hb_tag_t      table_tag,
 				    unsigned int  start_offset,
 				    unsigned int *script_count /* IN/OUT */,
 				    hb_tag_t     *script_tags /* OUT */);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_ot_layout_table_find_script (hb_face_t    *face,
 				hb_tag_t      table_tag,
 				hb_tag_t      script_tag,
 				unsigned int *script_index);
 
 /* Like find_script, but takes zero-terminated array of scripts to test */
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_ot_layout_table_choose_script (hb_face_t      *face,
 				  hb_tag_t        table_tag,
 				  const hb_tag_t *script_tags,
 				  unsigned int   *script_index,
 				  hb_tag_t       *chosen_script);
 
-unsigned int
+HB_EXTERN unsigned int
 hb_ot_layout_table_get_feature_tags (hb_face_t    *face,
 				     hb_tag_t      table_tag,
 				     unsigned int  start_offset,
 				     unsigned int *feature_count /* IN/OUT */,
 				     hb_tag_t     *feature_tags /* OUT */);
 
-unsigned int
+HB_EXTERN unsigned int
 hb_ot_layout_script_get_language_tags (hb_face_t    *face,
 				       hb_tag_t      table_tag,
 				       unsigned int  script_index,
@@ -132,21 +132,21 @@
 				       unsigned int *language_count /* IN/OUT */,
 				       hb_tag_t     *language_tags /* OUT */);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_ot_layout_script_find_language (hb_face_t    *face,
 				   hb_tag_t      table_tag,
 				   unsigned int  script_index,
 				   hb_tag_t      language_tag,
 				   unsigned int *language_index);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
 						  hb_tag_t      table_tag,
 						  unsigned int  script_index,
 						  unsigned int  language_index,
 						  unsigned int *feature_index);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_ot_layout_language_get_required_feature (hb_face_t    *face,
 					    hb_tag_t      table_tag,
 					    unsigned int  script_index,
@@ -154,7 +154,7 @@
 					    unsigned int *feature_index,
 					    hb_tag_t     *feature_tag);
 
-unsigned int
+HB_EXTERN unsigned int
 hb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
 					   hb_tag_t      table_tag,
 					   unsigned int  script_index,
@@ -163,7 +163,7 @@
 					   unsigned int *feature_count /* IN/OUT */,
 					   unsigned int *feature_indexes /* OUT */);
 
-unsigned int
+HB_EXTERN unsigned int
 hb_ot_layout_language_get_feature_tags (hb_face_t    *face,
 					hb_tag_t      table_tag,
 					unsigned int  script_index,
@@ -172,7 +172,7 @@
 					unsigned int *feature_count /* IN/OUT */,
 					hb_tag_t     *feature_tags /* OUT */);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_ot_layout_language_find_feature (hb_face_t    *face,
 				    hb_tag_t      table_tag,
 				    unsigned int  script_index,
@@ -180,7 +180,7 @@
 				    hb_tag_t      feature_tag,
 				    unsigned int *feature_index);
 
-unsigned int
+HB_EXTERN unsigned int
 hb_ot_layout_feature_get_lookups (hb_face_t    *face,
 				  hb_tag_t      table_tag,
 				  unsigned int  feature_index,
@@ -188,12 +188,12 @@
 				  unsigned int *lookup_count /* IN/OUT */,
 				  unsigned int *lookup_indexes /* OUT */);
 
-unsigned int
+HB_EXTERN unsigned int
 hb_ot_layout_table_get_lookup_count (hb_face_t    *face,
 				     hb_tag_t      table_tag);
 
 
-void
+HB_EXTERN void
 hb_ot_layout_collect_lookups (hb_face_t      *face,
 			      hb_tag_t        table_tag,
 			      const hb_tag_t *scripts,
@@ -201,7 +201,7 @@
 			      const hb_tag_t *features,
 			      hb_set_t       *lookup_indexes /* OUT */);
 
-void
+HB_EXTERN void
 hb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
 				    hb_tag_t      table_tag,
 				    unsigned int  lookup_index,
@@ -228,7 +228,7 @@
 				       const hb_ot_layout_glyph_sequence_t *sequence,
 				       void         *user_data);
 
-void
+HB_EXTERN void
 Xhb_ot_layout_lookup_enumerate_sequences (hb_face_t    *face,
 					 hb_tag_t      table_tag,
 					 unsigned int  lookup_index,
@@ -241,17 +241,17 @@
  * GSUB
  */
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_ot_layout_has_substitution (hb_face_t *face);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_ot_layout_lookup_would_substitute (hb_face_t            *face,
 				      unsigned int          lookup_index,
 				      const hb_codepoint_t *glyphs,
 				      unsigned int          glyphs_length,
 				      hb_bool_t             zero_context);
 
-void
+HB_EXTERN void
 hb_ot_layout_lookup_substitute_closure (hb_face_t    *face,
 				        unsigned int  lookup_index,
 				        hb_set_t     *glyphs
@@ -259,7 +259,7 @@
 
 #ifdef HB_NOT_IMPLEMENTED
 /* Note: You better have GDEF when using this API, or marks won't do much. */
-hb_bool_t
+HB_EXTERN hb_bool_t
 Xhb_ot_layout_lookup_substitute (hb_font_t            *font,
 				unsigned int          lookup_index,
 				const hb_ot_layout_glyph_sequence_t *sequence,
@@ -274,12 +274,12 @@
  * GPOS
  */
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_ot_layout_has_positioning (hb_face_t *face);
 
 #ifdef HB_NOT_IMPLEMENTED
 /* Note: You better have GDEF when using this API, or marks won't do much. */
-hb_bool_t
+HB_EXTERN hb_bool_t
 Xhb_ot_layout_lookup_position (hb_font_t            *font,
 			      unsigned int          lookup_index,
 			      const hb_ot_layout_glyph_sequence_t *sequence,
@@ -288,7 +288,7 @@
 
 /* Optical 'size' feature info.  Returns true if found.
  * http://www.microsoft.com/typography/otspec/features_pt.htm#size */
-hb_bool_t
+HB_EXTERN 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 */
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-map-private.hh.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-map-private.hh	2016-08-05 14:37:07.941011484 +0300
@@ -203,7 +203,8 @@
     unsigned int stage[2]; /* GSUB/GPOS */
 
     static int cmp (const feature_info_t *a, const feature_info_t *b)
-    { return (a->tag != b->tag) ?  (a->tag < b->tag ? -1 : 1) : (a->seq < b->seq ? -1 : 1); }
+    { return (a->tag != b->tag) ?  (a->tag < b->tag ? -1 : 1) :
+	     (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0); }
   };
 
   struct stage_info_t {
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-map.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-map.cc	2016-08-05 14:37:07.941011484 +0300
@@ -89,7 +89,7 @@
 
   for (unsigned int table_index = 0; table_index < 2; table_index++) {
     hb_tag_t table_tag = table_tags[table_index];
-    found_script[table_index] = hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]);
+    found_script[table_index] = (bool) hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]);
     hb_ot_layout_script_find_language (face, table_tag, script_index[table_index], language_tag, &language_index[table_index]);
   }
 }
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-os2-table.hh.1228540	2016-08-05 14:37:07.941011484 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-os2-table.hh	2016-08-05 14:37:07.941011484 +0300
@@ -0,0 +1,105 @@
+/*
+ * Copyright © 2011,2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * 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_OS2_TABLE_HH
+#define HB_OT_OS2_TABLE_HH
+
+#include "hb-open-type-private.hh"
+
+
+namespace OT {
+
+/*
+ * OS/2 and Windows Metrics
+ * http://www.microsoft.com/typography/otspec/os2.htm
+ */
+
+#define HB_OT_TAG_os2 HB_TAG('O','S','/','2')
+
+struct os2
+{
+  static const hb_tag_t tableTag = HB_OT_TAG_os2;
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  USHORT	version;
+
+  /* Version 0 */
+  SHORT		xAvgCharWidth;
+  USHORT	usWeightClass;
+  USHORT	usWidthClass;
+  USHORT	fsType;
+  SHORT		ySubscriptXSize;
+  SHORT		ySubscriptYSize;
+  SHORT		ySubscriptXOffset;
+  SHORT		ySubscriptYOffset;
+  SHORT		ySuperscriptXSize;
+  SHORT		ySuperscriptYSize;
+  SHORT		ySuperscriptXOffset;
+  SHORT		ySuperscriptYOffset;
+  SHORT		yStrikeoutSize;
+  SHORT		yStrikeoutPosition;
+  SHORT		sFamilyClass;
+  BYTE		panose[10];
+  ULONG		ulUnicodeRange[4];
+  Tag		achVendID;
+  USHORT	fsSelection;
+  USHORT	usFirstCharIndex;
+  USHORT	usLastCharIndex;
+  SHORT		sTypoAscender;
+  SHORT		sTypoDescender;
+  SHORT		sTypoLineGap;
+  USHORT	usWinAscent;
+  USHORT	usWinDescent;
+
+  /* Version 1 */
+  //ULONG ulCodePageRange1;
+  //ULONG ulCodePageRange2;
+
+  /* Version 2 */
+  //SHORT sxHeight;
+  //SHORT sCapHeight;
+  //USHORT  usDefaultChar;
+  //USHORT  usBreakChar;
+  //USHORT  usMaxContext;
+
+  /* Version 5 */
+  //USHORT  usLowerOpticalPointSize;
+  //USHORT  usUpperOpticalPointSize;
+
+  public:
+  DEFINE_SIZE_STATIC (78);
+};
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_OS2_TABLE_HH */
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc	2016-08-05 14:37:07.942011476 +0300
@@ -223,7 +223,6 @@
     map->add_gsub_pause (arabic_fallback_shape);
 
   map->add_global_bool_feature (HB_TAG('c','a','l','t'));
-  map->add_gsub_pause (NULL);
 
   /* The spec includes 'cswh'.  Earlier versions of Windows
    * used to enable this by default, but testing suggests
@@ -233,6 +232,7 @@
    * Note that IranNastaliq uses this feature extensively
    * to fixup broken glyph sequences.  Oh well...
    * Test case: U+0643,U+0640,U+0631. */
+  //map->add_gsub_pause (NULL);
   //map->add_global_bool_feature (HB_TAG('c','s','w','h'));
   map->add_global_bool_feature (HB_TAG('m','s','e','t'));
 }
@@ -463,10 +463,6 @@
    * Second pass applies the stretch, copying things to the end of buffer.
    */
 
-  /* 30 = 2048 / 70.
-   * https://www.microsoft.com/typography/cursivescriptguidelines.mspx */
-  hb_position_t overlap = font->x_scale / 30;
-  DEBUG_MSG (ARABIC, NULL, "overlap for stretching is %d", overlap);
   int sign = font->x_scale < 0 ? -1 : +1;
   unsigned int extra_glyphs_needed = 0; // Set during MEASURE, used during CUT
   typedef enum { MEASURE, CUT } step_t;
@@ -504,18 +500,15 @@
 	     hb_in_range<unsigned> (info[i - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING))
       {
 	i--;
-	hb_glyph_extents_t extents;
-	if (!font->get_glyph_extents (info[i].codepoint, &extents))
-	  extents.width = 0;
-	extents.width -= overlap;
+	hb_position_t width = font->get_glyph_h_advance (info[i].codepoint);
 	if (info[i].arabic_shaping_action() == STCH_FIXED)
 	{
-	  w_fixed += extents.width;
+	  w_fixed += width;
 	  n_fixed++;
 	}
 	else
 	{
-	  w_repeating += extents.width;
+	  w_repeating += width;
 	  n_repeating++;
 	}
       }
@@ -540,9 +533,20 @@
       /* Number of additional times to repeat each repeating tile. */
       int n_copies = 0;
 
-      hb_position_t w_remaining = w_total - w_fixed - overlap;
+      hb_position_t w_remaining = w_total - w_fixed;
       if (sign * w_remaining > sign * w_repeating && sign * w_repeating > 0)
-	n_copies = (sign * w_remaining + sign * w_repeating / 4) / (sign * w_repeating) - 1;
+	n_copies = (sign * w_remaining) / (sign * w_repeating) - 1;
+
+      /* See if we can improve the fit by adding an extra repeat and squeezing them together a bit. */
+      hb_position_t extra_repeat_overlap = 0;
+      hb_position_t shortfall = sign * w_remaining - sign * w_repeating * (n_copies + 1);
+      if (shortfall > 0)
+      {
+        ++n_copies;
+        hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining;
+        if (excess > 0)
+          extra_repeat_overlap = excess / (n_copies * n_repeating);
+      }
 
       if (step == MEASURE)
       {
@@ -551,13 +555,10 @@
       }
       else
       {
-        hb_position_t x_offset = -overlap;
+	hb_position_t x_offset = 0;
 	for (unsigned int k = end; k > start; k--)
 	{
-	  hb_glyph_extents_t extents;
-	  if (!font->get_glyph_extents (info[k - 1].codepoint, &extents))
-	    extents.width = 0;
-	  extents.width -= overlap;
+	  hb_position_t width = font->get_glyph_h_advance (info[k - 1].codepoint);
 
 	  unsigned int repeat = 1;
 	  if (info[k - 1].arabic_shaping_action() == STCH_REPEATING)
@@ -567,7 +568,9 @@
 		     repeat, info[k - 1].codepoint, j);
 	  for (unsigned int n = 0; n < repeat; n++)
 	  {
-	    x_offset -= extents.width;
+	    x_offset -= width;
+	    if (n > 0)
+	      x_offset += extra_repeat_overlap;
 	    pos[k - 1].x_offset = x_offset;
 	    /* Append copy. */
 	    --j;
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc	2016-08-05 14:37:07.942011476 +0300
@@ -40,6 +40,6 @@
   NULL, /* decompose */
   NULL, /* compose */
   NULL, /* setup_masks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT,
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE,
   true, /* fallback_position */
 };
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc	2016-08-05 14:37:07.942011476 +0300
@@ -68,7 +68,7 @@
     0xFB4Au /* TAV */
   };
 
-  bool found = c->unicode->compose (a, b, ab);
+  bool found = (bool) c->unicode->compose (a, b, ab);
 
   if (!found && !c->plan->has_mark)
   {
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh	2016-08-05 14:37:07.942011476 +0300
@@ -109,27 +109,31 @@
 
   INDIC_SYLLABIC_CATEGORY_AVAGRAHA			= OT_Symbol,
   INDIC_SYLLABIC_CATEGORY_BINDU				= OT_SM,
-  INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER		= OT_PLACEHOLDER, /* TODO */
+  INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER		= OT_PLACEHOLDER, /* Don't care. */
   INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK		= OT_A,
   INDIC_SYLLABIC_CATEGORY_CONSONANT			= OT_C,
   INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD		= OT_C,
   INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL		= OT_CM,
   INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER		= OT_C,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER		= OT_M, /* U+17CD only. */
   INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL		= OT_CM,
   INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER		= OT_PLACEHOLDER,
   INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA	= OT_Repha,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED		= OT_X, /* Don't care. */
   INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED		= OT_CM,
   INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA	= OT_N,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER	= OT_Repha, /* TODO */
   INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK		= OT_SM,
-  INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER		= OT_H, /* TODO */
+  INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER		= OT_Coeng,
   INDIC_SYLLABIC_CATEGORY_JOINER			= OT_ZWJ,
   INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER		= OT_X,
   INDIC_SYLLABIC_CATEGORY_NON_JOINER			= OT_ZWNJ,
   INDIC_SYLLABIC_CATEGORY_NUKTA				= OT_N,
   INDIC_SYLLABIC_CATEGORY_NUMBER			= OT_PLACEHOLDER,
-  INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER			= OT_PLACEHOLDER, /* TODO */
-  INDIC_SYLLABIC_CATEGORY_PURE_KILLER			= OT_H, /* TODO */
+  INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER			= OT_PLACEHOLDER, /* Don't care. */
+  INDIC_SYLLABIC_CATEGORY_PURE_KILLER			= OT_M, /* Is like a vowel matra. */
   INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER		= OT_RS,
+  INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER		= OT_M, /* Misc Khmer signs. */
   INDIC_SYLLABIC_CATEGORY_TONE_LETTER			= OT_X,
   INDIC_SYLLABIC_CATEGORY_TONE_MARK			= OT_N,
   INDIC_SYLLABIC_CATEGORY_VIRAMA			= OT_H,
@@ -162,17 +166,23 @@
 };
 
 #define INDIC_COMBINE_CATEGORIES(S,M) \
-  (ASSERT_STATIC_EXPR_ZERO (M == INDIC_MATRA_CATEGORY_NOT_APPLICABLE || \
-			    ( \
-			     S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \
-			     S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \
-			     S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \
-			     S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \
-			     S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \
-			     S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \
-			     false)) + \
-   ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \
-   ((M << 8) | S))
+  ( \
+    ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \
+    ( S | \
+     ( \
+      ( \
+       S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \
+       S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \
+       S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \
+       S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \
+       S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \
+       S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \
+       false \
+       ? M : INDIC_MATRA_CATEGORY_NOT_APPLICABLE \
+      ) << 8 \
+     ) \
+    ) \
+   )
 
 HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE
 hb_indic_get_categories (hb_codepoint_t u);
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc	2016-08-05 14:37:07.944011461 +0300
@@ -6,63 +6,67 @@
  *
  * on files with these headers:
  *
- * # IndicSyllabicCategory-7.0.0.txt
- * # Date: 2014-06-03, 07:00:00 GMT [KW, LI, AG, RP]
- * # IndicMatraCategory-7.0.0.txt
- * # Date: 2014-06-03, 07:00:00 GMT [KW, LI, AG, RP]
- * # Blocks-7.0.0.txt
- * # Date: 2014-04-03, 23:23:00 GMT [RP, KW]
+ * # IndicSyllabicCategory-8.0.0.txt
+ * # Date: 2015-05-12, 10:00:00 GMT [RP, KW, LI]
+ * # IndicPositionalCategory-8.0.0.txt
+ * # Date: 2015-05-12, 10:00:00 GMT [RP, KW, LI]
+ * # Blocks-8.0.0.txt
+ * # Date: 2014-11-10, 23:04:00 GMT [KW]
  */
 
 #include "hb-ot-shape-complex-indic-private.hh"
 
 
 #define ISC_A	INDIC_SYLLABIC_CATEGORY_AVAGRAHA		/*  13 chars; Avagraha */
-#define ISC_Bi	INDIC_SYLLABIC_CATEGORY_BINDU			/*  59 chars; Bindu */
+#define ISC_Bi	INDIC_SYLLABIC_CATEGORY_BINDU			/*  60 chars; Bindu */
 #define ISC_BJN	INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER	/*  20 chars; Brahmi_Joining_Number */
-#define ISC_Ca	INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK	/*  30 chars; Cantillation_Mark */
-#define ISC_C	INDIC_SYLLABIC_CATEGORY_CONSONANT		/* 1744 chars; Consonant */
+#define ISC_Ca	INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK	/*  52 chars; Cantillation_Mark */
+#define ISC_C	INDIC_SYLLABIC_CATEGORY_CONSONANT		/* 1805 chars; Consonant */
 #define ISC_CD	INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD		/*   7 chars; Consonant_Dead */
-#define ISC_CF	INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL		/*  61 chars; Consonant_Final */
+#define ISC_CF	INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL		/*  62 chars; Consonant_Final */
 #define ISC_CHL	INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER	/*   5 chars; Consonant_Head_Letter */
-#define ISC_CM	INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL	/*  19 chars; Consonant_Medial */
-#define ISC_CP	INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER	/*  11 chars; Consonant_Placeholder */
+#define ISC_CK	INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER	/*   2 chars; Consonant_Killer */
+#define ISC_CM	INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL	/*  22 chars; Consonant_Medial */
+#define ISC_CP	INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER	/*  13 chars; Consonant_Placeholder */
 #define ISC_CPR	INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA	/*   1 chars; Consonant_Preceding_Repha */
+#define ISC_CPrf	INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED	/*   2 chars; Consonant_Prefixed */
 #define ISC_CS	INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED	/*  61 chars; Consonant_Subjoined */
 #define ISC_CSR	INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA	/*   4 chars; Consonant_Succeeding_Repha */
+#define ISC_CWS	INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER	/*   4 chars; Consonant_With_Stacker */
 #define ISC_GM	INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK		/*   2 chars; Gemination_Mark */
 #define ISC_IS	INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER	/*   7 chars; Invisible_Stacker */
 #define ISC_ZWJ	INDIC_SYLLABIC_CATEGORY_JOINER			/*   1 chars; Joiner */
 #define ISC_ML	INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER	/*   1 chars; Modifying_Letter */
 #define ISC_ZWNJ	INDIC_SYLLABIC_CATEGORY_NON_JOINER		/*   1 chars; Non_Joiner */
-#define ISC_N	INDIC_SYLLABIC_CATEGORY_NUKTA			/*  18 chars; Nukta */
-#define ISC_Nd	INDIC_SYLLABIC_CATEGORY_NUMBER			/* 408 chars; Number */
+#define ISC_N	INDIC_SYLLABIC_CATEGORY_NUKTA			/*  23 chars; Nukta */
+#define ISC_Nd	INDIC_SYLLABIC_CATEGORY_NUMBER			/* 420 chars; Number */
 #define ISC_NJ	INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER		/*   1 chars; Number_Joiner */
 #define ISC_x	INDIC_SYLLABIC_CATEGORY_OTHER			/*   1 chars; Other */
-#define ISC_PK	INDIC_SYLLABIC_CATEGORY_PURE_KILLER		/*  15 chars; Pure_Killer */
-#define ISC_RS	INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER	/*   3 chars; Register_Shifter */
+#define ISC_PK	INDIC_SYLLABIC_CATEGORY_PURE_KILLER		/*  16 chars; Pure_Killer */
+#define ISC_RS	INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER	/*   2 chars; Register_Shifter */
+#define ISC_SM	INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER	/*  20 chars; Syllable_Modifier */
 #define ISC_TL	INDIC_SYLLABIC_CATEGORY_TONE_LETTER		/*   7 chars; Tone_Letter */
-#define ISC_TM	INDIC_SYLLABIC_CATEGORY_TONE_MARK		/*  62 chars; Tone_Mark */
+#define ISC_TM	INDIC_SYLLABIC_CATEGORY_TONE_MARK		/*  42 chars; Tone_Mark */
 #define ISC_V	INDIC_SYLLABIC_CATEGORY_VIRAMA			/*  22 chars; Virama */
 #define ISC_Vs	INDIC_SYLLABIC_CATEGORY_VISARGA			/*  29 chars; Visarga */
 #define ISC_Vo	INDIC_SYLLABIC_CATEGORY_VOWEL			/*  30 chars; Vowel */
-#define ISC_M	INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT		/* 553 chars; Vowel_Dependent */
-#define ISC_VI	INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT	/* 395 chars; Vowel_Independent */
+#define ISC_M	INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT		/* 572 chars; Vowel_Dependent */
+#define ISC_VI	INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT	/* 404 chars; Vowel_Independent */
 
-#define IMC_B	INDIC_MATRA_CATEGORY_BOTTOM			/* 142 chars; Bottom */
+#define IMC_B	INDIC_MATRA_CATEGORY_BOTTOM			/* 256 chars; Bottom */
 #define IMC_BR	INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT		/*   2 chars; Bottom_And_Right */
-#define IMC_L	INDIC_MATRA_CATEGORY_LEFT			/*  57 chars; Left */
+#define IMC_L	INDIC_MATRA_CATEGORY_LEFT			/*  55 chars; Left */
 #define IMC_LR	INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT		/*  21 chars; Left_And_Right */
 #define IMC_x	INDIC_MATRA_CATEGORY_NOT_APPLICABLE		/*   1 chars; Not_Applicable */
-#define IMC_O	INDIC_MATRA_CATEGORY_OVERSTRUCK			/*   2 chars; Overstruck */
-#define IMC_R	INDIC_MATRA_CATEGORY_RIGHT			/* 163 chars; Right */
-#define IMC_T	INDIC_MATRA_CATEGORY_TOP			/* 169 chars; Top */
+#define IMC_O	INDIC_MATRA_CATEGORY_OVERSTRUCK			/*  10 chars; Overstruck */
+#define IMC_R	INDIC_MATRA_CATEGORY_RIGHT			/* 249 chars; Right */
+#define IMC_T	INDIC_MATRA_CATEGORY_TOP			/* 324 chars; Top */
 #define IMC_TB	INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM		/*  10 chars; Top_And_Bottom */
 #define IMC_TBR	INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT	/*   1 chars; Top_And_Bottom_And_Right */
 #define IMC_TL	INDIC_MATRA_CATEGORY_TOP_AND_LEFT		/*   6 chars; Top_And_Left */
 #define IMC_TLR	INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT	/*   4 chars; Top_And_Left_And_Right */
 #define IMC_TR	INDIC_MATRA_CATEGORY_TOP_AND_RIGHT		/*  13 chars; Top_And_Right */
-#define IMC_VOL	INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT		/*  15 chars; Visual_Order_Left */
+#define IMC_VOL	INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT		/*  19 chars; Visual_Order_Left */
 
 #define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)
 
@@ -79,29 +83,33 @@
   /* 0030 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 0038 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
-#define indic_offset_0x00d0u 24
+#define indic_offset_0x00b0u 24
 
 
   /* Latin-1 Supplement */
 
+  /* 00B0 */  _(x,x),  _(x,x), _(SM,x), _(SM,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 00B8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 00C0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 00C8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 00D0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(CP,x),
 
-#define indic_offset_0x0900u 32
+#define indic_offset_0x0900u 64
 
 
   /* Devanagari */
 
-  /* 0900 */ _(Bi,x), _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+  /* 0900 */ _(Bi,T), _(Bi,T), _(Bi,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
   /* 0908 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
   /* 0910 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0918 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0920 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0928 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0930 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0938 */  _(C,x),  _(C,x),  _(M,T),  _(M,R),  _(N,x),  _(A,x),  _(M,R),  _(M,L),
+  /* 0938 */  _(C,x),  _(C,x),  _(M,T),  _(M,R),  _(N,B),  _(A,x),  _(M,R),  _(M,L),
   /* 0940 */  _(M,R),  _(M,B),  _(M,B),  _(M,B),  _(M,B),  _(M,T),  _(M,T),  _(M,T),
   /* 0948 */  _(M,T),  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(V,B),  _(M,L),  _(M,R),
-  /* 0950 */  _(x,x), _(TM,x), _(TM,x),  _(x,x),  _(x,x),  _(M,T),  _(M,B),  _(M,B),
+  /* 0950 */  _(x,x), _(Ca,T), _(Ca,B),  _(x,T),  _(x,T),  _(M,T),  _(M,B),  _(M,B),
   /* 0958 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0960 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
   /* 0968 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
@@ -110,14 +118,14 @@
 
   /* Bengali */
 
-  /* 0980 */  _(x,x), _(Bi,x), _(Bi,x), _(Vs,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
+  /* 0980 */  _(x,x), _(Bi,T), _(Bi,R), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
   /* 0988 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x),  _(x,x), _(VI,x),
   /* 0990 */ _(VI,x),  _(x,x),  _(x,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0998 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 09A0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 09A8 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 09B0 */  _(C,x),  _(x,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(C,x),  _(C,x),
-  /* 09B8 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,x),  _(A,x),  _(M,R),  _(M,L),
+  /* 09B8 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,B),  _(A,x),  _(M,R),  _(M,L),
   /* 09C0 */  _(M,R),  _(M,B),  _(M,B),  _(M,B),  _(M,B),  _(x,x),  _(x,x),  _(M,L),
   /* 09C8 */  _(M,L),  _(x,x),  _(x,x), _(M,LR), _(M,LR),  _(V,B), _(CD,x),  _(x,x),
   /* 09D0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,R),
@@ -129,33 +137,33 @@
 
   /* Gurmukhi */
 
-  /* 0A00 */  _(x,x), _(Bi,x), _(Bi,x), _(Vs,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
+  /* 0A00 */  _(x,x), _(Bi,T), _(Bi,T), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
   /* 0A08 */ _(VI,x), _(VI,x), _(VI,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(VI,x),
   /* 0A10 */ _(VI,x),  _(x,x),  _(x,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0A18 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0A20 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0A28 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0A30 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(x,x),
-  /* 0A38 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,x),  _(x,x),  _(M,R),  _(M,L),
+  /* 0A38 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,B),  _(x,x),  _(M,R),  _(M,L),
   /* 0A40 */  _(M,R),  _(M,B),  _(M,B),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,T),
   /* 0A48 */  _(M,T),  _(x,x),  _(x,x),  _(M,T),  _(M,T),  _(V,B),  _(x,x),  _(x,x),
   /* 0A50 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 0A58 */  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),  _(x,x),
   /* 0A60 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
   /* 0A68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* 0A70 */ _(Bi,x), _(GM,T), _(CP,x), _(CP,x),  _(x,x), _(CM,x),  _(x,x),  _(x,x),
+  /* 0A70 */ _(Bi,T), _(GM,T), _(CP,x), _(CP,x),  _(x,x), _(CM,B),  _(x,x),  _(x,x),
   /* 0A78 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
   /* Gujarati */
 
-  /* 0A80 */  _(x,x), _(Bi,x), _(Bi,x), _(Vs,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
+  /* 0A80 */  _(x,x), _(Bi,T), _(Bi,T), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
   /* 0A88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x), _(VI,x),
   /* 0A90 */ _(VI,x), _(VI,x),  _(x,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0A98 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0AA0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0AA8 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0AB0 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0AB8 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,x),  _(A,x),  _(M,R),  _(M,L),
+  /* 0AB8 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,B),  _(A,x),  _(M,R),  _(M,L),
   /* 0AC0 */  _(M,R),  _(M,B),  _(M,B),  _(M,B),  _(M,B),  _(M,T),  _(x,x),  _(M,T),
   /* 0AC8 */  _(M,T), _(M,TR),  _(x,x),  _(M,R),  _(M,R),  _(V,B),  _(x,x),  _(x,x),
   /* 0AD0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
@@ -163,18 +171,18 @@
   /* 0AE0 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
   /* 0AE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 0AF0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 0AF8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 0AF8 */  _(x,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
   /* Oriya */
 
-  /* 0B00 */  _(x,x), _(Bi,x), _(Bi,x), _(Vs,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
+  /* 0B00 */  _(x,x), _(Bi,T), _(Bi,R), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
   /* 0B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x),  _(x,x), _(VI,x),
   /* 0B10 */ _(VI,x),  _(x,x),  _(x,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0B18 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0B20 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0B28 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0B30 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0B38 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,x),  _(A,x),  _(M,R),  _(M,T),
+  /* 0B38 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,B),  _(A,x),  _(M,R),  _(M,T),
   /* 0B40 */  _(M,R),  _(M,B),  _(M,B),  _(M,B),  _(M,B),  _(x,x),  _(x,x),  _(M,L),
   /* 0B48 */ _(M,TL),  _(x,x),  _(x,x), _(M,LR),_(M,TLR),  _(V,B),  _(x,x),  _(x,x),
   /* 0B50 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,T), _(M,TR),
@@ -186,7 +194,7 @@
 
   /* Tamil */
 
-  /* 0B80 */  _(x,x),  _(x,x), _(Bi,x), _(ML,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
+  /* 0B80 */  _(x,x),  _(x,x), _(Bi,T), _(ML,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
   /* 0B88 */ _(VI,x), _(VI,x), _(VI,x),  _(x,x),  _(x,x),  _(x,x), _(VI,x), _(VI,x),
   /* 0B90 */ _(VI,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),  _(C,x),  _(x,x),  _(x,x),
   /* 0B98 */  _(x,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),  _(x,x),  _(C,x),  _(C,x),
@@ -194,7 +202,7 @@
   /* 0BA8 */  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(C,x),  _(C,x),
   /* 0BB0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0BB8 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,R),  _(M,R),
-  /* 0BC0 */  _(M,T),  _(M,B),  _(M,B),  _(x,x),  _(x,x),  _(x,x),  _(M,L),  _(M,L),
+  /* 0BC0 */  _(M,T),  _(M,R),  _(M,R),  _(x,x),  _(x,x),  _(x,x),  _(M,L),  _(M,L),
   /* 0BC8 */  _(M,L),  _(x,x), _(M,LR), _(M,LR), _(M,LR),  _(V,T),  _(x,x),  _(x,x),
   /* 0BD0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,R),
   /* 0BD8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
@@ -205,7 +213,7 @@
 
   /* Telugu */
 
-  /* 0C00 */ _(Bi,x), _(Bi,x), _(Bi,x), _(Vs,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
+  /* 0C00 */ _(Bi,T), _(Bi,R), _(Bi,R), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
   /* 0C08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x), _(VI,x), _(VI,x),
   /* 0C10 */ _(VI,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0C18 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
@@ -216,7 +224,7 @@
   /* 0C40 */  _(M,T),  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(x,x),  _(M,T),  _(M,T),
   /* 0C48 */ _(M,TB),  _(x,x),  _(M,T),  _(M,T),  _(M,T),  _(V,T),  _(x,x),  _(x,x),
   /* 0C50 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,T),  _(M,B),  _(x,x),
-  /* 0C58 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 0C58 */  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 0C60 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
   /* 0C68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 0C70 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
@@ -224,26 +232,26 @@
 
   /* Kannada */
 
-  /* 0C80 */  _(x,x), _(Bi,x), _(Bi,x), _(Vs,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
+  /* 0C80 */  _(x,x), _(Bi,T), _(Bi,R), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
   /* 0C88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x), _(VI,x), _(VI,x),
   /* 0C90 */ _(VI,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0C98 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0CA0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0CA8 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0CB0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0CB8 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,x),  _(A,x),  _(M,R),  _(M,T),
+  /* 0CB8 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,B),  _(A,x),  _(M,R),  _(M,T),
   /* 0CC0 */ _(M,TR),  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(x,x),  _(M,T), _(M,TR),
   /* 0CC8 */ _(M,TR),  _(x,x), _(M,TR), _(M,TR),  _(M,T),  _(V,T),  _(x,x),  _(x,x),
   /* 0CD0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,R),  _(M,R),  _(x,x),
   /* 0CD8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(C,x),  _(x,x),
   /* 0CE0 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
   /* 0CE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* 0CF0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 0CF0 */  _(x,x),_(CWS,x),_(CWS,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 0CF8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
   /* Malayalam */
 
-  /* 0D00 */  _(x,x), _(Bi,x), _(Bi,x), _(Vs,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
+  /* 0D00 */  _(x,x), _(Bi,T), _(Bi,R), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
   /* 0D08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x), _(VI,x), _(VI,x),
   /* 0D10 */ _(VI,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0D18 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
@@ -254,7 +262,7 @@
   /* 0D40 */  _(M,R),  _(M,R),  _(M,R),  _(M,B),  _(M,B),  _(x,x),  _(M,L),  _(M,L),
   /* 0D48 */  _(M,L),  _(x,x), _(M,LR), _(M,LR), _(M,LR),  _(V,T),_(CPR,x),  _(x,x),
   /* 0D50 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,R),
-  /* 0D58 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 0D58 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(VI,x),
   /* 0D60 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
   /* 0D68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 0D70 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
@@ -262,7 +270,7 @@
 
   /* Sinhala */
 
-  /* 0D80 */  _(x,x),  _(x,x), _(Bi,x), _(Vs,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
+  /* 0D80 */  _(x,x),  _(x,x), _(Bi,R), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
   /* 0D88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
   /* 0D90 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x),
   /* 0D98 */  _(x,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
@@ -278,7 +286,7 @@
   /* 0DE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 0DF0 */  _(x,x),  _(x,x),  _(M,R),  _(M,R),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
-#define indic_offset_0x1000u 1304
+#define indic_offset_0x1000u 1336
 
 
   /* Myanmar */
@@ -289,22 +297,22 @@
   /* 1018 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 1020 */  _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
   /* 1028 */ _(VI,x), _(VI,x), _(VI,x),  _(M,R),  _(M,R),  _(M,T),  _(M,T),  _(M,B),
-  /* 1030 */  _(M,B),  _(M,L),  _(M,T),  _(M,T),  _(M,T),  _(M,T), _(Bi,x), _(TM,x),
-  /* 1038 */ _(Vs,x), _(IS,x), _(PK,T), _(CM,x), _(CM,x), _(CM,x), _(CM,x),  _(C,x),
+  /* 1030 */  _(M,B),  _(M,L),  _(M,T),  _(M,T),  _(M,T),  _(M,T), _(Bi,T), _(TM,B),
+  /* 1038 */ _(Vs,R), _(IS,x), _(PK,T), _(CM,R), _(CM,x), _(CM,B), _(CM,B),  _(C,x),
   /* 1040 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 1048 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(CP,x),  _(x,x),
   /* 1050 */  _(C,x),  _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(M,R),  _(M,R),
-  /* 1058 */  _(M,B),  _(M,B),  _(C,x),  _(C,x),  _(C,x),  _(C,x), _(CM,x), _(CM,x),
-  /* 1060 */ _(CM,x),  _(C,x),  _(M,R), _(TM,x), _(TM,x),  _(C,x),  _(C,x),  _(M,R),
-  /* 1068 */  _(M,R), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x),  _(C,x),  _(C,x),
+  /* 1058 */  _(M,B),  _(M,B),  _(C,x),  _(C,x),  _(C,x),  _(C,x), _(CM,B), _(CM,B),
+  /* 1060 */ _(CM,B),  _(C,x),  _(M,R), _(TM,R), _(TM,R),  _(C,x),  _(C,x),  _(M,R),
+  /* 1068 */  _(M,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R),  _(C,x),  _(C,x),
   /* 1070 */  _(C,x),  _(M,T),  _(M,T),  _(M,T),  _(M,T),  _(C,x),  _(C,x),  _(C,x),
   /* 1078 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 1080 */  _(C,x),  _(C,x), _(CM,x),  _(M,R),  _(M,L),  _(M,T),  _(M,T), _(TM,x),
-  /* 1088 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x),  _(C,x), _(TM,x),
+  /* 1080 */  _(C,x),  _(C,x), _(CM,B),  _(M,R),  _(M,L),  _(M,T),  _(M,T), _(TM,R),
+  /* 1088 */ _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,B),  _(C,x), _(TM,R),
   /* 1090 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* 1098 */ _(Nd,x), _(Nd,x), _(TM,x), _(TM,x),  _(M,R),  _(M,T),  _(x,x),  _(x,x),
+  /* 1098 */ _(Nd,x), _(Nd,x), _(TM,R), _(TM,R),  _(M,R),  _(M,T),  _(x,x),  _(x,x),
 
-#define indic_offset_0x1700u 1464
+#define indic_offset_0x1700u 1496
 
 
   /* Tagalog */
@@ -345,14 +353,14 @@
   /* 17A8 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
   /* 17B0 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x),  _(x,x),  _(M,R),  _(M,T),
   /* 17B8 */  _(M,T),  _(M,T),  _(M,T),  _(M,B),  _(M,B),  _(M,B), _(M,TL),_(M,TLR),
-  /* 17C0 */ _(M,LR),  _(M,L),  _(M,L),  _(M,L), _(M,LR), _(M,LR), _(Bi,x), _(Vs,x),
-  /* 17C8 */  _(M,R), _(RS,T), _(RS,T), _(RS,T),_(CSR,T),  _(M,T),  _(M,T),  _(M,T),
-  /* 17D0 */  _(M,T), _(PK,T), _(IS,x),  _(M,T),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 17D8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(A,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 17C0 */ _(M,LR),  _(M,L),  _(M,L),  _(M,L), _(M,LR), _(M,LR), _(Bi,T), _(Vs,R),
+  /* 17C8 */  _(M,R), _(RS,T), _(RS,T), _(SM,T),_(CSR,T), _(CK,T), _(SM,T), _(SM,T),
+  /* 17D0 */ _(SM,T), _(PK,T), _(IS,x), _(SM,T),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 17D8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(A,x),  _(x,T),  _(x,x),  _(x,x),
   /* 17E0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 17E8 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
-#define indic_offset_0x1900u 1704
+#define indic_offset_0x1900u 1736
 
 
   /* Limbu */
@@ -362,9 +370,9 @@
   /* 1910 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 1918 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),
   /* 1920 */  _(M,T),  _(M,T),  _(M,B),  _(M,R),  _(M,R), _(M,TR), _(M,TR),  _(M,T),
-  /* 1928 */  _(M,T), _(CS,x), _(CS,x), _(CS,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 1930 */ _(CF,x), _(CF,x), _(Bi,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
-  /* 1938 */ _(CF,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 1928 */  _(M,T), _(CS,R), _(CS,R), _(CS,R),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 1930 */ _(CF,R), _(CF,R), _(Bi,B), _(CF,R), _(CF,R), _(CF,R), _(CF,R), _(CF,R),
+  /* 1938 */ _(CF,R), _(CF,B),  _(M,T), _(SM,B),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 1940 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
   /* 1948 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
 
@@ -385,10 +393,10 @@
   /* 1998 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 19A0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 19A8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 19B0 */  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(M,L),  _(M,L),  _(M,L),
-  /* 19B8 */  _(M,R),  _(M,R),  _(M,L),  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(M,R),
+  /* 19B0 */  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(M,R),_(M,VOL),_(M,VOL),_(M,VOL),
+  /* 19B8 */  _(M,R),  _(M,R),_(M,VOL),  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(M,R),
   /* 19C0 */  _(M,R), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
-  /* 19C8 */ _(TM,x), _(TM,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 19C8 */ _(TM,R), _(TM,R),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 19D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 19D8 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 19E0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
@@ -411,47 +419,47 @@
   /* 1A38 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 1A40 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 1A48 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x), _(VI,x), _(VI,x), _(VI,x),
-  /* 1A50 */ _(VI,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x), _(CM,L), _(CM,x), _(CF,x),
-  /* 1A58 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),  _(x,x),
+  /* 1A50 */ _(VI,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x), _(CM,L), _(CM,B), _(CF,R),
+  /* 1A58 */ _(CF,T), _(CF,T), _(CF,T), _(CF,B), _(CF,B), _(CF,B), _(CF,B),  _(x,x),
   /* 1A60 */ _(IS,x),  _(M,R),  _(M,T),  _(M,R),  _(M,R),  _(M,T),  _(M,T),  _(M,T),
   /* 1A68 */  _(M,T),  _(M,B),  _(M,B),  _(M,T),  _(M,B),  _(M,R),  _(M,L),  _(M,L),
-  /* 1A70 */  _(M,L),  _(M,L),  _(M,L),  _(M,T),  _(M,T), _(TM,x), _(TM,x), _(TM,x),
-  /* 1A78 */ _(TM,x), _(TM,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 1A70 */  _(M,L),  _(M,L),  _(M,L),  _(M,T),  _(M,T), _(TM,T), _(TM,T), _(TM,T),
+  /* 1A78 */ _(TM,T), _(TM,T), _(SM,T), _(SM,T), _(SM,T),  _(x,x),  _(x,x), _(SM,B),
   /* 1A80 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 1A88 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 1A90 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 1A98 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
-#define indic_offset_0x1b00u 2120
+#define indic_offset_0x1b00u 2152
 
 
   /* Balinese */
 
-  /* 1B00 */ _(Bi,x), _(Bi,x), _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x),
+  /* 1B00 */ _(Bi,T), _(Bi,T), _(Bi,T),_(CSR,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x),
   /* 1B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
   /* 1B10 */ _(VI,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 1B18 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 1B20 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 1B28 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 1B30 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(N,x),  _(M,R),  _(M,T),  _(M,T),
+  /* 1B30 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(N,T),  _(M,R),  _(M,T),  _(M,T),
   /* 1B38 */  _(M,B),  _(M,B),  _(M,B), _(M,BR), _(M,TB),_(M,TBR),  _(M,L),  _(M,L),
   /* 1B40 */ _(M,LR), _(M,LR),  _(M,T), _(M,TR),  _(V,R),  _(C,x),  _(C,x),  _(C,x),
   /* 1B48 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 1B50 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 1B58 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 1B60 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 1B68 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 1B70 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 1B68 */  _(x,x),  _(x,x),  _(x,x),  _(x,T),  _(x,B),  _(x,T),  _(x,T),  _(x,T),
+  /* 1B70 */  _(x,T),  _(x,T),  _(x,T),  _(x,T),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 1B78 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
   /* Sundanese */
 
-  /* 1B80 */ _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+  /* 1B80 */ _(Bi,T),_(CSR,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
   /* 1B88 */ _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 1B90 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 1B98 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 1BA0 */  _(C,x), _(CS,x), _(CS,x), _(CS,x),  _(M,T),  _(M,B),  _(M,L),  _(M,R),
-  /* 1BA8 */  _(M,T),  _(M,T), _(PK,R), _(IS,x), _(CS,x), _(CS,x),  _(C,x),  _(C,x),
+  /* 1BA0 */  _(C,x), _(CS,R), _(CS,B), _(CS,B),  _(M,T),  _(M,B),  _(M,L),  _(M,R),
+  /* 1BA8 */  _(M,T),  _(M,T), _(PK,R), _(IS,x), _(CS,B), _(CS,B),  _(C,x),  _(C,x),
   /* 1BB0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 1BB8 */ _(Nd,x), _(Nd,x),  _(A,x),  _(C,x),  _(C,x),  _(C,x), _(CF,x), _(CF,x),
 
@@ -461,9 +469,9 @@
   /* 1BC8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 1BD0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 1BD8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 1BE0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x), _(VI,x), _(VI,x),  _(N,x),  _(M,R),
+  /* 1BE0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x), _(VI,x), _(VI,x),  _(N,T),  _(M,R),
   /* 1BE8 */  _(M,T),  _(M,T),  _(M,R),  _(M,R),  _(M,R),  _(M,T),  _(M,R),  _(M,T),
-  /* 1BF0 */ _(CF,x), _(CF,x), _(PK,R), _(PK,R),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 1BF0 */ _(CF,T), _(CF,T), _(PK,R), _(PK,R),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 1BF8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
   /* Lepcha */
@@ -472,39 +480,49 @@
   /* 1C08 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 1C10 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 1C18 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 1C20 */  _(C,x),  _(C,x),  _(C,x),  _(C,x), _(CS,x), _(CS,x),  _(M,R),  _(M,L),
-  /* 1C28 */  _(M,L), _(M,TL),  _(M,R),  _(M,R),  _(M,B), _(CF,x), _(CF,x), _(CF,x),
-  /* 1C30 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(Bi,L), _(Bi,L),  _(x,x),  _(N,x),
+  /* 1C20 */  _(C,x),  _(C,x),  _(C,x),  _(C,x), _(CS,R), _(CS,R),  _(M,R),  _(M,L),
+  /* 1C28 */  _(M,L), _(M,TL),  _(M,R),  _(M,R),  _(M,B), _(CF,T), _(CF,T), _(CF,T),
+  /* 1C30 */ _(CF,T), _(CF,T), _(CF,T), _(CF,T), _(Bi,L), _(Bi,L), _(SM,T),  _(N,B),
   /* 1C38 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 1C40 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 1C48 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),
 
-#define indic_offset_0x1cd0u 2456
+#define indic_offset_0x1cd0u 2488
 
 
   /* Vedic Extensions */
 
-  /* 1CD0 */ _(TM,x), _(TM,x), _(TM,x),  _(x,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x),
-  /* 1CD8 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x),
-  /* 1CE0 */ _(TM,x), _(TM,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 1CE8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 1CF0 */  _(x,x),  _(x,x), _(Vs,x), _(Vs,x), _(TM,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 1CD0 */ _(Ca,T), _(Ca,T), _(Ca,T),  _(x,x), _(Ca,O), _(Ca,B), _(Ca,B), _(Ca,B),
+  /* 1CD8 */ _(Ca,B), _(Ca,B), _(Ca,T), _(Ca,T), _(Ca,B), _(Ca,B), _(Ca,B), _(Ca,B),
+  /* 1CE0 */ _(Ca,T), _(Ca,R),  _(x,O),  _(x,O),  _(x,O),  _(x,O),  _(x,O),  _(x,O),
+  /* 1CE8 */  _(x,O),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,B),  _(x,x),  _(x,x),
+  /* 1CF0 */  _(x,x),  _(x,x), _(Vs,x), _(Vs,x), _(Ca,T),  _(x,x),  _(x,x),  _(x,x),
+  /* 1CF8 */ _(Ca,x), _(Ca,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
-#define indic_offset_0x2008u 2496
+#define indic_offset_0x2008u 2536
 
 
   /* General Punctuation */
 
   /* 2008 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),_(ZWNJ,x),_(ZWJ,x),  _(x,x),  _(x,x),
-  /* 2010 */  _(x,x),  _(x,x), _(CP,x), _(CP,x), _(CP,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 2010 */ _(CP,x), _(CP,x), _(CP,x), _(CP,x), _(CP,x),  _(x,x),  _(x,x),  _(x,x),
 
-#define indic_offset_0xa800u 2512
+#define indic_offset_0x2070u 2552
+
+
+  /* Superscripts and Subscripts */
+
+  /* 2070 */  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(SM,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 2078 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 2080 */  _(x,x),  _(x,x), _(SM,x), _(SM,x), _(SM,x),  _(x,x),  _(x,x),  _(x,x),
+
+#define indic_offset_0xa800u 2576
 
 
   /* Syloti Nagri */
 
   /* A800 */ _(VI,x), _(VI,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x), _(PK,T),  _(C,x),
-  /* A808 */  _(C,x),  _(C,x),  _(C,x), _(Bi,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
+  /* A808 */  _(C,x),  _(C,x),  _(C,x), _(Bi,T),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* A810 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* A818 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* A820 */  _(C,x),  _(C,x),  _(C,x),  _(M,R),  _(M,R),  _(M,B),  _(M,T),  _(M,R),
@@ -525,13 +543,13 @@
 
   /* Saurashtra */
 
-  /* A880 */ _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+  /* A880 */ _(Bi,R), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
   /* A888 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
   /* A890 */ _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* A898 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* A8A0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* A8A8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* A8B0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x), _(CF,x),  _(M,R),  _(M,R),  _(M,R),
+  /* A8B0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x), _(CF,R),  _(M,R),  _(M,R),  _(M,R),
   /* A8B8 */  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(M,R),
   /* A8C0 */  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(V,B),  _(x,x),  _(x,x),  _(x,x),
   /* A8C8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
@@ -540,9 +558,9 @@
 
   /* Devanagari Extended */
 
-  /* A8E0 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x),
-  /* A8E8 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x),
-  /* A8F0 */ _(Ca,x), _(Ca,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* A8E0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),
+  /* A8E8 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),
+  /* A8F0 */ _(Ca,T), _(Ca,T),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* A8F8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
   /* Kayah Li */
@@ -552,15 +570,15 @@
   /* A910 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* A918 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* A920 */  _(C,x),  _(C,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x),
-  /* A928 */ _(Vo,x), _(Vo,x), _(Vo,x), _(TM,x), _(TM,x), _(TM,x),  _(x,x),  _(x,x),
+  /* A928 */ _(Vo,x), _(Vo,x), _(Vo,x), _(TM,B), _(TM,B), _(TM,B),  _(x,x),  _(x,x),
 
   /* Rejang */
 
   /* A930 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* A938 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* A940 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(M,B),
-  /* A948 */  _(M,B),  _(M,B),  _(M,T),  _(M,B),  _(M,B),  _(M,B),  _(M,B), _(CF,x),
-  /* A950 */ _(CF,x), _(CF,x), _(CF,x), _(PK,R),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* A948 */  _(M,B),  _(M,B),  _(M,T),  _(M,B),  _(M,B),  _(M,B),  _(M,B), _(CF,T),
+  /* A950 */ _(CF,T), _(CF,T), _(CF,R), _(PK,R),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* A958 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* A960 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* A968 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
@@ -569,14 +587,14 @@
 
   /* Javanese */
 
-  /* A980 */ _(Bi,x), _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+  /* A980 */ _(Bi,T), _(Bi,T),_(CSR,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
   /* A988 */ _(VI,x),  _(C,x),  _(C,x),  _(C,x), _(VI,x), _(VI,x), _(VI,x),  _(C,x),
   /* A990 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* A998 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* A9A0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* A9A8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* A9B0 */  _(C,x),  _(C,x),  _(C,x),  _(N,x),  _(M,R),  _(M,R),  _(M,T),  _(M,T),
-  /* A9B8 */  _(M,B),  _(M,B),  _(M,L),  _(M,L),  _(M,T), _(CS,x), _(CM,x), _(CM,x),
+  /* A9B0 */  _(C,x),  _(C,x),  _(C,x),  _(N,T),  _(M,R),  _(M,R),  _(M,T),  _(M,T),
+  /* A9B8 */  _(M,B),  _(M,B),  _(M,L),  _(M,L),  _(M,T), _(CS,R), _(CM,R), _(CM,R),
   /* A9C0 */ _(V,BR),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* A9C8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* A9D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
@@ -584,7 +602,7 @@
 
   /* Myanmar Extended-B */
 
-  /* A9E0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(C,x),
+  /* A9E0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(M,T),  _(x,x),  _(C,x),
   /* A9E8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* A9F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* A9F8 */ _(Nd,x), _(Nd,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),
@@ -597,10 +615,10 @@
   /* AA18 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* AA20 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* AA28 */  _(C,x),  _(M,T),  _(M,T),  _(M,T),  _(M,T),  _(M,B),  _(M,T),  _(M,L),
-  /* AA30 */  _(M,L),  _(M,T),  _(M,B), _(CM,x), _(CM,L), _(CM,x), _(CM,x),  _(x,x),
+  /* AA30 */  _(M,L),  _(M,T),  _(M,B), _(CM,R), _(CM,L), _(CM,B), _(CM,B),  _(x,x),
   /* AA38 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* AA40 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
-  /* AA48 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),  _(x,x),  _(x,x),
+  /* AA40 */ _(CF,x), _(CF,x), _(CF,x), _(CF,T), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
+  /* AA48 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,T), _(CF,R),  _(x,x),  _(x,x),
   /* AA50 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* AA58 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
@@ -609,7 +627,7 @@
   /* AA60 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* AA68 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* AA70 */  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* AA78 */  _(x,x),  _(x,x),  _(C,x), _(TM,x), _(TM,x), _(TM,x),  _(C,x),  _(C,x),
+  /* AA78 */  _(x,x),  _(x,x),  _(C,x), _(TM,R), _(TM,T), _(TM,R),  _(C,x),  _(C,x),
 
   /* Tai Viet */
 
@@ -620,8 +638,8 @@
   /* AAA0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* AAA8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* AAB0 */  _(M,T),  _(M,R),  _(M,T),  _(M,T),  _(M,B),_(M,VOL),_(M,VOL),  _(M,T),
-  /* AAB8 */  _(M,T),_(M,VOL),  _(M,R),_(M,VOL),_(M,VOL),  _(M,R),  _(M,T), _(TM,x),
-  /* AAC0 */ _(TL,x), _(TM,x), _(TL,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* AAB8 */  _(M,T),_(M,VOL),  _(M,R),_(M,VOL),_(M,VOL),  _(M,R),  _(M,T), _(TM,T),
+  /* AAC0 */ _(TL,x), _(TM,T), _(TL,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* AAC8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* AAD0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* AAD8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
@@ -630,9 +648,9 @@
 
   /* AAE0 */ _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* AAE8 */  _(C,x),  _(C,x),  _(C,x),  _(M,L),  _(M,B),  _(M,T),  _(M,L),  _(M,R),
-  /* AAF0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(Vs,x), _(IS,x),  _(x,x),
+  /* AAF0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(Vs,R), _(IS,x),  _(x,x),
 
-#define indic_offset_0xabc0u 3272
+#define indic_offset_0xabc0u 3336
 
 
   /* Meetei Mayek */
@@ -642,31 +660,31 @@
   /* ABD0 */  _(C,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* ABD8 */  _(C,x),  _(C,x),  _(C,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
   /* ABE0 */ _(CF,x), _(CF,x), _(CF,x),  _(M,R),  _(M,R),  _(M,T),  _(M,R),  _(M,R),
-  /* ABE8 */  _(M,B),  _(M,R),  _(M,R),  _(x,x), _(TM,x), _(PK,B),  _(x,x),  _(x,x),
+  /* ABE8 */  _(M,B),  _(M,R),  _(M,R),  _(x,x), _(TM,R), _(PK,B),  _(x,x),  _(x,x),
   /* ABF0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* ABF8 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
-#define indic_offset_0x10a00u 3336
+#define indic_offset_0x10a00u 3400
 
 
   /* Kharoshthi */
 
   /* 10A00 */  _(C,x),  _(M,O),  _(M,B),  _(M,B),  _(x,x),  _(M,T),  _(M,O),  _(x,x),
-  /* 10A08 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,B),  _(x,x), _(Bi,x), _(Vs,x),
+  /* 10A08 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,B),  _(M,B), _(Bi,B), _(Vs,T),
   /* 10A10 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),
   /* 10A18 */  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 10A20 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 10A28 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 10A30 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 10A38 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(IS,x),
+  /* 10A38 */  _(N,T),  _(N,B),  _(N,B),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(IS,x),
   /* 10A40 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
 
-#define indic_offset_0x11000u 3408
+#define indic_offset_0x11000u 3472
 
 
   /* Brahmi */
 
-  /* 11000 */ _(Bi,x), _(Bi,x), _(Vs,x),  _(x,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
+  /* 11000 */ _(Bi,R), _(Bi,T), _(Vs,R),_(CWS,x),_(CWS,x), _(VI,x), _(VI,x), _(VI,x),
   /* 11008 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
   /* 11010 */ _(VI,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 11018 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
@@ -685,21 +703,21 @@
 
   /* Kaithi */
 
-  /* 11080 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+  /* 11080 */ _(Bi,T), _(Bi,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
   /* 11088 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
   /* 11090 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 11098 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 110A0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 110A8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 110B0 */  _(M,R),  _(M,L),  _(M,R),  _(M,B),  _(M,B),  _(M,T),  _(M,T),  _(M,R),
-  /* 110B8 */  _(M,R),  _(V,B),  _(N,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 110B8 */  _(M,R),  _(V,B),  _(N,B),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
-#define indic_offset_0x11100u 3600
+#define indic_offset_0x11100u 3664
 
 
   /* Chakma */
 
-  /* 11100 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(C,x),
+  /* 11100 */ _(Bi,T), _(Bi,T), _(Vs,T), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(C,x),
   /* 11108 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 11110 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 11118 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
@@ -716,12 +734,12 @@
   /* 11158 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 11160 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 11168 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 11170 */  _(C,x),  _(C,x),  _(C,x),  _(N,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 11170 */  _(C,x),  _(C,x),  _(C,x),  _(N,B),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 11178 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
   /* Sharada */
 
-  /* 11180 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+  /* 11180 */ _(Bi,T), _(Bi,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
   /* 11188 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
   /* 11190 */ _(VI,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 11198 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
@@ -729,8 +747,8 @@
   /* 111A8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 111B0 */  _(C,x),  _(C,x),  _(C,x),  _(M,R),  _(M,L),  _(M,R),  _(M,B),  _(M,B),
   /* 111B8 */  _(M,B),  _(M,B),  _(M,B),  _(M,B),  _(M,T),  _(M,T),  _(M,T), _(M,TR),
-  /* 111C0 */  _(V,R),  _(A,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 111C8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 111C0 */  _(V,R),  _(A,x),_(CPrf,x),_(CPrf,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 111C8 */  _(x,x),  _(x,x),  _(N,x),  _(M,T),  _(M,B),  _(x,x),  _(x,x),  _(x,x),
   /* 111D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 111D8 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
@@ -749,11 +767,20 @@
   /* 11218 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 11220 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 11228 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(M,R),  _(M,R),  _(M,R),  _(M,B),
-  /* 11230 */  _(M,T),  _(M,T), _(M,TR), _(M,TR), _(Bi,x),  _(V,R),  _(N,x), _(GM,T),
+  /* 11230 */  _(M,T),  _(M,T), _(M,TR), _(M,TR), _(Bi,T),  _(V,R),  _(N,T), _(GM,T),
 
-#define indic_offset_0x112b0u 3912
+#define indic_offset_0x11280u 3976
 
 
+  /* Multani */
+
+  /* 11280 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),
+  /* 11288 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),
+  /* 11290 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
+  /* 11298 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),
+  /* 112A0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
+  /* 112A8 */  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+
   /* Khudawadi */
 
   /* 112B0 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
@@ -761,15 +788,15 @@
   /* 112C0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 112C8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 112D0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 112D8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x), _(Bi,x),
+  /* 112D8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x), _(Bi,T),
   /* 112E0 */  _(M,R),  _(M,L),  _(M,R),  _(M,B),  _(M,B),  _(M,T),  _(M,T),  _(M,T),
-  /* 112E8 */  _(M,T),  _(N,x), _(PK,B),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 112E8 */  _(M,T),  _(N,B), _(PK,B),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 112F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 112F8 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
   /* Grantha */
 
-  /* 11300 */  _(x,x), _(Bi,x), _(Bi,x), _(Vs,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
+  /* 11300 */ _(Bi,x), _(Bi,T), _(Bi,R), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
   /* 11308 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x),  _(x,x), _(VI,x),
   /* 11310 */ _(VI,x),  _(x,x),  _(x,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
   /* 11318 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
@@ -781,11 +808,11 @@
   /* 11348 */  _(M,L),  _(x,x),  _(x,x), _(M,LR), _(M,LR),  _(V,R),  _(x,x),  _(x,x),
   /* 11350 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,R),
   /* 11358 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 11360 */ _(VI,x), _(VI,x),  _(M,R),  _(M,R),  _(x,x),  _(x,x), _(Ca,x), _(Ca,x),
-  /* 11368 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 11370 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 11360 */ _(VI,x), _(VI,x),  _(M,R),  _(M,R),  _(x,x),  _(x,x), _(Ca,T), _(Ca,T),
+  /* 11368 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),  _(x,x),  _(x,x),  _(x,x),
+  /* 11370 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),  _(x,x),  _(x,x),  _(x,x),
 
-#define indic_offset_0x11480u 4112
+#define indic_offset_0x11480u 4224
 
 
   /* Tirhuta */
@@ -797,13 +824,13 @@
   /* 114A0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 114A8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 114B0 */  _(M,R),  _(M,L),  _(M,R),  _(M,B),  _(M,B),  _(M,B),  _(M,B),  _(M,B),
-  /* 114B8 */  _(M,B),  _(M,L),  _(M,T), _(M,TL), _(M,LR),  _(M,R), _(M,LR), _(Bi,x),
-  /* 114C0 */ _(Bi,x), _(Vs,x),  _(V,B),  _(N,x),  _(A,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 114B8 */  _(M,B),  _(M,L),  _(M,T), _(M,TL), _(M,LR),  _(M,R), _(M,LR), _(Bi,T),
+  /* 114C0 */ _(Bi,T), _(Vs,R),  _(V,B),  _(N,B),  _(A,x),  _(x,x),  _(x,x),  _(x,x),
   /* 114C8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 114D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 114D8 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
-#define indic_offset_0x11580u 4208
+#define indic_offset_0x11580u 4320
 
 
   /* Siddham */
@@ -815,11 +842,15 @@
   /* 115A0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 115A8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(M,R),
   /* 115B0 */  _(M,L),  _(M,R),  _(M,B),  _(M,B),  _(M,B),  _(M,B),  _(x,x),  _(x,x),
-  /* 115B8 */  _(M,L), _(M,TL), _(M,LR),_(M,TLR), _(Bi,x), _(Bi,x), _(Vs,x),  _(V,B),
-  /* 115C0 */  _(N,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-
-#define indic_offset_0x11600u 4280
-
+  /* 115B8 */  _(M,L), _(M,TL), _(M,LR),_(M,TLR), _(Bi,T), _(Bi,T), _(Vs,R),  _(V,B),
+  /* 115C0 */  _(N,B),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 115C8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 115D0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 115D8 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x),
+  /* 115E0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 115E8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 115F0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 115F8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
   /* Modi */
 
@@ -830,8 +861,8 @@
   /* 11620 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 11628 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 11630 */  _(M,R),  _(M,R),  _(M,R),  _(M,B),  _(M,B),  _(M,B),  _(M,B),  _(M,B),
-  /* 11638 */  _(M,B),  _(M,T),  _(M,T),  _(M,R),  _(M,R), _(Bi,x), _(Vs,x),  _(V,B),
-  /* 11640 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 11638 */  _(M,B),  _(M,T),  _(M,T),  _(M,R),  _(M,R), _(Bi,T), _(Vs,R),  _(V,B),
+  /* 11640 */  _(M,T),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 11648 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 11650 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 11658 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
@@ -847,13 +878,30 @@
   /* 11690 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 11698 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 116A0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 116A8 */  _(C,x),  _(C,x),  _(C,x), _(Bi,x), _(Vs,x),  _(M,T),  _(M,L),  _(M,R),
-  /* 116B0 */  _(M,B),  _(M,B),  _(M,T),  _(M,T),  _(M,T),  _(M,T),  _(V,T),  _(N,x),
+  /* 116A8 */  _(C,x),  _(C,x),  _(C,x), _(Bi,T), _(Vs,R),  _(M,T),  _(M,L),  _(M,R),
+  /* 116B0 */  _(M,B),  _(M,B),  _(M,T),  _(M,T),  _(M,T),  _(M,T),  _(V,R),  _(N,B),
   /* 116B8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 116C0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 116C8 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 116D0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 116D8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 116E0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 116E8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 116F0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 116F8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+
+  /* Ahom */
+
+  /* 11700 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
+  /* 11708 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
+  /* 11710 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
+  /* 11718 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x), _(CM,B), _(CM,x), _(CM,T),
+  /* 11720 */  _(M,R),  _(M,R),  _(M,T),  _(M,T),  _(M,B),  _(M,B),  _(M,L),  _(M,T),
+  /* 11728 */  _(M,B),  _(M,T),  _(M,T), _(PK,T),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 11730 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
+  /* 11738 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
-}; /* Table items: 4488; occupancy: 73% */
+}; /* Table items: 4768; occupancy: 72% */
 
 INDIC_TABLE_ELEMENT_TYPE
 hb_indic_get_categories (hb_codepoint_t u)
@@ -862,7 +910,7 @@
   {
     case 0x0u:
       if (hb_in_range (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
-      if (hb_in_range (u, 0x00D0u, 0x00D7u)) return indic_table[u - 0x00D0u + indic_offset_0x00d0u];
+      if (hb_in_range (u, 0x00B0u, 0x00D7u)) return indic_table[u - 0x00B0u + indic_offset_0x00b0u];
       if (hb_in_range (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
       if (unlikely (u == 0x00A0u)) return _(CP,x);
       break;
@@ -872,11 +920,12 @@
       if (hb_in_range (u, 0x1700u, 0x17EFu)) return indic_table[u - 0x1700u + indic_offset_0x1700u];
       if (hb_in_range (u, 0x1900u, 0x1A9Fu)) return indic_table[u - 0x1900u + indic_offset_0x1900u];
       if (hb_in_range (u, 0x1B00u, 0x1C4Fu)) return indic_table[u - 0x1B00u + indic_offset_0x1b00u];
-      if (hb_in_range (u, 0x1CD0u, 0x1CF7u)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
+      if (hb_in_range (u, 0x1CD0u, 0x1CFFu)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
       break;
 
     case 0x2u:
       if (hb_in_range (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
+      if (hb_in_range (u, 0x2070u, 0x2087u)) return indic_table[u - 0x2070u + indic_offset_0x2070u];
       if (unlikely (u == 0x25CCu)) return _(CP,x);
       break;
 
@@ -892,10 +941,9 @@
     case 0x11u:
       if (hb_in_range (u, 0x11000u, 0x110BFu)) return indic_table[u - 0x11000u + indic_offset_0x11000u];
       if (hb_in_range (u, 0x11100u, 0x11237u)) return indic_table[u - 0x11100u + indic_offset_0x11100u];
-      if (hb_in_range (u, 0x112B0u, 0x11377u)) return indic_table[u - 0x112B0u + indic_offset_0x112b0u];
+      if (hb_in_range (u, 0x11280u, 0x11377u)) return indic_table[u - 0x11280u + indic_offset_0x11280u];
       if (hb_in_range (u, 0x11480u, 0x114DFu)) return indic_table[u - 0x11480u + indic_offset_0x11480u];
-      if (hb_in_range (u, 0x11580u, 0x115C7u)) return indic_table[u - 0x11580u + indic_offset_0x11580u];
-      if (hb_in_range (u, 0x11600u, 0x116CFu)) return indic_table[u - 0x11600u + indic_offset_0x11600u];
+      if (hb_in_range (u, 0x11580u, 0x1173Fu)) return indic_table[u - 0x11580u + indic_offset_0x11580u];
       break;
 
     default:
@@ -914,11 +962,14 @@
 #undef ISC_CD
 #undef ISC_CF
 #undef ISC_CHL
+#undef ISC_CK
 #undef ISC_CM
 #undef ISC_CP
 #undef ISC_CPR
+#undef ISC_CPrf
 #undef ISC_CS
 #undef ISC_CSR
+#undef ISC_CWS
 #undef ISC_GM
 #undef ISC_IS
 #undef ISC_ZWJ
@@ -930,6 +981,7 @@
 #undef ISC_x
 #undef ISC_PK
 #undef ISC_RS
+#undef ISC_SM
 #undef ISC_TL
 #undef ISC_TM
 #undef ISC_V
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc	2016-08-05 14:37:07.945011454 +0300
@@ -176,24 +176,8 @@
    * Re-assign category
    */
 
-
-  /* The spec says U+0952 is OT_A.  However, testing shows that Uniscribe
-   * treats a whole bunch of characters similarly.
-   * TESTS: For example, for U+0951:
-   * U+092E,U+0947,U+0952
-   * U+092E,U+0952,U+0947
-   * U+092E,U+0947,U+0951
-   * U+092E,U+0951,U+0947
-   * U+092E,U+0951,U+0952
-   * U+092E,U+0952,U+0951
-   */
-  if (unlikely (hb_in_ranges (u, 0x0951u, 0x0952u,
-				 0x1CD0u, 0x1CD2u,
-				 0x1CD4u, 0x1CE1u) ||
-			    u == 0x1CF4u))
-    cat = OT_A;
   /* The following act more like the Bindus. */
-  else if (unlikely (hb_in_range (u, 0x0953u, 0x0954u)))
+  if (unlikely (hb_in_range (u, 0x0953u, 0x0954u)))
     cat = OT_SM;
   /* The following act like consonants. */
   else if (unlikely (hb_in_ranges (u, 0x0A72u, 0x0A73u,
@@ -216,15 +200,12 @@
     cat = OT_Symbol;
     ASSERT_STATIC ((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol);
   }
-  else if (unlikely (hb_in_range (u, 0x17CDu, 0x17D1u) ||
-		     u == 0x17CBu || u == 0x17D3u || u == 0x17DDu)) /* Khmer Various signs */
+  else if (unlikely (u == 0x17DDu)) /* https://github.com/roozbehp/unicode-data/issues/2 */
   {
-    /* These are like Top Matras. */
     cat = OT_M;
     pos = POS_ABOVE_C;
   }
   else if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */
-  else if (unlikely (u == 0x17D2u)) cat = OT_Coeng; /* Khmer coeng */
   else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u)))
 				    cat = OT_PLACEHOLDER;
   else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
@@ -557,8 +538,15 @@
   indic_plan->virama_glyph = (hb_codepoint_t) -1;
 
   /* Use zero-context would_substitute() matching for new-spec of the main
-   * Indic scripts, and scripts with one spec only, but not for old-specs. */
-  bool zero_context = !indic_plan->is_old_spec;
+   * Indic scripts, and scripts with one spec only, but not for old-specs.
+   * The new-spec for all dual-spec scripts says zero-context matching happens.
+   *
+   * However, testing with Malayalam shows that old and new spec both allow
+   * context.  Testing with Bengali new-spec however shows that it doesn't.
+   * So, the heuristic here is the way it is.  It should *only* be changed,
+   * as we discover more cases of what Windows does.  DON'T TOUCH OTHERWISE.
+   */
+  bool zero_context = !indic_plan->is_old_spec && plan->props.script != HB_SCRIPT_MALAYALAM;
   indic_plan->rphf.init (&plan->map, HB_TAG('r','p','h','f'), zero_context);
   indic_plan->pref.init (&plan->map, HB_TAG('p','r','e','f'), zero_context);
   indic_plan->blwf.init (&plan->map, HB_TAG('b','l','w','f'), zero_context);
@@ -1348,6 +1336,25 @@
 	    break;
 	  }
       }
+      /* For Malayalam, skip over unformed below- (but NOT post-) forms. */
+      if (buffer->props.script == HB_SCRIPT_MALAYALAM)
+      {
+	for (unsigned int i = base + 1; i < end; i++)
+	{
+	  while (i < end && is_joiner (info[i]))
+	    i++;
+	  if (i == end || !is_halant_or_coeng (info[i]))
+	    break;
+	  i++; /* Skip halant. */
+	  while (i < end && is_joiner (info[i]))
+	    i++;
+	  if (i < end && is_consonant (info[i]) && info[i].indic_position() == POS_BELOW_C)
+	  {
+	    base = i;
+	    info[base].indic_position() = POS_BASE_C;
+	  }
+	}
+      }
 
       if (start < base && info[base].indic_position() > POS_BASE_C)
         base--;
@@ -1806,7 +1813,7 @@
     }
   }
 
-  return c->unicode->decompose (ab, a, b);
+  return (bool) c->unicode->decompose (ab, a, b);
 }
 
 static bool
@@ -1822,7 +1829,7 @@
   /* Composition-exclusion exceptions that we want to recompose. */
   if (a == 0x09AFu && b == 0x09BCu) { *ab = 0x09DFu; return true; }
 
-  return c->unicode->compose (a, b, ab);
+  return (bool) c->unicode->compose (a, b, ab);
 }
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc	2016-08-05 14:37:07.945011454 +0300
@@ -199,6 +199,10 @@
       cat = (indic_category_t) OT_A;
       break;
 
+    case 0x1039u:
+      cat = (indic_category_t) OT_H;
+      break;
+
     case 0x103Au:
       cat = (indic_category_t) OT_As;
       break;
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh	2016-08-05 14:37:07.945011454 +0300
@@ -44,9 +44,7 @@
 //  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY,
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE,
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
-
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT = HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE
 };
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc	2016-08-05 14:37:07.945011454 +0300
@@ -377,6 +377,6 @@
   NULL, /* decompose */
   NULL, /* compose */
   NULL, /* setup_masks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT,
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE,
   false,/* fallback_position */
 };
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc	2016-08-05 14:37:07.946011446 +0300
@@ -57,6 +57,6 @@
   NULL, /* decompose */
   NULL, /* compose */
   NULL, /* setup_masks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT,
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE,
   true, /* fallback_position */
 };
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc	2016-08-05 14:37:07.946011446 +0300
@@ -285,6 +285,9 @@
 setup_topographical_masks (const hb_ot_shape_plan_t *plan,
 			   hb_buffer_t *buffer)
 {
+  const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
+  if (use_plan->arabic_plan)
+    return;
 
   ASSERT_STATIC (INIT < 4 && ISOL < 4 && MEDI < 4 && FINA < 4);
   hb_mask_t masks[4], all_masks = 0;
@@ -360,7 +363,7 @@
   hb_glyph_info_t *info = buffer->info;
   unsigned int count = buffer->len;
   for (unsigned int i = 0; i < count; i++)
-    _hb_glyph_info_clear_substituted_and_ligated_and_multiplied (&info[i]);
+    _hb_glyph_info_clear_substituted (&info[i]);
 }
 
 static void
@@ -405,6 +408,12 @@
   }
 }
 
+static inline bool
+is_halant (const hb_glyph_info_t &info)
+{
+  return info.use_category() == USE_H && !_hb_glyph_info_ligated (&info);
+}
+
 static void
 reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
 {
@@ -420,7 +429,6 @@
 
   hb_glyph_info_t *info = buffer->info;
 
-#define HALANT_FLAGS FLAG(USE_H)
 #define BASE_FLAGS (FLAG (USE_B) | FLAG (USE_GB) | FLAG (USE_IV))
 
   /* Move things forward. */
@@ -428,12 +436,12 @@
   {
     /* Got a repha.  Reorder it to after first base, before first halant. */
     for (unsigned int i = start + 1; i < end; i++)
-      if (FLAG_UNSAFE (info[i].use_category()) & (HALANT_FLAGS | BASE_FLAGS))
+      if ((FLAG_UNSAFE (info[i].use_category()) & (BASE_FLAGS)) || is_halant (info[i]))
       {
 	/* If we hit a halant, move before it; otherwise it's a base: move to it's
 	 * place, and shift things in between backward. */
 
-	if (info[i].use_category() == USE_H)
+	if (is_halant (info[i]))
 	  i--;
 
 	buffer->merge_clusters (start, i + 1);
@@ -450,11 +458,11 @@
   for (unsigned int i = start; i < end; i++)
   {
     uint32_t flag = FLAG_UNSAFE (info[i].use_category());
-    if (flag & (HALANT_FLAGS | BASE_FLAGS))
+    if ((flag & (BASE_FLAGS)) || is_halant (info[i]))
     {
-      /* If we hit a halant, move before it; otherwise it's a base: move to it's
+      /* If we hit a halant, move after it; otherwise it's a base: move to it's
        * place, and shift things in between backward. */
-      if (info[i].use_category() == USE_H)
+      if (is_halant (info[i]))
 	j = i + 1;
       else
 	j = i;
@@ -558,7 +566,7 @@
   if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (c->unicode->general_category (a)))
     return false;
 
-  return c->unicode->compose (a, b, ab);
+  return (bool)c->unicode->compose (a, b, ab);
 }
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-normalize.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape-normalize.cc	2016-08-05 14:37:07.946011446 +0300
@@ -76,7 +76,7 @@
 		   hb_codepoint_t *a,
 		   hb_codepoint_t *b)
 {
-  return c->unicode->decompose (ab, a, b);
+  return (bool) c->unicode->decompose (ab, a, b);
 }
 
 static bool
@@ -85,7 +85,7 @@
 		 hb_codepoint_t  b,
 		 hb_codepoint_t *ab)
 {
-  return c->unicode->compose (a, b, ab);
+  return (bool) c->unicode->compose (a, b, ab);
 }
 
 static inline void
@@ -127,7 +127,7 @@
       (b && !font->get_glyph (b, 0, &b_glyph)))
     return 0;
 
-  bool has_a = font->get_glyph (a, 0, &a_glyph);
+  bool has_a = (bool) font->get_glyph (a, 0, &a_glyph);
   if (shortest && has_a) {
     /* Output a and b */
     output_char (buffer, a, a_glyph);
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape.cc	2016-08-05 14:37:07.947011438 +0300
@@ -662,6 +662,7 @@
   {
     for (unsigned int i = 0; i < count; i++)
       pos[i].x_advance = c->font->get_glyph_h_advance (info[i].codepoint);
+    /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
     if (c->font->has_glyph_h_origin_func ())
       for (unsigned int i = 0; i < count; i++)
 	c->font->subtract_glyph_h_origin (info[i].codepoint,
@@ -671,12 +672,12 @@
   else
   {
     for (unsigned int i = 0; i < count; i++)
+    {
       pos[i].y_advance = c->font->get_glyph_v_advance (info[i].codepoint);
-    if (c->font->has_glyph_v_origin_func ())
-      for (unsigned int i = 0; i < count; i++)
-	c->font->subtract_glyph_v_origin (info[i].codepoint,
-					  &pos[i].x_offset,
-					  &pos[i].y_offset);
+      c->font->subtract_glyph_v_origin (info[i].codepoint,
+					&pos[i].x_offset,
+					&pos[i].y_offset);
+    }
   }
   if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK)
     _hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer);
@@ -687,7 +688,7 @@
 {
   bool ret = false;
   unsigned int count = c->buffer->len;
-  bool has_positioning = hb_ot_layout_has_positioning (c->face);
+  bool has_positioning = (bool) hb_ot_layout_has_positioning (c->face);
   /* If the font has no GPOS, AND, no fallback positioning will
    * happen, AND, direction is forward, then when zeroing mark
    * widths, we shift the mark with it, such that the mark
@@ -726,6 +727,7 @@
 
     /* Change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
 
+    /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
     if (c->font->has_glyph_h_origin_func ())
       for (unsigned int i = 0; i < count; i++)
 	c->font->add_glyph_h_origin (info[i].codepoint,
@@ -734,6 +736,7 @@
 
     c->plan->position (c->font, c->buffer);
 
+    /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
     if (c->font->has_glyph_h_origin_func ())
       for (unsigned int i = 0; i < count; i++)
 	c->font->subtract_glyph_h_origin (info[i].codepoint,
@@ -852,6 +855,8 @@
 
 
 /**
+ * hb_ot_shape_plan_collect_lookups:
+ *
  * Since: 0.9.7
  **/
 void
@@ -885,6 +890,8 @@
 
 
 /**
+ * hb_ot_shape_glyphs_closure:
+ *
  * Since: 0.9.2
  **/
 void
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-shape.h	2016-08-05 14:37:07.947011438 +0300
@@ -36,14 +36,14 @@
 HB_BEGIN_DECLS
 
 /* TODO port to shape-plan / set. */
-void
+HB_EXTERN void
 hb_ot_shape_glyphs_closure (hb_font_t          *font,
 			    hb_buffer_t        *buffer,
 			    const hb_feature_t *features,
 			    unsigned int        num_features,
 			    hb_set_t           *glyphs);
 
-void
+HB_EXTERN void
 hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
 				  hb_tag_t         table_tag,
 				  hb_set_t        *lookup_indexes /* OUT */);
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-tag.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-tag.cc	2016-08-05 14:37:07.947011438 +0300
@@ -355,7 +355,6 @@
   {"hay",	HB_TAG('H','A','Y',' ')},	/* Haya */
   {"haz",	HB_TAG('H','A','Z',' ')},	/* Hazaragi */
   {"he",	HB_TAG('I','W','R',' ')},	/* Hebrew */
-  {"hz",	HB_TAG('H','E','R',' ')},	/* Herero */
   {"hi",	HB_TAG('H','I','N',' ')},	/* Hindi */
   {"hil",	HB_TAG('H','I','L',' ')},	/* Hiligaynon */
   {"hnd",	HB_TAG('H','N','D',' ')},	/* [Southern] Hindko */
@@ -601,8 +600,8 @@
   {"sah",	HB_TAG('Y','A','K',' ')},	/* Yakut */
   {"sas",	HB_TAG('S','A','S',' ')},	/* Sasak */
   {"sat",	HB_TAG('S','A','T',' ')},	/* Santali */
-  {"sck",	HB_TAG('S','A','D',' ')},	/* Sadri */
   {"sc",	HB_TAG('S','R','D',' ')},	/* Sardinian [macrolanguage] */
+  {"sck",	HB_TAG('S','A','D',' ')},	/* Sadri */
   {"scn",	HB_TAG('S','C','N',' ')},	/* Sicilian */
   {"sco",	HB_TAG('S','C','O',' ')},	/* Scots */
   {"scs",	HB_TAG('S','L','A',' ')},	/* [North] Slavey */
@@ -690,8 +689,8 @@
   {"uzs",	HB_TAG('U','Z','B',' ')},	/* Southern Uzbek */
   {"ve",	HB_TAG('V','E','N',' ')},	/* Venda */
   {"vec",	HB_TAG('V','E','C',' ')},	/* Venetian */
-  {"vls",	HB_TAG('F','L','E',' ')},	/* Vlaams */
   {"vi",	HB_TAG('V','I','T',' ')},	/* Vietnamese */
+  {"vls",	HB_TAG('F','L','E',' ')},	/* Vlaams */
   {"vmw",	HB_TAG('M','A','K',' ')},	/* Makhuwa */
   {"vo",	HB_TAG('V','O','L',' ')},	/* Volapük */
   {"vro",	HB_TAG('V','R','O',' ')},	/* Võro */
@@ -700,9 +699,9 @@
   {"wbm",	HB_TAG('W','A',' ',' ')},	/* Wa */
   {"wbr",	HB_TAG('W','A','G',' ')},	/* Wagdi */
   {"wle",	HB_TAG('S','I','G',' ')},	/* Wolane */
+  {"wo",	HB_TAG('W','L','F',' ')},	/* Wolof */
   {"wry",	HB_TAG('M','A','W',' ')},	/* Merwari */
   {"wtm",	HB_TAG('W','T','M',' ')},	/* Mewati */
-  {"wo",	HB_TAG('W','L','F',' ')},	/* Wolof */
   {"xal",	HB_TAG('K','L','M',' ')},	/* Kalmyk */
   {"xh",	HB_TAG('X','H','S',' ')},	/* Xhosa */
   {"xog",	HB_TAG('X','O','G',' ')},	/* Soga */
@@ -928,4 +927,27 @@
   }
 }
 
+static inline void
+test_langs_sorted (void)
+{
+  for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages); i++)
+  {
+    int c = lang_compare_first_component (ot_languages[i-1].language, ot_languages[i].language);
+    if (c >= 0)
+    {
+      fprintf (stderr, "ot_languages not sorted at index %d: %s %d %s\n",
+	       i, ot_languages[i-1].language, c, ot_languages[i].language);
+      abort();
+    }
+  }
+}
+
+#ifdef MAIN
+int
+main (void)
+{
+  test_langs_sorted ();
+  return 0;
+}
 
+#endif
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-tag.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-ot-tag.h	2016-08-05 14:37:07.947011438 +0300
@@ -39,18 +39,18 @@
 #define HB_OT_TAG_DEFAULT_SCRIPT	HB_TAG ('D', 'F', 'L', 'T')
 #define HB_OT_TAG_DEFAULT_LANGUAGE	HB_TAG ('d', 'f', 'l', 't')
 
-void
+HB_EXTERN void
 hb_ot_tags_from_script (hb_script_t  script,
 			hb_tag_t    *script_tag_1,
 			hb_tag_t    *script_tag_2);
 
-hb_script_t
+HB_EXTERN hb_script_t
 hb_ot_tag_to_script (hb_tag_t tag);
 
-hb_tag_t
+HB_EXTERN hb_tag_t
 hb_ot_tag_from_language (hb_language_t language);
 
-hb_language_t
+HB_EXTERN hb_language_t
 hb_ot_tag_to_language (hb_tag_t tag);
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-private.hh.1228540	2016-06-04 03:12:40.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-private.hh	2016-08-05 14:37:07.948011431 +0300
@@ -53,9 +53,6 @@
 #include <errno.h>
 #include <stdarg.h>
 
-#ifdef _MSC_VER
-#include <windows.h> /* ensure DEFINE_ENUM_FLAG_OPERATORS is defined */
-#endif
 
 /* Compile-time custom allocator support. */
 
@@ -182,6 +179,9 @@
 #  endif
 #  if defined(_MSC_VER) && _MSC_VER < 1900
 #    define snprintf _snprintf
+#  elif defined(_MSC_VER) && _MSC_VER >= 1900
+#    /* Covers VC++ Error for strdup being a deprecated POSIX name and to instead use _strdup instead */
+#    define strdup _strdup
 #  endif
 #endif
 
@@ -899,27 +899,22 @@
  * one enum to another...  So this doesn't provide the type-checking that I
  * originally had in mind... :(.
  *
- * On MSVC use DEFINE_ENUM_FLAG_OPERATORS.  See:
- * https://github.com/behdad/harfbuzz/pull/163
+ * For MSVC warnings, see: https://github.com/behdad/harfbuzz/pull/163
  */
 #ifdef _MSC_VER
 # pragma warning(disable:4200)
 # pragma warning(disable:4800)
-# define HB_MARK_AS_FLAG_T(flags_t)	DEFINE_ENUM_FLAG_OPERATORS (##flags_t##);
-#else
-# define HB_MARK_AS_FLAG_T(flags_t)	template <> class hb_mark_as_flags_t<flags_t> {};
-template <class T> class hb_mark_as_flags_t;
-template <class T> static inline T operator | (T l, T r)
-{ hb_mark_as_flags_t<T> unused HB_UNUSED; return T ((unsigned int) l | (unsigned int) r); }
-template <class T> static inline T operator & (T l, T r)
-{ hb_mark_as_flags_t<T> unused HB_UNUSED; return T ((unsigned int) l & (unsigned int) r); }
-template <class T> static inline T operator ~ (T r)
-{ hb_mark_as_flags_t<T> unused HB_UNUSED; return T (~(unsigned int) r); }
-template <class T> static inline T& operator |= (T &l, T r)
-{ hb_mark_as_flags_t<T> unused HB_UNUSED; l = l | r; return l; }
-template <class T> static inline T& operator &= (T& l, T r)
-{ hb_mark_as_flags_t<T> unused HB_UNUSED; l = l & r; return l; }
 #endif
+#define HB_MARK_AS_FLAG_T(T) \
+	extern "C++" { \
+	  static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
+	  static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
+	  static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
+	  static inline T operator ~ (T r) { return T (~(unsigned int) r); } \
+	  static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
+	  static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
+	  static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
+	}
 
 
 /* Useful for set-operations on small enums.
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-set.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-set.h	2016-08-05 14:37:07.948011431 +0300
@@ -44,109 +44,109 @@
 typedef struct hb_set_t hb_set_t;
 
 
-hb_set_t *
+HB_EXTERN hb_set_t *
 hb_set_create (void);
 
-hb_set_t *
+HB_EXTERN hb_set_t *
 hb_set_get_empty (void);
 
-hb_set_t *
+HB_EXTERN hb_set_t *
 hb_set_reference (hb_set_t *set);
 
-void
+HB_EXTERN void
 hb_set_destroy (hb_set_t *set);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_set_set_user_data (hb_set_t           *set,
 		      hb_user_data_key_t *key,
 		      void *              data,
 		      hb_destroy_func_t   destroy,
 		      hb_bool_t           replace);
 
-void *
+HB_EXTERN void *
 hb_set_get_user_data (hb_set_t           *set,
 		      hb_user_data_key_t *key);
 
 
 /* Returns false if allocation has failed before */
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_set_allocation_successful (const hb_set_t *set);
 
-void
+HB_EXTERN void
 hb_set_clear (hb_set_t *set);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_set_is_empty (const hb_set_t *set);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_set_has (const hb_set_t *set,
 	    hb_codepoint_t  codepoint);
 
 /* Right now limited to 16-bit integers.  Eventually will do full codepoint range, sans -1
  * which we will use as a sentinel. */
-void
+HB_EXTERN void
 hb_set_add (hb_set_t       *set,
 	    hb_codepoint_t  codepoint);
 
-void
+HB_EXTERN void
 hb_set_add_range (hb_set_t       *set,
 		  hb_codepoint_t  first,
 		  hb_codepoint_t  last);
 
-void
+HB_EXTERN void
 hb_set_del (hb_set_t       *set,
 	    hb_codepoint_t  codepoint);
 
-void
+HB_EXTERN void
 hb_set_del_range (hb_set_t       *set,
 		  hb_codepoint_t  first,
 		  hb_codepoint_t  last);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_set_is_equal (const hb_set_t *set,
 		 const hb_set_t *other);
 
-void
+HB_EXTERN void
 hb_set_set (hb_set_t       *set,
 	    const hb_set_t *other);
 
-void
+HB_EXTERN void
 hb_set_union (hb_set_t       *set,
 	      const hb_set_t *other);
 
-void
+HB_EXTERN void
 hb_set_intersect (hb_set_t       *set,
 		  const hb_set_t *other);
 
-void
+HB_EXTERN void
 hb_set_subtract (hb_set_t       *set,
 		 const hb_set_t *other);
 
-void
+HB_EXTERN void
 hb_set_symmetric_difference (hb_set_t       *set,
 			     const hb_set_t *other);
 
-void
+HB_EXTERN void
 hb_set_invert (hb_set_t *set);
 
-unsigned int
+HB_EXTERN unsigned int
 hb_set_get_population (const hb_set_t *set);
 
 /* Returns -1 if set empty. */
-hb_codepoint_t
+HB_EXTERN hb_codepoint_t
 hb_set_get_min (const hb_set_t *set);
 
 /* Returns -1 if set empty. */
-hb_codepoint_t
+HB_EXTERN hb_codepoint_t
 hb_set_get_max (const hb_set_t *set);
 
 /* Pass -1 in to get started. */
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_set_next (const hb_set_t *set,
 	     hb_codepoint_t *codepoint);
 
 /* Pass -1 for first and last to get started. */
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_set_next_range (const hb_set_t *set,
 		   hb_codepoint_t *first,
 		   hb_codepoint_t *last);
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-shape-plan.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-shape-plan.h	2016-08-05 14:37:07.948011431 +0300
@@ -38,49 +38,49 @@
 
 typedef struct hb_shape_plan_t hb_shape_plan_t;
 
-hb_shape_plan_t *
+HB_EXTERN hb_shape_plan_t *
 hb_shape_plan_create (hb_face_t                     *face,
 		      const hb_segment_properties_t *props,
 		      const hb_feature_t            *user_features,
 		      unsigned int                   num_user_features,
 		      const char * const            *shaper_list);
 
-hb_shape_plan_t *
+HB_EXTERN hb_shape_plan_t *
 hb_shape_plan_create_cached (hb_face_t                     *face,
 			     const hb_segment_properties_t *props,
 			     const hb_feature_t            *user_features,
 			     unsigned int                   num_user_features,
 			     const char * const            *shaper_list);
 
-hb_shape_plan_t *
+HB_EXTERN hb_shape_plan_t *
 hb_shape_plan_get_empty (void);
 
-hb_shape_plan_t *
+HB_EXTERN hb_shape_plan_t *
 hb_shape_plan_reference (hb_shape_plan_t *shape_plan);
 
-void
+HB_EXTERN void
 hb_shape_plan_destroy (hb_shape_plan_t *shape_plan);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_shape_plan_set_user_data (hb_shape_plan_t    *shape_plan,
 			     hb_user_data_key_t *key,
 			     void *              data,
 			     hb_destroy_func_t   destroy,
 			     hb_bool_t           replace);
 
-void *
+HB_EXTERN void *
 hb_shape_plan_get_user_data (hb_shape_plan_t    *shape_plan,
 			     hb_user_data_key_t *key);
 
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_shape_plan_execute (hb_shape_plan_t    *shape_plan,
 		       hb_font_t          *font,
 		       hb_buffer_t        *buffer,
 		       const hb_feature_t *features,
 		       unsigned int        num_features);
 
-const char *
+HB_EXTERN const char *
 hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan);
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-shape.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-shape.cc	2016-08-05 14:37:07.949011423 +0300
@@ -210,13 +210,15 @@
 /**
  * hb_feature_from_string:
  * @str: (array length=len) (element-type uint8_t): a string to parse
- * @len: length of @str, or -1 if string is nul-terminated
+ * @len: length of @str, or -1 if string is %NULL terminated
  * @feature: (out): the #hb_feature_t to initialize with the parsed values
  *
- * Parses a string into a #hb_feature_t. If @len is -1 then @str is
- * %NULL-terminated.
+ * Parses a string into a #hb_feature_t.
  *
- * Return value: %TRUE if @str is successfully parsed, %FALSE otherwise
+ * TODO: document the syntax here.
+ *
+ * Return value:
+ * %true if @str is successfully parsed, %false otherwise.
  *
  * Since: 0.9.5
  **/
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-shape.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-shape.h	2016-08-05 14:37:07.949011423 +0300
@@ -47,29 +47,29 @@
   unsigned int  end;
 } hb_feature_t;
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_feature_from_string (const char *str, int len,
 			hb_feature_t *feature);
 
-void
+HB_EXTERN void
 hb_feature_to_string (hb_feature_t *feature,
 		      char *buf, unsigned int size);
 
 
-void
+HB_EXTERN void
 hb_shape (hb_font_t           *font,
 	  hb_buffer_t         *buffer,
 	  const hb_feature_t  *features,
 	  unsigned int         num_features);
 
-hb_bool_t
+HB_EXTERN 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);
 
-const char **
+HB_EXTERN const char **
 hb_shape_list_shapers (void);
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-shaper-list.hh.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-shaper-list.hh	2016-08-05 14:37:07.949011423 +0300
@@ -46,6 +46,9 @@
 #ifdef HAVE_UNISCRIBE
 HB_SHAPER_IMPLEMENT (uniscribe)
 #endif
+#ifdef HAVE_DIRECTWRITE
+HB_SHAPER_IMPLEMENT (directwrite)
+#endif
 #ifdef HAVE_CORETEXT
 HB_SHAPER_IMPLEMENT (coretext)
 #endif
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-unicode.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-unicode.h	2016-08-05 14:37:07.949011423 +0300
@@ -174,23 +174,23 @@
 /*
  * just give me the best implementation you've got there.
  */
-hb_unicode_funcs_t *
+HB_EXTERN hb_unicode_funcs_t *
 hb_unicode_funcs_get_default (void);
 
 
-hb_unicode_funcs_t *
+HB_EXTERN hb_unicode_funcs_t *
 hb_unicode_funcs_create (hb_unicode_funcs_t *parent);
 
-hb_unicode_funcs_t *
+HB_EXTERN hb_unicode_funcs_t *
 hb_unicode_funcs_get_empty (void);
 
-hb_unicode_funcs_t *
+HB_EXTERN hb_unicode_funcs_t *
 hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs);
 
-void
+HB_EXTERN void
 hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
 			        hb_user_data_key_t *key,
 			        void *              data,
@@ -198,18 +198,18 @@
 				hb_bool_t           replace);
 
 
-void *
+HB_EXTERN void *
 hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
 			        hb_user_data_key_t *key);
 
 
-void
+HB_EXTERN void
 hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs);
 
-hb_unicode_funcs_t *
+HB_EXTERN hb_unicode_funcs_t *
 hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs);
 
 
@@ -285,7 +285,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN 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);
@@ -301,7 +301,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN 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);
@@ -317,7 +317,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN 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);
@@ -333,7 +333,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN 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);
@@ -349,7 +349,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN 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);
@@ -365,7 +365,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN void
 hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t *ufuncs,
 				   hb_unicode_compose_func_t func,
 				   void *user_data, hb_destroy_func_t destroy);
@@ -381,7 +381,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN void
 hb_unicode_funcs_set_decompose_func (hb_unicode_funcs_t *ufuncs,
 				     hb_unicode_decompose_func_t func,
 				     void *user_data, hb_destroy_func_t destroy);
@@ -397,7 +397,7 @@
  *
  * Since: 0.9.2
  **/
-void
+HB_EXTERN void
 hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs,
 						   hb_unicode_decompose_compatibility_func_t func,
 						   void *user_data, hb_destroy_func_t destroy);
@@ -405,62 +405,78 @@
 /* accessors */
 
 /**
+ * hb_unicode_combining_class:
+ *
  * Since: 0.9.2
  **/
-hb_unicode_combining_class_t
+HB_EXTERN hb_unicode_combining_class_t
 hb_unicode_combining_class (hb_unicode_funcs_t *ufuncs,
 			    hb_codepoint_t unicode);
 
 /**
+ * hb_unicode_eastasian_width:
+ *
  * Since: 0.9.2
  **/
-unsigned int
+HB_EXTERN unsigned int
 hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs,
 			    hb_codepoint_t unicode);
 
 /**
+ * hb_unicode_general_category:
+ *
  * Since: 0.9.2
  **/
-hb_unicode_general_category_t
+HB_EXTERN hb_unicode_general_category_t
 hb_unicode_general_category (hb_unicode_funcs_t *ufuncs,
 			     hb_codepoint_t unicode);
 
 /**
+ * hb_unicode_mirroring:
+ *
  * Since: 0.9.2
  **/
-hb_codepoint_t
+HB_EXTERN hb_codepoint_t
 hb_unicode_mirroring (hb_unicode_funcs_t *ufuncs,
 		      hb_codepoint_t unicode);
 
 /**
+ * hb_unicode_script:
+ *
  * Since: 0.9.2
  **/
-hb_script_t
+HB_EXTERN hb_script_t
 hb_unicode_script (hb_unicode_funcs_t *ufuncs,
 		   hb_codepoint_t unicode);
 
 /**
+ * hb_unicode_compose:
+ *
  * Since: 0.9.2
  **/
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
 		    hb_codepoint_t      a,
 		    hb_codepoint_t      b,
 		    hb_codepoint_t     *ab);
 
 /**
+ * hb_unicode_decompose:
+ *
  * Since: 0.9.2
  **/
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
 		      hb_codepoint_t      ab,
 		      hb_codepoint_t     *a,
 		      hb_codepoint_t     *b);
 
 /**
+ * hb_unicode_decompose_compatibility:
+ *
  * Since: 0.9.2
  **/
-unsigned int
+HB_EXTERN unsigned int
 hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
 				    hb_codepoint_t      u,
 				    hb_codepoint_t     *decomposed);
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-uniscribe.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-uniscribe.cc	2016-08-05 14:37:07.949011423 +0300
@@ -919,7 +919,7 @@
 
     if (unlikely (items[i].a.fNoGlyphIndex))
       FAIL ("ScriptShapeOpenType() set fNoGlyphIndex");
-    if (unlikely (hr == E_OUTOFMEMORY))
+    if (unlikely (hr == E_OUTOFMEMORY || hr == E_NOT_SUFFICIENT_BUFFER))
     {
       if (unlikely (!buffer->ensure (buffer->allocated * 2)))
 	FAIL ("Buffer resize failed");
@@ -1019,7 +1019,7 @@
     hb_glyph_position_t *pos = &buffer->pos[i];
 
     /* TODO vertical */
-    pos->x_advance = x_mult * info->mask;
+    pos->x_advance = x_mult * (int32_t) info->mask;
     pos->x_offset = x_mult * (backward ? -info->var1.i32 : info->var1.i32);
     pos->y_offset = y_mult * info->var2.i32;
   }
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-uniscribe.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-uniscribe.h	2016-08-05 14:37:07.950011416 +0300
@@ -34,10 +34,10 @@
 HB_BEGIN_DECLS
 
 
-LOGFONTW *
+HB_EXTERN LOGFONTW *
 hb_uniscribe_font_get_logfontw (hb_font_t *font);
 
-HFONT
+HB_EXTERN HFONT
 hb_uniscribe_font_get_hfont (hb_font_t *font);
 
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-version.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-version.h	2016-08-05 14:37:07.950011416 +0300
@@ -38,24 +38,24 @@
 
 #define HB_VERSION_MAJOR 1
 #define HB_VERSION_MINOR 1
-#define HB_VERSION_MICRO 0
+#define HB_VERSION_MICRO 3
 
-#define HB_VERSION_STRING "1.1.0"
+#define HB_VERSION_STRING "1.1.3"
 
 #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_EXTERN void
 hb_version (unsigned int *major,
 	    unsigned int *minor,
 	    unsigned int *micro);
 
-const char *
+HB_EXTERN const char *
 hb_version_string (void);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_version_atleast (unsigned int major,
 		    unsigned int minor,
 		    unsigned int micro);
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb-version.h.in.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb-version.h.in	2016-08-05 14:37:07.950011416 +0300
@@ -47,15 +47,15 @@
 	 HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO)
 
 
-void
+HB_EXTERN void
 hb_version (unsigned int *major,
 	    unsigned int *minor,
 	    unsigned int *micro);
 
-const char *
+HB_EXTERN const char *
 hb_version_string (void);
 
-hb_bool_t
+HB_EXTERN hb_bool_t
 hb_version_atleast (unsigned int major,
 		    unsigned int minor,
 		    unsigned int micro);
--- firefox-45.3.0esr/gfx/harfbuzz/src/hb.h.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/hb.h	2016-08-05 14:37:07.950011416 +0300
@@ -28,6 +28,10 @@
 #define HB_H
 #define HB_H_IN
 
+#ifndef HB_EXTERN
+#define HB_EXTERN extern
+#endif
+
 #include "hb-blob.h"
 #include "hb-buffer.h"
 #include "hb-common.h"
--- firefox-45.3.0esr/gfx/harfbuzz/src/sample.py.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/sample.py	2016-08-05 14:37:07.950011416 +0300
@@ -33,6 +33,12 @@
 hb.ot_font_set_funcs (font)
 
 buf = hb.buffer_create ()
+class Debugger(object):
+	def message (self, buf, font, msg, data, _x_what_is_this):
+		print(msg)
+		return True
+debugger = Debugger()
+hb.buffer_set_message_func (buf, debugger.message, 1, 0)
 hb.buffer_add_utf8 (buf, text.encode('utf-8'), 0, -1)
 hb.buffer_guess_segment_properties (buf)
 
--- firefox-45.3.0esr/gfx/harfbuzz/src/test.cc.1228540	2016-05-12 20:09:51.000000000 +0300
+++ firefox-45.3.0esr/gfx/harfbuzz/src/test.cc	2016-08-05 14:37:07.950011416 +0300
@@ -120,7 +120,7 @@
 	    info->cluster,
 	    info->codepoint,
 	    pos->x_offset,
-	    pos->x_offset,
+	    pos->y_offset,
 	    pos->x_advance,
 	    pos->y_advance);