[HarfBuzz] harfbuzz-ng: Branch 'master' - 8 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Tue Apr 24 11:23:09 PDT 2012


 TODO                                 |    2 
 src/Makefile.am                      |    3 
 src/hb-buffer-private.hh             |    2 
 src/hb-buffer.cc                     |    2 
 src/hb-graphite2.cc                  |    5 
 src/hb-ot-layout-common-private.hh   |   19 +--
 src/hb-ot-layout-gpos-table.hh       |    2 
 src/hb-ot-layout-gsub-table.hh       |  144 +++++++++++-----------------
 src/hb-ot-layout-gsubgpos-private.hh |  179 +++++++++++++++++------------------
 src/hb-ot-layout-private.hh          |   47 ---------
 src/hb-ot-layout.cc                  |   10 -
 src/hb-ot-layout.h                   |   10 -
 src/hb-ot-map-private.hh             |    3 
 src/hb-ot-map.cc                     |   15 ++
 src/hb-ot-shape-complex-arabic.cc    |    4 
 src/hb-ot-shape-complex-misc.cc      |    4 
 src/hb-ot-shape.cc                   |    5 
 src/hb-set-private.hh                |  139 +++++++++++++++++++++++++++
 src/hb-set.cc                        |  175 ++++++++++++++++++++++++++++++++++
 src/hb-set.h                         |  119 +++++++++++++++++++++++
 src/hb.h                             |    1 
 21 files changed, 637 insertions(+), 253 deletions(-)

New commits:
commit 6c6ccaf575392f6e6bb9a15534026e4ea462705b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Apr 24 14:21:15 2012 -0400

    Add a few more set operations
    
    TODO: Tests for hb_set_t.

diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh
index a6239e4..660aaee 100644
--- a/src/hb-set-private.hh
+++ b/src/hb-set-private.hh
@@ -38,6 +38,12 @@ struct _hb_set_t
   inline void clear (void) {
     memset (elts, 0, sizeof elts);
   }
+  inline bool empty (void) const {
+    for (unsigned int i = 0; i < ARRAY_LENGTH (elts); i++)
+      if (elts[i])
+        return false;
+    return true;
+  }
   inline void add (hb_codepoint_t g)
   {
     if (unlikely (g > MAX_G)) return;
@@ -64,19 +70,65 @@ struct _hb_set_t
         return true;
     return false;
   }
+  inline bool equal (const hb_set_t *other) const
+  {
+    for (unsigned int i = 0; i < ELTS; i++)
+      if (elts[i] != other->elts[i])
+        return false;
+    return true;
+  }
+  inline void set (const hb_set_t *other)
+  {
+    for (unsigned int i = 0; i < ELTS; i++)
+      elts[i] = other->elts[i];
+  }
+  inline void union_ (const hb_set_t *other)
+  {
+    for (unsigned int i = 0; i < ELTS; i++)
+      elts[i] |= other->elts[i];
+  }
+  inline void intersect (const hb_set_t *other)
+  {
+    for (unsigned int i = 0; i < ELTS; i++)
+      elts[i] &= other->elts[i];
+  }
+  inline void subtract (const hb_set_t *other)
+  {
+    for (unsigned int i = 0; i < ELTS; i++)
+      elts[i] &= ~other->elts[i];
+  }
+  inline hb_codepoint_t min (void) const
+  {
+    for (unsigned int i = 0; i < ELTS; i++)
+      if (elts[i])
+	for (unsigned int j = 0; i < BITS; j++)
+	  if (elts[i] & (1 << j))
+	    return i * BITS + j;
+    return 0;
+  }
+  inline hb_codepoint_t max (void) const
+  {
+    for (unsigned int i = ELTS; i; i--)
+      if (elts[i - 1])
+	for (unsigned int j = BITS; j; j--)
+	  if (elts[i - 1] & (1 << (j - 1)))
+	    return (i - 1) * BITS + (j - 1);
+    return 0;
+  }
 
   typedef uint32_t elt_t;
   static const unsigned int MAX_G = 65536 - 1;
   static const unsigned int SHIFT = 5;
   static const unsigned int BITS = (1 << SHIFT);
   static const unsigned int MASK = BITS - 1;
+  static const unsigned int ELTS = (MAX_G + 1 + (BITS - 1)) / BITS;
 
   elt_t &elt (hb_codepoint_t g) { return elts[g >> SHIFT]; }
   elt_t elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; }
   elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); }
 
   hb_object_header_t header;
-  elt_t elts[(MAX_G + 1 + (BITS - 1)) / BITS]; /* 8kb */
+  elt_t elts[ELTS]; /* 8kb */
 
   ASSERT_STATIC (sizeof (elt_t) * 8 == BITS);
   ASSERT_STATIC (sizeof (elts) * 8 > MAX_G);
diff --git a/src/hb-set.cc b/src/hb-set.cc
index 353489b..3b1c5bd 100644
--- a/src/hb-set.cc
+++ b/src/hb-set.cc
@@ -28,6 +28,8 @@
 
 
 
+/* Public API */
+
 static hb_set_t _hb_set_nil = {
   HB_OBJECT_HEADER_STATIC,
 
@@ -99,6 +101,12 @@ hb_set_clear (hb_set_t *set)
 }
 
 hb_bool_t
