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

Behdad Esfahbod behdad at kemper.freedesktop.org
Wed Jan 2 22:07:50 PST 2013


 TODO                                 |    2 
 src/hb-atomic-private.hh             |    2 
 src/hb-ot-layout-gsubgpos-private.hh |   19 ++
 src/hb-ot-layout.cc                  |  123 +++++++++++++++---
 src/hb-set-private.hh                |   19 ++
 src/hb-set.cc                        |    9 +
 src/hb-set.h                         |    3 
 test/api/Makefile.am                 |    1 
 test/api/test-object.c               |   12 +
 test/api/test-set.c                  |  237 +++++++++++++++++++++++++++++++++++
 10 files changed, 401 insertions(+), 26 deletions(-)

New commits:
commit f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Jan 3 00:07:16 2013 -0600

    [OTLayout] Always collect default language system in collect_lookups
    
    Not sure if this is the most desired behavior.  It's the most easily
    defined though.

diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 4a86b6b..5c266e6 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -496,6 +496,13 @@ _hb_ot_layout_collect_lookups_languages (hb_face_t      *face,
 					 const hb_tag_t *features,
 					 hb_set_t       *lookup_indexes /* OUT */)
 {
+  _hb_ot_layout_collect_lookups_features (face,
+					  table_tag,
+					  script_index,
+					  HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
+					  features,
+					  lookup_indexes);
+
   if (!languages)
   {
     /* All languages */
commit 15e9e4e1ddaad655988144e7a56a765e8adf8782
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Jan 3 00:04:40 2013 -0600

    [OTLayout] Fix feature iteration in collect_lookups
    
    Previous logic was just wrong.

diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 56c0a19..4a86b6b 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -447,17 +447,30 @@ _hb_ot_layout_collect_lookups_features (hb_face_t      *face,
   if (!features)
   {
     /* All features */
-    unsigned int count = hb_ot_layout_language_get_feature_tags (face,
-								 table_tag,
-								 script_index,
-								 language_index,
-								 0, NULL, NULL);
-    for (unsigned int feature_index = 0; feature_index < count; feature_index++)
-      _hb_ot_layout_collect_lookups_lookups (face,
-					     table_tag,
-					     feature_index,
-					     lookup_indexes);
-  } else {
+    unsigned int feature_indices[32];
+    unsigned int offset, len;
+
+    offset = 0;
+    do {
+      len = ARRAY_LENGTH (feature_indices);
+      hb_ot_layout_language_get_feature_indexes (face,
+						 table_tag,
+						 script_index,
+						 language_index,
+						 offset, &len,
+						 feature_indices);
+
+      for (unsigned int i = 0; i < len; i++)
+	_hb_ot_layout_collect_lookups_lookups (face,
+					       table_tag,
+					       feature_indices[i],
+					       lookup_indexes);
+
+      offset += len;
+    } while (len == ARRAY_LENGTH (feature_indices));
+  }
+  else
+  {
     for (; *features; features++)
     {
       unsigned int feature_index;
@@ -497,7 +510,9 @@ _hb_ot_layout_collect_lookups_languages (hb_face_t      *face,
 					      language_index,
 					      features,
 					      lookup_indexes);
-  } else {
+  }
+  else
+  {
     for (; *languages; languages++)
     {
       unsigned int language_index;
@@ -537,7 +552,9 @@ hb_ot_layout_collect_lookups (hb_face_t      *face,
 					       languages,
 					       features,
 					       lookup_indexes);
-  } else {
+  }
+  else
+  {
     for (; *scripts; scripts++)
     {
       unsigned int script_index;
@@ -572,7 +589,8 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
 				     glyphs_after,
 				     glyphs_output);
 
-  switch (table_tag) {
+  switch (table_tag)
+  {
     case HB_OT_TAG_GSUB:
     {
       const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
commit 733e8c0d7bf0765884f2cc953c8edcd7ab7fb49b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Jan 3 00:00:23 2013 -0600

    [OTLayout] Whitespace

diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 8edb135..56c0a19 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -439,20 +439,38 @@ _hb_ot_layout_collect_lookups_features (hb_face_t      *face,
 							script_index,
 							language_index,
 							&required_feature_index))
-    _hb_ot_layout_collect_lookups_lookups (face, table_tag, required_feature_index, lookup_indexes);
+    _hb_ot_layout_collect_lookups_lookups (face,
+					   table_tag,
+					   required_feature_index,
+					   lookup_indexes);
 
   if (!features)
   {
     /* All features */
-    unsigned int count = hb_ot_layout_language_get_feature_tags (face, table_tag, script_index, language_index, 0, NULL, NULL);
+    unsigned int count = hb_ot_layout_language_get_feature_tags (face,
+								 table_tag,
+								 script_index,
+								 language_index,
+								 0, NULL, NULL);
     for (unsigned int feature_index = 0; feature_index < count; feature_index++)
-      _hb_ot_layout_collect_lookups_lookups (face, table_tag, feature_index, lookup_indexes);
+      _hb_ot_layout_collect_lookups_lookups (face,
+					     table_tag,
+					     feature_index,
+					     lookup_indexes);
   } else {
     for (; *features; features++)
     {
       unsigned int feature_index;
-      if (hb_ot_layout_language_find_feature (face, table_tag, script_index, language_index, *features, &feature_index))
-        _hb_ot_layout_collect_lookups_lookups (face, table_tag, feature_index, lookup_indexes);
+      if (hb_ot_layout_language_find_feature (face,
+					      table_tag,
+					      script_index,
+					      language_index,
+					      *features,
+					      &feature_index))
+        _hb_ot_layout_collect_lookups_lookups (face,
+					       table_tag,
+					       feature_index,
+					       lookup_indexes);
     }
   }
 }
@@ -468,15 +486,32 @@ _hb_ot_layout_collect_lookups_languages (hb_face_t      *face,
   if (!languages)
   {
     /* All languages */
-    unsigned int count = hb_ot_layout_script_get_language_tags (face, table_tag, script_index, 0, NULL, NULL);
+    unsigned int count = hb_ot_layout_script_get_language_tags (face,
+								table_tag,
+								script_index,
+								0, NULL, NULL);
     for (unsigned int language_index = 0; language_index < count; language_index++)
-      _hb_ot_layout_collect_lookups_features (face, table_tag, script_index, language_index, features, lookup_indexes);
+      _hb_ot_layout_collect_lookups_features (face,
+					      table_tag,
+					      script_index,
+					      language_index,
+					      features,
+					      lookup_indexes);
   } else {
     for (; *languages; languages++)
     {
       unsigned int language_index;
-      if (hb_ot_layout_script_find_language (face, table_tag, script_index, *languages, &language_index))
-        _hb_ot_layout_collect_lookups_features (face, table_tag, script_index, language_index, features, lookup_indexes);
+      if (hb_ot_layout_script_find_language (face,
+					     table_tag,
+					     script_index,
+					     *languages,
+					     &language_index))
+        _hb_ot_layout_collect_lookups_features (face,
+						table_tag,
+						script_index,
+						language_index,
+						features,
+						lookup_indexes);
     }
   }
 }
@@ -492,15 +527,30 @@ hb_ot_layout_collect_lookups (hb_face_t      *face,
   if (!scripts)
   {
     /* All scripts */
-    unsigned int count = hb_ot_layout_table_get_script_tags (face, table_tag, 0, NULL, NULL);
+    unsigned int count = hb_ot_layout_table_get_script_tags (face,
+							     table_tag,
+							     0, NULL, NULL);
     for (unsigned int script_index = 0; script_index < count; script_index++)
-      _hb_ot_layout_collect_lookups_languages (face, table_tag, script_index, languages, features, lookup_indexes);
+      _hb_ot_layout_collect_lookups_languages (face,
+					       table_tag,
+					       script_index,
+					       languages,
+					       features,
+					       lookup_indexes);
   } else {
     for (; *scripts; scripts++)
     {
       unsigned int script_index;
-      if (hb_ot_layout_table_find_script (face, table_tag, *scripts, &script_index))
-        _hb_ot_layout_collect_lookups_languages (face, table_tag, script_index, languages, features, lookup_indexes);
+      if (hb_ot_layout_table_find_script (face,
+					  table_tag,
+					  *scripts,
+					  &script_index))
+        _hb_ot_layout_collect_lookups_languages (face,
+						 table_tag,
+						 script_index,
+						 languages,
+						 features,
+						 lookup_indexes);
     }
   }
 }
@@ -516,7 +566,11 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
 {
   if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return;
 
-  OT::hb_collect_glyphs_context_t c (face, glyphs_before, glyphs_input, glyphs_after, glyphs_output);
+  OT::hb_collect_glyphs_context_t c (face,
+				     glyphs_before,
+				     glyphs_input,
+				     glyphs_after,
+				     glyphs_output);
 
   switch (table_tag) {
     case HB_OT_TAG_GSUB:
commit d37ae38047bee12639741af9bb083b857fab950d
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Jan 2 23:57:36 2013 -0600

    [OTLayout] Handle required_feature_index in collect_lookups

diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index e4bac0a..8edb135 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -433,6 +433,14 @@ _hb_ot_layout_collect_lookups_features (hb_face_t      *face,
 					const hb_tag_t *features,
 					hb_set_t       *lookup_indexes /* OUT */)
 {
+  unsigned int required_feature_index;
+  if (hb_ot_layout_language_get_required_feature_index (face,
+							table_tag,
+							script_index,
+							language_index,
+							&required_feature_index))
+    _hb_ot_layout_collect_lookups_lookups (face, table_tag, required_feature_index, lookup_indexes);
+
   if (!features)
   {
     /* All features */
commit 11fba79ee9383eb995ddf7eb924dd64c67e2df63
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Jan 2 23:36:37 2013 -0600

    [OTLayout] Fix various introspection issues with ClassDef's
    
    As reported by Jonathan Kew.

diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index 87abd3b..40be861 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -1175,7 +1175,7 @@ struct ContextFormat2
 
     struct ContextClosureLookupContext lookup_context = {
       {intersects_class},
-      NULL
+      &class_def
     };
 
     unsigned int count = ruleSet.len;
@@ -1191,9 +1191,10 @@ struct ContextFormat2
     TRACE_COLLECT_GLYPHS (this);
     (this+coverage).add_coverage (c->input);
 
+    const ClassDef &class_def = this+classDef;
     struct ContextCollectGlyphsLookupContext lookup_context = {
       {collect_class},
-      NULL
+      &class_def
     };
 
     unsigned int count = ruleSet.len;
@@ -1750,9 +1751,15 @@ struct ChainContextFormat2
     TRACE_COLLECT_GLYPHS (this);
     (this+coverage).add_coverage (c->input);
 
+    const ClassDef &backtrack_class_def = this+backtrackClassDef;
+    const ClassDef &input_class_def = this+inputClassDef;
+    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
     struct ChainContextCollectGlyphsLookupContext lookup_context = {
       {collect_class},
-      {NULL, NULL, NULL}
+      {&backtrack_class_def,
+       &input_class_def,
+       &lookahead_class_def}
     };
 
     unsigned int count = ruleSet.len;
@@ -1764,13 +1771,17 @@ struct ChainContextFormat2
   {
     TRACE_WOULD_APPLY (this);
 
+    const ClassDef &backtrack_class_def = this+backtrackClassDef;
     const ClassDef &input_class_def = this+inputClassDef;
+    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
 
     unsigned int index = input_class_def.get_class (c->glyphs[0]);
     const ChainRuleSet &rule_set = this+ruleSet[index];
     struct ChainContextApplyLookupContext lookup_context = {
       {match_class},
-      {NULL, &input_class_def, NULL}
+      {&backtrack_class_def,
+       &input_class_def,
+       &lookahead_class_def}
     };
     return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
   }
commit e81aff9ef785be28751aab1fcd484af550656181
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Jan 2 23:22:54 2013 -0600

    [tests] Finish test-set.c
    
    All passing now.

diff --git a/test/api/test-set.c b/test/api/test-set.c
index f59760d..b9e7ef8 100644
--- a/test/api/test-set.c
+++ b/test/api/test-set.c
@@ -29,243 +29,169 @@
 /* Unit tests for hb-set.h */
 
 
-#if 0
 static void
-test_buffer_properties (fixture_t *fixture, gconstpointer user_data)
+test_empty (hb_set_t *s)
 {
-  hb_buffer_t *b = fixture->buffer;
-  hb_unicode_funcs_t *ufuncs;
-
-  /* test default properties */
-
-  g_assert (hb_buffer_get_unicode_funcs (b) == hb_unicode_funcs_get_default ());
-  g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID);
-  g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID);
-  g_assert (hb_buffer_get_language (b) == NULL);
-  g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAGS_DEFAULT);
-
-
-  /* test property changes are retained */
-  ufuncs = hb_unicode_funcs_create (NULL);
-  hb_buffer_set_unicode_funcs (b, ufuncs);
-  hb_unicode_funcs_destroy (ufuncs);
-  g_assert (hb_buffer_get_unicode_funcs (b) == ufuncs);
-
-  hb_buffer_set_direction (b, HB_DIRECTION_RTL);
-  g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_RTL);
-
-  hb_buffer_set_script (b, HB_SCRIPT_ARABIC);
-  g_assert (hb_buffer_get_script (b) == HB_SCRIPT_ARABIC);
-
-  hb_buffer_set_language (b, hb_language_from_string ("fa", -1));
-  g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1));
-
-  hb_buffer_set_flags (b, HB_BUFFER_FLAG_BOT);
-  g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAG_BOT);
-
-
-
-  /* test clear clears all properties but unicode_funcs */
-
-  hb_buffer_clear (b);
-
-  g_assert (hb_buffer_get_unicode_funcs (b) == ufuncs);
-  g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID);
-  g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID);
-  g_assert (hb_buffer_get_language (b) == NULL);
-  g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAGS_DEFAULT);
-
-
-  /* test reset clears all properties */
-
-  hb_buffer_set_direction (b, HB_DIRECTION_RTL);
-  g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_RTL);
-
-  hb_buffer_set_script (b, HB_SCRIPT_ARABIC);
-  g_assert (hb_buffer_get_script (b) == HB_SCRIPT_ARABIC);
-
-  hb_buffer_set_language (b, hb_language_from_string ("fa", -1));
-  g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1));
-
-  hb_buffer_set_flags (b, HB_BUFFER_FLAG_BOT);
-  g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAG_BOT);
-
-  hb_buffer_reset (b);
-
-  g_assert (hb_buffer_get_unicode_funcs (b) == hb_unicode_funcs_get_default ());
-  g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID);
-  g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID);
-  g_assert (hb_buffer_get_language (b) == NULL);
-  g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAGS_DEFAULT);
+  hb_codepoint_t next = (hb_codepoint_t) -1;
+  g_assert_cmpint (hb_set_get_population (s), ==, 0);
+  g_assert_cmpint (hb_set_get_min (s), ==, (hb_codepoint_t) -1);
+  g_assert_cmpint (hb_set_get_max (s), ==, (hb_codepoint_t) -1);
+  g_assert (!hb_set_has (s, 13));
+  g_assert (!hb_set_next (s, &next));
+  g_assert_cmpint (next, ==, (hb_codepoint_t) -1);
 }
 
 static void
