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

Behdad Esfahbod behdad at kemper.freedesktop.org
Thu May 13 10:34:54 PDT 2010


 src/Makefile.am                      |   19 -
 src/check-internal-symbols.sh        |   28 +
 src/hb-blob-private.h                |    2 
 src/hb-buffer-private.h              |  156 --------
 src/hb-buffer-private.hh             |  175 +++++++++
 src/hb-buffer.c                      |  650 -----------------------------------
 src/hb-buffer.cc                     |  637 ++++++++++++++++++++++++++++++++++
 src/hb-common.h                      |    9 
 src/hb-font-private.h                |   92 ----
 src/hb-font-private.hh               |   92 ++++
 src/hb-font.cc                       |    4 
 src/hb-ft.c                          |  240 ------------
 src/hb-ft.cc                         |  240 ++++++++++++
 src/hb-open-type-private.hh          |   11 
 src/hb-ot-layout-common-private.hh   |    2 
 src/hb-ot-layout-gdef-private.hh     |    2 
 src/hb-ot-layout-gsub-private.hh     |   34 -
 src/hb-ot-layout-gsubgpos-private.hh |    6 
 src/hb-ot-layout-private.h           |  121 ------
 src/hb-ot-layout-private.hh          |  121 ++++++
 src/hb-ot-layout.cc                  |    2 
 src/hb-ot-shape-private.h            |   53 --
 src/hb-ot-shape-private.hh           |   53 ++
 src/hb-ot-shape.c                    |  164 --------
 src/hb-ot-shape.cc                   |  164 ++++++++
 src/hb-private.h                     |    8 
 src/hb-shape.c                       |  258 -------------
 src/hb-shape.cc                      |  258 +++++++++++++
 src/hb-unicode-private.h             |    3 
 src/hb-unicode.c                     |    2 
 30 files changed, 1824 insertions(+), 1782 deletions(-)

New commits:
commit f679635893eebc13402c5ee51a6f106eed0c76be
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 13 13:34:17 2010 -0400

    Don't use variable-length-arrays

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index adbd4c7..a57bef5 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -77,9 +77,14 @@ inline Type& StructAfter(TObject &X)
  * Size checking
  */
 
+/* Check _assertion in a method environment */
 #define _DEFINE_SIZE_ASSERTION(_assertion) \
   inline void _size_assertion (void) const \
   { ASSERT_STATIC (_assertion); }
+/* Check that _code compiles in a method environment */
+#define _DEFINE_COMPILES_ASSERTION(_code) \
+  inline void _compiles_assertion (void) const \
+  { _code; }
 
 
 #define DEFINE_SIZE_STATIC(size) \
@@ -99,11 +104,13 @@ inline Type& StructAfter(TObject &X)
   static const unsigned int min_size = (size)
 
 #define DEFINE_SIZE_ARRAY(size, array) \
-  _DEFINE_SIZE_ASSERTION (sizeof (*this) == (size) + array[0].static_size); \
+  _DEFINE_SIZE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \
+  _DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
   static const unsigned int min_size = (size)
 
 #define DEFINE_SIZE_ARRAY2(size, array1, array2) \
-  _DEFINE_SIZE_ASSERTION (sizeof (*this) == (size) + this->array1[0].static_size + this->array2[0].static_size); \
+  _DEFINE_SIZE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
+  _DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \
   static const unsigned int min_size = (size)
 
 
commit 72071a8afaba2952fe42be093024ae9dbd37f233
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 13 13:22:24 2010 -0400

    Add a few more buffer convenience methods

diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index 73bae80..db67f81 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -130,6 +130,18 @@ struct _hb_buffer_t {
   inline void swap (void) { _hb_buffer_swap (this); }
   inline void clear_output (void) { _hb_buffer_clear_output (this); }
   inline void next_glyph (void) { _hb_buffer_next_glyph (this); }
+  inline void add_output_glyphs (unsigned int num_in,
+				 unsigned int num_out,
+				 const hb_codepoint_t *glyph_data,
+				 unsigned short component,
+				 unsigned short ligID)
+  { _hb_buffer_add_output_glyphs (this, num_in, num_out, glyph_data, component, ligID); }
+  inline void add_output_glyphs_be16 (unsigned int num_in,
+				      unsigned int num_out,
+				      const uint16_t *glyph_data_be,
+				      unsigned short component,
+				      unsigned short ligID)
+  { _hb_buffer_add_output_glyphs_be16 (this, num_in, num_out, glyph_data_be, component, ligID); }
   inline void add_output_glyph (hb_codepoint_t glyph_index,
 				unsigned short component = 0xFFFF,
 				unsigned short ligID = 0xFFFF)
diff --git a/src/hb-ot-layout-gsub-private.hh b/src/hb-ot-layout-gsub-private.hh
index 9a4b2e8..2b5919e 100644
--- a/src/hb-ot-layout-gsub-private.hh
+++ b/src/hb-ot-layout-gsub-private.hh
@@ -166,9 +166,9 @@ struct Sequence
     if (unlikely (!substitute.len))
       return false;
 
-    _hb_buffer_add_output_glyphs_be16 (context->buffer, 1,
-				       substitute.len, (const uint16_t *) substitute.array,
-				       0xFFFF, 0xFFFF);
+    context->buffer->add_output_glyphs_be16 (1,
+					     substitute.len, (const uint16_t *) substitute.array,
+					     0xFFFF, 0xFFFF);
 
     /* This is a guess only ... */
     if (_hb_ot_layout_has_new_glyph_classes (context->layout->face))
@@ -400,15 +400,15 @@ struct Ligature
     if (j == context->buffer->in_pos + i) /* No input glyphs skipped */
       /* We don't use a new ligature ID if there are no skipped
 	 glyphs and the ligature already has an ID. */
-      _hb_buffer_add_output_glyphs_be16 (context->buffer, i,
-					 1, (const uint16_t *) &ligGlyph,
-					 0,
-					 IN_LIGID (context->buffer->in_pos) && !IN_COMPONENT (context->buffer->in_pos) ?
-					 0xFFFF : context->buffer->allocate_lig_id ());
+      context->buffer->add_output_glyphs_be16 (i,
+					       1, (const uint16_t *) &ligGlyph,
+					       0,
+					       IN_LIGID (context->buffer->in_pos) && !IN_COMPONENT (context->buffer->in_pos) ?
+					       0xFFFF : context->buffer->allocate_lig_id ());
     else
     {
       unsigned int lig_id = context->buffer->allocate_lig_id ();
-      _hb_buffer_add_output_glyph (context->buffer, ligGlyph, 0xFFFF, lig_id);
+      context->buffer->add_output_glyph (ligGlyph, 0xFFFF, lig_id);
 
       /* Now we must do a second loop to copy the skipped glyphs to
 	 `out' and assign component values to it.  We start with the
@@ -420,7 +420,7 @@ struct Ligature
       for ( i = 1; i < count; i++ )
       {
 	while (_hb_ot_layout_skip_mark (context->layout->face, IN_CURINFO (), context->lookup_flag, NULL))
-	  _hb_buffer_add_output_glyph (context->buffer, IN_CURGLYPH (), i, lig_id);
+	  context->buffer->add_output_glyph (IN_CURGLYPH (), i, lig_id);
 
 	(context->buffer->in_pos)++;
       }
commit 11a81612e51c598e857507c268312206423cbfca
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 13 00:01:40 2010 -0400

    Minor

diff --git a/src/hb-unicode.c b/src/hb-unicode.c
index fce79e6..7970a79 100644
--- a/src/hb-unicode.c
+++ b/src/hb-unicode.c
@@ -291,7 +291,7 @@ const hb_direction_t horiz_dir[] =
 #undef LTR
 #undef RTL
 
-HB_INTERNAL hb_direction_t
+hb_direction_t
 _hb_script_get_horizontal_direction (hb_script_t script)
 {
   if (unlikely ((unsigned int) script >= ARRAY_LENGTH (horiz_dir)))
commit 3f93518a634cb1852bf050877db23b9b9203ad03
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed May 12 23:48:40 2010 -0400

    Improve check for internal symbols

diff --git a/src/check-internal-symbols.sh b/src/check-internal-symbols.sh
index 7558518..124a7b0 100755
--- a/src/check-internal-symbols.sh
+++ b/src/check-internal-symbols.sh
@@ -17,7 +17,7 @@ stat=0
 so=.libs/libharfbuzz.so
 if test -f "$so"; then
 	echo "Checking that we are exposing internal symbols"
-	if nm $so | grep ' T _hb'; then
+	if nm $so | grep ' T ' | grep -v ' T _fini\>\| T _init\>\| T hb_'; then
 		echo "Ouch, internal symbols exposed"
 		stat=1
 	fi
commit 357d0f29c431b842179ee4b56c21bcc402178ce7
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed May 12 23:46:16 2010 -0400

    Make HB_PRIVATE more useful
    
    So we can apply it to class methods also.  Not sure if that works!

diff --git a/src/hb-blob-private.h b/src/hb-blob-private.h
index 26cad0a..c91af65 100644
--- a/src/hb-blob-private.h
+++ b/src/hb-blob-private.h
@@ -50,7 +50,7 @@ struct _hb_blob_t {
   void *user_data;
 };
 
-HB_INTERNAL hb_blob_t _hb_blob_nil;
+extern HB_INTERNAL hb_blob_t _hb_blob_nil;
 
 HB_END_DECLS
 
diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index ec07931..0d82850 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -50,8 +50,8 @@ struct _hb_font_funcs_t {
   hb_font_get_kerning_func_t		get_kerning;
 };
 
-HB_INTERNAL hb_font_funcs_t
-_hb_font_funcs_nil;
+extern HB_INTERNAL hb_font_funcs_t _hb_font_funcs_nil;
+
 
 /*
  * hb_face_t
diff --git a/src/hb-private.h b/src/hb-private.h
index 03c53fb..6108d40 100644
--- a/src/hb-private.h
+++ b/src/hb-private.h
@@ -108,7 +108,7 @@
 #endif
 
 #ifndef HB_INTERNAL
-# define HB_INTERNAL extern __attribute__((__visibility__("hidden")))
+# define HB_INTERNAL __attribute__((__visibility__("hidden")))
 #endif
 
 
diff --git a/src/hb-unicode-private.h b/src/hb-unicode-private.h
index ba530d2..01272da 100644
--- a/src/hb-unicode-private.h
+++ b/src/hb-unicode-private.h
@@ -49,8 +49,7 @@ struct _hb_unicode_funcs_t {
   hb_unicode_get_eastasian_width_func_t		get_eastasian_width;
 };
 
-HB_INTERNAL hb_unicode_funcs_t
-_hb_unicode_funcs_nil;
+extern HB_INTERNAL hb_unicode_funcs_t _hb_unicode_funcs_nil;
 
 
 HB_INTERNAL hb_direction_t
commit 1d5e78013696b10751d8a35027619e81978e1312
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed May 12 23:43:00 2010 -0400

    Add a few other buffer methods

diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index b5e4550..73bae80 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -94,10 +94,6 @@ _hb_buffer_add_output_glyph (hb_buffer_t *buffer,
 HB_INTERNAL void
 _hb_buffer_next_glyph (hb_buffer_t *buffer);
 
-HB_INTERNAL void
-_hb_buffer_replace_glyph (hb_buffer_t *buffer,
-			  hb_codepoint_t glyph_index);
-
 
 
 struct _hb_buffer_t {
@@ -132,6 +128,13 @@ struct _hb_buffer_t {
   /* Methods */
   inline unsigned int allocate_lig_id (void) { return max_lig_id++; }
   inline void swap (void) { _hb_buffer_swap (this); }
+  inline void clear_output (void) { _hb_buffer_clear_output (this); }
+  inline void next_glyph (void) { _hb_buffer_next_glyph (this); }
+  inline void add_output_glyph (hb_codepoint_t glyph_index,
+				unsigned short component = 0xFFFF,
+				unsigned short ligID = 0xFFFF)
+  { _hb_buffer_add_output_glyph (this, glyph_index, component, ligID); }
+  inline void replace_glyph (hb_codepoint_t glyph_index) { add_output_glyph (glyph_index); }
 };
 
 
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index de7a2eb..bad5dcd 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -443,13 +443,6 @@ _hb_buffer_next_glyph (hb_buffer_t *buffer)
   buffer->in_pos++;
 }
 
-void
-_hb_buffer_replace_glyph (hb_buffer_t *buffer,
-			  hb_codepoint_t glyph_index)
-{
-  _hb_buffer_add_output_glyph (buffer, glyph_index, 0xFFFF, 0xFFFF);
-}
-
 
 unsigned int
 hb_buffer_get_length (hb_buffer_t *buffer)
diff --git a/src/hb-ot-layout-gsub-private.hh b/src/hb-ot-layout-gsub-private.hh
index 0101c4f..9a4b2e8 100644
--- a/src/hb-ot-layout-gsub-private.hh
+++ b/src/hb-ot-layout-gsub-private.hh
@@ -49,7 +49,7 @@ struct SingleSubstFormat1
       return false;
 
     glyph_id += deltaGlyphID;
-    _hb_buffer_replace_glyph (context->buffer, glyph_id);
+    context->buffer->replace_glyph (glyph_id);
 
     /* We inherit the old glyph class to the substituted glyph */
     if (_hb_ot_layout_has_new_glyph_classes (context->layout->face))
@@ -93,7 +93,7 @@ struct SingleSubstFormat2
       return false;
 
     glyph_id = substitute[index];
-    _hb_buffer_replace_glyph (context->buffer, glyph_id);
+    context->buffer->replace_glyph (glyph_id);
 
     /* We inherit the old glyph class to the substituted glyph */
     if (_hb_ot_layout_has_new_glyph_classes (context->layout->face))
@@ -302,7 +302,7 @@ struct AlternateSubstFormat1
 
     glyph_id = alt_set[alt_index];
 
-    _hb_buffer_replace_glyph (context->buffer, glyph_id);
+    context->buffer->replace_glyph (glyph_id);
 
     /* We inherit the old glyph class to the substituted glyph */
     if (_hb_ot_layout_has_new_glyph_classes (context->layout->face))
@@ -832,7 +832,7 @@ struct SubstLookup : Lookup
     if (likely (!is_reverse ()))
     {
 	/* in/out forward substitution */
-	_hb_buffer_clear_output (buffer);
+	buffer->clear_output ();
 	buffer->in_pos = 0;
 	while (buffer->in_pos < buffer->in_length)
 	{
@@ -840,7 +840,7 @@ struct SubstLookup : Lookup
 	      apply_once (layout, buffer, NO_CONTEXT, MAX_NESTING_LEVEL))
 	    ret = true;
 	  else
-	    _hb_buffer_next_glyph (buffer);
+	    buffer->next_glyph ();
 
 	}
 	if (ret)
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index 066abbd..cefde13 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -208,7 +208,7 @@ static inline bool apply_lookup (hb_apply_context_t *context,
       if (unlikely (context->buffer->in_pos == end))
 	return true;
       /* No lookup applied for this index */
-      _hb_buffer_next_glyph (context->buffer);
+      context->buffer->next_glyph ();
     }
 
     if (lookupCount && i == lookupRecord->sequenceIndex)
@@ -232,7 +232,7 @@ static inline bool apply_lookup (hb_apply_context_t *context,
     {
     not_applied:
       /* No lookup applied for this index */
-      _hb_buffer_next_glyph (context->buffer);
+      context->buffer->next_glyph ();
       i++;
     }
   }
commit d0316a81f59a4e814b0af78797d915d7ce04d119
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed May 12 23:34:52 2010 -0400

    Add buffer->swap()

diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index c8859c8..b5e4550 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -62,37 +62,6 @@ ASSERT_STATIC (sizeof (hb_glyph_position_t) == sizeof (hb_internal_glyph_positio
 ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t));
 
 
-struct _hb_buffer_t {
-  hb_reference_count_t ref_count;
-
-  /* Information about how the text in the buffer should be treated */
-  hb_unicode_funcs_t *unicode;
-  hb_direction_t      direction;
-  hb_script_t         script;
-  hb_language_t       language;
-
-  /* Buffer contents */
-
-  unsigned int allocated;
-
-  hb_bool_t    have_output; /* whether we have an output buffer going on */
-  hb_bool_t    have_positions; /* whether we have positions */
-  unsigned int in_length;
-  unsigned int out_length;
-  unsigned int in_pos;
-  unsigned int out_pos; /* out_length and out_pos are actually always the same */
-
-  hb_internal_glyph_info_t     *in_string;
-  hb_internal_glyph_info_t     *out_string;
-  hb_internal_glyph_position_t *positions;
-
-  /* Other stuff */
-
-  unsigned int         max_lig_id;
-
-  inline unsigned int allocate_lig_id (void) { return max_lig_id++; }
-};
-
 
 HB_INTERNAL void
 _hb_buffer_swap (hb_buffer_t *buffer);