+hb_set_empty (hb_set_t *set)
+{
+  return set->empty ();
+}
+
+hb_bool_t
 hb_set_has (hb_set_t       *set,
 	    hb_codepoint_t  codepoint)
 {
@@ -118,3 +126,50 @@ hb_set_del (hb_set_t       *set,
 {
   set->del (codepoint);
 }
+
+hb_bool_t
+hb_set_equal (hb_set_t *set,
+	      hb_set_t *other)
+{
+  return set->equal (other);
+}
+
+void
+hb_set_set (hb_set_t *set,
+	    hb_set_t *other)
+{
+  set->set (other);
+}
+
+void
+hb_set_union (hb_set_t *set,
+	      hb_set_t *other)
+{
+  set->union_ (other);
+}
+
+void
+hb_set_intersect (hb_set_t *set,
+		  hb_set_t *other)
+{
+  set->intersect (other);
+}
+
+void
+hb_set_subtract (hb_set_t *set,
+		 hb_set_t *other)
+{
+  set->subtract (other);
+}
+
+hb_codepoint_t
+hb_set_min (hb_set_t *set)
+{
+  return set->min ();
+}
+
+hb_codepoint_t
+hb_set_max (hb_set_t *set)
+{
+  return set->max ();
+}
diff --git a/src/hb-set.h b/src/hb-set.h
index a9c734b..35c77b8 100644
--- a/src/hb-set.h
+++ b/src/hb-set.h
@@ -52,14 +52,14 @@ void
 hb_set_destroy (hb_set_t *set);
 
 hb_bool_t
-hb_set_set_user_data (hb_set_t        *set,
+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_set_get_user_data (hb_set_t        *set,
+hb_set_get_user_data (hb_set_t           *set,
 		      hb_user_data_key_t *key);
 
 
@@ -71,6 +71,9 @@ void
 hb_set_clear (hb_set_t *set);
 
 hb_bool_t
+hb_set_empty (hb_set_t *set);
+
+hb_bool_t
 hb_set_has (hb_set_t       *set,
 	    hb_codepoint_t  codepoint);
 
@@ -82,8 +85,33 @@ void
 hb_set_del (hb_set_t       *set,
 	    hb_codepoint_t  codepoint);
 
-/* TODO: add union, intersect, subtract, equal, empty, min, max, iter, etc */
+hb_bool_t
+hb_set_equal (hb_set_t *set,
+	      hb_set_t *other);
+
+void
+hb_set_set (hb_set_t *set,
+	    hb_set_t *other);
+
+void
+hb_set_union (hb_set_t *set,
+	      hb_set_t *other);
+
+void
+hb_set_intersect (hb_set_t *set,
+		  hb_set_t *other);
+
+void
+hb_set_subtract (hb_set_t *set,
+		 hb_set_t *other);
+
+hb_codepoint_t
+hb_set_min (hb_set_t *set);
+
+hb_codepoint_t
+hb_set_max (hb_set_t *set);
 
+/* TODO: Add faster iteration API? */
 
 
 HB_END_DECLS
commit 5caece67ab9eee322bdcdf6f4b607eadde297e56
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 23 23:03:12 2012 -0400

    Make closure() return void

diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index e4e631a..371672a 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -39,17 +39,15 @@ struct SingleSubstFormat1
 
   private:
 
-  inline bool closure (hb_closure_context_t *c) const
+  inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE ();
-    bool ret = false;
     Coverage::Iter iter;
     for (iter.init (this+coverage); iter.more (); iter.next ()) {
       hb_codepoint_t glyph_id = iter.get_glyph ();
       if (c->glyphs->has (glyph_id))
-	ret = c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFF) || ret;
+	c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFF);
     }
-    return ret;
   }
 
   inline bool would_apply (hb_codepoint_t glyph_id) const
@@ -96,16 +94,14 @@ struct SingleSubstFormat2
 
   private:
 
-  inline bool closure (hb_closure_context_t *c) const
+  inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE ();
-    bool ret = false;
     Coverage::Iter iter;
     for (iter.init (this+coverage); iter.more (); iter.next ()) {
       if (c->glyphs->has (iter.get_glyph ()))
-	ret = c->glyphs->add (substitute[iter.get_coverage ()]) || ret;
+	c->glyphs->add (substitute[iter.get_coverage ()]);
     }
-    return ret;
   }
 
   inline bool would_apply (hb_codepoint_t glyph_id) const
@@ -154,13 +150,13 @@ struct SingleSubst
 
   private:
 
-  inline bool closure (hb_closure_context_t *c) const
+  inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE ();
     switch (u.format) {
-    case 1: return u.format1.closure (c);
-    case 2: return u.format2.closure (c);
-    default:return false;
+    case 1: u.format1.closure (c); break;
+    case 2: u.format2.closure (c); break;
+    default:                       break;
     }
   }
 
@@ -208,14 +204,12 @@ struct Sequence
 
   private:
 
-  inline bool closure (hb_closure_context_t *c) const
+  inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE ();
     unsigned int count = substitute.len;
-    bool ret = false;
     for (unsigned int i = 0; i < count; i++)
-      ret = c->glyphs->add (substitute[i]) || ret;
-    return ret;
+      c->glyphs->add (substitute[i]);
   }
 
   inline bool apply (hb_apply_context_t *c) const
@@ -250,16 +244,14 @@ struct MultipleSubstFormat1
 
   private:
 
-  inline bool closure (hb_closure_context_t *c) const
+  inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE ();
-    bool ret = false;
     Coverage::Iter iter;
     for (iter.init (this+coverage); iter.more (); iter.next ()) {
       if (c->glyphs->has (iter.get_glyph ()))
-	ret = (this+sequence[iter.get_coverage ()]).closure (c) || ret;
+	(this+sequence[iter.get_coverage ()]).closure (c);
     }
-    return ret;
   }
 
   inline bool would_apply (hb_codepoint_t glyph_id) const
@@ -302,12 +294,12 @@ struct MultipleSubst
 
   private:
 
-  inline bool closure (hb_closure_context_t *c) const
+  inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE ();
     switch (u.format) {
-    case 1: return u.format1.closure (c);
-    default:return false;
+    case 1: u.format1.closure (c); break;
+    default:                       break;
     }
   }
 
@@ -354,20 +346,18 @@ struct AlternateSubstFormat1
 
   private:
 
-  inline bool closure (hb_closure_context_t *c) const
+  inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE ();
-    bool ret = false;
     Coverage::Iter iter;
     for (iter.init (this+coverage); iter.more (); iter.next ()) {
       if (c->glyphs->has (iter.get_glyph ())) {
 	const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
 	unsigned int count = alt_set.len;
 	for (unsigned int i = 0; i < count; i++)
-	  ret = c->glyphs->add (alt_set[i]) || ret;
+	  c->glyphs->add (alt_set[i]);
       }
     }
-    return ret;
   }
 
   inline bool would_apply (hb_codepoint_t glyph_id) const
@@ -430,12 +420,12 @@ struct AlternateSubst
 
   private:
 
-  inline bool closure (hb_closure_context_t *c) const
+  inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE ();
     switch (u.format) {
-    case 1: return u.format1.closure (c);
-    default:return false;
+    case 1: u.format1.closure (c); break;
+    default:                       break;
     }
   }
 
@@ -479,14 +469,14 @@ struct Ligature
 
   private:
 
-  inline bool closure (hb_closure_context_t *c) const
+  inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE ();
     unsigned int count = component.len;
     for (unsigned int i = 1; i < count; i++)
       if (!c->glyphs->has (component[i]))
-        return false;
-    return c->glyphs->add (ligGlyph);
+        return;
+    c->glyphs->add (ligGlyph);
   }
 
   inline bool would_apply (hb_codepoint_t second) const
@@ -584,17 +574,12 @@ struct LigatureSet
 
   private:
 
-  inline bool closure (hb_closure_context_t *c) const
+  inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE ();
-    bool ret = false;
     unsigned int num_ligs = ligature.len;
     for (unsigned int i = 0; i < num_ligs; i++)
-    {
-      const Ligature &lig = this+ligature[i];
-      ret = lig.closure (c) || ret;
-    }
-    return ret;
+      (this+ligature[i]).closure (c);
   }
 
   inline bool would_apply (hb_codepoint_t second) const
@@ -643,17 +628,14 @@ struct LigatureSubstFormat1
 
   private:
 
-  inline bool closure (hb_closure_context_t *c) const
+  inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE ();
-    bool ret = false;
     Coverage::Iter iter;
     for (iter.init (this+coverage); iter.more (); iter.next ()) {
       if (c->glyphs->has (iter.get_glyph ()))
-	ret = (this+ligatureSet[iter.get_coverage ()]).closure (c) || ret;
+	(this+ligatureSet[iter.get_coverage ()]).closure (c);
     }
-    return ret;
-    return false;
   }
 
   inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const
@@ -700,12 +682,12 @@ struct LigatureSubst
 
   private:
 
-  inline bool closure (hb_closure_context_t *c) const
+  inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE ();
     switch (u.format) {
-    case 1: return u.format1.closure (c);
-    default:return false;
+    case 1: u.format1.closure (c); break;
+    default:                       break;
     }
   }
 
@@ -744,7 +726,7 @@ struct LigatureSubst
 
 
 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index);
