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

Behdad Esfahbod behdad at kemper.freedesktop.org
Fri Apr 15 08:45:40 PDT 2011


 Makefile.am                       |    2 
 TODO                              |   39 +++++--
 configure.ac                      |    1 
 src/Makefile.am                   |    2 
 src/hb-buffer.cc                  |   33 ++++++
 src/hb-buffer.h                   |   16 ++-
 src/hb-common.c                   |   97 ++++++++++++++++++
 src/hb-common.h                   |   56 +++++-----
 src/hb-glib.c                     |    2 
 src/hb-icu.c                      |   64 ++++++------
 src/hb-language.c                 |  120 ----------------------
 src/hb-language.h                 |   46 --------
 src/hb-ot-shape-complex-arabic.cc |    8 -
 src/hb-ot-shape-private.hh        |    2 
 src/hb-ot-shape.cc                |    2 
 src/hb-ot-tag.c                   |    8 -
 src/hb-ot-tag.h                   |    1 
 src/hb-private.h                  |   31 +++++
 src/hb-unicode.c                  |    4 
 src/hb-unicode.h                  |   66 ++++++------
 src/hb.h                          |    1 
 test/Makefile.am                  |   24 ++++
 test/Makefile.decl                |   90 +++++++++++++++++
 test/hb-test.h                    |   75 ++++++++++++++
 test/test-buffer.c                |  200 ++++++++++++++++++++++++++++++++++++++
 test/test-types.c                 |  166 +++++++++++++++++++++++++++++++
 26 files changed, 865 insertions(+), 291 deletions(-)

New commits:
commit 2f2f448af35c232d18888c0e57cb21c9796ba7a8
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Apr 15 11:45:14 2011 -0400

    [test] Add more TODO items

diff --git a/test/test-buffer.c b/test/test-buffer.c
index c5d83c1..d4c9243 100644
--- a/test/test-buffer.c
+++ b/test/test-buffer.c
@@ -193,6 +193,8 @@ main (int argc, char **argv)
   /* XXX test invalid UTF-8 / UTF-16 text input (also overlong sequences) */
   /* XXX test reverse() and reverse_clusters() */
   /* XXX test ensure() and memory management */
+  /* XXX test buffer reset */
+  /* XXX test buffer set length */
 
   return g_test_run();
 }
commit c910bec863215f918c659f58debbc7fe5264d7b6
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 13 15:49:06 2011 -0400

    Add hb_buffer_reset() and hb_buffer_set_length()

diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 5a44a3f..839a256 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 1998-2004  David Turner and Werner Lemberg
  * Copyright (C) 2004,2007,2009,2010  Red Hat, Inc.
+ * Copyright (C) 2011  Google, Inc.
  *
  * This is part of HarfBuzz, a text shaping library.
  *
@@ -23,6 +24,7 @@
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
  */
 
 #include "hb-buffer-private.hh"
@@ -227,6 +229,17 @@ hb_buffer_get_language (hb_buffer_t *buffer)
 
 
 void
+hb_buffer_reset (hb_buffer_t *buffer)
+{
+  hb_buffer_clear (buffer);
+
+  buffer->props = _hb_buffer_nil.props;
+
+  hb_unicode_funcs_destroy (buffer->unicode);
+  buffer->unicode = _hb_buffer_nil.unicode;
+}
+
+void
 hb_buffer_clear (hb_buffer_t *buffer)
 {
   buffer->have_output = FALSE;
@@ -434,6 +447,24 @@ _hb_buffer_set_masks (hb_buffer_t *buffer,
 
 /* Public API again */
 
+hb_bool_t
+hb_buffer_set_length (hb_buffer_t  *buffer,
+		      unsigned int  length)
+{
+  if (!hb_buffer_ensure (buffer, length))
+    return FALSE;
+
+  /* Wipe the new space */
+  if (length > buffer->len) {
+    memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len));
+    if (buffer->have_positions)
+      memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len));
+  }
+
+  buffer->len = length;
+  return TRUE;
+}
+
 unsigned int
 hb_buffer_get_length (hb_buffer_t *buffer)
 {
diff --git a/src/hb-buffer.h b/src/hb-buffer.h
index 652f80b..a2785ee 100644
--- a/src/hb-buffer.h
+++ b/src/hb-buffer.h
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 1998-2004  David Turner and Werner Lemberg
  * Copyright (C) 2004,2007,2009  Red Hat, Inc.
+ * Copyright (C) 2011  Google, Inc.
  *
  * This is part of HarfBuzz, a text shaping library.
  *
@@ -23,6 +24,7 @@
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
  */
 
 #ifndef HB_BUFFER_H
@@ -95,6 +97,12 @@ hb_language_t
 hb_buffer_get_language (hb_buffer_t *buffer);
 
 
+/* Resets the buffer.  Afterwards it's as if it was just created,
+ * except that it has a larger buffer allocated perhaps... */
+void
+hb_buffer_reset (hb_buffer_t *buffer);
+
+/* Clears buffer glyphs, but doesn't touch other buffer attributes. */
 void
 hb_buffer_clear (hb_buffer_t *buffer);
 
@@ -142,12 +150,17 @@ hb_buffer_add_utf32 (hb_buffer_t    *buffer,
 		     unsigned int    item_length);
 
 
-/* Getting glyphs out of the buffer */
+/* Clears any new items added at the end */
+hb_bool_t
+hb_buffer_set_length (hb_buffer_t  *buffer,
+		      unsigned int  length);
 
 /* Return value valid as long as buffer not modified */
 unsigned int
 hb_buffer_get_length (hb_buffer_t *buffer);
 
+/* Getting glyphs out of the buffer */
+
 /* Return value valid as long as buffer not modified */
 hb_glyph_info_t *
 hb_buffer_get_glyph_infos (hb_buffer_t *buffer);
commit 69ea23cb5d47dd1cfd3129f68375021ef79bf63b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 13 15:02:40 2011 -0400

    Minor

diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index c868091..5a44a3f 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -592,7 +592,7 @@ hb_utf16_next (const uint16_t *text,
   if (unlikely (c >= 0xd800 && c < 0xdc00)) {
     /* high surrogate */
     uint16_t l;
-    if (text < end && ((l = *text), unlikely (l >= 0xdc00 && l < 0xe000))) {
+    if (text < end && ((l = *text), likely (l >= 0xdc00 && l < 0xe000))) {
       /* low surrogate */
       *unicode = ((hb_codepoint_t) ((c) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x10000);
        text++;
commit 7dea908cd582c8c25555015940065c69c1e7e65b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 13 01:35:58 2011 -0400

    [test] Add todo items

diff --git a/test/test-buffer.c b/test/test-buffer.c
index 4e7c6e5..c5d83c1 100644
--- a/test/test-buffer.c
+++ b/test/test-buffer.c
@@ -148,6 +148,7 @@ test_buffer_contents (Fixture *fixture, gconstpointer user_data)
   }
 
   hb_buffer_clear (fixture->b);
+  /* XXX Make sure clear() doesn't unset other properties? */
   g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
 }
 
@@ -189,7 +190,9 @@ main (int argc, char **argv)
 #undef TEST_ADD
   }
 
-  /* XXX test invalid UTF-8 / UTF-16 text input */
+  /* XXX test invalid UTF-8 / UTF-16 text input (also overlong sequences) */
+  /* XXX test reverse() and reverse_clusters() */
+  /* XXX test ensure() and memory management */
 
   return g_test_run();
 }
commit 07cbaac07d7f43437b171e9275430b5fb3097716
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 13 01:11:19 2011 -0400

    [TODO] Add item re script iso15924 functions

diff --git a/TODO b/TODO
index 06f850e..def1e21 100644
--- a/TODO
+++ b/TODO
@@ -29,6 +29,8 @@ API issues to fix before 1.0:
 
 - Use tags for hb_script_t
 
+- Better name for iso15924 script functions
+
 - Figure out how many .so objects, how to link, etc
 
 - Shall y axis progress downward instead of upward?
commit d0f53fdbead15d9003b521b8ed47d02fd29a4c64
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 13 01:09:09 2011 -0400

    [test] Test hb-buffer.h

diff --git a/test/Makefile.am b/test/Makefile.am
index 19e38b2..2056b39 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,12 +1,18 @@
 include Makefile.decl
 
+NULL =
+
 if HAVE_GLIB
 AM_CPPFLAGS = -I$(top_srcdir)/src/ $(GLIB_CFLAGS)
 LDADD = $(top_builddir)/src/libharfbuzz.la $(GLIB_LIBS)
 
 check_PROGRAMS = $(TEST_PROGS)
 
-TEST_PROGS += test-types
+TEST_PROGS += \
+	test-buffer \
+	test-types \
+	$(NULL)
+
 
 
 else
diff --git a/test/test-buffer.c b/test/test-buffer.c
new file mode 100644
index 0000000..4e7c6e5
--- /dev/null
+++ b/test/test-buffer.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2010  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"
+
+/* This file tests types defined in hb-buffer.h */
+
+
+static const char utf8[10] = "ab\360\240\200\200defg";
+static const uint16_t utf16[8] = {'a', 'b', 0xD840, 0xDC00, 'd', 'e', 'f', 'g'};
+static const uint32_t utf32[7] = {'a', 'b', 0x20000, 'd', 'e', 'f', 'g'};
+
+typedef enum {
+  BUFFER_EMPTY,
+  BUFFER_ONE_BY_ONE,
+  BUFFER_UTF32,
+  BUFFER_UTF16,
+  BUFFER_UTF8,
+  BUFFER_NUM_TYPES,
+} buffer_type_t;
+
+static const char *buffer_names[] = {
+  "empty",
+  "one-by-one",
+  "utf32",
+  "utf16",
+  "utf8"
+};
+
+typedef struct
+{
+  hb_buffer_t *b;
+} Fixture;
+
+static void
+fixture_init (Fixture *fixture, gconstpointer user_data)
+{
+  unsigned int i;
+
+  fixture->b = hb_buffer_create (0);
+
+  switch (GPOINTER_TO_INT (user_data)) {
+    case BUFFER_EMPTY:
+      break;
+
+    case BUFFER_ONE_BY_ONE:
+      for (i = 1; i < G_N_ELEMENTS (utf32) - 1; i++)
+	hb_buffer_add_glyph (fixture->b, utf32[i], 1, i);
+      break;
+
+    case BUFFER_UTF32:
+      hb_buffer_add_utf32 (fixture->b, utf32, G_N_ELEMENTS (utf32), 1, G_N_ELEMENTS (utf32) - 2);
+      break;
+
+    case BUFFER_UTF16:
+      hb_buffer_add_utf16 (fixture->b, utf16, G_N_ELEMENTS (utf16), 1, G_N_ELEMENTS (utf16) - 2);
+      break;
+
+    case BUFFER_UTF8:
+      hb_buffer_add_utf8  (fixture->b, utf8,  G_N_ELEMENTS (utf8),  1, G_N_ELEMENTS (utf8)  - 2);
+      break;
+
+    default:
+      g_assert_not_reached ();
+  }
+}
+
+static void
+fixture_fini (Fixture *fixture, gconstpointer user_data)
+{
+  hb_buffer_destroy (fixture->b);
+}
+
+
+static void
+test_buffer_properties (Fixture *fixture, gconstpointer user_data)
+{
+  /* TODO check unicode_funcs */
+
+  g_assert (hb_buffer_get_direction (fixture->b) == HB_DIRECTION_LTR);
+  g_assert (hb_buffer_get_script (fixture->b) == HB_SCRIPT_COMMON);
+  g_assert (hb_buffer_get_language (fixture->b) == NULL);
+
+  hb_buffer_set_direction (fixture->b, HB_DIRECTION_RTL);
+  g_assert (hb_buffer_get_direction (fixture->b) == HB_DIRECTION_RTL);
+
+  hb_buffer_set_script (fixture->b, HB_SCRIPT_ARABIC);
+  g_assert (hb_buffer_get_script (fixture->b) == HB_SCRIPT_ARABIC);
+
+  hb_buffer_set_language (fixture->b, hb_language_from_string ("fa"));
+  g_assert (hb_buffer_get_language (fixture->b) == hb_language_from_string ("Fa"));
+}
+
+static void
+test_buffer_contents (Fixture *fixture, gconstpointer user_data)
+{
+  unsigned int i, len;
+  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_length (fixture->b), ==, 0);
+    return;
+  }
+
+  len = hb_buffer_get_length (fixture->b);
+  g_assert_cmpint (len, ==, 5);
+
+  glyphs = hb_buffer_get_glyph_infos (fixture->b);
+
+  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);
+    g_assert_cmphex (glyphs[i].mask,      ==, 1);
+    g_assert_cmphex (glyphs[i].var1.u32,  ==, 0);
+    g_assert_cmphex (glyphs[i].var2.u32,  ==, 0);
+  }
+
+  hb_buffer_clear (fixture->b);
+  g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
+}
+
+static void
+test_buffer_positions (Fixture *fixture, gconstpointer user_data)
+{
+  unsigned int i, len;
+  hb_glyph_position_t *positions;
+
+  /* Without shaping, positions should all be zero */
+  positions = hb_buffer_get_glyph_positions (fixture->b);
+  len = hb_buffer_get_length (fixture->b);
+  for (i = 0; i < len; i++) {
+    g_assert_cmpint (0, ==, positions[i].x_advance);
+    g_assert_cmpint (0, ==, positions[i].y_advance);
+    g_assert_cmpint (0, ==, positions[i].x_offset);
+    g_assert_cmpint (0, ==, positions[i].y_offset);
+    g_assert_cmpint (0, ==, positions[i].var.i32);
+  }
+}
+
+int
+main (int argc, char **argv)
+{
+  int i;
+
+  g_test_init (&argc, &argv, NULL);
+
+  for (i = 0; i < BUFFER_NUM_TYPES; i++) {
+#define TEST_ADD(path, func) \
+    G_STMT_START { \
+      char *s = g_strdup_printf ("%s/%s", path, buffer_names[i]); \
+      g_test_add (s, Fixture, GINT_TO_POINTER (i), fixture_init, func, fixture_fini); \
+      g_free (s); \
+    } G_STMT_END
+    TEST_ADD ("/buffer/properties", test_buffer_properties);
+    TEST_ADD ("/buffer/contents", test_buffer_contents);
+    TEST_ADD ("/buffer/positions", test_buffer_positions);
+#undef TEST_ADD
+  }
+
+  /* XXX test invalid UTF-8 / UTF-16 text input */
+
+  return g_test_run();
+}
commit 72d89404c2837d578f5305456c817130b6a15c73
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 13 01:07:42 2011 -0400

    [TODO] Add item re hb_buffer_reset()