-test_buffer_contents (fixture_t *fixture, gconstpointer user_data)
+test_not_empty (hb_set_t *s)
 {
-  hb_buffer_t *b = fixture->buffer;
-  unsigned int i, len, len2;
-  buffer_type_t buffer_type = GPOINTER_TO_INT (user_data);
-  hb_glyph_info_t *glyphs;
-
-  if (buffer_type == BUFFER_EMPTY) {
-    g_assert_cmpint (hb_buffer_get_population (b), ==, 0);
-    return;
-  }
-
-  len = hb_buffer_get_population (b);
-  hb_buffer_get_glyph_infos (b, NULL); /* test NULL */
-  glyphs = hb_buffer_get_glyph_infos (b, &len2);
-  g_assert_cmpint (len, ==, len2);
-  g_assert_cmpint (len, ==, 5);
-
-  for (i = 0; i < len; i++) {
-    g_assert_cmphex (glyphs[i].mask,      ==, 1);
-    g_assert_cmphex (glyphs[i].var1.u32,  ==, 0);
-    g_assert_cmphex (glyphs[i].var2.u32,  ==, 0);
-  }
-
-  for (i = 0; i < len; i++) {
-    unsigned int cluster;
-    cluster = 1+i;
-    if (i >= 2) {
-      if (buffer_type == BUFFER_UTF16)
-	cluster++;
-      else if (buffer_type == BUFFER_UTF8)
-        cluster += 3;
-    }
-    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
-    g_assert_cmphex (glyphs[i].cluster,   ==, cluster);
-  }
-
-  /* reverse, test, and reverse back */
-
-  hb_buffer_reverse (b);
-  for (i = 0; i < len; i++)
-    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
-
-  hb_buffer_reverse (b);
-  for (i = 0; i < len; i++)
-    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
-
-  /* reverse_clusters works same as reverse for now since each codepoint is
-   * in its own cluster */
-
-  hb_buffer_reverse_clusters (b);
-  for (i = 0; i < len; i++)
-    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
-
-  hb_buffer_reverse_clusters (b);
-  for (i = 0; i < len; i++)
-    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
-
-  /* now form a cluster and test again */
-  glyphs[2].cluster = glyphs[1].cluster;
-
-  /* reverse, test, and reverse back */
-
-  hb_buffer_reverse (b);
-  for (i = 0; i < len; i++)
-    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
-
-  hb_buffer_reverse (b);
-  for (i = 0; i < len; i++)
-    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
-
-  /* reverse_clusters twice still should return the original string,
-   * but when applied once, the 1-2 cluster should be retained. */
-
-  hb_buffer_reverse_clusters (b);
-  for (i = 0; i < len; i++) {
-    unsigned int j = len-1-i;
-    if (j == 1)
-      j = 2;
-    else if (j == 2)
-      j = 1;
-    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+j]);
-  }
-
-  hb_buffer_reverse_clusters (b);
-  for (i = 0; i < len; i++)
-    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
-
-
-  /* test setting length */
-
-  /* enlarge */
-  g_assert (hb_buffer_set_length (b, 10));
-  glyphs = hb_buffer_get_glyph_infos (b, NULL);
-  g_assert_cmpint (hb_buffer_get_population (b), ==, 10);
-  for (i = 0; i < 5; i++)
-    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
-  for (i = 5; i < 10; i++)
-    g_assert_cmphex (glyphs[i].codepoint, ==, 0);
-  /* shrink */
-  g_assert (hb_buffer_set_length (b, 3));
-  glyphs = hb_buffer_get_glyph_infos (b, NULL);
-  g_assert_cmpint (hb_buffer_get_population (b), ==, 3);
-  for (i = 0; i < 3; i++)
-    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
-
-
-  g_assert (hb_buffer_allocation_successful (b));
-
-
-  /* test reset clears content */
-
-  hb_buffer_reset (b);
-  g_assert_cmpint (hb_buffer_get_population (b), ==, 0);
+  hb_codepoint_t next = (hb_codepoint_t) -1;
+  g_assert_cmpint (hb_set_get_population (s), !=, 0);
+  g_assert_cmpint (hb_set_get_min (s), !=, (hb_codepoint_t) -1);
+  g_assert_cmpint (hb_set_get_max (s), !=, (hb_codepoint_t) -1);
+  g_assert (hb_set_next (s, &next));
+  g_assert_cmpint (next, !=, (hb_codepoint_t) -1);
 }
 
 static void
