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

Behdad Esfahbod behdad at kemper.freedesktop.org
Thu May 5 12:15:01 PDT 2011


 TODO                     |    9 ---
 src/hb-common.cc         |   52 +++++++++-----------
 src/hb-mutex-private.hh  |   54 +++++++++++++++++++++
 src/hb-object-private.hh |   32 +++++++-----
 src/hb-ot-map-private.hh |   26 +++-------
 src/hb-ot-map.cc         |   66 +++++++++++++-------------
 src/hb-ot-shape.cc       |    2 
 src/hb-private.hh        |  119 ++++++++++++++++++++++++++++-------------------
 test/test-object.c       |    4 +
 9 files changed, 221 insertions(+), 143 deletions(-)

New commits:
commit b8d6183ebc4697a434776cf2aec7857d63a7d881
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 5 15:14:04 2011 -0400

    Use threadsafe set implementation for hb_language lookups
    
    Note that the static variable has to be a global static, as gcc
    implements local statics differently and that would require linking
    to libstdc++, which we don't want.

diff --git a/src/hb-common.cc b/src/hb-common.cc
index 67988c3..368789a 100644
--- a/src/hb-common.cc
+++ b/src/hb-common.cc
@@ -28,6 +28,8 @@
 
 #include "hb-private.hh"
 
+#include "hb-mutex-private.hh"
+
 HB_BEGIN_DECLS
 
 
@@ -155,11 +157,11 @@ struct hb_language_item_t {
   void finish (void) { free (lang); }
 };
 