@@ -130,6 +99,43 @@ _hb_buffer_replace_glyph (hb_buffer_t *buffer,
 			  hb_codepoint_t glyph_index);
 
 
+
+struct _hb_buffer_t {
+  hb_reference_count_t ref_count;
+
+  /* Information about how the text in the buffer should be treated */
+  hb_unicode_funcs_t *unicode;
+  hb_direction_t      direction;
+  hb_script_t         script;
+  hb_language_t       language;
+
+  /* Buffer contents */
+
+  unsigned int allocated;
+
+  hb_bool_t    have_output; /* whether we have an output buffer going on */
+  hb_bool_t    have_positions; /* whether we have positions */
+  unsigned int in_length;
+  unsigned int out_length;
+  unsigned int in_pos;
+  unsigned int out_pos; /* out_length and out_pos are actually always the same */
+
+  hb_internal_glyph_info_t     *in_string;
+  hb_internal_glyph_info_t     *out_string;
+  hb_internal_glyph_position_t *positions;
+
+  /* Other stuff */
+
+  unsigned int         max_lig_id;
+
+
+  /* Methods */
+  inline unsigned int allocate_lig_id (void) { return max_lig_id++; }
+  inline void swap (void) { _hb_buffer_swap (this); }
+};
+
+
+
 #ifndef BUFFER
 #define BUFFER buffer
 #endif
diff --git a/src/hb-ot-layout-gsub-private.hh b/src/hb-ot-layout-gsub-private.hh
index 38364a5..0101c4f 100644
--- a/src/hb-ot-layout-gsub-private.hh
+++ b/src/hb-ot-layout-gsub-private.hh
@@ -844,7 +844,7 @@ struct SubstLookup : Lookup
 
 	}
 	if (ret)
-	  _hb_buffer_swap (buffer);
+	  buffer->swap ();
     }
     else
     {
commit 3b649a38b5772dd7aba7f07ff7698a7f427f421f
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed May 12 23:28:38 2010 -0400

    Add check for internal symbols

diff --git a/src/Makefile.am b/src/Makefile.am
index 9c534a6..f52ea49 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -99,7 +99,8 @@ main_SOURCES = main.cc
 main_CPPFLAGS = $(HBCFLAGS)
 main_LDADD = libharfbuzz.la $(HBLIBS)
 
-TESTS =
+TESTS = \
+	check-internal-symbols.sh
 
 if HAVE_ICU
 else
diff --git a/src/check-internal-symbols.sh b/src/check-internal-symbols.sh
new file mode 100755
index 0000000..7558518
--- /dev/null
+++ b/src/check-internal-symbols.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+LC_ALL=C
+export LC_ALL
+
+if which nm 2>/dev/null >/dev/null; then
+	:
+else
+	echo "check-internal-symbols.sh: 'nm' not found; skipping test"
+	exit 0
+fi
+
+test -z "$srcdir" && srcdir=.
+test -z "$MAKE" && MAKE=make
+stat=0
+
+so=.libs/libharfbuzz.so
+if test -f "$so"; then
+	echo "Checking that we are exposing internal symbols"
+	if nm $so | grep ' T _hb'; then
+		echo "Ouch, internal symbols exposed"
+		stat=1
+	fi
+else
+	echo "check-internal-symbols.sh: libharfbuzz.so not found; skipping test"
+fi
+
+exit $stat
commit eee8598d75d3af692d9ececf7e8ac458e892ba9e
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed May 12 23:22:55 2010 -0400

    Hide internal symbols

diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index e18222b..e25f7ac 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -80,10 +80,10 @@ struct _hb_ot_layout_context_t
 };
 
 
-void
+HB_INTERNAL void
 _hb_ot_layout_init (hb_face_t *face);
 
-void
+HB_INTERNAL void
 _hb_ot_layout_fini (hb_face_t *face);
 
 
diff --git a/src/hb-private.h b/src/hb-private.h
index 7e292dc..03c53fb 100644
--- a/src/hb-private.h
+++ b/src/hb-private.h
@@ -66,10 +66,6 @@
 #undef MAX
 #define MAX(a,b) ((a) > (b) ? (a) : (b))
 
-#ifndef HB_INTERNAL
-# define HB_INTERNAL extern
-#endif
-
 #undef  ARRAY_LENGTH
 #define ARRAY_LENGTH(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
 
@@ -111,6 +107,10 @@
 #define HB_UNUSED
 #endif
 
+#ifndef HB_INTERNAL
+# define HB_INTERNAL extern __attribute__((__visibility__("hidden")))
+#endif
+
 
 #if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
 #define snprintf _snprintf
commit 8951fc2c82f2db4865da6d9e303fce419b6363bb
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed May 12 23:13:39 2010 -0400

    Add buffer->allocate_lig_id()

diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index 1a3ac70..c8859c8 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -89,6 +89,8 @@ struct _hb_buffer_t {
   /* Other stuff */
 
   unsigned int         max_lig_id;
+
+  inline unsigned int allocate_lig_id (void) { return max_lig_id++; }
 };
 
 
@@ -127,9 +129,6 @@ HB_INTERNAL void
 _hb_buffer_replace_glyph (hb_buffer_t *buffer,
 			  hb_codepoint_t glyph_index);
 
-HB_INTERNAL unsigned short
-_hb_buffer_allocate_lig_id (hb_buffer_t *buffer);
-
 
 #ifndef BUFFER
 #define BUFFER buffer
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 9588d5e..de7a2eb 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -450,12 +450,6 @@ _hb_buffer_replace_glyph (hb_buffer_t *buffer,
   _hb_buffer_add_output_glyph (buffer, glyph_index, 0xFFFF, 0xFFFF);
 }
 
-unsigned short
-_hb_buffer_allocate_lig_id (hb_buffer_t *buffer)
-{
-  return ++buffer->max_lig_id;
-}
-
 
 unsigned int
 hb_buffer_get_length (hb_buffer_t *buffer)
diff --git a/src/hb-ot-layout-gsub-private.hh b/src/hb-ot-layout-gsub-private.hh
index 849a20c..38364a5 100644
--- a/src/hb-ot-layout-gsub-private.hh
+++ b/src/hb-ot-layout-gsub-private.hh
@@ -404,10 +404,10 @@ struct Ligature
 					 1, (const uint16_t *) &ligGlyph,
 					 0,
 					 IN_LIGID (context->buffer->in_pos) && !IN_COMPONENT (context->buffer->in_pos) ?
