[HarfBuzz] harfbuzz: Branch 'master' - 9 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Sat Jan 20 02:10:23 UTC 2018


 .circleci/config.yml                       |    4 
 CMakeLists.txt                             |   46 +++++----
 configure.ac                               |    3 
 src/Makefile.am                            |   11 --
 src/check-defs.sh                          |   37 ++++---
 src/gen-def.py                             |   16 +++
 src/hb-aat-layout-common-private.hh        |   58 ++++++++++--
 src/hb-aat-layout-morx-table.hh            |  135 ++++++++++++++++++++++++-----
 src/hb-aat-layout-private.hh               |    2 
 src/hb-aat-layout.cc                       |   20 ++--
 src/hb-common.cc                           |    1 
 src/hb-ot-head-table.hh                    |   20 +---
 src/hb-ot-layout-gpos-table.hh             |   48 +++++-----
 src/hb-ot-layout-gsub-table.hh             |   24 ++---
 src/hb-ot-layout-gsubgpos-private.hh       |   58 ++++++------
 src/hb-ot-layout-private.hh                |    4 
 src/hb-ot-layout.cc                        |   16 +--
 src/hb-ot-post-table.hh                    |   10 +-
 src/hb-ot-shape-complex-arabic-fallback.hh |    2 
 src/hb-ot-shape-fallback.cc                |    4 
 src/hb-ot-shape.cc                         |    3 
 test/api/Makefile.am                       |    3 
 test/shaping/README.md                     |   11 +-
 test/shaping/record-test.sh                |   17 ++-
 24 files changed, 360 insertions(+), 193 deletions(-)

New commits:
commit e6f283ed7db6f8e2f8016dcbf07e589c40976aa6
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Jan 19 18:08:56 2018 -0800

    [aat] Implement LigatureSubtable
    
    We form the Zapfino ligature now. Yay! No further testing done.

diff --git a/src/hb-aat-layout-common-private.hh b/src/hb-aat-layout-common-private.hh
index 538615f7..d62bafc5 100644
--- a/src/hb-aat-layout-common-private.hh
+++ b/src/hb-aat-layout-common-private.hh
@@ -627,23 +627,26 @@ struct StateTableDriver
   inline void drive (context_t *c)
   {
     hb_glyph_info_t *info = buffer->info;
-    unsigned int count = buffer->len;
+
+    if (!c->in_place)
+      buffer->clear_output ();
+
     unsigned int state = 0;
     bool last_was_dont_advance = false;
-    for (buffer->idx = 0; buffer->idx <= count;)
+    for (buffer->idx = 0;;)
     {
       if (!state)
 	last_zero = buffer->idx;
 
-      unsigned int klass = buffer->idx < count ?
+      unsigned int klass = buffer->idx < buffer->len ?
 			   machine.get_class (info[buffer->idx].codepoint, num_glyphs) :
 			   0 /* End of text */;
       const Entry<EntryData> *entry = machine.get_entryZ (state, klass);
       if (unlikely (!entry))
 	break;
 
-      c->transition (this, entry);
-
+      if (unlikely (!c->transition (this, entry)))
+        break;
 
       if (entry->flags & context_t::DontAdvance)
       {
@@ -655,7 +658,7 @@ struct StateTableDriver
 	    dont_advance_set = hb_set_create ();
 	}
 
-	unsigned int key = info[buffer->idx].codepoint | (state << 16);
+	unsigned int key = info[buffer->idx].codepoint ^ (state << 16);
 	if (likely (!dont_advance_set->has (key)))
 	{
 	  dont_advance_set->add (key);
@@ -667,16 +670,20 @@ struct StateTableDriver
       else
         last_was_dont_advance = false;
 
+      state = entry->newState;
+
+      if (buffer->idx == buffer->len)
+        break;
+
       if (!last_was_dont_advance)
         buffer->next_glyph ();
-
-      state = entry->newState;
     }
 
     if (!c->in_place)
     {
-      for (buffer->idx = 0; buffer->idx <= count;)
+      for (; buffer->idx < buffer->len;)
         buffer->next_glyph ();
+      buffer->swap_buffers ();
     }
   }
 
diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index 5b3402be..4a997eec 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -61,7 +61,7 @@ struct RearrangementSubtable
 	start (0), end (0),
 	last_zero_before_start (0) {}
 
-    inline void transition (StateTableDriver<void> *driver,
+    inline bool transition (StateTableDriver<void> *driver,
 			    const Entry<void> *entry)
     {
       hb_buffer_t *buffer = driver->buffer;
@@ -138,6 +138,8 @@ struct RearrangementSubtable
 	  }
 	}
       }
+
+      return true;
     }
 
     public:
@@ -200,7 +202,7 @@ struct ContextualSubtable
 	last_zero_before_mark (0),
 	subs (table+table->substitutionTables) {}
 
-    inline void transition (StateTableDriver<EntryData> *driver,
+    inline bool transition (StateTableDriver<EntryData> *driver,
 			    const Entry<EntryData> *entry)
     {
       hb_buffer_t *buffer = driver->buffer;
@@ -235,6 +237,8 @@ struct ContextualSubtable
 	  ret = true;
 	}
       }
+
+      return true;
     }
 
     public:
@@ -309,28 +313,113 @@ struct LigatureSubtable
 					 * group. */
       Reserved		= 0x1FFF,	/* These bits are reserved and should be set to 0. */
     };
+    enum LigActionFlags {
+      LigActionLast	= 0x80000000,	/* This is the last action in the list. This also
+					 * implies storage. */
+      LigActionStore	= 0x40000000,	/* Store the ligature at the current cumulated index
+					 * in the ligature table in place of the marked
+					 * (i.e. currently-popped) glyph. */
+      LigActionOffset	= 0x3FFFFFFF,	/* A 30-bit value which is sign-extended to 32-bits
+					 * and added to the glyph ID, resulting in an index
+					 * into the component table. */
+    };
 
-    inline driver_context_t (const LigatureSubtable *table) :
-	ret (false) {}
+    inline driver_context_t (const LigatureSubtable *table,
+			     hb_aat_apply_context_t *c_) :
+	ret (false),
+	c (c_),
+	ligAction (table+table->ligAction),
+	component (table+table->component),
+	ligature (table+table->ligature),
+	match_length (0) {}
 