+static hb_threadsafe_set_t<hb_language_item_t> langs;
+
 hb_language_t
 hb_language_from_string (const char *str)
 {
-  static hb_set_t<hb_language_item_t> langs;
-
   if (!str || !*str)
     return NULL;
 
commit d37486d87b65c5abaaa2998fa5c9e48eedde0933
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 5 15:07:54 2011 -0400

    Add hb_threadsafe_set_t

diff --git a/src/hb-mutex-private.hh b/src/hb-mutex-private.hh
index cf5beb1..65e5892 100644
--- a/src/hb-mutex-private.hh
+++ b/src/hb-mutex-private.hh
@@ -110,4 +110,58 @@ struct hb_static_mutex_t : hb_mutex_t
 
 HB_END_DECLS
 
+
+template <typename item_t>
+struct hb_threadsafe_set_t
+{
+  hb_set_t <item_t> set;
+  hb_static_mutex_t mutex;
+
+  template <typename T>
+  inline item_t *insert (T v)
+  {
+    hb_mutex_lock (&mutex);
+    item_t *item = set.insert (v);
+    hb_mutex_unlock (&mutex);
+    return item;
+  }
+
+  template <typename T>
+  inline void remove (T v)
+  {
+    hb_mutex_lock (&mutex);
+    set.remove (v);
+    hb_mutex_unlock (&mutex);
+  }
+
+  template <typename T>
+  inline item_t *find (T v)
+  {
+    hb_mutex_lock (&mutex);
+    item_t *item = set.find (v);
+    hb_mutex_unlock (&mutex);
+    return item;
+  }
+
+  template <typename T>
+  inline item_t *find_or_insert (T v) {
+    hb_mutex_lock (&mutex);
+    item_t *item = set.find_or_insert (v);
+    hb_mutex_unlock (&mutex);
+    return item;
+  }
+
+  void finish (void) {
+    hb_mutex_lock (&mutex);
+    set.finish ();
+    hb_mutex_unlock (&mutex);
+  }
+
+};
+
+
+HB_BEGIN_DECLS
+
+HB_END_DECLS
+
 #endif /* HB_MUTEX_PRIVATE_HH */
diff --git a/src/hb-private.hh b/src/hb-private.hh
index d31e014..577389d 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -324,8 +324,6 @@ struct hb_set_t
 {
   hb_array_t <item_t> items;
 
-  public:
-
   template <typename T>
   inline item_t *insert (T v)
   {
@@ -370,6 +368,7 @@ struct hb_set_t
   void finish (void) {
     for (unsigned i = 0; i < items.len; i++)
       items[i].finish ();
+    items.shrink (0);
   }
 
 };
commit b45f32ee4e599c515ce93e44315283d236b073bb
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 5 15:00:43 2011 -0400

    Use hb_array_t for hb_language_t mapping

diff --git a/src/hb-common.cc b/src/hb-common.cc
index b75146d..67988c3 100644
--- a/src/hb-common.cc
+++ b/src/hb-common.cc
@@ -136,40 +136,36 @@ lang_hash (const void *key)
 #endif
 
 
+struct hb_language_item_t {
+
+  hb_language_t lang;
+
+  inline bool operator == (const char *s) const {
+    return lang_equal (lang, s);
+  }
+
+  inline hb_language_item_t & operator = (const char *s) {
+    lang = (hb_language_t) strdup (s);
+    for (unsigned char *p = (unsigned char *) lang; *p; p++)
+      *p = canon_map[*p];
+
+    return *this;
+  }
+
+  void finish (void) { free (lang); }
+};
+
 hb_language_t
 hb_language_from_string (const char *str)
 {
-  static unsigned int num_langs;
-  static unsigned int num_alloced;
-  static hb_language_t *langs;
-  unsigned int i;
-  unsigned char *p;
-
-  /* TODO Use a hash table or something */
+  static hb_set_t<hb_language_item_t> langs;
 
   if (!str || !*str)
     return NULL;
 
-  for (i = 0; i < num_langs; i++)
-    if (lang_equal (str, langs[i]->s))
-      return langs[i];
-
-  if (unlikely (num_langs == num_alloced)) {
-    unsigned int new_alloced = 2 * (8 + num_alloced);
-    hb_language_t *new_langs = (hb_language_t *) realloc (langs, new_alloced * sizeof (langs[0]));
-    if (!new_langs)
-      return NULL;
-    num_alloced = new_alloced;
-    langs = new_langs;
-  }
-
-  langs[i] = (hb_language_t) strdup (str);
-  for (p = (unsigned char *) langs[i]->s; *p; p++)
-    *p = canon_map[*p];
-
-  num_langs++;
+  hb_language_item_t *item = langs.find_or_insert (str);
 
-  return langs[i];
+  return likely (item) ? item->lang : NULL;
 }
 
 const char *
diff --git a/src/hb-object-private.hh b/src/hb-object-private.hh
index 1add2e7..dc7dba9 100644
--- a/src/hb-object-private.hh
+++ b/src/hb-object-private.hh
@@ -132,11 +132,11 @@ struct hb_user_data_array_t {
       return true;
     }
     hb_user_data_item_t item = {key, data, destroy};
-    return items.insert (item);
+    return !!items.insert (item);
   }
 
   inline void *get (hb_user_data_key_t *key) {
-    hb_user_data_item_t *item = items.get (key);
+    hb_user_data_item_t *item = items.find (key);
     return item ? item->data : NULL;
   }
 
diff --git a/src/hb-private.hh b/src/hb-private.hh
index c37518d..d31e014 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -327,16 +327,16 @@ struct hb_set_t
   public:
 
   template <typename T>
-  inline bool insert (T v)
+  inline item_t *insert (T v)
   {
     item_t *item = items.find (v);
     if (item)
       item->finish ();
     else
       item = items.push ();
-    if (unlikely (!item)) return false;
+    if (unlikely (!item)) return NULL;
     *item = v;
-    return true;
+    return item;
   }
 
   template <typename T>
@@ -351,11 +351,22 @@ struct hb_set_t
   }
 
   template <typename T>
-  inline item_t *get (T v)
+  inline item_t *find (T v)
   {
     return items.find (v);
   }
 