-test_buffer_allocation (fixture_t *fixture, gconstpointer user_data)
+test_set_basic (void)
 {
-  hb_buffer_t *b = fixture->buffer;
-
-  g_assert_cmpint (hb_buffer_get_population (b), ==, 0);
-
-  g_assert (hb_buffer_pre_allocate (b, 100));
-  g_assert_cmpint (hb_buffer_get_population (b), ==, 0);
-  g_assert (hb_buffer_allocation_successful (b));
-
-  /* lets try a huge allocation, make sure it fails */
-  g_assert (!hb_buffer_pre_allocate (b, (unsigned int) -1));
-  g_assert_cmpint (hb_buffer_get_population (b), ==, 0);
-  g_assert (!hb_buffer_allocation_successful (b));
-
-  /* small one again */
-  g_assert (hb_buffer_pre_allocate (b, 50));
-  g_assert_cmpint (hb_buffer_get_population (b), ==, 0);
-  g_assert (!hb_buffer_allocation_successful (b));
-
-  hb_buffer_reset (b);
-  g_assert (hb_buffer_allocation_successful (b));
-
-  /* all allocation and size  */
-  g_assert (!hb_buffer_pre_allocate (b, ((unsigned int) -1) / 20 + 1));
-  g_assert (!hb_buffer_allocation_successful (b));
-
-  hb_buffer_reset (b);
-  g_assert (hb_buffer_allocation_successful (b));
-
-  /* technically, this one can actually pass on 64bit machines, but
-   * I'm doubtful that any malloc allows 4GB allocations at a time.
-   * But let's only enable it on a 32-bit machine. */
-  if (sizeof (long) == 4) {
-    g_assert (!hb_buffer_pre_allocate (b, ((unsigned int) -1) / 20 - 1));
-    g_assert (!hb_buffer_allocation_successful (b));
-  }
+  hb_set_t *s = hb_set_create ();
+
+  test_empty (s);
+  hb_set_add (s, 13);
+  test_not_empty (s);
+
+  hb_set_clear (s);
+  test_empty (s);
+
+  hb_set_add_range (s, 10, 29);
+  test_not_empty (s);
+  g_assert (hb_set_has (s, 13));
+  g_assert_cmpint (hb_set_get_population (s), ==, 20);
+  g_assert_cmpint (hb_set_get_min (s), ==, 10);
+  g_assert_cmpint (hb_set_get_max (s), ==, 29);
+
+  hb_set_invert (s);
+  test_not_empty (s);
+  g_assert (!hb_set_has (s, 13));
+  g_assert_cmpint (hb_set_get_min (s), ==, 0);
+
+  hb_set_invert (s);
+  test_not_empty (s);
+  g_assert (hb_set_has (s, 13));
+  g_assert_cmpint (hb_set_get_population (s), ==, 20);
+  g_assert_cmpint (hb_set_get_min (s), ==, 10);
+  g_assert_cmpint (hb_set_get_max (s), ==, 29);
+
+  hb_set_del_range (s, 10, 18);
+  test_not_empty (s);
+  g_assert (!hb_set_has (s, 13));
+}
 