diff --git a/TODO b/TODO
index 4153b60..06f850e 100644
--- a/TODO
+++ b/TODO
@@ -17,6 +17,8 @@ API issues to fix before 1.0:
 
 - Add hb_buffer_resize()?
 
+- Add hb_buffer_reset()?
+
 - Rename / remove hb_buffer_add_glyph()?
 
 - Sprinkle const all over public and private API
commit 5015c12dfb4de8525325178ae6def9e80fd83669
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 13 01:06:02 2011 -0400

    [TODO] Add item re hb_buffer_resize()

diff --git a/TODO b/TODO
index c7cd8d9..4153b60 100644
--- a/TODO
+++ b/TODO
@@ -15,6 +15,8 @@ General fixes:
 API issues to fix before 1.0:
 ============================
 
+- Add hb_buffer_resize()?
+
 - Rename / remove hb_buffer_add_glyph()?
 
 - Sprinkle const all over public and private API
commit 9329ec92078d0e2d7bb04f683e0c6a582aab92f7
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 13 00:06:23 2011 -0400

    [TODO] Add API item

diff --git a/TODO b/TODO
index 1167e24..c7cd8d9 100644
--- a/TODO
+++ b/TODO
@@ -15,6 +15,8 @@ General fixes:
 API issues to fix before 1.0:
 ============================
 
+- Rename / remove hb_buffer_add_glyph()?
+
 - Sprinkle const all over public and private API
 
 - Rename get_table to reference_table
commit 4744379efc6063d94e15ff99381a7ab8b88ee567
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 11 19:47:33 2011 -0400

    Minor

diff --git a/test/test-types.c b/test/test-types.c
index 4a542fc..48aa087 100644
--- a/test/test-types.c
+++ b/test/test-types.c
@@ -31,7 +31,7 @@
 static void
 test_types_int (void)
 {
-  /* We already ASSERT_STATIC these in hb-common.h, but anyway */
+  /* We already ASSERT_STATIC these in hb-private.h, but anyway */
   g_assert_cmpint (sizeof (int8_t), ==, 1);
   g_assert_cmpint (sizeof (uint8_t), ==, 1);
   g_assert_cmpint (sizeof (int16_t), ==, 2);
commit 9385caa8a693df0f06a511a71de9aa407637097c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 11 19:43:51 2011 -0400

    [test] Actually hook up hb_script_t tests
    
    I really shall find a way to automate the test enumeration.  Otherwise
    it's too easy to add a test and wrongly hook it up.  Did it twice today.

diff --git a/test/test-types.c b/test/test-types.c
index 15221a8..4a542fc 100644
--- a/test/test-types.c
+++ b/test/test-types.c
@@ -152,14 +152,14 @@ test_types_language (void)
 }
 
 int