-static inline bool closure_lookup (hb_closure_context_t *c, unsigned int lookup_index);
+static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_index);
 
 struct ContextSubst : Context
 {
@@ -752,7 +734,7 @@ struct ContextSubst : Context
 
   private:
 
-  inline bool closure (hb_closure_context_t *c) const
+  inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE ();
     return Context::closure (c, closure_lookup);
@@ -771,7 +753,7 @@ struct ChainContextSubst : ChainContext
 
   private:
 
-  inline bool closure (hb_closure_context_t *c) const
+  inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE ();
     return ChainContext::closure (c, closure_lookup);
@@ -798,7 +780,7 @@ struct ExtensionSubst : Extension
     return StructAtOffset<SubstLookupSubTable> (this, offset);
   }
 
-  inline bool closure (hb_closure_context_t *c) const;
+  inline void closure (hb_closure_context_t *c) const;
   inline bool would_apply (hb_codepoint_t glyph_id) const;
   inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const;
 
@@ -816,7 +798,7 @@ struct ReverseChainSingleSubstFormat1
 
   private:
 
-  inline bool closure (hb_closure_context_t *c) const
+  inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE ();
     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
@@ -826,21 +808,19 @@ struct ReverseChainSingleSubstFormat1
     count = backtrack.len;
     for (unsigned int i = 0; i < count; i++)
       if (!(this+backtrack[i]).intersects (c->glyphs))
-        return false;
+        return;
 
     count = lookahead.len;
     for (unsigned int i = 0; i < count; i++)
       if (!(this+lookahead[i]).intersects (c->glyphs))
-        return false;
+        return;
 
     const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
-    bool ret = false;
     Coverage::Iter iter;
     for (iter.init (this+coverage); iter.more (); iter.next ()) {
       if (c->glyphs->has (iter.get_glyph ()))
-	ret = c->glyphs->add (substitute[iter.get_coverage ()]) || ret;
+	c->glyphs->add (substitute[iter.get_coverage ()]);
     }
-    return false;
   }
 
   inline bool apply (hb_apply_context_t *c) const
@@ -910,12 +890,12 @@ struct ReverseChainSingleSubst
 
   private:
 
-  inline bool closure (hb_closure_context_t *c) const
+  inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE ();
     switch (u.format) {
-    case 1: return u.format1.closure (c);
-    default:return false;
+    case 1: u.format1.closure (c); break;
+    default:                       break;
     }
   }
 
@@ -965,20 +945,20 @@ struct SubstLookupSubTable
     ReverseChainSingle	= 8
   };
 
-  inline bool closure (hb_closure_context_t *c,
+  inline void closure (hb_closure_context_t *c,
 		       unsigned int    lookup_type) const
   {
     TRACE_CLOSURE ();
     switch (lookup_type) {
-    case Single:		return u.single.closure (c);
-    case Multiple:		return u.multiple.closure (c);
-    case Alternate:		return u.alternate.closure (c);
-    case Ligature:		return u.ligature.closure (c);
-    case Context:		return u.c.closure (c);
-    case ChainContext:		return u.chainContext.closure (c);
-    case Extension:		return u.extension.closure (c);
-    case ReverseChainSingle:	return u.reverseChainContextSingle.closure (c);
-    default:return false;
+    case Single:		u.single.closure (c); break;
+    case Multiple:		u.multiple.closure (c); break;
+    case Alternate:		u.alternate.closure (c); break;
+    case Ligature:		u.ligature.closure (c); break;
+    case Context:		u.c.closure (c); break;
+    case ChainContext:		u.chainContext.closure (c); break;
+    case Extension:		u.extension.closure (c); break;
+    case ReverseChainSingle:	u.reverseChainContextSingle.closure (c); break;
+    default:                    break;
     }
   }
 
@@ -1068,14 +1048,12 @@ struct SubstLookup : Lookup
     return lookup_type_is_reverse (type);
   }
 
-  inline bool closure (hb_closure_context_t *c) const
+  inline void closure (hb_closure_context_t *c) const
   {
     unsigned int lookup_type = get_type ();
-    bool ret = false;
     unsigned int count = get_subtable_count ();
     for (unsigned int i = 0; i < count; i++)
-      ret = get_subtable (i).closure (c, lookup_type) || ret;
-    return ret;
+      get_subtable (i).closure (c, lookup_type);
   }
 
   inline bool would_apply (hb_codepoint_t glyph_id) const
@@ -1196,7 +1174,7 @@ struct GSUB : GSUBGPOS
   static inline void substitute_start (hb_buffer_t *buffer);
   static inline void substitute_finish (hb_buffer_t *buffer);
 
-  inline bool closure_lookup (hb_closure_context_t *c,
+  inline void closure_lookup (hb_closure_context_t *c,
 			      unsigned int          lookup_index) const
   { return get_lookup (lookup_index).closure (c); }
 
@@ -1231,9 +1209,9 @@ GSUB::substitute_finish (hb_buffer_t *buffer)
 
 /* Out-of-class implementation for methods recursing */
 
-inline bool ExtensionSubst::closure (hb_closure_context_t *c) const
+inline void ExtensionSubst::closure (hb_closure_context_t *c) const
 {
-  return get_subtable ().closure (c, get_type ());
+  get_subtable ().closure (c, get_type ());
 }
 
 inline bool ExtensionSubst::would_apply (hb_codepoint_t glyph_id) const
@@ -1269,19 +1247,17 @@ inline bool ExtensionSubst::is_reverse (void) const
   return SubstLookup::lookup_type_is_reverse (type);
 }
 
-static inline bool closure_lookup (hb_closure_context_t *c, unsigned int lookup_index)
+static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_index)
 {
   const GSUB &gsub = *(c->face->ot_layout->gsub);
   const SubstLookup &l = gsub.get_lookup (lookup_index);
 
   if (unlikely (c->nesting_level_left == 0))
-    return false;
+    return;
 
   c->nesting_level_left--;
-  bool ret = l.closure (c);
+  l.closure (c);
   c->nesting_level_left++;
-
-  return ret;
 }
 
 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index)
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index d40b2ce..1d12db1 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -229,7 +229,7 @@ struct hb_apply_context_t
 
 typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
 typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