-					 0xFFFF : _hb_buffer_allocate_lig_id (context->buffer));
+					 0xFFFF : context->buffer->allocate_lig_id ());
     else
     {
-      unsigned int lig_id = _hb_buffer_allocate_lig_id (context->buffer);
+      unsigned int lig_id = context->buffer->allocate_lig_id ();
       _hb_buffer_add_output_glyph (context->buffer, ligGlyph, 0xFFFF, lig_id);
 
       /* Now we must do a second loop to copy the skipped glyphs to
commit 1ce4dc95dbb28842085342aea4f9d12cbe9671a9
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed May 12 18:29:25 2010 -0400

    Use bit tricks for HB_DIRECTION_IS_*
    
    We already depend on the exact values of the direction enum
    in HB_DIRECTION_REVERSE(), so we may as well use that.

diff --git a/src/hb-common.h b/src/hb-common.h
index cc673ad..f64d6cc 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -79,10 +79,10 @@ typedef enum _hb_direction_t {
   HB_DIRECTION_BTT
 } hb_direction_t;
 
-#define HB_DIRECTION_IS_HORIZONTAL(dir)	((dir) == HB_DIRECTION_LTR || (dir) == HB_DIRECTION_RTL)
-#define HB_DIRECTION_IS_VERTICAL(dir)	((dir) == HB_DIRECTION_TTB || (dir) == HB_DIRECTION_BTT)
-#define HB_DIRECTION_IS_FORWARD(dir)	((dir) == HB_DIRECTION_LTR || (dir) == HB_DIRECTION_TTB)
-#define HB_DIRECTION_IS_BACKWARD(dir)	((dir) == HB_DIRECTION_RTL || (dir) == HB_DIRECTION_BTT)
+#define HB_DIRECTION_IS_HORIZONTAL(dir)	((((unsigned int) (dir)) & ~1U) == 0)
+#define HB_DIRECTION_IS_VERTICAL(dir)	((((unsigned int) (dir)) & ~1U) == 2)
+#define HB_DIRECTION_IS_FORWARD(dir)	((((unsigned int) (dir)) & ~2U) == 0)
+#define HB_DIRECTION_IS_BACKWARD(dir)	((((unsigned int) (dir)) & ~2U) == 1)
 #define HB_DIRECTION_REVERSE(dir)	((hb_direction_t) (((unsigned int) (dir)) ^ 1))
 
 
commit 22da7fd94d6318c52df69d70470a85464ffc533d
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed May 12 18:23:21 2010 -0400

    Rename a few files to be C++ sources
    
    In anticipation for buffer revamp coming.

diff --git a/src/Makefile.am b/src/Makefile.am
index 7b10fe2..9c534a6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,16 +12,16 @@ HBLIBS =
 HBSOURCES =  \
 	hb-blob.c \
 	hb-blob-private.h \
-	hb-buffer.c \
-	hb-buffer-private.h \
+	hb-buffer.cc \
+	hb-buffer-private.hh \
 	hb-font.cc \
-	hb-font-private.h \
+	hb-font-private.hh \
 	hb-object-private.h \
 	hb-open-file-private.hh \
 	hb-open-type-private.hh \
 	hb-language.c \
 	hb-private.h \
-	hb-shape.c \
+	hb-shape.cc \
 	hb-unicode.c \
 	hb-unicode-private.h \
 	$(NULL)
@@ -43,9 +43,9 @@ HBSOURCES += \
 	hb-ot-layout-gpos-private.hh \
 	hb-ot-layout-gsubgpos-private.hh \
 	hb-ot-layout-gsub-private.hh \
-	hb-ot-layout-private.h \
-	hb-ot-shape.c \
-	hb-ot-shape-private.h \
+	hb-ot-layout-private.hh \
+	hb-ot-shape.cc \
+	hb-ot-shape-private.hh \
 	hb-ot-tag.c \
 	$(NULL)
 HBHEADERS += \
@@ -80,7 +80,7 @@ if HAVE_FREETYPE
 HBCFLAGS += $(FREETYPE_CFLAGS)
 HBLIBS   += $(FREETYPE_LIBS)
 HBSOURCES += \
-	hb-ft.c \
+	hb-ft.cc \
 	$(NULL)
 HBHEADERS += \
 	hb-ft.h \
diff --git a/src/hb-buffer-private.h b/src/hb-buffer-private.h
deleted file mode 100644
index bc562ba..0000000
--- a/src/hb-buffer-private.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 1998-2004  David Turner and Werner Lemberg
- * Copyright (C) 2004,2007,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): Owen Taylor, Behdad Esfahbod
- */
-
-#ifndef HB_BUFFER_PRIVATE_H
-#define HB_BUFFER_PRIVATE_H
-
-#include "hb-private.h"
-#include "hb-buffer.h"
-#include "hb-unicode-private.h"
-
-HB_BEGIN_DECLS
-
-#define HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN 0xFFFF
-
-
-typedef struct _hb_internal_glyph_info_t {
-  hb_codepoint_t codepoint;
-  hb_mask_t      mask;
-  uint32_t       cluster;
-  uint16_t       component;
-  uint16_t       lig_id;
-  uint32_t       gproperty;
-} hb_internal_glyph_info_t;
-
-typedef struct _hb_internal_glyph_position_t {
-  hb_position_t  x_advance;
-  hb_position_t  y_advance;
-  hb_position_t  x_offset;
-  hb_position_t  y_offset;
-  uint32_t       back : 16;		/* number of glyphs to go back
-					   for drawing current glyph */
-  int32_t        cursive_chain : 16;	/* character to which this connects,
-					   may be positive or negative */
-} hb_internal_glyph_position_t;
-
-ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_internal_glyph_info_t));
-ASSERT_STATIC (sizeof (hb_glyph_position_t) == sizeof (hb_internal_glyph_position_t));
-ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t));
-
-
-struct _hb_buffer_t {
-  hb_reference_count_t ref_count;
-
-  /* Information about how the text in the buffer should be treated */
-  hb_unicode_funcs_t *unicode;
-  hb_direction_t      direction;
-  hb_script_t         script;
-  hb_language_t       language;
-
-  /* Buffer contents */
-
-  unsigned int allocated;
-
-  hb_bool_t    have_output; /* whether we have an output buffer going on */
-  hb_bool_t    have_positions; /* whether we have positions */
-  unsigned int in_length;
-  unsigned int out_length;
-  unsigned int in_pos;
-  unsigned int out_pos; /* out_length and out_pos are actually always the same */
-
-  hb_internal_glyph_info_t     *in_string;
-  hb_internal_glyph_info_t     *out_string;
-  hb_internal_glyph_position_t *positions;
-
-  /* Other stuff */
-
-  unsigned int         max_lig_id;
-};
-
-
-HB_INTERNAL void
-_hb_buffer_swap (hb_buffer_t *buffer);
-
-HB_INTERNAL void
-_hb_buffer_clear_output (hb_buffer_t *buffer);
-
-HB_INTERNAL void
-_hb_buffer_add_output_glyphs (hb_buffer_t *buffer,
-			      unsigned int num_in,
-			      unsigned int num_out,
-			      const hb_codepoint_t *glyph_data,
-			      unsigned short component,
-			      unsigned short ligID);
-
-HB_INTERNAL void
-_hb_buffer_add_output_glyphs_be16 (hb_buffer_t *buffer,
-				   unsigned int num_in,
-				   unsigned int num_out,
-				   const uint16_t *glyph_data_be,
-				   unsigned short component,
-				   unsigned short ligID);
-
-HB_INTERNAL void
-_hb_buffer_add_output_glyph (hb_buffer_t *buffer,
-			     hb_codepoint_t glyph_index,
-			     unsigned short component,
-			     unsigned short ligID);
-
-HB_INTERNAL void
-_hb_buffer_next_glyph (hb_buffer_t *buffer);
-
-HB_INTERNAL void
-_hb_buffer_replace_glyph (hb_buffer_t *buffer,
-			  hb_codepoint_t glyph_index);
-
-HB_INTERNAL unsigned short
-_hb_buffer_allocate_lig_id (hb_buffer_t *buffer);
-
-
-#ifndef BUFFER
-#define BUFFER buffer
-#endif
-
-/* convenience macros */
-#define IN_GLYPH(pos)		(BUFFER->in_string[(pos)].codepoint)
-#define IN_INFO(pos)		(&BUFFER->in_string[(pos)])
-#define IN_CURGLYPH()		(BUFFER->in_string[BUFFER->in_pos].codepoint)
-#define IN_NEXTGLYPH()		(BUFFER->in_string[BUFFER->in_pos + 1].codepoint)
-#define IN_CURINFO()		(&BUFFER->in_string[BUFFER->in_pos])
-#define IN_MASK(pos)		(BUFFER->in_string[(pos)].mask)
-#define IN_CLUSTER(pos)		(BUFFER->in_string[(pos)].cluster)
-#define IN_LIGID(pos)		(BUFFER->in_string[(pos)].lig_id)
-#define IN_COMPONENT(pos)	(BUFFER->in_string[(pos)].component)
-#define POSITION(pos)		(&BUFFER->positions[(pos)])
-#define CURPOSITION()		(&BUFFER->positions[BUFFER->in_pos])
-#define OUT_GLYPH(pos)		(BUFFER->out_string[(pos)].codepoint)
-#define OUT_INFO(pos)		(&BUFFER->out_string[(pos)])
-
-HB_END_DECLS
-
-#endif /* HB_BUFFER_PRIVATE_H */
diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
new file mode 100644
index 0000000..1a3ac70
--- /dev/null
+++ b/src/hb-buffer-private.hh
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 1998-2004  David Turner and Werner Lemberg
+ * Copyright (C) 2004,2007,2009,2010  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): Owen Taylor, Behdad Esfahbod
+ */
+
+#ifndef HB_BUFFER_PRIVATE_H
+#define HB_BUFFER_PRIVATE_H
+
+#include "hb-private.h"
+#include "hb-buffer.h"
+#include "hb-unicode-private.h"
+
+HB_BEGIN_DECLS
+
+#define HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN 0xFFFF
+
+
+typedef struct _hb_internal_glyph_info_t {
+  hb_codepoint_t codepoint;
+  hb_mask_t      mask;
+  uint32_t       cluster;
+  uint16_t       component;
+  uint16_t       lig_id;
+  uint32_t       gproperty;
+} hb_internal_glyph_info_t;
+
+typedef struct _hb_internal_glyph_position_t {
+  hb_position_t  x_advance;
+  hb_position_t  y_advance;
+  hb_position_t  x_offset;
+  hb_position_t  y_offset;
+  uint32_t       back : 16;		/* number of glyphs to go back
+					   for drawing current glyph */
+  int32_t        cursive_chain : 16;	/* character to which this connects,
+					   may be positive or negative */
+} hb_internal_glyph_position_t;
+
+ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_internal_glyph_info_t));
+ASSERT_STATIC (sizeof (hb_glyph_position_t) == sizeof (hb_internal_glyph_position_t));
+ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t));
+
+
+struct _hb_buffer_t {
+  hb_reference_count_t ref_count;
+
+  /* Information about how the text in the buffer should be treated */
+  hb_unicode_funcs_t *unicode;
+  hb_direction_t      direction;
+  hb_script_t         script;
+  hb_language_t       language;
+
+  /* Buffer contents */
+
+  unsigned int allocated;
+
+  hb_bool_t    have_output; /* whether we have an output buffer going on */
+  hb_bool_t    have_positions; /* whether we have positions */
+  unsigned int in_length;
+  unsigned int out_length;
+  unsigned int in_pos;
+  unsigned int out_pos; /* out_length and out_pos are actually always the same */
+
+  hb_internal_glyph_info_t     *in_string;
+  hb_internal_glyph_info_t     *out_string;
+  hb_internal_glyph_position_t *positions;
+
+  /* Other stuff */
+
+  unsigned int         max_lig_id;
+};
+
+
+HB_INTERNAL void
+_hb_buffer_swap (hb_buffer_t *buffer);
+
+HB_INTERNAL void
+_hb_buffer_clear_output (hb_buffer_t *buffer);
+
+HB_INTERNAL void
+_hb_buffer_add_output_glyphs (hb_buffer_t *buffer,
+			      unsigned int num_in,
+			      unsigned int num_out,
+			      const hb_codepoint_t *glyph_data,
+			      unsigned short component,
+			      unsigned short ligID);
+
+HB_INTERNAL void
+_hb_buffer_add_output_glyphs_be16 (hb_buffer_t *buffer,
+				   unsigned int num_in,
+				   unsigned int num_out,
+				   const uint16_t *glyph_data_be,
+				   unsigned short component,
+				   unsigned short ligID);
+
+HB_INTERNAL void
+_hb_buffer_add_output_glyph (hb_buffer_t *buffer,
+			     hb_codepoint_t glyph_index,
+			     unsigned short component,
+			     unsigned short ligID);
+
+HB_INTERNAL void
+_hb_buffer_next_glyph (hb_buffer_t *buffer);
+
+HB_INTERNAL void
+_hb_buffer_replace_glyph (hb_buffer_t *buffer,
+			  hb_codepoint_t glyph_index);
+
+HB_INTERNAL unsigned short
+_hb_buffer_allocate_lig_id (hb_buffer_t *buffer);
+
+
+#ifndef BUFFER
+#define BUFFER buffer
+#endif
+
+/* convenience macros */
+#define IN_GLYPH(pos)		(BUFFER->in_string[(pos)].codepoint)
+#define IN_INFO(pos)		(&BUFFER->in_string[(pos)])
+#define IN_CURGLYPH()		(BUFFER->in_string[BUFFER->in_pos].codepoint)
+#define IN_NEXTGLYPH()		(BUFFER->in_string[BUFFER->in_pos + 1].codepoint)
+#define IN_CURINFO()		(&BUFFER->in_string[BUFFER->in_pos])
+#define IN_MASK(pos)		(BUFFER->in_string[(pos)].mask)
+#define IN_CLUSTER(pos)		(BUFFER->in_string[(pos)].cluster)
+#define IN_LIGID(pos)		(BUFFER->in_string[(pos)].lig_id)
+#define IN_COMPONENT(pos)	(BUFFER->in_string[(pos)].component)
+#define POSITION(pos)		(&BUFFER->positions[(pos)])
+#define CURPOSITION()		(&BUFFER->positions[BUFFER->in_pos])
+#define OUT_GLYPH(pos)		(BUFFER->out_string[(pos)].codepoint)
+#define OUT_INFO(pos)		(&BUFFER->out_string[(pos)])
+
+HB_END_DECLS
+
+#endif /* HB_BUFFER_PRIVATE_H */
diff --git a/src/hb-buffer.c b/src/hb-buffer.c
deleted file mode 100644
index adec7c1..0000000
--- a/src/hb-buffer.c
+++ /dev/null
@@ -1,650 +0,0 @@
-/*
- * Copyright (C) 1998-2004  David Turner and Werner Lemberg
- * Copyright (C) 2004,2007  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): Owen Taylor, Behdad Esfahbod
- */
-
-#include "hb-buffer-private.h"
-
-#include <string.h>
-
-
-static hb_buffer_t _hb_buffer_nil = {
-  HB_REFERENCE_COUNT_INVALID, /* ref_count */
-
-  &_hb_unicode_funcs_nil  /* unicode */
-};
-
-/* Here is how the buffer works internally:
- *
- * There are two string pointers: in_string and out_string.  They
- * always have same allocated size, but different length and positions.
- *
- * As an optimization, both in_string and out_string may point to the
- * same piece of memory, which is owned by in_string.  This remains the
- * case as long as out_length doesn't exceed in_length at any time.
- * In that case, swap() is no-op and the glyph operations operate mostly
- * in-place.
- *
- * As soon as out_string gets longer than in_string, out_string is moved over
- * to an alternate buffer (which we reuse the positions buffer for!), and its
- * current contents (out_length entries) are copied to the alt buffer.
- * This should all remain transparent to the user.  swap() then switches
- * in_string and out_string.
- */
-
-/* XXX err handling */
-
-/* Internal API */
-
-static void
-hb_buffer_ensure_separate (hb_buffer_t *buffer, unsigned int size)
-{
-  hb_buffer_ensure (buffer, size);
-  if (buffer->out_string == buffer->in_string)
-  {
-    assert (buffer->have_output);
-    if (!buffer->positions)
-      buffer->positions = calloc (buffer->allocated, sizeof (buffer->positions[0]));
-
-    buffer->out_string = (hb_internal_glyph_info_t *) buffer->positions;
-    memcpy (buffer->out_string, buffer->in_string, buffer->out_length * sizeof (buffer->out_string[0]));
-  }
-}
-
-/* Public API */
-
-hb_buffer_t *
-hb_buffer_create (unsigned int pre_alloc_size)
-{
-  hb_buffer_t *buffer;
-
-  if (!HB_OBJECT_DO_CREATE (hb_buffer_t, buffer))
-    return &_hb_buffer_nil;
-
-  if (pre_alloc_size)
-    hb_buffer_ensure(buffer, pre_alloc_size);
-
-  buffer->unicode = &_hb_unicode_funcs_nil;
-
-  return buffer;
-}
-
-hb_buffer_t *
-hb_buffer_reference (hb_buffer_t *buffer)
-{
-  HB_OBJECT_DO_REFERENCE (buffer);
-}
-
-unsigned int
-hb_buffer_get_reference_count (hb_buffer_t *buffer)
-{
-  HB_OBJECT_DO_GET_REFERENCE_COUNT (buffer);
-}
-
-void
-hb_buffer_destroy (hb_buffer_t *buffer)
-{
-  HB_OBJECT_DO_DESTROY (buffer);
-
-  hb_unicode_funcs_destroy (buffer->unicode);
-
-  free (buffer->in_string);
-  free (buffer->positions);
-
-  free (buffer);
-}
-
-
-void
-hb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
-			     hb_unicode_funcs_t *unicode)
-{
-  if (!unicode)
-    unicode = &_hb_unicode_funcs_nil;
-
-  hb_unicode_funcs_reference (unicode);
-  hb_unicode_funcs_destroy (buffer->unicode);
-  buffer->unicode = unicode;
-}
-
-hb_unicode_funcs_t *
-hb_buffer_get_unicode_funcs (hb_buffer_t        *buffer)
-{
-  return buffer->unicode;
-}
-
-void
-hb_buffer_set_direction (hb_buffer_t    *buffer,
-			 hb_direction_t  direction)
-
-{
-  buffer->direction = direction;
-}
-
-hb_direction_t
-hb_buffer_get_direction (hb_buffer_t    *buffer)
-{
-  return buffer->direction;
-}
-
-void
-hb_buffer_set_script (hb_buffer_t *buffer,
-		      hb_script_t  script)
-{
-  buffer->script = script;
-}
-
-hb_script_t
-hb_buffer_get_script (hb_buffer_t *buffer)
-{
-  return buffer->script;
-}
-
-void
-hb_buffer_set_language (hb_buffer_t   *buffer,
-			hb_language_t  language)
-{
-  buffer->language = language;
-}
-
-hb_language_t
-hb_buffer_get_language (hb_buffer_t *buffer)
-{
-  return buffer->language;
-}
-
-
-void
-hb_buffer_clear (hb_buffer_t *buffer)
-{
-  buffer->have_output = FALSE;
-  buffer->have_positions = FALSE;
-  buffer->in_length = 0;
-  buffer->out_length = 0;
-  buffer->in_pos = 0;
-  buffer->out_pos = 0;
-  buffer->out_string = buffer->in_string;
-  buffer->max_lig_id = 0;
-}
-
-void
-hb_buffer_ensure (hb_buffer_t *buffer, unsigned int size)
-{
-  unsigned int new_allocated = buffer->allocated;
-
-  if (size > new_allocated)
-  {
-    while (size > new_allocated)
-      new_allocated += (new_allocated >> 1) + 8;
-
-    if (buffer->positions)
-      buffer->positions = realloc (buffer->positions, new_allocated * sizeof (buffer->positions[0]));
-
-    if (buffer->out_string != buffer->in_string)
-    {
-      buffer->in_string = realloc (buffer->in_string, new_allocated * sizeof (buffer->in_string[0]));
-      buffer->out_string = (hb_internal_glyph_info_t *) buffer->positions;
-    }
-    else
-    {
-      buffer->in_string = realloc (buffer->in_string, new_allocated * sizeof (buffer->in_string[0]));
-      buffer->out_string = buffer->in_string;
-    }
-
-    buffer->allocated = new_allocated;
-  }
-}
-
-void
-hb_buffer_add_glyph (hb_buffer_t    *buffer,
-		     hb_codepoint_t  codepoint,
-		     hb_mask_t       mask,
-		     unsigned int    cluster)
-{
-  hb_internal_glyph_info_t *glyph;
-
-  hb_buffer_ensure (buffer, buffer->in_length + 1);
-
-  glyph = &buffer->in_string[buffer->in_length];
-  glyph->codepoint = codepoint;
-  glyph->mask = mask;
-  glyph->cluster = cluster;
-  glyph->component = 0;
-  glyph->lig_id = 0;
-  glyph->gproperty = HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN;
-
-  buffer->in_length++;
-}
-
-
-/* HarfBuzz-Internal API */
-
-void
-_hb_buffer_clear_output (hb_buffer_t *buffer)
-{
-  buffer->have_output = TRUE;
-  buffer->have_positions = FALSE;
-  buffer->out_length = 0;
-  buffer->out_pos = 0;
-  buffer->out_string = buffer->in_string;
-}
-
-void
-hb_buffer_clear_positions (hb_buffer_t *buffer)
-{
-  _hb_buffer_clear_output (buffer);
-  buffer->have_output = FALSE;
-  buffer->have_positions = TRUE;
-
-  if (unlikely (!buffer->positions))
-  {
-    buffer->positions = calloc (buffer->allocated, sizeof (buffer->positions[0]));
-    return;
-  }
-
-  memset (buffer->positions, 0, sizeof (buffer->positions[0]) * buffer->in_length);
-}
-
-void
-_hb_buffer_swap (hb_buffer_t *buffer)
-{
-  unsigned int tmp;
-
-  assert (buffer->have_output);
-
-  if (buffer->out_string != buffer->in_string)
-  {
-    hb_internal_glyph_info_t *tmp_string;
-    tmp_string = buffer->in_string;
-    buffer->in_string = buffer->out_string;
-    buffer->out_string = tmp_string;
-    buffer->positions = (hb_internal_glyph_position_t *) buffer->out_string;
-  }
-
-  tmp = buffer->in_length;
-  buffer->in_length = buffer->out_length;
-  buffer->out_length = tmp;
-
-  tmp = buffer->in_pos;
-  buffer->in_pos = buffer->out_pos;
-  buffer->out_pos = tmp;
-}
-
-/* The following function copies `num_out' elements from `glyph_data'
-   to `buffer->out_string', advancing the in array pointer in the structure
-   by `num_in' elements, and the out array pointer by `num_out' elements.
-   Finally, it sets the `length' field of `out' equal to
-   `pos' of the `out' structure.
-
-   If `component' is 0xFFFF, the component value from buffer->in_pos
-   will copied `num_out' times, otherwise `component' itself will
-   be used to fill the `component' fields.
-
-   If `lig_id' is 0xFFFF, the lig_id value from buffer->in_pos
-   will copied `num_out' times, otherwise `lig_id' itself will
-   be used to fill the `lig_id' fields.
-
-   The mask for all replacement glyphs are taken
-   from the glyph at position `buffer->in_pos'.
-
-   The cluster value for the glyph at position buffer->in_pos is used
-   for all replacement glyphs */
-
-void
-_hb_buffer_add_output_glyphs (hb_buffer_t *buffer,
-			      unsigned int num_in,
-			      unsigned int num_out,
-			      const hb_codepoint_t *glyph_data,
-			      unsigned short component,
-			      unsigned short lig_id)
-{
-  unsigned int i;
-  unsigned int mask;
-  unsigned int cluster;
-
-  if (buffer->out_string != buffer->in_string ||
-      buffer->out_pos + num_out > buffer->in_pos + num_in)
-  {
-    hb_buffer_ensure_separate (buffer, buffer->out_pos + num_out);
-  }
-
-  mask = buffer->in_string[buffer->in_pos].mask;
-  cluster = buffer->in_string[buffer->in_pos].cluster;
-  if (component == 0xFFFF)
-    component = buffer->in_string[buffer->in_pos].component;
-  if (lig_id == 0xFFFF)
-    lig_id = buffer->in_string[buffer->in_pos].lig_id;
-
-  for (i = 0; i < num_out; i++)
-  {
-    hb_internal_glyph_info_t *info = &buffer->out_string[buffer->out_pos + i];
-    info->codepoint = glyph_data[i];
-    info->mask = mask;
-    info->cluster = cluster;
-    info->component = component;
-    info->lig_id = lig_id;
-    info->gproperty = HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN;
-  }
-
-  buffer->in_pos  += num_in;
-  buffer->out_pos += num_out;
-  buffer->out_length = buffer->out_pos;
-}
-
-void
-_hb_buffer_add_output_glyphs_be16 (hb_buffer_t *buffer,
-				   unsigned int num_in,
-				   unsigned int num_out,
-				   const uint16_t *glyph_data_be,
-				   unsigned short component,
-				   unsigned short lig_id)
-{
-  unsigned int i;
-  unsigned int mask;
-  unsigned int cluster;
-
-  if (buffer->out_string != buffer->in_string ||
-      buffer->out_pos + num_out > buffer->in_pos + num_in)
-  {
-    hb_buffer_ensure_separate (buffer, buffer->out_pos + num_out);
-  }
-
-  mask = buffer->in_string[buffer->in_pos].mask;
-  cluster = buffer->in_string[buffer->in_pos].cluster;
-  if (component == 0xFFFF)
-    component = buffer->in_string[buffer->in_pos].component;
-  if (lig_id == 0xFFFF)
-    lig_id = buffer->in_string[buffer->in_pos].lig_id;
-
-  for (i = 0; i < num_out; i++)
-  {
-    hb_internal_glyph_info_t *info = &buffer->out_string[buffer->out_pos + i];
-    info->codepoint = hb_be_uint16 (glyph_data_be[i]);
-    info->mask = mask;
-    info->cluster = cluster;
-    info->component = component;
-    info->lig_id = lig_id;
-    info->gproperty = HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN;
-  }
-
-  buffer->in_pos  += num_in;
-  buffer->out_pos += num_out;
-  buffer->out_length = buffer->out_pos;
-}
-
-void
-_hb_buffer_add_output_glyph (hb_buffer_t *buffer,
-			     hb_codepoint_t glyph_index,
-			     unsigned short component,
-			     unsigned short lig_id)
-{
-  hb_internal_glyph_info_t *info;
-
-  if (buffer->out_string != buffer->in_string)
-  {
-    hb_buffer_ensure (buffer, buffer->out_pos + 1);
-    buffer->out_string[buffer->out_pos] = buffer->in_string[buffer->in_pos];
-  }
-  else if (buffer->out_pos != buffer->in_pos)
-    buffer->out_string[buffer->out_pos] = buffer->in_string[buffer->in_pos];
-
-  info = &buffer->out_string[buffer->out_pos];
-  info->codepoint = glyph_index;
-  if (component != 0xFFFF)
-    info->component = component;
-  if (lig_id != 0xFFFF)
-    info->lig_id = lig_id;
-  info->gproperty = HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN;
-
-  buffer->in_pos++;
-  buffer->out_pos++;
-  buffer->out_length = buffer->out_pos;
-}
-
-void
-_hb_buffer_next_glyph (hb_buffer_t *buffer)
-{
-  if (buffer->have_output)
-  {
-    if (buffer->out_string != buffer->in_string)
-    {
-      hb_buffer_ensure (buffer, buffer->out_pos + 1);
-      buffer->out_string[buffer->out_pos] = buffer->in_string[buffer->in_pos];
-    }
-    else if (buffer->out_pos != buffer->in_pos)
-      buffer->out_string[buffer->out_pos] = buffer->in_string[buffer->in_pos];
-
-    buffer->out_pos++;
-    buffer->out_length = buffer->out_pos;
-  }
-
-  buffer->in_pos++;
-}
-
-void
-_hb_buffer_replace_glyph (hb_buffer_t *buffer,
-			  hb_codepoint_t glyph_index)
-{
-  _hb_buffer_add_output_glyph (buffer, glyph_index, 0xFFFF, 0xFFFF);
-}
-
-unsigned short
-_hb_buffer_allocate_lig_id (hb_buffer_t *buffer)
-{
-  return ++buffer->max_lig_id;
-}
-
-
-unsigned int
-hb_buffer_get_length (hb_buffer_t *buffer)
-{
-  return buffer->in_length;
-}
-
-/* Return value valid as long as buffer not modified */
-hb_glyph_info_t *
-hb_buffer_get_glyph_infos (hb_buffer_t *buffer)
-{
-  return (hb_glyph_info_t *) buffer->in_string;
-}
-
-/* Return value valid as long as buffer not modified */
-hb_glyph_position_t *
-hb_buffer_get_glyph_positions (hb_buffer_t *buffer)
-{
-  if (!buffer->have_positions)
-    hb_buffer_clear_positions (buffer);
-
-  return (hb_glyph_position_t *) buffer->positions;
-}
-
-
-static void
-reverse_range (hb_buffer_t *buffer,
-	       unsigned int start,
-	       unsigned int end)
-{
-  unsigned int i, j;
-
-  for (i = start, j = end - 1; i < j; i++, j--) {
-    hb_internal_glyph_info_t t;
-
-    t = buffer->in_string[i];
-    buffer->in_string[i] = buffer->in_string[j];
-    buffer->in_string[j] = t;
-  }
-
-  if (buffer->positions) {
-    for (i = 0, j = end - 1; i < j; i++, j--) {
-      hb_internal_glyph_position_t t;
-
-      t = buffer->positions[i];
-      buffer->positions[i] = buffer->positions[j];
-      buffer->positions[j] = t;
-    }
-  }
-}
-
-void
-hb_buffer_reverse (hb_buffer_t *buffer)
-{
-  if (unlikely (!buffer->in_length))
-    return;
-
-  reverse_range (buffer, 0, buffer->in_length);
-}
-
-void
-hb_buffer_reverse_clusters (hb_buffer_t *buffer)
-{
-  unsigned int i, start, count, last_cluster;
-
-  if (unlikely (!buffer->in_length))
-    return;
-
-  hb_buffer_reverse (buffer);
-
-  count = buffer->in_length;
-  start = 0;
-  last_cluster = buffer->in_string[0].cluster;
-  for (i = 1; i < count; i++) {
-    if (last_cluster != buffer->in_string[i].cluster) {
-      reverse_range (buffer, start, i);
-      start = i;
-      last_cluster = buffer->in_string[i].cluster;
-    }
-  }
-  reverse_range (buffer, start, i);
-}
-
-
-#define ADD_UTF(T) \
-	HB_STMT_START { \
-	  const T *next = (const T *) text + item_offset; \
-	  const T *end = next + item_length; \
-	  while (next < end) { \
-	    hb_codepoint_t u; \
-	    const T *old_next = next; \
-	    next = UTF_NEXT (next, end, u); \
-	    hb_buffer_add_glyph (buffer, u, 0,  old_next - (const T *) text); \
-	  } \
-	} HB_STMT_END
-
-
-#define UTF8_COMPUTE(Char, Mask, Len) \
-  if (Char < 128) { Len = 1; Mask = 0x7f; } \
-  else if ((Char & 0xe0) == 0xc0) { Len = 2; Mask = 0x1f; } \
-  else if ((Char & 0xf0) == 0xe0) { Len = 3; Mask = 0x0f; } \
-  else if ((Char & 0xf8) == 0xf0) { Len = 4; Mask = 0x07; } \
-  else Len = 0;
-
-static inline const uint8_t *
-hb_utf8_next (const uint8_t *text,
-	      const uint8_t *end,
-	      hb_codepoint_t *unicode)
-{
-  uint8_t c = *text;
-  unsigned int mask, len;
-
-  UTF8_COMPUTE (c, mask, len);
-  if (unlikely (!len || (unsigned int) (end - text) < len)) {
-    *unicode = -1;
-    return text + 1;
-  } else {
-    hb_codepoint_t result;
-    unsigned int i;
-    result = c & mask;
-    for (i = 1; i < len; i++)
-      {
-	if (unlikely ((text[i] & 0xc0) != 0x80))
-	  {
-	    *unicode = -1;
-	    return text + 1;
-	  }
-	result <<= 6;
-	result |= (text[i] & 0x3f);
-      }
-    *unicode = result;
-    return text + len;
-  }
-}
-
-void
-hb_buffer_add_utf8 (hb_buffer_t  *buffer,
-		    const char   *text,
-		    unsigned int  text_length HB_UNUSED,
-		    unsigned int  item_offset,
-		    unsigned int  item_length)
-{
-#define UTF_NEXT(S, E, U)	hb_utf8_next (S, E, &(U))
-  ADD_UTF (uint8_t);
-#undef UTF_NEXT
-}
-
-static inline const uint16_t *
-hb_utf16_next (const uint16_t *text,
-	       const uint16_t *end,
-	       hb_codepoint_t *unicode)
-{
-  uint16_t c = *text++;
-
-  if (unlikely (c >= 0xd800 && c < 0xdc00)) {
-    /* high surrogate */
-    uint16_t l;
-    if (text < end && ((l = *text), unlikely (l >= 0xdc00 && l < 0xe000))) {
-      /* low surrogate */
-      *unicode = ((hb_codepoint_t) ((c) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x10000);
-       text++;
-    } else
-      *unicode = -1;
-  } else
-    *unicode = c;
-
-  return text;
-}
-
-void
-hb_buffer_add_utf16 (hb_buffer_t    *buffer,
-		     const uint16_t *text,
-		     unsigned int    text_length HB_UNUSED,
-		     unsigned int    item_offset,
-		     unsigned int    item_length)
-{
-#define UTF_NEXT(S, E, U)	hb_utf16_next (S, E, &(U))
-  ADD_UTF (uint16_t);
-#undef UTF_NEXT
-}
-
-void
-hb_buffer_add_utf32 (hb_buffer_t    *buffer,
-		     const uint32_t *text,
-		     unsigned int    text_length HB_UNUSED,
-		     unsigned int    item_offset,
-		     unsigned int    item_length)
-{
-#define UTF_NEXT(S, E, U)	((U) = *(S), (S)+1)
-  ADD_UTF (uint32_t);
-#undef UTF_NEXT
-}
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
new file mode 100644
index 0000000..9588d5e
--- /dev/null
+++ b/src/hb-buffer.cc
@@ -0,0 +1,650 @@
+/*
+ * Copyright (C) 1998-2004  David Turner and Werner Lemberg
+ * Copyright (C) 2004,2007,2009,2010  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): Owen Taylor, Behdad Esfahbod
+ */
+
+#include "hb-buffer-private.hh"
+
+#include <string.h>
+
+
+static hb_buffer_t _hb_buffer_nil = {
+  HB_REFERENCE_COUNT_INVALID, /* ref_count */
+
+  &_hb_unicode_funcs_nil  /* unicode */
+};
+
+/* Here is how the buffer works internally:
+ *
+ * There are two string pointers: in_string and out_string.  They
+ * always have same allocated size, but different length and positions.
+ *
+ * As an optimization, both in_string and out_string may point to the
+ * same piece of memory, which is owned by in_string.  This remains the
+ * case as long as out_length doesn't exceed in_length at any time.
+ * In that case, swap() is no-op and the glyph operations operate mostly
+ * in-place.
+ *
+ * As soon as out_string gets longer than in_string, out_string is moved over
+ * to an alternate buffer (which we reuse the positions buffer for!), and its
+ * current contents (out_length entries) are copied to the alt buffer.
+ * This should all remain transparent to the user.  swap() then switches
+ * in_string and out_string.
+ */
+
+/* XXX err handling */
+
+/* Internal API */
+
+static void
+hb_buffer_ensure_separate (hb_buffer_t *buffer, unsigned int size)
+{
+  hb_buffer_ensure (buffer, size);
+  if (buffer->out_string == buffer->in_string)
+  {
+    assert (buffer->have_output);
+    if (!buffer->positions)
+      buffer->positions = (hb_internal_glyph_position_t *) calloc (buffer->allocated, sizeof (buffer->positions[0]));
+
+    buffer->out_string = (hb_internal_glyph_info_t *) buffer->positions;
+    memcpy (buffer->out_string, buffer->in_string, buffer->out_length * sizeof (buffer->out_string[0]));
+  }
+}
+
+/* Public API */
+
+hb_buffer_t *
+hb_buffer_create (unsigned int pre_alloc_size)
+{
+  hb_buffer_t *buffer;
+
+  if (!HB_OBJECT_DO_CREATE (hb_buffer_t, buffer))
+    return &_hb_buffer_nil;
+
+  if (pre_alloc_size)
+    hb_buffer_ensure(buffer, pre_alloc_size);
+
+  buffer->unicode = &_hb_unicode_funcs_nil;
+
+  return buffer;
+}
+
+hb_buffer_t *
+hb_buffer_reference (hb_buffer_t *buffer)
+{
+  HB_OBJECT_DO_REFERENCE (buffer);
+}
+
+unsigned int
+hb_buffer_get_reference_count (hb_buffer_t *buffer)
+{
+  HB_OBJECT_DO_GET_REFERENCE_COUNT (buffer);
+}
+
+void
+hb_buffer_destroy (hb_buffer_t *buffer)
+{
+  HB_OBJECT_DO_DESTROY (buffer);
+
+  hb_unicode_funcs_destroy (buffer->unicode);
+
+  free (buffer->in_string);
+  free (buffer->positions);
+
+  free (buffer);
+}
+
+
+void
+hb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
+			     hb_unicode_funcs_t *unicode)
+{
+  if (!unicode)
+    unicode = &_hb_unicode_funcs_nil;
+
+  hb_unicode_funcs_reference (unicode);
+  hb_unicode_funcs_destroy (buffer->unicode);
+  buffer->unicode = unicode;
+}
+
+hb_unicode_funcs_t *
+hb_buffer_get_unicode_funcs (hb_buffer_t        *buffer)
+{
+  return buffer->unicode;
+}
+
+void
+hb_buffer_set_direction (hb_buffer_t    *buffer,
+			 hb_direction_t  direction)
+
+{
+  buffer->direction = direction;
+}
+
+hb_direction_t
+hb_buffer_get_direction (hb_buffer_t    *buffer)
+{
+  return buffer->direction;
+}
+
+void
+hb_buffer_set_script (hb_buffer_t *buffer,
+		      hb_script_t  script)
+{
+  buffer->script = script;
+}
+
+hb_script_t
+hb_buffer_get_script (hb_buffer_t *buffer)
+{
+  return buffer->script;
+}
+
+void
+hb_buffer_set_language (hb_buffer_t   *buffer,
+			hb_language_t  language)
+{
+  buffer->language = language;
+}
+
+hb_language_t
+hb_buffer_get_language (hb_buffer_t *buffer)
+{
+  return buffer->language;
+}
+
+
+void
+hb_buffer_clear (hb_buffer_t *buffer)
+{
+  buffer->have_output = FALSE;
+  buffer->have_positions = FALSE;
+  buffer->in_length = 0;
+  buffer->out_length = 0;
+  buffer->in_pos = 0;
+  buffer->out_pos = 0;
+  buffer->out_string = buffer->in_string;
+  buffer->max_lig_id = 0;
+}
+
+void
+hb_buffer_ensure (hb_buffer_t *buffer, unsigned int size)
+{
+  unsigned int new_allocated = buffer->allocated;
+
+  if (size > new_allocated)
+  {
+    while (size > new_allocated)
+      new_allocated += (new_allocated >> 1) + 8;
+
+    if (buffer->positions)
+      buffer->positions = (hb_internal_glyph_position_t *) realloc (buffer->positions, new_allocated * sizeof (buffer->positions[0]));
+
+    if (buffer->out_string != buffer->in_string)
+    {
+      buffer->in_string = (hb_internal_glyph_info_t *) realloc (buffer->in_string, new_allocated * sizeof (buffer->in_string[0]));
+      buffer->out_string = (hb_internal_glyph_info_t *) buffer->positions;
+    }
+    else
+    {
+      buffer->in_string = (hb_internal_glyph_info_t *) realloc (buffer->in_string, new_allocated * sizeof (buffer->in_string[0]));
+      buffer->out_string = buffer->in_string;
+    }
+
+    buffer->allocated = new_allocated;
+  }
+}
+
+void
+hb_buffer_add_glyph (hb_buffer_t    *buffer,
+		     hb_codepoint_t  codepoint,
+		     hb_mask_t       mask,
+		     unsigned int    cluster)
+{
+  hb_internal_glyph_info_t *glyph;
+
+  hb_buffer_ensure (buffer, buffer->in_length + 1);
+
+  glyph = &buffer->in_string[buffer->in_length];
+  glyph->codepoint = codepoint;
+  glyph->mask = mask;
+  glyph->cluster = cluster;
+  glyph->component = 0;
+  glyph->lig_id = 0;
+  glyph->gproperty = HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN;
+
+  buffer->in_length++;
+}
+
+
+/* HarfBuzz-Internal API */
+
+void
+_hb_buffer_clear_output (hb_buffer_t *buffer)
+{
+  buffer->have_output = TRUE;
+  buffer->have_positions = FALSE;
+  buffer->out_length = 0;
+  buffer->out_pos = 0;
+  buffer->out_string = buffer->in_string;
+}
+
+void
+hb_buffer_clear_positions (hb_buffer_t *buffer)
+{
+  _hb_buffer_clear_output (buffer);
+  buffer->have_output = FALSE;
+  buffer->have_positions = TRUE;
+
+  if (unlikely (!buffer->positions))
+  {
+    buffer->positions = (hb_internal_glyph_position_t *) calloc (buffer->allocated, sizeof (buffer->positions[0]));
+    return;
+  }
+
+  memset (buffer->positions, 0, sizeof (buffer->positions[0]) * buffer->in_length);
+}
+
+void
+_hb_buffer_swap (hb_buffer_t *buffer)
+{
+  unsigned int tmp;
+
+  assert (buffer->have_output);
+
+  if (buffer->out_string != buffer->in_string)
+  {
+    hb_internal_glyph_info_t *tmp_string;
+    tmp_string = buffer->in_string;
+    buffer->in_string = buffer->out_string;
+    buffer->out_string = tmp_string;
+    buffer->positions = (hb_internal_glyph_position_t *) buffer->out_string;
+  }
+
+  tmp = buffer->in_length;
+  buffer->in_length = buffer->out_length;
+  buffer->out_length = tmp;
+
+  tmp = buffer->in_pos;
+  buffer->in_pos = buffer->out_pos;
+  buffer->out_pos = tmp;
+}
+
+/* The following function copies `num_out' elements from `glyph_data'
+   to `buffer->out_string', advancing the in array pointer in the structure
+   by `num_in' elements, and the out array pointer by `num_out' elements.
+   Finally, it sets the `length' field of `out' equal to
+   `pos' of the `out' structure.
+
+   If `component' is 0xFFFF, the component value from buffer->in_pos
+   will copied `num_out' times, otherwise `component' itself will
+   be used to fill the `component' fields.
+
+   If `lig_id' is 0xFFFF, the lig_id value from buffer->in_pos
+   will copied `num_out' times, otherwise `lig_id' itself will
+   be used to fill the `lig_id' fields.
+
+   The mask for all replacement glyphs are taken
+   from the glyph at position `buffer->in_pos'.
+
+   The cluster value for the glyph at position buffer->in_pos is used
+   for all replacement glyphs */
+
+void
+_hb_buffer_add_output_glyphs (hb_buffer_t *buffer,
+			      unsigned int num_in,
+			      unsigned int num_out,
+			      const hb_codepoint_t *glyph_data,
+			      unsigned short component,
+			      unsigned short lig_id)
+{
+  unsigned int i;
+  unsigned int mask;
+  unsigned int cluster;
+
+  if (buffer->out_string != buffer->in_string ||
+      buffer->out_pos + num_out > buffer->in_pos + num_in)
+  {
+    hb_buffer_ensure_separate (buffer, buffer->out_pos + num_out);
+  }
+
+  mask = buffer->in_string[buffer->in_pos].mask;
+  cluster = buffer->in_string[buffer->in_pos].cluster;
+  if (component == 0xFFFF)
+    component = buffer->in_string[buffer->in_pos].component;
+  if (lig_id == 0xFFFF)
+    lig_id = buffer->in_string[buffer->in_pos].lig_id;
+
+  for (i = 0; i < num_out; i++)
+  {
+    hb_internal_glyph_info_t *info = &buffer->out_string[buffer->out_pos + i];
+    info->codepoint = glyph_data[i];
+    info->mask = mask;
+    info->cluster = cluster;
+    info->component = component;
+    info->lig_id = lig_id;
+    info->gproperty = HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN;
+  }
+
+  buffer->in_pos  += num_in;
+  buffer->out_pos += num_out;
+  buffer->out_length = buffer->out_pos;
+}
+
+void
+_hb_buffer_add_output_glyphs_be16 (hb_buffer_t *buffer,
+				   unsigned int num_in,
+				   unsigned int num_out,
+				   const uint16_t *glyph_data_be,
+				   unsigned short component,
+				   unsigned short lig_id)
+{
+  unsigned int i;
+  unsigned int mask;
+  unsigned int cluster;
+
+  if (buffer->out_string != buffer->in_string ||
+      buffer->out_pos + num_out > buffer->in_pos + num_in)
+  {
+    hb_buffer_ensure_separate (buffer, buffer->out_pos + num_out);
+  }
+
+  mask = buffer->in_string[buffer->in_pos].mask;
+  cluster = buffer->in_string[buffer->in_pos].cluster;
+  if (component == 0xFFFF)
+    component = buffer->in_string[buffer->in_pos].component;
+  if (lig_id == 0xFFFF)
+    lig_id = buffer->in_string[buffer->in_pos].lig_id;
+
+  for (i = 0; i < num_out; i++)
+  {
+    hb_internal_glyph_info_t *info = &buffer->out_string[buffer->out_pos + i];
+    info->codepoint = hb_be_uint16 (glyph_data_be[i]);
+    info->mask = mask;
+    info->cluster = cluster;
+    info->component = component;
+    info->lig_id = lig_id;
+    info->gproperty = HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN;
+  }
+
+  buffer->in_pos  += num_in;
+  buffer->out_pos += num_out;
+  buffer->out_length = buffer->out_pos;
+}
+
+void
+_hb_buffer_add_output_glyph (hb_buffer_t *buffer,
+			     hb_codepoint_t glyph_index,
+			     unsigned short component,
+			     unsigned short lig_id)
+{
+  hb_internal_glyph_info_t *info;
+
+  if (buffer->out_string != buffer->in_string)
+  {
+    hb_buffer_ensure (buffer, buffer->out_pos + 1);
+    buffer->out_string[buffer->out_pos] = buffer->in_string[buffer->in_pos];
+  }
+  else if (buffer->out_pos != buffer->in_pos)
+    buffer->out_string[buffer->out_pos] = buffer->in_string[buffer->in_pos];
+
+  info = &buffer->out_string[buffer->out_pos];
+  info->codepoint = glyph_index;
+  if (component != 0xFFFF)
+    info->component = component;
+  if (lig_id != 0xFFFF)
+    info->lig_id = lig_id;
+  info->gproperty = HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN;
+
+  buffer->in_pos++;
+  buffer->out_pos++;
+  buffer->out_length = buffer->out_pos;
+}
+
+void
+_hb_buffer_next_glyph (hb_buffer_t *buffer)
+{
+  if (buffer->have_output)
+  {
+    if (buffer->out_string != buffer->in_string)
+    {
+      hb_buffer_ensure (buffer, buffer->out_pos + 1);
+      buffer->out_string[buffer->out_pos] = buffer->in_string[buffer->in_pos];
+    }
+    else if (buffer->out_pos != buffer->in_pos)
+      buffer->out_string[buffer->out_pos] = buffer->in_string[buffer->in_pos];
+
+    buffer->out_pos++;
+    buffer->out_length = buffer->out_pos;
+  }
+
+  buffer->in_pos++;
+}
+
+void
+_hb_buffer_replace_glyph (hb_buffer_t *buffer,
+			  hb_codepoint_t glyph_index)
+{
+  _hb_buffer_add_output_glyph (buffer, glyph_index, 0xFFFF, 0xFFFF);
+}
+
+unsigned short
+_hb_buffer_allocate_lig_id (hb_buffer_t *buffer)
+{
+  return ++buffer->max_lig_id;
+}
+
+
+unsigned int
+hb_buffer_get_length (hb_buffer_t *buffer)
+{
+  return buffer->in_length;
+}
+
+/* Return value valid as long as buffer not modified */
+hb_glyph_info_t *
+hb_buffer_get_glyph_infos (hb_buffer_t *buffer)
+{
+  return (hb_glyph_info_t *) buffer->in_string;
+}
+
+/* Return value valid as long as buffer not modified */
+hb_glyph_position_t *
+hb_buffer_get_glyph_positions (hb_buffer_t *buffer)
+{
+  if (!buffer->have_positions)
+    hb_buffer_clear_positions (buffer);
+
+  return (hb_glyph_position_t *) buffer->positions;
+}
+
+
+static void
+reverse_range (hb_buffer_t *buffer,
+	       unsigned int start,
+	       unsigned int end)
+{
+  unsigned int i, j;
+
+  for (i = start, j = end - 1; i < j; i++, j--) {
+    hb_internal_glyph_info_t t;
+
+    t = buffer->in_string[i];
+    buffer->in_string[i] = buffer->in_string[j];
+    buffer->in_string[j] = t;
+  }
+
+  if (buffer->positions) {
+    for (i = 0, j = end - 1; i < j; i++, j--) {
+      hb_internal_glyph_position_t t;
+
+      t = buffer->positions[i];
+      buffer->positions[i] = buffer->positions[j];
+      buffer->positions[j] = t;
+    }
+  }
+}
+
+void
+hb_buffer_reverse (hb_buffer_t *buffer)
+{
+  if (unlikely (!buffer->in_length))
+    return;
+
+  reverse_range (buffer, 0, buffer->in_length);
+}
+
+void
+hb_buffer_reverse_clusters (hb_buffer_t *buffer)
+{
+  unsigned int i, start, count, last_cluster;
+
+  if (unlikely (!buffer->in_length))
+    return;
+
+  hb_buffer_reverse (buffer);
+
+  count = buffer->in_length;
+  start = 0;
+  last_cluster = buffer->in_string[0].cluster;
+  for (i = 1; i < count; i++) {
+    if (last_cluster != buffer->in_string[i].cluster) {
+      reverse_range (buffer, start, i);
+      start = i;
+      last_cluster = buffer->in_string[i].cluster;
+    }
+  }
+  reverse_range (buffer, start, i);
+}
+
+
+#define ADD_UTF(T) \
+	HB_STMT_START { \
+	  const T *next = (const T *) text + item_offset; \
+	  const T *end = next + item_length; \
+	  while (next < end) { \
+	    hb_codepoint_t u; \
+	    const T *old_next = next; \
+	    next = UTF_NEXT (next, end, u); \
+	    hb_buffer_add_glyph (buffer, u, 0,  old_next - (const T *) text); \
+	  } \
+	} HB_STMT_END
+
+
+#define UTF8_COMPUTE(Char, Mask, Len) \
+  if (Char < 128) { Len = 1; Mask = 0x7f; } \
+  else if ((Char & 0xe0) == 0xc0) { Len = 2; Mask = 0x1f; } \
+  else if ((Char & 0xf0) == 0xe0) { Len = 3; Mask = 0x0f; } \
+  else if ((Char & 0xf8) == 0xf0) { Len = 4; Mask = 0x07; } \
+  else Len = 0;
+
+static inline const uint8_t *
+hb_utf8_next (const uint8_t *text,
+	      const uint8_t *end,
+	      hb_codepoint_t *unicode)
+{
+  uint8_t c = *text;
+  unsigned int mask, len;
+
+  UTF8_COMPUTE (c, mask, len);
+  if (unlikely (!len || (unsigned int) (end - text) < len)) {
+    *unicode = -1;
+    return text + 1;
+  } else {
+    hb_codepoint_t result;
+    unsigned int i;
+    result = c & mask;
+    for (i = 1; i < len; i++)
+      {
+	if (unlikely ((text[i] & 0xc0) != 0x80))
+	  {
+	    *unicode = -1;
+	    return text + 1;
+	  }
+	result <<= 6;
+	result |= (text[i] & 0x3f);
+      }
+    *unicode = result;
+    return text + len;
+  }
+}
+
+void
+hb_buffer_add_utf8 (hb_buffer_t  *buffer,
+		    const char   *text,
+		    unsigned int  text_length HB_UNUSED,
+		    unsigned int  item_offset,
+		    unsigned int  item_length)
+{
+#define UTF_NEXT(S, E, U)	hb_utf8_next (S, E, &(U))
+  ADD_UTF (uint8_t);
+#undef UTF_NEXT
+}
+
+static inline const uint16_t *
+hb_utf16_next (const uint16_t *text,
+	       const uint16_t *end,
+	       hb_codepoint_t *unicode)
+{
+  uint16_t c = *text++;
+
+  if (unlikely (c >= 0xd800 && c < 0xdc00)) {
+    /* high surrogate */
+    uint16_t l;
+    if (text < end && ((l = *text), unlikely (l >= 0xdc00 && l < 0xe000))) {
+      /* low surrogate */
+      *unicode = ((hb_codepoint_t) ((c) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x10000);
+       text++;
+    } else
+      *unicode = -1;
+  } else
+    *unicode = c;
+
+  return text;
+}
+
+void
+hb_buffer_add_utf16 (hb_buffer_t    *buffer,
+		     const uint16_t *text,
+		     unsigned int    text_length HB_UNUSED,
+		     unsigned int    item_offset,
+		     unsigned int    item_length)
+{
+#define UTF_NEXT(S, E, U)	hb_utf16_next (S, E, &(U))
+  ADD_UTF (uint16_t);
+#undef UTF_NEXT
+}
+
+void
+hb_buffer_add_utf32 (hb_buffer_t    *buffer,
+		     const uint32_t *text,
+		     unsigned int    text_length HB_UNUSED,
+		     unsigned int    item_offset,
+		     unsigned int    item_length)
+{
+#define UTF_NEXT(S, E, U)	((U) = *(S), (S)+1)
+  ADD_UTF (uint32_t);
+#undef UTF_NEXT
+}
diff --git a/src/hb-common.h b/src/hb-common.h
index a2bc114..cc673ad 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -83,6 +83,7 @@ typedef enum _hb_direction_t {
 #define HB_DIRECTION_IS_VERTICAL(dir)	((dir) == HB_DIRECTION_TTB || (dir) == HB_DIRECTION_BTT)
 #define HB_DIRECTION_IS_FORWARD(dir)	((dir) == HB_DIRECTION_LTR || (dir) == HB_DIRECTION_TTB)
 #define HB_DIRECTION_IS_BACKWARD(dir)	((dir) == HB_DIRECTION_RTL || (dir) == HB_DIRECTION_BTT)
+#define HB_DIRECTION_REVERSE(dir)	((hb_direction_t) (((unsigned int) (dir)) ^ 1))
 
 
 #endif /* HB_COMMON_H */
diff --git a/src/hb-font-private.h b/src/hb-font-private.h
deleted file mode 100644
index 2b024cc..0000000
--- a/src/hb-font-private.h
+++ /dev/null
@@ -1,92 +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_FONT_PRIVATE_H
-#define HB_FONT_PRIVATE_H
-
-#include "hb-private.h"
-
-#include "hb-font.h"
-
-#include "hb-ot-layout-private.h"
-
-HB_BEGIN_DECLS
-
-/*
- * hb_font_funcs_t
- */
-
-struct _hb_font_funcs_t {
-  hb_reference_count_t ref_count;
-
-  hb_bool_t immutable;
-
-  hb_font_get_glyph_func_t		get_glyph;
-  hb_font_get_contour_point_func_t	get_contour_point;
-  hb_font_get_glyph_metrics_func_t	get_glyph_metrics;
-  hb_font_get_kerning_func_t		get_kerning;
-};
-
-HB_INTERNAL hb_font_funcs_t
-_hb_font_funcs_nil;
-
-/*
- * hb_face_t
- */
-
-struct _hb_face_t {
-  hb_reference_count_t ref_count;
-
-  hb_get_table_func_t  get_table;
-  hb_destroy_func_t    destroy;
-  void                *user_data;
-
-  hb_ot_layout_t ot_layout;
-};
-
-
-/*
- * hb_font_t
- */
-
-struct _hb_font_t {
-  hb_reference_count_t ref_count;
-
-  hb_16dot16_t x_scale;
-  hb_16dot16_t y_scale;
-
-  unsigned int x_ppem;
-  unsigned int y_ppem;
-
-  hb_font_funcs_t   *klass;
-  hb_destroy_func_t  destroy;
-  void              *user_data;
-};
-
-
-HB_END_DECLS
-
-#endif /* HB_FONT_PRIVATE_H */
diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
new file mode 100644
index 0000000..ec07931
--- /dev/null
+++ b/src/hb-font-private.hh
@@ -0,0 +1,92 @@
+/*
+ * 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_FONT_PRIVATE_H
+#define HB_FONT_PRIVATE_H
+
+#include "hb-private.h"
+
+#include "hb-font.h"
+
+#include "hb-ot-layout-private.hh"
+
+HB_BEGIN_DECLS
+
+/*
+ * hb_font_funcs_t
+ */
+
+struct _hb_font_funcs_t {
+  hb_reference_count_t ref_count;
+
+  hb_bool_t immutable;
+
+  hb_font_get_glyph_func_t		get_glyph;
+  hb_font_get_contour_point_func_t	get_contour_point;
+  hb_font_get_glyph_metrics_func_t	get_glyph_metrics;
+  hb_font_get_kerning_func_t		get_kerning;
+};
+
+HB_INTERNAL hb_font_funcs_t
+_hb_font_funcs_nil;
+
+/*
+ * hb_face_t
+ */
+
+struct _hb_face_t {
+  hb_reference_count_t ref_count;
+
+  hb_get_table_func_t  get_table;
+  hb_destroy_func_t    destroy;
+  void                *user_data;
+
+  hb_ot_layout_t ot_layout;
+};
+
+
+/*
+ * hb_font_t
+ */
+
+struct _hb_font_t {
+  hb_reference_count_t ref_count;
+
+  hb_16dot16_t x_scale;
+  hb_16dot16_t y_scale;
+
+  unsigned int x_ppem;
+  unsigned int y_ppem;
+
+  hb_font_funcs_t   *klass;
+  hb_destroy_func_t  destroy;
+  void              *user_data;
+};
+
+
+HB_END_DECLS
+
+#endif /* HB_FONT_PRIVATE_H */
diff --git a/src/hb-font.cc b/src/hb-font.cc
index 20aeb16..46b63a4 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -26,11 +26,11 @@
 
 #include "hb-private.h"
 
-#include "hb-font-private.h"
+#include "hb-font-private.hh"
 #include "hb-blob-private.h"
 #include "hb-open-file-private.hh"
 
-#include "hb-ot-layout-private.h"
+#include "hb-ot-layout-private.hh"
 
 #include <string.h>
 
diff --git a/src/hb-ft.c b/src/hb-ft.c
deleted file mode 100644
index e6f3e84..0000000
--- a/src/hb-ft.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (C) 2009  Red Hat, Inc.
- * Copyright (C) 2009  Keith Stribley <devel at thanlwinsoft.org>
- *
- *  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-ft.h"
-
-#include "hb-font-private.h"
-
-#include FT_TRUETYPE_TABLES_H
-
-static hb_codepoint_t
-hb_ft_get_glyph (hb_font_t *font HB_UNUSED,
-		 hb_face_t *face HB_UNUSED,
-		 const void *user_data,
-		 hb_codepoint_t unicode,
-		 hb_codepoint_t variation_selector)
-{
-  FT_Face ft_face = (FT_Face) user_data;
-
-#ifdef HAVE_FT_FACE_GETCHARVARIANTINDEX
-  if (unlikely (variation_selector)) {
-    hb_codepoint_t glyph = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector);
-    if (glyph)
-      return glyph;
-  }
-#endif
-
-  return FT_Get_Char_Index (ft_face, unicode);
-}
-
-static hb_bool_t
-hb_ft_get_contour_point (hb_font_t *font HB_UNUSED,
-			 hb_face_t *face HB_UNUSED,
-			 const void *user_data,
-			 unsigned int point_index,
-			 hb_codepoint_t glyph,
-			 hb_position_t *x,
-			 hb_position_t *y)
-{
-  FT_Face ft_face = (FT_Face) user_data;
-  int load_flags = FT_LOAD_DEFAULT;
-
-  /* TODO: load_flags, embolden, etc */
-
-  if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
-      return FALSE;
-
-  if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE))
-      return FALSE;
-
-  if (unlikely (point_index >= (unsigned int) ft_face->glyph->outline.n_points))
-      return FALSE;
-
-  *x = ft_face->glyph->outline.points[point_index].x;
-  *y = ft_face->glyph->outline.points[point_index].y;
-
-  return TRUE;
-}
-
-static void
-hb_ft_get_glyph_metrics (hb_font_t *font HB_UNUSED,
-			 hb_face_t *face HB_UNUSED,
-			 const void *user_data,
-			 hb_codepoint_t glyph,
-			 hb_glyph_metrics_t *metrics)
-{
-  FT_Face ft_face = (FT_Face) user_data;
-  int load_flags = FT_LOAD_DEFAULT;
-
-  /* TODO: load_flags, embolden, etc */
-
-  metrics->x_advance = metrics->y_advance = 0;
-  metrics->x_offset = metrics->y_offset = 0;
-  metrics->width = metrics->height = 0;
-  if (likely (!FT_Load_Glyph (ft_face, glyph, load_flags)))
-  {
-    /* TODO: A few negations should be in order here, not sure. */
-    metrics->x_advance = ft_face->glyph->advance.x;
-    metrics->y_advance = ft_face->glyph->advance.y;
-    metrics->x_offset = ft_face->glyph->metrics.horiBearingX;
-    metrics->y_offset = ft_face->glyph->metrics.horiBearingY;
-    metrics->width = ft_face->glyph->metrics.width;
-    metrics->height = ft_face->glyph->metrics.height;
-  }
-}
-
-static hb_position_t
-hb_ft_get_kerning (hb_font_t *font HB_UNUSED,
-		   hb_face_t *face HB_UNUSED,
-		   const void *user_data,
-		   hb_codepoint_t first_glyph,
-		   hb_codepoint_t second_glyph)
-{
-  FT_Face ft_face = (FT_Face) user_data;
-  FT_Vector kerning;
-
-  /* TODO: Kern type? */
-  if (FT_Get_Kerning (ft_face, first_glyph, second_glyph, FT_KERNING_DEFAULT, &kerning))
-      return 0;
-
-  return kerning.x;
-}
-
-static hb_font_funcs_t ft_ffuncs = {
-  HB_REFERENCE_COUNT_INVALID, /* ref_count */
-
-  TRUE, /* immutable */
-
-  hb_ft_get_glyph,
-  hb_ft_get_contour_point,
-  hb_ft_get_glyph_metrics,
-  hb_ft_get_kerning
-};
-
-hb_font_funcs_t *
-hb_ft_get_font_funcs (void)
-{
-  return &ft_ffuncs;
-}
-
-
-static hb_blob_t *
-_get_table  (hb_tag_t tag, void *user_data)
-{
-  FT_Face ft_face = (FT_Face) user_data;
-  FT_Byte *buffer;
-  FT_ULong  length = 0;
-  FT_Error error;
-
-  if (unlikely (tag == HB_TAG_NONE))
-    return hb_blob_create_empty ();
-
-  error = FT_Load_Sfnt_Table (ft_face, tag, 0, NULL, &length);
-  if (error)
-    return hb_blob_create_empty ();
-
-  /* TODO Use FT_Memory? */
-  buffer = malloc (length);
-  if (buffer == NULL)
-    return NULL;
-
-  error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
-  if (error)
-    return hb_blob_create_empty ();
-
-  return hb_blob_create ((const char *) buffer, length,
-			 HB_MEMORY_MODE_WRITABLE,
-			 free, buffer);
-}
-
-
-hb_face_t *
-hb_ft_face_create (FT_Face           ft_face,
-		   hb_destroy_func_t destroy)
-{
-  hb_face_t *face;
-
-  if (ft_face->stream->read == NULL) {
-    hb_blob_t *blob;
-
-    blob = hb_blob_create ((const char *) ft_face->stream->base,
-			   (unsigned int) ft_face->stream->size,
-			   /* TODO: Check FT_FACE_FLAG_EXTERNAL_STREAM? */
-			   HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE,
-			   destroy, ft_face);
-    face = hb_face_create_for_data (blob, ft_face->face_index);
-    hb_blob_destroy (blob);
-  } else {
-    face = hb_face_create_for_tables (_get_table, destroy, ft_face);
-  }
-
-  return face;
-}
-
-static void
-hb_ft_face_finalize (FT_Face ft_face)
-{
-  hb_face_destroy (ft_face->generic.data);
-}
-
-hb_face_t *
-hb_ft_face_create_cached (FT_Face ft_face)
-{
-  if (unlikely (!ft_face->generic.data || ft_face->generic.finalizer != (FT_Generic_Finalizer) hb_ft_face_finalize))
-  {
-    if (ft_face->generic.finalizer)
-      ft_face->generic.finalizer (ft_face);
-
-    ft_face->generic.data = hb_ft_face_create (ft_face, NULL);
-    ft_face->generic.finalizer = (FT_Generic_Finalizer) hb_ft_face_finalize;
-  }
-
-  return hb_face_reference (ft_face->generic.data);
-}
-
-
-hb_font_t *
-hb_ft_font_create (FT_Face           ft_face,
-		   hb_destroy_func_t destroy)
-{
-  hb_font_t *font;
-
-  font = hb_font_create ();
-  hb_font_set_funcs (font,
-		     hb_ft_get_font_funcs (),
-		     destroy, ft_face);
-  hb_font_set_scale (font,
-		     ft_face->size->metrics.x_scale,
-		     ft_face->size->metrics.y_scale);
-  hb_font_set_ppem (font,
-		    ft_face->size->metrics.x_ppem,
-		    ft_face->size->metrics.y_ppem);
-
-  return font;
-}
diff --git a/src/hb-ft.cc b/src/hb-ft.cc
new file mode 100644
index 0000000..5b911bc
--- /dev/null
+++ b/src/hb-ft.cc
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2009  Red Hat, Inc.
+ * Copyright (C) 2009  Keith Stribley <devel at thanlwinsoft.org>
+ *
+ *  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-ft.h"
+
+#include "hb-font-private.hh"
+
+#include FT_TRUETYPE_TABLES_H
+
+static hb_codepoint_t
+hb_ft_get_glyph (hb_font_t *font HB_UNUSED,
+		 hb_face_t *face HB_UNUSED,
+		 const void *user_data,
+		 hb_codepoint_t unicode,
+		 hb_codepoint_t variation_selector)
+{
+  FT_Face ft_face = (FT_Face) user_data;
+
+#ifdef HAVE_FT_FACE_GETCHARVARIANTINDEX
+  if (unlikely (variation_selector)) {
+    hb_codepoint_t glyph = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector);
+    if (glyph)
+      return glyph;
+  }
+#endif
+
+  return FT_Get_Char_Index (ft_face, unicode);
+}
+
+static hb_bool_t
+hb_ft_get_contour_point (hb_font_t *font HB_UNUSED,
+			 hb_face_t *face HB_UNUSED,
+			 const void *user_data,
+			 unsigned int point_index,
+			 hb_codepoint_t glyph,
+			 hb_position_t *x,
+			 hb_position_t *y)
+{
+  FT_Face ft_face = (FT_Face) user_data;
+  int load_flags = FT_LOAD_DEFAULT;
+
+  /* TODO: load_flags, embolden, etc */
+
+  if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
+      return FALSE;
+
+  if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE))
+      return FALSE;
+
+  if (unlikely (point_index >= (unsigned int) ft_face->glyph->outline.n_points))
+      return FALSE;
+
+  *x = ft_face->glyph->outline.points[point_index].x;
+  *y = ft_face->glyph->outline.points[point_index].y;
+
+  return TRUE;
+}
+
+static void
+hb_ft_get_glyph_metrics (hb_font_t *font HB_UNUSED,
+			 hb_face_t *face HB_UNUSED,
+			 const void *user_data,
+			 hb_codepoint_t glyph,
+			 hb_glyph_metrics_t *metrics)
+{
+  FT_Face ft_face = (FT_Face) user_data;
+  int load_flags = FT_LOAD_DEFAULT;
+
+  /* TODO: load_flags, embolden, etc */
+
+  metrics->x_advance = metrics->y_advance = 0;
+  metrics->x_offset = metrics->y_offset = 0;
+  metrics->width = metrics->height = 0;
+  if (likely (!FT_Load_Glyph (ft_face, glyph, load_flags)))
+  {
+    /* TODO: A few negations should be in order here, not sure. */
+    metrics->x_advance = ft_face->glyph->advance.x;
+    metrics->y_advance = ft_face->glyph->advance.y;
+    metrics->x_offset = ft_face->glyph->metrics.horiBearingX;
+    metrics->y_offset = ft_face->glyph->metrics.horiBearingY;
+    metrics->width = ft_face->glyph->metrics.width;
+    metrics->height = ft_face->glyph->metrics.height;
+  }
+}
+
+static hb_position_t
+hb_ft_get_kerning (hb_font_t *font HB_UNUSED,
+		   hb_face_t *face HB_UNUSED,
+		   const void *user_data,
+		   hb_codepoint_t first_glyph,
+		   hb_codepoint_t second_glyph)
+{
+  FT_Face ft_face = (FT_Face) user_data;
+  FT_Vector kerning;
+
+  /* TODO: Kern type? */
+  if (FT_Get_Kerning (ft_face, first_glyph, second_glyph, FT_KERNING_DEFAULT, &kerning))
+      return 0;
+
+  return kerning.x;
+}
+
+static hb_font_funcs_t ft_ffuncs = {
+  HB_REFERENCE_COUNT_INVALID, /* ref_count */
+
+  TRUE, /* immutable */
+
+  hb_ft_get_glyph,
+  hb_ft_get_contour_point,
+  hb_ft_get_glyph_metrics,
+  hb_ft_get_kerning
+};
+
+hb_font_funcs_t *
+hb_ft_get_font_funcs (void)
+{
+  return &ft_ffuncs;
+}
+
+
+static hb_blob_t *
+_get_table  (hb_tag_t tag, void *user_data)
+{
+  FT_Face ft_face = (FT_Face) user_data;
+  FT_Byte *buffer;
+  FT_ULong  length = 0;
+  FT_Error error;
+
+  if (unlikely (tag == HB_TAG_NONE))
+    return hb_blob_create_empty ();
+
+  error = FT_Load_Sfnt_Table (ft_face, tag, 0, NULL, &length);
+  if (error)
+    return hb_blob_create_empty ();
+
+  /* TODO Use FT_Memory? */
+  buffer = (FT_Byte *) malloc (length);
+  if (buffer == NULL)
+    return NULL;
+
+  error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
+  if (error)
+    return hb_blob_create_empty ();
+
+  return hb_blob_create ((const char *) buffer, length,
+			 HB_MEMORY_MODE_WRITABLE,
+			 free, buffer);
+}
+
+
+hb_face_t *
+hb_ft_face_create (FT_Face           ft_face,
+		   hb_destroy_func_t destroy)
+{
+  hb_face_t *face;
+
+  if (ft_face->stream->read == NULL) {
+    hb_blob_t *blob;
+
+    blob = hb_blob_create ((const char *) ft_face->stream->base,
+			   (unsigned int) ft_face->stream->size,
+			   /* TODO: Check FT_FACE_FLAG_EXTERNAL_STREAM? */
+			   HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE,
+			   destroy, ft_face);
+    face = hb_face_create_for_data (blob, ft_face->face_index);
+    hb_blob_destroy (blob);
+  } else {
+    face = hb_face_create_for_tables (_get_table, destroy, ft_face);
+  }
+
+  return face;
+}
+
+static void
+hb_ft_face_finalize (FT_Face ft_face)
+{
+  hb_face_destroy ((hb_face_t *) ft_face->generic.data);
+}
+
+hb_face_t *
+hb_ft_face_create_cached (FT_Face ft_face)
+{
+  if (unlikely (!ft_face->generic.data || ft_face->generic.finalizer != (FT_Generic_Finalizer) hb_ft_face_finalize))
+  {
+    if (ft_face->generic.finalizer)
+      ft_face->generic.finalizer (ft_face);
+
+    ft_face->generic.data = hb_ft_face_create (ft_face, NULL);
+    ft_face->generic.finalizer = (FT_Generic_Finalizer) hb_ft_face_finalize;
+  }
+
+  return hb_face_reference ((hb_face_t *) ft_face->generic.data);
+}
+
+
+hb_font_t *
+hb_ft_font_create (FT_Face           ft_face,
+		   hb_destroy_func_t destroy)
+{
+  hb_font_t *font;
+
+  font = hb_font_create ();
+  hb_font_set_funcs (font,
+		     hb_ft_get_font_funcs (),
+		     destroy, ft_face);
+  hb_font_set_scale (font,
+		     ft_face->size->metrics.x_scale,
+		     ft_face->size->metrics.y_scale);
+  hb_font_set_ppem (font,
+		    ft_face->size->metrics.x_ppem,
+		    ft_face->size->metrics.y_ppem);
+
+  return font;
+}
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 75cbc64..8c04150 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -27,7 +27,7 @@
 #ifndef HB_OT_LAYOUT_COMMON_PRIVATE_HH
 #define HB_OT_LAYOUT_COMMON_PRIVATE_HH
 