-main (int   argc, char **argv)
+main (int argc, char **argv)
 {
   g_test_init (&argc, &argv, NULL);
 
   g_test_add_func ("/types/int", test_types_int);
   g_test_add_func ("/types/direction", test_types_direction);
   g_test_add_func ("/types/tag", test_types_tag);
-  g_test_add_func ("/types/script", test_types_tag);
+  g_test_add_func ("/types/script", test_types_script);
   g_test_add_func ("/types/language", test_types_language);
 
   return g_test_run();
commit 8e4bb3cacc269ed32187aaaeaa166c64f41a0418
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 11 17:55:58 2011 -0400

    Fold hb-language.[ch] into hb-common.[ch]

diff --git a/src/Makefile.am b/src/Makefile.am
index 88aadf5..2fbf278 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,7 +21,6 @@ HBSOURCES =  \
 	hb-object-private.h \
 	hb-open-file-private.hh \
 	hb-open-type-private.hh \
-	hb-language.c \
 	hb-ot-head-private.hh \
 	hb-private.h \
 	hb-shape.cc \
@@ -34,7 +33,6 @@ HBHEADERS = \
 	hb-buffer.h \
 	hb-common.h \
 	hb-font.h \
-	hb-language.h \
 	hb-shape.h \
 	hb-unicode.h \
 	$(NULL)
diff --git a/src/hb-buffer.h b/src/hb-buffer.h
index 0185415..652f80b 100644
--- a/src/hb-buffer.h
+++ b/src/hb-buffer.h
@@ -30,7 +30,6 @@
 
 #include "hb-common.h"
 #include "hb-unicode.h"
-#include "hb-language.h"
 
 HB_BEGIN_DECLS
 
diff --git a/src/hb-common.c b/src/hb-common.c
index 90cba4e..c57ba0b 100644
--- a/src/hb-common.c
+++ b/src/hb-common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010  Red Hat, Inc.
+ * Copyright (C) 2009,2010  Red Hat, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -29,6 +29,8 @@
 HB_BEGIN_DECLS
 
 
+/* hb_tag_t */
+
 hb_tag_t
 hb_tag_from_string (const char *s)
 {
@@ -47,4 +49,92 @@ hb_tag_from_string (const char *s)
 }
 
 
+/* hb_language_t */
+
+static const char canon_map[256] = {
+   0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,  '-',  0,   0,
+  '0', '1', '2', '3', '4', '5', '6', '7',  '8', '9',  0,   0,   0,   0,   0,   0,
+  '-', 'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,  '-',
+   0,  'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,   0
+};
+
+static hb_bool_t
+lang_equal (const void *v1,
+	    const void *v2)
+{
+  const unsigned char *p1 = v1;
+  const unsigned char *p2 = v2;
+
+  while (canon_map[*p1] && canon_map[*p1] == canon_map[*p2])
+    {
+      p1++, p2++;
+    }
+
+  return (canon_map[*p1] == canon_map[*p2]);
+}
+
+#if 0
+static unsigned int
+lang_hash (const void *key)
+{
+  const unsigned char *p = key;
+  unsigned int h = 0;
+  while (canon_map[*p])
+    {
+      h = (h << 5) - h + canon_map[*p];
+      p++;
+    }
+
+  return h;
+}
+#endif
+
+
+hb_language_t
+hb_language_from_string (const char *str)
+{
+  static unsigned int num_langs;
+  static unsigned int num_alloced;
+  static const char **langs;
+  unsigned int i;
+  unsigned char *p;
+
+  /* TODO Use a hash table or something */
+
+  if (!str || !*str)
+    return NULL;
+
+  for (i = 0; i < num_langs; i++)
+    if (lang_equal (str, langs[i]))
+      return langs[i];
+
+  if (unlikely (num_langs == num_alloced)) {
+    unsigned int new_alloced = 2 * (8 + num_alloced);
+    const char **new_langs = realloc (langs, new_alloced * sizeof (langs[0]));
+    if (!new_langs)
+      return NULL;
+    num_alloced = new_alloced;
+    langs = new_langs;
+  }
+
+  langs[i] = strdup (str);
+  for (p = (unsigned char *) langs[i]; *p; p++)
+    *p = canon_map[*p];
+
+  num_langs++;
+
+  return (hb_language_t) langs[i];
+}
+
+const char *
+hb_language_to_string (hb_language_t language)
+{
+  return (const char *) language;
+}
+
+
 HB_END_DECLS
diff --git a/src/hb-common.h b/src/hb-common.h
index a5ebc29..606e117 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -53,7 +53,26 @@ typedef unsigned long long uint64_t;
 
 typedef int hb_bool_t;
 
+typedef uint32_t hb_codepoint_t;
+typedef int32_t hb_position_t;
+typedef uint32_t hb_mask_t;
+
+typedef union _hb_var_int_t {
+  uint32_t u32;
+  int32_t i32;
+  uint16_t u16[2];
+  int16_t i16[2];
+  uint8_t u8[4];
+  int8_t i8[4];
+} hb_var_int_t;
+
+typedef void (*hb_destroy_func_t) (void *user_data);
+
+
+/* hb_tag_t */
+
 typedef uint32_t hb_tag_t;
+
 #define HB_TAG(a,b,c,d) ((hb_tag_t)((((uint8_t)(a))<<24)|(((uint8_t)(b))<<16)|(((uint8_t)(c))<<8)|((uint8_t)(d))))
 
 #define HB_TAG_NONE HB_TAG(0,0,0,0)
@@ -61,11 +80,7 @@ typedef uint32_t hb_tag_t;
 hb_tag_t hb_tag_from_string (const char *s);
 
 
-typedef uint32_t hb_codepoint_t;
-typedef int32_t hb_position_t;
-typedef uint32_t hb_mask_t;
-
-typedef void (*hb_destroy_func_t) (void *user_data);
+/* hb_direction_t */
 
 typedef enum _hb_direction_t {
   HB_DIRECTION_INVALID = -1,
@@ -82,14 +97,15 @@ typedef enum _hb_direction_t {
 #define HB_DIRECTION_REVERSE(dir)	((hb_direction_t) (((unsigned int) (dir)) ^ 1))
 
 
-typedef union _hb_var_int_t {
-  uint32_t u32;
-  int32_t i32;
-  uint16_t u16[2];
-  int16_t i16[2];
-  uint8_t u8[4];
-  int8_t i8[4];
-} hb_var_int_t;
+/* hb_language_t */
+
+typedef const void *hb_language_t;
+
+hb_language_t
+hb_language_from_string (const char *str);
+
+const char *
+hb_language_to_string (hb_language_t language);
 
 
 HB_END_DECLS
diff --git a/src/hb-language.c b/src/hb-language.c
deleted file mode 100644
index 7c2295a..0000000
--- a/src/hb-language.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2009  Red Hat, 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.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.h"
-
-#include "hb-language.h"
-
-HB_BEGIN_DECLS
-
-
-static const char canon_map[256] = {
-   0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,  '-',  0,   0,
-  '0', '1', '2', '3', '4', '5', '6', '7',  '8', '9',  0,   0,   0,   0,   0,   0,
-  '-', 'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
-  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,  '-',
-   0,  'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
-  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,   0
-};
-
-static hb_bool_t
-lang_equal (const void *v1,
-	    const void *v2)
-{
-  const unsigned char *p1 = v1;
-  const unsigned char *p2 = v2;
-
-  while (canon_map[*p1] && canon_map[*p1] == canon_map[*p2])
-    {
-      p1++, p2++;
-    }
-
-  return (canon_map[*p1] == canon_map[*p2]);
-}
-
-#if 0
-static unsigned int
-lang_hash (const void *key)
-{
-  const unsigned char *p = key;
-  unsigned int h = 0;
-  while (canon_map[*p])
-    {
-      h = (h << 5) - h + canon_map[*p];
-      p++;
-    }
-
-  return h;
-}
-#endif
-
-
-hb_language_t
-hb_language_from_string (const char *str)
-{
-  static unsigned int num_langs;
-  static unsigned int num_alloced;
-  static const char **langs;
-  unsigned int i;
-  unsigned char *p;
-
-  /* TODO Use a hash table or something */
-
-  if (!str || !*str)
-    return NULL;
-
-  for (i = 0; i < num_langs; i++)
-    if (lang_equal (str, langs[i]))
-      return langs[i];
-
-  if (unlikely (num_langs == num_alloced)) {
-    unsigned int new_alloced = 2 * (8 + num_alloced);
-    const char **new_langs = realloc (langs, new_alloced * sizeof (langs[0]));
-    if (!new_langs)
-      return NULL;
-    num_alloced = new_alloced;
-    langs = new_langs;
-  }
-
-  langs[i] = strdup (str);
-  for (p = (unsigned char *) langs[i]; *p; p++)
-    *p = canon_map[*p];
-
-  num_langs++;
-
-  return (hb_language_t) langs[i];
-}
-
-const char *
-hb_language_to_string (hb_language_t language)
-{
-  return (const char *) language;
-}
-
-
-HB_END_DECLS
diff --git a/src/hb-language.h b/src/hb-language.h
deleted file mode 100644
index d3c91fb..0000000
--- a/src/hb-language.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2009  Red Hat, 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.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_LANGUAGE_H
-#define HB_LANGUAGE_H
-
-#include "hb-common.h"
-
-HB_BEGIN_DECLS
-
-
-typedef const void *hb_language_t;
-
-hb_language_t
-hb_language_from_string (const char *str);
-
-const char *
-hb_language_to_string (hb_language_t language);
-
-
-HB_END_DECLS
-
-#endif /* HB_LANGUAGE_H */
diff --git a/src/hb-ot-tag.h b/src/hb-ot-tag.h
index 1eec69f..4a5e26d 100644
--- a/src/hb-ot-tag.h
+++ b/src/hb-ot-tag.h
@@ -28,7 +28,6 @@
 #define HB_OT_TAG_H
 
 #include "hb-common.h"
-#include "hb-language.h"
 
 HB_BEGIN_DECLS
 
diff --git a/src/hb.h b/src/hb.h
index 691adee..e705d65 100644
--- a/src/hb.h
+++ b/src/hb.h
@@ -31,7 +31,6 @@
 #include "hb-buffer.h"
 #include "hb-common.h"
 #include "hb-font.h"
-#include "hb-language.h"
 #include "hb-shape.h"
 #include "hb-unicode.h"
 
commit 09125576ca745b3393f3dc49071df891400bbdc9
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 11 17:49:33 2011 -0400

    [test] Test hb_language_t

diff --git a/test/test-types.c b/test/test-types.c
index 5bc5fcf..15221a8 100644
--- a/test/test-types.c
+++ b/test/test-types.c
@@ -128,15 +128,39 @@ test_types_script (void)
   g_assert_cmpint (hb_script_get_horizontal_direction (hb_script_from_iso15924_tag (wWyZ)), ==, HB_DIRECTION_LTR);
 }
 
+static void
+test_types_language (void)
+{
+  hb_language_t fa = hb_language_from_string ("fa");
+  hb_language_t fa_IR = hb_language_from_string ("fa_IR");
+  hb_language_t fa_ir = hb_language_from_string ("fa-ir");
+  hb_language_t en = hb_language_from_string ("en");
+
+  g_assert (fa != NULL);
+  g_assert (fa_IR != NULL);
+  g_assert (fa_IR == fa_ir);
+
+  g_assert (en != NULL);
+  g_assert (en != fa);
+
+  /* Test recall */
+  g_assert (en == hb_language_from_string ("en"));
+  g_assert (en == hb_language_from_string ("eN"));
+
+  g_assert (NULL == hb_language_from_string (NULL));
+  g_assert (NULL == hb_language_from_string (""));
+}
+
 int
 main (int   argc, char **argv)
 {
   g_test_init (&argc, &argv, NULL);
 
-  g_test_add_func ("/types/direction", test_types_direction);
   g_test_add_func ("/types/int", test_types_int);
+  g_test_add_func ("/types/direction", test_types_direction);
   g_test_add_func ("/types/tag", test_types_tag);
   g_test_add_func ("/types/script", test_types_tag);
+  g_test_add_func ("/types/language", test_types_language);
 
   return g_test_run();
 }
commit 316b7a1afb84a5dfeaed886a585669b4d549c9b7
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 11 17:49:10 2011 -0400

    Make hb_language_from_string("") return NULL language

diff --git a/src/hb-language.c b/src/hb-language.c
index 2aabada..7c2295a 100644
--- a/src/hb-language.c
+++ b/src/hb-language.c
@@ -85,7 +85,7 @@ hb_language_from_string (const char *str)
 
   /* TODO Use a hash table or something */
 
-  if (!str)
+  if (!str || !*str)
     return NULL;
 
   for (i = 0; i < num_langs; i++)
commit db60c96f20426111ffa71e9802ef6e248f8b28d0
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 11 16:17:02 2011 -0400

    [teset] Test hb_script_t

diff --git a/test/hb-test.h b/test/hb-test.h
index 2ec02c2..42f0d44 100644
--- a/test/hb-test.h
+++ b/test/hb-test.h
@@ -62,6 +62,14 @@ hb_test_bug_redhat (unsigned int number)
   hb_test_bug ("http://bugzilla.redhat.com/", number);
 }
 
+
+/* Misc */
+
+/* This is too ugly to be public API, but quite handy. */
+#define HB_TAG_CHAR4(s)   (HB_TAG(((const char *) s)[0], \
+				  ((const char *) s)[1], \
+				  ((const char *) s)[2], \
+				  ((const char *) s)[3]))
 HB_END_DECLS
 
 #endif /* HB_TEST_H */