-typedef bool (*closure_lookup_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
+typedef void (*closure_lookup_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
 typedef bool (*apply_lookup_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
 
 struct ContextClosureFuncs
@@ -375,15 +375,13 @@ struct LookupRecord
 };
 
 
-static inline bool closure_lookup (hb_closure_context_t *c,
+static inline void closure_lookup (hb_closure_context_t *c,
 				   unsigned int lookupCount,
 				   const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
 				   closure_lookup_func_t closure_func)
 {
-  bool ret = false;
   for (unsigned int i = 0; i < lookupCount; i++)
-    ret = closure_func (c, lookupRecord->lookupListIndex) || ret;
-  return ret;
+    closure_func (c, lookupRecord->lookupListIndex);
 }
 
 static inline bool apply_lookup (hb_apply_context_t *c,
@@ -460,19 +458,19 @@ struct ContextApplyLookupContext
   const void *match_data;
 };
 
-static inline bool context_closure_lookup (hb_closure_context_t *c,
+static inline void context_closure_lookup (hb_closure_context_t *c,
 					   unsigned int inputCount, /* Including the first glyph (not matched) */
 					   const USHORT input[], /* Array of input values--start with second glyph */
 					   unsigned int lookupCount,
 					   const LookupRecord lookupRecord[],
 					   ContextClosureLookupContext &lookup_context)
 {
-  return intersects_array (c,
-			   inputCount ? inputCount - 1 : 0, input,
-			   lookup_context.funcs.intersects, lookup_context.intersects_data)
-      && closure_lookup (c,
-			 lookupCount, lookupRecord,
-			 lookup_context.funcs.closure);
+  if (intersects_array (c,
+			inputCount ? inputCount - 1 : 0, input,
+			lookup_context.funcs.intersects, lookup_context.intersects_data))
+    closure_lookup (c,
+		    lookupCount, lookupRecord,
+		    lookup_context.funcs.closure);
 }
 
 
@@ -500,14 +498,14 @@ struct Rule
 
   private:
 
-  inline bool closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
+  inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
   {
     TRACE_CLOSURE ();
     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
-    return context_closure_lookup (c,
-				   inputCount, input,
-				   lookupCount, lookupRecord,
-				   lookup_context);
+    context_closure_lookup (c,
+			    inputCount, input,
+			    lookupCount, lookupRecord,
+			    lookup_context);
   }
 
   inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
@@ -545,14 +543,12 @@ struct Rule
 
 struct RuleSet
 {
-  inline bool closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
+  inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
   {
     TRACE_CLOSURE ();
-    bool ret = false;
     unsigned int num_rules = rule.len;
     for (unsigned int i = 0; i < num_rules; i++)
-      ret = (this+rule[i]).closure (c, lookup_context) || ret;
-    return ret;
+      (this+rule[i]).closure (c, lookup_context);
   }
 
   inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
@@ -587,7 +583,7 @@ struct ContextFormat1
 
   private:
 
-  inline bool closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
+  inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
   {
     TRACE_CLOSURE ();
 
@@ -598,14 +594,12 @@ struct ContextFormat1
       NULL
     };
 
-    bool ret = false;
     unsigned int count = ruleSet.len;
     for (unsigned int i = 0; i < count; i++)
       if (cov.intersects_coverage (c->glyphs, i)) {
 	const RuleSet &rule_set = this+ruleSet[i];
-	ret = rule_set.closure (c, lookup_context) || ret;
+	rule_set.closure (c, lookup_context);
       }
-    return ret;
   }
 
   inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
@@ -648,11 +642,11 @@ struct ContextFormat2
 
   private:
 
-  inline bool closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
+  inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
   {
     TRACE_CLOSURE ();
     if (!(this+coverage).intersects (c->glyphs))
-      return false;
+      return;
 
     const ClassDef &class_def = this+classDef;
 
@@ -661,14 +655,12 @@ struct ContextFormat2
       NULL
     };
 
-    bool ret = false;
     unsigned int count = ruleSet.len;
     for (unsigned int i = 0; i < count; i++)
       if (class_def.intersects_class (c->glyphs, i)) {
 	const RuleSet &rule_set = this+ruleSet[i];
-	ret = rule_set.closure (c, lookup_context) || ret;
+	rule_set.closure (c, lookup_context);
       }
-    return ret;
   }
 
   inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
@@ -717,21 +709,21 @@ struct ContextFormat3
 
   private:
 
-  inline bool closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
+  inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
   {
     TRACE_CLOSURE ();
     if (!(this+coverage[0]).intersects (c->glyphs))
-      return false;
+      return;
 
     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
     struct ContextClosureLookupContext lookup_context = {
       {intersects_coverage, closure_func},
       this
     };
-    return context_closure_lookup (c,
-				   glyphCount, (const USHORT *) (coverage + 1),
-				   lookupCount, lookupRecord,
-				   lookup_context);
+    context_closure_lookup (c,
+			    glyphCount, (const USHORT *) (coverage + 1),
+			    lookupCount, lookupRecord,
+			    lookup_context);
   }
 
   inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
@@ -781,14 +773,14 @@ struct Context
 {
   protected:
 
-  inline bool closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
+  inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
   {
     TRACE_CLOSURE ();
     switch (u.format) {
-    case 1: return u.format1.closure (c, closure_func);
-    case 2: return u.format2.closure (c, closure_func);
-    case 3: return u.format3.closure (c, closure_func);
-    default:return false;
+    case 1: u.format1.closure (c, closure_func); break;
+    case 2: u.format2.closure (c, closure_func); break;
+    case 3: u.format3.closure (c, closure_func); break;
+    default:                                     break;
     }
   }
 
@@ -838,7 +830,7 @@ struct ChainContextApplyLookupContext
   const void *match_data[3];
 };
 
-static inline bool chain_context_closure_lookup (hb_closure_context_t *c,
+static inline void chain_context_closure_lookup (hb_closure_context_t *c,
 						 unsigned int backtrackCount,
 						 const USHORT backtrack[],
 						 unsigned int inputCount, /* Including the first glyph (not matched) */
@@ -849,18 +841,18 @@ static inline bool chain_context_closure_lookup (hb_closure_context_t *c,
 						 const LookupRecord lookupRecord[],
 						 ChainContextClosureLookupContext &lookup_context)
 {
-  return intersects_array (c,
-			   backtrackCount, backtrack,
-			   lookup_context.funcs.intersects, lookup_context.intersects_data[0])
-      && intersects_array (c,
-			   inputCount ? inputCount - 1 : 0, input,
-			   lookup_context.funcs.intersects, lookup_context.intersects_data[1])
-      && intersects_array (c,
-			   lookaheadCount, lookahead,
-			   lookup_context.funcs.intersects, lookup_context.intersects_data[2])
-      && closure_lookup (c,
-			 lookupCount, lookupRecord,
-			 lookup_context.funcs.closure);
+  if (intersects_array (c,
+			backtrackCount, backtrack,
+			lookup_context.funcs.intersects, lookup_context.intersects_data[0])
+   && intersects_array (c,
+			inputCount ? inputCount - 1 : 0, input,
+			lookup_context.funcs.intersects, lookup_context.intersects_data[1])
+  && intersects_array (c,
+		       lookaheadCount, lookahead,
+		       lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
+    closure_lookup (c,
+		    lookupCount, lookupRecord,
+		    lookup_context.funcs.closure);
 }
 
 static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
@@ -904,18 +896,18 @@ struct ChainRule
 
   private:
 
-  inline bool closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
+  inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
   {
     TRACE_CLOSURE ();
     const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
     const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return chain_context_closure_lookup (c,
-					 backtrack.len, backtrack.array,
-					 input.len, input.array,
-					 lookahead.len, lookahead.array,
-					 lookup.len, lookup.array,
-					 lookup_context);
+    chain_context_closure_lookup (c,
+				  backtrack.len, backtrack.array,
+				  input.len, input.array,
+				  lookahead.len, lookahead.array,
+				  lookup.len, lookup.array,
+				  lookup_context);
   }
 
   inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
@@ -964,14 +956,12 @@ struct ChainRule
 
 struct ChainRuleSet
 {
-  inline bool closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
+  inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
   {
     TRACE_CLOSURE ();
-    bool ret = false;
     unsigned int num_rules = rule.len;
     for (unsigned int i = 0; i < num_rules; i++)
-      ret = (this+rule[i]).closure (c, lookup_context) || ret;
-    return ret;
+      (this+rule[i]).closure (c, lookup_context);
   }
 
   inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
@@ -1006,7 +996,7 @@ struct ChainContextFormat1
 
   private:
 
-  inline bool closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
+  inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
   {
     TRACE_CLOSURE ();
     const Coverage &cov = (this+coverage);
@@ -1016,14 +1006,12 @@ struct ChainContextFormat1
       {NULL, NULL, NULL}
     };
 
-    bool ret = false;
     unsigned int count = ruleSet.len;
     for (unsigned int i = 0; i < count; i++)
       if (cov.intersects_coverage (c->glyphs, i)) {
 	const ChainRuleSet &rule_set = this+ruleSet[i];
-	ret = rule_set.closure (c, lookup_context) || ret;
+	rule_set.closure (c, lookup_context);
       }
-    return ret;
   }
 
   inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
@@ -1065,11 +1053,11 @@ struct ChainContextFormat2
 
   private:
 
-  inline bool closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
+  inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
   {
     TRACE_CLOSURE ();
     if (!(this+coverage).intersects (c->glyphs))
-      return false;
+      return;
 
     const ClassDef &backtrack_class_def = this+backtrackClassDef;
     const ClassDef &input_class_def = this+inputClassDef;
@@ -1082,14 +1070,12 @@ struct ChainContextFormat2
        &lookahead_class_def}
     };
 
-    bool ret = false;
     unsigned int count = ruleSet.len;
     for (unsigned int i = 0; i < count; i++)
       if (input_class_def.intersects_class (c->glyphs, i)) {
 	const ChainRuleSet &rule_set = this+ruleSet[i];
-	ret = rule_set.closure (c, lookup_context) || ret;
+	rule_set.closure (c, lookup_context);
       }
-    return ret;
   }
 
   inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
@@ -1153,11 +1139,26 @@ struct ChainContextFormat3
 
   private:
 
-  inline bool closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
+  inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
   {
     TRACE_CLOSURE ();
-    /* TODO FILLME */
-    return false;
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+    if (!(this+input[0]).intersects (c->glyphs))
+      return;
+
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_coverage, closure_func},
+      {this, this, this}
+    };
+    chain_context_closure_lookup (c,
+				  backtrack.len, (const USHORT *) backtrack.array,
+				  input.len, (const USHORT *) input.array + 1,
+				  lookahead.len, (const USHORT *) lookahead.array,
+				  lookup.len, lookup.array,
+				  lookup_context);
   }
 
   inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
@@ -1219,14 +1220,14 @@ struct ChainContext
 {
   protected:
 
-  inline bool closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
+  inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
   {
     TRACE_CLOSURE ();
     switch (u.format) {
-    case 1: return u.format1.closure (c, closure_func);
-    case 2: return u.format2.closure (c, closure_func);
-    case 3: return u.format3.closure (c, closure_func);
-    default:return false;
+    case 1: u.format1.closure (c, closure_func); break;
+    case 2: u.format2.closure (c, closure_func); break;
+    case 3: u.format3.closure (c, closure_func); break;
+    default:                                     break;
     }
   }
 
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 95ed9c6..ded3dcc 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -470,13 +470,13 @@ hb_ot_layout_substitute_finish (hb_buffer_t  *buffer HB_UNUSED)
   GSUB::substitute_finish (buffer);
 }
 
-hb_bool_t
-hb_ot_layout_substitute_closure_lookup (hb_face_t      *face,
-				        hb_set_t *glyphs,
-				        unsigned int    lookup_index)
+void
+hb_ot_layout_substitute_closure_lookup (hb_face_t    *face,
+				        hb_set_t     *glyphs,
+				        unsigned int  lookup_index)
 {
   hb_closure_context_t c (face, glyphs);
-  return _get_gsub (face).closure_lookup (&c, lookup_index);
+  _get_gsub (face).closure_lookup (&c, lookup_index);
 }
 
 /*
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index f6890b6..b8b5baf 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -183,10 +183,10 @@ void
 hb_ot_layout_substitute_finish (hb_buffer_t  *buffer);
 
 
-hb_bool_t
-hb_ot_layout_substitute_closure_lookup (hb_face_t      *face,
-				        hb_set_t *glyphs,
-				        unsigned int    lookup_index);
+void
+hb_ot_layout_substitute_closure_lookup (hb_face_t    *face,
+				        hb_set_t     *glyphs,
+				        unsigned int  lookup_index);
 
 /*
  * GPOS
diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh
index 4b24370..a6239e4 100644
--- a/src/hb-set-private.hh
+++ b/src/hb-set-private.hh
@@ -38,23 +38,15 @@ struct _hb_set_t
   inline void clear (void) {
     memset (elts, 0, sizeof elts);
   }
-  inline bool add (hb_codepoint_t g)
+  inline void add (hb_codepoint_t g)
   {
-    if (unlikely (g > MAX_G)) return false;
-    elt_t &e = elt (g);
-    elt_t m = mask (g);
-    bool ret = !(e & m);
-    e |= m;
-    return ret;
+    if (unlikely (g > MAX_G)) return;
+    elt (g) |= mask (g);
   }
-  inline bool del (hb_codepoint_t g)
+  inline void del (hb_codepoint_t g)
   {
-    if (unlikely (g > MAX_G)) return false;
-    elt_t &e = elt (g);
-    elt_t m = mask (g);
-    bool ret = !!(e & m);
-    e &= ~m;
-    return ret;
+    if (unlikely (g > MAX_G)) return;
+    elt (g) &= ~mask (g);
   }
   inline bool has (hb_codepoint_t g) const
   {
commit 0b08adb3539f2ec29682456b89c69e89ff5e9c03
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 23 22:41:09 2012 -0400

    Add hb_set_t

diff --git a/TODO b/TODO
index d763c30..56eac54 100644
--- a/TODO
+++ b/TODO
@@ -85,6 +85,8 @@ Tests to write:
 
 - GObject, FreeType, etc
 
+- hb_set_t
+
 
 Optimizations:
 =============
diff --git a/src/Makefile.am b/src/Makefile.am
index f53505e..63d4e31 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -34,6 +34,8 @@ HBSOURCES =  \
 	hb-ot-name-table.hh \
 	hb-ot-tag.cc \
 	hb-private.hh \
+	hb-set-private.hh \
+	hb-set.cc \
 	hb-shape.cc \
 	hb-tt-font.cc \
 	hb-unicode-private.hh \
@@ -46,6 +48,7 @@ HBHEADERS = \
 	hb-buffer.h \
 	hb-common.h \
 	hb-font.h \
+	hb-set.h \
 	hb-shape.h \
 	hb-unicode.h \
 	hb-version.h \
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 8158df1..142eb5c 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -31,6 +31,7 @@
 
 #include "hb-ot-layout-private.hh"
 #include "hb-open-type-private.hh"
+#include "hb-set-private.hh"
 
 
 #define NO_CONTEXT		((unsigned int) 0x110000)
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index 32da46d..bf7e43b 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -95,51 +95,4 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout);
 
 
 
-struct _hb_set_t
-{
-  void clear (void) {
-    memset (elts, 0, sizeof elts);
-  }
-  bool add (hb_codepoint_t g)
-  {
-    if (unlikely (g > MAX_G)) return false;
-    elt_t &e = elt (g);
-    elt_t m = mask (g);
-    bool ret = !!(e & m);
-    e |= m;
-    return ret;
-  }
-  bool has (hb_codepoint_t g) const
-  {
-    if (unlikely (g > MAX_G)) return false;
-    return !!(elt (g) & mask (g));
-  }
-  bool intersects (hb_codepoint_t first,
-		   hb_codepoint_t last) const
-  {
-    if (unlikely (first > MAX_G)) return false;
-    if (unlikely (last  > MAX_G)) last = MAX_G;
-    unsigned int end = last + 1;
-    for (hb_codepoint_t i = first; i < end; i++)
-      if (has (i))
-        return true;
-    return false;
-  }
-
-  private:
-  typedef uint32_t elt_t;
-  static const unsigned int MAX_G = 65536 - 1;
-  static const unsigned int SHIFT = 5;
-  static const unsigned int BITS = (1 << SHIFT);
-  static const unsigned int MASK = BITS - 1;
-
-  elt_t &elt (hb_codepoint_t g) { return elts[g >> SHIFT]; }
-  elt_t elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; }
-  elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); }
-
-  elt_t elts[(MAX_G + 1 + (BITS - 1)) / BITS]; /* 8kb */
-  ASSERT_STATIC (sizeof (elt_t) * 8 == BITS);
-  ASSERT_STATIC (sizeof (elts) * 8 > MAX_G);
-};
-
 #endif /* HB_OT_LAYOUT_PRIVATE_HH */
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index 1c1e7d9..f6890b6 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -183,8 +183,6 @@ void
 hb_ot_layout_substitute_finish (hb_buffer_t  *buffer);
 
 
-typedef struct _hb_set_t hb_set_t;
-
 hb_bool_t
 hb_ot_layout_substitute_closure_lookup (hb_face_t      *face,
 				        hb_set_t *glyphs,
diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh
new file mode 100644
index 0000000..4b24370
--- /dev/null
+++ b/src/hb-set-private.hh
@@ -0,0 +1,95 @@
+/*
+ * Copyright © 2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_SET_PRIVATE_HH
+#define HB_SET_PRIVATE_HH
+
+#include "hb-private.hh"
+#include "hb-set.h"
+#include "hb-object-private.hh"
+
+
+
+struct _hb_set_t
+{
+  inline void clear (void) {
+    memset (elts, 0, sizeof elts);
+  }
+  inline bool add (hb_codepoint_t g)
+  {
+    if (unlikely (g > MAX_G)) return false;
+    elt_t &e = elt (g);
+    elt_t m = mask (g);
+    bool ret = !(e & m);
+    e |= m;
+    return ret;
+  }
+  inline bool del (hb_codepoint_t g)
+  {
+    if (unlikely (g > MAX_G)) return false;
+    elt_t &e = elt (g);
+    elt_t m = mask (g);
+    bool ret = !!(e & m);
+    e &= ~m;
+    return ret;
+  }
+  inline bool has (hb_codepoint_t g) const
+  {
+    if (unlikely (g > MAX_G)) return false;
+    return !!(elt (g) & mask (g));
+  }
+  inline bool intersects (hb_codepoint_t first,
+			  hb_codepoint_t last) const
+  {
+    if (unlikely (first > MAX_G)) return false;
+    if (unlikely (last  > MAX_G)) last = MAX_G;
+    unsigned int end = last + 1;
+    for (hb_codepoint_t i = first; i < end; i++)
+      if (has (i))
+        return true;
+    return false;
+  }
+
+  typedef uint32_t elt_t;
+  static const unsigned int MAX_G = 65536 - 1;
+  static const unsigned int SHIFT = 5;
+  static const unsigned int BITS = (1 << SHIFT);
+  static const unsigned int MASK = BITS - 1;
+
+  elt_t &elt (hb_codepoint_t g) { return elts[g >> SHIFT]; }
+  elt_t elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; }
+  elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); }
+
+  hb_object_header_t header;
+  elt_t elts[(MAX_G + 1 + (BITS - 1)) / BITS]; /* 8kb */
+
+  ASSERT_STATIC (sizeof (elt_t) * 8 == BITS);
+  ASSERT_STATIC (sizeof (elts) * 8 > MAX_G);
+};
+
+
+
+#endif /* HB_SET_PRIVATE_HH */
diff --git a/src/hb-set.cc b/src/hb-set.cc
new file mode 100644
index 0000000..353489b
--- /dev/null
+++ b/src/hb-set.cc
@@ -0,0 +1,120 @@
+/*
+ * Copyright © 2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-set-private.hh"
+
+
+
+static hb_set_t _hb_set_nil = {
+  HB_OBJECT_HEADER_STATIC,
+
+  {0} /* elts */
+};
+
+
+hb_set_t *
+hb_set_create ()
+{
+  hb_set_t *set;
+
+  if (!(set = hb_object_create<hb_set_t> ()))
+    return &_hb_set_nil;
+
+  set->clear ();
+
+  return set;
+}
+
+hb_set_t *
+hb_set_get_empty (void)
+{
+  return &_hb_set_nil;
+}
+
+hb_set_t *
+hb_set_reference (hb_set_t *set)
+{
+  return hb_object_reference (set);
+}
+
+void
+hb_set_destroy (hb_set_t *set)
+{
+  if (!hb_object_destroy (set)) return;
+
+  free (set);
+}
+
+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)
+{
+  return hb_object_set_user_data (set, key, data, destroy, replace);
+}
+
+void *
+hb_set_get_user_data (hb_set_t        *set,
+			 hb_user_data_key_t *key)
+{
+  return hb_object_get_user_data (set, key);
+}
+
+
+hb_bool_t
+hb_set_allocation_successful (hb_set_t  *set)
+{
+  return TRUE;
+}
+
+void
+hb_set_clear (hb_set_t *set)
+{
+  set->clear ();
+}
+
+hb_bool_t
+hb_set_has (hb_set_t       *set,
+	    hb_codepoint_t  codepoint)
+{
+  return set->has (codepoint);
+}
+
+void
+hb_set_add (hb_set_t       *set,
+	    hb_codepoint_t  codepoint)
+{
+  set->add (codepoint);
+}
+
+void
+hb_set_del (hb_set_t       *set,
+	    hb_codepoint_t  codepoint)
+{
+  set->del (codepoint);
+}
diff --git a/src/hb-set.h b/src/hb-set.h
new file mode 100644
index 0000000..a9c734b
--- /dev/null
+++ b/src/hb-set.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_H_IN
+#error "Include <hb.h> instead."
+#endif
+
+#ifndef HB_SET_H
+#define HB_SET_H
+
+#include "hb-common.h"
+
+HB_BEGIN_DECLS
+
+
+typedef struct _hb_set_t hb_set_t;
+
+
+hb_set_t *
+hb_set_create (void);
+
+hb_set_t *
+hb_set_get_empty (void);
+
+hb_set_t *
+hb_set_reference (hb_set_t *set);
+
+void
+hb_set_destroy (hb_set_t *set);
+
+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_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_set_allocation_successful (hb_set_t  *set);
+
+void
+hb_set_clear (hb_set_t *set);
+
+hb_bool_t
+hb_set_has (hb_set_t       *set,
+	    hb_codepoint_t  codepoint);
+
+void
+hb_set_add (hb_set_t       *set,
+	    hb_codepoint_t  codepoint);
+
+void
+hb_set_del (hb_set_t       *set,
+	    hb_codepoint_t  codepoint);
+
+/* TODO: add union, intersect, subtract, equal, empty, min, max, iter, etc */
+
+
+
+HB_END_DECLS
+
+#endif /* HB_SET_H */
diff --git a/src/hb.h b/src/hb.h
index 996dc91..d36040e 100644
--- a/src/hb.h
+++ b/src/hb.h
@@ -32,6 +32,7 @@
 #include "hb-buffer.h"
 #include "hb-common.h"
 #include "hb-font.h"