-#include "hb-ot-layout-private.h"
+#include "hb-ot-layout-private.hh"
 
 #include "hb-open-type-private.hh"
 
diff --git a/src/hb-ot-layout-gdef-private.hh b/src/hb-ot-layout-gdef-private.hh
index 517f9ef..d43a4c2 100644
--- a/src/hb-ot-layout-gdef-private.hh
+++ b/src/hb-ot-layout-gdef-private.hh
@@ -29,7 +29,7 @@
 
 #include "hb-ot-layout-common-private.hh"
 
-#include "hb-font-private.h"
+#include "hb-font-private.hh"
 
 
 /*
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index 09c817d..066abbd 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -27,7 +27,7 @@
 #ifndef HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
 #define HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
 
-#include "hb-buffer-private.h"
+#include "hb-buffer-private.hh"
 #include "hb-ot-layout-gdef-private.hh"
 
 
diff --git a/src/hb-ot-layout-private.h b/src/hb-ot-layout-private.h
deleted file mode 100644
index a9d4c57..0000000
--- a/src/hb-ot-layout-private.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2007,2008,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_OT_LAYOUT_PRIVATE_H
-#define HB_OT_LAYOUT_PRIVATE_H
-
-#include "hb-private.h"
-
-#include "hb-ot-layout.h"
-
-#include "hb-font.h"
-#include "hb-buffer-private.h"
-
-
-HB_BEGIN_DECLS
-
-typedef unsigned int hb_ot_layout_class_t;
-
-/*
- * hb_ot_layout_t
- */
-
-typedef struct _hb_ot_layout_t hb_ot_layout_t;
-
-struct _hb_ot_layout_t
-{
-  hb_blob_t *gdef_blob;
-  hb_blob_t *gsub_blob;
-  hb_blob_t *gpos_blob;
-
-  const struct GDEF *gdef;
-  const struct GSUB *gsub;
-  const struct GPOS *gpos;
-
-  struct
-  {
-    unsigned char *klasses;
-    unsigned int len;
-  } new_gdef;
-};
-
-typedef struct _hb_ot_layout_context_t hb_ot_layout_context_t;
-struct _hb_ot_layout_context_t
-{
-  hb_face_t *face;
-  hb_font_t *font;
-
-  union info_t
-  {
-    struct gpos_t
-    {
-      unsigned int last;        /* the last valid glyph--used with cursive positioning */
-      hb_position_t anchor_x;   /* the coordinates of the anchor point */
-      hb_position_t anchor_y;   /* of the last valid glyph */
-    } gpos;
-  } info;
-};
-
-
-void
-_hb_ot_layout_init (hb_face_t *face);
-
-void
-_hb_ot_layout_fini (hb_face_t *face);
-
-
-/*
- * GDEF
- */
-
-HB_INTERNAL hb_bool_t
-_hb_ot_layout_has_new_glyph_classes (hb_face_t *face);
-
-HB_INTERNAL void
-_hb_ot_layout_set_glyph_property (hb_face_t      *face,
-				  hb_codepoint_t  glyph,
-				  unsigned int    property);
-
-HB_INTERNAL void
-_hb_ot_layout_set_glyph_class (hb_face_t                  *face,
-			       hb_codepoint_t              glyph,
-			       hb_ot_layout_glyph_class_t  klass);
-
-HB_INTERNAL hb_bool_t
-_hb_ot_layout_check_glyph_property (hb_face_t    *face,
-				    hb_internal_glyph_info_t *ginfo,
-				    unsigned int  lookup_flags,
-				    unsigned int *property);
-
-HB_INTERNAL hb_bool_t
-_hb_ot_layout_skip_mark (hb_face_t    *face,
-			 hb_internal_glyph_info_t *ginfo,
-			 unsigned int  lookup_flags,
-			 unsigned int *property);
-
-HB_END_DECLS
-
-#endif /* HB_OT_LAYOUT_PRIVATE_H */
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
new file mode 100644
index 0000000..e18222b
--- /dev/null
+++ b/src/hb-ot-layout-private.hh
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2007,2008,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_OT_LAYOUT_PRIVATE_H
+#define HB_OT_LAYOUT_PRIVATE_H
+
+#include "hb-private.h"
+
+#include "hb-ot-layout.h"
+
+#include "hb-font.h"
+#include "hb-buffer-private.hh"
+
+
+HB_BEGIN_DECLS
+
+typedef unsigned int hb_ot_layout_class_t;
+
+/*
+ * hb_ot_layout_t
+ */
+
+typedef struct _hb_ot_layout_t hb_ot_layout_t;
+
+struct _hb_ot_layout_t
+{
+  hb_blob_t *gdef_blob;
+  hb_blob_t *gsub_blob;
+  hb_blob_t *gpos_blob;
+
+  const struct GDEF *gdef;
+  const struct GSUB *gsub;
+  const struct GPOS *gpos;
+
+  struct
+  {
+    unsigned char *klasses;
+    unsigned int len;
+  } new_gdef;
+};
+
+typedef struct _hb_ot_layout_context_t hb_ot_layout_context_t;
+struct _hb_ot_layout_context_t
+{
+  hb_face_t *face;
+  hb_font_t *font;
+
+  union info_t
+  {
+    struct gpos_t
+    {
+      unsigned int last;        /* the last valid glyph--used with cursive positioning */
+      hb_position_t anchor_x;   /* the coordinates of the anchor point */
+      hb_position_t anchor_y;   /* of the last valid glyph */
+    } gpos;
+  } info;
+};
+
+
+void
+_hb_ot_layout_init (hb_face_t *face);
+
+void
+_hb_ot_layout_fini (hb_face_t *face);
+
+
+/*
+ * GDEF
+ */
+
+HB_INTERNAL hb_bool_t
+_hb_ot_layout_has_new_glyph_classes (hb_face_t *face);
+
+HB_INTERNAL void
+_hb_ot_layout_set_glyph_property (hb_face_t      *face,
+				  hb_codepoint_t  glyph,
+				  unsigned int    property);
+
+HB_INTERNAL void
+_hb_ot_layout_set_glyph_class (hb_face_t                  *face,
+			       hb_codepoint_t              glyph,
+			       hb_ot_layout_glyph_class_t  klass);
+
+HB_INTERNAL hb_bool_t
+_hb_ot_layout_check_glyph_property (hb_face_t    *face,
+				    hb_internal_glyph_info_t *ginfo,
+				    unsigned int  lookup_flags,
+				    unsigned int *property);
+
+HB_INTERNAL hb_bool_t
+_hb_ot_layout_skip_mark (hb_face_t    *face,
+			 hb_internal_glyph_info_t *ginfo,
+			 unsigned int  lookup_flags,
+			 unsigned int *property);
+
+HB_END_DECLS
+
+#endif /* HB_OT_LAYOUT_PRIVATE_H */
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 5908cdd..63186a3 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -28,7 +28,7 @@
 
 #define HB_OT_LAYOUT_CC
 