-  hb_buffer_reset (b);
-  g_assert (hb_buffer_allocation_successful (b));
+static void
+test_set_algebra (void)
+{
+  hb_set_t *s = hb_set_create ();
+  hb_set_t *o = hb_set_create ();
+
+  hb_set_add (o, 13);
+  hb_set_add (o, 19);
+
+  test_empty (s);
+  g_assert (!hb_set_is_equal (s, o));
+  hb_set_set (s, o);
+  g_assert (hb_set_is_equal (s, o));
+  test_not_empty (s);
+  g_assert_cmpint (hb_set_get_population (s), ==, 2);
+
+  hb_set_clear (s);
+  test_empty (s);
+  hb_set_add (s, 10);
+  g_assert_cmpint (hb_set_get_population (s), ==, 1);
+  hb_set_union (s, o);
+  g_assert_cmpint (hb_set_get_population (s), ==, 3);
+  g_assert (hb_set_has (s, 10));
+  g_assert (hb_set_has (s, 13));
+
+  hb_set_clear (s);
+  test_empty (s);
+  hb_set_add_range (s, 10, 17);
+  g_assert (!hb_set_is_equal (s, o));
+  hb_set_intersect (s, o);
+  g_assert (!hb_set_is_equal (s, o));
+  test_not_empty (s);
+  g_assert_cmpint (hb_set_get_population (s), ==, 1);
+  g_assert (!hb_set_has (s, 10));
+  g_assert (hb_set_has (s, 13));
+
+  hb_set_clear (s);
+  test_empty (s);
+  hb_set_add_range (s, 10, 17);
+  g_assert (!hb_set_is_equal (s, o));
+  hb_set_subtract (s, o);
+  g_assert (!hb_set_is_equal (s, o));
+  test_not_empty (s);
+  g_assert_cmpint (hb_set_get_population (s), ==, 7);
+  g_assert (hb_set_has (s, 12));
+  g_assert (!hb_set_has (s, 13));
+  g_assert (!hb_set_has (s, 19));
+
+  hb_set_clear (s);
+  test_empty (s);
+  hb_set_add_range (s, 10, 17);
+  g_assert (!hb_set_is_equal (s, o));
+  hb_set_symmetric_difference (s, o);
+  g_assert (!hb_set_is_equal (s, o));
+  test_not_empty (s);
+  g_assert_cmpint (hb_set_get_population (s), ==, 8);
+  g_assert (hb_set_has (s, 12));
+  g_assert (!hb_set_has (s, 13));
+  g_assert (hb_set_has (s, 19));
 }