-    inline void transition (StateTableDriver<EntryData> *driver,
+    inline bool transition (StateTableDriver<EntryData> *driver,
 			    const Entry<EntryData> *entry)
     {
       hb_buffer_t *buffer = driver->buffer;
+      unsigned int flags = entry->flags;
+
+      if (flags & SetComponent)
+      {
+        if (unlikely (match_length >= ARRAY_LENGTH (match_positions)))
+	  return false;
+
+	/* Never mark same index twice, in case DontAdvance was used... */
+	if (match_length && match_positions[match_length - 1] == buffer->out_len)
+	  match_length--;
+
+	match_positions[match_length++] = buffer->out_len;
+      }
+
+      if (flags & PerformAction)
+      {
+	unsigned int end = buffer->out_len;
+	unsigned int action_idx = entry->data.ligActionIndex;
+	unsigned int action;
+	unsigned int ligature_idx = 0;
+        do
+	{
+	  if (unlikely (!match_length))
+	    return false;
+
+	  buffer->move_to (match_positions[match_length - 1]);
 
-      /* TODO */
+	  const HBUINT32 &actionData = ligAction[action_idx];
+	  if (unlikely (!actionData.sanitize (&c->sanitizer))) return false;
+	  action = actionData;
+
+	  uint32_t uoffset = action & LigActionOffset;
+	  if (uoffset & 0x20000000)
+	    uoffset += 0xC0000000;
+	  int32_t offset = (int32_t) uoffset;
+	  unsigned int component_idx = buffer->cur().codepoint + offset;
+
+	  const HBUINT16 &componentData = component[component_idx];
+	  if (unlikely (!componentData.sanitize (&c->sanitizer))) return false;
+	  ligature_idx += componentData;
+
+	  if (action & (LigActionStore | LigActionLast))
+	  {
+	    const GlyphID &ligatureData = ligature[ligature_idx];
+	    if (unlikely (!ligatureData.sanitize (&c->sanitizer))) return false;
+	    hb_codepoint_t lig = ligatureData;
+
+	    buffer->replace_glyph (lig);
+
+	    //ligature_idx = 0; // XXX Yes or no?
+	  }
+	  else
+	  {
+	    buffer->skip_glyph ();
+	    end--;
+	  }
+
+	  match_length--;
+	  action_idx++;
+	}
+	while (!(action & LigActionLast));
+	buffer->move_to (end);
+      }
+
+      return true;
     }
 
     public:
     bool ret;
     private:
+    hb_aat_apply_context_t *c;
+    const UnsizedArrayOf<HBUINT32> &ligAction;
+    const UnsizedArrayOf<HBUINT16> &component;
+    const UnsizedArrayOf<GlyphID> &ligature;
+    unsigned int match_length;
+    unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
   };
 
   inline bool apply (hb_aat_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
-    driver_context_t dc (this);
+    driver_context_t dc (this, c);
 
     StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
     driver.drive (&dc);
@@ -341,8 +430,9 @@ struct LigatureSubtable
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    /* The main sanitization is done at run-time. */
-    return machine.sanitize (c);
+    /* The rest of array sanitizations are done at run-time. */
+    return c->check_struct (this) && machine.sanitize (c) &&
+	   ligAction && component && ligature;
     return_trace (true);
   }
 
commit f07ce661a2056965c573c99bdb721c065563ea7b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Jan 19 16:52:01 2018 -0800

    [aat] Embed a sanitizer context in hb_aat_apply_context_t
    
    For run-time checking.

diff --git a/src/hb-aat-layout-common-private.hh b/src/hb-aat-layout-common-private.hh
index b1165e9b..538615f7 100644
--- a/src/hb-aat-layout-common-private.hh
+++ b/src/hb-aat-layout-common-private.hh
@@ -704,13 +704,23 @@ struct hb_aat_apply_context_t :
   hb_font_t *font;
   hb_face_t *face;
   hb_buffer_t *buffer;
-  const char *end;
+  hb_sanitize_context_t sanitizer;
 
-  hb_aat_apply_context_t (hb_font_t *font_,
-			  hb_buffer_t *buffer_,
-			  const char *end_) :
-			font (font_), face (font->face), buffer (buffer_),
-			end (end_) {}
+  inline hb_aat_apply_context_t (hb_font_t *font_,
+				 hb_buffer_t *buffer_,
+				 hb_blob_t *table) :
+		font (font_), face (font->face), buffer (buffer_),
+		sanitizer ()
+  {
+    sanitizer.init (table);
+    sanitizer.num_glyphs = face->get_num_glyphs ();
+    sanitizer.start_processing ();
+  }
+
+  inline ~hb_aat_apply_context_t (void)
+  {
+    sanitizer.end_processing ();
+  }
 };
 
 
diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc
index 465aec64..d882fa16 100644
--- a/src/hb-aat-layout.cc
+++ b/src/hb-aat-layout.cc
@@ -37,19 +37,19 @@
  */
 
 static inline const AAT::morx&
-_get_morx (hb_face_t *face, unsigned int *length = nullptr)
+_get_morx (hb_face_t *face, hb_blob_t **blob = nullptr)
 {
   if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
   {
-    if (length)
-      *length = 0;
+    if (blob)
+      *blob = hb_blob_get_empty ();
     return OT::Null(AAT::morx);
   }
   hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
   /* XXX this doesn't call set_num_glyphs on sanitizer. */
   const AAT::morx& morx = *(layout->morx.get ());
-  if (length)
-    *length = hb_blob_get_length (layout->morx.blob);
+  if (blob)
+    *blob = layout->morx.blob;
   return morx;
 }
 
@@ -70,9 +70,9 @@ _hb_aat_layout_create (hb_face_t *face)
 void
 hb_aat_layout_substitute (hb_font_t *font, hb_buffer_t *buffer)
 {
-  unsigned int length;
-  const AAT::morx& morx = _get_morx (font->face, &length);
+  hb_blob_t *blob;
+  const AAT::morx& morx = _get_morx (font->face, &blob);
 
-  AAT::hb_aat_apply_context_t c (font, buffer, (const char *) &morx + length);
+  AAT::hb_aat_apply_context_t c (font, buffer, blob);
   morx.apply (&c);
 }
commit 046690a4df0fdc93e3490210ef105f26057b1462
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Jan 17 16:59:55 2018 -0800

    [aat] Add hb_aat_apply_context_t

diff --git a/src/hb-aat-layout-common-private.hh b/src/hb-aat-layout-common-private.hh
index c93661c3..b1165e9b 100644
--- a/src/hb-aat-layout-common-private.hh
+++ b/src/hb-aat-layout-common-private.hh
@@ -691,6 +691,29 @@ struct StateTableDriver
 };
 
 
+
+struct hb_aat_apply_context_t :
+       hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
+{
+  inline const char *get_name (void) { return "APPLY"; }
+  template <typename T>
+  inline return_t dispatch (const T &obj) { return obj.apply (this); }
+  static return_t default_return_value (void) { return false; }
+  bool stop_sublookup_iteration (return_t r) const { return r; }
+
+  hb_font_t *font;
+  hb_face_t *face;
+  hb_buffer_t *buffer;
+  const char *end;
+
+  hb_aat_apply_context_t (hb_font_t *font_,
+			  hb_buffer_t *buffer_,
+			  const char *end_) :
+			font (font_), face (font->face), buffer (buffer_),
+			end (end_) {}
+};
+
+
 } /* namespace AAT */
 
 
diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index 419185c5..5b3402be 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -148,7 +148,7 @@ struct RearrangementSubtable
     unsigned int last_zero_before_start;
   };
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  inline bool apply (hb_aat_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
@@ -245,7 +245,7 @@ struct ContextualSubtable
     const UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT32> &subs;
   };
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  inline bool apply (hb_aat_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
@@ -326,7 +326,7 @@ struct LigatureSubtable
     private:
   };
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  inline bool apply (hb_aat_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
@@ -360,7 +360,7 @@ struct LigatureSubtable
 
 struct NoncontextualSubtable
 {
-  inline bool apply (hb_ot_apply_context_t *c) const
+  inline bool apply (hb_aat_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
@@ -396,7 +396,7 @@ struct NoncontextualSubtable
 
 struct InsertionSubtable
 {
-  inline bool apply (hb_ot_apply_context_t *c) const
+  inline bool apply (hb_aat_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     /* TODO */
@@ -448,13 +448,13 @@ struct ChainSubtable
     Insertion		= 5
   };
 
-  inline void apply (hb_ot_apply_context_t *c, const char *end) const
+  inline void apply (hb_aat_apply_context_t *c) const
   {
-    dispatch (c, end);
+    dispatch (c);
   }
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c, const char *end) const
+  inline typename context_t::return_t dispatch (context_t *c) const
   {
     unsigned int subtable_type = get_type ();
     TRACE_DISPATCH (this, subtable_type);
@@ -476,7 +476,7 @@ struct ChainSubtable
 	!c->check_range (this, length))
       return_trace (false);
 
-    return_trace (dispatch (c, c->end));
+    return_trace (dispatch (c));
   }
 
   protected:
@@ -496,13 +496,13 @@ struct ChainSubtable
 
 struct Chain
 {
-  inline void apply (hb_ot_apply_context_t *c, const char *end) const
+  inline void apply (hb_aat_apply_context_t *c) const
   {
     const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (featureZ, featureZ[0].static_size * featureCount);
     unsigned int count = subtableCount;
     for (unsigned int i = 0; i < count; i++)
     {
-      subtable->apply (c, end);
+      subtable->apply (c);
       subtable = &StructAfter<ChainSubtable> (*subtable);
     }
   }
@@ -555,14 +555,13 @@ struct morx
 {
   static const hb_tag_t tableTag = HB_AAT_TAG_MORX;
 
-  inline void apply (hb_ot_apply_context_t *c, unsigned int length) const
+  inline void apply (hb_aat_apply_context_t *c) const
   {
-    const char *end = (const char *) this + length;
     const Chain *chain = chains;
     unsigned int count = chainCount;
     for (unsigned int i = 0; i < count; i++)
     {
-      chain->apply (c, end);
+      chain->apply (c);
       chain = &StructAfter<Chain> (*chain);
     }
   }
diff --git a/src/hb-aat-layout-private.hh b/src/hb-aat-layout-private.hh
index ebddf3b4..c1c607a2 100644
--- a/src/hb-aat-layout-private.hh
+++ b/src/hb-aat-layout-private.hh
@@ -35,6 +35,6 @@
 
 
 HB_INTERNAL void
-hb_aat_layout_substitute (OT::hb_ot_apply_context_t *c);
+hb_aat_layout_substitute (hb_font_t *font, hb_buffer_t *buffer);
 
 #endif /* HB_AAT_LAYOUT_PRIVATE_HH */
diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc
index 94e1442d..465aec64 100644
--- a/src/hb-aat-layout.cc
+++ b/src/hb-aat-layout.cc
@@ -68,9 +68,11 @@ _hb_aat_layout_create (hb_face_t *face)
 }
 
 void
-hb_aat_layout_substitute (OT::hb_ot_apply_context_t *c)
+hb_aat_layout_substitute (hb_font_t *font, hb_buffer_t *buffer)
 {
   unsigned int length;
-  const AAT::morx& morx = _get_morx (c->face, &length);
-  morx.apply (c, length);
+  const AAT::morx& morx = _get_morx (font->face, &length);
+
+  AAT::hb_aat_apply_context_t c (font, buffer, (const char *) &morx + length);
+  morx.apply (&c);
 }
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 3076586d..fc5dd108 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -619,8 +619,7 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c)
   c->plan->substitute (c->font, buffer);
 
   /* XXX Call morx instead. */
-  //OT::hb_ot_apply_context_t ac (0, c->font, c->buffer);
-  //hb_aat_layout_substitute (&ac);
+  //hb_aat_layout_substitute (c->font, c->buffer);
 }
 
 static inline void
commit fd034490942c06e31cfb42f32023c78734f8aeeb
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Jan 17 16:46:51 2018 -0800

    Rename hb_apply_context_t to hb_ot_apply_context_t

diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index 766292b3..419185c5 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -148,7 +148,7 @@ struct RearrangementSubtable
     unsigned int last_zero_before_start;
   };
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
@@ -245,7 +245,7 @@ struct ContextualSubtable
     const UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT32> &subs;
   };
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
@@ -326,7 +326,7 @@ struct LigatureSubtable
     private:
   };
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
@@ -360,7 +360,7 @@ struct LigatureSubtable
 
 struct NoncontextualSubtable
 {
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
@@ -396,7 +396,7 @@ struct NoncontextualSubtable
 
 struct InsertionSubtable
 {
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     /* TODO */
@@ -448,7 +448,7 @@ struct ChainSubtable
     Insertion		= 5
   };
 
-  inline void apply (hb_apply_context_t *c, const char *end) const
+  inline void apply (hb_ot_apply_context_t *c, const char *end) const
   {
     dispatch (c, end);
   }
@@ -496,7 +496,7 @@ struct ChainSubtable
 
 struct Chain
 {
-  inline void apply (hb_apply_context_t *c, const char *end) const
+  inline void apply (hb_ot_apply_context_t *c, const char *end) const
   {
     const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (featureZ, featureZ[0].static_size * featureCount);
     unsigned int count = subtableCount;
@@ -555,7 +555,7 @@ struct morx
 {
   static const hb_tag_t tableTag = HB_AAT_TAG_MORX;
 
-  inline void apply (hb_apply_context_t *c, unsigned int length) const
+  inline void apply (hb_ot_apply_context_t *c, unsigned int length) const
   {
     const char *end = (const char *) this + length;
     const Chain *chain = chains;
diff --git a/src/hb-aat-layout-private.hh b/src/hb-aat-layout-private.hh
index eb2cdd1c..ebddf3b4 100644
--- a/src/hb-aat-layout-private.hh
+++ b/src/hb-aat-layout-private.hh
@@ -35,6 +35,6 @@
 
 
 HB_INTERNAL void
-hb_aat_layout_substitute (OT::hb_apply_context_t *c);
+hb_aat_layout_substitute (OT::hb_ot_apply_context_t *c);
 
 #endif /* HB_AAT_LAYOUT_PRIVATE_HH */
diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc
index 7455787f..94e1442d 100644
--- a/src/hb-aat-layout.cc
+++ b/src/hb-aat-layout.cc
@@ -68,7 +68,7 @@ _hb_aat_layout_create (hb_face_t *face)
 }
 
 void
-hb_aat_layout_substitute (OT::hb_apply_context_t *c)
+hb_aat_layout_substitute (OT::hb_ot_apply_context_t *c)
 {
   unsigned int length;
   const AAT::morx& morx = _get_morx (c->face, &length);
diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index 836a2e24..3ef3d30b 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -103,7 +103,7 @@ struct ValueFormat : HBUINT16
   inline unsigned int get_size (void) const
   { return get_len () * Value::static_size; }
 
-  void apply_value (hb_apply_context_t   *c,
+  void apply_value (hb_ot_apply_context_t   *c,
 		    const void           *base,
 		    const Value          *values,
 		    hb_glyph_position_t  &glyph_pos) const
@@ -232,7 +232,7 @@ struct ValueFormat : HBUINT16
 
 struct AnchorFormat1
 {
-  inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
 			  float *x, float *y) const
   {
     hb_font_t *font = c->font;
@@ -256,7 +256,7 @@ struct AnchorFormat1
 
 struct AnchorFormat2
 {
-  inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id,
+  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
 			  float *x, float *y) const
   {
     hb_font_t *font = c->font;
@@ -288,7 +288,7 @@ struct AnchorFormat2
 
 struct AnchorFormat3
 {
-  inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
 			  float *x, float *y) const
   {
     hb_font_t *font = c->font;
@@ -325,7 +325,7 @@ struct AnchorFormat3
 
 struct Anchor
 {
-  inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id,
+  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
 			  float *x, float *y) const
   {
     *x = *y = 0;
@@ -413,7 +413,7 @@ struct MarkRecord
 
 struct MarkArray : ArrayOf<MarkRecord>	/* Array of MarkRecords--in Coverage order */
 {
-  inline bool apply (hb_apply_context_t *c,
+  inline bool apply (hb_ot_apply_context_t *c,
 		     unsigned int mark_index, unsigned int glyph_index,
 		     const AnchorMatrix &anchors, unsigned int class_count,
 		     unsigned int glyph_pos) const
@@ -470,7 +470,7 @@ struct SinglePosFormat1
     return this+coverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -518,7 +518,7 @@ struct SinglePosFormat2
     return this+coverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -610,7 +610,7 @@ struct PairSet
     c->input->add_array (&record->secondGlyph, len, record_size);
   }
 
-  inline bool apply (hb_apply_context_t *c,
+  inline bool apply (hb_ot_apply_context_t *c,
 		     const ValueFormat *valueFormats,
 		     unsigned int pos) const
   {
@@ -695,14 +695,14 @@ struct PairPosFormat1
     return this+coverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
-    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
     if (!skippy_iter.next ()) return_trace (false);
 
@@ -759,14 +759,14 @@ struct PairPosFormat2
     return this+coverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
-    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
     if (!skippy_iter.next ()) return_trace (false);
 
@@ -900,7 +900,7 @@ struct CursivePosFormat1
     return this+coverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -908,7 +908,7 @@ struct CursivePosFormat1
     const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage  (buffer->cur().codepoint)];
     if (!this_record.exitAnchor) return_trace (false);
 
-    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
     if (!skippy_iter.next ()) return_trace (false);
 
@@ -1059,7 +1059,7 @@ struct MarkBasePosFormat1
     return this+markCoverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -1067,7 +1067,7 @@ struct MarkBasePosFormat1
     if (likely (mark_index == NOT_COVERED)) return_trace (false);
 
     /* Now we search backwards for a non-mark glyph */
-    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
     skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
     do {
@@ -1162,7 +1162,7 @@ struct MarkLigPosFormat1
     return this+markCoverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -1170,7 +1170,7 @@ struct MarkLigPosFormat1
     if (likely (mark_index == NOT_COVERED)) return_trace (false);
 
     /* Now we search backwards for a non-mark glyph */
-    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
     skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
     if (!skippy_iter.prev ()) return_trace (false);
@@ -1275,7 +1275,7 @@ struct MarkMarkPosFormat1
     return this+mark1Coverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -1283,7 +1283,7 @@ struct MarkMarkPosFormat1
     if (likely (mark1_index == NOT_COVERED)) return_trace (false);
 
     /* now we search backwards for a suitable mark glyph until a non-mark glyph */
-    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
     skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags);
     if (!skippy_iter.prev ()) return_trace (false);
@@ -1450,7 +1450,7 @@ struct PosLookup : Lookup
     return false;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     return_trace (dispatch (c));
@@ -1469,7 +1469,7 @@ struct PosLookup : Lookup
     dispatch (&c);
   }
 
-  static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index);
+  static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
 
   template <typename context_t>
   static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
@@ -1621,7 +1621,7 @@ template <typename context_t>
   return l.dispatch (c);
 }
 
-/*static*/ inline bool PosLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index)
+/*static*/ inline bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
 {
   const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
   const PosLookup &l = gpos.get_lookup (lookup_index);
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index f483d752..263e0a6e 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -76,7 +76,7 @@ struct SingleSubstFormat1
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
@@ -161,7 +161,7 @@ struct SingleSubstFormat2
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
@@ -272,7 +272,7 @@ struct Sequence
     c->output->add_array (substitute.array, substitute.len);
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int count = substitute.len;
@@ -363,7 +363,7 @@ struct MultipleSubstFormat1
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
@@ -495,7 +495,7 @@ struct AlternateSubstFormat1
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
@@ -628,7 +628,7 @@ struct Ligature
     return_trace (true);
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int count = component.len;
@@ -730,7 +730,7 @@ struct LigatureSet
     return_trace (false);
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int num_ligs = ligature.len;
@@ -821,7 +821,7 @@ struct LigatureSubstFormat1
     return_trace (lig_set.would_apply (c));
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
@@ -993,7 +993,7 @@ struct ReverseChainSingleSubstFormat1
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
@@ -1150,7 +1150,7 @@ struct SubstLookup : Lookup
     return lookup_type_is_reverse (type);
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     return_trace (dispatch (c));
@@ -1186,7 +1186,7 @@ struct SubstLookup : Lookup
       return_trace (dispatch (c));
   }
 
-  static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index);
+  static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
 
   inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c,
 						  unsigned int i)
@@ -1343,7 +1343,7 @@ template <typename context_t>
   return l.dispatch (c);
 }
 
-/*static*/ inline bool SubstLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index)
+/*static*/ inline bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
 {
   const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
   const SubstLookup &l = gsub.get_lookup (lookup_index);
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index a5cb105c..4f56dbab 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -218,8 +218,8 @@ struct hb_add_coverage_context_t :
 };
 
 
-struct hb_apply_context_t :
-       hb_dispatch_context_t<hb_apply_context_t, bool, HB_DEBUG_APPLY>
+struct hb_ot_apply_context_t :
+       hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
 {
   struct matcher_t
   {
@@ -271,7 +271,7 @@ struct hb_apply_context_t :
     };
 
     inline may_skip_t
-    may_skip (const hb_apply_context_t *c,
+    may_skip (const hb_ot_apply_context_t *c,
 	      const hb_glyph_info_t    &info) const
     {
       if (!c->check_glyph_property (&info, lookup_props))
@@ -297,7 +297,7 @@ struct hb_apply_context_t :
 
   struct skipping_iterator_t
   {
-    inline void init (hb_apply_context_t *c_, bool context_match = false)
+    inline void init (hb_ot_apply_context_t *c_, bool context_match = false)
     {
       c = c_;
       match_glyph_data = nullptr;
@@ -333,7 +333,7 @@ struct hb_apply_context_t :
     inline void reject (void) { num_items++; match_glyph_data--; }
 
     inline matcher_t::may_skip_t
-    may_skip (const hb_apply_context_t *c,
+    may_skip (const hb_ot_apply_context_t *c,
 	      const hb_glyph_info_t    &info) const
     {
       return matcher.may_skip (c, info);
@@ -396,7 +396,7 @@ struct hb_apply_context_t :
 
     unsigned int idx;
     protected:
-    hb_apply_context_t *c;
+    hb_ot_apply_context_t *c;
     matcher_t matcher;
     const HBUINT16 *match_glyph_data;
 
@@ -406,7 +406,7 @@ struct hb_apply_context_t :
 
 
   inline const char *get_name (void) { return "APPLY"; }
-  typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
+  typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index);
   template <typename T>
   inline return_t dispatch (const T &obj) { return obj.apply (this); }
   static return_t default_return_value (void) { return false; }
@@ -444,7 +444,7 @@ struct hb_apply_context_t :
   bool has_glyph_classes;
 
 
-  hb_apply_context_t (unsigned int table_index_,
+  hb_ot_apply_context_t (unsigned int table_index_,
 		      hb_font_t *font_,
 		      hb_buffer_t *buffer_) :
 			iter_input (), iter_context (),
@@ -670,7 +670,7 @@ static inline bool would_match_input (hb_would_apply_context_t *c,
 
   return true;
 }
-static inline bool match_input (hb_apply_context_t *c,
+static inline bool match_input (hb_ot_apply_context_t *c,
 				unsigned int count, /* Including the first glyph (not matched) */
 				const HBUINT16 input[], /* Array of input values--start with second glyph */
 				match_func_t match_func,
@@ -686,7 +686,7 @@ static inline bool match_input (hb_apply_context_t *c,
 
   hb_buffer_t *buffer = c->buffer;
 
-  hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
   skippy_iter.reset (buffer->idx, count - 1);
   skippy_iter.set_match_func (match_func, match_data, input);
 
@@ -763,7 +763,7 @@ static inline bool match_input (hb_apply_context_t *c,
 	    j--;
 	  }
 
-	  if (found && skippy_iter.may_skip (c, out[j]) == hb_apply_context_t::matcher_t::SKIP_YES)
+	  if (found && skippy_iter.may_skip (c, out[j]) == hb_ot_apply_context_t::matcher_t::SKIP_YES)
 	    ligbase = LIGBASE_MAY_SKIP;
 	  else
 	    ligbase = LIGBASE_MAY_NOT_SKIP;
@@ -796,7 +796,7 @@ static inline bool match_input (hb_apply_context_t *c,
 
   return_trace (true);
 }
-static inline bool ligate_input (hb_apply_context_t *c,
+static inline bool ligate_input (hb_ot_apply_context_t *c,
 				 unsigned int count, /* Including the first glyph */
 				 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
 				 unsigned int match_length,
@@ -894,7 +894,7 @@ static inline bool ligate_input (hb_apply_context_t *c,
   return_trace (true);
 }
 
-static inline bool match_backtrack (hb_apply_context_t *c,
+static inline bool match_backtrack (hb_ot_apply_context_t *c,
 				    unsigned int count,
 				    const HBUINT16 backtrack[],
 				    match_func_t match_func,
@@ -903,7 +903,7 @@ static inline bool match_backtrack (hb_apply_context_t *c,
 {
   TRACE_APPLY (nullptr);
 
-  hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
+  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
   skippy_iter.reset (c->buffer->backtrack_len (), count);
   skippy_iter.set_match_func (match_func, match_data, backtrack);
 
@@ -916,7 +916,7 @@ static inline bool match_backtrack (hb_apply_context_t *c,
   return_trace (true);
 }
 
-static inline bool match_lookahead (hb_apply_context_t *c,
+static inline bool match_lookahead (hb_ot_apply_context_t *c,
 				    unsigned int count,
 				    const HBUINT16 lookahead[],
 				    match_func_t match_func,
@@ -926,7 +926,7 @@ static inline bool match_lookahead (hb_apply_context_t *c,
 {
   TRACE_APPLY (nullptr);
 
-  hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
+  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
   skippy_iter.reset (c->buffer->idx + offset - 1, count);
   skippy_iter.set_match_func (match_func, match_data, lookahead);
 
@@ -967,7 +967,7 @@ static inline void recurse_lookups (context_t *c,
     c->recurse (lookupRecord[i].lookupListIndex);
 }
 
-static inline bool apply_lookup (hb_apply_context_t *c,
+static inline bool apply_lookup (hb_ot_apply_context_t *c,
 				 unsigned int count, /* Including the first glyph */
 				 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
 				 unsigned int lookupCount,
@@ -1149,7 +1149,7 @@ static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
 			    inputCount, input,
 			    lookup_context.funcs.match, lookup_context.match_data);
 }
-static inline bool context_apply_lookup (hb_apply_context_t *c,
+static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
 					 unsigned int inputCount, /* Including the first glyph (not matched) */
 					 const HBUINT16 input[], /* Array of input values--start with second glyph */
 					 unsigned int lookupCount,
@@ -1198,7 +1198,7 @@ struct Rule
     return_trace (context_would_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
   }
 
-  inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
+  inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
   {
     TRACE_APPLY (this);
     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
@@ -1259,7 +1259,7 @@ struct RuleSet
     return_trace (false);
   }
 
-  inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
+  inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
   {
     TRACE_APPLY (this);
     unsigned int num_rules = rule.len;
@@ -1339,7 +1339,7 @@ struct ContextFormat1
     return this+coverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
@@ -1431,7 +1431,7 @@ struct ContextFormat2
     return this+coverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
@@ -1522,7 +1522,7 @@ struct ContextFormat3
     return this+coverageZ[0];
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
@@ -1673,7 +1673,7 @@ static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c
 			    lookup_context.funcs.match, lookup_context.match_data[1]);
 }
 
-static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
+static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
 					       unsigned int backtrackCount,
 					       const HBUINT16 backtrack[],
 					       unsigned int inputCount, /* Including the first glyph (not matched) */
@@ -1748,7 +1748,7 @@ struct ChainRule
 						    lookup.array, lookup_context));
   }
 
-  inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+  inline bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
   {
     TRACE_APPLY (this);
     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
@@ -1820,7 +1820,7 @@ struct ChainRuleSet
     return_trace (false);
   }
 
-  inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+  inline bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
   {
     TRACE_APPLY (this);
     unsigned int num_rules = rule.len;
@@ -1897,7 +1897,7 @@ struct ChainContextFormat1
     return this+coverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
@@ -2001,7 +2001,7 @@ struct ChainContextFormat2
     return this+coverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
@@ -2125,7 +2125,7 @@ struct ChainContextFormat3
     return this+input[0];
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index 39d1a672..60119629 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -90,12 +90,12 @@ hb_ot_layout_substitute_start (hb_font_t    *font,
 struct hb_ot_layout_lookup_accelerator_t;
 
 namespace OT {
-  struct hb_apply_context_t;
+  struct hb_ot_apply_context_t;
   struct SubstLookup;
 }
 
 HB_INTERNAL void
-hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
+hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
 				const OT::SubstLookup &lookup,
 				const hb_ot_layout_lookup_accelerator_t &accel);
 
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 14b64359..919ecbb4 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1057,13 +1057,13 @@ struct hb_get_subtables_context_t :
        OT::hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
 {
   template <typename Type>
-  static inline bool apply_to (const void *obj, OT::hb_apply_context_t *c)
+  static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
   {
     const Type *typed_obj = (const Type *) obj;
     return typed_obj->apply (c);
   }
 
-  typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_apply_context_t *c);
+  typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c);
 
   struct hb_applicable_t
   {
@@ -1073,7 +1073,7 @@ struct hb_get_subtables_context_t :
       apply_func = apply_func_;
     }
 
-    inline bool apply (OT::hb_apply_context_t *c) const { return apply_func (obj, c); }
+    inline bool apply (OT::hb_ot_apply_context_t *c) const { return apply_func (obj, c); }
 
     private:
     const void *obj;
@@ -1104,7 +1104,7 @@ struct hb_get_subtables_context_t :
 };
 
 static inline bool
-apply_forward (OT::hb_apply_context_t *c,
+apply_forward (OT::hb_ot_apply_context_t *c,
 	       const hb_ot_layout_lookup_accelerator_t &accel,
 	       const hb_get_subtables_context_t::array_t &subtables)
 {
@@ -1134,7 +1134,7 @@ apply_forward (OT::hb_apply_context_t *c,
 }
 
 static inline bool
-apply_backward (OT::hb_apply_context_t *c,
+apply_backward (OT::hb_ot_apply_context_t *c,
 	       const hb_ot_layout_lookup_accelerator_t &accel,
 	       const hb_get_subtables_context_t::array_t &subtables)
 {
@@ -1163,7 +1163,7 @@ apply_backward (OT::hb_apply_context_t *c,
 
 template <typename Proxy>
 static inline void
-apply_string (OT::hb_apply_context_t *c,
+apply_string (OT::hb_ot_apply_context_t *c,
 	      const typename Proxy::Lookup &lookup,
 	      const hb_ot_layout_lookup_accelerator_t &accel)
 {
@@ -1214,7 +1214,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
 {
   const unsigned int table_index = proxy.table_index;
   unsigned int i = 0;
-  OT::hb_apply_context_t c (table_index, font, buffer);
+  OT::hb_ot_apply_context_t c (table_index, font, buffer);
   c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
 
   for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) {
@@ -1254,7 +1254,7 @@ void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_
 }
 
 HB_INTERNAL void
-hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
+hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
 				const OT::SubstLookup &lookup,
 				const hb_ot_layout_lookup_accelerator_t &accel)
 {
diff --git a/src/hb-ot-shape-complex-arabic-fallback.hh b/src/hb-ot-shape-complex-arabic-fallback.hh
index d98cde12..5a257f04 100644
--- a/src/hb-ot-shape-complex-arabic-fallback.hh
+++ b/src/hb-ot-shape-complex-arabic-fallback.hh
@@ -340,7 +340,7 @@ arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan,
 			    hb_font_t *font,
 			    hb_buffer_t *buffer)
 {
-  OT::hb_apply_context_t c (0, font, buffer);
+  OT::hb_ot_apply_context_t c (0, font, buffer);
   for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
     if (fallback_plan->lookup_array[i]) {
       c.set_lookup_mask (fallback_plan->mask_array[i]);
diff --git a/src/hb-ot-shape-fallback.cc b/src/hb-ot-shape-fallback.cc
index 695f6b06..6b228790 100644
--- a/src/hb-ot-shape-fallback.cc
+++ b/src/hb-ot-shape-fallback.cc
@@ -442,10 +442,10 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
 {
   if (!plan->has_kern) return;
 
-  OT::hb_apply_context_t c (1, font, buffer);
+  OT::hb_ot_apply_context_t c (1, font, buffer);
   c.set_lookup_mask (plan->kern_mask);
   c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
-  OT::hb_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
+  OT::hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
   skippy_iter.init (&c);
 
   unsigned int count = buffer->len;
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 64e118a7..3076586d 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -619,7 +619,7 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c)
   c->plan->substitute (c->font, buffer);
 
   /* XXX Call morx instead. */
-  //OT::hb_apply_context_t ac (0, c->font, c->buffer);
+  //OT::hb_ot_apply_context_t ac (0, c->font, c->buffer);
   //hb_aat_layout_substitute (&ac);
 }
 
commit 94b49beee972fec98cbb80658df3d8491b45485d
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Jan 17 12:46:08 2018 -0800

    Whitespace

diff --git a/src/hb-ot-head-table.hh b/src/hb-ot-head-table.hh
index 98510985..2024cea7 100644
--- a/src/hb-ot-head-table.hh
+++ b/src/hb-ot-head-table.hh
@@ -64,10 +64,10 @@ struct head
   FixedVersion<>version;		/* Version of the head table--currently
 					 * 0x00010000u for version 1.0. */
   FixedVersion<>fontRevision;		/* Set by font manufacturer. */
-  HBUINT32		checkSumAdjustment;	/* To compute: set it to 0, sum the
+  HBUINT32	checkSumAdjustment;	/* To compute: set it to 0, sum the
 					 * entire font as HBUINT32, then store
 					 * 0xB1B0AFBAu - sum. */
-  HBUINT32		magicNumber;		/* Set to 0x5F0F3CF5u. */
+  HBUINT32	magicNumber;		/* Set to 0x5F0F3CF5u. */
   HBUINT16	flags;			/* Bit 0: Baseline for font at y=0;
 					 * Bit 1: Left sidebearing point at x=0;
 					 * Bit 2: Instructions may depend on point size;
@@ -76,7 +76,6 @@ struct head
 					 *   ppem sizes if this bit is clear;
 					 * Bit 4: Instructions may alter advance width
 					 *   (the advance widths might not scale linearly);
-
 					 * Bits 5-10: These should be set according to
 					 *   Apple's specification. However, they are not
 					 *   implemented in OpenType.
@@ -96,7 +95,6 @@ struct head
 					 *   contains any strong right-to-left glyphs.
 					 * Bit 10: This bit should be set if the font
 					 *   contains Indic-style rearrangement effects.
-
 					 * Bit 11: Font data is 'lossless,' as a result
 					 *   of having been compressed and decompressed
 					 *   with the Agfa MicroType Express engine.
@@ -121,10 +119,10 @@ struct head
 					   January 1, 1904. 64-bit integer */
   LONGDATETIME	modified;		/* Number of seconds since 12:00 midnight,
 					   January 1, 1904. 64-bit integer */
-  HBINT16		xMin;			/* For all glyph bounding boxes. */
-  HBINT16		yMin;			/* For all glyph bounding boxes. */
-  HBINT16		xMax;			/* For all glyph bounding boxes. */
-  HBINT16		yMax;			/* For all glyph bounding boxes. */
+  HBINT16	xMin;			/* For all glyph bounding boxes. */
+  HBINT16	yMin;			/* For all glyph bounding boxes. */
+  HBINT16	xMax;			/* For all glyph bounding boxes. */
+  HBINT16	yMax;			/* For all glyph bounding boxes. */
   HBUINT16	macStyle;		/* Bit 0: Bold (if set to 1);
 					 * Bit 1: Italic (if set to 1)
 					 * Bit 2: Underline (if set to 1)
@@ -134,15 +132,15 @@ struct head
 					 * Bit 6: Extended (if set to 1)
 					 * Bits 7-15: Reserved (set to 0). */
   HBUINT16	lowestRecPPEM;		/* Smallest readable size in pixels. */
-  HBINT16		fontDirectionHint;	/* Deprecated (Set to 2).
+  HBINT16	fontDirectionHint;	/* Deprecated (Set to 2).
 					 * 0: Fully mixed directional glyphs;
 					 * 1: Only strongly left to right;
 					 * 2: Like 1 but also contains neutrals;
 					 * -1: Only strongly right to left;
 					 * -2: Like -1 but also contains neutrals. */
   public:
-  HBINT16		indexToLocFormat;	/* 0 for short offsets, 1 for long. */
-  HBINT16		glyphDataFormat;	/* 0 for current format. */
+  HBINT16	indexToLocFormat;	/* 0 for short offsets, 1 for long. */
+  HBINT16	glyphDataFormat;	/* 0 for current format. */
 
   DEFINE_SIZE_STATIC (54);
 };
diff --git a/src/hb-ot-post-table.hh b/src/hb-ot-post-table.hh
index 019472c8..9e479211 100644
--- a/src/hb-ot-post-table.hh
+++ b/src/hb-ot-post-table.hh
@@ -261,16 +261,16 @@ struct post
 					 * from the value of this field. */
   FWORD		underlineThickness;	/* Suggested values for the underline
 					   thickness. */
-  HBUINT32		isFixedPitch;		/* Set to 0 if the font is proportionally
+  HBUINT32	isFixedPitch;		/* Set to 0 if the font is proportionally
 					 * spaced, non-zero if the font is not
 					 * proportionally spaced (i.e. monospaced). */
-  HBUINT32		minMemType42;		/* Minimum memory usage when an OpenType font
+  HBUINT32	minMemType42;		/* Minimum memory usage when an OpenType font
 					 * is downloaded. */
-  HBUINT32		maxMemType42;		/* Maximum memory usage when an OpenType font
+  HBUINT32	maxMemType42;		/* Maximum memory usage when an OpenType font
 					 * is downloaded. */
-  HBUINT32		minMemType1;		/* Minimum memory usage when an OpenType font
+  HBUINT32	minMemType1;		/* Minimum memory usage when an OpenType font
 					 * is downloaded as a Type 1 font. */
-  HBUINT32		maxMemType1;		/* Maximum memory usage when an OpenType font
+  HBUINT32	maxMemType1;		/* Maximum memory usage when an OpenType font
 					 * is downloaded as a Type 1 font. */
 /*postV2Tail	v2[VAR];*/
   DEFINE_SIZE_STATIC (32);
commit e849b8a85bb66219db4d797d86ddd60ed7c26a2e
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Fri Jan 19 16:12:24 2018 +0330

    [cmake] Always put test/api/CMakeLists.txt on distributions

diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index 834f43b3..e22d726a 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -10,11 +10,12 @@ MAINTAINERCLEANFILES =
 lib:
 	@$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
 
+EXTRA_DIST += CMakeLists.txt
+
 if HAVE_GLIB
 AM_CPPFLAGS = -DSRCDIR="\"$(srcdir)\"" -I$(top_srcdir)/src/ -I$(top_builddir)/src/ $(GLIB_CFLAGS)
 LDADD = $(top_builddir)/src/libharfbuzz.la $(GLIB_LIBS)
 
-EXTRA_DIST += CMakeLists.txt
 EXTRA_DIST += hb-test.h
 
 check_PROGRAMS = $(TEST_PROGS)
commit c8f2a4f5b99d3be3079286817386b4185d35a545
Author: Cosimo Lupo <cosimo at anthrotype.com>
Date:   Thu Jan 18 22:49:40 2018 +0100

    hb-common.cc: Hatran script is right-to-left (#714)
    
    "Hatran is written from right to left horizontally"
    
    http://www.unicode.org/L2/L2012/12312-n4324-hatran.pdf
    
    This ancient script was added with Unicode 8.0.
    
    Also this spreadsheet (referenced in an inline comment in the
    source code) has it as RTL: http://goo.gl/x9ilM

diff --git a/src/hb-common.cc b/src/hb-common.cc
index cb1fb43f..1d0e7264 100644
--- a/src/hb-common.cc
+++ b/src/hb-common.cc
@@ -524,6 +524,7 @@ hb_script_get_horizontal_direction (hb_script_t script)
     case HB_SCRIPT_PSALTER_PAHLAVI:
 
     /* Unicode-8.0 additions */
+    case HB_SCRIPT_HATRAN:
     case HB_SCRIPT_OLD_HUNGARIAN:
 
     /* Unicode-9.0 additions */
commit 00806149b9b591e4ec15996d3d56bdbd60687821
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Fri Jan 19 01:12:31 2018 +0330

    Improve avoiding C++ linkage, definition creation and cmake tests (#710)

diff --git a/.circleci/config.yml b/.circleci/config.yml
index cd54b659..f558e6d6 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -25,7 +25,7 @@ jobs:
       - image: base/devel
     steps:
       - checkout
-      - run: pacman --noconfirm -Syu freetype2 cairo icu gettext gobject-introspection gcc gcc-libs glib2 graphite pkg-config ragel
+      - run: pacman --noconfirm -Syu freetype2 cairo icu gettext gobject-introspection gcc gcc-libs glib2 graphite pkg-config ragel python
       - run: ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2
       - run: make && (make check || (cat `find -name '*.log'` && false))
 
@@ -34,7 +34,7 @@ jobs:
       - image: fedora
     steps:
       - checkout
-      - run: dnf install -y pkg-config ragel gcc gcc-c++ automake autoconf libtool make which glib2-devel freetype-devel cairo-devel libicu-devel gobject-introspection-devel graphite2-devel redhat-rpm-config || true
+      - run: dnf install -y pkg-config ragel gcc gcc-c++ automake autoconf libtool make which glib2-devel freetype-devel cairo-devel libicu-devel gobject-introspection-devel graphite2-devel redhat-rpm-config python || true
       - run: NOCONFIGURE=1 ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2
       - run: mkdir build && cd build && ../configure && make && (make check || (cat `find -name '*.log'` && false))
 
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d75bb58c..435d4fa5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -127,7 +127,7 @@ if (BUILD_SHARED_LIBS)
     add_definitions("-DHB_EXTERN=__declspec(dllexport) extern")
   else ()
     set (CMAKE_CXX_FLAGS "-fvisibility=hidden ${CMAKE_CXX_FLAGS}")
-    set (CMAKE_C_FLAGS "-fvisibility=hidden ${CMAKE_CXX_FLAGS}")
+    set (CMAKE_C_FLAGS "-fvisibility=hidden ${CMAKE_C_FLAGS}")
     add_definitions("-DHB_EXTERN=__attribute__((visibility(\"default\"))) extern")
   endif ()
 endif ()
@@ -524,11 +524,19 @@ if (UNIX OR MINGW)
   link_libraries(-Bsymbolic-functions)
 
   # Make sure we don't link to libstdc++
-  set (CMAKE_CXX_FLAGS "-fno-rtti -fno-exceptions ${CMAKE_CXX_FLAGS}")
-  if (NOT APPLE)
-    set (CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
-    set (CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
-    set_target_properties(harfbuzz PROPERTIES LINKER_LANGUAGE C)
+  if (BUILD_SHARED_LIBS AND (
+    CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR
+    CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
+  ))
+    set (CMAKE_CXX_FLAGS "-fno-rtti -fno-exceptions ${CMAKE_CXX_FLAGS}")
+  endif ()
+  set (CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
+  set (CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
+  set_target_properties(harfbuzz PROPERTIES LINKER_LANGUAGE C)
+
+  # No threadsafe statics as we do it ourselves
+  if (BUILD_SHARED_LIBS)
+    set (CMAKE_CXX_FLAGS "-fno-threadsafe-statics ${CMAKE_CXX_FLAGS}")
   endif ()
 endif ()
 
@@ -782,22 +790,20 @@ endif ()
 ## Tests
 if (UNIX OR MINGW)
   if (BUILD_SHARED_LIBS)
-    # does some "make" stuff inside
-    #add_test(NAME check-defs.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-defs.sh)
-    #set_tests_properties(check-defs.sh PROPERTIES ENVIRONMENT "libs=.")
+    string(REPLACE ";" " " space_separated_headers "${project_headers}")  
+    add_custom_command(TARGET harfbuzz POST_BUILD
+      COMMAND ${CMAKE_COMMAND} -E env "headers=${space_separated_headers}" python ${PROJECT_SOURCE_DIR}/src/gen-def.py ${PROJECT_BINARY_DIR}/harfbuzz.def
+      WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src)
 
     add_test(NAME check-symbols.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-symbols.sh)
-    set_tests_properties(check-symbols.sh PROPERTIES ENVIRONMENT "libs=.")
-
-    if (NOT APPLE)
-      add_test(NAME check-libstdc++.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-libstdc++.sh)
-      add_test(NAME check-static-inits.sh
-        COMMAND ${PROJECT_SOURCE_DIR}/src/check-static-inits.sh
-        WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/CMakeFiles/harfbuzz.dir/src # ugly hack
-      )
-      set_tests_properties(check-libstdc++.sh check-static-inits.sh
-        PROPERTIES ENVIRONMENT "libs=.")
-    endif ()
+    add_test(NAME check-static-inits.sh
+      COMMAND ${PROJECT_SOURCE_DIR}/src/check-static-inits.sh
+      WORKING_DIRECTORY ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/harfbuzz.dir/src # ugly hack
+    )
+    add_test(NAME check-libstdc++.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-libstdc++.sh)
+    add_test(NAME check-defs.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-defs.sh)
+    set_tests_properties(check-symbols.sh check-static-inits.sh check-libstdc++.sh check-defs.sh
+      PROPERTIES ENVIRONMENT "libs=.;srcdir=${PROJECT_SOURCE_DIR}/src")
   endif ()
 
   add_test(NAME check-c-linkage-decls.sh COMMAND ./check-c-linkage-decls.sh)
diff --git a/configure.ac b/configure.ac
index ade962af..54c5260e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -83,6 +83,9 @@ if test "x$GCC" = "xyes"; then
 	# Make sure we don't link to libstdc++
 	CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions"
 
+	# No threadsafe statics and C++ as we do it ourselves
+	CXXFLAGS="$CXXFLAGS -fno-threadsafe-statics"
+
 	# Assorted warnings
 	CXXFLAGS="$CXXFLAGS -Wcast-align"
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 912a98cb..833d1f95 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -223,21 +223,14 @@ CLEANFILES += $(pkgconfig_DATA)
 
 CLEANFILES += harfbuzz.def
 harfbuzz.def: $(HBHEADERS) $(HBNODISTHEADERS)
-	$(AM_V_GEN) (echo EXPORTS; \
-	(cat $^ || echo 'hb_ERROR ()' ) | \
-	$(EGREP) '^hb_.* \(' | \
-	sed -e 's/ (.*//' | \
-	LC_ALL=C sort; \
-	echo LIBRARY libharfbuzz-0.dll; \
-	) >"$@"
-	@ ! grep -q hb_ERROR "$@" \
-	|| ($(RM) "$@"; false)
+	$(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py $@
 
 
 GENERATORS = \
 	gen-arabic-table.py \
 	gen-indic-table.py \
 	gen-use-table.py \
+	gen-def.py \
 	$(NULL)
 EXTRA_DIST += $(GENERATORS)
 
diff --git a/src/check-defs.sh b/src/check-defs.sh
index c7eac355..9b4b7572 100755
--- a/src/check-defs.sh
+++ b/src/check-defs.sh
@@ -5,7 +5,6 @@ export LC_ALL
 
 test -z "$srcdir" && srcdir=.
 test -z "$libs" && libs=.libs
-test -z "$MAKE" && MAKE=make
 stat=0
 
 if which nm 2>/dev/null >/dev/null; then
@@ -16,26 +15,36 @@ else
 fi
 
 defs="harfbuzz.def"
-$MAKE $defs > /dev/null
+if ! test -f "$defs"; then
+	echo "check-defs.sh: '$defs' not found; skipping test"
+	exit 77
+fi
+
 tested=false
 for def in $defs; do
 	lib=`echo "$def" | sed 's/[.]def$//;s at .*/@@'`
-	so=$libs/lib${lib}.so
+	for suffix in so dylib; do
+		so=$libs/lib${lib}.$suffix
+		if ! test -f "$so"; then continue; fi
+
+		EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] .' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>\| __gcov_flush\>\| llvm_' | cut -d' ' -f3`"
 
-	EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] .' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>\| __gcov_flush\>\| llvm_' | cut -d' ' -f3`"
+		# On mac, C symbols are prefixed with _
+		if test $suffix = dylib; then prefix="_"; fi
 
-	if test -f "$so"; then
+		if test -f "$so"; then
 
-		echo "Checking that $so has the same symbol list as $def"
-		{
-			echo EXPORTS
-			echo "$EXPORTED_SYMBOLS"
-			# cheat: copy the last line from the def file!
-			tail -n1 "$def"
-		} | diff "$def" - >&2 || stat=1
+			echo "Checking that $so has the same symbol list as $def"
+			{
+				echo EXPORTS
+				echo "$EXPORTED_SYMBOLS" | sed -e "s/^${prefix}hb/hb/g"
+				# cheat: copy the last line from the def file!
+				tail -n1 "$def"
+			} | diff "$def" - >&2 || stat=1
 
-		tested=true
-	fi
+			tested=true
+		fi
+	done
 done
 if ! $tested; then
 	echo "check-defs.sh: libharfbuzz shared library not found; skipping test"
diff --git a/src/gen-def.py b/src/gen-def.py
new file mode 100755
index 00000000..ad1606ec
--- /dev/null
+++ b/src/gen-def.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+
+import io, os, re, sys
+
+headers_content = []
+for h in os.environ["headers"].split (' '):
+	if h.endswith (".h"):
+		with io.open(h, encoding='utf8') as f: headers_content.append (f.read ())
+
+result = ("EXPORTS\n" +
+	"\n".join (sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re.M))) +
+	"\nLIBRARY libharfbuzz-0.dll")
+
+with open (sys.argv[1], "w") as f: f.write (result)
commit 9b693212a834a96252f4ebe0b006b85e9f35fc91
Author: David Corbett <corbett.dav at husky.neu.edu>
Date:   Thu Jan 18 16:34:13 2018 -0500

    Update record-test.sh to the new directory layout (#716)

diff --git a/test/shaping/README.md b/test/shaping/README.md
index d1df6347..4c9a1e5d 100644
--- a/test/shaping/README.md
+++ b/test/shaping/README.md
@@ -23,18 +23,19 @@ what this does is:
   * If the outputs differ, perhaps it is because the font does not have
     glyph names; it then compares the output of `hb-view` for both fonts.
   * If the outputs differ, recording fails.  Otherwise, it will move the
-    subset font file into `fonts/sha1sum` and name it after its hash,
-    and prints out the test case input, which you can then redirect to
-    an existing or new test file in `tests`, eg.:
+    subset font file into `data/in-house/fonts` and name it after its
+    hash, and print out the test case input, which you can then redirect
+    to an existing or new test file in `data/in-house/tests` using `-o=`,
+    e.g.:
 ```sh
-$ ./hb-unicode-encode 41 42 43 627 | ./record-test.sh ../../util/hb-shape font.ttf >> tests/test-name.test
+$ ./hb-unicode-encode 41 42 43 627 | ./record-test.sh -o=data/in-house/tests/test-name.test ../../util/hb-shape font.ttf
 ```
 
 If you created a new test file, add it to `Makefile.am` so it is run.
 Check that `make check` does indeed run it, and that the test passes.
 When everything looks good, `git add` the new font as well as new
 test file if you created any.  You can see what new files are there
-by running `git status tests fonts/sha1sum`.  And commit!
+by running `git status data/in-house`.  And commit!
 
 *Note!*  Please only add tests using Open Source fonts, preferably under
 OFL or similar license.
diff --git a/test/shaping/record-test.sh b/test/shaping/record-test.sh
index 9a71cc87..8ce1653d 100755
--- a/test/shaping/record-test.sh
+++ b/test/shaping/record-test.sh
@@ -2,6 +2,11 @@
 
 dir=`mktemp -d`
 
+out=/dev/stdout
+if test "x${1:0:3}" == 'x-o='; then
+	out=${1:3}
+	shift
+fi
 hb_shape=$1
 shift
 fontfile=$1
@@ -67,8 +72,8 @@ if ! test "x$glyphs" = "x$glyphs_subset"; then
 	echo "$text" | $hb_view $options "$dir/font.subset.ttf" --output-format=png --output-file="$dir/subset.png"
 	if ! cmp "$dir/orig.png" "$dir/subset.png"; then
 		echo "Images differ.  Please inspect $dir/*.png." >&2
-		echo "$glyphs"
-		echo "$glyphs_subset"
+		echo "$glyphs" >> "$out"
+		echo "$glyphs_subset" >> "$out"
 		exit 2
 	fi
 	echo "Yep; all good." >&2
@@ -78,7 +83,7 @@ if ! test "x$glyphs" = "x$glyphs_subset"; then
 fi
 
 sha1sum=`sha1sum "$dir/font.subset.ttf" | cut -d' ' -f1`
-subset="fonts/sha1sum/$sha1sum.ttf"
+subset="data/in-house/fonts/$sha1sum.ttf"
 mv "$dir/font.subset.ttf" "$subset"
 
 # There ought to be an easier way to do this, but it escapes me...
@@ -89,8 +94,12 @@ echo "$glyphs" > "$glyphs_file"
 # Open the "file"s
 exec 3<"$unicodes_file"
 exec 4<"$glyphs_file"
+relative_subset="$subset"
+if test "$out" != "/dev/stdout"; then
+	relative_subset="$(/usr/bin/python -c 'import os, sys; print (os.path.relpath (sys.argv[1], sys.argv[2]))' "$subset" "$(dirname "$out")")"
+fi
 while read uline <&3 && read gline <&4; do
-	echo "$subset:$options:$uline:$gline"
+	echo "$relative_subset:$options:$uline:$gline" >> "$out"
 done
 
 


More information about the HarfBuzz mailing list