diff --git a/test/test-types.c b/test/test-types.c
index a5cb31a..5bc5fcf 100644
--- a/test/test-types.c
+++ b/test/test-types.c
@@ -50,7 +50,7 @@ test_types_int (void)
 static void
 test_types_direction (void)
 {
-  g_assert_cmpint ((signed) HB_DIRECTION_INVALID, <, 0);
+  g_assert_cmpint ((signed) HB_DIRECTION_INVALID, ==, -1);
   g_assert_cmpint (HB_DIRECTION_LTR, ==, 0);
 
   g_assert (HB_DIRECTION_IS_HORIZONTAL (HB_DIRECTION_LTR));
@@ -96,6 +96,38 @@ test_types_tag (void)
   g_assert_cmphex (hb_tag_from_string (NULL),    ==, HB_TAG_NONE);
 }
 
+static void
+test_types_script (void)
+{
+  hb_tag_t arab = HB_TAG_CHAR4 ("arab");
+  hb_tag_t Arab = HB_TAG_CHAR4 ("Arab");
+  hb_tag_t ARAB = HB_TAG_CHAR4 ("ARAB");
+
+  hb_tag_t wWyZ = HB_TAG_CHAR4 ("wWyZ");
+  hb_tag_t Wwyz = HB_TAG_CHAR4 ("Wwyz");
+
+  hb_tag_t x123 = HB_TAG_CHAR4 ("x123");
+
+  g_assert_cmpint ((signed) HB_SCRIPT_INVALID, ==, -1);
+  g_assert_cmphex (HB_SCRIPT_ARABIC, !=, HB_SCRIPT_LATIN);
+
+  g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_iso15924_tag (arab));
+  g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_iso15924_tag (Arab));
+  g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_iso15924_tag (ARAB));
+
+  /* Arbitrary tags that look like may be valid ISO 15924 should be preserved. */
+  g_assert_cmphex (HB_SCRIPT_UNKNOWN, !=, hb_script_from_iso15924_tag (wWyZ));
+  /* Otherwise, UNKNOWN should be returned. */
+  g_assert_cmphex (HB_SCRIPT_UNKNOWN, ==, hb_script_from_iso15924_tag (x123));
+
+  g_assert_cmphex (hb_script_to_iso15924_tag (HB_SCRIPT_ARABIC), ==, Arab);
+  g_assert_cmphex (hb_script_to_iso15924_tag (hb_script_from_iso15924_tag (wWyZ)), ==, Wwyz);
+
+  g_assert_cmpint (hb_script_get_horizontal_direction (HB_SCRIPT_LATIN), ==, HB_DIRECTION_LTR);
+  g_assert_cmpint (hb_script_get_horizontal_direction (HB_SCRIPT_ARABIC), ==, HB_DIRECTION_RTL);
+  g_assert_cmpint (hb_script_get_horizontal_direction (hb_script_from_iso15924_tag (wWyZ)), ==, HB_DIRECTION_LTR);
+}
+
 int
 main (int   argc, char **argv)
 {
@@ -104,6 +136,7 @@ main (int   argc, char **argv)
   g_test_add_func ("/types/direction", test_types_direction);
   g_test_add_func ("/types/int", test_types_int);
   g_test_add_func ("/types/tag", test_types_tag);
+  g_test_add_func ("/types/script", test_types_tag);
 
   return g_test_run();
 }
commit 99b74760a4cddc798ab44b5ca897486bbb9c76d6
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 11 15:47:40 2011 -0400

    Rename hb_category_t to hb_unicode_general_category_t

diff --git a/src/hb-glib.c b/src/hb-glib.c
index c548fa6..56123f3 100644
--- a/src/hb-glib.c
+++ b/src/hb-glib.c
@@ -36,7 +36,7 @@ HB_BEGIN_DECLS
 
 
 static hb_codepoint_t hb_glib_get_mirroring (hb_codepoint_t unicode) { g_unichar_get_mirror_char (unicode, &unicode); return unicode; }
-static hb_category_t hb_glib_get_general_category (hb_codepoint_t unicode) { return g_unichar_type (unicode); }
+static hb_unicode_general_category_t hb_glib_get_general_category (hb_codepoint_t unicode) { return g_unichar_type (unicode); }
 static hb_script_t hb_glib_get_script (hb_codepoint_t unicode) { return g_unichar_get_script (unicode); }
 static unsigned int hb_glib_get_combining_class (hb_codepoint_t unicode) { return g_unichar_combining_class (unicode); }
 static unsigned int hb_glib_get_eastasian_width (hb_codepoint_t unicode) { return g_unichar_iswide (unicode); }
diff --git a/src/hb-icu.c b/src/hb-icu.c
index 49230df..0ebc9c5 100644
--- a/src/hb-icu.c
+++ b/src/hb-icu.c
@@ -58,53 +58,53 @@ hb_icu_get_eastasian_width (hb_codepoint_t unicode)
   return 1;
 }
 
-static hb_category_t
+static hb_unicode_general_category_t
 hb_icu_get_general_category (hb_codepoint_t unicode)
 {
   switch (u_getIntPropertyValue(unicode, UCHAR_GENERAL_CATEGORY))
   {
-  case U_UNASSIGNED:			return HB_CATEGORY_UNASSIGNED;
+  case U_UNASSIGNED:			return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
 
-  case U_UPPERCASE_LETTER:		return HB_CATEGORY_UPPERCASE_LETTER;	/* Lu */
-  case U_LOWERCASE_LETTER:		return HB_CATEGORY_LOWERCASE_LETTER;	/* Ll */
-  case U_TITLECASE_LETTER:		return HB_CATEGORY_TITLECASE_LETTER;	/* Lt */
-  case U_MODIFIER_LETTER:		return HB_CATEGORY_MODIFIER_LETTER;	/* Lm */
-  case U_OTHER_LETTER:			return HB_CATEGORY_OTHER_LETTER;	/* Lo */
+  case U_UPPERCASE_LETTER:		return HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER;	/* Lu */
+  case U_LOWERCASE_LETTER:		return HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER;	/* Ll */
+  case U_TITLECASE_LETTER:		return HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER;	/* Lt */
+  case U_MODIFIER_LETTER:		return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER;	/* Lm */
+  case U_OTHER_LETTER:			return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER;	/* Lo */
 
-  case U_NON_SPACING_MARK:		return HB_CATEGORY_NON_SPACING_MARK;	/* Mn */
-  case U_ENCLOSING_MARK:		return HB_CATEGORY_ENCLOSING_MARK;	/* Me */
-  case U_COMBINING_SPACING_MARK:	return HB_CATEGORY_COMBINING_MARK;	/* Mc */
+  case U_NON_SPACING_MARK:		return HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK;	/* Mn */
+  case U_ENCLOSING_MARK:		return HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;	/* Me */
+  case U_COMBINING_SPACING_MARK:	return HB_UNICODE_GENERAL_CATEGORY_COMBINING_MARK;	/* Mc */
 
-  case U_DECIMAL_DIGIT_NUMBER:		return HB_CATEGORY_DECIMAL_NUMBER;	/* Nd */
-  case U_LETTER_NUMBER:			return HB_CATEGORY_LETTER_NUMBER;	/* Nl */
-  case U_OTHER_NUMBER:			return HB_CATEGORY_OTHER_NUMBER;	/* No */
+  case U_DECIMAL_DIGIT_NUMBER:		return HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER;	/* Nd */
+  case U_LETTER_NUMBER:			return HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER;	/* Nl */
+  case U_OTHER_NUMBER:			return HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER;	/* No */
 
-  case U_SPACE_SEPARATOR:		return HB_CATEGORY_SPACE_SEPARATOR;	/* Zs */
-  case U_LINE_SEPARATOR:		return HB_CATEGORY_LINE_SEPARATOR;	/* Zl */
-  case U_PARAGRAPH_SEPARATOR:		return HB_CATEGORY_PARAGRAPH_SEPARATOR;	/* Zp */
+  case U_SPACE_SEPARATOR:		return HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;	/* Zs */
+  case U_LINE_SEPARATOR:		return HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR;	/* Zl */
+  case U_PARAGRAPH_SEPARATOR:		return HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR;	/* Zp */
 
-  case U_CONTROL_CHAR:			return HB_CATEGORY_CONTROL;		/* Cc */
-  case U_FORMAT_CHAR:			return HB_CATEGORY_FORMAT;		/* Cf */
-  case U_PRIVATE_USE_CHAR:		return HB_CATEGORY_PRIVATE_USE;		/* Co */
-  case U_SURROGATE:			return HB_CATEGORY_SURROGATE;		/* Cs */
+  case U_CONTROL_CHAR:			return HB_UNICODE_GENERAL_CATEGORY_CONTROL;		/* Cc */
+  case U_FORMAT_CHAR:			return HB_UNICODE_GENERAL_CATEGORY_FORMAT;		/* Cf */
+  case U_PRIVATE_USE_CHAR:		return HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE;		/* Co */
+  case U_SURROGATE:			return HB_UNICODE_GENERAL_CATEGORY_SURROGATE;		/* Cs */
 
 
-  case U_DASH_PUNCTUATION:		return HB_CATEGORY_DASH_PUNCTUATION;	/* Pd */
-  case U_START_PUNCTUATION:		return HB_CATEGORY_OPEN_PUNCTUATION;	/* Ps */
-  case U_END_PUNCTUATION:		return HB_CATEGORY_CLOSE_PUNCTUATION;	/* Pe */
-  case U_CONNECTOR_PUNCTUATION:		return HB_CATEGORY_CONNECT_PUNCTUATION;	/* Pc */
-  case U_OTHER_PUNCTUATION:		return HB_CATEGORY_OTHER_PUNCTUATION;	/* Po */
+  case U_DASH_PUNCTUATION:		return HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION;	/* Pd */
+  case U_START_PUNCTUATION:		return HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION;	/* Ps */
+  case U_END_PUNCTUATION:		return HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION;	/* Pe */
+  case U_CONNECTOR_PUNCTUATION:		return HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION;	/* Pc */
+  case U_OTHER_PUNCTUATION:		return HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION;	/* Po */
 
-  case U_MATH_SYMBOL:			return HB_CATEGORY_MATH_SYMBOL;		/* Sm */
-  case U_CURRENCY_SYMBOL:		return HB_CATEGORY_CURRENCY_SYMBOL;	/* Sc */
-  case U_MODIFIER_SYMBOL:		return HB_CATEGORY_MODIFIER_SYMBOL;	/* Sk */
-  case U_OTHER_SYMBOL:			return HB_CATEGORY_OTHER_SYMBOL;	/* So */
+  case U_MATH_SYMBOL:			return HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL;		/* Sm */
+  case U_CURRENCY_SYMBOL:		return HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL;	/* Sc */
+  case U_MODIFIER_SYMBOL:		return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL;	/* Sk */
+  case U_OTHER_SYMBOL:			return HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL;	/* So */
 
-  case U_INITIAL_PUNCTUATION:		return HB_CATEGORY_INITIAL_PUNCTUATION;	/* Pi */
-  case U_FINAL_PUNCTUATION:		return HB_CATEGORY_FINAL_PUNCTUATION;	/* Pf */
+  case U_INITIAL_PUNCTUATION:		return HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION;	/* Pi */
+  case U_FINAL_PUNCTUATION:		return HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION;	/* Pf */
   }
 
-  return HB_CATEGORY_UNASSIGNED;
+  return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
 }
 
 static hb_script_t
diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc
index 4aa3398..cc08fbb 100644
--- a/src/hb-ot-shape-complex-arabic.cc
+++ b/src/hb-ot-shape-complex-arabic.cc
@@ -57,7 +57,7 @@ enum {
 
 #include "hb-ot-shape-complex-arabic-table.h"
 
-static unsigned int get_joining_type (hb_codepoint_t u, hb_category_t gen_cat)
+static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_category_t gen_cat)
 {
   /* TODO Macroize the magic bit operations */
 
@@ -71,7 +71,7 @@ static unsigned int get_joining_type (hb_codepoint_t u, hb_category_t gen_cat)
   if (unlikely (0x1800 <= u && u <= 0x18AF))
   {
     /* All letters, SIBE SYLLABLE BOUNDARY MARKER, and NIRUGU are D */
-    if (gen_cat == HB_CATEGORY_OTHER_LETTER || u == 0x1807 || u == 0x180A)
+    if (gen_cat == HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER || u == 0x1807 || u == 0x180A)
       return JOINING_TYPE_D;
   }
 
@@ -79,7 +79,7 @@ static unsigned int get_joining_type (hb_codepoint_t u, hb_category_t gen_cat)
     return u == 0x200C ? JOINING_TYPE_U : JOINING_TYPE_C;
   }
 
-  return ((1<<gen_cat) & ((1<<HB_CATEGORY_NON_SPACING_MARK)|(1<<HB_CATEGORY_ENCLOSING_MARK)|(1<<HB_CATEGORY_FORMAT))) ?
+  return ((1<<gen_cat) & ((1<<HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)|(1<<HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK)|(1<<HB_UNICODE_GENERAL_CATEGORY_FORMAT))) ?
 	 JOINING_TYPE_T : JOINING_TYPE_U;
 }
 
@@ -170,7 +170,7 @@ _hb_ot_shape_complex_setup_masks_arabic	(hb_ot_shape_context_t *c)
 
   for (unsigned int i = 0; i < count; i++)
   {
-    unsigned int this_type = get_joining_type (c->buffer->info[i].codepoint, (hb_category_t) c->buffer->info[i].general_category());
+    unsigned int this_type = get_joining_type (c->buffer->info[i].codepoint, (hb_unicode_general_category_t) c->buffer->info[i].general_category());
 
     if (unlikely (this_type == JOINING_TYPE_T)) {
       c->buffer->info[i].arabic_shaping_action() = NONE;
diff --git a/src/hb-ot-shape-private.hh b/src/hb-ot-shape-private.hh
index deaec97..1a5c670 100644
--- a/src/hb-ot-shape-private.hh
+++ b/src/hb-ot-shape-private.hh
@@ -37,7 +37,7 @@ HB_BEGIN_DECLS
 
 
 /* buffer var allocations */
-#define general_category() var1.u8[0] /* unicode general_category (hb_category_t) */
+#define general_category() var1.u8[0] /* unicode general_category (hb_unicode_general_category_t) */
 #define combining_class() var1.u8[1] /* unicode combining_class (uint8_t) */
 
 
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 9f60e1c..4950e00 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -159,7 +159,7 @@ hb_form_clusters (hb_ot_shape_context_t *c)
 {
   unsigned int count = c->buffer->len;
   for (unsigned int i = 1; i < count; i++)
-    if (c->buffer->info[i].general_category() == HB_CATEGORY_NON_SPACING_MARK)
+    if (c->buffer->info[i].general_category() == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
       c->buffer->info[i].cluster = c->buffer->info[i - 1].cluster;
 }
 
diff --git a/src/hb-unicode.c b/src/hb-unicode.c
index b69eec6..63c39b1 100644
--- a/src/hb-unicode.c
+++ b/src/hb-unicode.c
@@ -36,7 +36,7 @@ HB_BEGIN_DECLS
  */
 
 static hb_codepoint_t hb_unicode_get_mirroring_nil (hb_codepoint_t unicode) { return unicode; }
-static hb_category_t hb_unicode_get_general_category_nil (hb_codepoint_t unicode HB_UNUSED) { return HB_CATEGORY_OTHER_LETTER; }
+static hb_unicode_general_category_t hb_unicode_get_general_category_nil (hb_codepoint_t unicode HB_UNUSED) { return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER; }
 static hb_script_t hb_unicode_get_script_nil (hb_codepoint_t unicode HB_UNUSED) { return HB_SCRIPT_UNKNOWN; }
 static unsigned int hb_unicode_get_combining_class_nil (hb_codepoint_t unicode HB_UNUSED) { return 0; }
 static unsigned int hb_unicode_get_eastasian_width_nil (hb_codepoint_t unicode HB_UNUSED) { return 1; }
@@ -205,7 +205,7 @@ hb_unicode_get_mirroring (hb_unicode_funcs_t *ufuncs,
   return ufuncs->v.get_mirroring (unicode);
 }
 
-hb_category_t
+hb_unicode_general_category_t
 hb_unicode_get_general_category (hb_unicode_funcs_t *ufuncs,
 				 hb_codepoint_t unicode)
 {
diff --git a/src/hb-unicode.h b/src/hb-unicode.h
index 9d13ba4..148b5a2 100644
--- a/src/hb-unicode.h
+++ b/src/hb-unicode.h
@@ -35,37 +35,37 @@ HB_BEGIN_DECLS
 /* Unicode General Category property */
 typedef enum
 {
-  HB_CATEGORY_CONTROL,			/* Cc */
-  HB_CATEGORY_FORMAT,			/* Cf */
-  HB_CATEGORY_UNASSIGNED,		/* Cn */
-  HB_CATEGORY_PRIVATE_USE,		/* Co */
-  HB_CATEGORY_SURROGATE,		/* Cs */
-  HB_CATEGORY_LOWERCASE_LETTER,		/* Ll */
-  HB_CATEGORY_MODIFIER_LETTER,		/* Lm */
-  HB_CATEGORY_OTHER_LETTER,		/* Lo */
-  HB_CATEGORY_TITLECASE_LETTER,		/* Lt */
-  HB_CATEGORY_UPPERCASE_LETTER,		/* Lu */
-  HB_CATEGORY_COMBINING_MARK,		/* Mc */
-  HB_CATEGORY_ENCLOSING_MARK,		/* Me */
-  HB_CATEGORY_NON_SPACING_MARK,		/* Mn */
-  HB_CATEGORY_DECIMAL_NUMBER,		/* Nd */
-  HB_CATEGORY_LETTER_NUMBER,		/* Nl */
-  HB_CATEGORY_OTHER_NUMBER,		/* No */
-  HB_CATEGORY_CONNECT_PUNCTUATION,	/* Pc */
-  HB_CATEGORY_DASH_PUNCTUATION,		/* Pd */
-  HB_CATEGORY_CLOSE_PUNCTUATION,	/* Pe */
-  HB_CATEGORY_FINAL_PUNCTUATION,	/* Pf */
-  HB_CATEGORY_INITIAL_PUNCTUATION,	/* Pi */
-  HB_CATEGORY_OTHER_PUNCTUATION,	/* Po */
-  HB_CATEGORY_OPEN_PUNCTUATION,		/* Ps */
-  HB_CATEGORY_CURRENCY_SYMBOL,		/* Sc */
-  HB_CATEGORY_MODIFIER_SYMBOL,		/* Sk */
-  HB_CATEGORY_MATH_SYMBOL,		/* Sm */
-  HB_CATEGORY_OTHER_SYMBOL,		/* So */
-  HB_CATEGORY_LINE_SEPARATOR,		/* Zl */
-  HB_CATEGORY_PARAGRAPH_SEPARATOR,	/* Zp */
-  HB_CATEGORY_SPACE_SEPARATOR		/* Zs */
-} hb_category_t;
+  HB_UNICODE_GENERAL_CATEGORY_CONTROL,			/* Cc */
+  HB_UNICODE_GENERAL_CATEGORY_FORMAT,			/* Cf */
+  HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED,		/* Cn */
+  HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE,		/* Co */
+  HB_UNICODE_GENERAL_CATEGORY_SURROGATE,		/* Cs */
+  HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER,		/* Ll */
+  HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER,		/* Lm */
+  HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER,		/* Lo */
+  HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER,		/* Lt */
+  HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER,		/* Lu */
+  HB_UNICODE_GENERAL_CATEGORY_COMBINING_MARK,		/* Mc */
+  HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK,		/* Me */
+  HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK,		/* Mn */
+  HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER,		/* Nd */
+  HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER,		/* Nl */
+  HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER,		/* No */
+  HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION,	/* Pc */
+  HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION,		/* Pd */
+  HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION,	/* Pe */
+  HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION,	/* Pf */
+  HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION,	/* Pi */
+  HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION,	/* Po */
+  HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION,		/* Ps */
+  HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL,		/* Sc */
+  HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL,		/* Sk */
+  HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL,		/* Sm */
+  HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL,		/* So */
+  HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR,		/* Zl */
+  HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR,	/* Zp */
+  HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR		/* Zs */
+} hb_unicode_general_category_t;
 
 /* Unicode Script property */
 typedef enum
@@ -218,7 +218,7 @@ hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs);
 /* typedefs */
 
 typedef hb_codepoint_t (*hb_unicode_get_mirroring_func_t) (hb_codepoint_t unicode);
-typedef hb_category_t (*hb_unicode_get_general_category_func_t) (hb_codepoint_t unicode);
+typedef hb_unicode_general_category_t (*hb_unicode_get_general_category_func_t) (hb_codepoint_t unicode);
 typedef hb_script_t (*hb_unicode_get_script_func_t) (hb_codepoint_t unicode);
 typedef unsigned int (*hb_unicode_get_combining_class_func_t) (hb_codepoint_t unicode);
 typedef unsigned int (*hb_unicode_get_eastasian_width_func_t) (hb_codepoint_t unicode);
@@ -273,7 +273,7 @@ hb_codepoint_t
 hb_unicode_get_mirroring (hb_unicode_funcs_t *ufuncs,
 			  hb_codepoint_t unicode);
 
-hb_category_t
+hb_unicode_general_category_t
 hb_unicode_get_general_category (hb_unicode_funcs_t *ufuncs,
 				 hb_codepoint_t unicode);
 
commit 4188096a7722f09ffa9319986c0286071da10a27
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 11 14:58:28 2011 -0400

    Make HB_TAG_CHAR4 private
    
    It's just sugar.

diff --git a/src/hb-common.h b/src/hb-common.h
index d46c4a8..a5ebc29 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -55,10 +55,7 @@ typedef int hb_bool_t;
 
 typedef uint32_t hb_tag_t;
 #define HB_TAG(a,b,c,d) ((hb_tag_t)((((uint8_t)(a))<<24)|(((uint8_t)(b))<<16)|(((uint8_t)(c))<<8)|((uint8_t)(d))))
-#define HB_TAG_CHAR4(s)   (HB_TAG(((const char *) s)[0], \
-				  ((const char *) s)[1], \
-				  ((const char *) s)[2], \
-				  ((const char *) s)[3]))
+
 #define HB_TAG_NONE HB_TAG(0,0,0,0)
 
 hb_tag_t hb_tag_from_string (const char *s);