+  template <typename T>
+  inline item_t *find_or_insert (T v) {
+    item_t *item = find (v);
+    if (!item) {
+      item = items.push ();
+      if (likely (item))
+        *item = v;
+    }
+    return item;
+  }
+
   void finish (void) {
     for (unsigned i = 0; i < items.len; i++)
       items[i].finish ();
commit 21d2c92fdf7307c7117f8948021f0dd7d5a5d2a3
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 5 14:47:53 2011 -0400

    Move code around

diff --git a/src/hb-object-private.hh b/src/hb-object-private.hh
index ffe87b4..1add2e7 100644
--- a/src/hb-object-private.hh
+++ b/src/hb-object-private.hh
@@ -106,20 +106,20 @@ typedef struct {
 
 /* XXX make this thread-safe, somehow! */
 
-struct hb_user_data_t {
-  hb_user_data_key_t *key;
-  void *data;
-  hb_destroy_func_t destroy;
+struct hb_user_data_array_t {
 
-  inline bool operator == (hb_user_data_key_t *other_key) const { return key == other_key; }
-  inline bool operator == (hb_user_data_t &other) const { return key == other.key; }
+  struct hb_user_data_item_t {
+    hb_user_data_key_t *key;
+    void *data;
+    hb_destroy_func_t destroy;
 
-  void finish (void) { if (destroy) destroy (data); }
-};
+    inline bool operator == (hb_user_data_key_t *other_key) const { return key == other_key; }
+    inline bool operator == (hb_user_data_item_t &other) const { return key == other.key; }
 
-struct hb_user_data_array_t {
+    void finish (void) { if (destroy) destroy (data); }
+  };
 
-  hb_set_t<hb_user_data_t> items;
+  hb_set_t<hb_user_data_item_t> items;
 
   inline bool set (hb_user_data_key_t *key,
 		   void *              data,
@@ -131,13 +131,13 @@ struct hb_user_data_array_t {
       items.remove (key);
       return true;
     }
-    hb_user_data_t user_data = {key, data, destroy};
-    return items.insert (user_data);
+    hb_user_data_item_t item = {key, data, destroy};
+    return items.insert (item);
   }
 
   inline void *get (hb_user_data_key_t *key) {
-    hb_user_data_t *user_data = items.get (key);
-    return user_data ? user_data->data : NULL;
+    hb_user_data_item_t *item = items.get (key);
+    return item ? item->data : NULL;
   }
 
   void finish (void) { items.finish (); }
commit 448ea9bf63104d39f87fff66219034222fa632b8
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 5 14:39:24 2011 -0400

    [TODO] Remove done items

diff --git a/TODO b/TODO
index e95dd4f..1152d5e 100644
--- a/TODO
+++ b/TODO
@@ -7,8 +7,6 @@ General fixes:
 
 - Fix tt kern on/off and GPOS interaction
 
-- Remove fixed-size feature/lookup arrays in hb-ot-map
-
 API issues to fix before 1.0:
 ============================
 
@@ -52,16 +50,9 @@ hb-view enhancements:
 - Add XML and JSON formats
 
 
-Build fixes:
-===========
-
-- GNOME Bug 612402 - (hb-arm) HarfBuzz compilation fix for arm
-
-
 Optimizations:
 =============
 
 - Avoid allocating blob objects internally for for_data() faces?
 
 - Add caching layer to hb-ft
-
commit 265ac614ea6d26041c7d64739098b76a82bbc4f4
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 5 14:38:16 2011 -0400

    Replace fixed-size lookup_maps array with hb_array_t

diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index bd4e868..2a74138 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -36,8 +36,6 @@
 HB_BEGIN_DECLS
 
 
-#define MAX_LOOKUPS 1000 /* FIXME */
-
 static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
 
 struct hb_ot_map_t {
@@ -113,12 +111,12 @@ struct hb_ot_map_t {
   }
 
   inline void substitute (hb_face_t *face, hb_buffer_t *buffer) const {
-    for (unsigned int i = 0; i < lookup_count[0]; i++)
+    for (unsigned int i = 0; i < lookup_maps[0].len; i++)
       hb_ot_layout_substitute_lookup (face, buffer, lookup_maps[0][i].index, lookup_maps[0][i].mask);
   }
 
   inline void position (hb_font_t *font, hb_face_t *face, hb_buffer_t *buffer) const {
-    for (unsigned int i = 0; i < lookup_count[1]; i++)
+    for (unsigned int i = 0; i < lookup_maps[1].len; i++)
       hb_ot_layout_position_lookup (font, buffer, lookup_maps[1][i].index, lookup_maps[1][i].mask);
   }
 
@@ -126,11 +124,10 @@ struct hb_ot_map_t {
 
   hb_mask_t global_mask;
 
-  hb_prealloced_array_t<feature_info_t,16> feature_infos; /* used before compile() only */
-  hb_prealloced_array_t<feature_map_t, 16> feature_maps;
+  hb_prealloced_array_t<feature_info_t,8> feature_infos; /* used before compile() only */
+  hb_prealloced_array_t<feature_map_t, 8> feature_maps;
 
-  lookup_map_t lookup_maps[2][MAX_LOOKUPS]; /* GSUB/GPOS */
-  unsigned int lookup_count[2];
+  hb_prealloced_array_t<lookup_map_t, 32> lookup_maps[2]; /* GSUB/GPOS */
 };
 
 
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index 04f41ee..9006bf9 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -39,23 +39,28 @@ hb_ot_map_t::add_lookups (hb_face_t    *face,
 			  unsigned int  feature_index,
 			  hb_mask_t     mask)
 {
-  unsigned int i = MAX_LOOKUPS - lookup_count[table_index];
-  lookup_map_t *lookups = lookup_maps[table_index] + lookup_count[table_index];
-
-  unsigned int *lookup_indices = (unsigned int *) lookups;
-
-  hb_ot_layout_feature_get_lookup_indexes (face,
-					   table_tags[table_index],
-					   feature_index,
-					   0, &i,
-					   lookup_indices);
-
-  lookup_count[table_index] += i;
+  unsigned int lookup_indices[32];
+  unsigned int offset, len;
+
+  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);
+
+    for (unsigned int i = 0; i < len; i++) {
+      lookup_map_t *lookup = lookup_maps[table_index].push ();
+      if (unlikely (!lookup))
+        return;
+      lookup->mask = mask;
+      lookup->index = lookup_indices[i];
+    }
 
-  while (i--) {
-    lookups[i].mask = mask;
-    lookups[i].index = lookup_indices[i];
-  }
+    offset += len;
+  } while (len == ARRAY_LENGTH (lookup_indices));
 }
 
 
@@ -64,7 +69,6 @@ hb_ot_map_t::compile (hb_face_t *face,
 		      const hb_segment_properties_t *props)
 {
  global_mask = 1;
- lookup_count[0] = lookup_count[1] = 0;
 
   if (!feature_infos.len)
     return;
@@ -176,17 +180,16 @@ hb_ot_map_t::compile (hb_face_t *face,
       add_lookups (face, table_index, feature_maps[i].index[table_index], feature_maps[i].mask);
 
     /* Sort lookups and merge duplicates */
-    qsort (lookup_maps[table_index], lookup_count[table_index], sizeof (lookup_maps[table_index][0]), (hb_compare_func_t) lookup_map_t::cmp);
-    if (lookup_count[table_index])
+    lookup_maps[table_index].sort ();
+    if (lookup_maps[table_index].len)
     {
       unsigned int j = 0;
-      for (unsigned int i = 1; i < lookup_count[table_index]; i++)
+      for (unsigned int i = 1; i < lookup_maps[table_index].len; i++)
 	if (lookup_maps[table_index][i].index != lookup_maps[table_index][j].index)
 	  lookup_maps[table_index][++j] = lookup_maps[table_index][i];
 	else
 	  lookup_maps[table_index][j].mask |= lookup_maps[table_index][i].mask;
-      j++;
-      lookup_count[table_index] = j;
+      lookup_maps[table_index].shrink (j + 1);
     }
   }
 }
diff --git a/src/hb-private.hh b/src/hb-private.hh
index e776daf..c37518d 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -235,10 +235,8 @@ struct hb_prealloced_array_t {
   Type *array;
   Type static_array[StaticSize];
 
-  inline Type& operator [] (unsigned int i)
-  {
-    return array[i];
-  }
+  inline Type& operator [] (unsigned int i) { return array[i]; }
+  inline const Type& operator [] (unsigned int i) const { return array[i]; }
 
   inline Type *push (void)
   {
commit 6843569d2c70c1771ce964e3d1a4cf91e14e7687
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 5 14:12:37 2011 -0400

    Replace fixed-size feature_maps array with hb_array_t

diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index 3b0cc19..bd4e868 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -82,8 +82,6 @@ struct hb_ot_map_t {
 
   public:
 
-  hb_ot_map_t (void) : feature_count (0) {}
-
   void add_feature (hb_tag_t tag, unsigned int value, bool global)
   {
     feature_info_t *info = feature_infos.push();
@@ -104,13 +102,13 @@ struct hb_ot_map_t {
   inline hb_mask_t get_global_mask (void) const { return global_mask; }
 
   inline hb_mask_t get_mask (hb_tag_t tag, unsigned int *shift = NULL) const {
-    const feature_map_t *map = (const feature_map_t *) bsearch (&tag, feature_maps, feature_count, sizeof (feature_maps[0]), (hb_compare_func_t) feature_map_t::cmp);
+    const feature_map_t *map = feature_maps.bsearch (&tag);
     if (shift) *shift = map ? map->shift : 0;
     return map ? map->mask : 0;
   }
 
   inline hb_mask_t get_1_mask (hb_tag_t tag) const {
-    const feature_map_t *map = (const feature_map_t *) bsearch (&tag, feature_maps, feature_count, sizeof (feature_maps[0]), (hb_compare_func_t) feature_map_t::cmp);
+    const feature_map_t *map = feature_maps.bsearch (&tag);
     return map ? map->_1_mask : 0;
   }
 
@@ -128,10 +126,8 @@ struct hb_ot_map_t {
 
   hb_mask_t global_mask;
 
-  unsigned int feature_count;
   hb_prealloced_array_t<feature_info_t,16> feature_infos; /* used before compile() only */
-#define MAX_FEATURES 100
-  feature_map_t feature_maps[MAX_FEATURES];
+  hb_prealloced_array_t<feature_map_t, 16> feature_maps;
 
   lookup_map_t lookup_maps[2][MAX_LOOKUPS]; /* GSUB/GPOS */
   unsigned int lookup_count[2];
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index d313da7..04f41ee 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -106,10 +106,8 @@ hb_ot_map_t::compile (hb_face_t *face,
 
 
   /* Allocate bits now */
-  feature_count = feature_infos.len;
   unsigned int next_bit = 1;
-  j = 0;
-  for (unsigned int i = 0; i < feature_count; i++) {
+  for (unsigned int i = 0; i < feature_infos.len; i++) {
     const feature_info_t *info = &feature_infos[i];
 
     unsigned int bits_needed;
@@ -137,7 +135,9 @@ hb_ot_map_t::compile (hb_face_t *face,
       continue;
 
 
-    feature_map_t *map = &feature_maps[j++];
+    feature_map_t *map = feature_maps.push ();
+    if (unlikely (!map))
+      break;
 
     map->tag = info->tag;
     map->index[0] = feature_index[0];
@@ -156,7 +156,7 @@ hb_ot_map_t::compile (hb_face_t *face,
     map->_1_mask = (1 << map->shift) & map->mask;
 
   }
-  feature_count = j;
+  feature_infos.shrink (0); /* Done with these */
 
 
   for (unsigned int table_index = 0; table_index < 2; table_index++) {
@@ -172,7 +172,7 @@ hb_ot_map_t::compile (hb_face_t *face,
 							  &required_feature_index))
       add_lookups (face, table_index, required_feature_index, 1);
 
-    for (unsigned i = 0; i < feature_count; i++)
+    for (unsigned i = 0; i < feature_maps.len; i++)
       add_lookups (face, table_index, feature_maps[i].index[table_index], feature_maps[i].mask);
 
     /* Sort lookups and merge duplicates */
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index e01f372..306bb41 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -370,7 +370,7 @@ hb_ot_shape (hb_font_t          *font,
 	     const hb_feature_t *features,
 	     unsigned int        num_features)
 {
-  hb_ot_shape_plan_t plan;
+  hb_ot_shape_plan_t plan = hb_ot_shape_plan_t ();
 
   hb_ot_shape_plan_internal (&plan, font->face, &buffer->props, features, num_features);
   hb_ot_shape_execute (&plan, font, buffer, features, num_features);
diff --git a/src/hb-private.hh b/src/hb-private.hh
index d3edad3..e776daf 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -285,10 +285,36 @@ struct hb_prealloced_array_t {
     /* TODO: shrink array if needed */
   }
 
+  template <typename T>
+  inline Type *find (T v) {
+    for (unsigned int i = 0; i < len; i++)
+      if (array[i] == v)
+	return &array[i];
+    return NULL;
+  }
+  template <typename T>
+  inline const Type *find (T v) const {
+    for (unsigned int i = 0; i < len; i++)
+      if (array[i] == v)
+	return &array[i];
+    return NULL;
+  }
+
   inline void sort (void)
   {
     qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
   }
+
+  template <typename T>
+  inline Type *bsearch (T *key)
+  {
+    return (Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
+  }
+  template <typename T>
+  inline const Type *bsearch (T *key) const
+  {
+    return (const Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
+  }
 };
 
 template <typename Type>
@@ -300,22 +326,12 @@ struct hb_set_t
 {
   hb_array_t <item_t> items;
 
-  private:
-
-  template <typename T>
-  inline item_t *find (T v) {
-    for (unsigned int i = 0; i < items.len; i++)
-      if (items[i] == v)
-	return &items[i];
-    return NULL;
-  }
-
   public:
 
   template <typename T>
   inline bool insert (T v)
   {
-    item_t *item = find (v);
+    item_t *item = items.find (v);
     if (item)
       item->finish ();
     else
@@ -328,7 +344,7 @@ struct hb_set_t
   template <typename T>
   inline void remove (T v)
   {
-    item_t *item = find (v);
+    item_t *item = items.find (v);
     if (!item) return;
 
     item->finish ();
@@ -339,7 +355,7 @@ struct hb_set_t
   template <typename T>
   inline item_t *get (T v)
   {
-    return find (v);
+    return items.find (v);
   }
 
   void finish (void) {
commit 44b0a4d2fc62689fc56ef57f412b4bb1e439a614
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 5 13:42:19 2011 -0400

    Replace fixed-size feature_infos array with hb_array_t

diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index e0fe51b..3b0cc19 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -36,7 +36,6 @@
 HB_BEGIN_DECLS
 
 
-#define MAX_FEATURES 100 /* FIXME */
 #define MAX_LOOKUPS 1000 /* FIXME */
 
 static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
@@ -87,9 +86,10 @@ struct hb_ot_map_t {
 
   void add_feature (hb_tag_t tag, unsigned int value, bool global)
   {
-    feature_info_t *info = &feature_infos[feature_count++];
+    feature_info_t *info = feature_infos.push();
+    if (unlikely (!info)) return;
     info->tag = tag;
-    info->seq = feature_count;
+    info->seq = feature_infos.len;
     info->max_value = value;
     info->global = global;
     info->default_value = global ? value : 0;
@@ -129,7 +129,8 @@ struct hb_ot_map_t {
   hb_mask_t global_mask;
 
   unsigned int feature_count;
-  feature_info_t feature_infos[MAX_FEATURES]; /* used before compile() only */
+  hb_prealloced_array_t<feature_info_t,16> feature_infos; /* used before compile() only */
+#define MAX_FEATURES 100
   feature_map_t feature_maps[MAX_FEATURES];
 
   lookup_map_t lookup_maps[2][MAX_LOOKUPS]; /* GSUB/GPOS */
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index 9b15305..d313da7 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -66,7 +66,7 @@ hb_ot_map_t::compile (hb_face_t *face,
  global_mask = 1;
  lookup_count[0] = lookup_count[1] = 0;
 
-  if (!feature_count)
+  if (!feature_infos.len)
     return;
 
 
@@ -88,9 +88,9 @@ hb_ot_map_t::compile (hb_face_t *face,
 
 
   /* Sort features and merge duplicates */
-  qsort (feature_infos, feature_count, sizeof (feature_infos[0]), (hb_compare_func_t) feature_info_t::cmp);
+  feature_infos.sort ();
   unsigned int j = 0;
-  for (unsigned int i = 1; i < feature_count; i++)
+  for (unsigned int i = 1; i < feature_infos.len; i++)
     if (feature_infos[i].tag != feature_infos[j].tag)
       feature_infos[++j] = feature_infos[i];
     else {
@@ -102,10 +102,11 @@ hb_ot_map_t::compile (hb_face_t *face,
 	/* Inherit default_value from j */
       }
     }
-  feature_count = j + 1;
+  feature_infos.shrink (j + 1);
 
 
   /* Allocate bits now */
+  feature_count = feature_infos.len;
   unsigned int next_bit = 1;
   j = 0;
   for (unsigned int i = 0; i < feature_count; i++) {
diff --git a/src/hb-private.hh b/src/hb-private.hh
index 26e0a69..d3edad3 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -277,6 +277,18 @@ struct hb_prealloced_array_t {
     len--;
     /* TODO: shrink array if needed */
   }
+
+  inline void shrink (unsigned int l)
+  {
+     if (l < len)
+       len = l;
+    /* TODO: shrink array if needed */
+  }
+
+  inline void sort (void)
+  {
+    qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
+  }
 };
 
 template <typename Type>
commit b214ec3ac0ce6568e9226fd09661d52de11dca96
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 5 13:24:07 2011 -0400

    Minor

diff --git a/src/hb-private.hh b/src/hb-private.hh
index 28c33b7..26e0a69 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -228,7 +228,7 @@ HB_END_DECLS
 
 
 template <typename Type, unsigned int StaticSize>
-struct hb_static_array_t {
+struct hb_prealloced_array_t {
 
   unsigned int len;
   unsigned int allocated;
@@ -280,7 +280,7 @@ struct hb_static_array_t {
 };
 
 template <typename Type>
-struct hb_array_t : hb_static_array_t<Type, 2> {};
+struct hb_array_t : hb_prealloced_array_t<Type, 2> {};
 
 
 template <typename item_t>
commit 811482bd650fb5652a9835471ae8ecf0fb185611
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 5 13:21:04 2011 -0400

    Replace hb_map_t with hb_set_t which is more intuitive and flexible

diff --git a/src/hb-object-private.hh b/src/hb-object-private.hh
index 77e0089..ffe87b4 100644
--- a/src/hb-object-private.hh
+++ b/src/hb-object-private.hh
@@ -106,37 +106,41 @@ typedef struct {
 
 /* XXX make this thread-safe, somehow! */
 
-typedef struct {
+struct hb_user_data_t {
+  hb_user_data_key_t *key;
   void *data;
   hb_destroy_func_t destroy;
 
+  inline bool operator == (hb_user_data_key_t *other_key) const { return key == other_key; }
+  inline bool operator == (hb_user_data_t &other) const { return key == other.key; }
+
   void finish (void) { if (destroy) destroy (data); }
-} hb_user_data_t;
+};
 
 struct hb_user_data_array_t {
 
-  hb_map_t<hb_user_data_key_t *, hb_user_data_t> map;
+  hb_set_t<hb_user_data_t> items;
 
   inline bool set (hb_user_data_key_t *key,
 		   void *              data,
 		   hb_destroy_func_t   destroy)
   {
+    if (!key)
+      return false;
     if (!data && !destroy) {
-      map.unset (key);
+      items.remove (key);
       return true;
     }
-    if (!key)
-      return false;
-    hb_user_data_t user_data = {data, destroy};
-    return map.set (key, user_data);
+    hb_user_data_t user_data = {key, data, destroy};
+    return items.insert (user_data);
   }
 
   inline void *get (hb_user_data_key_t *key) {
-    hb_user_data_t *user_data = map.get (key);
+    hb_user_data_t *user_data = items.get (key);
     return user_data ? user_data->data : NULL;
   }
 
-  void finish (void) { map.finish (); }
+  void finish (void) { items.finish (); }
 };
 
 
diff --git a/src/hb-private.hh b/src/hb-private.hh
index 9a23cd3..28c33b7 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -235,8 +235,6 @@ struct hb_static_array_t {
   Type *array;
   Type static_array[StaticSize];
 
-  void finish (void) { for (unsigned i = 0; i < len; i++) array[i].finish (); }
-
   inline Type& operator [] (unsigned int i)
   {
     return array[i];
@@ -285,25 +283,17 @@ template <typename Type>
 struct hb_array_t : hb_static_array_t<Type, 2> {};
 
 
-template <typename Key, typename Value>
-struct hb_map_t
+template <typename item_t>
+struct hb_set_t
 {
-  struct item_t {
-    Key key;
-    /* unsigned int hash; */
-    Value value;
-
-    void finish (void) { value.finish (); }
-  };
-
   hb_array_t <item_t> items;
 
   private:
 
   template <typename T>
-  inline item_t *find (T key) {
+  inline item_t *find (T v) {
     for (unsigned int i = 0; i < items.len; i++)
-      if (items[i].key == key)
+      if (items[i] == v)
 	return &items[i];
     return NULL;
   }
@@ -311,25 +301,22 @@ struct hb_map_t
   public:
 
   template <typename T>
-  inline bool set (T     key,
-		   Value &value)
+  inline bool insert (T v)
   {
-    item_t *item;
-    item = find (key);
+    item_t *item = find (v);
     if (item)
       item->finish ();
     else
       item = items.push ();
     if (unlikely (!item)) return false;
-    item->key = key;
-    item->value = value;
+    *item = v;
     return true;
   }
 
-  inline void unset (Key &key)
+  template <typename T>
+  inline void remove (T v)
   {
-    item_t *item;
-    item = find (key);
+    item_t *item = find (v);
     if (!item) return;
 
     item->finish ();
@@ -338,13 +325,16 @@ struct hb_map_t
   }
 
   template <typename T>
-  inline Value *get (T key)
+  inline item_t *get (T v)
   {
-    item_t *item = find (key);
-    return item ? &item->value : NULL;
+    return find (v);
+  }
+
+  void finish (void) {
+    for (unsigned i = 0; i < items.len; i++)
+      items[i].finish ();
   }
 
-  void finish (void) { items.finish (); }
 };
 
 
diff --git a/test/test-object.c b/test/test-object.c
index 297aa29..3662d30 100644
--- a/test/test-object.c
+++ b/test/test-object.c
@@ -269,6 +269,10 @@ test_object (void)
 	g_assert (o->get_user_data (obj, &key[i]) == &data[i]);
       for (i = 100; i < 1000; i++)
 	g_assert (o->set_user_data (obj, &key[i], NULL, NULL));
+      for (i = 2; i < 100; i++)
+	g_assert (o->get_user_data (obj, &key[i]) == &data[i]);
+      for (i = 100; i < 1000; i++)
+	g_assert (!o->get_user_data (obj, &key[i]));
       g_assert_cmpuint (global_data, ==, 900);
 
 
commit 478a42536ff7ab777a7774fbfdb9c5e51334a14e
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 5 12:39:51 2011 -0400

    Make array/map implementation more generic

diff --git a/src/hb-object-private.hh b/src/hb-object-private.hh
index 1f49885..77e0089 100644
--- a/src/hb-object-private.hh
+++ b/src/hb-object-private.hh
@@ -125,6 +125,8 @@ struct hb_user_data_array_t {
       map.unset (key);
       return true;
     }
+    if (!key)
+      return false;
     hb_user_data_t user_data = {data, destroy};
     return map.set (key, user_data);
   }
diff --git a/src/hb-private.hh b/src/hb-private.hh
index 1d40d66..9a23cd3 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -300,20 +300,20 @@ struct hb_map_t
 
   private:
 
-  inline item_t *find (Key key) {
-    if (unlikely (!key)) return NULL;
+  template <typename T>
+  inline item_t *find (T key) {
     for (unsigned int i = 0; i < items.len; i++)
-      if (key == items[i].key)
+      if (items[i].key == key)
 	return &items[i];
     return NULL;
   }
 
   public:
 
-  inline bool set (Key   key,
+  template <typename T>
+  inline bool set (T     key,
 		   Value &value)
   {
-    if (unlikely (!key)) return NULL;
     item_t *item;
     item = find (key);
     if (item)
@@ -337,7 +337,8 @@ struct hb_map_t
     items.pop ();
   }
 
-  inline Value *get (Key key)
+  template <typename T>
+  inline Value *get (T key)
   {
     item_t *item = find (key);
     return item ? &item->value : NULL;



More information about the HarfBuzz mailing list