-#endif
 
 static void
-test_empty (hb_set_t *b)
+test_set_iter (void)
 {
-  g_assert_cmpint (hb_set_get_population (b), ==, 0);
-  g_assert_cmpint (hb_set_get_min (b), ==, (hb_codepoint_t) -1);
-  g_assert_cmpint (hb_set_get_max (b), ==, (hb_codepoint_t) -1);
+  hb_codepoint_t next, first, last;
+  hb_set_t *s = hb_set_create ();
+
+  hb_set_add (s, 13);
+  hb_set_add_range (s, 6, 6);
+  hb_set_add_range (s, 10, 15);
+  hb_set_add (s, 20005);
+
+  test_not_empty (s);
+
+  next = (hb_codepoint_t) -1;
+  g_assert (hb_set_next (s, &next));
+  g_assert_cmpint (next, ==, 6);
+  g_assert (hb_set_next (s, &next));
+  g_assert_cmpint (next, ==, 10);
+  g_assert (hb_set_next (s, &next));
+  g_assert (hb_set_next (s, &next));
+  g_assert (hb_set_next (s, &next));
+  g_assert_cmpint (next, ==, 13);
+  g_assert (hb_set_next (s, &next));
+  g_assert (hb_set_next (s, &next));
+  g_assert_cmpint (next, ==, 15);
+  g_assert (hb_set_next (s, &next));
+  g_assert_cmpint (next, ==, 20005);
+  g_assert (!hb_set_next (s, &next));
+  g_assert_cmpint (next, ==, 20005);
+
+  first = last = (hb_codepoint_t) -1;
+  g_assert (hb_set_next_range (s, &first, &last));
+  g_assert_cmpint (first, ==, 6);
+  g_assert_cmpint (last,  ==, 6);
+  g_assert (hb_set_next_range (s, &first, &last));
+  g_assert_cmpint (first, ==, 10);
+  g_assert_cmpint (last,  ==, 15);
+  g_assert (hb_set_next_range (s, &first, &last));
+  g_assert_cmpint (first, ==, 20005);
+  g_assert_cmpint (last,  ==, 20005);
+  g_assert (!hb_set_next_range (s, &first, &last));
+  g_assert_cmpint (first, ==, 20005);
+  g_assert_cmpint (last,  ==, 20005);
 }
 
 static void