+#include "hb-set.h"
 #include "hb-shape.h"
 #include "hb-unicode.h"
 #include "hb-version.h"
commit 5b93e8d94fb4c2474816304ae3f52e1c704882de
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 23 22:26:13 2012 -0400

    Update copyright headers

diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index d104a44..8158df1 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 2010  Google, Inc.
+ * Copyright © 2010,2012  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index 6e5b85e..c51e89a 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
- * Copyright © 2010  Google, Inc.
+ * Copyright © 2010,2012  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index 1feb3c8..e4e631a 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
- * Copyright © 2010  Google, Inc.
+ * Copyright © 2010,2012  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index aa3b268..d40b2ce 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
- * Copyright © 2010  Google, Inc.
+ * Copyright © 2010,2012  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
commit 6a9be5bd3524dc3eb1e88d1063bde2e4d8b57011
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 23 22:23:17 2012 -0400

    Rename hb_glyph_map_t to hb_set_t

diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index cec339b..d104a44 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -131,7 +131,7 @@ struct RangeRecord
     return c->check_struct (this);
   }
 
-  inline bool intersects (const hb_glyph_map_t *glyphs) const {
+  inline bool intersects (const hb_set_t *glyphs) const {
     return glyphs->intersects (start, end);
   }
 
@@ -358,7 +358,7 @@ struct CoverageFormat1
     return glyphArray.sanitize (c);
   }
 
