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

Behdad Esfahbod behdad at kemper.freedesktop.org
Thu Nov 15 18:48:34 PST 2012


 src/Makefile.am                  |    2 
 src/hb-buffer-private.hh         |   39 -------------
 src/hb-buffer.cc                 |   59 ++++++++++++++++++--
 src/hb-buffer.h                  |   58 ++++++++++++++++----
 src/hb-fallback-shape.cc         |    2 
 src/hb-font-private.hh           |    9 +++
 src/hb-font.cc                   |   29 +++++++++-
 src/hb-font.h                    |    7 ++
 src/hb-ot-layout-private.hh      |   10 ---
 src/hb-ot-layout.cc              |   20 +++---
 src/hb-ot-layout.h               |  112 ++++++++++++++++++++++++++++++++++++---
 src/hb-ot-map-private.hh         |    2 
 src/hb-ot-map.cc                 |   15 ++---
 src/hb-ot-shape-complex-indic.cc |    2 
 src/hb-ot-shape-complex-thai.cc  |    2 
 src/hb-ot-shape-private.hh       |   11 +++
 src/hb-ot-shape.cc               |   56 +++++++++++++------
 src/hb-ot.h                      |    1 
 src/hb-set-private.hh            |   35 +++++++++++-
 src/hb-set.cc                    |   86 ++++++++++++++++++++---------
 src/hb-set.h                     |   55 ++++++++++++-------
 src/hb-shape-plan-private.hh     |    3 -
 src/hb-shape-plan.cc             |   23 ++++++--
 src/hb-shape-plan.h              |   50 +++++++++++------
 src/hb-shape.cc                  |    2 
 src/hb-shaper-list.hh            |   15 ++---
 src/hb-shaper-private.hh         |    2 
 src/hb-shaper.cc                 |    2 
 src/hb.h                         |    1 
 src/test-would-substitute.cc     |    2 
 util/hb-ot-shape-closure.cc      |   26 ++++-----
 util/hb-shape.cc                 |    6 ++
 32 files changed, 532 insertions(+), 212 deletions(-)

New commits:
commit 3f82f8ff07a9d16a7c047129658c1bbedfdb5436
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Nov 15 18:45:31 2012 -0800

    Rename hb_buffer_guess_properties() to hb_buffer_guess_segment_properties()

diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index 80ca7ae..13cf4bb 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -114,7 +114,7 @@ struct hb_buffer_t {
   HB_INTERNAL void reverse_range (unsigned int start, unsigned int end);
   HB_INTERNAL void reverse (void);
   HB_INTERNAL void reverse_clusters (void);
-  HB_INTERNAL void guess_properties (void);
+  HB_INTERNAL void guess_segment_properties (void);
 
   HB_INTERNAL void swap_buffers (void);
   HB_INTERNAL void remove_output (void);
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 5d38b3c..0f5a97f 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -491,7 +491,7 @@ hb_buffer_t::merge_out_clusters (unsigned int start,
 }
 
 void
-hb_buffer_t::guess_properties (void)
+hb_buffer_t::guess_segment_properties (void)
 {
   if (unlikely (!len)) return;
   assert (content_type == HB_BUFFER_CONTENT_TYPE_UNICODE);
@@ -886,9 +886,9 @@ hb_buffer_reverse_clusters (hb_buffer_t *buffer)
 }
 
 void
-hb_buffer_guess_properties (hb_buffer_t *buffer)
+hb_buffer_guess_segment_properties (hb_buffer_t *buffer)
 {
-  buffer->guess_properties ();
+  buffer->guess_segment_properties ();
 }
 
 template <typename T>
diff --git a/src/hb-buffer.h b/src/hb-buffer.h
index 255f005..48ec4a5 100644
--- a/src/hb-buffer.h
+++ b/src/hb-buffer.h
@@ -168,7 +168,7 @@ hb_buffer_get_segment_properties (hb_buffer_t *buffer,
 				  hb_segment_properties_t *props);
 
 void
-hb_buffer_guess_properties (hb_buffer_t *buffer);
+hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
 
 
 typedef enum {
diff --git a/src/hb-fallback-shape.cc b/src/hb-fallback-shape.cc
index 3f9024f..989596e 100644
--- a/src/hb-fallback-shape.cc
+++ b/src/hb-fallback-shape.cc
@@ -98,7 +98,7 @@ _hb_fallback_shape (hb_shape_plan_t    *shape_plan,
   hb_codepoint_t space;
   font->get_glyph (' ', 0, &space);
 
-  buffer->guess_properties ();
+  buffer->guess_segment_properties ();
   buffer->clear_positions ();
 
   unsigned int count = buffer->len;
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 7ef35c0..450d609 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -610,7 +610,7 @@ hb_ot_shape_glyphs_closure (hb_font_t          *font,
 {
   hb_ot_shape_plan_t plan;
 
-  buffer->guess_properties ();
+  buffer->guess_segment_properties ();
 
   const char *shapers[] = {"ot", NULL};
   hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props,
diff --git a/src/hb-shape.cc b/src/hb-shape.cc
index 7dfe049..389ce3e 100644
--- a/src/hb-shape.cc
+++ b/src/hb-shape.cc
@@ -255,7 +255,7 @@ hb_shape_full (hb_font_t          *font,
 
   assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE);
 
-  buffer->guess_properties ();
+  buffer->guess_segment_properties ();
 
   hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list);
   hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features);
commit f30641038ba96e83950729b1bd9d86d2e98e46c5
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Nov 15 18:39:46 2012 -0800

    Bunch of independent changes (ouch)
    
    API additions:
    
    	hb_segment_properties_t
    	HB_SEGMENT_PROPERTIES_DEFAULT
    	hb_segment_properties_equal()
    	hb_segment_properties_hash()
    
    	hb_buffer_set_segment_properties()
    	hb_buffer_get_segment_properties()
    
    	hb_ot_layout_glyph_class_t
    
    	hb_shape_plan_t
    	hb_shape_plan_create()
    	hb_shape_plan_create_cached()
    	hb_shape_plan_get_empty()
    	hb_shape_plan_reference()
    	hb_shape_plan_destroy()
    	hb_shape_plan_set_user_data()
    	hb_shape_plan_get_user_data()
    	hb_shape_plan_execute()
    
    	hb_ot_shape_plan_collect_lookups()
    
    API changes:
    
    	Rename hb_ot_layout_feature_get_lookup_indexes() to
    	hb_ot_layout_feature_get_lookups().
    
    New header file:
    
    	hb-shape-plan.h
    
    And a bunch of prototyped but not implemented stuff.  Coming soon.
    (Tests fail because of the prototypes right now.)

diff --git a/src/Makefile.am b/src/Makefile.am
index aca8abf..bb7601e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -43,7 +43,6 @@ HBSOURCES =  \
 	hb-shape.cc \
 	hb-shape-plan-private.hh \
 	hb-shape-plan.cc \
-	hb-shape-plan.h \
 	hb-shaper-list.hh \
 	hb-shaper-impl-private.hh \
 	hb-shaper-private.hh \
@@ -62,6 +61,7 @@ HBHEADERS = \
 	hb-font.h \
 	hb-set.h \
 	hb-shape.h \
+	hb-shape-plan.h \
 	hb-unicode.h \
 	hb-version.h \
 	$(NULL)
diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index 6c1f3a3..80ca7ae 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -36,48 +36,11 @@
 #include "hb-unicode-private.hh"
 
 
-
 ASSERT_STATIC (sizeof (hb_glyph_info_t) == 20);
 ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t));
 
 
 /*
- * hb_segment_properties_t
- */
-
-typedef struct hb_segment_properties_t {
-    hb_direction_t      direction;
-    hb_script_t         script;
-    hb_language_t       language;
-    ASSERT_POD ();
-} hb_segment_properties_t;
-
-#define _HB_BUFFER_PROPS_DEFAULT { HB_DIRECTION_INVALID, HB_SCRIPT_INVALID, HB_LANGUAGE_INVALID }
-
-static inline hb_bool_t
-hb_segment_properties_equal (const hb_segment_properties_t *a,
-			     const hb_segment_properties_t *b)
-{
-  return a->direction == b->direction &&
-	 a->script    == b->script    &&
-	 a->language  == b->language;
-}
-
-
-#if 0
-static inline unsigned int
-hb_segment_properties_hash (const hb_segment_properties_t *p)
-{
-  /* TODO improve */
-  return (unsigned int) p->direction +
-	 (unsigned int) p->script +
-	 (intptr_t) (p->language);
-}
-#endif
-
-
-
-/*
  * hb_buffer_t
  */
 
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index ee5a888..5d38b3c 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -35,6 +35,29 @@
 #define HB_DEBUG_BUFFER (HB_DEBUG+0)
 #endif
 
+
+hb_bool_t
+hb_segment_properties_equal (const hb_segment_properties_t *a,
+			     const hb_segment_properties_t *b)
+{
+  return a->direction == b->direction &&
+	 a->script    == b->script    &&
+	 a->language  == b->language  &&
+	 a->reserved1 == b->reserved1 &&
+	 a->reserved2 == b->reserved2;
+
+}
+
+unsigned int
+hb_segment_properties_hash (const hb_segment_properties_t *p)
+{
+  return (unsigned int) p->direction ^
+	 (unsigned int) p->script ^
+	 (intptr_t) (p->language);
+}
+
+
+
 /* Here is how the buffer works internally:
  *
  * There are two info pointers: info and out_info.  They always have
@@ -151,7 +174,7 @@ hb_buffer_t::clear (void)
   if (unlikely (hb_object_is_inert (this)))
     return;
 
-  hb_segment_properties_t default_props = _HB_BUFFER_PROPS_DEFAULT;
+  hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT;
   props = default_props;
   flags = HB_BUFFER_FLAGS_DEFAULT;
 
@@ -589,7 +612,7 @@ hb_buffer_get_empty (void)
     HB_OBJECT_HEADER_STATIC,
 
     const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
-    _HB_BUFFER_PROPS_DEFAULT,
+    HB_SEGMENT_PROPERTIES_DEFAULT,
     HB_BUFFER_FLAGS_DEFAULT,
 
     HB_BUFFER_CONTENT_TYPE_INVALID,
@@ -726,6 +749,24 @@ hb_buffer_get_language (hb_buffer_t *buffer)
 }
 
 void
+hb_buffer_set_segment_properties (hb_buffer_t *buffer,
+				  const hb_segment_properties_t *props)
+{
+  if (unlikely (hb_object_is_inert (buffer)))
+    return;
+
+  buffer->props = *props;
+}
+
+void
+hb_buffer_get_segment_properties (hb_buffer_t *buffer,
+				  hb_segment_properties_t *props)
+{
+  *props = buffer->props;
+}
+
+
+void
 hb_buffer_set_flags (hb_buffer_t       *buffer,
 		     hb_buffer_flags_t  flags)
 {
diff --git a/src/hb-buffer.h b/src/hb-buffer.h
index cd574c3..255f005 100644
--- a/src/hb-buffer.h
+++ b/src/hb-buffer.h
@@ -41,8 +41,6 @@
 HB_BEGIN_DECLS
 
 
-typedef struct hb_buffer_t hb_buffer_t;
-
 typedef struct hb_glyph_info_t {
   hb_codepoint_t codepoint;
   hb_mask_t      mask;
@@ -64,6 +62,36 @@ typedef struct hb_glyph_position_t {
 } hb_glyph_position_t;
 
 
+typedef struct hb_segment_properties_t {
+  hb_direction_t  direction;
+  hb_script_t     script;
+  hb_language_t   language;
+  /*< private >*/
+  void           *reserved1;
+  void           *reserved2;
+} hb_segment_properties_t;
+
+#define HB_SEGMENT_PROPERTIES_DEFAULT {HB_DIRECTION_INVALID, \
+				       HB_SCRIPT_INVALID, \
+				       HB_LANGUAGE_INVALID, \
+				       NULL, \
+				       NULL}
+
+hb_bool_t
+hb_segment_properties_equal (const hb_segment_properties_t *a,
+			     const hb_segment_properties_t *b);
+
+unsigned int
+hb_segment_properties_hash (const hb_segment_properties_t *p);
+
+
+
+/*
+ * hb_buffer_t
+ */
+
+typedef struct hb_buffer_t hb_buffer_t;
+
 hb_buffer_t *
 hb_buffer_create (void);
 