diff --git a/src/hb-private.h b/src/hb-private.h
index 481015c..ae10b5d 100644
--- a/src/hb-private.h
+++ b/src/hb-private.h
@@ -263,12 +263,17 @@ typedef int hb_mutex_t;
 #define hb_be_uint32_cmp(a,b)	(a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3])
 
 
-/* ASCII character handling */
+/* ASCII tag/character handling */
 
 #define ISALPHA(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
 #define TOUPPER(c) (((c) >= 'a' && (c) <= 'z') ? (c) - 'a' + 'A' : (c))
 #define TOLOWER(c) (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c))
 
+#define HB_TAG_CHAR4(s)   (HB_TAG(((const char *) s)[0], \
+				  ((const char *) s)[1], \
+				  ((const char *) s)[2], \
+				  ((const char *) s)[3]))
+
 
 /* Debug */
 
diff --git a/test/test-types.c b/test/test-types.c
index eb13f13..a5cb31a 100644
--- a/test/test-types.c
+++ b/test/test-types.c
@@ -86,8 +86,6 @@ test_types_tag (void)
 
   g_assert_cmphex (HB_TAG ('a','B','c','D'), ==, 0x61426344);
 
-  g_assert_cmphex (HB_TAG_CHAR4 ("aBcD"), ==, 0x61426344);
-
   g_assert_cmphex (hb_tag_from_string ("aBcDe"), ==, 0x61426344);
   g_assert_cmphex (hb_tag_from_string ("aBcD"),  ==, 0x61426344);
   g_assert_cmphex (hb_tag_from_string ("aBc"),   ==, 0x61426320);
commit 7ff7401c9237cda661869c1cb196d685706ac4e9
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 11 13:27:30 2011 -0400

    Make hb_tag_from_string(NULL) return HB_TAG_NONE

diff --git a/src/hb-common.c b/src/hb-common.c
index 3dfdbe8..90cba4e 100644
--- a/src/hb-common.c
+++ b/src/hb-common.c
@@ -35,6 +35,9 @@ hb_tag_from_string (const char *s)
   char tag[4];
   unsigned int i;
 
+  if (!s)
+    return HB_TAG_NONE;
+
   for (i = 0; i < 4 && s[i]; i++)
     tag[i] = s[i];
   for (; i < 4; i++)
diff --git a/test/test-types.c b/test/test-types.c
index 0f32e42..eb13f13 100644
--- a/test/test-types.c
+++ b/test/test-types.c
@@ -83,6 +83,7 @@ static void
 test_types_tag (void)
 {
   g_assert_cmphex (HB_TAG_NONE, ==, 0);
+
   g_assert_cmphex (HB_TAG ('a','B','c','D'), ==, 0x61426344);
 
   g_assert_cmphex (HB_TAG_CHAR4 ("aBcD"), ==, 0x61426344);
@@ -93,6 +94,8 @@ test_types_tag (void)
   g_assert_cmphex (hb_tag_from_string ("aB"),    ==, 0x61422020);
   g_assert_cmphex (hb_tag_from_string ("a"),     ==, 0x61202020);
   g_assert_cmphex (hb_tag_from_string (""),      ==, 0x20202020);
+
+  g_assert_cmphex (hb_tag_from_string (NULL),    ==, HB_TAG_NONE);
 }
 
 int
commit 02f6e62d6cabc7808c188daef26a1fe7ac626b1f
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 11 13:27:21 2011 -0400

    Build fix

diff --git a/test/Makefile.am b/test/Makefile.am
index 55d3976..19e38b2 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,8 +1,8 @@
 include Makefile.decl
 
 if HAVE_GLIB
-AM_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir)/src/
-LDADD = $(GLIB_LIBS) $(top_builddir)/src/libharfbuzz.la
+AM_CPPFLAGS = -I$(top_srcdir)/src/ $(GLIB_CFLAGS)
+LDADD = $(top_builddir)/src/libharfbuzz.la $(GLIB_LIBS)
 
 check_PROGRAMS = $(TEST_PROGS)
 
commit db5227c40e5c35fe2ffb750f32b639cb44424a1d
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 11 13:16:08 2011 -0400

    Move macros around

diff --git a/src/hb-ot-tag.c b/src/hb-ot-tag.c
index 4017c88..8f62f84 100644
--- a/src/hb-ot-tag.c
+++ b/src/hb-ot-tag.c
@@ -639,10 +639,8 @@ hb_ot_tag_from_language (hb_language_t language)
     char tag[4];
     int i;
     lang_str += 6;
-#define IS_LETTER(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
-#define TO_UPPER(c) (((c) >= 'a' && (c) <= 'z') ? (c) + 'A' - 'a' : (c))
-    for (i = 0; i < 4 && IS_LETTER (lang_str[i]); i++)
-      tag[i] = TO_UPPER (lang_str[i]);
+    for (i = 0; i < 4 && ISALPHA (lang_str[i]); i++)
+      tag[i] = TOUPPER (lang_str[i]);
     for (; i < 4; i++)
       tag[i] = ' ';
     return HB_TAG_CHAR4 (tag);
diff --git a/src/hb-private.h b/src/hb-private.h
index 98dc0bb..481015c 100644
--- a/src/hb-private.h
+++ b/src/hb-private.h
@@ -263,6 +263,13 @@ typedef int hb_mutex_t;
 #define hb_be_uint32_cmp(a,b)	(a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3])
 
 
+/* ASCII character handling */
+
+#define ISALPHA(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
+#define TOUPPER(c) (((c) >= 'a' && (c) <= 'z') ? (c) - 'a' + 'A' : (c))
+#define TOLOWER(c) (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c))
+
+
 /* Debug */
 
 #ifndef HB_DEBUG
commit 07233581c9d953708d3c020907c42b8b89472b89
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 11 13:12:37 2011 -0400

    Rename HB_TAG_STR() to HB_TAG_CHAR4()
    
    The problem with HB_TAG_STR() was that it expected a string of size 4
    exactly, and unlike hb_tag_from_string() it doesn't pad the tag with
    space characters.  So, the new name is more appropriate.

diff --git a/src/hb-common.c b/src/hb-common.c
index 74f8933..3dfdbe8 100644
--- a/src/hb-common.c
+++ b/src/hb-common.c
@@ -40,7 +40,7 @@ hb_tag_from_string (const char *s)
   for (; i < 4; i++)
     tag[i] = ' ';
 
-  return HB_TAG_STR (tag);
+  return HB_TAG_CHAR4 (tag);
 }
 
 
diff --git a/src/hb-common.h b/src/hb-common.h
index ba65ec1..d46c4a8 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -55,10 +55,10 @@ typedef int hb_bool_t;
 
 typedef uint32_t hb_tag_t;
 #define HB_TAG(a,b,c,d) ((hb_tag_t)((((uint8_t)(a))<<24)|(((uint8_t)(b))<<16)|(((uint8_t)(c))<<8)|((uint8_t)(d))))
-#define HB_TAG_STR(s)   (HB_TAG(((const char *) s)[0], \
-				((const char *) s)[1], \
-				((const char *) s)[2], \
-				((const char *) s)[3]))
+#define HB_TAG_CHAR4(s)   (HB_TAG(((const char *) s)[0], \
+				  ((const char *) s)[1], \
+				  ((const char *) s)[2], \
+				  ((const char *) s)[3]))
 #define HB_TAG_NONE HB_TAG(0,0,0,0)
 
 hb_tag_t hb_tag_from_string (const char *s);
diff --git a/src/hb-ot-tag.c b/src/hb-ot-tag.c
index df86bd4..4017c88 100644
--- a/src/hb-ot-tag.c
+++ b/src/hb-ot-tag.c
@@ -645,7 +645,7 @@ hb_ot_tag_from_language (hb_language_t language)
       tag[i] = TO_UPPER (lang_str[i]);
     for (; i < 4; i++)
       tag[i] = ' ';
-    return HB_TAG_STR (tag);
+    return HB_TAG_CHAR4 (tag);
   }
 
   /* find a language matching in the first component */
diff --git a/test/test-types.c b/test/test-types.c
index 1c72673..0f32e42 100644
--- a/test/test-types.c
+++ b/test/test-types.c
@@ -85,7 +85,7 @@ test_types_tag (void)
   g_assert_cmphex (HB_TAG_NONE, ==, 0);
   g_assert_cmphex (HB_TAG ('a','B','c','D'), ==, 0x61426344);
 
-  g_assert_cmphex (HB_TAG_STR ("aBcD"), ==, 0x61426344);
+  g_assert_cmphex (HB_TAG_CHAR4 ("aBcD"), ==, 0x61426344);
 
   g_assert_cmphex (hb_tag_from_string ("aBcDe"), ==, 0x61426344);
   g_assert_cmphex (hb_tag_from_string ("aBcD"),  ==, 0x61426344);