-#include "hb-ot-layout-private.h"
+#include "hb-ot-layout-private.hh"
 
 #include "hb-ot-layout-gdef-private.hh"
 #include "hb-ot-layout-gsub-private.hh"
diff --git a/src/hb-ot-shape-private.h b/src/hb-ot-shape-private.h
deleted file mode 100644
index 1183a63..0000000
--- a/src/hb-ot-shape-private.h
+++ /dev/null
@@ -1,53 +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_OT_SHAPE_PRIVATE_H
-#define HB_OT_SHAPE_PRIVATE_H
-
-#include "hb-private.h"
-
-#include "hb-shape.h"
-
-
-HB_BEGIN_DECLS
-
-HB_INTERNAL hb_bool_t
-_hb_ot_substitute_complex (hb_font_t    *font,
-			   hb_face_t    *face,
-			   hb_buffer_t  *buffer,
-			   hb_feature_t *features,
-			   unsigned int  num_features);
-
-HB_INTERNAL hb_bool_t
-_hb_ot_position_complex (hb_font_t    *font,
-			 hb_face_t    *face,
-			 hb_buffer_t  *buffer,
-			 hb_feature_t *features,
-			 unsigned int  num_features);
-
-HB_END_DECLS
-
-#endif /* HB_OT_SHAPE_PRIVATE_H */
diff --git a/src/hb-ot-shape-private.hh b/src/hb-ot-shape-private.hh
new file mode 100644
index 0000000..1183a63
--- /dev/null
+++ b/src/hb-ot-shape-private.hh
@@ -0,0 +1,53 @@
+/*
+ * 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_OT_SHAPE_PRIVATE_H
+#define HB_OT_SHAPE_PRIVATE_H
+
+#include "hb-private.h"
+
+#include "hb-shape.h"
+
+
+HB_BEGIN_DECLS
+
+HB_INTERNAL hb_bool_t
+_hb_ot_substitute_complex (hb_font_t    *font,
+			   hb_face_t    *face,
+			   hb_buffer_t  *buffer,
+			   hb_feature_t *features,
+			   unsigned int  num_features);
+
+HB_INTERNAL hb_bool_t
+_hb_ot_position_complex (hb_font_t    *font,
+			 hb_face_t    *face,
+			 hb_buffer_t  *buffer,
+			 hb_feature_t *features,
+			 unsigned int  num_features);
+
+HB_END_DECLS
+
+#endif /* HB_OT_SHAPE_PRIVATE_H */
diff --git a/src/hb-ot-shape.c b/src/hb-ot-shape.c
deleted file mode 100644
index 7ff8166..0000000
--- a/src/hb-ot-shape.c
+++ /dev/null
@@ -1,164 +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-ot-shape-private.h"
-
-#include "hb-buffer-private.h"
-
-#include "hb-ot-layout.h"
-
-hb_tag_t default_features[] = {
-  /* GSUB */
-  HB_TAG('c','c','m','p'),
-  HB_TAG('l','o','c','l'),
-  HB_TAG('l','i','g','a'),
-  HB_TAG('c','l','i','g'),
-  /* GPOS */
-  HB_TAG('k','e','r','n'),
-  HB_TAG('m','a','r','k'),
-  HB_TAG('m','k','m','k'),
-};
-
-
-static void
-add_feature (hb_face_t    *face,
-	     hb_tag_t      table_tag,
-	     unsigned int  feature_index,
-	     unsigned int *lookups,
-	     unsigned int *num_lookups,
-	     unsigned int  room_lookups)
-{
-  unsigned int i = room_lookups - *num_lookups;
-  hb_ot_layout_feature_get_lookup_indexes (face, table_tag, feature_index, 0,
-					   &i,
-					   lookups + *num_lookups);
-  *num_lookups += i;
-}
-
-static int
-cmp_lookups (const void *p1, const void *p2)
-{
-  unsigned int a = * (const unsigned int *) p1;
-  unsigned int b = * (const unsigned int *) p2;
-
-  return a - b;
-}
-
-static void
-setup_lookups (hb_face_t    *face,
-	       hb_buffer_t  *buffer,
-	       hb_feature_t *features,
-	       unsigned int  num_features,
-	       hb_tag_t      table_tag,
-	       unsigned int *lookups,
-	       unsigned int *num_lookups)
-{
-  unsigned int i, j, script_index, language_index, feature_index, room_lookups;
-
-  room_lookups = *num_lookups;
-  *num_lookups = 0;
-
-  hb_ot_layout_table_choose_script (face, table_tag,
-				    hb_ot_tags_from_script (buffer->script),
-				    &script_index);
-  hb_ot_layout_script_find_language (face, table_tag, script_index,
-				     hb_ot_tag_from_language (buffer->language),
-				     &language_index);
-
-  if (hb_ot_layout_language_get_required_feature_index (face, table_tag, script_index, language_index,
-							&feature_index))
-    add_feature (face, table_tag, feature_index, lookups, num_lookups, room_lookups);
-
-  for (i = 0; i < ARRAY_LENGTH (default_features); i++)
-  {
-    if (hb_ot_layout_language_find_feature (face, table_tag, script_index, language_index,
-					    default_features[i],
-					    &feature_index))
-      add_feature (face, table_tag, feature_index, lookups, num_lookups, room_lookups);
-  }
-
-  qsort (lookups, *num_lookups, sizeof (lookups[0]), cmp_lookups);
-
-  if (*num_lookups)
-  {
-    for (i = 1, j = 0; i < *num_lookups; i++)
-      if (lookups[i] != lookups[j])
-	lookups[++j] = lookups[i];
-    lookups[j++] = lookups[i - 1];
-    *num_lookups = j;
-  }
-}
-
-
-hb_bool_t
-_hb_ot_substitute_complex (hb_font_t    *font HB_UNUSED,
-			   hb_face_t    *face,
-			   hb_buffer_t  *buffer,
-			   hb_feature_t *features,
-			   unsigned int  num_features)
-{
-  unsigned int lookups[1000];
-  unsigned int num_lookups = ARRAY_LENGTH (lookups);
-  unsigned int i;
-
-  if (!hb_ot_layout_has_substitution (face))
-    return FALSE;
-
-  setup_lookups (face, buffer, features, num_features,
-		 HB_OT_TAG_GSUB,
-		 lookups, &num_lookups);
-
-  for (i = 0; i < num_lookups; i++)
-    hb_ot_layout_substitute_lookup (face, buffer, lookups[i], 0xFFFF);
-
-  return TRUE;
-}
-
-hb_bool_t
-_hb_ot_position_complex (hb_font_t    *font,
-			 hb_face_t    *face,
-			 hb_buffer_t  *buffer,
-			 hb_feature_t *features,
-			 unsigned int  num_features)
-{
-  unsigned int lookups[1000];
-  unsigned int num_lookups = ARRAY_LENGTH (lookups);
-  unsigned int i;
-
-  if (!hb_ot_layout_has_positioning (face))
-    return FALSE;
-
-  setup_lookups (face, buffer, features, num_features,
-		 HB_OT_TAG_GPOS,
-		 lookups, &num_lookups);
-
-  for (i = 0; i < num_lookups; i++)
-    hb_ot_layout_position_lookup (font, face, buffer, lookups[i], 0xFFFF);
-
-  hb_ot_layout_position_finish (font, face, buffer);
-
-  return TRUE;
-}
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
new file mode 100644
index 0000000..61f67cd
--- /dev/null
+++ b/src/hb-ot-shape.cc
@@ -0,0 +1,164 @@
+/*
+ * 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-ot-shape-private.hh"
+
+#include "hb-buffer-private.hh"
+
+#include "hb-ot-layout.h"
+
+hb_tag_t default_features[] = {
+  /* GSUB */
+  HB_TAG('c','c','m','p'),
+  HB_TAG('l','o','c','l'),
+  HB_TAG('l','i','g','a'),
+  HB_TAG('c','l','i','g'),
+  /* GPOS */
+  HB_TAG('k','e','r','n'),
+  HB_TAG('m','a','r','k'),
+  HB_TAG('m','k','m','k'),
+};
+
+
+static void
+add_feature (hb_face_t    *face,
+	     hb_tag_t      table_tag,
+	     unsigned int  feature_index,
+	     unsigned int *lookups,
+	     unsigned int *num_lookups,
+	     unsigned int  room_lookups)
+{
+  unsigned int i = room_lookups - *num_lookups;
+  hb_ot_layout_feature_get_lookup_indexes (face, table_tag, feature_index, 0,
+					   &i,
+					   lookups + *num_lookups);
+  *num_lookups += i;
+}
+
+static int
+cmp_lookups (const void *p1, const void *p2)
+{
+  unsigned int a = * (const unsigned int *) p1;
+  unsigned int b = * (const unsigned int *) p2;
+
+  return a - b;
+}
+
+static void
+setup_lookups (hb_face_t    *face,
+	       hb_buffer_t  *buffer,
+	       hb_feature_t *features,
+	       unsigned int  num_features,
+	       hb_tag_t      table_tag,
+	       unsigned int *lookups,
+	       unsigned int *num_lookups)
+{
+  unsigned int i, j, script_index, language_index, feature_index, room_lookups;
+
+  room_lookups = *num_lookups;
+  *num_lookups = 0;
+
+  hb_ot_layout_table_choose_script (face, table_tag,
+				    hb_ot_tags_from_script (buffer->script),
+				    &script_index);
+  hb_ot_layout_script_find_language (face, table_tag, script_index,
+				     hb_ot_tag_from_language (buffer->language),
+				     &language_index);
+
+  if (hb_ot_layout_language_get_required_feature_index (face, table_tag, script_index, language_index,
+							&feature_index))
+    add_feature (face, table_tag, feature_index, lookups, num_lookups, room_lookups);
+
+  for (i = 0; i < ARRAY_LENGTH (default_features); i++)
+  {
+    if (hb_ot_layout_language_find_feature (face, table_tag, script_index, language_index,
+					    default_features[i],
+					    &feature_index))
+      add_feature (face, table_tag, feature_index, lookups, num_lookups, room_lookups);
+  }
+
+  qsort (lookups, *num_lookups, sizeof (lookups[0]), cmp_lookups);
+
+  if (*num_lookups)
+  {
+    for (i = 1, j = 0; i < *num_lookups; i++)
+      if (lookups[i] != lookups[j])
+	lookups[++j] = lookups[i];
+    lookups[j++] = lookups[i - 1];
+    *num_lookups = j;
+  }
+}
+
+
+hb_bool_t
+_hb_ot_substitute_complex (hb_font_t    *font HB_UNUSED,
+			   hb_face_t    *face,
+			   hb_buffer_t  *buffer,
+			   hb_feature_t *features,
+			   unsigned int  num_features)
+{
+  unsigned int lookups[1000];
+  unsigned int num_lookups = ARRAY_LENGTH (lookups);
+  unsigned int i;
+
+  if (!hb_ot_layout_has_substitution (face))
+    return FALSE;
+
+  setup_lookups (face, buffer, features, num_features,
+		 HB_OT_TAG_GSUB,
+		 lookups, &num_lookups);
+
+  for (i = 0; i < num_lookups; i++)
+    hb_ot_layout_substitute_lookup (face, buffer, lookups[i], 0xFFFF);
+
+  return TRUE;
+}
+
+hb_bool_t
+_hb_ot_position_complex (hb_font_t    *font,
+			 hb_face_t    *face,
+			 hb_buffer_t  *buffer,
+			 hb_feature_t *features,
+			 unsigned int  num_features)
+{
+  unsigned int lookups[1000];
+  unsigned int num_lookups = ARRAY_LENGTH (lookups);
+  unsigned int i;
+
+  if (!hb_ot_layout_has_positioning (face))
+    return FALSE;
+
+  setup_lookups (face, buffer, features, num_features,
+		 HB_OT_TAG_GPOS,
+		 lookups, &num_lookups);
+
+  for (i = 0; i < num_lookups; i++)
+    hb_ot_layout_position_lookup (font, face, buffer, lookups[i], 0xFFFF);
+
+  hb_ot_layout_position_finish (font, face, buffer);
+
+  return TRUE;
+}
diff --git a/src/hb-shape.c b/src/hb-shape.c
deleted file mode 100644
index 6818891..0000000
--- a/src/hb-shape.c
+++ /dev/null
@@ -1,258 +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-shape.h"
-
-#include "hb-buffer-private.h"
-
-#include "hb-ot-shape-private.h"
-
-
-/* Prepare */
-
-static inline hb_bool_t
-is_variation_selector (hb_codepoint_t unicode)
-{
-  return unlikely ((unicode >=  0x180B && unicode <=  0x180D) || /* MONGOLIAN FREE VARIATION SELECTOR ONE..THREE */
-		   (unicode >=  0xFE00 && unicode <=  0xFE0F) || /* VARIATION SELECTOR-1..16 */
-		   (unicode >= 0xE0100 && unicode <= 0xE01EF));  /* VARIATION SELECTOR-17..256 */
-}
-
-static void
-hb_form_clusters (hb_buffer_t *buffer)
-{
-  unsigned int count;
-
-  count = buffer->in_length;
-  for (buffer->in_pos = 1; buffer->in_pos < count; buffer->in_pos++)
-    if (buffer->unicode->get_general_category (IN_CURGLYPH()) == HB_CATEGORY_NON_SPACING_MARK)
-      IN_CLUSTER (buffer->in_pos) = IN_CLUSTER (buffer->in_pos - 1);
-}
-
-static hb_direction_t
-hb_ensure_native_direction (hb_buffer_t *buffer)
-{
-  hb_direction_t original_direction = buffer->direction;
-
-  /* TODO vertical */
-  if (HB_DIRECTION_IS_HORIZONTAL (original_direction) &&
-      original_direction != _hb_script_get_horizontal_direction (buffer->script))
-  {
-    hb_buffer_reverse_clusters (buffer);
-    buffer->direction ^=  1;
-  }
-
-  return original_direction;
-}
-
-
-/* Substitute */
-
-static void
-hb_mirror_chars (hb_buffer_t *buffer)
-{
-  unsigned int count;
-  hb_unicode_get_mirroring_func_t get_mirroring = buffer->unicode->get_mirroring;
-
-  if (HB_DIRECTION_IS_FORWARD (buffer->direction))
-    return;
-
-  count = buffer->in_length;
-  for (buffer->in_pos = 0; buffer->in_pos < count; buffer->in_pos++) {
-      IN_CURGLYPH() = get_mirroring (IN_CURGLYPH());
-  }
-}
-
-static void
-hb_map_glyphs (hb_font_t    *font,
-	       hb_face_t    *face,
-	       hb_buffer_t  *buffer)
-{
-  unsigned int count;
-
-  if (unlikely (!buffer->in_length))
-    return;
-  count = buffer->in_length - 1;
-  for (buffer->in_pos = 0; buffer->in_pos < count; buffer->in_pos++) {
-    if (unlikely (is_variation_selector (IN_NEXTGLYPH()))) {
-      IN_CURGLYPH() = hb_font_get_glyph (font, face, IN_CURGLYPH(), IN_NEXTGLYPH());
-      buffer->in_pos++;
-    } else {
-      IN_CURGLYPH() = hb_font_get_glyph (font, face, IN_CURGLYPH(), 0);
-    }
-  }
-  IN_CURGLYPH() = hb_font_get_glyph (font, face, IN_CURGLYPH(), 0);
-}
-
-static void
-hb_substitute_default (hb_font_t    *font,
-		       hb_face_t    *face,
-		       hb_buffer_t  *buffer,
-		       hb_feature_t *features HB_UNUSED,
-		       unsigned int  num_features HB_UNUSED)
-{
-  hb_mirror_chars (buffer);
-  hb_map_glyphs (font, face, buffer);
-}
-
-static hb_bool_t
-hb_substitute_complex (hb_font_t    *font,
-		       hb_face_t    *face,
-		       hb_buffer_t  *buffer,
-		       hb_feature_t *features,
-		       unsigned int  num_features)
-{
-  return _hb_ot_substitute_complex (font, face, buffer, features, num_features);
-}
-
-static void
-hb_substitute_fallback (hb_font_t    *font HB_UNUSED,
-			hb_face_t    *face HB_UNUSED,
-			hb_buffer_t  *buffer HB_UNUSED,
-			hb_feature_t *features HB_UNUSED,
-			unsigned int  num_features HB_UNUSED)
-{
-  /* TODO Arabic */
-}
-
-
-/* Position */
-
-static void
-hb_position_default (hb_font_t    *font,
-		     hb_face_t    *face,
-		     hb_buffer_t  *buffer,
-		     hb_feature_t *features HB_UNUSED,
-		     unsigned int  num_features HB_UNUSED)
-{
-  unsigned int count;
-
-  hb_buffer_clear_positions (buffer);
-
-  count = buffer->in_length;
-  for (buffer->in_pos = 0; buffer->in_pos < count; buffer->in_pos++) {
-    hb_glyph_metrics_t metrics;
-    hb_font_get_glyph_metrics (font, face, IN_CURGLYPH(), &metrics);
-    CURPOSITION()->x_advance = metrics.x_advance;
-    CURPOSITION()->y_advance = metrics.y_advance;
-  }
-}
-
-static hb_bool_t
-hb_position_complex (hb_font_t    *font,
-		     hb_face_t    *face,
-		     hb_buffer_t  *buffer,
-		     hb_feature_t *features,
-		     unsigned int  num_features)
-{
-  return _hb_ot_position_complex (font, face, buffer, features, num_features);
-}
-
-static void
-hb_position_fallback (hb_font_t    *font HB_UNUSED,
-		      hb_face_t    *face HB_UNUSED,
-		      hb_buffer_t  *buffer HB_UNUSED,
-		      hb_feature_t *features HB_UNUSED,
-		      unsigned int  num_features HB_UNUSED)
-{
-  /* TODO Mark pos */
-}
-
-static void
-hb_truetype_kern (hb_font_t    *font,
-		  hb_face_t    *face,
-		  hb_buffer_t  *buffer,
-		  hb_feature_t *features HB_UNUSED,
-		  unsigned int  num_features HB_UNUSED)
-{
-  unsigned int count;
-
-  /* TODO Check for kern=0 */
-  count = buffer->in_length;
-  for (buffer->in_pos = 1; buffer->in_pos < count; buffer->in_pos++) {
-    hb_position_t kern, kern1, kern2;
-    kern = hb_font_get_kerning (font, face, IN_GLYPH(buffer->in_pos - 1), IN_CURGLYPH());
-    kern1 = kern >> 1;
-    kern2 = kern - kern1;
-    POSITION(buffer->in_pos - 1)->x_advance += kern1;
-    CURPOSITION()->x_advance += kern2;
-    CURPOSITION()->x_offset += kern2;
-  }
-}
-
-static void
-hb_position_fallback_visual (hb_font_t    *font,
-			     hb_face_t    *face,
-			     hb_buffer_t  *buffer,
-			     hb_feature_t *features,
-			     unsigned int  num_features)
-{
-  hb_truetype_kern (font, face, buffer, features, num_features);
-}
-
-
-/* Shape */
-
-void
-hb_shape (hb_font_t    *font,
-	  hb_face_t    *face,
-	  hb_buffer_t  *buffer,
-	  hb_feature_t *features,
-	  unsigned int  num_features)
-{
-  hb_direction_t original_direction;
-  hb_bool_t substitute_fallback, position_fallback;
-
-  hb_form_clusters (buffer);
-
-  hb_substitute_default (font, face, buffer, features, num_features);
-
-  /* We do this after substitute_default because mirroring needs to
-   * see the original direction. */
-  original_direction = hb_ensure_native_direction (buffer);
-
-  substitute_fallback = !hb_substitute_complex (font, face, buffer, features, num_features);
-
-  if (substitute_fallback)
-    hb_substitute_fallback (font, face, buffer, features, num_features);
-
-  hb_position_default (font, face, buffer, features, num_features);
-
-  position_fallback = !hb_position_complex (font, face, buffer, features, num_features);
-
-  if (position_fallback)
-    hb_position_fallback (font, face, buffer, features, num_features);
-
-  if (HB_DIRECTION_IS_BACKWARD (buffer->direction))
-    hb_buffer_reverse (buffer);
-
-  if (position_fallback)
-    hb_position_fallback_visual (font, face, buffer, features, num_features);
-
-  buffer->direction = original_direction;
-}
diff --git a/src/hb-shape.cc b/src/hb-shape.cc
new file mode 100644
index 0000000..ef10375
--- /dev/null
+++ b/src/hb-shape.cc
@@ -0,0 +1,258 @@
+/*
+ * 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-shape.h"
+
+#include "hb-buffer-private.hh"
+
+#include "hb-ot-shape-private.hh"
+
+
+/* Prepare */
+
+static inline hb_bool_t
+is_variation_selector (hb_codepoint_t unicode)
+{
+  return unlikely ((unicode >=  0x180B && unicode <=  0x180D) || /* MONGOLIAN FREE VARIATION SELECTOR ONE..THREE */
+		   (unicode >=  0xFE00 && unicode <=  0xFE0F) || /* VARIATION SELECTOR-1..16 */
+		   (unicode >= 0xE0100 && unicode <= 0xE01EF));  /* VARIATION SELECTOR-17..256 */
+}
+
+static void
+hb_form_clusters (hb_buffer_t *buffer)
+{
+  unsigned int count;
+
+  count = buffer->in_length;
+  for (buffer->in_pos = 1; buffer->in_pos < count; buffer->in_pos++)
+    if (buffer->unicode->get_general_category (IN_CURGLYPH()) == HB_CATEGORY_NON_SPACING_MARK)
+      IN_CLUSTER (buffer->in_pos) = IN_CLUSTER (buffer->in_pos - 1);
+}
+
+static hb_direction_t
+hb_ensure_native_direction (hb_buffer_t *buffer)
+{
+  hb_direction_t original_direction = buffer->direction;
+
+  /* TODO vertical */
+  if (HB_DIRECTION_IS_HORIZONTAL (original_direction) &&
+      original_direction != _hb_script_get_horizontal_direction (buffer->script))
+  {
+    hb_buffer_reverse_clusters (buffer);
+    buffer->direction = HB_DIRECTION_REVERSE (buffer->direction);
+  }
+
+  return original_direction;
+}
+
+
+/* Substitute */
+
+static void
+hb_mirror_chars (hb_buffer_t *buffer)
+{
+  unsigned int count;
+  hb_unicode_get_mirroring_func_t get_mirroring = buffer->unicode->get_mirroring;
+
+  if (HB_DIRECTION_IS_FORWARD (buffer->direction))
+    return;
+
+  count = buffer->in_length;
+  for (buffer->in_pos = 0; buffer->in_pos < count; buffer->in_pos++) {
+      IN_CURGLYPH() = get_mirroring (IN_CURGLYPH());
+  }
+}
+
+static void
+hb_map_glyphs (hb_font_t    *font,
+	       hb_face_t    *face,
+	       hb_buffer_t  *buffer)
+{
+  unsigned int count;
+
+  if (unlikely (!buffer->in_length))
+    return;
+  count = buffer->in_length - 1;
+  for (buffer->in_pos = 0; buffer->in_pos < count; buffer->in_pos++) {
+    if (unlikely (is_variation_selector (IN_NEXTGLYPH()))) {
+      IN_CURGLYPH() = hb_font_get_glyph (font, face, IN_CURGLYPH(), IN_NEXTGLYPH());
+      buffer->in_pos++;
+    } else {
+      IN_CURGLYPH() = hb_font_get_glyph (font, face, IN_CURGLYPH(), 0);
+    }
+  }
+  IN_CURGLYPH() = hb_font_get_glyph (font, face, IN_CURGLYPH(), 0);
+}
+
+static void
+hb_substitute_default (hb_font_t    *font,
+		       hb_face_t    *face,
+		       hb_buffer_t  *buffer,
+		       hb_feature_t *features HB_UNUSED,
+		       unsigned int  num_features HB_UNUSED)
+{
+  hb_mirror_chars (buffer);
+  hb_map_glyphs (font, face, buffer);
+}
+
+static hb_bool_t
+hb_substitute_complex (hb_font_t    *font,
+		       hb_face_t    *face,
+		       hb_buffer_t  *buffer,
+		       hb_feature_t *features,
+		       unsigned int  num_features)
+{
+  return _hb_ot_substitute_complex (font, face, buffer, features, num_features);
+}
+
+static void
+hb_substitute_fallback (hb_font_t    *font HB_UNUSED,
+			hb_face_t    *face HB_UNUSED,
+			hb_buffer_t  *buffer HB_UNUSED,
+			hb_feature_t *features HB_UNUSED,
+			unsigned int  num_features HB_UNUSED)
+{
+  /* TODO Arabic */
+}
+
+
+/* Position */
+
+static void
+hb_position_default (hb_font_t    *font,
+		     hb_face_t    *face,
+		     hb_buffer_t  *buffer,
+		     hb_feature_t *features HB_UNUSED,
+		     unsigned int  num_features HB_UNUSED)
+{
+  unsigned int count;
+
+  hb_buffer_clear_positions (buffer);
+
+  count = buffer->in_length;
+  for (buffer->in_pos = 0; buffer->in_pos < count; buffer->in_pos++) {
+    hb_glyph_metrics_t metrics;
+    hb_font_get_glyph_metrics (font, face, IN_CURGLYPH(), &metrics);
+    CURPOSITION()->x_advance = metrics.x_advance;
+    CURPOSITION()->y_advance = metrics.y_advance;
+  }
+}
+
+static hb_bool_t
+hb_position_complex (hb_font_t    *font,
+		     hb_face_t    *face,
+		     hb_buffer_t  *buffer,
+		     hb_feature_t *features,
+		     unsigned int  num_features)
+{
+  return _hb_ot_position_complex (font, face, buffer, features, num_features);
+}
+
+static void
+hb_position_fallback (hb_font_t    *font HB_UNUSED,
+		      hb_face_t    *face HB_UNUSED,
+		      hb_buffer_t  *buffer HB_UNUSED,
+		      hb_feature_t *features HB_UNUSED,
+		      unsigned int  num_features HB_UNUSED)
+{
+  /* TODO Mark pos */
+}
+
+static void
+hb_truetype_kern (hb_font_t    *font,
+		  hb_face_t    *face,
+		  hb_buffer_t  *buffer,
+		  hb_feature_t *features HB_UNUSED,
+		  unsigned int  num_features HB_UNUSED)
+{
+  unsigned int count;
+
+  /* TODO Check for kern=0 */
+  count = buffer->in_length;
+  for (buffer->in_pos = 1; buffer->in_pos < count; buffer->in_pos++) {
+    hb_position_t kern, kern1, kern2;
+    kern = hb_font_get_kerning (font, face, IN_GLYPH(buffer->in_pos - 1), IN_CURGLYPH());
+    kern1 = kern >> 1;
+    kern2 = kern - kern1;
+    POSITION(buffer->in_pos - 1)->x_advance += kern1;
+    CURPOSITION()->x_advance += kern2;
+    CURPOSITION()->x_offset += kern2;
+  }
+}
+
+static void
+hb_position_fallback_visual (hb_font_t    *font,
+			     hb_face_t    *face,
+			     hb_buffer_t  *buffer,
+			     hb_feature_t *features,
+			     unsigned int  num_features)
+{
+  hb_truetype_kern (font, face, buffer, features, num_features);
+}
+
+
+/* Shape */
+
+void
+hb_shape (hb_font_t    *font,
+	  hb_face_t    *face,
+	  hb_buffer_t  *buffer,
+	  hb_feature_t *features,
+	  unsigned int  num_features)
+{
+  hb_direction_t original_direction;
+  hb_bool_t substitute_fallback, position_fallback;
+
+  hb_form_clusters (buffer);
+
+  hb_substitute_default (font, face, buffer, features, num_features);
+
+  /* We do this after substitute_default because mirroring needs to
+   * see the original direction. */
+  original_direction = hb_ensure_native_direction (buffer);
+
+  substitute_fallback = !hb_substitute_complex (font, face, buffer, features, num_features);
+
+  if (substitute_fallback)
+    hb_substitute_fallback (font, face, buffer, features, num_features);
+
+  hb_position_default (font, face, buffer, features, num_features);
+
+  position_fallback = !hb_position_complex (font, face, buffer, features, num_features);
+
+  if (position_fallback)
+    hb_position_fallback (font, face, buffer, features, num_features);
+
+  if (HB_DIRECTION_IS_BACKWARD (buffer->direction))
+    hb_buffer_reverse (buffer);
+
+  if (position_fallback)
+    hb_position_fallback_visual (font, face, buffer, features, num_features);
+
+  buffer->direction = original_direction;
+}
commit c3df649f258b334e93c7626a43cd8ebfbd5a610e
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue May 11 13:54:12 2010 -0400

    Fix comment

diff --git a/src/hb-buffer-private.h b/src/hb-buffer-private.h
index d4a1641..bc562ba 100644
--- a/src/hb-buffer-private.h
+++ b/src/hb-buffer-private.h
@@ -54,8 +54,7 @@ typedef struct _hb_internal_glyph_position_t {
   uint32_t       back : 16;		/* number of glyphs to go back
 					   for drawing current glyph */
   int32_t        cursive_chain : 16;	/* character to which this connects,
-					   may be positive or negative; used
-					   only internally */
+					   may be positive or negative */
 } hb_internal_glyph_position_t;
 
 ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_internal_glyph_info_t));



More information about the HarfBuzz mailing list