@@ -127,9 +155,21 @@ void
 hb_buffer_set_language (hb_buffer_t   *buffer,
 			hb_language_t  language);
 
+
 hb_language_t
 hb_buffer_get_language (hb_buffer_t *buffer);
 
+void
+hb_buffer_set_segment_properties (hb_buffer_t *buffer,
+				  const hb_segment_properties_t *props);
+
+void
+hb_buffer_get_segment_properties (hb_buffer_t *buffer,
+				  hb_segment_properties_t *props);
+
+void
+hb_buffer_guess_properties (hb_buffer_t *buffer);
+
 
 typedef enum {
   HB_BUFFER_FLAGS_DEFAULT			= 0x00000000,
@@ -171,9 +211,6 @@ hb_buffer_reverse (hb_buffer_t *buffer);
 void
 hb_buffer_reverse_clusters (hb_buffer_t *buffer);
 
-void
-hb_buffer_guess_properties (hb_buffer_t *buffer);
-
 
 /* Filling the buffer in */
 
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index 16b460d..055933f 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -49,14 +49,6 @@
  * GDEF
  */
 
-typedef enum {
-  HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED	= 0x0001,
-  HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH	= 0x0002,
-  HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE	= 0x0004,
-  HB_OT_LAYOUT_GLYPH_CLASS_MARK		= 0x0008,
-  HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT	= 0x0010
-} hb_ot_layout_glyph_class_t;
-
 
 
 /*
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 0b85dc5..e57b765 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -374,12 +374,12 @@ hb_ot_layout_language_find_feature (hb_face_t    *face,
 }
 
 unsigned int
-hb_ot_layout_feature_get_lookup_indexes (hb_face_t    *face,
-					 hb_tag_t      table_tag,
-					 unsigned int  feature_index,
-					 unsigned int  start_offset,
-					 unsigned int *lookup_count /* IN/OUT */,
-					 unsigned int *lookup_indexes /* OUT */)
+hb_ot_layout_feature_get_lookups (hb_face_t    *face,
+				  hb_tag_t      table_tag,
+				  unsigned int  feature_index,
+				  unsigned int  start_offset,
+				  unsigned int *lookup_count /* IN/OUT */,
+				  unsigned int *lookup_indexes /* OUT */)
 {
   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
   const OT::Feature &f = g.get_feature (feature_index);
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index ac086c9..3f6e5d9 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -50,6 +50,27 @@ HB_BEGIN_DECLS
 hb_bool_t
 hb_ot_layout_has_glyph_classes (hb_face_t *face);
 
+typedef enum {
+  HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED	= 0x0001,
+  HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH	= 0x0002,
+  HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE	= 0x0004,
+  HB_OT_LAYOUT_GLYPH_CLASS_MARK		= 0x0008,
+  HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT	= 0x0010
+} hb_ot_layout_glyph_class_t;
+
+#ifdef HB_NOT_IMPLEMENTED
+hb_ot_layout_glyph_class_t
+hb_ot_layout_get_glyph_class (hb_face_t      *face,
+			      hb_codepoint_t  glyph);
+#endif
+
+#ifdef HB_NOT_IMPLEMENTED
+hb_ot_layout_get_glyphs_in_class (hb_face_t                  *face,
+				  hb_ot_layout_glyph_class_t  klass,
+				  hb_set_t                   *glyphs /* OUT */);
+#endif
+
+
 /* Not that useful.  Provides list of attach points for a glyph that a
  * client may want to cache */
 unsigned int
@@ -154,12 +175,64 @@ hb_ot_layout_language_find_feature (hb_face_t    *face,
 				    unsigned int *feature_index);
 
 unsigned int
-hb_ot_layout_feature_get_lookup_indexes (hb_face_t    *face,
+hb_ot_layout_feature_get_lookups (hb_face_t    *face,
+				  hb_tag_t      table_tag,
+				  unsigned int  feature_index,
+				  unsigned int  start_offset,
+				  unsigned int *lookup_count /* IN/OUT */,
+				  unsigned int *lookup_indexes /* OUT */);
+
+#ifdef HB_NOT_IMPLEMENTED
+void
+hb_ot_layout_collect_lookups (hb_face_t      *face,
+			      hb_tag_t        table_tag,
+			      const hb_tag_t *scripts,
+			      const hb_tag_t *languages,
+			      const hb_tag_t *features,
+			      hb_set_t       *lookup_indexes /* OUT */);
+#endif
+
+void
+hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
+				  hb_tag_t         table_tag,
+				  hb_set_t        *lookup_indexes /* OUT */);
+
+#ifdef HB_NOT_IMPLEMENTED
+void
+hb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
+				    hb_tag_t      table_tag,
+				    unsigned int  lookup_index,
+				    hb_set_t     *glyphs_before, /* OUT. May be NULL */
+				    hb_set_t     *glyphs_input,  /* OUT. May be NULL */
+				    hb_set_t     *glyphs_after,  /* OUT. May be NULL */
+				    hb_set_t     *glyphs_output  /* OUT. May be NULL */);
+#endif
+
+#ifdef HB_NOT_IMPLEMENTED
+typedef struct
+{
+  const hb_codepoint_t *before,
+  unsigned int          before_length,
+  const hb_codepoint_t *input,
+  unsigned int          input_length,
+  const hb_codepoint_t *after,
+  unsigned int          after_length,
+} hb_ot_layout_glyph_sequence_t;
+
+typedef hb_bool_t
+(*hb_ot_layout_glyph_sequence_func_t) (hb_font_t    *font,
+				       hb_tag_t      table_tag,
+				       unsigned int  lookup_index,
+				       const hb_ot_layout_glyph_sequence_t *sequence,
+				       void         *user_data);
+
+void
+hb_ot_layout_lookup_enumerate_sequences (hb_face_t    *face,
 					 hb_tag_t      table_tag,
-					 unsigned int  feature_index,
-					 unsigned int  start_offset,
-					 unsigned int *lookup_count /* IN/OUT */,
-					 unsigned int *lookup_indexes /* OUT */);
+					 unsigned int  lookup_index,
+					 hb_ot_layout_glyph_sequence_func_t callback,
+					 void         *user_data);
+#endif
 
 
 /*
@@ -179,7 +252,21 @@ hb_ot_layout_lookup_would_substitute (hb_face_t            *face,
 void
 hb_ot_layout_lookup_substitute_closure (hb_face_t    *face,
 				        unsigned int  lookup_index,
-				        hb_set_t     *glyphs);
+				        hb_set_t     *glyphs
+					/*TODO , hb_bool_t  inclusive */);
+
+#ifdef HB_NOT_IMPLEMENTED
+/* Note: You better have GDEF when using this API, or marks won't do much. */
+hb_bool_t
+hb_ot_layout_lookup_substitute (hb_font_t            *font,
+				unsigned int          lookup_index,
+				const hb_ot_layout_glyph_sequence_t *sequence,
+				unsigned int          out_size,
+				hb_codepoint_t       *glyphs_out,   /* OUT */
+				unsigned int         *clusters_out, /* OUT */
+				unsigned int         *out_length    /* OUT */);
+#endif
+
 
 /*
  * GPOS
@@ -188,6 +275,15 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t    *face,
 hb_bool_t
 hb_ot_layout_has_positioning (hb_face_t *face);
 
+#ifdef HB_NOT_IMPLEMENTED
+/* Note: You better have GDEF when using this API, or marks won't do much. */
+hb_bool_t
+hb_ot_layout_lookup_position (hb_font_t            *font,
+			      unsigned int          lookup_index,
+			      const hb_ot_layout_glyph_sequence_t *sequence,
+			      hb_glyph_position_t  *positions /* IN / OUT */);
+#endif
+
 
 HB_END_DECLS
 
diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index c7dbea5..b140207 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -115,7 +115,7 @@ struct hb_ot_map_t
     *lookup_count = end - start;
   }
 
-  HB_INTERNAL void substitute_closure (const struct hb_ot_shape_plan_t *plan, hb_face_t *face, hb_set_t *glyphs) const;
+  HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const;
   HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
   HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
 
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index 26ca1a3..62f7904 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -41,11 +41,11 @@ hb_ot_map_t::add_lookups (hb_face_t    *face,
   offset = 0;
   do {
     len = ARRAY_LENGTH (lookup_indices);
-    hb_ot_layout_feature_get_lookup_indexes (face,
-					     table_tags[table_index],
-					     feature_index,
-					     offset, &len,
-					     lookup_indices);
+    hb_ot_layout_feature_get_lookups (face,
+				      table_tags[table_index],
+				      feature_index,
+				      offset, &len,
+				      lookup_indices);
 
     for (unsigned int i = 0; i < len; i++) {
       hb_ot_map_t::lookup_map_t *lookup = lookups[table_index].push ();
@@ -138,11 +138,10 @@ void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_
     hb_ot_layout_position_lookup (font, buffer, lookups[table_index][i].index, lookups[table_index][i].mask);
 }
 
-void hb_ot_map_t::substitute_closure (const hb_ot_shape_plan_t *plan, hb_face_t *face, hb_set_t *glyphs) const
+void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const
 {
-  unsigned int table_index = 0;
   for (unsigned int i = 0; i < lookups[table_index].len; i++)
-    hb_ot_layout_lookup_substitute_closure (face, lookups[table_index][i].index, glyphs);
+    hb_set_add (lookups_out, 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)
diff --git a/src/hb-ot-shape-private.hh b/src/hb-ot-shape-private.hh
index 76bf3ee..23e80b7 100644
--- a/src/hb-ot-shape-private.hh
+++ b/src/hb-ot-shape-private.hh
@@ -46,7 +46,16 @@ struct hb_ot_shape_plan_t
   hb_ot_map_t map;
   const void *data;
 
-  inline void substitute_closure (hb_face_t *face, hb_set_t *glyphs) const { map.substitute_closure (this, face, glyphs); }
+  inline void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const
+  {
+    unsigned int table_index;
+    switch (table_tag) {
+      case HB_OT_TAG_GSUB: table_index = 0; break;
+      case HB_OT_TAG_GPOS: table_index = 1; break;
+      default: return;
+    }
+    map.collect_lookups (table_index, lookups);
+  }
   inline void substitute (hb_font_t *font, hb_buffer_t *buffer) const { map.substitute (this, font, buffer); }
   inline void position (hb_font_t *font, hb_buffer_t *buffer) const { map.position (this, font, buffer); }
 
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 4b9afb7..7ef35c0 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -572,16 +572,35 @@ _hb_ot_shape (hb_shape_plan_t    *shape_plan,
 }
 
 
+void
+hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
+				  hb_tag_t         table_tag,
+				  hb_set_t        *lookup_indexes /* OUT */)
+{
+  HB_SHAPER_DATA_GET (shape_plan)->collect_lookups (table_tag, lookup_indexes);
+}
 
-static inline void
-hb_ot_map_glyphs_dumb (hb_font_t    *font,
-		       hb_buffer_t  *buffer)
+
+/* TODO Move this to hb-ot-shape-normalize, make it do decompose, and make it public. */
+static void
+add_char (hb_font_t          *font,
+	  hb_unicode_funcs_t *unicode,
+	  hb_bool_t           mirror,
+	  hb_codepoint_t      u,
+	  hb_set_t           *glyphs)
 {
-  unsigned int count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
-    font->get_glyph (buffer->info[i].codepoint, 0, &buffer->info[i].codepoint);
+  hb_codepoint_t glyph;
+  if (font->get_glyph (u, 0, &glyph))
+    glyphs->add (glyph);
+  if (mirror)
+  {
+    hb_codepoint_t m = unicode->mirroring (u);
+    if (m != u && font->get_glyph (m, 0, &glyph))
+      glyphs->add (glyph);
+  }
 }
 
+
 void
 hb_ot_shape_glyphs_closure (hb_font_t          *font,
 			    hb_buffer_t        *buffer,
@@ -593,26 +612,27 @@ hb_ot_shape_glyphs_closure (hb_font_t          *font,
 
   buffer->guess_properties ();
 
-  /* TODO cache / ensure correct backend, etc. */
-  hb_shape_plan_t *shape_plan = hb_shape_plan_create (font->face, &buffer->props, features, num_features, NULL);
+  const char *shapers[] = {"ot", NULL};
+  hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props,
+							     features, num_features, shapers);
 
-  /* TODO: normalization? have shapers do closure()? */
-  /* TODO: Deal with mirrored chars? */
-  hb_ot_map_glyphs_dumb (font, buffer);
+  bool mirror = hb_script_get_horizontal_direction (buffer->props.script) == HB_DIRECTION_RTL;
 
-  /* Seed it.  It's user's responsibility to have cleard glyphs
-   * if that's what they desire. */
   unsigned int count = buffer->len;
   for (unsigned int i = 0; i < count; i++)
-    glyphs->add (buffer->info[i].codepoint);
+    add_char (font, buffer->unicode, mirror, buffer->info[i].codepoint, glyphs);
+
+  hb_set_t lookups;
+  lookups.init ();
+  hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, &lookups);
 
   /* And find transitive closure. */
   hb_set_t copy;
   copy.init ();
-
   do {
     copy.set (glyphs);
-    HB_SHAPER_DATA_GET (shape_plan)->substitute_closure (font->face, glyphs);
+    for (hb_codepoint_t lookup_index = -1; hb_set_next (&lookups, &lookup_index);)
+      hb_ot_layout_lookup_substitute_closure (font->face, lookup_index, glyphs);
   } while (!copy.is_equal (glyphs));
 
   hb_shape_plan_destroy (shape_plan);
diff --git a/src/hb-ot.h b/src/hb-ot.h
index 2d750c3..8073906 100644
--- a/src/hb-ot.h
+++ b/src/hb-ot.h
@@ -35,6 +35,7 @@
 
 HB_BEGIN_DECLS
 
+/* TODO remove */
 void
 hb_ot_shape_glyphs_closure (hb_font_t          *font,
 			    hb_buffer_t        *buffer,
diff --git a/src/hb-shape-plan-private.hh b/src/hb-shape-plan-private.hh
index d6a57d6..c5a9927 100644
--- a/src/hb-shape-plan-private.hh
+++ b/src/hb-shape-plan-private.hh
@@ -28,9 +28,8 @@
 #define HB_SHAPE_PLAN_PRIVATE_HH
 
 #include "hb-private.hh"
-
 #include "hb-shape-plan.h"
-
+#include "hb-object-private.hh"
 #include "hb-shaper-private.hh"
 
 
diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc
index 038f6af..d73a828 100644
--- a/src/hb-shape-plan.cc
+++ b/src/hb-shape-plan.cc
@@ -24,8 +24,6 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
-
 #include "hb-shape-plan-private.hh"
 #include "hb-shaper-private.hh"
 #include "hb-font-private.hh"
@@ -119,7 +117,7 @@ hb_shape_plan_get_empty (void)
 
     true, /* default_shaper_list */
     NULL, /* face */
-    _HB_BUFFER_PROPS_DEFAULT, /* props */
+    HB_SEGMENT_PROPERTIES_DEFAULT, /* props */
 
     NULL, /* shaper_func */
 
@@ -153,9 +151,26 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan)
   free (shape_plan);
 }
 
+hb_bool_t
+hb_shape_plan_set_user_data (hb_shape_plan_t    *shape_plan,
+			     hb_user_data_key_t *key,
+			     void *              data,
+			     hb_destroy_func_t   destroy,
+			     hb_bool_t           replace)
+{
+  return hb_object_set_user_data (shape_plan, key, data, destroy, replace);
+}
+
+void *
+hb_shape_plan_get_user_data (hb_shape_plan_t    *shape_plan,
+			     hb_user_data_key_t *key)
+{
+  return hb_object_get_user_data (shape_plan, key);
+}
+
 
 hb_bool_t
-hb_shape_plan_execute (hb_shape_plan      *shape_plan,
+hb_shape_plan_execute (hb_shape_plan_t    *shape_plan,
 		       hb_font_t          *font,
 		       hb_buffer_t        *buffer,
 		       const hb_feature_t *features,
diff --git a/src/hb-shape-plan.h b/src/hb-shape-plan.h
index f1a14a9..1f74ba5 100644
--- a/src/hb-shape-plan.h
+++ b/src/hb-shape-plan.h
@@ -24,52 +24,68 @@
  * Google Author(s): Behdad Esfahbod
  */
 
+#ifndef HB_H_IN
+#error "Include <hb.h> instead."
+#endif
+
 #ifndef HB_SHAPE_PLAN_H
 #define HB_SHAPE_PLAN_H
 
-/* TODO To become public one day */
-
-#include "hb-private.hh"
-
-#include "hb-buffer-private.hh"
+#include "hb-common.h"
+#include "hb-font.h"
 
+HB_BEGIN_DECLS
 
-typedef struct hb_shape_plan_t hb_shape_plan;
-
-/*
- * hb_shape_plan_t
- */
+typedef struct hb_shape_plan_t hb_shape_plan_t;
 
-HB_INTERNAL hb_shape_plan_t *
+hb_shape_plan_t *
 hb_shape_plan_create (hb_face_t                     *face,
 		      const hb_segment_properties_t *props,
 		      const hb_feature_t            *user_features,
 		      unsigned int                   num_user_features,
 		      const char * const            *shaper_list);
 
-HB_INTERNAL hb_shape_plan_t *
+hb_shape_plan_t *
 hb_shape_plan_create_cached (hb_face_t                     *face,
 			     const hb_segment_properties_t *props,
 			     const hb_feature_t            *user_features,
 			     unsigned int                   num_user_features,
 			     const char * const            *shaper_list);
 
-HB_INTERNAL hb_shape_plan_t *
+hb_shape_plan_t *
 hb_shape_plan_get_empty (void);
 
-HB_INTERNAL hb_shape_plan_t *
+hb_shape_plan_t *
 hb_shape_plan_reference (hb_shape_plan_t *shape_plan);
 
-HB_INTERNAL void
+void
 hb_shape_plan_destroy (hb_shape_plan_t *shape_plan);
 
+hb_bool_t
+hb_shape_plan_set_user_data (hb_shape_plan_t    *shape_plan,
+			     hb_user_data_key_t *key,
+			     void *              data,
+			     hb_destroy_func_t   destroy,
+			     hb_bool_t           replace);
+
+void *
+hb_shape_plan_get_user_data (hb_shape_plan_t    *shape_plan,
+			     hb_user_data_key_t *key);
+
 
-HB_INTERNAL hb_bool_t
-hb_shape_plan_execute (hb_shape_plan      *shape_plan,
+hb_bool_t
+hb_shape_plan_execute (hb_shape_plan_t    *shape_plan,
 		       hb_font_t          *font,
 		       hb_buffer_t        *buffer,
 		       const hb_feature_t *features,
 		       unsigned int        num_features);
 
+#ifdef HB_NOT_IMPLEMENTED
+const char *
+hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan);
+#endif
+
+
+HB_END_DECLS
 
 #endif /* HB_SHAPE_PLAN_H */
diff --git a/src/hb-shaper-private.hh b/src/hb-shaper-private.hh
index 186318d..9d30c1e 100644
--- a/src/hb-shaper-private.hh
+++ b/src/hb-shaper-private.hh
@@ -29,8 +29,6 @@
 
 #include "hb-private.hh"
 
-#include "hb-shape-plan.h" /* TODO remove */
-
 typedef hb_bool_t hb_shape_func_t (hb_shape_plan_t    *shape_plan,
 				   hb_font_t          *font,
 				   hb_buffer_t        *buffer,
diff --git a/src/hb-shaper.cc b/src/hb-shaper.cc
index a16ffc8..1c1aed9 100644
--- a/src/hb-shaper.cc
+++ b/src/hb-shaper.cc
@@ -25,8 +25,8 @@
  */
 
 #include "hb-private.hh"
-
 #include "hb-shaper-private.hh"
+#include "hb-atomic-private.hh"
 
 
 static const hb_shaper_pair_t all_shapers[] = {
diff --git a/src/hb.h b/src/hb.h
index d36040e..52c479c 100644
--- a/src/hb.h
+++ b/src/hb.h
@@ -34,6 +34,7 @@
 #include "hb-font.h"
 #include "hb-set.h"
 #include "hb-shape.h"
+#include "hb-shape-plan.h"
 #include "hb-unicode.h"
 #include "hb-version.h"
 
commit 75da37dcb17aacc0be6bb006683a84aa31155938
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Nov 15 18:39:23 2012 -0800

    Minor

diff --git a/util/hb-ot-shape-closure.cc b/util/hb-ot-shape-closure.cc
index 41517f2..fd9756b 100644
--- a/util/hb-ot-shape-closure.cc
+++ b/util/hb-ot-shape-closure.cc
@@ -74,18 +74,18 @@ struct shape_closure_consumer_t : option_group_t
     /* Print it out! */
     bool first = true;
     for (hb_codepoint_t i = -1; hb_set_next (glyphs, &i);)
-      if (hb_set_has (glyphs, i)) {
-        if (first)
-	  first = false;
-	else
-	  printf (" ");
-	char glyph_name[32];
-	if (show_glyph_names) {
-	  hb_font_get_glyph_name (font, i, glyph_name, sizeof (glyph_name));
-	  printf ("%s", glyph_name);
-	} else
-	  printf ("%u", i);
-      }
+    {
+      if (first)
+	first = false;
+      else
+	printf (" ");
+      char glyph_name[32];
+      if (show_glyph_names) {
+	hb_font_get_glyph_name (font, i, glyph_name, sizeof (glyph_name));
+	printf ("%s", glyph_name);
+      } else
+	printf ("%u", i);
+    }
   }
   void finish (const font_options_t *font_opts)
   {
commit e05a999495e6575f7cebd7f35db087d964f11ef6
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Nov 15 16:23:21 2012 -0800

    Add hb_face_[sg]et_glyph_count()

diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index b6dafbf..48fbb0e 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -100,6 +100,7 @@ struct hb_face_t {
 
   unsigned int index;
   mutable unsigned int upem;
+  mutable unsigned int num_glyphs;
 
   struct hb_shaper_data_t shaper_data;
 
@@ -130,8 +131,16 @@ struct hb_face_t {
     return upem;
   }
 
+  inline unsigned int get_num_glyphs (void) const
+  {
+    if (unlikely (num_glyphs == (unsigned int) -1))
+      load_num_glyphs ();
+    return num_glyphs;
+  }
+
   private:
   HB_INTERNAL void load_upem (void) const;
+  HB_INTERNAL void load_num_glyphs (void) const;
 };
 
 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
diff --git a/src/hb-font.cc b/src/hb-font.cc
index 0627032..b59fdeb 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -34,6 +34,7 @@
 #include "hb-blob.h"
 #include "hb-open-file-private.hh"
 #include "hb-ot-head-table.hh"
+#include "hb-ot-maxp-table.hh"
 
 #include "hb-cache-private.hh"
 
@@ -520,6 +521,7 @@ static const hb_face_t _hb_face_nil = {
 
   0,    /* index */
   1000, /* upem */
+  0,    /* num_glyphs */
 
   {
 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
@@ -549,6 +551,7 @@ hb_face_create_for_tables (hb_reference_table_func_t  reference_table_func,
   face->destroy = destroy;
 
   face->upem = 0;
+  face->num_glyphs = (unsigned int) -1;
 
   return face;
 }
@@ -736,7 +739,6 @@ hb_face_get_upem (hb_face_t *face)
   return face->get_upem ();
 }
 
-
 void
 hb_face_t::load_upem (void) const
 {
@@ -746,6 +748,31 @@ hb_face_t::load_upem (void) const
   hb_blob_destroy (head_blob);
 }
 
+void
+hb_face_set_glyph_count (hb_face_t    *face,
+			 unsigned int  glyph_count)
+{
+  if (hb_object_is_inert (face))
+    return;
+
+  face->num_glyphs = glyph_count;
+}
+
+unsigned int
+hb_face_get_glyph_count (hb_face_t *face)
+{
+  return face->get_num_glyphs ();
+}
+
+void
+hb_face_t::load_num_glyphs (void) const
+{
+  hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>::sanitize (reference_table (HB_OT_TAG_maxp));
+  const OT::maxp *maxp_table = OT::Sanitizer<OT::maxp>::lock_instance (maxp_blob);
+  num_glyphs = maxp_table->get_num_glyphs ();
+  hb_blob_destroy (maxp_blob);
+}
+
 
 /*
  * hb_font_t
diff --git a/src/hb-font.h b/src/hb-font.h
index d796856..88d4895 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -105,6 +105,13 @@ hb_face_set_upem (hb_face_t    *face,
 unsigned int
 hb_face_get_upem (hb_face_t *face);
 
+void
+hb_face_set_glyph_count (hb_face_t    *face,
+			 unsigned int  glyph_count);
+
+unsigned int
+hb_face_get_glyph_count (hb_face_t *face);
+
 
 /*
  * hb_font_funcs_t
commit aec89de5641fbe1c3031d63dd5f40ec99bf2a538
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Nov 15 16:15:42 2012 -0800

    Add / modify set API a bit

diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index ee0796e..4b9afb7 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -613,7 +613,7 @@ hb_ot_shape_glyphs_closure (hb_font_t          *font,
   do {
     copy.set (glyphs);
     HB_SHAPER_DATA_GET (shape_plan)->substitute_closure (font->face, glyphs);
-  } while (!copy.equal (glyphs));
+  } while (!copy.is_equal (glyphs));
 
   hb_shape_plan_destroy (shape_plan);
 }
diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh
index 43cf925..c736b69 100644
--- a/src/hb-set-private.hh
+++ b/src/hb-set-private.hh
@@ -147,7 +147,7 @@ struct hb_set_t
   inline void clear (void) {
     memset (elts, 0, sizeof elts);
   }
-  inline bool empty (void) const {
+  inline bool is_empty (void) const {
     for (unsigned int i = 0; i < ARRAY_LENGTH (elts); i++)
       if (elts[i])
         return false;
@@ -161,6 +161,7 @@ struct hb_set_t
   }
   inline void add_range (hb_codepoint_t a, hb_codepoint_t b)
   {
+    /* TODO Speedup */
     for (unsigned int i = a; i < b + 1; i++)
       add (i);
   }
@@ -169,6 +170,12 @@ struct hb_set_t
     if (unlikely (g > MAX_G)) return;
     elt (g) &= ~mask (g);
   }
+  inline void del_range (hb_codepoint_t a, hb_codepoint_t b)
+  {
+    /* TODO Speedup */
+    for (unsigned int i = a; i < b + 1; i++)
+      del (i);
+  }
   inline bool has (hb_codepoint_t g) const
   {
     if (unlikely (g > MAX_G)) return false;
@@ -185,7 +192,7 @@ struct hb_set_t
         return true;
     return false;
   }
-  inline bool equal (const hb_set_t *other) const
+  inline bool is_equal (const hb_set_t *other) const
   {
     for (unsigned int i = 0; i < ELTS; i++)
       if (elts[i] != other->elts[i])
@@ -217,7 +224,7 @@ struct hb_set_t
     for (unsigned int i = 0; i < ELTS; i++)
       elts[i] ^= other->elts[i];
   }
-  inline bool next (hb_codepoint_t *codepoint)
+  inline bool next (hb_codepoint_t *codepoint) const
   {
     if (unlikely (*codepoint == SENTINEL)) {
       hb_codepoint_t i = get_min ();
@@ -234,6 +241,28 @@ struct hb_set_t
       }
     return false;
   }
+  inline bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
+  {
+    hb_codepoint_t i;
+
+    i = *last;
+    if (!next (&i))
+      return false;
+
+    *last = *first = i;
+    while (next (&i) && i == *last + 1)
+      (*last)++;
+
+    return true;
+  }
+
+  inline unsigned int get_population (void) const
+  {
+    unsigned int count = 0;
+    for (unsigned int i = 0; i < ELTS; i++)
+      count += _hb_popcount32 (elts[i]);
+    return count;
+  }
   inline hb_codepoint_t get_min (void) const
   {
     for (unsigned int i = 0; i < ELTS; i++)
diff --git a/src/hb-set.cc b/src/hb-set.cc
index 4225e3c..37866c4 100644
--- a/src/hb-set.cc
+++ b/src/hb-set.cc
@@ -32,7 +32,7 @@
 
 
 hb_set_t *
-hb_set_create ()
+hb_set_create (void)
 {
   hb_set_t *set;
 
@@ -73,25 +73,25 @@ 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)
+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)
+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 HB_UNUSED)
+hb_set_allocation_successful (const hb_set_t  *set HB_UNUSED)
 {
   return true;
 }
@@ -103,13 +103,13 @@ hb_set_clear (hb_set_t *set)
 }
 
 hb_bool_t
-hb_set_empty (hb_set_t *set)
+hb_set_is_empty (const hb_set_t *set)
 {
-  return set->empty ();
+  return set->is_empty ();
 }
 
 hb_bool_t
-hb_set_has (hb_set_t       *set,
+hb_set_has (const hb_set_t *set,
 	    hb_codepoint_t  codepoint)
 {
   return set->has (codepoint);
@@ -123,69 +123,99 @@ hb_set_add (hb_set_t       *set,
 }
 
 void
+hb_set_add_range (hb_set_t       *set,
+		  hb_codepoint_t  first,
+		  hb_codepoint_t  last)
+{
+  set->add_range (first, last);
+}
+
+void
 hb_set_del (hb_set_t       *set,
 	    hb_codepoint_t  codepoint)
 {
   set->del (codepoint);
 }
 
+void
+hb_set_del_range (hb_set_t       *set,
+		  hb_codepoint_t  first,
+		  hb_codepoint_t  last)
+{
+  set->del_range (first, last);
+}
+
 hb_bool_t
-hb_set_equal (hb_set_t *set,
-	      hb_set_t *other)
+hb_set_is_equal (const hb_set_t *set,
+		 const hb_set_t *other)
 {
-  return set->equal (other);
+  return set->is_equal (other);
 }
 
 void
-hb_set_set (hb_set_t *set,
-	    hb_set_t *other)
+hb_set_set (hb_set_t       *set,
+	    const hb_set_t *other)
 {
   set->set (other);
 }
 
 void
-hb_set_union (hb_set_t *set,
-	      hb_set_t *other)
+hb_set_union (hb_set_t       *set,
+	      const hb_set_t *other)
 {
   set->union_ (other);
 }
 
 void
-hb_set_intersect (hb_set_t *set,
-		  hb_set_t *other)
+hb_set_intersect (hb_set_t       *set,
+		  const hb_set_t *other)
 {
   set->intersect (other);
 }
 
 void
-hb_set_subtract (hb_set_t *set,
-		 hb_set_t *other)
+hb_set_subtract (hb_set_t       *set,
+		 const hb_set_t *other)
 {
   set->subtract (other);
 }
 
 void
-hb_set_symmetric_difference (hb_set_t *set,
-			     hb_set_t *other)
+hb_set_symmetric_difference (hb_set_t       *set,
+			     const hb_set_t *other)
 {
   set->symmetric_difference (other);
 }
 
+unsigned int
+hb_set_population (const hb_set_t *set)
+{
+  return set->get_population ();
+}
+
 hb_codepoint_t
-hb_set_min (hb_set_t *set)
+hb_set_get_min (const hb_set_t *set)
 {
   return set->get_min ();
 }
 
 hb_codepoint_t
-hb_set_max (hb_set_t *set)
+hb_set_get_max (const hb_set_t *set)
 {
   return set->get_max ();
 }
 
 hb_bool_t
-hb_set_next (hb_set_t       *set,
+hb_set_next (const hb_set_t *set,
 	     hb_codepoint_t *codepoint)
 {
   return set->next (codepoint);
 }
+
+hb_bool_t
+hb_set_next_range (const hb_set_t *set,
+		   hb_codepoint_t *first,
+		   hb_codepoint_t *last)
+{
+  return set->next_range (first, last);
+}
diff --git a/src/hb-set.h b/src/hb-set.h
index 1838889..06f3582 100644
--- a/src/hb-set.h
+++ b/src/hb-set.h
@@ -65,16 +65,16 @@ hb_set_get_user_data (hb_set_t           *set,
 
 /* Returns false if allocation has failed before */
 hb_bool_t
-hb_set_allocation_successful (hb_set_t  *set);
+hb_set_allocation_successful (const hb_set_t *set);
 
 void
 hb_set_clear (hb_set_t *set);
 
 hb_bool_t
-hb_set_empty (hb_set_t *set);
+hb_set_is_empty (const hb_set_t *set);
 
 hb_bool_t
-hb_set_has (hb_set_t       *set,
+hb_set_has (const hb_set_t *set,
 	    hb_codepoint_t  codepoint);
 
 /* Right now limited to 16-bit integers.  Eventually will do full codepoint range, sans -1
@@ -84,47 +84,64 @@ hb_set_add (hb_set_t       *set,
 	    hb_codepoint_t  codepoint);
 
 void
+hb_set_add_range (hb_set_t       *set,
+		  hb_codepoint_t  first,
+		  hb_codepoint_t  last);
+
+void
 hb_set_del (hb_set_t       *set,
 	    hb_codepoint_t  codepoint);
 
+void
+hb_set_del_range (hb_set_t       *set,
+		  hb_codepoint_t  first,
+		  hb_codepoint_t  last);
+
 hb_bool_t
-hb_set_equal (hb_set_t *set,
-	      hb_set_t *other);
+hb_set_is_equal (const hb_set_t *set,
+		 const hb_set_t *other);
 
 void
-hb_set_set (hb_set_t *set,
-	    hb_set_t *other);
+hb_set_set (hb_set_t       *set,
+	    const hb_set_t *other);
 
 void
-hb_set_union (hb_set_t *set,
-	      hb_set_t *other);
+hb_set_union (hb_set_t       *set,
+	      const hb_set_t *other);
 
 void
-hb_set_intersect (hb_set_t *set,
-		  hb_set_t *other);
+hb_set_intersect (hb_set_t       *set,
+		  const hb_set_t *other);
 
 void
-hb_set_subtract (hb_set_t *set,
-		 hb_set_t *other);
+hb_set_subtract (hb_set_t       *set,
+		 const hb_set_t *other);
 
 void
-hb_set_symmetric_difference (hb_set_t *set,
-			     hb_set_t *other);
+hb_set_symmetric_difference (hb_set_t       *set,
+			     const hb_set_t *other);
+
+unsigned int
+hb_set_population (const hb_set_t *set);
 
 /* Returns -1 if set empty. */
 hb_codepoint_t
-hb_set_min (hb_set_t *set);
+hb_set_get_min (const hb_set_t *set);
 
 /* Returns -1 if set empty. */
 hb_codepoint_t
-hb_set_max (hb_set_t *set);
+hb_set_get_max (const hb_set_t *set);
 
 /* Pass -1 in to get started. */
 hb_bool_t
-hb_set_next (hb_set_t       *set,
+hb_set_next (const hb_set_t *set,
 	     hb_codepoint_t *codepoint);
 
-/* TODO: Add faster iteration API? */
+/* Pass -1 for first and last to get started. */
+hb_bool_t
+hb_set_next_range (const hb_set_t *set,
+		   hb_codepoint_t *first,
+		   hb_codepoint_t *last);
 
 
 HB_END_DECLS
diff --git a/util/hb-ot-shape-closure.cc b/util/hb-ot-shape-closure.cc
index 2289605..41517f2 100644
--- a/util/hb-ot-shape-closure.cc
+++ b/util/hb-ot-shape-closure.cc
@@ -68,7 +68,7 @@ struct shape_closure_consumer_t : option_group_t
     hb_set_clear (glyphs);
     shaper.shape_closure (text, text_len, font, buffer, glyphs);
 
-    if (hb_set_empty (glyphs))
+    if (hb_set_is_empty (glyphs))
       return;
 
     /* Print it out! */
commit c54599ad269380c7aa28d885fcfd660fc2c10a7b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Nov 15 16:14:23 2012 -0800

    Minor

diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 4ac1fbe..ee5a888 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -570,7 +570,7 @@ void hb_buffer_t::deallocate_var_all (void)
 /* Public API */
 
 hb_buffer_t *
-hb_buffer_create ()
+hb_buffer_create (void)
 {
   hb_buffer_t *buffer;
 
diff --git a/src/hb-buffer.h b/src/hb-buffer.h
index db9b40f..cd574c3 100644
--- a/src/hb-buffer.h
+++ b/src/hb-buffer.h
@@ -232,12 +232,10 @@ hb_buffer_get_glyph_positions (hb_buffer_t  *buffer,
 void
 hb_buffer_normalize_glyphs (hb_buffer_t *buffer);
 
-/*
- * NOT IMPLEMENTED
- void
- hb_buffer_normalize_characters (hb_buffer_t *buffer);
-*/
 
+/*
+ * Serialize
+ */
 
 typedef enum {
   HB_BUFFER_SERIALIZE_FLAGS_DEFAULT		= 0x00000000,
commit d1aa143ca434fe272de21d2002768c83387b583b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Nov 15 15:38:08 2012 -0800

    [Thai] Remove U+0E2C from "AC" consonants
    
    WinXP doesn't include it.

diff --git a/src/hb-ot-shape-complex-thai.cc b/src/hb-ot-shape-complex-thai.cc
index 87fe521..0760891 100644
--- a/src/hb-ot-shape-complex-thai.cc
+++ b/src/hb-ot-shape-complex-thai.cc
@@ -46,7 +46,7 @@ enum thai_consonant_type_t
 static thai_consonant_type_t
 get_consonant_type (hb_codepoint_t u)
 {
-  if (u == 0x0E1B || u == 0x0E1D || u == 0x0E1F || u == 0x0E2C)
+  if (u == 0x0E1B || u == 0x0E1D || u == 0x0E1F/* || u == 0x0E2C*/)
     return AC;
   if (u == 0x0E0D || u == 0x0E10)
     return RC;
commit 362a990b2246f5448ecb9d600761f710aea7d42d
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Nov 15 14:57:31 2012 -0800

    Rename hb_ot_layout_would_substitute_lookup() and hb_ot_layout_substitute_closure_lookup()
    
    To match upcoming API.

diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index 70fda8e..16b460d 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -138,7 +138,7 @@ static inline uint8_t allocate_lig_id (hb_buffer_t *buffer) {
 
 
 HB_INTERNAL hb_bool_t
-hb_ot_layout_would_substitute_lookup_fast (hb_face_t            *face,
+hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
 					   unsigned int          lookup_index,
 					   const hb_codepoint_t *glyphs,
 					   unsigned int          glyphs_length,
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index e241e33..0b85dc5 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -399,18 +399,18 @@ hb_ot_layout_has_substitution (hb_face_t *face)
 }
 
 hb_bool_t
-hb_ot_layout_would_substitute_lookup (hb_face_t            *face,
+hb_ot_layout_lookup_would_substitute (hb_face_t            *face,
 				      unsigned int          lookup_index,
 				      const hb_codepoint_t *glyphs,
 				      unsigned int          glyphs_length,
 				      hb_bool_t             zero_context)
 {
   if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return false;
-  return hb_ot_layout_would_substitute_lookup_fast (face, lookup_index, glyphs, glyphs_length, zero_context);
+  return hb_ot_layout_lookup_would_substitute_fast (face, lookup_index, glyphs, glyphs_length, zero_context);
 }
 
 hb_bool_t
-hb_ot_layout_would_substitute_lookup_fast (hb_face_t            *face,
+hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
 					   unsigned int          lookup_index,
 					   const hb_codepoint_t *glyphs,
 					   unsigned int          glyphs_length,
@@ -452,7 +452,7 @@ hb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer)
 }
 
 void
-hb_ot_layout_substitute_closure_lookup (hb_face_t    *face,
+hb_ot_layout_lookup_substitute_closure (hb_face_t    *face,
 				        unsigned int  lookup_index,
 				        hb_set_t     *glyphs)
 {
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index d431a38..ac086c9 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -170,14 +170,14 @@ hb_bool_t
 hb_ot_layout_has_substitution (hb_face_t *face);
 
 hb_bool_t
-hb_ot_layout_would_substitute_lookup (hb_face_t            *face,
+hb_ot_layout_lookup_would_substitute (hb_face_t            *face,
 				      unsigned int          lookup_index,
 				      const hb_codepoint_t *glyphs,
 				      unsigned int          glyphs_length,
 				      hb_bool_t             zero_context);
 
 void
-hb_ot_layout_substitute_closure_lookup (hb_face_t    *face,
+hb_ot_layout_lookup_substitute_closure (hb_face_t    *face,
 				        unsigned int  lookup_index,
 				        hb_set_t     *glyphs);
 
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index 024b7df..26ca1a3 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -142,7 +142,7 @@ void hb_ot_map_t::substitute_closure (const hb_ot_shape_plan_t *plan, hb_face_t
 {
   unsigned int table_index = 0;
   for (unsigned int i = 0; i < lookups[table_index].len; i++)
-    hb_ot_layout_substitute_closure_lookup (face, lookups[table_index][i].index, glyphs);
+    hb_ot_layout_lookup_substitute_closure (face, lookups[table_index][i].index, glyphs);
 }
 
 void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func)
diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index c5a23b6..eaa77b7 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -269,7 +269,7 @@ struct would_substitute_feature_t
 				hb_face_t         *face) const
   {
     for (unsigned int i = 0; i < count; i++)
-      if (hb_ot_layout_would_substitute_lookup_fast (face, lookups[i].index, glyphs, glyphs_count, zero_context))
+      if (hb_ot_layout_lookup_would_substitute_fast (face, lookups[i].index, glyphs, glyphs_count, zero_context))
 	return true;
     return false;
   }
diff --git a/src/test-would-substitute.cc b/src/test-would-substitute.cc
index d15aec4..4731e26 100644
--- a/src/test-would-substitute.cc
+++ b/src/test-would-substitute.cc
@@ -99,5 +99,5 @@ main (int argc, char **argv)
       (argc > 4 &&
        !hb_font_glyph_from_string (font, argv[4], -1, &glyphs[1])))
     return 2;
-  return !hb_ot_layout_would_substitute_lookup (face, strtol (argv[2], NULL, 0), glyphs, len, false);
+  return !hb_ot_layout_lookup_would_substitute (face, strtol (argv[2], NULL, 0), glyphs, len, false);
 }
commit a4bef84e375b090c1bc7e4221b8e0ee435dfcbba
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Nov 15 13:29:51 2012 -0800

    [util] Make hb-shape err if output-format is not understood
    
    And list supported formats.

diff --git a/util/hb-shape.cc b/util/hb-shape.cc
index ef926da..ca94152 100644
--- a/util/hb-shape.cc
+++ b/util/hb-shape.cc
@@ -45,6 +45,12 @@ struct output_buffer_t
       output_format = HB_BUFFER_SERIALIZE_FORMAT_TEXT;
     else
       output_format = hb_buffer_serialize_format_from_string (options.output_format, -1);
+    if (!hb_buffer_serialize_format_to_string (output_format))
+    {
+      fail (false, "Unknown output format `%s'; supported formats are: %s",
+	    options.output_format,
+	    g_strjoinv (" / ", (gchar**) hb_buffer_serialize_list_formats ()));
+    }
 
     unsigned int flags = HB_BUFFER_SERIALIZE_FLAGS_DEFAULT;
     if (!format.show_glyph_names)
commit 3cec819d39e45470d03085bb6fa132882cc85943
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Nov 15 13:15:39 2012 -0800

    Make the OT shaper default, even if CoreText or Uniscribe is enabled

diff --git a/src/hb-shaper-list.hh b/src/hb-shaper-list.hh
index 6c02de4..b9c029e 100644
--- a/src/hb-shaper-list.hh
+++ b/src/hb-shaper-list.hh
@@ -29,15 +29,11 @@
 #endif /* HB_SHAPER_LIST_HH */ /* Dummy header guards */
 
 /* v--- Add new shapers in the right place here. */
+
 #ifdef HAVE_GRAPHITE2
+/* Only picks up fonts that have a "Silf" table. */
 HB_SHAPER_IMPLEMENT (graphite2)
 #endif
-#ifdef HAVE_UNISCRIBE
-HB_SHAPER_IMPLEMENT (uniscribe)
-#endif
-#ifdef HAVE_CORETEXT
-HB_SHAPER_IMPLEMENT (coretext)
-#endif
 
 #ifdef HAVE_OT
 HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */
@@ -46,9 +42,14 @@ HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */
 #ifdef HAVE_HB_OLD
 HB_SHAPER_IMPLEMENT (old)
 #endif
-
 #ifdef HAVE_ICU_LE
 HB_SHAPER_IMPLEMENT (icu_le)
 #endif
+#ifdef HAVE_UNISCRIBE
+HB_SHAPER_IMPLEMENT (uniscribe)
+#endif
+#ifdef HAVE_CORETEXT
+HB_SHAPER_IMPLEMENT (coretext)
+#endif
 
 HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */
commit 072ae7a982bf640804eee0b41525e7c328806bf5
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Nov 15 13:14:12 2012 -0800

    Add hb_buffer_serialize_list_formats()

diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index a599153..4ac1fbe 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -1035,6 +1035,12 @@ static const char *serialize_formats[] = {
   NULL
 };
 
+const char **
+hb_buffer_serialize_list_formats (void)
+{
+  return serialize_formats;
+}
+
 hb_buffer_serialize_format_t
 hb_buffer_serialize_format_from_string (const char *str, int len)
 {
diff --git a/src/hb-buffer.h b/src/hb-buffer.h
index ba9cd1d..db9b40f 100644
--- a/src/hb-buffer.h
+++ b/src/hb-buffer.h
@@ -259,6 +259,9 @@ hb_buffer_serialize_format_from_string (const char *str, int len);
 const char *
 hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format);
 
+const char **
+hb_buffer_serialize_list_formats (void);
+
 /* Returns number of items, starting at start, that were serialized. */
 unsigned int
 hb_buffer_serialize_glyphs (hb_buffer_t *buffer,



More information about the HarfBuzz mailing list