commit 9faa980067f802f712c2adf8263152ed40c98088
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 11 12:46:49 2011 -0400

    Add an in-tree test suite
    
    Uses the glib testing framework.  Wrote unit tests for hb-common.h
    types.

diff --git a/Makefile.am b/Makefile.am
index e81c0bc..95c5701 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = src
+SUBDIRS = src test
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = harfbuzz.pc
diff --git a/test/Makefile.am b/test/Makefile.am
index e69de29..55d3976 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -0,0 +1,18 @@
+include Makefile.decl
+
+if HAVE_GLIB
+AM_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir)/src/
+LDADD = $(GLIB_LIBS) $(top_builddir)/src/libharfbuzz.la
+
+check_PROGRAMS = $(TEST_PROGS)
+
+TEST_PROGS += test-types
+
+
+else
+check-am:
+	@echo "You need to have glib support enabled to run the tests"
+	@exit 77
+endif
+
+-include $(top_srcdir)/git.mk
diff --git a/test/Makefile.decl b/test/Makefile.decl
new file mode 100644
index 0000000..c226169
--- /dev/null
+++ b/test/Makefile.decl
@@ -0,0 +1,90 @@
+GTESTER = gtester 			# for non-GLIB packages
+#GTESTER = $(top_builddir)/glib/gtester			# for the GLIB package
+#GTESTER_REPORT = $(top_builddir)/glib/gtester-report	# for the GLIB package
+
+# initialize variables for unconditional += appending
+EXTRA_DIST =
+TEST_PROGS =
+
+### testing rules
+
+# test: run all tests in cwd and subdirs
+test: test-nonrecursive
+	@ for subdir in $(SUBDIRS) . ; do \
+	    test "$$subdir" = "." -o "$$subdir" = "po" || \
+	    ( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $? ; \
+	  done
+
+# test-nonrecursive: run tests only in cwd
+test-nonrecursive: ${TEST_PROGS}
+	@test -z "${TEST_PROGS}" || MALLOC_CHECK_=2 MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256)) ${GTESTER} --verbose ${TEST_PROGS}
+
+# test-report: run tests in subdirs and generate report
+# perf-report: run tests in subdirs with -m perf and generate report
+# full-report: like test-report: with -m perf and -m slow
+test-report perf-report full-report:	${TEST_PROGS}
+	@test -z "${TEST_PROGS}" || { \
+	  case $@ in \
+	  test-report) test_options="-k";; \
+	  perf-report) test_options="-k -m=perf";; \
+	  full-report) test_options="-k -m=perf -m=slow";; \
+	  esac ; \
+	  if test -z "$$GTESTER_LOGDIR" ; then	\
+	    ${GTESTER} --verbose $$test_options -o test-report.xml ${TEST_PROGS} ; \
+	  elif test -n "${TEST_PROGS}" ; then \
+	    ${GTESTER} --verbose $$test_options -o `mktemp "$$GTESTER_LOGDIR/log-XXXXXX"` ${TEST_PROGS} ; \
+	  fi ; \
+	}
+	@ ignore_logdir=true ; \
+	  if test -z "$$GTESTER_LOGDIR" ; then \
+	    GTESTER_LOGDIR=`mktemp -d "\`pwd\`/.testlogs-XXXXXX"`; export GTESTER_LOGDIR ; \
+	    ignore_logdir=false ; \
+	  fi ; \
+	  if test -d "$(top_srcdir)/.git" ; then \
+	    REVISION=`git describe` ; \
+	  else \
+	    REVISION=$(VERSION) ; \
+	  fi ; \
+	  for subdir in $(SUBDIRS) . ; do \
+	    test "$$subdir" = "." -o "$$subdir" = "po" || \
+	    ( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $? ; \
+	  done ; \
+	  $$ignore_logdir || { \
+	    echo '<?xml version="1.0"?>'              > $@.xml ; \
+	    echo '<report-collection>'               >> $@.xml ; \
+	    echo '<info>'                            >> $@.xml ; \
+	    echo '  <package>$(PACKAGE)</package>'   >> $@.xml ; \
+	    echo '  <version>$(VERSION)</version>'   >> $@.xml ; \
+	    echo "  <revision>$$REVISION</revision>" >> $@.xml ; \
+	    echo '</info>'                           >> $@.xml ; \
+	    for lf in `ls -L "$$GTESTER_LOGDIR"/.` ; do \
+	      sed '1,1s/^<?xml\b[^>?]*?>//' <"$$GTESTER_LOGDIR"/"$$lf" >> $@.xml ; \
+	    done ; \
+	    echo >> $@.xml ; \
+	    echo '</report-collection>' >> $@.xml ; \
+	    rm -rf "$$GTESTER_LOGDIR"/ ; \
+	    ${GTESTER_REPORT} --version 2>/dev/null 1>&2 ; test "$$?" != 0 || ${GTESTER_REPORT} $@.xml >$@.html ; \
+	  }
+.PHONY: test test-report perf-report full-report test-nonrecursive
+
+.PHONY: lcov genlcov lcov-clean
+# use recursive makes in order to ignore errors during check
+lcov:
+	-$(MAKE) $(AM_MAKEFLAGS) -k check
+	$(MAKE) $(AM_MAKEFLAGS) genlcov
+
+# we have to massage the lcov.info file slightly to hide the effect of libtool
+# placing the objects files in the .libs/ directory separate from the *.c
+# we also have to delete tests/.libs/libmoduletestplugin_*.gcda
+genlcov:
+	rm -f $(top_builddir)/tests/.libs/libmoduletestplugin_*.gcda
+	$(LTP) --directory $(top_builddir) --capture --output-file glib-lcov.info --test-name GLIB_PERF --no-checksum --compat-libtool
+	LANG=C $(LTP_GENHTML) --prefix $(top_builddir) --output-directory glib-lcov --title "GLib Code Coverage" --legend --show-details glib-lcov.info
+
+lcov-clean:
+	-$(LTP) --directory $(top_builddir) -z
+	-rm -rf glib-lcov.info glib-lcov
+	-find -name '*.gcda' -print | xargs rm
+
+# run tests in cwd as part of make check
+check-local: test-nonrecursive
diff --git a/test/hb-test.h b/test/hb-test.h
new file mode 100644
index 0000000..2ec02c2
--- /dev/null
+++ b/test/hb-test.h
@@ -0,0 +1,67 @@
+/* * Copyright (C) 2010  Google, Inc.  * *  This is part of HarfBuzz, a text shaping library.  * * Permission is hereby granted, without written agreement and without * license or royalty fees, to use, copy, modify, and distribute this * software and its documentation for any purpose, provided that the * above copyright notice and the following two paragraphs appear in * all copies of this software.  * * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_TEST_H
+#define HB_TEST_H
+
+#include <hb.h>
+#include <hb-glib.h>
+
+#include <glib.h>
+
+#include <stdlib.h>
+
+HB_BEGIN_DECLS
+
+/* Just in case */
+#undef G_DISABLE_ASSERT
+
+
+/* Bugzilla helpers */
+
+static inline void
+hb_test_bug (const char *uri_base, unsigned int number)
+{
+  char *s = g_strdup_printf ("%u", number);
+
+  g_test_bug_base (uri_base);
+  g_test_bug (s);
+
+  g_free (s);
+}
+
+static inline void
+hb_test_bug_freedesktop (unsigned int number)
+{
+  hb_test_bug ("http://bugs.freedesktop.org/", number);
+}
+
+static inline void
+hb_test_bug_gnome (unsigned int number)
+{
+  hb_test_bug ("http://bugzilla.gnome.org/", number);
+}
+
+static inline void
+hb_test_bug_mozilla (unsigned int number)
+{
+  hb_test_bug ("http://bugzilla.mozilla.org/", number);
+}
+
+static inline void
+hb_test_bug_redhat (unsigned int number)
+{
+  hb_test_bug ("http://bugzilla.redhat.com/", number);
+}
+
+HB_END_DECLS
+
+#endif /* HB_TEST_H */
diff --git a/test/test-types.c b/test/test-types.c
new file mode 100644
index 0000000..1c72673
--- /dev/null
+++ b/test/test-types.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2010  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"
+
+/* This file tests types defined in hb-common.h */
+
+static void
+test_types_int (void)
+{
+  /* We already ASSERT_STATIC these in hb-common.h, but anyway */
+  g_assert_cmpint (sizeof (int8_t), ==, 1);
+  g_assert_cmpint (sizeof (uint8_t), ==, 1);
+  g_assert_cmpint (sizeof (int16_t), ==, 2);
+  g_assert_cmpint (sizeof (uint16_t), ==, 2);
+  g_assert_cmpint (sizeof (int32_t), ==, 4);
+  g_assert_cmpint (sizeof (uint32_t), ==, 4);
+  g_assert_cmpint (sizeof (int64_t), ==, 8);
+  g_assert_cmpint (sizeof (uint64_t), ==, 8);
+
+  g_assert_cmpint (sizeof (hb_codepoint_t), ==, 4);
+  g_assert_cmpint (sizeof (hb_position_t), ==, 4);
+  g_assert_cmpint (sizeof (hb_mask_t), ==, 4);
+  g_assert_cmpint (sizeof (hb_var_int_t), ==, 4);
+}
+
+static void
+test_types_direction (void)
+{
+  g_assert_cmpint ((signed) HB_DIRECTION_INVALID, <, 0);
+  g_assert_cmpint (HB_DIRECTION_LTR, ==, 0);
+
+  g_assert (HB_DIRECTION_IS_HORIZONTAL (HB_DIRECTION_LTR));
+  g_assert (HB_DIRECTION_IS_HORIZONTAL (HB_DIRECTION_RTL));
+  g_assert (!HB_DIRECTION_IS_HORIZONTAL (HB_DIRECTION_TTB));
+  g_assert (!HB_DIRECTION_IS_HORIZONTAL (HB_DIRECTION_BTT));
+
+  g_assert (!HB_DIRECTION_IS_VERTICAL (HB_DIRECTION_LTR));
+  g_assert (!HB_DIRECTION_IS_VERTICAL (HB_DIRECTION_RTL));
+  g_assert (HB_DIRECTION_IS_VERTICAL (HB_DIRECTION_TTB));
+  g_assert (HB_DIRECTION_IS_VERTICAL (HB_DIRECTION_BTT));
+
+  g_assert (HB_DIRECTION_IS_FORWARD (HB_DIRECTION_LTR));
+  g_assert (HB_DIRECTION_IS_FORWARD (HB_DIRECTION_TTB));
+  g_assert (!HB_DIRECTION_IS_FORWARD (HB_DIRECTION_RTL));
+  g_assert (!HB_DIRECTION_IS_FORWARD (HB_DIRECTION_BTT));
+
+  g_assert (!HB_DIRECTION_IS_BACKWARD (HB_DIRECTION_LTR));
+  g_assert (!HB_DIRECTION_IS_BACKWARD (HB_DIRECTION_TTB));
+  g_assert (HB_DIRECTION_IS_BACKWARD (HB_DIRECTION_RTL));
+  g_assert (HB_DIRECTION_IS_BACKWARD (HB_DIRECTION_BTT));
+
+  g_assert_cmpint (HB_DIRECTION_REVERSE (HB_DIRECTION_LTR), ==, HB_DIRECTION_RTL);
+  g_assert_cmpint (HB_DIRECTION_REVERSE (HB_DIRECTION_RTL), ==, HB_DIRECTION_LTR);
+  g_assert_cmpint (HB_DIRECTION_REVERSE (HB_DIRECTION_TTB), ==, HB_DIRECTION_BTT);
+  g_assert_cmpint (HB_DIRECTION_REVERSE (HB_DIRECTION_BTT), ==, HB_DIRECTION_TTB);
+}
+
+static void
+test_types_tag (void)
+{
+  g_assert_cmphex (HB_TAG_NONE, ==, 0);
+  g_assert_cmphex (HB_TAG ('a','B','c','D'), ==, 0x61426344);
+
+  g_assert_cmphex (HB_TAG_STR ("aBcD"), ==, 0x61426344);
+
+  g_assert_cmphex (hb_tag_from_string ("aBcDe"), ==, 0x61426344);
+  g_assert_cmphex (hb_tag_from_string ("aBcD"),  ==, 0x61426344);
+  g_assert_cmphex (hb_tag_from_string ("aBc"),   ==, 0x61426320);
+  g_assert_cmphex (hb_tag_from_string ("aB"),    ==, 0x61422020);
+  g_assert_cmphex (hb_tag_from_string ("a"),     ==, 0x61202020);
+  g_assert_cmphex (hb_tag_from_string (""),      ==, 0x20202020);
+}
+
+int
+main (int   argc, char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+
+  g_test_add_func ("/types/direction", test_types_direction);
+  g_test_add_func ("/types/int", test_types_int);
+  g_test_add_func ("/types/tag", test_types_tag);
+
+  return g_test_run();
+}
commit d77b76200efbaa0611691920f9f2018b1e8be340
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 11 12:29:52 2011 -0400

    Add few more paratheses to the HB_TAG macro
    
    Never hurts.

diff --git a/src/hb-common.h b/src/hb-common.h
index 6648486..ba65ec1 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -54,7 +54,7 @@ typedef unsigned long long uint64_t;
 typedef int hb_bool_t;
 
 typedef uint32_t hb_tag_t;
-#define HB_TAG(a,b,c,d) ((hb_tag_t)(((uint8_t)a<<24)|((uint8_t)b<<16)|((uint8_t)c<<8)|(uint8_t)d))
+#define HB_TAG(a,b,c,d) ((hb_tag_t)((((uint8_t)(a))<<24)|(((uint8_t)(b))<<16)|(((uint8_t)(c))<<8)|((uint8_t)(d))))
 #define HB_TAG_STR(s)   (HB_TAG(((const char *) s)[0], \
 				((const char *) s)[1], \
 				((const char *) s)[2], \
commit b13640de6992de9ee9d07e3581c33b8181b70ff9
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 11 12:29:31 2011 -0400

    A few more ASSERTs

diff --git a/src/hb-private.h b/src/hb-private.h
index 69a8153..98dc0bb 100644
--- a/src/hb-private.h
+++ b/src/hb-private.h
@@ -90,6 +90,9 @@ ASSERT_STATIC (sizeof (uint32_t) == 4);
 ASSERT_STATIC (sizeof (int64_t) == 8);
 ASSERT_STATIC (sizeof (uint64_t) == 8);
 
+ASSERT_STATIC (sizeof (hb_codepoint_t) == 4);
+ASSERT_STATIC (sizeof (hb_position_t) == 4);
+ASSERT_STATIC (sizeof (hb_mask_t) == 4);
 ASSERT_STATIC (sizeof (hb_var_int_t) == 4);
 
 /* Misc */
commit ae9eeaff9300f3bb7bed588c5478e8e5461b3df0
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 11 11:49:08 2011 -0400

    Remove warning message from public header file
    
    Since we now assert thos in hb-private.h, the int types cannot be wrong.
    (Except for when someone else includes hb-common.h in a very broken
    configuration, but that's not our problem!)
    
    Plus, we don't use inline in the public headers, so remove that too.

diff --git a/src/hb-common.h b/src/hb-common.h
index ebb10b3..6648486 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -39,10 +39,6 @@ HB_BEGIN_DECLS
 
 
 #ifdef _MSC_VER
-#define _HB__STR2__(x) #x
-#define _HB__STR1__(x) _HB__STR2__(x)
-#define _HB__LOC__ __FILE__ "("_HB__STR1__(__LINE__)") : Warning Msg: "
-#pragma message(_HB__LOC__"Not using stdint.h; integer types may have wrong size")
 typedef signed char int8_t;
 typedef unsigned char uint8_t;
 typedef signed short int16_t;
@@ -51,9 +47,6 @@ typedef signed int int32_t;
 typedef unsigned int uint32_t;
 typedef signed long long int64_t;
 typedef unsigned long long uint64_t;
-#ifndef __cplusplus
-#define inline __inline
-#endif
 #else
 #include <stdint.h>
 #endif
diff --git a/src/hb-private.h b/src/hb-private.h
index eecb441..69a8153 100644
--- a/src/hb-private.h
+++ b/src/hb-private.h
@@ -90,6 +90,7 @@ ASSERT_STATIC (sizeof (uint32_t) == 4);
 ASSERT_STATIC (sizeof (int64_t) == 8);
 ASSERT_STATIC (sizeof (uint64_t) == 8);
 
+ASSERT_STATIC (sizeof (hb_var_int_t) == 4);
 
 /* Misc */
 
@@ -223,6 +224,9 @@ typedef GStaticMutex hb_mutex_t;
 #else
 
 #ifdef _MSC_VER
+#define _HB__STR2__(x) #x
+#define _HB__STR1__(x) _HB__STR2__(x)
+#define _HB__LOC__ __FILE__ "("_HB__STR1__(__LINE__)") : Warning Msg: "
 #pragma message(_HB__LOC__"Could not find any system to define platform macros, library will NOT be thread-safe")
 #else
 #warning "Could not find any system to define platform macros, library will NOT be thread-safe"
commit 6fd5364bdc3a2b459175377e9e16c86cff054232
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 11 11:47:14 2011 -0400

    Assert int types

diff --git a/src/hb-private.h b/src/hb-private.h
index 9f4f8b7..eecb441 100644
--- a/src/hb-private.h
+++ b/src/hb-private.h
@@ -79,6 +79,18 @@ HB_BEGIN_DECLS
 #define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond))
 
 
+/* Lets assert int types.  Saves trouble down the road. */
+
+ASSERT_STATIC (sizeof (int8_t) == 1);
+ASSERT_STATIC (sizeof (uint8_t) == 1);
+ASSERT_STATIC (sizeof (int16_t) == 2);
+ASSERT_STATIC (sizeof (uint16_t) == 2);
+ASSERT_STATIC (sizeof (int32_t) == 4);
+ASSERT_STATIC (sizeof (uint32_t) == 4);
+ASSERT_STATIC (sizeof (int64_t) == 8);
+ASSERT_STATIC (sizeof (uint64_t) == 8);
+
+
 /* Misc */
 
 
commit bbdeff59646e5502b9fc53ab1761b3f014ee276c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 7 16:05:07 2011 -0400

    Add test directory

diff --git a/configure.ac b/configure.ac
index 3e83a38..2c612a5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -88,6 +88,7 @@ AC_CONFIG_FILES([
 harfbuzz.pc
 Makefile
 src/Makefile
+test/Makefile
 ])
 
 AC_OUTPUT
diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644
index 0000000..e69de29
commit 4accc92afc702177ea53280d977cec839af3c12c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 7 15:53:26 2011 -0400

    Update TODO items

diff --git a/TODO b/TODO
index 5a33c3c..1167e24 100644
--- a/TODO
+++ b/TODO
@@ -2,9 +2,10 @@ General fixes:
 =============
 
 - Instead of forming clusters immediately, only do it if we are reversing
-  the text.  We'd need a separate bit to indicate cluster start then
+  the text.  We'd need a separate bit to indicate cluster start then.
+  Right now, BTW, for non-native direction runs, we get the cluster wrong...
 
-- Fix tt kern on/off
+- Fix tt kern on/off and GPOS interaction
 
 - Remove fixed-size feature/lookup arrays in hb-ot-map
 
@@ -20,12 +21,26 @@ API issues to fix before 1.0:
 
 - get_table shouldn't return NULL
 
-- Use tags for hb_script_t?
+- Use tags for hb_script_t
 
 - Figure out how many .so objects, how to link, etc
 
 - Shall y axis progress downward instead of upward?
 
+- User-data support ala cairo
+
+- Real subclassing support for vfunc vectors
+
+- Investigate Mozilla's user-data issue, make sure it's addressed
+
+- Add hb-glib / hb-icu two-way script conversion API
+
+- Add hb-cairo glue
+
+- Fix blob, remove mutex, etc.
+
+- Add sanitize API (since may affect blob API)
+
 
 API to add (maybe after 1.0):
 ============================
@@ -34,21 +49,15 @@ API to add (maybe after 1.0):
 
 - Add hb_shape_plan()/hb_shape_execute()
 
-- Add sanitize API
-
 - Add query API for aalt-like features?
 
 - SFNT api? get_num_faces?
 
 - Full matrix instead of scale?
 
-- Add hb-glib / hb-icu script conversion API
-
 - Add segmentation API
 
-- Add hb-cairo
-
-- Add hb-fribidi
+- Add hb-fribidi?
 
 
 Build fixes:
@@ -62,7 +71,7 @@ Build fixes:
 Optimizations:
 =============
 
-- Avoid allocating blob objects internally for for_data() faces
+- Avoid allocating blob objects internally for for_data() faces?
 
 - Add caching layer to hb-ft
 



More information about the HarfBuzz mailing list