@@ -302,10 +228,9 @@ main (int argc, char **argv)
 {
   hb_test_init (&argc, &argv);
 
-#if 0
+  hb_test_add (test_set_basic);
   hb_test_add (test_set_algebra);
   hb_test_add (test_set_iter);
-#endif
   hb_test_add (test_set_empty);
 
   return hb_test_run();
commit 7b1b720a8da69b68b775ce17104a40d55401b7ef
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Jan 2 23:02:59 2013 -0600

    Protect sets in-error from further modication
    
    Fixes test-set.c

diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh
index 8e03d68..5e30a7e 100644
--- a/src/hb-set-private.hh
+++ b/src/hb-set-private.hh
@@ -146,6 +146,9 @@ struct hb_set_t
   inline void fini (void) {
   }
   inline void clear (void) {
+    if (unlikely (hb_object_is_inert (this)))
+      return;
+    in_error = false;
     memset (elts, 0, sizeof elts);
   }
   inline bool is_empty (void) const {
@@ -156,23 +159,27 @@ struct hb_set_t
   }
   inline void add (hb_codepoint_t g)
   {
+    if (unlikely (in_error)) return;
     if (unlikely (g == SENTINEL)) return;
     if (unlikely (g > MAX_G)) return;
     elt (g) |= mask (g);
   }
   inline void add_range (hb_codepoint_t a, hb_codepoint_t b)
   {
+    if (unlikely (in_error)) return;
     /* TODO Speedup */
     for (unsigned int i = a; i < b + 1; i++)
       add (i);
   }
   inline void del (hb_codepoint_t g)
   {
+    if (unlikely (in_error)) return;
     if (unlikely (g > MAX_G)) return;
     elt (g) &= ~mask (g);
   }
   inline void del_range (hb_codepoint_t a, hb_codepoint_t b)
   {
+    if (unlikely (in_error)) return;
     /* TODO Speedup */
     for (unsigned int i = a; i < b + 1; i++)
       del (i);
@@ -202,31 +209,37 @@ struct hb_set_t
   }
   inline void set (const hb_set_t *other)
   {
+    if (unlikely (in_error)) return;
     for (unsigned int i = 0; i < ELTS; i++)
       elts[i] = other->elts[i];
   }
   inline void union_ (const hb_set_t *other)
   {
+    if (unlikely (in_error)) return;
     for (unsigned int i = 0; i < ELTS; i++)
       elts[i] |= other->elts[i];
   }
   inline void intersect (const hb_set_t *other)
   {
+    if (unlikely (in_error)) return;
     for (unsigned int i = 0; i < ELTS; i++)
       elts[i] &= other->elts[i];
   }
   inline void subtract (const hb_set_t *other)
   {
+    if (unlikely (in_error)) return;
     for (unsigned int i = 0; i < ELTS; i++)
       elts[i] &= ~other->elts[i];
   }
   inline void symmetric_difference (const hb_set_t *other)
   {
+    if (unlikely (in_error)) return;
     for (unsigned int i = 0; i < ELTS; i++)
       elts[i] ^= other->elts[i];
   }
   inline void invert (void)
   {
+    if (unlikely (in_error)) return;
     for (unsigned int i = 0; i < ELTS; i++)
       elts[i] = ~elts[i];
   }
commit 8165f2765b93e99577ecc79b7956ae38c614bc78
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Jan 2 22:50:36 2013 -0600

    [tests] Start adding tests for hb-set.h
    
    Fails now.  Fixing.

diff --git a/TODO b/TODO
index 27ff868..c93b33e 100644
--- a/TODO
+++ b/TODO
@@ -85,8 +85,6 @@ Tests to write:
 
 - GObject, FreeType, etc
 
-- hb_set_t
-
 - hb_cache_t and relatives
 
 - hb_feature_to/from_string
diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh
index c736b69..8e03d68 100644
--- a/src/hb-set-private.hh
+++ b/src/hb-set-private.hh
@@ -137,6 +137,7 @@ struct hb_set_t
 {
   hb_object_header_t header;
   ASSERT_POD ();
+  bool in_error;
 
   inline void init (void) {
     header.init ();
@@ -224,6 +225,11 @@ struct hb_set_t
     for (unsigned int i = 0; i < ELTS; i++)
       elts[i] ^= other->elts[i];
   }
+  inline void invert (void)
+  {
+    for (unsigned int i = 0; i < ELTS; i++)
+      elts[i] = ~elts[i];
+  }
   inline bool next (hb_codepoint_t *codepoint) const
   {
     if (unlikely (*codepoint == SENTINEL)) {
diff --git a/src/hb-set.cc b/src/hb-set.cc
index 93f983a..5f427a5 100644
--- a/src/hb-set.cc
+++ b/src/hb-set.cc
@@ -49,6 +49,7 @@ hb_set_get_empty (void)
 {
   static const hb_set_t _hb_set_nil = {
     HB_OBJECT_HEADER_STATIC,
+    true, /* in_error */
 
     {0} /* elts */
   };
@@ -93,7 +94,7 @@ hb_set_get_user_data (hb_set_t           *set,
 hb_bool_t
 hb_set_allocation_successful (const hb_set_t  *set HB_UNUSED)
 {
-  return true;
+  return !set->in_error;
 }
 
 void
@@ -187,6 +188,12 @@ hb_set_symmetric_difference (hb_set_t       *set,
   set->symmetric_difference (other);
 }
 
+void
+hb_set_invert (hb_set_t *set)
+{
+  set->invert ();
+}
+
 unsigned int
 hb_set_get_population (const hb_set_t *set)
 {
diff --git a/src/hb-set.h b/src/hb-set.h
index ec3d119..291e249 100644
--- a/src/hb-set.h
+++ b/src/hb-set.h
@@ -121,6 +121,9 @@ void
 hb_set_symmetric_difference (hb_set_t       *set,
 			     const hb_set_t *other);
 
+void
+hb_set_invert (hb_set_t *set);
+
 unsigned int
 hb_set_get_population (const hb_set_t *set);
 
diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index c5a015f..237f92c 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -21,6 +21,7 @@ TEST_PROGS = \
 	test-common \
 	test-font \
 	test-object \
+	test-set \
 	test-shape \
 	test-unicode \
 	test-version \
diff --git a/test/api/test-set.c b/test/api/test-set.c
new file mode 100644
index 0000000..f59760d
--- /dev/null
+++ b/test/api/test-set.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright © 2013  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-test.h"
+
+/* Unit tests for hb-set.h */
+
+
+#if 0
+static void
+test_buffer_properties (fixture_t *fixture, gconstpointer user_data)
+{
+  hb_buffer_t *b = fixture->buffer;
+  hb_unicode_funcs_t *ufuncs;
+
+  /* test default properties */
+
+  g_assert (hb_buffer_get_unicode_funcs (b) == hb_unicode_funcs_get_default ());
+  g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID);
+  g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID);
+  g_assert (hb_buffer_get_language (b) == NULL);
+  g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAGS_DEFAULT);
+
+
+  /* test property changes are retained */
+  ufuncs = hb_unicode_funcs_create (NULL);
+  hb_buffer_set_unicode_funcs (b, ufuncs);
+  hb_unicode_funcs_destroy (ufuncs);
+  g_assert (hb_buffer_get_unicode_funcs (b) == ufuncs);
+
+  hb_buffer_set_direction (b, HB_DIRECTION_RTL);
+  g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_RTL);
+
+  hb_buffer_set_script (b, HB_SCRIPT_ARABIC);
+  g_assert (hb_buffer_get_script (b) == HB_SCRIPT_ARABIC);
+
+  hb_buffer_set_language (b, hb_language_from_string ("fa", -1));
+  g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1));
+
+  hb_buffer_set_flags (b, HB_BUFFER_FLAG_BOT);
+  g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAG_BOT);
+
+
+
+  /* test clear clears all properties but unicode_funcs */
+
+  hb_buffer_clear (b);
+
+  g_assert (hb_buffer_get_unicode_funcs (b) == ufuncs);
+  g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID);
+  g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID);
+  g_assert (hb_buffer_get_language (b) == NULL);
+  g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAGS_DEFAULT);
+
+
+  /* test reset clears all properties */
+
+  hb_buffer_set_direction (b, HB_DIRECTION_RTL);
+  g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_RTL);
+
+  hb_buffer_set_script (b, HB_SCRIPT_ARABIC);
+  g_assert (hb_buffer_get_script (b) == HB_SCRIPT_ARABIC);
+
+  hb_buffer_set_language (b, hb_language_from_string ("fa", -1));
+  g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1));
+
+  hb_buffer_set_flags (b, HB_BUFFER_FLAG_BOT);
+  g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAG_BOT);
+
+  hb_buffer_reset (b);
+
+  g_assert (hb_buffer_get_unicode_funcs (b) == hb_unicode_funcs_get_default ());
+  g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID);
+  g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID);
+  g_assert (hb_buffer_get_language (b) == NULL);
+  g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAGS_DEFAULT);
+}
+
+static void
+test_buffer_contents (fixture_t *fixture, gconstpointer user_data)
+{
+  hb_buffer_t *b = fixture->buffer;
+  unsigned int i, len, len2;
+  buffer_type_t buffer_type = GPOINTER_TO_INT (user_data);
+  hb_glyph_info_t *glyphs;
+
+  if (buffer_type == BUFFER_EMPTY) {
+    g_assert_cmpint (hb_buffer_get_population (b), ==, 0);
+    return;
+  }
+
+  len = hb_buffer_get_population (b);
+  hb_buffer_get_glyph_infos (b, NULL); /* test NULL */
+  glyphs = hb_buffer_get_glyph_infos (b, &len2);
+  g_assert_cmpint (len, ==, len2);
+  g_assert_cmpint (len, ==, 5);
+
+  for (i = 0; i < len; i++) {
+    g_assert_cmphex (glyphs[i].mask,      ==, 1);
+    g_assert_cmphex (glyphs[i].var1.u32,  ==, 0);
+    g_assert_cmphex (glyphs[i].var2.u32,  ==, 0);
+  }
+
+  for (i = 0; i < len; i++) {
+    unsigned int cluster;
+    cluster = 1+i;
+    if (i >= 2) {
+      if (buffer_type == BUFFER_UTF16)
+	cluster++;
+      else if (buffer_type == BUFFER_UTF8)
+        cluster += 3;
+    }
+    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
+    g_assert_cmphex (glyphs[i].cluster,   ==, cluster);
+  }
+
+  /* reverse, test, and reverse back */
+
+  hb_buffer_reverse (b);
+  for (i = 0; i < len; i++)
+    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
+
+  hb_buffer_reverse (b);
+  for (i = 0; i < len; i++)
+    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
+
+  /* reverse_clusters works same as reverse for now since each codepoint is
+   * in its own cluster */
+
+  hb_buffer_reverse_clusters (b);
+  for (i = 0; i < len; i++)
+    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
+
+  hb_buffer_reverse_clusters (b);
+  for (i = 0; i < len; i++)
+    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
+
+  /* now form a cluster and test again */
+  glyphs[2].cluster = glyphs[1].cluster;
+
+  /* reverse, test, and reverse back */
+
+  hb_buffer_reverse (b);
+  for (i = 0; i < len; i++)
+    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
+
+  hb_buffer_reverse (b);
+  for (i = 0; i < len; i++)
+    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
+
+  /* reverse_clusters twice still should return the original string,
+   * but when applied once, the 1-2 cluster should be retained. */
+
+  hb_buffer_reverse_clusters (b);
+  for (i = 0; i < len; i++) {
+    unsigned int j = len-1-i;
+    if (j == 1)
+      j = 2;
+    else if (j == 2)
+      j = 1;
+    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+j]);
+  }
+
+  hb_buffer_reverse_clusters (b);
+  for (i = 0; i < len; i++)
+    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
+
+
+  /* test setting length */
+
+  /* enlarge */
+  g_assert (hb_buffer_set_length (b, 10));
+  glyphs = hb_buffer_get_glyph_infos (b, NULL);
+  g_assert_cmpint (hb_buffer_get_population (b), ==, 10);
+  for (i = 0; i < 5; i++)
+    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
+  for (i = 5; i < 10; i++)
+    g_assert_cmphex (glyphs[i].codepoint, ==, 0);
+  /* shrink */
+  g_assert (hb_buffer_set_length (b, 3));
+  glyphs = hb_buffer_get_glyph_infos (b, NULL);
+  g_assert_cmpint (hb_buffer_get_population (b), ==, 3);
+  for (i = 0; i < 3; i++)
+    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
+
+
+  g_assert (hb_buffer_allocation_successful (b));
+
+
+  /* test reset clears content */
+
+  hb_buffer_reset (b);
+  g_assert_cmpint (hb_buffer_get_population (b), ==, 0);
+}
+
+static void
+test_buffer_allocation (fixture_t *fixture, gconstpointer user_data)
+{
+  hb_buffer_t *b = fixture->buffer;
+
+  g_assert_cmpint (hb_buffer_get_population (b), ==, 0);
+
+  g_assert (hb_buffer_pre_allocate (b, 100));
+  g_assert_cmpint (hb_buffer_get_population (b), ==, 0);
+  g_assert (hb_buffer_allocation_successful (b));
+
+  /* lets try a huge allocation, make sure it fails */
+  g_assert (!hb_buffer_pre_allocate (b, (unsigned int) -1));
+  g_assert_cmpint (hb_buffer_get_population (b), ==, 0);
+  g_assert (!hb_buffer_allocation_successful (b));
+
+  /* small one again */
+  g_assert (hb_buffer_pre_allocate (b, 50));
+  g_assert_cmpint (hb_buffer_get_population (b), ==, 0);
+  g_assert (!hb_buffer_allocation_successful (b));
+
+  hb_buffer_reset (b);
+  g_assert (hb_buffer_allocation_successful (b));
+
+  /* all allocation and size  */
+  g_assert (!hb_buffer_pre_allocate (b, ((unsigned int) -1) / 20 + 1));
+  g_assert (!hb_buffer_allocation_successful (b));
+
+  hb_buffer_reset (b);
+  g_assert (hb_buffer_allocation_successful (b));
+
+  /* technically, this one can actually pass on 64bit machines, but
+   * I'm doubtful that any malloc allows 4GB allocations at a time.
+   * But let's only enable it on a 32-bit machine. */
+  if (sizeof (long) == 4) {
+    g_assert (!hb_buffer_pre_allocate (b, ((unsigned int) -1) / 20 - 1));
+    g_assert (!hb_buffer_allocation_successful (b));
+  }
+
+  hb_buffer_reset (b);
+  g_assert (hb_buffer_allocation_successful (b));
+}
+#endif
+
+static void
+test_empty (hb_set_t *b)
+{
+  g_assert_cmpint (hb_set_get_population (b), ==, 0);
+  g_assert_cmpint (hb_set_get_min (b), ==, (hb_codepoint_t) -1);
+  g_assert_cmpint (hb_set_get_max (b), ==, (hb_codepoint_t) -1);
+}
+
+static void
+test_set_empty (void)
+{
+  hb_set_t *b = hb_set_get_empty ();
+
+  g_assert (hb_set_get_empty ());
+  g_assert (hb_set_get_empty () == b);
+
+  g_assert (!hb_set_allocation_successful (b));
+
+  test_empty (b);
+
+  hb_set_add (b, 13);
+
+  test_empty (b);
+
+  hb_set_invert (b);
+
+  test_empty (b);
+
+  g_assert (!hb_set_allocation_successful (b));
+
+  hb_set_clear (b);
+
+  test_empty (b);
+
+  g_assert (!hb_set_allocation_successful (b));
+}
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+#if 0
+  hb_test_add (test_set_algebra);
+  hb_test_add (test_set_iter);
+#endif
+  hb_test_add (test_set_empty);
+
+  return hb_test_run();
+}
commit b9d28f696c433b94c5ffbad8d7c87cf3acff4056
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Jan 2 22:49:58 2013 -0600

    [tests] Add set object to test-object.c