-  inline bool intersects_coverage (const hb_glyph_map_t *glyphs, unsigned int index) const {
+  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
     return glyphs->has (glyphArray[index]);
   }
 
@@ -402,7 +402,7 @@ struct CoverageFormat2
     return rangeRecord.sanitize (c);
   }
 
-  inline bool intersects_coverage (const hb_glyph_map_t *glyphs, unsigned int index) const {
+  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
     unsigned int i;
     unsigned int count = rangeRecord.len;
     for (i = 0; i < count; i++) {
@@ -476,7 +476,7 @@ struct Coverage
     }
   }
 
-  inline bool intersects (const hb_glyph_map_t *glyphs) const {
+  inline bool intersects (const hb_set_t *glyphs) const {
     /* TODO speed this up */
     Coverage::Iter iter;
     for (iter.init (*this); iter.more (); iter.next ()) {
@@ -486,7 +486,7 @@ struct Coverage
     return false;
   }
 
-  inline bool intersects_coverage (const hb_glyph_map_t *glyphs, unsigned int index) const {
+  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
     switch (u.format) {
     case 1: return u.format1.intersects_coverage (glyphs, index);
     case 2: return u.format2.intersects_coverage (glyphs, index);
@@ -574,7 +574,7 @@ struct ClassDefFormat1
 	&& classValue.sanitize (c);
   }
 
-  inline bool intersects_class (const hb_glyph_map_t *glyphs, unsigned int klass) const {
+  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
     unsigned int count = classValue.len;
     for (unsigned int i = 0; i < count; i++)
       if (classValue[i] == klass && glyphs->has (startGlyph + i))
@@ -608,7 +608,7 @@ struct ClassDefFormat2
     return rangeRecord.sanitize (c);
   }
 
-  inline bool intersects_class (const hb_glyph_map_t *glyphs, unsigned int klass) const {
+  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
     unsigned int count = rangeRecord.len;
     for (unsigned int i = 0; i < count; i++)
       if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
@@ -647,7 +647,7 @@ struct ClassDef
     }
   }
 
-  inline bool intersects_class (const hb_glyph_map_t *glyphs, unsigned int klass) const {
+  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
     switch (u.format) {
     case 1: return u.format1.intersects_class (glyphs, klass);
     case 2: return u.format2.intersects_class (glyphs, klass);
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index 10cfd34..aa3b268 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -58,13 +58,13 @@ static inline uint8_t allocate_lig_id (hb_buffer_t *buffer) {
 struct hb_closure_context_t
 {
   hb_face_t *face;
-  hb_glyph_map_t *glyphs;
+  hb_set_t *glyphs;
   unsigned int nesting_level_left;
   unsigned int debug_depth;
 
 
   hb_closure_context_t (hb_face_t *face_,
-			hb_glyph_map_t *glyphs_,
+			hb_set_t *glyphs_,
 		        unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
 			  face (face_), glyphs (glyphs_),
 			  nesting_level_left (nesting_level_left_),
@@ -227,7 +227,7 @@ struct hb_apply_context_t
 
 
 
-typedef bool (*intersects_func_t) (hb_glyph_map_t *glyphs, const USHORT &value, const void *data);
+typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
 typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
 typedef bool (*closure_lookup_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
 typedef bool (*apply_lookup_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
@@ -243,16 +243,16 @@ struct ContextApplyFuncs
   apply_lookup_func_t apply;
 };
 
-static inline bool intersects_glyph (hb_glyph_map_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
+static inline bool intersects_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
 {
   return glyphs->has (value);
 }
-static inline bool intersects_class (hb_glyph_map_t *glyphs, const USHORT &value, const void *data)
+static inline bool intersects_class (hb_set_t *glyphs, const USHORT &value, const void *data)
 {
   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
   return class_def.intersects_class (glyphs, value);
 }
-static inline bool intersects_coverage (hb_glyph_map_t *glyphs, const USHORT &value, const void *data)
+static inline bool intersects_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
 {
   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
   return (data+coverage).intersects (glyphs);
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index 92f3c26..32da46d 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -95,7 +95,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout);
 
 
 
-struct _hb_glyph_map_t
+struct _hb_set_t
 {
   void clear (void) {
     memset (elts, 0, sizeof elts);
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 4441a7e..95ed9c6 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -472,7 +472,7 @@ hb_ot_layout_substitute_finish (hb_buffer_t  *buffer HB_UNUSED)
 
 hb_bool_t
 hb_ot_layout_substitute_closure_lookup (hb_face_t      *face,
-				        hb_glyph_map_t *glyphs,
+				        hb_set_t *glyphs,
 				        unsigned int    lookup_index)
 {
   hb_closure_context_t c (face, glyphs);
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index a9db04f..1c1e7d9 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -183,11 +183,11 @@ void
 hb_ot_layout_substitute_finish (hb_buffer_t  *buffer);
 
 
-typedef struct _hb_glyph_map_t hb_glyph_map_t;
+typedef struct _hb_set_t hb_set_t;
 
 hb_bool_t
 hb_ot_layout_substitute_closure_lookup (hb_face_t      *face,
-				        hb_glyph_map_t *glyphs,
+				        hb_set_t *glyphs,
 				        unsigned int    lookup_index);
 
 /*
diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index 5675d37..d5fc4ce 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -126,7 +126,7 @@ struct hb_ot_map_t
 			  hb_buffer_t *buffer) const;
 
   HB_INTERNAL void substitute_closure (hb_face_t *face,
-				       hb_glyph_map_t *glyphs) const;
+				       hb_set_t *glyphs) const;
 
   hb_mask_t global_mask;
 
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index a0efe90..bebf3ed 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -96,7 +96,7 @@ void hb_ot_map_t::apply (unsigned int table_index,
 }
 
 void hb_ot_map_t::substitute_closure (hb_face_t *face,
-				      hb_glyph_map_t *glyphs) const
+				      hb_set_t *glyphs) const
 {
   unsigned int table_index = 0;
   unsigned int i = 0;
commit a4385f0b0a6949e2ce49e6a147ad4beaa724f6c3
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 23 22:20:14 2012 -0400

    Improve clustering

diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 66b1461..b31cdc5 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -193,7 +193,7 @@ hb_form_clusters (hb_buffer_t *buffer)
 	(FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) |
 	 FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
 	 FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
-      buffer->info[i].cluster = buffer->info[i - 1].cluster;
+      buffer->info[i].cluster = buffer->info[i - 1].cluster; /* XXX do the min() here */
 }
 
 static void
@@ -251,8 +251,7 @@ hb_map_glyphs (hb_font_t    *font,
   for (buffer->idx = 0; buffer->idx < count;) {
     if (unlikely (_hb_unicode_is_variation_selector (buffer->info[buffer->idx + 1].codepoint))) {
       hb_font_get_glyph (font, buffer->info[buffer->idx].codepoint, buffer->info[buffer->idx + 1].codepoint, &glyph);
-      buffer->replace_glyph (glyph);
-      buffer->skip_glyph ();
+      buffer->replace_glyphs (2, 1, &glyph);
     } else {
       hb_font_get_glyph (font, buffer->info[buffer->idx].codepoint, 0, &glyph);
       buffer->replace_glyph (glyph);
commit 8e3715f8a16b315c1c7dd4b256e7f68a36c53e7c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 23 22:18:54 2012 -0400

    Minor

diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index 06d4912..6296608 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -104,7 +104,7 @@ struct _hb_buffer_t {
 					const uint16_t *glyph_data_be);
   HB_INTERNAL void replace_glyphs (unsigned int num_in,
 				   unsigned int num_out,
-				   const uint16_t *glyph_data);
+				   const hb_codepoint_t *glyph_data);
   HB_INTERNAL void replace_glyph (hb_codepoint_t glyph_index);
   /* Makes a copy of the glyph at idx to output and replace glyph_index */
   HB_INTERNAL void output_glyph (hb_codepoint_t glyph_index);
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 4a37e66..c566a4a 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -271,7 +271,7 @@ hb_buffer_t::replace_glyphs_be16 (unsigned int num_in,
 void
 hb_buffer_t::replace_glyphs (unsigned int num_in,
 			     unsigned int num_out,
-			     const uint16_t *glyph_data)
+			     const uint32_t *glyph_data)
 {
   if (!make_room_for (num_in, num_out)) return;
 
diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc
index fa07ae9..eab2eae 100644
--- a/src/hb-graphite2.cc
+++ b/src/hb-graphite2.cc
@@ -247,11 +247,10 @@ _hb_graphite_shape (hb_font_t          *font,
     features++;
   }
 
-  unsigned short *gids = NULL;
+  hb_codepoint_t *gids = NULL, *pg;
   hb_gr_cluster_t *clusters = NULL;
   gr_segment *seg = NULL;
   uint32_t *text = NULL;
-  unsigned short *pg;
   const gr_slot *is;
   unsigned int ci = 0, ic = 0;
   float curradvx = 0., curradvy = 0.;
@@ -280,7 +279,7 @@ _hb_graphite_shape (hb_font_t          *font,
   clusters = (hb_gr_cluster_t *) calloc (charlen, sizeof (hb_gr_cluster_t));
   if (!glyphlen || !clusters) goto dieout;
 
-  gids = (uint16_t *) malloc (glyphlen * sizeof (uint16_t));
+  gids = (hb_codepoint_t *) malloc (glyphlen * sizeof (hb_codepoint_t));
   if (!gids) goto dieout;
 
   pg = gids;
diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc
index a56d161..880a6b9 100644
--- a/src/hb-ot-shape-complex-arabic.cc
+++ b/src/hb-ot-shape-complex-arabic.cc
@@ -221,8 +221,8 @@ arabic_fallback_shape (hb_font_t *font, hb_buffer_t *buffer)
   /* Mandatory ligatures */
   buffer->clear_output ();
   for (buffer->idx = 0; buffer->idx + 1 < count;) {
-    uint16_t ligature = get_ligature (buffer->info[buffer->idx].codepoint,
-				      buffer->info[buffer->idx + 1].codepoint);
+    hb_codepoint_t ligature = get_ligature (buffer->info[buffer->idx].codepoint,
+					    buffer->info[buffer->idx + 1].codepoint);
     if (likely (!ligature) || !(hb_font_get_glyph (font, ligature, 0, &glyph))) {
       buffer->next_glyph ();
       continue;
diff --git a/src/hb-ot-shape-complex-misc.cc b/src/hb-ot-shape-complex-misc.cc
index 76cb3a3..c95749a 100644
--- a/src/hb-ot-shape-complex-misc.cc
+++ b/src/hb-ot-shape-complex-misc.cc
@@ -148,8 +148,8 @@ _hb_ot_shape_complex_setup_masks_thai (hb_ot_map_t *map, hb_buffer_t *buffer, hb
     }
 
     /* Is SARA AM. Decompose and reorder. */
-    uint16_t decomposed[2] = {uint16_t (NIKHAHIT_FROM_SARA_AM (u)),
-			      uint16_t (SARA_AA_FROM_SARA_AM (u))};
+    hb_codepoint_t decomposed[2] = {hb_codepoint_t (NIKHAHIT_FROM_SARA_AM (u)),
+				    hb_codepoint_t (SARA_AA_FROM_SARA_AM (u))};
     buffer->replace_glyphs (1, 2, decomposed);
     if (unlikely (buffer->in_error))
       return;
commit d2984a241e4819474d827b1dd5d4b6d76596b3a5
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 23 17:21:14 2012 -0400

    Add map->substitute_closure()

diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index 710cc0a..5675d37 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -125,6 +125,9 @@ struct hb_ot_map_t
 			  void *face_or_font,
 			  hb_buffer_t *buffer) const;
 
+  HB_INTERNAL void substitute_closure (hb_face_t *face,
+				       hb_glyph_map_t *glyphs) const;
+
   hb_mask_t global_mask;
 
   hb_tag_t chosen_script[2];
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index a54e306..a0efe90 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -95,6 +95,21 @@ void hb_ot_map_t::apply (unsigned int table_index,
     apply_lookup_func (face_or_font, buffer, lookups[table_index][i].index, lookups[table_index][i].mask);
 }
 
+void hb_ot_map_t::substitute_closure (hb_face_t *face,
+				      hb_glyph_map_t *glyphs) const
+{
+  unsigned int table_index = 0;
+  unsigned int i = 0;
+
+  for (unsigned int pause_index = 0; pause_index < pauses[table_index].len; pause_index++) {
+    const pause_map_t *pause = &pauses[table_index][pause_index];
+    for (; i < pause->num_lookups; i++)
+      hb_ot_layout_substitute_closure_lookup (face, glyphs, lookups[table_index][i].index);
+  }
+
+  for (; i < lookups[table_index].len; i++)
+    hb_ot_layout_substitute_closure_lookup (face, glyphs, lookups[table_index][i].index);
+}
 
 void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func, void *user_data)
 {



More information about the HarfBuzz mailing list