diff --git a/test/api/test-object.c b/test/api/test-object.c
index ae4d1cc..3afe6ae 100644
--- a/test/api/test-object.c
+++ b/test/api/test-object.c
@@ -53,6 +53,17 @@ create_buffer_inert (void)
 }
 
 static void *
+create_set (void)
+{
+  return hb_set_create ();
+}
+static void *
+create_set_inert (void)
+{
+  return NULL;
+}
+
+static void *
 create_face (void)
 {
   hb_blob_t *blob = (hb_blob_t *) create_blob ();
@@ -154,6 +165,7 @@ typedef struct {
 static const object_t objects[] =
 {
   OBJECT_WITHOUT_IMMUTABILITY (buffer),
+  OBJECT_WITHOUT_IMMUTABILITY (set),
   OBJECT_WITH_IMMUTABILITY (blob),
   OBJECT_WITH_IMMUTABILITY (face),
   OBJECT_WITH_IMMUTABILITY (font),
commit 11d2956553f0d4a0086166a04ffc352fcfacf56e
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Jan 2 17:41:27 2013 -0600

    Minor

diff --git a/src/hb-atomic-private.hh b/src/hb-atomic-private.hh
index 111d7a0..67579cd 100644
--- a/src/hb-atomic-private.hh
+++ b/src/hb-atomic-private.hh
@@ -59,7 +59,7 @@ static inline void HBMemoryBarrier (void) {
 }
 #endif
 
-typedef long hb_atomic_int_t;
+typedef LONG hb_atomic_int_t;
 #define hb_atomic_int_add(AI, V)	InterlockedExchangeAdd (&(AI), (V))
 
 #define hb_atomic_ptr_get(P)		(HBMemoryBarrier (), (void *) *(P))



More information about the HarfBuzz mailing list