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

Behdad Esfahbod behdad at kemper.freedesktop.org
Wed Nov 7 00:12:37 PST 2007


 src/Makefile.am               |    8 
 src/harfbuzz-buffer-private.h |   93 ++++++
 src/harfbuzz-buffer.c         |  254 ++++++++++++++----
 src/harfbuzz-buffer.h         |   37 --
 src/harfbuzz-dump-main.c      |   45 ---
 src/harfbuzz-dump.c           |   15 -
 src/harfbuzz-external.h       |    2 
 src/harfbuzz-gdef-private.h   |   19 -
 src/harfbuzz-gdef.c           |   51 ++-
 src/harfbuzz-gdef.h           |    3 
 src/harfbuzz-global.c         |   79 -----
 src/harfbuzz-global.h         |  105 ++-----
 src/harfbuzz-gpos-private.h   |   22 +
 src/harfbuzz-gpos.c           |  399 +++++++++++------------------
 src/harfbuzz-gpos.h           |    1 
 src/harfbuzz-gsub-private.h   |   23 +
 src/harfbuzz-gsub.c           |  565 ++++++++++++++----------------------------
 src/harfbuzz-gsub.h           |    1 
 src/harfbuzz-impl.c           |   87 ++++++
 src/harfbuzz-impl.h           |   85 ++++--
 src/harfbuzz-open-private.h   |   53 ++-
 src/harfbuzz-open.c           |  201 ++++++++------
 src/harfbuzz-open.h           |    3 
 src/harfbuzz-shaper.cpp       |   13 
 src/harfbuzz-shaper.h         |   11 
 src/harfbuzz-stream-private.h |   68 +++++
 src/harfbuzz-stream.c         |   73 +++--
 src/harfbuzz-stream.h         |   36 --
 src/harfbuzz.c                |   10 
 src/harfbuzz.h                |    7 
 30 files changed, 1217 insertions(+), 1152 deletions(-)

New commits:
commit 84778393a6f360e8657fedc77231b4087960abb7
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Nov 7 03:11:11 2007 -0500

    Port changes from Pango

diff --git a/src/Makefile.am b/src/Makefile.am
index 01e1bd0..d46cc0e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,13 +3,13 @@
 noinst_LTLIBRARIES = libharfbuzz-1.la
 
 MAINSOURCES =  \
-	harfbuzz-global.c \
 	harfbuzz-buffer.c \
 	harfbuzz-stream.c \
 	harfbuzz-dump.c \
 	harfbuzz-gdef.c \
 	harfbuzz-gpos.c \
 	harfbuzz-gsub.c \
+	harfbuzz-impl.c \
 	harfbuzz-open.c \
 	harfbuzz-shaper.cpp \
 	harfbuzz-tibetan.c \
@@ -32,11 +32,13 @@ PUBLICHEADERS = \
 	harfbuzz-open.h \
 	harfbuzz-global.h \
 	harfbuzz-external.h \
-	harfbuzz-shaper.h
+	harfbuzz-shaper.h \
+	harfbuzz-stream.h
 
 PRIVATEHEADERS = \
 	harfbuzz-impl.h \
-	harfbuzz-stream.h \
+	harfbuzz-buffer-private.h \
+	harfbuzz-stream-private.h \
 	harfbuzz-gdef-private.h \
 	harfbuzz-gpos-private.h \
 	harfbuzz-gsub-private.h \
diff --git a/src/harfbuzz-buffer-private.h b/src/harfbuzz-buffer-private.h
new file mode 100644
index 0000000..3037e6b
--- /dev/null
+++ b/src/harfbuzz-buffer-private.h
@@ -0,0 +1,93 @@
+/* harfbuzz-buffer-private.h: Buffer of glyphs for substitution/positioning
+ *
+ * Copyright 2004,7 Red Hat Software
+ *
+ * Portions Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ */
+#ifndef HARFBUZZ_BUFFER_PRIVATE_H
+#define HARFBUZZ_BUFFER_PRIVATE_H
+
+#include "harfbuzz-impl.h"
+#include "harfbuzz-buffer.h"
+
+HB_BEGIN_HEADER
+
+#define HB_GLYPH_PROPERTIES_UNKNOWN 0xFFFF
+
+HB_INTERNAL void
+_hb_buffer_swap( HB_Buffer buffer );
+
+HB_INTERNAL void
+_hb_buffer_clear_output( HB_Buffer buffer );
+
+HB_INTERNAL HB_Error
+_hb_buffer_clear_positions( HB_Buffer buffer );
+
+HB_INTERNAL HB_Error
+_hb_buffer_add_output_glyphs( HB_Buffer  buffer,
+			      HB_UShort  num_in,
+			      HB_UShort  num_out,
+			      HB_UShort *glyph_data,
+			      HB_UShort  component,
+			      HB_UShort  ligID );
+
+HB_INTERNAL HB_Error
+_hb_buffer_add_output_glyph ( HB_Buffer buffer,
+			      HB_UInt   glyph_index,
+			      HB_UShort component,
+			      HB_UShort ligID );
+
+HB_INTERNAL HB_Error
+_hb_buffer_copy_output_glyph ( HB_Buffer buffer );
+
+HB_INTERNAL HB_Error
+_hb_buffer_replace_output_glyph ( HB_Buffer buffer,
+				  HB_UInt   glyph_index,
+				  HB_Bool   inplace );
+
+HB_INTERNAL HB_UShort
+_hb_buffer_allocate_ligid( HB_Buffer buffer );
+
+
+/* convenience macros */
+
+#define IN_GLYPH( pos )        (buffer->in_string[(pos)].gindex)
+#define IN_ITEM( pos )         (&buffer->in_string[(pos)])
+#define IN_CURGLYPH()          (buffer->in_string[buffer->in_pos].gindex)
+#define IN_CURITEM()           (&buffer->in_string[buffer->in_pos])
+#define IN_PROPERTIES( pos )   (buffer->in_string[(pos)].properties)
+#define IN_LIGID( pos )        (buffer->in_string[(pos)].ligID)
+#define IN_COMPONENT( pos )    (buffer->in_string[(pos)].component)
+#define POSITION( pos )        (&buffer->positions[(pos)])
+#define OUT_GLYPH( pos )       (buffer->out_string[(pos)].gindex)
+#define OUT_ITEM( pos )        (&buffer->out_string[(pos)])
+
+#define CHECK_Property( gdef, index, flags, property )					\
+          ( ( error = _HB_GDEF_Check_Property( (gdef), (index), (flags),		\
+                                      (property) ) ) != HB_Err_Ok )
+
+#define ADD_String( buffer, num_in, num_out, glyph_data, component, ligID )             \
+          ( ( error = _hb_buffer_add_output_glyphs( (buffer),                            \
+						    (num_in), (num_out),                \
+                                                    (glyph_data), (component), (ligID)  \
+                                                  ) ) != HB_Err_Ok )
+#define ADD_Glyph( buffer, glyph_index, component, ligID )				\
+          ( ( error = _hb_buffer_add_output_glyph( (buffer),                             \
+                                                    (glyph_index), (component), (ligID) \
+                                                  ) ) != HB_Err_Ok )
+#define REPLACE_Glyph( buffer, glyph_index, nesting_level )				\
+          ( ( error = _hb_buffer_replace_output_glyph( (buffer), (glyph_index),		\
+						      (nesting_level) == 1 ) ) != HB_Err_Ok )
+#define COPY_Glyph( buffer )								\
+	  ( (error = _hb_buffer_copy_output_glyph ( buffer ) ) != HB_Err_Ok )
+
+HB_END_HEADER
+
+#endif /* HARFBUZZ_BUFFER_PRIVATE_H */
diff --git a/src/harfbuzz-buffer.c b/src/harfbuzz-buffer.c
index 3eb7965..f995531 100644
--- a/src/harfbuzz-buffer.c
+++ b/src/harfbuzz-buffer.c
@@ -1,16 +1,45 @@
 /* harfbuzz-buffer.c: Buffer of glyphs for substitution/positioning
  *
- * Copyright 2004 Red Hat Software
+ * Copyright 2004,2007 Red Hat Software
  *
  * Portions Copyright 1996-2000 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  */
 
 #include "harfbuzz-impl.h"
-#include "harfbuzz-buffer.h"
+#include "harfbuzz-buffer-private.h"
 #include "harfbuzz-gsub-private.h"
 #include "harfbuzz-gpos-private.h"
 
+/* 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:
+ *
+ *   - copy_glyph() is called
+ *   - replace_glyph() is called with inplace=TRUE
+ *   - add_output_glyph() and add_output_glyphs() are not called
+ *
+ * In that case swap(), and copy_glyph(), and replace_glyph() are all
+ * mostly no-op.
+ *
+ * As soon an add_output_glyph[s]() or replace_glyph() with inplace=FALSE is
+ * called, out_string is moved over to an alternate buffer (alt_string), 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 alt_string.  alt_string is not allocated until its needed,
+ * but after that it's grown with in_string unconditionally.
+ *
+ * The buffer->separate_out boolean keeps status of whether out_string points
+ * to in_string (FALSE) or alt_string (TRUE).
+ */
+
+/* Internal API */
+
 static HB_Error
 hb_buffer_ensure( HB_Buffer buffer,
 		   HB_UInt   size )
@@ -24,86 +53,107 @@ hb_buffer_ensure( HB_Buffer buffer,
       while (size > new_allocated)
 	new_allocated += (new_allocated >> 1) + 8;
       
-      if ( REALLOC_ARRAY( buffer->in_string, buffer->allocated, new_allocated, HB_GlyphItemRec ) )
-	return error;
-      if ( REALLOC_ARRAY( buffer->out_string, buffer->allocated, new_allocated, HB_GlyphItemRec ) )
-	return error;
-      if ( REALLOC_ARRAY( buffer->positions, buffer->allocated, new_allocated, HB_PositionRec ) )
+      if ( buffer->positions )
+        {
+	  if ( REALLOC_ARRAY( buffer->positions, new_allocated, HB_PositionRec ) )
+	    return error;
+	}
+
+      if ( REALLOC_ARRAY( buffer->in_string, new_allocated, HB_GlyphItemRec ) )
 	return error;
 
+      if ( buffer->separate_out )
+        {
+	  if ( REALLOC_ARRAY( buffer->alt_string, new_allocated, HB_GlyphItemRec ) )
+	    return error;
+
+	  buffer->out_string = buffer->alt_string;
+	}
+      else
+        {
+	  buffer->out_string = buffer->in_string;
+
+	  if ( buffer->alt_string )
+	    {
+	      if ( REALLOC_ARRAY( buffer->alt_string, new_allocated, HB_GlyphItemRec ) )
+		return error;
+	    }
+	}
+
       buffer->allocated = new_allocated;
     }
 
   return HB_Err_Ok;
 }
 
-HB_Error
-hb_buffer_new(HB_Buffer *buffer )
+static HB_Error
+hb_buffer_duplicate_out_buffer( HB_Buffer buffer )
 {
-  HB_Error error;
-  
-  if ( ALLOC( *buffer, sizeof( HB_BufferRec ) ) )
-    return error;
+  if ( !buffer->alt_string )
+    {
+      HB_Error error;
 
-  (*buffer)->in_length = 0;
-  (*buffer)->out_length = 0;
-  (*buffer)->allocated = 0;
-  (*buffer)->in_pos = 0;
-  (*buffer)->out_pos = 0;
+      if ( ALLOC_ARRAY( buffer->alt_string, buffer->allocated, HB_GlyphItemRec ) )
+	return error;
+    }
 
-  (*buffer)->in_string = NULL;
-  (*buffer)->out_string = NULL;
-  (*buffer)->positions = NULL;
-  (*buffer)->max_ligID = 0;
+  buffer->out_string = buffer->alt_string;
+  memcpy( buffer->out_string, buffer->in_string, buffer->out_length * sizeof (buffer->out_string[0]) );
+  buffer->separate_out = TRUE;
 
   return HB_Err_Ok;
 }
 
+/* Public API */
+
 HB_Error
-hb_buffer_swap( HB_Buffer buffer )
+hb_buffer_new( HB_Buffer *pbuffer )
 {
-  HB_GlyphItem tmp_string;
+  HB_Buffer buffer;
+  HB_Error error;
 
-  tmp_string = buffer->in_string;
-  buffer->in_string = buffer->out_string;
-  buffer->out_string = tmp_string;
+  if ( ALLOC( buffer, sizeof( HB_BufferRec ) ) )
+    return error;
 
-  buffer->in_length = buffer->out_length;
-  buffer->out_length = 0;
-  
-  buffer->in_pos = 0;
-  buffer->out_pos = 0;
+  buffer->allocated = 0;
+  buffer->in_string = NULL;
+  buffer->alt_string = NULL;
+  buffer->positions = NULL;
+
+  hb_buffer_clear( buffer );
+
+  *pbuffer = buffer;
 
   return HB_Err_Ok;
 }
 
-HB_Error
+void
 hb_buffer_free( HB_Buffer buffer )
 {
   FREE( buffer->in_string );
-  FREE( buffer->out_string );
+  FREE( buffer->alt_string );
+  buffer->out_string = NULL;
   FREE( buffer->positions );
   FREE( buffer );
-
-  return HB_Err_Ok;
 }
 
-HB_Error
+void
 hb_buffer_clear( HB_Buffer buffer )
 {
   buffer->in_length = 0;
   buffer->out_length = 0;
   buffer->in_pos = 0;
   buffer->out_pos = 0;
-  
-  return HB_Err_Ok;
+  buffer->out_string = buffer->in_string;
+  buffer->separate_out = FALSE;
+  buffer->max_ligID = 0;
 }
 
 HB_Error
 hb_buffer_add_glyph( HB_Buffer buffer,
-		      HB_UInt    glyph_index,
-		      HB_UInt    properties,
-		      HB_UInt    cluster )
+		      HB_UInt   glyph_index,
+		      HB_UInt   properties,
+		      HB_UInt   cluster )
 {
   HB_Error error;
   HB_GlyphItem glyph;
@@ -125,6 +175,57 @@ hb_buffer_add_glyph( HB_Buffer buffer,
   return HB_Err_Ok;
 }
 
+/* HarfBuzz-Internal API */
+
+HB_INTERNAL void
+_hb_buffer_clear_output( HB_Buffer buffer )
+{
+  buffer->out_length = 0;
+  buffer->out_pos = 0;
+  buffer->out_string = buffer->in_string;
+  buffer->separate_out = FALSE;
+}
+
+HB_INTERNAL HB_Error
+_hb_buffer_clear_positions( HB_Buffer buffer )
+{
+  if ( !buffer->positions )
+    {
+      HB_Error error;
+
+      if ( ALLOC_ARRAY( buffer->positions, buffer->allocated, HB_PositionRec ) )
+	return error;
+    }
+
+  memset (buffer->positions, 0, sizeof (buffer->positions[0]) * buffer->in_length);
+
+  return HB_Err_Ok;
+}
+
+HB_INTERNAL void
+_hb_buffer_swap( HB_Buffer buffer )
+{
+  HB_GlyphItem tmp_string;
+  int tmp_length;
+  int tmp_pos;
+
+  if ( buffer->separate_out )
+    {
+      tmp_string = buffer->in_string;
+      buffer->in_string = buffer->out_string;
+      buffer->out_string = tmp_string;
+      buffer->alt_string = buffer->out_string;
+    }
+
+  tmp_length = buffer->in_length;
+  buffer->in_length = buffer->out_length;
+  buffer->out_length = tmp_length;
+
+  tmp_pos = buffer->in_pos;
+  buffer->in_pos = buffer->out_pos;
+  buffer->out_pos = tmp_pos;
+}
+
 /* 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.
@@ -144,8 +245,8 @@ hb_buffer_add_glyph( HB_Buffer buffer,
 
    The cluster value for the glyph at position buffer->in_pos is used
    for all replacement glyphs */
-HB_Error
-hb_buffer_add_output_glyphs( HB_Buffer buffer,
+HB_INTERNAL HB_Error
+_hb_buffer_add_output_glyphs( HB_Buffer  buffer,
 			      HB_UShort  num_in,
 			      HB_UShort  num_out,
 			      HB_UShort *glyph_data,
@@ -161,6 +262,13 @@ hb_buffer_add_output_glyphs( HB_Buffer buffer,
   if ( error )
     return error;
 
+  if ( !buffer->separate_out )
+    {
+      error = hb_buffer_duplicate_out_buffer( buffer );
+      if ( error )
+	return error;
+    }
+
   properties = buffer->in_string[buffer->in_pos].properties;
   cluster = buffer->in_string[buffer->in_pos].cluster;
   if ( component == 0xFFFF )
@@ -188,20 +296,20 @@ hb_buffer_add_output_glyphs( HB_Buffer buffer,
   return HB_Err_Ok;
 }
 
-HB_Error
-hb_buffer_add_output_glyph( HB_Buffer buffer,	
-			     HB_UInt    glyph_index,
-			     HB_UShort  component,
-			     HB_UShort  ligID )
+HB_INTERNAL HB_Error
+_hb_buffer_add_output_glyph( HB_Buffer buffer,
+			     HB_UInt   glyph_index,
+			     HB_UShort component,
+			     HB_UShort ligID )
 {
   HB_UShort glyph_data =  glyph_index;
 
-  return hb_buffer_add_output_glyphs ( buffer, 1, 1,
+  return _hb_buffer_add_output_glyphs ( buffer, 1, 1,
 					&glyph_data, component, ligID );
 }
 
-HB_Error
-hb_buffer_copy_output_glyph ( HB_Buffer buffer )
+HB_INTERNAL HB_Error
+_hb_buffer_copy_output_glyph ( HB_Buffer buffer )
 {  
   HB_Error  error;
 
@@ -209,14 +317,48 @@ hb_buffer_copy_output_glyph ( HB_Buffer buffer )
   if ( error )
     return error;
   
-  buffer->out_string[buffer->out_pos++] = buffer->in_string[buffer->in_pos++];
+  if ( buffer->separate_out )
+    {
+      buffer->out_string[buffer->out_pos] = buffer->in_string[buffer->in_pos];
+    }
+
+  buffer->in_pos++;
+  buffer->out_pos++;
   buffer->out_length = buffer->out_pos;
 
   return HB_Err_Ok;
 }
 
-HB_UShort
-hb_buffer_allocate_ligid( HB_Buffer buffer )
+HB_INTERNAL HB_Error
+_hb_buffer_replace_output_glyph( HB_Buffer buffer,
+				 HB_UInt   glyph_index,
+				 HB_Bool   inplace )
 {
-  return ++buffer->max_ligID;
+
+  HB_Error error;
+
+  if ( inplace )
+    {
+      error = _hb_buffer_copy_output_glyph ( buffer );
+      if ( error )
+	return error;
+
+      buffer->out_string[buffer->out_pos-1].gindex = glyph_index;
+    }
+  else
+    {
+      return _hb_buffer_add_output_glyph( buffer, glyph_index, 0xFFFF, 0xFFFF );
+    }
+
+  return HB_Err_Ok;
+}
+
+HB_INTERNAL HB_UShort
+_hb_buffer_allocate_ligid( HB_Buffer buffer )
+{
+  buffer->max_ligID++;
+  if (HB_UNLIKELY (buffer->max_ligID == 0))
+    buffer->max_ligID++;
+
+  return buffer->max_ligID;
 }
diff --git a/src/harfbuzz-buffer.h b/src/harfbuzz-buffer.h
index 8a57e54..6c32ead 100644
--- a/src/harfbuzz-buffer.h
+++ b/src/harfbuzz-buffer.h
@@ -1,6 +1,6 @@
 /* harfbuzz-buffer.h: Buffer of glyphs for substitution/positioning
  *
- * Copyrigh 2004 Red Hat Software
+ * Copyright 2004,7 Red Hat Software
  *
  * Portions Copyright 1996-2000 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
@@ -14,12 +14,10 @@
 #ifndef HARFBUZZ_BUFFER_H
 #define HARFBUZZ_BUFFER_H
 
-#include <harfbuzz-global.h>
+#include "harfbuzz-global.h"
 
 HB_BEGIN_HEADER
 
-#define HB_GLYPH_PROPERTIES_UNKNOWN 0xFFFF
-
 typedef struct HB_GlyphItemRec_ {
   HB_UInt     gindex;
   HB_UInt     properties;
@@ -54,22 +52,21 @@ typedef struct HB_BufferRec_{
   HB_UInt    in_pos;
   HB_UInt    out_pos;
   
+  HB_Bool       separate_out;
   HB_GlyphItem  in_string;
   HB_GlyphItem  out_string;
+  HB_GlyphItem  alt_string;
   HB_Position   positions;
   HB_UShort      max_ligID;
 } HB_BufferRec, *HB_Buffer;
 
 HB_Error
-hb_buffer_new(HB_Buffer *buffer );
-
-HB_Error
-hb_buffer_swap( HB_Buffer buffer );
+hb_buffer_new( HB_Buffer *buffer );
 
-HB_Error
+void
 hb_buffer_free( HB_Buffer buffer );
 
-HB_Error
+void
 hb_buffer_clear( HB_Buffer buffer );
 
 HB_Error
@@ -78,26 +75,6 @@ hb_buffer_add_glyph( HB_Buffer buffer,
 		      HB_UInt    properties,
 		      HB_UInt    cluster );
 
-HB_Error
-hb_buffer_add_output_glyphs( HB_Buffer buffer,
-			      HB_UShort  num_in,
-			      HB_UShort  num_out,
-			      HB_UShort *glyph_data,
-			      HB_UShort  component,
-			      HB_UShort  ligID );
-
-HB_Error
-hb_buffer_add_output_glyph ( HB_Buffer buffer,
-			      HB_UInt    glyph_index,
-			      HB_UShort  component,
-			      HB_UShort  ligID );
-
-HB_Error
-hb_buffer_copy_output_glyph ( HB_Buffer buffer );
-
-HB_UShort
-hb_buffer_allocate_ligid( HB_Buffer buffer );
-
 HB_END_HEADER
 
 #endif /* HARFBUZZ_BUFFER_H */
diff --git a/src/harfbuzz-dump-main.c b/src/harfbuzz-dump-main.c
index 6a320a8..5945c9d 100644
--- a/src/harfbuzz-dump-main.c
+++ b/src/harfbuzz-dump-main.c
@@ -21,8 +21,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "harfbuzz-open.h"
-
+#include "harfbuzz.h"
 #include "harfbuzz-dump.h"
 
 #define N_ELEMENTS(arr) (sizeof(arr)/ sizeof((arr)[0]))
@@ -82,44 +81,6 @@ maybe_add_feature (HB_GSUB  gsub,
 }
 
 static void
-select_cmap (FT_Face face)
-{
-  HB_UShort  i;
-  HB_CharMap cmap = NULL;
-  
-  for (i = 0; i < face->num_charmaps; i++)
-    {
-      if (face->charmaps[i]->platform_id == 3 && face->charmaps[i]->encoding_id == 1)
-	{
-	  cmap = face->charmaps[i];
-	  break;
-	}
-    }
-  
-  /* we try only pid/eid (0,0) if no (3,1) map is found -- many Windows
-     fonts have only rudimentary (0,0) support.                         */
-
-  if (!cmap)
-    for (i = 0; i < face->num_charmaps; i++)
-      {
-	if (face->charmaps[i]->platform_id == 3 && face->charmaps[i]->encoding_id == 1)
-	  {
-	    cmap = face->charmaps[i];
-	    break;
-	  }
-      }
-
-  if (cmap)
-    FT_Set_Charmap (face, cmap);
-  else
-    {
-      fprintf (stderr, "Sorry, but this font doesn't contain"
-	       " any Unicode mapping table.\n");
-      exit (1);
-    }
-}
-
-static void
 add_features (HB_GSUB gsub)
 {
   HB_Error error;
diff --git a/src/harfbuzz-dump.c b/src/harfbuzz-dump.c
index 9c214cc..ed365d8 100644
--- a/src/harfbuzz-dump.c
+++ b/src/harfbuzz-dump.c
@@ -452,7 +452,7 @@ static void
 Dump_Device (HB_Device *Device, FILE *stream, int indent, HB_Type hb_type)
 {
   int i;
-  int bits = 0;
+  int bits;
   int n_per;
   unsigned int mask;
 
@@ -472,6 +472,9 @@ Dump_Device (HB_Device *Device, FILE *stream, int indent, HB_Type hb_type)
     case 3:
       bits = 8;
       break;
+    default:
+      bits = 0;
+      break;
     }
 
   DUMP ("<DeltaValue>");
@@ -634,7 +637,7 @@ Dump_GPOS_Lookup_Markbase (HB_SubTable *subtable, FILE *stream, int indent, HB_T
 DEF_DUMP (Lookup)
 {
   int i;
-  const char *lookup_name = NULL;
+  const char *lookup_name;
   void (*lookup_func) (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type) = NULL;
 
   if (hb_type == HB_Type_GSUB)
@@ -663,6 +666,10 @@ DEF_DUMP (Lookup)
 	  lookup_name = "CHAIN";
 	  lookup_func = Dump_GSUB_Lookup_Chain;
 	  break;
+	default:
+	  lookup_name = "(unknown)";
+	  lookup_func = NULL;
+	  break;
 	}
     }
   else
@@ -696,6 +703,10 @@ DEF_DUMP (Lookup)
 	case HB_GPOS_LOOKUP_CHAIN:
 	  lookup_name = "CHAIN";
 	  break;
+	default:
+	  lookup_name = "(unknown)";
+	  lookup_func = NULL;
+	  break;
 	}
     }
 
diff --git a/src/harfbuzz-external.h b/src/harfbuzz-external.h
index cb76b0c..3469ed0 100644
--- a/src/harfbuzz-external.h
+++ b/src/harfbuzz-external.h
@@ -10,7 +10,7 @@
 #ifndef HARFBUZZ_EXTERNAL_H
 #define HARFBUZZ_EXTERNAL_H
 
-#include <harfbuzz-global.h>
+#include "harfbuzz-global.h"
 
 HB_BEGIN_HEADER
 
diff --git a/src/harfbuzz-gdef-private.h b/src/harfbuzz-gdef-private.h
index 174502a..2228d20 100644
--- a/src/harfbuzz-gdef-private.h
+++ b/src/harfbuzz-gdef-private.h
@@ -13,8 +13,10 @@
 #ifndef HARFBUZZ_GDEF_PRIVATE_H
 #define HARFBUZZ_GDEF_PRIVATE_H
 
+#include "harfbuzz-impl.h"
+#include "harfbuzz-stream-private.h"
+#include "harfbuzz-buffer-private.h"
 #include "harfbuzz-gdef.h"
-#include "harfbuzz-buffer.h"
 
 HB_BEGIN_HEADER
 
@@ -87,19 +89,22 @@ struct  HB_LigGlyph_
 };
 
 
-HB_Error  _HB_GDEF_Add_Glyph_Property( HB_GDEFHeader*   gdef,
+HB_INTERNAL HB_Error
+_HB_GDEF_Add_Glyph_Property( HB_GDEFHeader* gdef,
 				       HB_UShort        glyphID,
 				       HB_UShort        property );
 
-HB_Error  _HB_GDEF_Check_Property( HB_GDEFHeader*   gdef,
+HB_INTERNAL HB_Error
+_HB_GDEF_Check_Property( HB_GDEFHeader* gdef,
 				   HB_GlyphItem    item,
 				   HB_UShort        flags,
 				   HB_UShort*       property );
 
-HB_Error _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( HB_GDEFHeader* gdef,
-							   HB_Stream      stream,
-							   HB_Lookup*     lo,
-							   HB_UShort      num_lookups );
+HB_INTERNAL HB_Error
+_HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( HB_GDEFHeader* gdef,
+						  HB_Stream      stream,
+						  HB_Lookup*     lo,
+						  HB_UShort      num_lookups );
 
 HB_END_HEADER
 
diff --git a/src/harfbuzz-gdef.c b/src/harfbuzz-gdef.c
index edf1c33..56099e6 100644
--- a/src/harfbuzz-gdef.c
+++ b/src/harfbuzz-gdef.c
@@ -13,7 +13,6 @@
 #include "harfbuzz-impl.h"
 #include "harfbuzz-gdef-private.h"
 #include "harfbuzz-open-private.h"
-#include "harfbuzz-stream.h"
 
 static HB_Error  Load_AttachList( HB_AttachList*  al,
 				  HB_Stream        stream );
@@ -167,6 +166,9 @@ HB_Error  HB_Load_GDEF_Table( HB_Stream stream,
   if ( !retptr )
     return ERR(HB_Err_Invalid_Argument);
 
+  if ( GOTO_Table( TTAG_GDEF ) )
+    return error;
+
   if (( error = HB_New_GDEF_Table ( &gdef ) ))
     return error;
 
@@ -760,7 +762,7 @@ HB_Error  HB_GDEF_Get_Glyph_Property( HB_GDEFHeader*  gdef,
 				      HB_UShort        glyphID,
 				      HB_UShort*       property )
 {
-  HB_UShort class, index;
+  HB_UShort class = 0, index = 0; /* shut compiler up */
 
   HB_Error  error;
 
@@ -794,6 +796,7 @@ HB_Error  HB_GDEF_Get_Glyph_Property( HB_GDEFHeader*  gdef,
 
   switch ( class )
   {
+  default:
   case UNCLASSIFIED_GLYPH:
     *property = 0;
     break;
@@ -834,7 +837,6 @@ static HB_Error  Make_ClassRange( HB_ClassDefinition*  cd,
   cdf2 = &cd->cd.cd2;
 
   if ( REALLOC_ARRAY( cdf2->ClassRangeRecord,
-		      cdf2->ClassRangeCount,
 		      cdf2->ClassRangeCount + 1 ,
 		      HB_ClassRangeRecord ) )
     return error;
@@ -899,7 +901,7 @@ HB_Error  HB_GDEF_Build_ClassDefinition( HB_GDEFHeader*  gdef,
 
   glyph_count--;
 
-  for ( n = 0; n <= glyph_count; n++ )
+  for ( n = 0; n < glyph_count + 1; n++ )
   {
     if ( curr_glyph == glyph_array[n] && curr_class == class_array[n] )
     {
@@ -1055,12 +1057,13 @@ static void  Free_NewGlyphClasses( HB_GDEFHeader*  gdef )
 }
 
 
-HB_Error  _HB_GDEF_Add_Glyph_Property( HB_GDEFHeader*  gdef,
+HB_INTERNAL HB_Error
+_HB_GDEF_Add_Glyph_Property( HB_GDEFHeader* gdef,
 			      HB_UShort        glyphID,
 			      HB_UShort        property )
 {
   HB_Error               error;
-  HB_UShort              class, new_class, index;
+  HB_UShort              class, new_class, index = 0; /* shut compiler up */
   HB_UShort              byte, bits, mask;
   HB_UShort              array_index, glyph_index, count;
 
@@ -1140,7 +1143,8 @@ HB_Error  _HB_GDEF_Add_Glyph_Property( HB_GDEFHeader*  gdef,
 }
 
 
-HB_Error  _HB_GDEF_Check_Property( HB_GDEFHeader*  gdef,
+HB_INTERNAL HB_Error
+_HB_GDEF_Check_Property( HB_GDEFHeader* gdef,
 			  HB_GlyphItem    gitem,
 			  HB_UShort        flags,
 			  HB_UShort*       property )
@@ -1195,10 +1199,11 @@ HB_Error  _HB_GDEF_Check_Property( HB_GDEFHeader*  gdef,
   return HB_Err_Ok;
 }
 
-HB_Error _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( HB_GDEFHeader* gdef,
-							   HB_Stream      stream,
-							   HB_Lookup*     lo,
-							   HB_UShort      num_lookups)
+HB_INTERNAL HB_Error
+_HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( HB_GDEFHeader* gdef,
+						  HB_Stream      stream,
+						  HB_Lookup*     lo,
+						  HB_UShort      num_lookups)
 {
   HB_Error   error = HB_Err_Ok;
   HB_UShort  i;
diff --git a/src/harfbuzz-gdef.h b/src/harfbuzz-gdef.h
index d63f2df..1c1150b 100644
--- a/src/harfbuzz-gdef.h
+++ b/src/harfbuzz-gdef.h
@@ -99,7 +99,8 @@ typedef struct HB_GDEFHeader_*  HB_GDEF;
 HB_Error  HB_New_GDEF_Table( HB_GDEFHeader** retptr );
       
 
-HB_Error  HB_Load_GDEF_Table( HB_Stream stream, HB_GDEFHeader** gdef );
+HB_Error  HB_Load_GDEF_Table( HB_Stream       stream,
+			      HB_GDEFHeader** gdef );
 
 
 HB_Error  HB_Done_GDEF_Table ( HB_GDEFHeader* gdef );
diff --git a/src/harfbuzz-global.c b/src/harfbuzz-global.c
deleted file mode 100644
index 33d414d..0000000
--- a/src/harfbuzz-global.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*******************************************************************
- *
- *  Copyright 2005  David Turner, The FreeType Project (www.freetype.org)
- *  Copyright 2007  Trolltech ASA
- *
- *  This is part of HarfBuzz, an OpenType Layout engine library.
- *
- *  See the file name COPYING for licensing information.
- *
- ******************************************************************/
-#include "harfbuzz-global.h"
-#include "harfbuzz-impl.h"
-
-#if 0
-#include <stdio.h>
-#define  LOG(x)  _hb_log x
-
-static void
-_hb_log( const char*   format, ... )
-{
-  va_list  ap;
- 
-  va_start( ap, format );
-  vfprintf( stderr, format, ap );
-  va_end( ap );
-}
-
-#else
-#define  LOG(x)  do {} while (0)
-#endif
-
-
-HB_Pointer _hb_alloc(HB_UInt   size,
-                            HB_Error  *perror )
-{
-  HB_Error    error = 0;
-  HB_Pointer  block = NULL;
-
-  if ( size > 0 )
-  {
-    block = malloc( size );
-    if ( !block )
-      error = ERR(HB_Err_Out_Of_Memory);
-    else
-      memset( (char*)block, 0, (size_t)size );
-  }
-
-  *perror = error;
-  return block;
-}
-
-
-HB_Pointer _hb_realloc(HB_Pointer  block,
-                       HB_UInt    old_size,
-                       HB_UInt    new_size,
-                       HB_Error   *perror )
-{
-    HB_Pointer  block2 = NULL;
-    HB_Error    error  = 0;
-
-    block2 = realloc( block, new_size );
-    if ( block2 == NULL )
-        error = ERR(HB_Err_Out_Of_Memory);
-    else if ( new_size > old_size )
-        memset( (char*)block2 + old_size, 0, (size_t)(new_size - old_size) );
-
-    if ( !error )
-        block = block2;
-    
-    *perror = error;
-    return block;
-}
-
-
-void _hb_free( HB_Pointer  block )
-{
-  if ( block )
-    free( block );
-}
-
diff --git a/src/harfbuzz-global.h b/src/harfbuzz-global.h
index 156416f..f370a47 100644
--- a/src/harfbuzz-global.h
+++ b/src/harfbuzz-global.h
@@ -24,6 +24,20 @@
 
 HB_BEGIN_HEADER
 
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+
+#define HB_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
+          ( ( (HB_UInt)_x1 << 24 ) |     \
+            ( (HB_UInt)_x2 << 16 ) |     \
+            ( (HB_UInt)_x3 <<  8 ) |     \
+              (HB_UInt)_x4         )
+
 typedef char hb_int8;
 typedef unsigned char hb_uint8;
 typedef short hb_int16;
@@ -53,14 +67,6 @@ typedef hb_int32 HB_16Dot16; /* 16.16 */
 typedef void * HB_Pointer;
 typedef hb_uint32 HB_Tag;
 
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE (!FALSE)
-#endif
-
 typedef enum {
   /* no error */
   HB_Err_Ok                           = 0x0000,
@@ -90,56 +96,6 @@ typedef struct HB_Font_ *HB_Font;
 typedef struct HB_StreamRec_ *HB_Stream;
 typedef struct HB_FaceRec_ *HB_Face;
 
-#define HB_IsHighSurrogate(ucs) \
-    (((ucs) & 0xfc00) == 0xd800)
-
-#define HB_IsLowSurrogate(ucs) \
-    (((ucs) & 0xfc00) == 0xdc00)
-
-#define HB_SurrogateToUcs4(high, low) \
-    (((HB_UChar32)(high))<<10) + (low) - 0x35fdc00;
-
-#define HB_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
-          ( ( (HB_UInt)_x1 << 24 ) |     \
-            ( (HB_UInt)_x2 << 16 ) |     \
-            ( (HB_UInt)_x3 <<  8 ) |     \
-              (HB_UInt)_x4         )
-
-/* memory macros used by the OpenType parser */
-#define  ALLOC(_ptr,_size)   \
-           ( (_ptr) = _hb_alloc( _size, &error ), error != 0 )
-
-#define  REALLOC(_ptr,_oldsz,_newsz)  \
-           ( (_ptr) = _hb_realloc( (_ptr), (_oldsz), (_newsz), &error ), error != 0 )
-
-#define  FREE(_ptr)                    \
-  do {                                 \
-    if ( (_ptr) )                      \
-    {                                  \
-      _hb_free( _ptr );     \
-      _ptr = NULL;                     \
-    }                                  \
-  } while (0)
-
-#define  ALLOC_ARRAY(_ptr,_count,_type)   \
-           ALLOC(_ptr,(_count)*sizeof(_type))
-
-#define  REALLOC_ARRAY(_ptr,_oldcnt,_newcnt,_type) \
-           REALLOC(_ptr,(_oldcnt)*sizeof(_type),(_newcnt)*sizeof(_type))
-
-#define  MEM_Copy(dest,source,count)   memcpy( (char*)(dest), (const char*)(source), (size_t)(count) )
-
-
-HB_Pointer _hb_alloc( HB_UInt   size,
-                      HB_Error  *perror_ );
-
-HB_Pointer _hb_realloc( HB_Pointer  block,
-                        HB_UInt    old_size,
-                        HB_UInt    new_size,
-                        HB_Error   *perror_ );
-
-void _hb_free( HB_Pointer  block );
-
 HB_END_HEADER
 
 #endif
diff --git a/src/harfbuzz-gpos-private.h b/src/harfbuzz-gpos-private.h
index 5e614c9..72a6c20 100644
--- a/src/harfbuzz-gpos-private.h
+++ b/src/harfbuzz-gpos-private.h
@@ -13,7 +13,8 @@
 #ifndef HARFBUZZ_GPOS_PRIVATE_H
 #define HARFBUZZ_GPOS_PRIVATE_H
 
-#include "harfbuzz-stream.h"
+#include "harfbuzz-impl.h"
+#include "harfbuzz-stream-private.h"
 #include "harfbuzz-gpos.h"
 
 HB_BEGIN_HEADER
@@ -655,6 +656,19 @@ struct  HB_ChainContextPos_
 typedef struct HB_ChainContextPos_  HB_ChainContextPos;
 
 
+#if 0
+/* LookupType 10 */
+struct HB_ExtensionPos_
+{
+  HB_UShort      PosFormat;           /* always 1 */
+  HB_UShort      LookuptType;         /* lookup-type of referenced subtable */
+  HB_GPOS_SubTable *subtable;         /* referenced subtable */
+};
+
+typedef struct HB_ExtensionPos_  HB_ExtensionPos;
+#endif
+
+
 union  HB_GPOS_SubTable_
 {
   HB_SinglePos        single;
@@ -671,11 +685,13 @@ typedef union HB_GPOS_SubTable_  HB_GPOS_SubTable;
 
 
 
-HB_Error  _HB_GPOS_Load_SubTable( HB_GPOS_SubTable*  st,
+HB_INTERNAL HB_Error
+_HB_GPOS_Load_SubTable( HB_GPOS_SubTable* st,
 				  HB_Stream     stream,
 				  HB_UShort     lookup_type );
 
-void  _HB_GPOS_Free_SubTable( HB_GPOS_SubTable*  st,
+HB_INTERNAL void
+_HB_GPOS_Free_SubTable( HB_GPOS_SubTable* st,
 			      HB_UShort     lookup_type );
 
 HB_END_HEADER
diff --git a/src/harfbuzz-gpos.c b/src/harfbuzz-gpos.c
index 1479f9e..dc7549b 100644
--- a/src/harfbuzz-gpos.c
+++ b/src/harfbuzz-gpos.c
@@ -4,6 +4,7 @@
  *  David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  *  Copyright 2006  Behdad Esfahbod
+ *  Copyright 2007  Red Hat Software
  *
  *  This is part of HarfBuzz, an OpenType Layout engine library.
  *
@@ -53,7 +54,7 @@ static HB_Error  default_mmfunc( HB_Font      font,
   HB_UNUSED(metric_id);
   HB_UNUSED(metric_value);
   HB_UNUSED(data);
-  return ERR(HB_Err_Not_Covered);
+  return ERR(HB_Err_Not_Covered); /* ERR() call intended */
 }
 
 
@@ -70,9 +71,11 @@ HB_Error  HB_Load_GPOS_Table( HB_Stream stream,
   HB_Error   error;
 
 
-  if ( !retptr || !stream )
+  if ( !retptr )
     return ERR(HB_Err_Invalid_Argument);
 
+  if ( GOTO_Table( TTAG_GPOS ) )
+    return error;
 
   base_offset = FILE_Pos();
 
@@ -127,15 +130,6 @@ HB_Error  HB_Load_GPOS_Table( HB_Stream stream,
 
   gpos->gdef = gdef;      /* can be NULL */
 
-  /* We now check the LookupFlags for values larger than 0xFF to find
-     out whether we need to load the `MarkAttachClassDef' field of the
-     GDEF table -- this hack is necessary for OpenType 1.2 tables since
-     the version field of the GDEF table hasn't been incremented.
-
-     For constructed GDEF tables, we only load it if
-     `MarkAttachClassDef_offset' is not zero (nevertheless, a build of
-     a constructed mark attach table is not supported currently).       */
-
   if ( ( error =  _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( gdef, gdefStream,
 								     gpos->LookupList.Lookup,
 								     gpos->LookupList.LookupCount ) ) )
@@ -550,6 +544,7 @@ static HB_Error  Load_Anchor( HB_Anchor*  an,
 			      HB_Stream    stream )
 {
   HB_Error  error;
+
   HB_UInt cur_offset, new_offset, base_offset;
 
 
@@ -698,6 +693,7 @@ static HB_Error  Get_Anchor( GPOS_Instance*   gpi,
   {
   case 0:
     /* The special case of an empty AnchorTable */
+  default:
 
     return HB_Err_Not_Covered;
 
@@ -955,27 +951,13 @@ static void  Free_SinglePos( HB_GPOS_SubTable* st )
       FREE( v );
     }
     break;
+  default:
+    break;
   }
 
   _HB_OPEN_Free_Coverage( &sp->Coverage );
 }
 
-static HB_Error  Lookup_DefaultPos(  GPOS_Instance*    gpi,
-				     HB_GPOS_SubTable* st,
-				     HB_Buffer        buffer,
-				     HB_UShort         flags,
-				     HB_UShort         context_length,
-				     int               nesting_level )
-{
-  HB_UNUSED(gpi);
-  HB_UNUSED(st);
-  HB_UNUSED(buffer);
-  HB_UNUSED(flags);
-  HB_UNUSED(context_length);
-  HB_UNUSED(nesting_level);
-  return HB_Err_Not_Covered;
-}
-
 static HB_Error  Lookup_SinglePos( GPOS_Instance*    gpi,
 				   HB_GPOS_SubTable* st,
 				   HB_Buffer        buffer,
@@ -1449,6 +1431,9 @@ static void  Free_PairPos( HB_GPOS_SubTable* st )
   case 2:
     Free_PairPos2( &pp->ppf.ppf2, format1, format2 );
     break;
+
+  default:
+    break;
   }
 
   _HB_OPEN_Free_Coverage( &pp->Coverage );
@@ -1505,7 +1490,7 @@ static HB_Error  Lookup_PairPos2( GPOS_Instance*       gpi,
 				  HB_UShort            format2 )
 {
   HB_Error           error;
-  HB_UShort          cl1, cl2;
+  HB_UShort          cl1 = 0, cl2 = 0; /* shut compiler up */
 
   HB_Class1Record*  c1r;
   HB_Class2Record*  c2r;
@@ -2027,7 +2012,10 @@ static HB_Error  Load_BaseArray( HB_BaseArray*  ba,
       FORGET_Frame();
 
       if (new_offset == base_offset) {
-	/* Doulos SIL Regular is buggy and has zer offsets here.  Skip */
+	/* XXX
+	 * Doulos SIL Regular is buggy and has zero offsets here.
+	 * Skip it
+	 */
 	ban[n].PosFormat = 0;
 	continue;
       }
@@ -3784,17 +3772,10 @@ static void  Free_ContextPos( HB_GPOS_SubTable* st )
 
   switch ( cp->PosFormat )
   {
-  case 1:
-    Free_ContextPos1( &cp->cpf.cpf1 );
-    break;
-
-  case 2:
-    Free_ContextPos2( &cp->cpf.cpf2 );
-    break;
-
-  case 3:
-    Free_ContextPos3( &cp->cpf.cpf3 );
-    break;
+  case 1:  Free_ContextPos1( &cp->cpf.cpf1 ); break;
+  case 2:  Free_ContextPos2( &cp->cpf.cpf2 ); break;
+  case 3:  Free_ContextPos3( &cp->cpf.cpf3 ); break;
+  default:					      break;
   }
 }
 
@@ -5017,17 +4998,10 @@ static void  Free_ChainContextPos( HB_GPOS_SubTable* st )
 
   switch ( ccp->PosFormat )
   {
-  case 1:
-    Free_ChainContextPos1( &ccp->ccpf.ccpf1 );
-    break;
-
-  case 2:
-    Free_ChainContextPos2( &ccp->ccpf.ccpf2 );
-    break;
-
-  case 3:
-    Free_ChainContextPos3( &ccp->ccpf.ccpf3 );
-    break;
+  case 1:  Free_ChainContextPos1( &ccp->ccpf.ccpf1 ); break;
+  case 2:  Free_ChainContextPos2( &ccp->ccpf.ccpf2 ); break;
+  case 3:  Free_ChainContextPos3( &ccp->ccpf.ccpf3 ); break;
+  default:						      break;
   }
 }
 
@@ -5795,25 +5769,6 @@ HB_Error  HB_GPOS_Query_Features( HB_GPOSHeader*  gpos,
 }
 
 
-typedef HB_Error  (*Lookup_Pos_Func_Type)  ( GPOS_Instance*    gpi,
-					     HB_GPOS_SubTable* st,
-					     HB_Buffer        buffer,
-					     HB_UShort         flags,
-					     HB_UShort         context_length,
-					     int               nesting_level );
-static const Lookup_Pos_Func_Type Lookup_Pos_Call_Table[] = {
-  Lookup_DefaultPos,
-  Lookup_SinglePos,		/* HB_GPOS_LOOKUP_SINGLE     1 */
-  Lookup_PairPos,		/* HB_GPOS_LOOKUP_PAIR       2 */
-  Lookup_CursivePos,		/* HB_GPOS_LOOKUP_CURSIVE    3 */
-  Lookup_MarkBasePos,		/* HB_GPOS_LOOKUP_MARKBASE   4 */
-  Lookup_MarkLigPos,		/* HB_GPOS_LOOKUP_MARKLIG    5 */
-  Lookup_MarkMarkPos,		/* HB_GPOS_LOOKUP_MARKMARK   6 */
-  Lookup_ContextPos,		/* HB_GPOS_LOOKUP_CONTEXT    7 */
-  Lookup_ChainContextPos,	/* HB_GPOS_LOOKUP_CHAIN      8 */
-  Lookup_DefaultPos,		/* HB_GPOS_LOOKUP_EXTENSION  9 */
-};
-
 /* Do an individual subtable lookup.  Returns HB_Err_Ok if positioning
    has been done, or HB_Err_Not_Covered if not.                        */
 static HB_Error  GPOS_Do_Glyph_Lookup( GPOS_Instance*    gpi,
@@ -5827,13 +5782,12 @@ static HB_Error  GPOS_Do_Glyph_Lookup( GPOS_Instance*    gpi,
   HB_GPOSHeader*       gpos = gpi->gpos;
   HB_Lookup*           lo;
   int		       lookup_type;
-  Lookup_Pos_Func_Type Func;
 
 
   nesting_level++;
 
   if ( nesting_level > HB_MAX_NESTING_LEVEL )
-    return ERR(HB_Err_Not_Covered);
+    return ERR(HB_Err_Not_Covered); /* ERR() call intended */
 
   lookup_count = gpos->LookupList.LookupCount;
   if (lookup_index >= lookup_count)
@@ -5842,21 +5796,36 @@ static HB_Error  GPOS_Do_Glyph_Lookup( GPOS_Instance*    gpi,
   lo    = &gpos->LookupList.Lookup[lookup_index];
   flags = lo->LookupFlag;
   lookup_type = lo->LookupType;
-  if (lookup_type >= ARRAY_LEN (Lookup_Pos_Call_Table))
-    lookup_type = 0;
-  Func = Lookup_Pos_Call_Table[lookup_type];
 
   for ( i = 0; i < lo->SubTableCount; i++ )
   {
-    error = Func ( gpi,
-		   &lo->SubTable[i].st.gpos,
-		   buffer,
-		   flags, context_length,
-		   nesting_level );
+    HB_GPOS_SubTable *st = &lo->SubTable[i].st.gpos;
+
+    switch (lookup_type) {
+      case HB_GPOS_LOOKUP_SINGLE:
+        error = Lookup_SinglePos	( gpi, st, buffer, flags, context_length, nesting_level ); break;
+      case HB_GPOS_LOOKUP_PAIR:
+	error = Lookup_PairPos		( gpi, st, buffer, flags, context_length, nesting_level ); break;
+      case HB_GPOS_LOOKUP_CURSIVE:
+	error = Lookup_CursivePos	( gpi, st, buffer, flags, context_length, nesting_level ); break;
+      case HB_GPOS_LOOKUP_MARKBASE:
+	error = Lookup_MarkBasePos	( gpi, st, buffer, flags, context_length, nesting_level ); break;
+      case HB_GPOS_LOOKUP_MARKLIG:
+	error = Lookup_MarkLigPos	( gpi, st, buffer, flags, context_length, nesting_level ); break;
+      case HB_GPOS_LOOKUP_MARKMARK:
+	error = Lookup_MarkMarkPos	( gpi, st, buffer, flags, context_length, nesting_level ); break;
+      case HB_GPOS_LOOKUP_CONTEXT:
+	error = Lookup_ContextPos	( gpi, st, buffer, flags, context_length, nesting_level ); break;
+      case HB_GPOS_LOOKUP_CHAIN:
+	error = Lookup_ChainContextPos	( gpi, st, buffer, flags, context_length, nesting_level ); break;
+    /*case HB_GPOS_LOOKUP_EXTENSION:
+	error = Lookup_ExtensionPos	( gpi, st, buffer, flags, context_length, nesting_level ); break;*/
+      default:
+	error = HB_Err_Not_Covered;
+    }
 
     /* Check whether we have a successful positioning or an error other
        than HB_Err_Not_Covered                                         */
-
     if ( error != HB_Err_Not_Covered )
       return error;
   }
@@ -5865,78 +5834,45 @@ static HB_Error  GPOS_Do_Glyph_Lookup( GPOS_Instance*    gpi,
 }
 
 
-static HB_Error  Load_DefaultPos( HB_GPOS_SubTable* st,
-				  HB_Stream         stream )
-{
-  HB_UNUSED(st);
-  HB_UNUSED(stream);
-  return ERR(HB_Err_Invalid_SubTable_Format);
-}
-
-typedef HB_Error  (*Load_Pos_Func_Type)( HB_GPOS_SubTable* st,
-					 HB_Stream         stream );
-static const Load_Pos_Func_Type Load_Pos_Call_Table[] = {
-  Load_DefaultPos,
-  Load_SinglePos,		/* HB_GPOS_LOOKUP_SINGLE     1 */
-  Load_PairPos,			/* HB_GPOS_LOOKUP_PAIR       2 */
-  Load_CursivePos,		/* HB_GPOS_LOOKUP_CURSIVE    3 */
-  Load_MarkBasePos,		/* HB_GPOS_LOOKUP_MARKBASE   4 */
-  Load_MarkLigPos,		/* HB_GPOS_LOOKUP_MARKLIG    5 */
-  Load_MarkMarkPos,		/* HB_GPOS_LOOKUP_MARKMARK   6 */
-  Load_ContextPos,		/* HB_GPOS_LOOKUP_CONTEXT    7 */
-  Load_ChainContextPos,		/* HB_GPOS_LOOKUP_CHAIN      8 */
-  Load_DefaultPos,		/* HB_GPOS_LOOKUP_EXTENSION  9 */
-};
-
-HB_Error  _HB_GPOS_Load_SubTable( HB_GPOS_SubTable*  st,
-				  HB_Stream     stream,
-				  HB_UShort     lookup_type )
+HB_INTERNAL HB_Error
+_HB_GPOS_Load_SubTable( HB_GPOS_SubTable* st,
+			HB_Stream         stream,
+			HB_UShort         lookup_type )
 {
-  Load_Pos_Func_Type Func;
-
-  if (lookup_type >= ARRAY_LEN (Load_Pos_Call_Table))
-    lookup_type = 0;
-
-  Func = Load_Pos_Call_Table[lookup_type];
-
-  return Func ( st, stream );
+  switch ( lookup_type ) {
+    case HB_GPOS_LOOKUP_SINGLE:		return Load_SinglePos		( st, stream );
+    case HB_GPOS_LOOKUP_PAIR:		return Load_PairPos		( st, stream );
+    case HB_GPOS_LOOKUP_CURSIVE:	return Load_CursivePos		( st, stream );
+    case HB_GPOS_LOOKUP_MARKBASE:	return Load_MarkBasePos		( st, stream );
+    case HB_GPOS_LOOKUP_MARKLIG:	return Load_MarkLigPos		( st, stream );
+    case HB_GPOS_LOOKUP_MARKMARK:	return Load_MarkMarkPos		( st, stream );
+    case HB_GPOS_LOOKUP_CONTEXT:	return Load_ContextPos		( st, stream );
+    case HB_GPOS_LOOKUP_CHAIN:		return Load_ChainContextPos	( st, stream );
+  /*case HB_GPOS_LOOKUP_EXTENSION:	return Load_ExtensionPos	( st, stream );*/
+    default:				return ERR(HB_Err_Invalid_SubTable_Format);
+  }
 }
 
 
-static void  Free_DefaultPos( HB_GPOS_SubTable* st )
+HB_INTERNAL void
+_HB_GPOS_Free_SubTable( HB_GPOS_SubTable* st,
+			HB_UShort         lookup_type )
 {
-  HB_UNUSED(st);
-}
-
-typedef void (*Free_Pos_Func_Type)( HB_GPOS_SubTable* st );
-static const Free_Pos_Func_Type Free_Pos_Call_Table[] = {
-  Free_DefaultPos,
-  Free_SinglePos,		/* HB_GPOS_LOOKUP_SINGLE     1 */
-  Free_PairPos,			/* HB_GPOS_LOOKUP_PAIR       2 */
-  Free_CursivePos,		/* HB_GPOS_LOOKUP_CURSIVE    3 */
-  Free_MarkBasePos,		/* HB_GPOS_LOOKUP_MARKBASE   4 */
-  Free_MarkLigPos,		/* HB_GPOS_LOOKUP_MARKLIG    5 */
-  Free_MarkMarkPos,		/* HB_GPOS_LOOKUP_MARKMARK   6 */
-  Free_ContextPos,		/* HB_GPOS_LOOKUP_CONTEXT    7 */
-  Free_ChainContextPos,		/* HB_GPOS_LOOKUP_CHAIN      8 */
-  Free_DefaultPos,		/* HB_GPOS_LOOKUP_EXTENSION  9 */
-};
-
-void  _HB_GPOS_Free_SubTable( HB_GPOS_SubTable*  st,
-			      HB_UShort     lookup_type )
-{
-  Free_Pos_Func_Type Func;
-
-  if (lookup_type >= ARRAY_LEN (Free_Pos_Call_Table))
-    lookup_type = 0;
-
-  Func = Free_Pos_Call_Table[lookup_type];
-
-  Func ( st );
+  switch ( lookup_type ) {
+    case HB_GPOS_LOOKUP_SINGLE:		Free_SinglePos		( st ); return;
+    case HB_GPOS_LOOKUP_PAIR:		Free_PairPos		( st ); return;
+    case HB_GPOS_LOOKUP_CURSIVE:	Free_CursivePos		( st ); return;
+    case HB_GPOS_LOOKUP_MARKBASE:	Free_MarkBasePos	( st ); return;
+    case HB_GPOS_LOOKUP_MARKLIG:	Free_MarkLigPos		( st ); return;
+    case HB_GPOS_LOOKUP_MARKMARK:	Free_MarkMarkPos	( st ); return;
+    case HB_GPOS_LOOKUP_CONTEXT:	Free_ContextPos		( st ); return;
+    case HB_GPOS_LOOKUP_CHAIN:		Free_ChainContextPos	( st ); return;
+  /*case HB_GPOS_LOOKUP_EXTENSION:	Free_ExtensionPos	( st ); return;*/
+    default:									return;
+  }
 }
 
 
-
 /* apply one lookup to the input string object */
 
 static HB_Error  GPOS_Do_String_Lookup( GPOS_Instance*    gpi,
@@ -5948,19 +5884,18 @@ static HB_Error  GPOS_Do_String_Lookup( GPOS_Instance*    gpi,
 
   HB_UInt*  properties = gpos->LookupList.Properties;
 
-  int       nesting_level = 0;
+  const int       nesting_level = 0;
+  /* 0xFFFF indicates that we don't have a context length yet */
+  const HB_UShort context_length = 0xFFFF;
 
 
   gpi->last  = 0xFFFF;     /* no last valid glyph for cursive pos. */
 
   buffer->in_pos = 0;
-
   while ( buffer->in_pos < buffer->in_length )
   {
     if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
     {
-      /* 0xFFFF indicates that we don't have a context length yet. */
-
       /* Note that the connection between mark and base glyphs hold
 	 exactly one (string) lookup.  For example, it would be possible
 	 that in the first lookup, mark glyph X is attached to base
@@ -5968,8 +5903,7 @@ static HB_Error  GPOS_Do_String_Lookup( GPOS_Instance*    gpi,
 	 It is up to the font designer to provide meaningful lookups and
 	 lookup order.                                                   */
 
-      error = GPOS_Do_Glyph_Lookup( gpi, lookup_index, buffer,
-				    0xFFFF, nesting_level );
+      error = GPOS_Do_Glyph_Lookup( gpi, lookup_index, buffer, context_length, nesting_level );
       if ( error && error != HB_Err_Not_Covered )
 	return error;
     }
@@ -6103,13 +6037,14 @@ HB_Error  HB_GPOS_Apply_String( HB_Font            font,
 {
   HB_Error       error, retError = HB_Err_Not_Covered;
   GPOS_Instance  gpi;
-  HB_UShort      i, j, feature_index, lookup_count;
-  HB_Feature    feature;
+  int            i, j, lookup_count, num_features;
 
-  if ( !font || !gpos ||
-       !buffer || buffer->in_length == 0 || buffer->in_pos >= buffer->in_length )
+  if ( !font || !gpos || !buffer )
     return ERR(HB_Err_Invalid_Argument);
 
+  if ( buffer->in_length == 0 )
+    return HB_Err_Not_Covered;
+
   gpi.font       = font;
   gpi.gpos       = gpos;
   gpi.load_flags = load_flags;
@@ -6117,12 +6052,19 @@ HB_Error  HB_GPOS_Apply_String( HB_Font            font,
   gpi.dvi        = dvi;
 
   lookup_count = gpos->LookupList.LookupCount;
+  num_features = gpos->FeatureList.ApplyCount;
+
+  if ( num_features )
+    {
+      error = _hb_buffer_clear_positions( buffer );
+      if ( error )
+	return error;
+    }
 
-  for ( i = 0; i < gpos->FeatureList.ApplyCount; i++ )
+  for ( i = 0; i < num_features; i++ )
   {
-    /* index of i'th feature */
-    feature_index = gpos->FeatureList.ApplyOrder[i];
-    feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;
+    HB_UShort  feature_index = gpos->FeatureList.ApplyOrder[i];
+    HB_Feature feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;
 
     for ( j = 0; j < feature.LookupListCount; j++ )
     {
@@ -6143,9 +6085,12 @@ HB_Error  HB_GPOS_Apply_String( HB_Font            font,
     }
   }
 
+  if ( num_features )
+    {
   error = Position_CursiveChain ( buffer );
   if ( error )
     return error;
+    }
 
   return retError;
 }
diff --git a/src/harfbuzz-gpos.h b/src/harfbuzz-gpos.h
index 4344367..d8151a0 100644
--- a/src/harfbuzz-gpos.h
+++ b/src/harfbuzz-gpos.h
@@ -18,6 +18,7 @@
 
 HB_BEGIN_HEADER
 
+
 /* Lookup types for glyph positioning */
 
 #define HB_GPOS_LOOKUP_SINGLE     1
diff --git a/src/harfbuzz-gsub-private.h b/src/harfbuzz-gsub-private.h
index d5f0942..70b3012 100644
--- a/src/harfbuzz-gsub-private.h
+++ b/src/harfbuzz-gsub-private.h
@@ -13,7 +13,8 @@
 #ifndef HARFBUZZ_GSUB_PRIVATE_H
 #define HARFBUZZ_GSUB_PRIVATE_H
 
-#include "harfbuzz-stream.h"
+#include "harfbuzz-impl.h"
+#include "harfbuzz-stream-private.h"
 #include "harfbuzz-gsub.h"
 
 HB_BEGIN_HEADER
@@ -403,6 +404,19 @@ struct  HB_ChainContextSubst_
 typedef struct HB_ChainContextSubst_  HB_ChainContextSubst;
 
 
+#if 0
+/* LookupType 7 */
+struct HB_ExtensionSubst_
+{
+  HB_UShort      SubstFormat;         /* always 1 */
+  HB_UShort      LookuptType;         /* lookup-type of referenced subtable */
+  HB_GSUB_SubTable *subtable;         /* referenced subtable */
+};
+
+typedef struct HB_ExtensionSubst_  HB_ExtensionSubst;
+#endif
+
+
 /* LookupType 8 */
 struct HB_ReverseChainContextSubst_
 {
@@ -435,12 +449,13 @@ union  HB_GSUB_SubTable_
 
 
 
-
-HB_Error  _HB_GSUB_Load_SubTable( HB_GSUB_SubTable*  st,
+HB_INTERNAL HB_Error
+_HB_GSUB_Load_SubTable( HB_GSUB_SubTable* st,
 				  HB_Stream     stream,
 				  HB_UShort     lookup_type );
 
-void  _HB_GSUB_Free_SubTable( HB_GSUB_SubTable*  st,
+HB_INTERNAL void
+_HB_GSUB_Free_SubTable( HB_GSUB_SubTable* st,
 			      HB_UShort     lookup_type );
 
 HB_END_HEADER
diff --git a/src/harfbuzz-gsub.c b/src/harfbuzz-gsub.c
index 6375a5d..1c7829e 100644
--- a/src/harfbuzz-gsub.c
+++ b/src/harfbuzz-gsub.c
@@ -4,6 +4,7 @@
  *  David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  *  Copyright 2006  Behdad Esfahbod
+ *  Copyright 2007  Red Hat Software
  *
  *  This is part of HarfBuzz, an OpenType Layout engine library.
  *
@@ -42,6 +43,9 @@ HB_Error  HB_Load_GSUB_Table( HB_Stream stream,
   if ( !retptr )
     return ERR(HB_Err_Invalid_Argument);
 
+  if ( GOTO_Table( TTAG_GSUB ) )
+    return error;
+
   base_offset = FILE_Pos();
 
   if ( ALLOC ( gsub, sizeof( *gsub ) ) ) 
@@ -94,15 +98,6 @@ HB_Error  HB_Load_GSUB_Table( HB_Stream stream,
 
   gsub->gdef = gdef;      /* can be NULL */
 
-  /* We now check the LookupFlags for values larger than 0xFF to find
-     out whether we need to load the `MarkAttachClassDef' field of the
-     GDEF table -- this hack is necessary for OpenType 1.2 tables since
-     the version field of the GDEF table hasn't been incremented.
-
-     For constructed GDEF tables, we only load it if
-     `MarkAttachClassDef_offset' is not zero (nevertheless, a build of
-     a constructed mark attach table is not supported currently).       */
-
   if ( ( error =  _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( gdef, gdefStream,
 								     gsub->LookupList.Lookup,
 								     gsub->LookupList.LookupCount ) ) )
@@ -144,22 +139,6 @@ HB_Error   HB_Done_GSUB_Table( HB_GSUBHeader* gsub )
  * SubTable related functions
  *****************************/
 
-static HB_Error  Lookup_DefaultSubst( HB_GSUBHeader*    gsub,
-				      HB_GSUB_SubTable* st,
-				      HB_Buffer         buffer,
-				      HB_UShort          flags,
-				      HB_UShort          context_length,
-				      int                nesting_level )
-{
-  HB_UNUSED(gsub);
-  HB_UNUSED(st);
-  HB_UNUSED(buffer);
-  HB_UNUSED(flags);
-  HB_UNUSED(context_length);
-  HB_UNUSED(nesting_level);
-  return HB_Err_Not_Covered;
-}
-
 
 /* LookupType 1 */
 
@@ -258,6 +237,9 @@ static void  Free_SingleSubst( HB_GSUB_SubTable* st )
   case 2:
     FREE( ss->ssf.ssf2.Substitute );
     break;
+
+  default:
+    break;
   }
 
   _HB_OPEN_Free_Coverage( &ss->Coverage );
@@ -278,7 +260,6 @@ static HB_Error  Lookup_SingleSubst( HB_GSUBHeader*   gsub,
 
   HB_UNUSED(nesting_level);
 
-
   if ( context_length != 0xFFFF && context_length < 1 )
     return HB_Err_Not_Covered;
 
@@ -292,8 +273,8 @@ static HB_Error  Lookup_SingleSubst( HB_GSUBHeader*   gsub,
   switch ( ss->SubstFormat )
   {
   case 1:
-	  value = ( IN_CURGLYPH() + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;
-    if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) )
+    value = ( IN_CURGLYPH() + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;
+    if ( REPLACE_Glyph( buffer, value, nesting_level ) )
       return error;
     break;
 
@@ -301,7 +282,7 @@ static HB_Error  Lookup_SingleSubst( HB_GSUBHeader*   gsub,
     if ( index >= ss->ssf.ssf2.GlyphCount )
       return ERR(HB_Err_Invalid_SubTable);
     value = ss->ssf.ssf2.Substitute[index];
-    if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) )
+    if ( REPLACE_Glyph( buffer, value, nesting_level ) )
       return error;
     break;
 
@@ -676,7 +657,7 @@ static HB_Error  Lookup_AlternateSubst( HB_GSUBHeader*    gsub,
 					int                nesting_level )
 {
   HB_Error          error;
-  HB_UShort         index, alt_index, property;
+  HB_UShort         index, value, alt_index, property;
   HB_AlternateSubst* as = &st->alternate;
   HB_GDEFHeader*     gdef = gsub->gdef;
   HB_AlternateSet  aset;
@@ -704,16 +685,15 @@ static HB_Error  Lookup_AlternateSubst( HB_GSUBHeader*    gsub,
   else
     alt_index = 0;
 
-  if ( ADD_Glyph( buffer, aset.Alternate[alt_index],
-		  0xFFFF, 0xFFFF ) )
+  value = aset.Alternate[alt_index];
+  if ( REPLACE_Glyph( buffer, value, nesting_level ) )
     return error;
 
   if ( gdef && gdef->NewGlyphClasses )
   {
     /* we inherit the old glyph class to the substituted glyph */
 
-    error = _HB_GDEF_Add_Glyph_Property( gdef, aset.Alternate[alt_index],
-				property );
+    error = _HB_GDEF_Add_Glyph_Property( gdef, value, property );
     if ( error && error != HB_Err_Not_Covered )
       return error;
   }
@@ -1035,7 +1015,7 @@ static HB_Error  Lookup_LigatureSubst( HB_GSUBHeader*    gsub,
       }
       else
       {
-	HB_UShort ligID = hb_buffer_allocate_ligid( buffer );
+	HB_UShort ligID = _hb_buffer_allocate_ligid( buffer );
 	if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
 			0xFFFF, ligID ) )
 	  return error;
@@ -1043,9 +1023,8 @@ static HB_Error  Lookup_LigatureSubst( HB_GSUBHeader*    gsub,
     }
     else
     {
-      HB_UShort ligID = hb_buffer_allocate_ligid( buffer );
-      if ( ADD_Glyph( buffer, lig->LigGlyph,
-		      0xFFFF, ligID ) )
+      HB_UShort ligID = _hb_buffer_allocate_ligid( buffer );
+      if ( ADD_Glyph( buffer, lig->LigGlyph, 0xFFFF, ligID ) )
 	return error;
 
       /* Now we must do a second loop to copy the skipped glyphs to
@@ -1059,8 +1038,7 @@ static HB_Error  Lookup_LigatureSubst( HB_GSUBHeader*    gsub,
       {
 	while ( CHECK_Property( gdef, IN_CURITEM(),
 				flags, &property ) )
-	  if ( ADD_Glyph( buffer, IN_CURGLYPH(),
-			  i, ligID ) )
+	  if ( ADD_Glyph( buffer, IN_CURGLYPH(), i, ligID ) )
 	    return error;
 
 	(buffer->in_pos)++;
@@ -1111,10 +1089,7 @@ static HB_Error  Do_ContextSubst( HB_GSUBHeader*        gsub,
 
       if ( error == HB_Err_Not_Covered )
       {
-	/* XXX "can't happen" -- but don't count on it */
-
-	if ( ADD_Glyph( buffer, IN_CURGLYPH(),
-			0xFFFF, 0xFFFF ) )
+	if ( COPY_Glyph( buffer ) )
 	  return error;
 	i++;
       }
@@ -1125,8 +1100,7 @@ static HB_Error  Do_ContextSubst( HB_GSUBHeader*        gsub,
     {
       /* No substitution for this index */
 
-      if ( ADD_Glyph( buffer, IN_CURGLYPH(),
-		      0xFFFF, 0xFFFF ) )
+      if ( COPY_Glyph( buffer ) )
 	return error;
       i++;
     }
@@ -1797,17 +1771,10 @@ static HB_Error  Load_ContextSubst( HB_GSUB_SubTable* st,
 
   switch ( cs->SubstFormat )
   {
-  case 1:
-    return Load_ContextSubst1( &cs->csf.csf1, stream );
-
-  case 2:
-    return Load_ContextSubst2( &cs->csf.csf2, stream );
-
-  case 3:
-    return Load_ContextSubst3( &cs->csf.csf3, stream );
-
-  default:
-    return ERR(HB_Err_Invalid_SubTable_Format);
+  case 1:  return Load_ContextSubst1( &cs->csf.csf1, stream );
+  case 2:  return Load_ContextSubst2( &cs->csf.csf2, stream );
+  case 3:  return Load_ContextSubst3( &cs->csf.csf3, stream );
+  default: return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;               /* never reached */
@@ -1820,17 +1787,10 @@ static void  Free_ContextSubst( HB_GSUB_SubTable* st )
 
   switch ( cs->SubstFormat )
   {
-  case 1:
-    Free_ContextSubst1( &cs->csf.csf1 );
-    break;
-
-  case 2:
-    Free_ContextSubst2( &cs->csf.csf2 );
-    break;
-
-  case 3:
-    Free_ContextSubst3( &cs->csf.csf3 );
-    break;
+  case 1:  Free_ContextSubst1( &cs->csf.csf1 ); break;
+  case 2:  Free_ContextSubst2( &cs->csf.csf2 ); break;
+  case 3:  Free_ContextSubst3( &cs->csf.csf3 ); break;
+  default:						break;
   }
 }
 
@@ -2066,20 +2026,10 @@ static HB_Error  Lookup_ContextSubst( HB_GSUBHeader*    gsub,
 
   switch ( cs->SubstFormat )
   {
-  case 1:
-    return Lookup_ContextSubst1( gsub, &cs->csf.csf1, buffer,
-				 flags, context_length, nesting_level );
-
-  case 2:
-    return Lookup_ContextSubst2( gsub, &cs->csf.csf2, buffer,
-				 flags, context_length, nesting_level );
-
-  case 3:
-    return Lookup_ContextSubst3( gsub, &cs->csf.csf3, buffer,
-				 flags, context_length, nesting_level );
-
-  default:
-    return ERR(HB_Err_Invalid_SubTable_Format);
+  case 1:  return Lookup_ContextSubst1( gsub, &cs->csf.csf1, buffer, flags, context_length, nesting_level );
+  case 2:  return Lookup_ContextSubst2( gsub, &cs->csf.csf2, buffer, flags, context_length, nesting_level );
+  case 3:  return Lookup_ContextSubst3( gsub, &cs->csf.csf3, buffer, flags, context_length, nesting_level );
+  default: return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;               /* never reached */
@@ -3029,19 +2979,11 @@ static HB_Error  Load_ChainContextSubst( HB_GSUB_SubTable* st,
 
   FORGET_Frame();
 
-  switch ( ccs->SubstFormat )
-  {
-  case 1:
-    return Load_ChainContextSubst1( &ccs->ccsf.ccsf1, stream );
-
-  case 2:
-    return Load_ChainContextSubst2( &ccs->ccsf.ccsf2, stream );
-
-  case 3:
-    return Load_ChainContextSubst3( &ccs->ccsf.ccsf3, stream );
-
-  default:
-    return ERR(HB_Err_Invalid_SubTable_Format);
+  switch ( ccs->SubstFormat ) {
+    case 1:  return Load_ChainContextSubst1( &ccs->ccsf.ccsf1, stream );
+    case 2:  return Load_ChainContextSubst2( &ccs->ccsf.ccsf2, stream );
+    case 3:  return Load_ChainContextSubst3( &ccs->ccsf.ccsf3, stream );
+    default: return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;               /* never reached */
@@ -3052,19 +2994,11 @@ static void  Free_ChainContextSubst( HB_GSUB_SubTable* st )
 {
   HB_ChainContextSubst*  ccs = &st->chain;
 
-  switch ( ccs->SubstFormat )
-  {
-  case 1:
-    Free_ChainContextSubst1( &ccs->ccsf.ccsf1 );
-    break;
-
-  case 2:
-    Free_ChainContextSubst2( &ccs->ccsf.ccsf2 );
-    break;
-
-  case 3:
-    Free_ChainContextSubst3( &ccs->ccsf.ccsf3 );
-    break;
+  switch ( ccs->SubstFormat ) {
+    case 1:  Free_ChainContextSubst1( &ccs->ccsf.ccsf1 ); break;
+    case 2:  Free_ChainContextSubst2( &ccs->ccsf.ccsf2 ); break;
+    case 3:  Free_ChainContextSubst3( &ccs->ccsf.ccsf3 ); break;
+    default:							  break;
   }
 }
 
@@ -3514,28 +3448,12 @@ static HB_Error  Lookup_ChainContextSubst( HB_GSUBHeader*    gsub,
 {
   HB_ChainContextSubst*  ccs = &st->chain;
 
-  switch ( ccs->SubstFormat )
-  {
-  case 1:
-    return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, buffer,
-				      flags, context_length,
-				      nesting_level );
-
-  case 2:
-    return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, buffer,
-				      flags, context_length,
-				      nesting_level );
-
-  case 3:
-    return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, buffer,
-				      flags, context_length,
-				      nesting_level );
-
-  default:
-    return ERR(HB_Err_Invalid_SubTable_Format);
+  switch ( ccs->SubstFormat ) {
+    case 1:  return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, buffer, flags, context_length, nesting_level );
+    case 2:  return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, buffer, flags, context_length, nesting_level );
+    case 3:  return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, buffer, flags, context_length, nesting_level );
+    default: return ERR(HB_Err_Invalid_SubTable_Format);
   }
-
-  return HB_Err_Ok;               /* never reached */
 }
 
 
@@ -3735,7 +3653,8 @@ static HB_Error  Lookup_ReverseChainContextSubst( HB_GSUBHeader*    gsub,
 						  HB_GSUB_SubTable* st,
 						  HB_Buffer         buffer,
 						  HB_UShort          flags,
-      /* note different signature here: */	  HB_UInt           string_index )
+						  HB_UShort         context_length,
+						  int               nesting_level )
 {
   HB_UShort        index, input_index, i, j, property;
   HB_UShort        bgc, lgc;
@@ -3746,9 +3665,12 @@ static HB_Error  Lookup_ReverseChainContextSubst( HB_GSUBHeader*    gsub,
   HB_Coverage*    lc;
   HB_GDEFHeader*  gdef;
 
+  if ( nesting_level != 1 || context_length != 0xFFFF )
+    return HB_Err_Not_Covered;
+
   gdef = gsub->gdef;
 
-  if ( CHECK_Property( gdef, IN_ITEM( string_index ), flags, &property ) )
+  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
     return error;
 
   bgc = rccs->BacktrackGlyphCount;
@@ -3756,7 +3678,7 @@ static HB_Error  Lookup_ReverseChainContextSubst( HB_GSUBHeader*    gsub,
 
   /* check whether context is too long; it is a first guess only */
 
-  if ( bgc > string_index || string_index + 1 + lgc > buffer->in_length )
+  if ( bgc > buffer->in_pos || buffer->in_pos + 1 + lgc > buffer->in_length )
     return HB_Err_Not_Covered;
 
   if ( bgc )
@@ -3766,7 +3688,7 @@ static HB_Error  Lookup_ReverseChainContextSubst( HB_GSUBHeader*    gsub,
 
     bc       = rccs->BacktrackCoverage;
 
-    for ( i = 0, j = string_index - 1; i < bgc; i++, j-- )
+    for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
     {
       while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
       {
@@ -3784,20 +3706,15 @@ static HB_Error  Lookup_ReverseChainContextSubst( HB_GSUBHeader*    gsub,
     }
   }
 
-  j = string_index;
+  j = buffer->in_pos;
 
   error = _HB_OPEN_Coverage_Index( &rccs->Coverage, IN_GLYPH( j ), &input_index );
   if ( error )
       return error;
 
-  /* we are starting for lookahead glyphs right after the last context
-     glyph                                                             */
-
-  j += 1;
-
   lc       = rccs->LookaheadCoverage;
 
-  for ( i = 0; i < lgc; i++, j++ )
+  for ( i = 0, j = buffer->in_pos + 1; i < lgc; i++, j++ )
   {
     while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
     {
@@ -3814,7 +3731,8 @@ static HB_Error  Lookup_ReverseChainContextSubst( HB_GSUBHeader*    gsub,
       return error;
   }
 
-  IN_GLYPH( string_index ) = rccs->Substitute[input_index];
+  IN_CURGLYPH() = rccs->Substitute[input_index];
+  buffer->in_pos--; /* Reverse! */
 
   return error;
 }
@@ -3979,7 +3897,6 @@ HB_Error  HB_GSUB_Query_Scripts( HB_GSUBHeader*  gsub,
   if ( !gsub || !script_tag_list )
     return ERR(HB_Err_Invalid_Argument);
 
-
   sl = &gsub->ScriptList;
   sr = sl->ScriptRecord;
 
@@ -4107,28 +4024,6 @@ HB_Error  HB_GSUB_Query_Features( HB_GSUBHeader*  gsub,
 }
 
 
-typedef HB_Error  (*Lookup_Subst_Func_Type)( HB_GSUBHeader*    gsub,
-					     HB_GSUB_SubTable* st,
-					     HB_Buffer         buffer,
-					     HB_UShort          flags,
-					     HB_UShort          context_length,
-					     int                nesting_level );
-static const Lookup_Subst_Func_Type Lookup_Subst_Call_Table[] = {
-  Lookup_DefaultSubst,
-  Lookup_SingleSubst,		/* HB_GSUB_LOOKUP_SINGLE        1 */
-  Lookup_MultipleSubst,		/* HB_GSUB_LOOKUP_MULTIPLE      2 */
-  Lookup_AlternateSubst,	/* HB_GSUB_LOOKUP_ALTERNATE     3 */
-  Lookup_LigatureSubst,		/* HB_GSUB_LOOKUP_LIGATURE      4 */
-  Lookup_ContextSubst,		/* HB_GSUB_LOOKUP_CONTEXT       5 */
-  Lookup_ChainContextSubst,	/* HB_GSUB_LOOKUP_CHAIN         6 */
-  Lookup_DefaultSubst		/* HB_GSUB_LOOKUP_EXTENSION     7 */
-};
-/* Note that the following lookup does not belong to the table above:
- * Lookup_ReverseChainContextSubst,	 HB_GSUB_LOOKUP_REVERSE_CHAIN 8
- * because it's invalid to happen where this table is used.  It's
- * signature is different too...
- */
-
 /* Do an individual subtable lookup.  Returns HB_Err_Ok if substitution
    has been done, or HB_Err_Not_Covered if not.                        */
 static HB_Error  GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub,
@@ -4141,13 +4036,11 @@ static HB_Error  GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub,
   HB_UShort              i, flags, lookup_count;
   HB_Lookup*             lo;
   int                    lookup_type;
-  Lookup_Subst_Func_Type Func;
-
 
   nesting_level++;
 
   if ( nesting_level > HB_MAX_NESTING_LEVEL )
-    return ERR(HB_Err_Not_Covered);
+    return ERR(HB_Err_Not_Covered); /* ERR() call intended */
 
   lookup_count = gsub->LookupList.LookupCount;
   if (lookup_index >= lookup_count)
@@ -4157,21 +4050,33 @@ static HB_Error  GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub,
   flags = lo->LookupFlag;
   lookup_type = lo->LookupType;
 
-  if (lookup_type >= ARRAY_LEN (Lookup_Subst_Call_Table))
-    lookup_type = 0;
-  Func = Lookup_Subst_Call_Table[lookup_type];
-
   for ( i = 0; i < lo->SubTableCount; i++ )
   {
-    error = Func ( gsub,
-		   &lo->SubTable[i].st.gsub,
-		   buffer,
-		   flags, context_length,
-		   nesting_level );
+    HB_GSUB_SubTable *st = &lo->SubTable[i].st.gsub;
+
+    switch (lookup_type) {
+      case HB_GSUB_LOOKUP_SINGLE:
+	error = Lookup_SingleSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;
+      case HB_GSUB_LOOKUP_MULTIPLE:
+	error = Lookup_MultipleSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;
+      case HB_GSUB_LOOKUP_ALTERNATE:
+	error = Lookup_AlternateSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;
+      case HB_GSUB_LOOKUP_LIGATURE:
+	error = Lookup_LigatureSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;
+      case HB_GSUB_LOOKUP_CONTEXT:
+	error = Lookup_ContextSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;
+      case HB_GSUB_LOOKUP_CHAIN:
+	error = Lookup_ChainContextSubst	( gsub, st, buffer, flags, context_length, nesting_level ); break;
+    /*case HB_GSUB_LOOKUP_EXTENSION:
+	error = Lookup_ExtensionSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;*/
+      case HB_GSUB_LOOKUP_REVERSE_CHAIN:
+	error = Lookup_ReverseChainContextSubst	( gsub, st, buffer, flags, context_length, nesting_level ); break;
+      default:
+	error = HB_Err_Not_Covered;
+    };
 
     /* Check whether we have a successful substitution or an error other
        than HB_Err_Not_Covered                                          */
-
     if ( error != HB_Err_Not_Covered )
       return error;
   }
@@ -4180,73 +4085,40 @@ static HB_Error  GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub,
 }
 
 
-static HB_Error  Load_DefaultSubst( HB_GSUB_SubTable* st,
-				    HB_Stream         stream )
+HB_INTERNAL HB_Error
+_HB_GSUB_Load_SubTable( HB_GSUB_SubTable* st,
+			HB_Stream         stream,
+			HB_UShort         lookup_type )
 {
-  HB_UNUSED(st);
-  HB_UNUSED(stream);
-
-  return ERR(HB_Err_Invalid_SubTable_Format);
-}
-
-typedef HB_Error  (*Load_Subst_Func_Type)( HB_GSUB_SubTable* st,
-					   HB_Stream         stream );
-static const Load_Subst_Func_Type Load_Subst_Call_Table[] = {
-  Load_DefaultSubst,
-  Load_SingleSubst,		/* HB_GSUB_LOOKUP_SINGLE        1 */
-  Load_MultipleSubst,		/* HB_GSUB_LOOKUP_MULTIPLE      2 */
-  Load_AlternateSubst,		/* HB_GSUB_LOOKUP_ALTERNATE     3 */
-  Load_LigatureSubst,		/* HB_GSUB_LOOKUP_LIGATURE      4 */
-  Load_ContextSubst,		/* HB_GSUB_LOOKUP_CONTEXT       5 */
-  Load_ChainContextSubst,	/* HB_GSUB_LOOKUP_CHAIN         6 */
-  Load_DefaultSubst,		/* HB_GSUB_LOOKUP_EXTENSION     7 */
-  Load_ReverseChainContextSubst /* HB_GSUB_LOOKUP_REVERSE_CHAIN 8 */
-};
-
-HB_Error  _HB_GSUB_Load_SubTable( HB_GSUB_SubTable*  st,
-				  HB_Stream     stream,
-				  HB_UShort     lookup_type )
-{
-  Load_Subst_Func_Type Func;
-
-  if (lookup_type >= ARRAY_LEN (Load_Subst_Call_Table))
-    lookup_type = 0;
-
-  Func = Load_Subst_Call_Table[lookup_type];
-
-  return Func ( st, stream );
+  switch (lookup_type) {
+    case HB_GSUB_LOOKUP_SINGLE:		return Load_SingleSubst			( st, stream );
+    case HB_GSUB_LOOKUP_MULTIPLE:	return Load_MultipleSubst		( st, stream );
+    case HB_GSUB_LOOKUP_ALTERNATE:	return Load_AlternateSubst		( st, stream );
+    case HB_GSUB_LOOKUP_LIGATURE:	return Load_LigatureSubst		( st, stream );
+    case HB_GSUB_LOOKUP_CONTEXT:	return Load_ContextSubst		( st, stream );
+    case HB_GSUB_LOOKUP_CHAIN:		return Load_ChainContextSubst		( st, stream );
+  /*case HB_GSUB_LOOKUP_EXTENSION:	return Load_ExtensionSubst		( st, stream );*/
+    case HB_GSUB_LOOKUP_REVERSE_CHAIN:	return Load_ReverseChainContextSubst	( st, stream );
+    default:				return ERR(HB_Err_Invalid_SubTable_Format);
+  };
 }
 
 
-static void  Free_DefaultSubst( HB_GSUB_SubTable* st )
-{
-  HB_UNUSED(st);
-}
-
-typedef void  (*Free_Subst_Func_Type)( HB_GSUB_SubTable* st );
-static const Free_Subst_Func_Type Free_Subst_Call_Table[] = {
-  Free_DefaultSubst,
-  Free_SingleSubst,		/* HB_GSUB_LOOKUP_SINGLE        1 */
-  Free_MultipleSubst,		/* HB_GSUB_LOOKUP_MULTIPLE      2 */
-  Free_AlternateSubst,		/* HB_GSUB_LOOKUP_ALTERNATE     3 */
-  Free_LigatureSubst,		/* HB_GSUB_LOOKUP_LIGATURE      4 */
-  Free_ContextSubst,		/* HB_GSUB_LOOKUP_CONTEXT       5 */
-  Free_ChainContextSubst,	/* HB_GSUB_LOOKUP_CHAIN         6 */
-  Free_DefaultSubst,		/* HB_GSUB_LOOKUP_EXTENSION     7 */
-  Free_ReverseChainContextSubst /* HB_GSUB_LOOKUP_REVERSE_CHAIN 8 */
-};
-
-void  _HB_GSUB_Free_SubTable( HB_GSUB_SubTable*  st,
-			      HB_UShort     lookup_type )
+HB_INTERNAL void
+_HB_GSUB_Free_SubTable( HB_GSUB_SubTable* st,
+			HB_UShort         lookup_type )
 {
-  Free_Subst_Func_Type Func;
-
-  if (lookup_type >= ARRAY_LEN (Free_Subst_Call_Table))
-    lookup_type = 0;
-
-  Func = Free_Subst_Call_Table[lookup_type];
-
-  Func ( st );
+  switch ( lookup_type ) {
+    case HB_GSUB_LOOKUP_SINGLE:		Free_SingleSubst		( st ); return;
+    case HB_GSUB_LOOKUP_MULTIPLE:	Free_MultipleSubst		( st ); return;
+    case HB_GSUB_LOOKUP_ALTERNATE:	Free_AlternateSubst		( st ); return;
+    case HB_GSUB_LOOKUP_LIGATURE:	Free_LigatureSubst		( st ); return;
+    case HB_GSUB_LOOKUP_CONTEXT:	Free_ContextSubst		( st ); return;
+    case HB_GSUB_LOOKUP_CHAIN:		Free_ChainContextSubst		( st ); return;
+  /*case HB_GSUB_LOOKUP_EXTENSION:	Free_ExtensionSubst		( st ); return;*/
+    case HB_GSUB_LOOKUP_REVERSE_CHAIN:	Free_ReverseChainContextSubst	( st ); return;
+    default:									return;
+  };
 }
 
 
@@ -4260,17 +4132,29 @@ static HB_Error  GSUB_Do_String_Lookup( HB_GSUBHeader*   gsub,
   HB_Error  error, retError = HB_Err_Not_Covered;
 
   HB_UInt*  properties = gsub->LookupList.Properties;
+  int       lookup_type = gsub->LookupList.Lookup[lookup_index].LookupType;
+
+  const int       nesting_level = 0;
+  /* 0xFFFF indicates that we don't have a context length yet */
+  const HB_UShort context_length = 0xFFFF;
 
-  int      nesting_level = 0;
+  switch (lookup_type) {
 
+    case HB_GSUB_LOOKUP_SINGLE:
+    case HB_GSUB_LOOKUP_MULTIPLE:
+    case HB_GSUB_LOOKUP_ALTERNATE:
+    case HB_GSUB_LOOKUP_LIGATURE:
+    case HB_GSUB_LOOKUP_CONTEXT:
+    case HB_GSUB_LOOKUP_CHAIN:
+      /* in/out forward substitution (implemented lazy) */
 
+      _hb_buffer_clear_output ( buffer );
+      buffer->in_pos = 0;
   while ( buffer->in_pos < buffer->in_length )
   {
     if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
     {
-      /* 0xFFFF indicates that we don't have a context length yet */
-      error = GSUB_Do_Glyph_Lookup( gsub, lookup_index, buffer,
-				    0xFFFF, nesting_level );
+	  error = GSUB_Do_Glyph_Lookup( gsub, lookup_index, buffer, context_length, nesting_level );
       if ( error )
       {
 	if ( error != HB_Err_Not_Covered )
@@ -4283,39 +4167,28 @@ static HB_Error  GSUB_Do_String_Lookup( HB_GSUBHeader*   gsub,
       error = HB_Err_Not_Covered;
 
     if ( error == HB_Err_Not_Covered )
-      if ( (error = hb_buffer_copy_output_glyph ( buffer ) ) )
+	  if ( COPY_Glyph ( buffer ) )
 	return error;
   }
+      /* we shouldn't swap if error occurred.
+       *
+       * also don't swap if nothing changed (ie HB_Err_Not_Covered).
+       * shouldn't matter in that case though.
+       */
+      if ( retError == HB_Err_Ok )
+	_hb_buffer_swap( buffer );
 
   return retError;
-}
 
+    case HB_GSUB_LOOKUP_REVERSE_CHAIN:
+      /* in-place backward substitution */
 
-static HB_Error  Apply_ReverseChainContextSubst( HB_GSUBHeader*   gsub,
-						 HB_UShort         lookup_index,
-						 HB_Buffer        buffer )
-{
-  HB_UInt*     properties =  gsub->LookupList.Properties;
-  HB_Error     error, retError = HB_Err_Not_Covered;
-  HB_UInt     subtable_Count, string_index;
-  HB_UShort    flags;
-  HB_Lookup*  lo;
-
-  if ( buffer->in_length == 0 )
-    return HB_Err_Not_Covered;
-
-  lo    = &gsub->LookupList.Lookup[lookup_index];
-  flags = lo->LookupFlag;
-
-  for ( subtable_Count = 0; subtable_Count < lo->SubTableCount; subtable_Count++ )
-  {
-    string_index  = buffer->in_length - 1;
+      buffer->in_pos = buffer->in_length - 1;
     do
     {
       if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
 	{
-	  error = Lookup_ReverseChainContextSubst( gsub, &lo->SubTable[subtable_Count].st.gsub,
-						   buffer, flags, string_index );
+	  error = GSUB_Do_Glyph_Lookup( gsub, lookup_index, buffer, context_length, nesting_level );
 	  if ( error )
 	    {
 	      if ( error != HB_Err_Not_Covered )
@@ -4324,11 +4197,20 @@ static HB_Error  Apply_ReverseChainContextSubst( HB_GSUBHeader*   gsub,
 	  else
 	    retError = error;
 	}
+	else
+	  error = HB_Err_Not_Covered;
+
+	if ( error == HB_Err_Not_Covered )
+	  buffer->in_pos--;
     }
-    while (string_index--);
-  }
+      while (buffer->in_pos);
 
+      return retError;
+
+  /*case HB_GSUB_LOOKUP_EXTENSION:*/
+    default:
   return retError;
+  };
 }
 
 
@@ -4405,73 +4287,51 @@ HB_Error  HB_GSUB_Register_Alternate_Function( HB_GSUBHeader*  gsub,
   return HB_Err_Ok;
 }
 
-
-
+/* returns error if one happened, otherwise returns HB_Err_Not_Covered if no
+ * feature were applied, or HB_Err_Ok otherwise.
+ */
 HB_Error  HB_GSUB_Apply_String( HB_GSUBHeader*   gsub,
 				HB_Buffer        buffer )
 {
   HB_Error          error, retError = HB_Err_Not_Covered;
-  HB_UShort         i, j, lookup_count;
+  int               i, j, lookup_count, num_features;
 
   if ( !gsub ||
-       !buffer || buffer->in_length == 0 || buffer->in_pos >= buffer->in_length )
+       !buffer)
     return ERR(HB_Err_Invalid_Argument);
 
+  if ( buffer->in_length == 0 )
+    return retError;
+
   lookup_count = gsub->LookupList.LookupCount;
+  num_features = gsub->FeatureList.ApplyCount;
 
-  for ( i = 0; i < gsub->FeatureList.ApplyCount; i++)
+  for ( i = 0; i < num_features; i++)
   {
-    HB_UShort         feature_index;
-    HB_Feature       feature;
-
-    feature_index = gsub->FeatureList.ApplyOrder[i];
-    feature = gsub->FeatureList.FeatureRecord[feature_index].Feature;
+    HB_UShort  feature_index = gsub->FeatureList.ApplyOrder[i];
+    HB_Feature feature = gsub->FeatureList.FeatureRecord[feature_index].Feature;
 
     for ( j = 0; j < feature.LookupListCount; j++ )
     {
-      HB_UShort         lookup_index;
-      HB_Lookup*       lookup;
-      HB_Bool           need_swap;
-
-      lookup_index = feature.LookupListIndex[j];
+      HB_UShort         lookup_index = feature.LookupListIndex[j];
 
       /* Skip nonexistant lookups */
       if (lookup_index >= lookup_count)
        continue;
 
-      lookup = &gsub->LookupList.Lookup[lookup_index];
-
-      if ( lookup->LookupType == HB_GSUB_LOOKUP_REVERSE_CHAIN )
-      {
-	error = Apply_ReverseChainContextSubst( gsub, lookup_index, buffer);
-	need_swap = FALSE; /* We do ReverseChainContextSubst in-place */
-      }
-      else
-      {
 	error = GSUB_Do_String_Lookup( gsub, lookup_index, buffer );
-	need_swap = TRUE;
-      }
-
       if ( error )
       {
 	if ( error != HB_Err_Not_Covered )
-	  goto End;
+	  return error;
       }
       else
 	retError = error;
-
-      if ( need_swap )
-      {
-	error = hb_buffer_swap( buffer );
-	if ( error )
-	  goto End;
-      }
     }
   }
 
   error = retError;
 
-End:
   return error;
 }
 
diff --git a/src/harfbuzz-gsub.h b/src/harfbuzz-gsub.h
index 867d59d..6ff8fec 100644
--- a/src/harfbuzz-gsub.h
+++ b/src/harfbuzz-gsub.h
@@ -18,6 +18,7 @@
 
 HB_BEGIN_HEADER
 
+
 /* Lookup types for glyph substitution */
 
 #define HB_GSUB_LOOKUP_SINGLE        1
diff --git a/src/harfbuzz-impl.c b/src/harfbuzz-impl.c
new file mode 100644
index 0000000..c601048
--- /dev/null
+++ b/src/harfbuzz-impl.c
@@ -0,0 +1,87 @@
+/*******************************************************************
+ *
+ *  Copyright 2005  David Turner, The FreeType Project (www.freetype.org)
+ *  Copyright 2007  Trolltech ASA
+ *  Copyright 2007  Red Hat, Inc
+ *
+ *  This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ *  See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#include "harfbuzz-impl.h"
+
+#if 0
+#include <stdio.h>
+#define  LOG(x)  _hb_log x
+
+static void
+_hb_log( const char*   format, ... )
+{
+  va_list  ap;
+
+  va_start( ap, format );
+  vfprintf( stderr, format, ap );
+  va_end( ap );
+}
+
+#else
+#define  LOG(x)  do {} while (0)
+#endif
+
+
+HB_INTERNAL HB_Pointer
+_hb_alloc(HB_UInt   size,
+	  HB_Error  *perror )
+{
+  HB_Error    error = 0;
+  HB_Pointer  block = NULL;
+
+  if ( size > 0 )
+  {
+    block = malloc( size );
+    if ( !block )
+      error = ERR(HB_Err_Out_Of_Memory);
+    else
+      memset( (char*)block, 0, (size_t)size );
+  }
+
+  *perror = error;
+  return block;
+}
+
+
+HB_INTERNAL HB_Pointer
+_hb_realloc(HB_Pointer  block,
+	    HB_UInt    new_size,
+	    HB_Error   *perror )
+{
+    HB_Pointer  block2 = NULL;
+    HB_Error    error  = 0;
+
+    block2 = realloc( block, new_size );
+    if ( block2 == NULL && new_size != 0 )
+        error = ERR(HB_Err_Out_Of_Memory);
+
+    if ( !error )
+        block = block2;
+
+    *perror = error;
+    return block;
+}
+
+
+HB_INTERNAL void
+_hb_free( HB_Pointer  block )
+{
+  if ( block )
+    free( block );
+}
+
+
+/* helper func to set a breakpoint on */
+HB_INTERNAL HB_Error
+_hb_err (HB_Error code)
+{
+  return code;
+}
diff --git a/src/harfbuzz-impl.h b/src/harfbuzz-impl.h
index bfada40..9273a4f 100644
--- a/src/harfbuzz-impl.h
+++ b/src/harfbuzz-impl.h
@@ -17,6 +17,10 @@
 
 HB_BEGIN_HEADER
 
+#ifndef HB_INTERNAL
+# define HB_INTERNAL
+#endif
+
 #ifndef NULL
 # define NULL ((void *)0)
 #endif
@@ -43,37 +47,69 @@ HB_BEGIN_HEADER
 # define HB_UNUSED(arg) ((arg) = (arg))
 #endif
 
+#define HB_LIKELY(cond) (cond)
+#define HB_UNLIKELY(cond) (cond)
+
 #define ARRAY_LEN(Array) ((int)(sizeof (Array) / sizeof (Array)[0]))
 
 
 
+#define HB_IsHighSurrogate(ucs) \
+    (((ucs) & 0xfc00) == 0xd800)
+
+#define HB_IsLowSurrogate(ucs) \
+    (((ucs) & 0xfc00) == 0xdc00)
+
+#define HB_SurrogateToUcs4(high, low) \
+    (((HB_UChar32)(high))<<10) + (low) - 0x35fdc00;
+
+
+
+
+
+#define  ALLOC(_ptr,_size)   \
+           ( (_ptr) = _hb_alloc( _size, &error ), error != 0 )
+
+#define  REALLOC(_ptr,_newsz)  \
+           ( (_ptr) = _hb_realloc( (_ptr), (_newsz), &error ), error != 0 )
+
+#define  FREE(_ptr)                    \
+  do {                                 \
+    if ( (_ptr) )                      \
+    {                                  \
+      _hb_free( _ptr );     \
+      _ptr = NULL;                     \
+    }                                  \
+  } while (0)
+
+#define  ALLOC_ARRAY(_ptr,_count,_type)   \
+           ALLOC(_ptr,(_count)*sizeof(_type))
+
+#define  REALLOC_ARRAY(_ptr,_newcnt,_type) \
+           REALLOC(_ptr,(_newcnt)*sizeof(_type))
+
+#define  MEM_Copy(dest,source,count)   memcpy( (char*)(dest), (const char*)(source), (size_t)(count) )
+
+#define ERR(err)   _hb_err (err)
+
+
+HB_INTERNAL HB_Pointer
+_hb_alloc( HB_UInt   size,
+	   HB_Error *perror_ );
+
+HB_INTERNAL HB_Pointer
+_hb_realloc( HB_Pointer block,
+	     HB_UInt    new_size,
+	     HB_Error  *perror_ );
 
-#define IN_GLYPH( pos )        (buffer->in_string[(pos)].gindex)
-#define IN_ITEM( pos )         (&buffer->in_string[(pos)])
-#define IN_CURGLYPH()          (buffer->in_string[buffer->in_pos].gindex)
-#define IN_CURITEM()           (&buffer->in_string[buffer->in_pos])
-#define IN_PROPERTIES( pos )   (buffer->in_string[(pos)].properties)
-#define IN_LIGID( pos )        (buffer->in_string[(pos)].ligID)
-#define IN_COMPONENT( pos )    (buffer->in_string[(pos)].component)
-#define POSITION( pos )        (&buffer->positions[(pos)])
-#define OUT_GLYPH( pos )       (buffer->out_string[(pos)].gindex)
-#define OUT_ITEM( pos )        (&buffer->out_string[(pos)])
+HB_INTERNAL void
+_hb_free( HB_Pointer block );
 
-#define CHECK_Property( gdef, index, flags, property )              \
-          ( ( error = _HB_GDEF_Check_Property( (gdef), (index), (flags),     \
-                                      (property) ) ) != HB_Err_Ok )
 
-#define ADD_String( buffer, num_in, num_out, glyph_data, component, ligID )             \
-          ( ( error = hb_buffer_add_output_glyphs( (buffer),                           \
-						    (num_in), (num_out),                \
-                                                    (glyph_data), (component), (ligID)  \
-                                                  ) ) != HB_Err_Ok )
-#define ADD_Glyph( buffer, glyph_index, component, ligID )             		 	 \
-          ( ( error = hb_buffer_add_output_glyph( (buffer),                             \
-                                                    (glyph_index), (component), (ligID)  \
-                                                  ) ) != HB_Err_Ok )
+/* helper func to set a breakpoint on */
+HB_INTERNAL HB_Error
+_hb_err (HB_Error code);
 
-#define ERR(err) (err)
 
 HB_END_HEADER
 
diff --git a/src/harfbuzz-open-private.h b/src/harfbuzz-open-private.h
index 79859ce..05cea9e 100644
--- a/src/harfbuzz-open-private.h
+++ b/src/harfbuzz-open-private.h
@@ -4,7 +4,6 @@
  *  David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  *  Copyright 2006  Behdad Esfahbod
- *  Copyright 2007  Trolltech ASA
  *
  *  This is part of HarfBuzz, an OpenType Layout engine library.
  *
@@ -14,6 +13,7 @@
 #ifndef HARFBUZZ_OPEN_PRIVATE_H
 #define HARFBUZZ_OPEN_PRIVATE_H
 
+#include "harfbuzz-impl.h"
 #include "harfbuzz-open.h"
 #include "harfbuzz-gsub-private.h"
 #include "harfbuzz-gpos-private.h"
@@ -31,48 +31,56 @@ struct  HB_SubTable_
 };
 
 
-HB_Error  _HB_OPEN_Load_ScriptList( HB_ScriptList*  sl,
-			   HB_Stream     stream );
-HB_Error  _HB_OPEN_Load_FeatureList( HB_FeatureList*  fl,
+HB_INTERNAL HB_Error
+_HB_OPEN_Load_ScriptList( HB_ScriptList* sl,
+			   HB_Stream     input );
+HB_INTERNAL HB_Error
+_HB_OPEN_Load_FeatureList( HB_FeatureList* fl,
 			    HB_Stream         input );
-HB_Error  _HB_OPEN_Load_LookupList( HB_LookupList*  ll,
+HB_INTERNAL HB_Error
+_HB_OPEN_Load_LookupList( HB_LookupList*  ll,
 			   HB_Stream        input,
 			   HB_Type         type );
 
-HB_Error  _HB_OPEN_Load_Coverage( HB_Coverage*  c,
+HB_INTERNAL HB_Error
+_HB_OPEN_Load_Coverage( HB_Coverage* c,
 			 HB_Stream      input );
-HB_Error  _HB_OPEN_Load_ClassDefinition( HB_ClassDefinition*  cd,
+HB_INTERNAL HB_Error
+_HB_OPEN_Load_ClassDefinition( HB_ClassDefinition* cd,
 				HB_UShort             limit,
 				HB_Stream             input );
-HB_Error  _HB_OPEN_Load_EmptyClassDefinition( HB_ClassDefinition*  cd,
-				     HB_Stream             input );
-HB_Error _HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition*  cd,
+HB_INTERNAL HB_Error
+_HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition* cd,
 					       HB_UShort             limit,
 					       HB_UInt              class_offset,
 					       HB_UInt              base_offset,
-					       HB_Stream             stream );
-HB_Error  _HB_OPEN_Load_Device( HB_Device*  d,
+					       HB_Stream             input );
+HB_INTERNAL HB_Error
+_HB_OPEN_Load_Device( HB_Device* d,
 		       HB_Stream    input );
 
-void  _HB_OPEN_Free_ScriptList( HB_ScriptList*  sl);
-void  _HB_OPEN_Free_FeatureList( HB_FeatureList*  fl);
-void  _HB_OPEN_Free_LookupList( HB_LookupList*  ll,
+HB_INTERNAL void  _HB_OPEN_Free_ScriptList( HB_ScriptList*  sl );
+HB_INTERNAL void  _HB_OPEN_Free_FeatureList( HB_FeatureList*  fl );
+HB_INTERNAL void  _HB_OPEN_Free_LookupList( HB_LookupList*  ll,
 		       HB_Type         type );
 
-void  _HB_OPEN_Free_Coverage( HB_Coverage*  c );
-void  _HB_OPEN_Free_ClassDefinition( HB_ClassDefinition*  cd );
-void  _HB_OPEN_Free_Device( HB_Device*  d );
+HB_INTERNAL void  _HB_OPEN_Free_Coverage( HB_Coverage*  c );
+HB_INTERNAL void  _HB_OPEN_Free_ClassDefinition( HB_ClassDefinition*  cd );
+HB_INTERNAL void  _HB_OPEN_Free_Device( HB_Device*  d );
 
 
 
-HB_Error  _HB_OPEN_Coverage_Index( HB_Coverage*  c,
+HB_INTERNAL HB_Error
+_HB_OPEN_Coverage_Index( HB_Coverage* c,
 			  HB_UShort      glyphID,
 			  HB_UShort*     index );
-HB_Error  _HB_OPEN_Get_Class( HB_ClassDefinition*  cd,
+HB_INTERNAL HB_Error
+_HB_OPEN_Get_Class( HB_ClassDefinition* cd,
 		     HB_UShort             glyphID,
-		     HB_UShort*            class,
+		    HB_UShort*          klass,
 		     HB_UShort*            index );
-HB_Error  _HB_OPEN_Get_Device( HB_Device*  d,
+HB_INTERNAL HB_Error
+_HB_OPEN_Get_Device( HB_Device* d,
 		      HB_UShort    size,
 		      HB_Short*    value );
 
diff --git a/src/harfbuzz-open.c b/src/harfbuzz-open.c
index 80f046d..48305dd 100644
--- a/src/harfbuzz-open.c
+++ b/src/harfbuzz-open.c
@@ -116,7 +116,7 @@ static HB_Error  Load_Script( HB_ScriptTable*  s,
 
   if ( s->LangSysCount == 0 && s->DefaultLangSys.FeatureCount == 0 )
   {
-    error = ERR(HB_Err_Not_Covered);
+    error = HB_Err_Not_Covered;
     goto Fail2;
   }
 
@@ -184,7 +184,8 @@ static void  Free_Script( HB_ScriptTable*  s )
 
 /* ScriptList */
 
-HB_Error  _HB_OPEN_Load_ScriptList( HB_ScriptList*  sl,
+HB_INTERNAL HB_Error
+_HB_OPEN_Load_ScriptList( HB_ScriptList* sl,
 			   HB_Stream        stream )
 {
   HB_Error   error;
@@ -258,7 +259,8 @@ Fail:
 }
 
 
-void  _HB_OPEN_Free_ScriptList( HB_ScriptList*  sl )
+HB_INTERNAL void
+_HB_OPEN_Free_ScriptList( HB_ScriptList* sl )
 {
   HB_UShort          n, count;
 
@@ -334,7 +336,8 @@ static void  Free_Feature( HB_Feature*  f )
 
 /* FeatureList */
 
-HB_Error  _HB_OPEN_Load_FeatureList( HB_FeatureList*  fl,
+HB_INTERNAL HB_Error
+_HB_OPEN_Load_FeatureList( HB_FeatureList* fl,
 			    HB_Stream         stream )
 {
   HB_Error   error;
@@ -397,7 +400,8 @@ Fail2:
 }
 
 
-void  _HB_OPEN_Free_FeatureList( HB_FeatureList*  fl)
+HB_INTERNAL void
+_HB_OPEN_Free_FeatureList( HB_FeatureList*  fl )
 {
   HB_UShort           n, count;
 
@@ -557,7 +561,8 @@ static void  Free_Lookup( HB_Lookup*   l,
 
 /* LookupList */
 
-HB_Error  _HB_OPEN_Load_LookupList( HB_LookupList*  ll,
+HB_INTERNAL HB_Error
+_HB_OPEN_Load_LookupList( HB_LookupList* ll,
 			   HB_Stream        stream,
 			   HB_Type         type )
 {
@@ -617,7 +622,8 @@ Fail2:
 }
 
 
-void  _HB_OPEN_Free_LookupList( HB_LookupList*  ll,
+HB_INTERNAL void
+_HB_OPEN_Free_LookupList( HB_LookupList* ll,
 		       HB_Type         type )
 {
   HB_UShort    n, count;
@@ -754,7 +760,8 @@ static void  Free_Coverage2( HB_CoverageFormat2*  cf2 )
 }
 
 
-HB_Error  _HB_OPEN_Load_Coverage( HB_Coverage*  c,
+HB_INTERNAL HB_Error
+_HB_OPEN_Load_Coverage( HB_Coverage* c,
 			 HB_Stream      stream )
 {
   HB_Error   error;
@@ -768,31 +775,23 @@ HB_Error  _HB_OPEN_Load_Coverage( HB_Coverage*  c,
 
   switch ( c->CoverageFormat )
   {
-  case 1:
-    return Load_Coverage1( &c->cf.cf1, stream );
-
-  case 2:
-    return Load_Coverage2( &c->cf.cf2, stream );
-
-  default:
-    return ERR(HB_Err_Invalid_SubTable_Format);
+  case 1:  return Load_Coverage1( &c->cf.cf1, stream );
+  case 2:  return Load_Coverage2( &c->cf.cf2, stream );
+  default: return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;               /* never reached */
 }
 
 
-void  _HB_OPEN_Free_Coverage( HB_Coverage*  c)
+HB_INTERNAL void
+_HB_OPEN_Free_Coverage( HB_Coverage* c )
 {
   switch ( c->CoverageFormat )
   {
-  case 1:
-    Free_Coverage1( &c->cf.cf1 );
-    break;
-
-  case 2:
-    Free_Coverage2( &c->cf.cf2 );
-    break;
+  case 1:  Free_Coverage1( &c->cf.cf1 ); break;
+  case 2:  Free_Coverage2( &c->cf.cf2 ); break;
+  default:					 break;
   }
 }
 
@@ -897,20 +896,16 @@ static HB_Error  Coverage_Index2( HB_CoverageFormat2*  cf2,
 }
 
 
-HB_Error  _HB_OPEN_Coverage_Index( HB_Coverage*  c,
+HB_INTERNAL HB_Error
+_HB_OPEN_Coverage_Index( HB_Coverage* c,
 			  HB_UShort      glyphID,
 			  HB_UShort*     index )
 {
   switch ( c->CoverageFormat )
   {
-  case 1:
-    return Coverage_Index1( &c->cf.cf1, glyphID, index );
-
-  case 2:
-    return Coverage_Index2( &c->cf.cf2, glyphID, index );
-
-  default:
-    return ERR(HB_Err_Invalid_SubTable_Format);
+  case 1:  return Coverage_Index1( &c->cf.cf1, glyphID, index );
+  case 2:  return Coverage_Index2( &c->cf.cf2, glyphID, index );
+  default: return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;               /* never reached */
@@ -1014,7 +1009,8 @@ static HB_Error  Load_ClassDef2( HB_ClassDefinition*  cd,
   if ( ACCESS_Frame( 2L ) )
     return error;
 
-  count = cdf2->ClassRangeCount = GET_UShort();
+  count = GET_UShort();
+  cdf2->ClassRangeCount = 0; /* zero for now.  we fill with the number of good entries later */
 
   FORGET_Frame();
 
@@ -1040,14 +1036,21 @@ static HB_Error  Load_ClassDef2( HB_ClassDefinition*  cd,
     if ( crr[n].Start > crr[n].End ||
 	 crr[n].Class >= limit )
     {
-      error = ERR(HB_Err_Invalid_SubTable);
-      goto Fail;
+      /* XXX
+       * Corrupt entry.  Skip it.
+       * This is hit by Nafees Nastaliq font for example
+       */
+       n--;
+       count--;
     }
+    else
     d[crr[n].Class] = TRUE;
   }
 
   FORGET_Frame();
 
+  cdf2->ClassRangeCount = count;
+
   return HB_Err_Ok;
 
 Fail:
@@ -1065,13 +1068,13 @@ static void  Free_ClassDef2( HB_ClassDefFormat2*  cdf2 )
 
 /* ClassDefinition */
 
-HB_Error  _HB_OPEN_Load_ClassDefinition( HB_ClassDefinition*  cd,
+HB_INTERNAL HB_Error
+_HB_OPEN_Load_ClassDefinition( HB_ClassDefinition* cd,
 				HB_UShort             limit,
 				HB_Stream             stream )
 {
   HB_Error   error;
 
-
   if ( ALLOC_ARRAY( cd->Defined, limit, HB_Bool ) )
     return error;
 
@@ -1084,17 +1087,9 @@ HB_Error  _HB_OPEN_Load_ClassDefinition( HB_ClassDefinition*  cd,
 
   switch ( cd->ClassFormat )
   {
-  case 1:
-    error = Load_ClassDef1( cd, limit, stream );
-    break;
-
-  case 2:
-    error = Load_ClassDef2( cd, limit, stream );
-    break;
-
-  default:
-    error = ERR(HB_Err_Invalid_SubTable_Format);
-    break;
+  case 1:  error = Load_ClassDef1( cd, limit, stream ); break;
+  case 2:  error = Load_ClassDef2( cd, limit, stream ); break;
+  default: error = ERR(HB_Err_Invalid_SubTable_Format);	break;
   }
 
   if ( error )
@@ -1110,11 +1105,10 @@ Fail:
 }
 
 
-HB_Error  _HB_OPEN_Load_EmptyClassDefinition( HB_ClassDefinition*  cd,
-                                              HB_Stream             stream )
+static HB_Error
+_HB_OPEN_Load_EmptyClassDefinition( HB_ClassDefinition*  cd )
 {
   HB_Error   error;
-  HB_UNUSED(stream);
 
   if ( ALLOC_ARRAY( cd->Defined, 1, HB_Bool ) )
     return error;
@@ -1132,7 +1126,8 @@ Fail:
   return error;
 }
 
-HB_Error _HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition*  cd,
+HB_INTERNAL HB_Error
+_HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition* cd,
 					       HB_UShort             limit,
 					       HB_UInt              class_offset,
 					       HB_UInt              base_offset,
@@ -1149,7 +1144,7 @@ HB_Error _HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition*  cd,
 	error = _HB_OPEN_Load_ClassDefinition( cd, limit, stream );
     }
   else
-     error = _HB_OPEN_Load_EmptyClassDefinition ( cd, stream );
+     error = _HB_OPEN_Load_EmptyClassDefinition ( cd );
 
   if (error == HB_Err_Ok)
     (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */
@@ -1157,7 +1152,8 @@ HB_Error _HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition*  cd,
   return error;
 }
 
-void  _HB_OPEN_Free_ClassDefinition( HB_ClassDefinition*  cd )
+HB_INTERNAL void
+_HB_OPEN_Free_ClassDefinition( HB_ClassDefinition*  cd )
 {
   if ( !cd->loaded )
     return;
@@ -1166,20 +1162,16 @@ void  _HB_OPEN_Free_ClassDefinition( HB_ClassDefinition*  cd )
 
   switch ( cd->ClassFormat )
   {
-  case 1:
-    Free_ClassDef1( &cd->cd.cd1 );
-    break;
-
-  case 2:
-    Free_ClassDef2( &cd->cd.cd2 );
-    break;
+  case 1:  Free_ClassDef1( &cd->cd.cd1 ); break;
+  case 2:  Free_ClassDef2( &cd->cd.cd2 ); break;
+  default:				  break;
   }
 }
 
 
 static HB_Error  Get_Class1( HB_ClassDefFormat1*  cdf1,
 			     HB_UShort             glyphID,
-			     HB_UShort*            class,
+			     HB_UShort*            klass,
 			     HB_UShort*            index )
 {
   HB_UShort*  cva = cdf1->ClassValueArray;
@@ -1191,12 +1183,12 @@ static HB_Error  Get_Class1( HB_ClassDefFormat1*  cdf1,
   if ( glyphID >= cdf1->StartGlyph &&
        glyphID < cdf1->StartGlyph + cdf1->GlyphCount )
   {
-    *class = cva[glyphID - cdf1->StartGlyph];
+    *klass = cva[glyphID - cdf1->StartGlyph];
     return HB_Err_Ok;
   }
   else
   {
-    *class = 0;
+    *klass = 0;
     return HB_Err_Not_Covered;
   }
 }
@@ -1207,7 +1199,7 @@ static HB_Error  Get_Class1( HB_ClassDefFormat1*  cdf1,
 
 static HB_Error  Get_Class2( HB_ClassDefFormat2*  cdf2,
 			     HB_UShort             glyphID,
-			     HB_UShort*            class,
+			     HB_UShort*            klass,
 			     HB_UShort*            index )
 {
   HB_Error               error = HB_Err_Ok;
@@ -1220,7 +1212,7 @@ static HB_Error  Get_Class2( HB_ClassDefFormat2*  cdf2,
 
   if ( cdf2->ClassRangeCount == 0 )
     {
-      *class = 0;
+      *klass = 0;
       if ( index )
 	*index = 0;
       
@@ -1242,7 +1234,7 @@ static HB_Error  Get_Class2( HB_ClassDefFormat2*  cdf2,
 
     if ( glyphID >= crr[middle].Start && glyphID <= crr[middle].End )
     {
-      *class = crr[middle].Class;
+      *klass = crr[middle].Class;
       error  = HB_Err_Ok;
       break;
     }
@@ -1250,7 +1242,7 @@ static HB_Error  Get_Class2( HB_ClassDefFormat2*  cdf2,
     {
       if ( middle == min )
       {
-	*class = 0;
+	*klass = 0;
 	error  = HB_Err_Not_Covered;
 	break;
       }
@@ -1260,7 +1252,7 @@ static HB_Error  Get_Class2( HB_ClassDefFormat2*  cdf2,
     {
       if ( middle == max )
       {
-	*class = 0;
+	*klass = 0;
 	error  = HB_Err_Not_Covered;
 	break;
       }
@@ -1275,21 +1267,17 @@ static HB_Error  Get_Class2( HB_ClassDefFormat2*  cdf2,
 }
 
 
-HB_Error  _HB_OPEN_Get_Class( HB_ClassDefinition*  cd,
+HB_INTERNAL HB_Error
+_HB_OPEN_Get_Class( HB_ClassDefinition* cd,
 		     HB_UShort             glyphID,
-		     HB_UShort*            class,
+		    HB_UShort*          klass,
 		     HB_UShort*            index )
 {
   switch ( cd->ClassFormat )
   {
-  case 1:
-    return Get_Class1( &cd->cd.cd1, glyphID, class, index );
-
-  case 2:
-    return Get_Class2( &cd->cd.cd2, glyphID, class, index );
-
-  default:
-    return ERR(HB_Err_Invalid_SubTable_Format);
+  case 1:  return Get_Class1( &cd->cd.cd1, glyphID, klass, index );
+  case 2:  return Get_Class2( &cd->cd.cd2, glyphID, klass, index );
+  default: return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;               /* never reached */
@@ -1302,7 +1290,8 @@ HB_Error  _HB_OPEN_Get_Class( HB_ClassDefinition*  cd,
  ***************************/
 
 
-HB_Error  _HB_OPEN_Load_Device( HB_Device*  d,
+HB_INTERNAL HB_Error
+_HB_OPEN_Load_Device( HB_Device* d,
 		       HB_Stream    stream )
 {
   HB_Error   error;
@@ -1321,11 +1310,18 @@ HB_Error  _HB_OPEN_Load_Device( HB_Device*  d,
 
   FORGET_Frame();
 
+  d->DeltaValue = NULL;
+
   if ( d->StartSize > d->EndSize ||
        d->DeltaFormat == 0 || d->DeltaFormat > 3 )
-    return ERR(HB_Err_Invalid_SubTable);
-
-  d->DeltaValue = NULL;
+    {
+      /* XXX
+       * I've seen fontforge generate DeltaFormat == 0.
+       * Just return Ok and let the NULL DeltaValue disable
+       * this table.
+       */
+      return HB_Err_Ok;
+    }
 
   count = ( ( d->EndSize - d->StartSize + 1 ) >>
 	      ( 4 - d->DeltaFormat ) ) + 1;
@@ -1350,7 +1346,8 @@ HB_Error  _HB_OPEN_Load_Device( HB_Device*  d,
 }
 
 
-void  _HB_OPEN_Free_Device( HB_Device*  d )
+HB_INTERNAL void
+_HB_OPEN_Free_Device( HB_Device* d )
 {
   FREE( d->DeltaValue );
 }
@@ -1391,7 +1388,8 @@ void  _HB_OPEN_Free_Device( HB_Device*  d )
 
      mask = 0x00FF                                    */
 
-HB_Error  _HB_OPEN_Get_Device( HB_Device*  d,
+HB_INTERNAL HB_Error
+_HB_OPEN_Get_Device( HB_Device* d,
 		      HB_UShort    size,
 		      HB_Short*    value )
 {
diff --git a/src/harfbuzz-open.h b/src/harfbuzz-open.h
index a3287a3..29084bd 100644
--- a/src/harfbuzz-open.h
+++ b/src/harfbuzz-open.h
@@ -13,7 +13,7 @@
 #ifndef HARFBUZZ_OPEN_H
 #define HARFBUZZ_OPEN_H
 
-#include <harfbuzz-global.h>
+#include "harfbuzz-global.h"
 
 HB_BEGIN_HEADER
 
@@ -24,6 +24,7 @@ HB_BEGIN_HEADER
 
 #define HB_MAX_NESTING_LEVEL             100
 
+
 /* Script list related structures */
 
 struct  HB_LangSys_
diff --git a/src/harfbuzz-shaper.cpp b/src/harfbuzz-shaper.cpp
index 4638978..38017a7 100644
--- a/src/harfbuzz-shaper.cpp
+++ b/src/harfbuzz-shaper.cpp
@@ -11,8 +11,7 @@
 #include "harfbuzz-shaper.h"
 #include "harfbuzz-shaper-private.h"
 
-#include "harfbuzz-global.h"
-#include "harfbuzz-impl.h"
+#include "harfbuzz-stream-private.h"
 #include <assert.h>
 #include <stdio.h>
 
@@ -928,7 +927,7 @@ static HB_Stream getTableStream(void *font, HB_GetFontTableFunc tableFunc, HB_Ta
     stream->base = (HB_Byte*)malloc(length);
     error = tableFunc(font, tag, stream->base, &length);
     if (error) {
-        HB_close_stream(stream);
+        _hb_close_stream(stream);
         return 0;
     }
     stream->size = length;
@@ -972,16 +971,16 @@ HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc)
             //DEBUG("face doesn't have a gsub table");
         }
     }
-    HB_close_stream(stream);
+    _hb_close_stream(stream);
 
     stream = getTableStream(font, tableFunc, TTAG_GPOS);
     if (!stream || (error = HB_Load_GPOS_Table(stream, &face->gpos, face->gdef, gdefStream))) {
         face->gpos = 0;
         DEBUG("error loading gpos table: %d", error);
     }
-    HB_close_stream(stream);
+    _hb_close_stream(stream);
 
-    HB_close_stream(gdefStream);
+    _hb_close_stream(gdefStream);
 
     for (unsigned int i = 0; i < HB_ScriptCount; ++i)
         face->supported_scripts[i] = checkScript(face, i);
diff --git a/src/harfbuzz-shaper.h b/src/harfbuzz-shaper.h
index 864c3f4..16dcc87 100644
--- a/src/harfbuzz-shaper.h
+++ b/src/harfbuzz-shaper.h
@@ -10,11 +10,12 @@
 #ifndef HARFBUZZ_SHAPER_H
 #define HARFBUZZ_SHAPER_H
 
-#include <harfbuzz-global.h>
-#include <harfbuzz-gdef.h>
-#include <harfbuzz-gpos.h>
-#include <harfbuzz-gsub.h>
-#include <harfbuzz-external.h>
+#include "harfbuzz-global.h"
+#include "harfbuzz-gdef.h"
+#include "harfbuzz-gpos.h"
+#include "harfbuzz-gsub.h"
+#include "harfbuzz-external.h"
+#include "harfbuzz-stream-private.h"
 
 HB_BEGIN_HEADER
 
diff --git a/src/harfbuzz-stream-private.h b/src/harfbuzz-stream-private.h
new file mode 100644
index 0000000..14c7ff4
--- /dev/null
+++ b/src/harfbuzz-stream-private.h
@@ -0,0 +1,68 @@
+/*******************************************************************
+ *
+ *  Copyright 1996-2000 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ *  Copyright 2006  Behdad Esfahbod
+ *
+ *  This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ *  See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_STREAM_PRIVATE_H
+#define HARFBUZZ_STREAM_PRIVATE_H
+
+#include "harfbuzz-impl.h"
+#include "harfbuzz-stream.h"
+
+HB_BEGIN_HEADER
+
+HB_INTERNAL void
+_hb_close_stream( HB_Stream stream );
+
+HB_INTERNAL HB_Int
+_hb_stream_pos( HB_Stream stream );
+
+HB_INTERNAL HB_Error
+_hb_stream_seek( HB_Stream stream,
+                 HB_UInt   pos );
+
+HB_INTERNAL HB_Error
+_hb_stream_frame_enter( HB_Stream stream,
+                        HB_UInt   size );
+
+HB_INTERNAL void
+_hb_stream_frame_exit( HB_Stream stream );
+
+/* convenience macros */
+
+#define  SET_ERR(c)   ( (error = (c)) != 0 )
+
+#define  GOTO_Table(tag) (0)
+#define  FILE_Pos()      _hb_stream_pos( stream )
+#define  FILE_Seek(pos)  SET_ERR( _hb_stream_seek( stream, pos ) )
+#define  ACCESS_Frame(size)  SET_ERR( _hb_stream_frame_enter( stream, size ) )
+#define  FORGET_Frame()      _hb_stream_frame_exit( stream )
+
+#define  GET_Byte()      (*stream->cursor++)
+#define  GET_Short()     (stream->cursor += 2, (HB_Short)( \
+				(*(((HB_Byte*)stream->cursor)-2) << 8) | \
+				 *(((HB_Byte*)stream->cursor)-1) \
+			 ))
+#define  GET_Long()      (stream->cursor += 4, (HB_Int)( \
+				(*(((HB_Byte*)stream->cursor)-4) << 24) | \
+				(*(((HB_Byte*)stream->cursor)-3) << 16) | \
+				(*(((HB_Byte*)stream->cursor)-2) << 8) | \
+				 *(((HB_Byte*)stream->cursor)-1) \
+			 ))
+
+
+#define  GET_Char()      ((HB_Char)GET_Byte())
+#define  GET_UShort()    ((HB_UShort)GET_Short())
+#define  GET_ULong()     ((HB_UInt)GET_Long())
+#define  GET_Tag4()      GET_ULong()
+
+HB_END_HEADER
+
+#endif /* HARFBUZZ_STREAM_PRIVATE_H */
diff --git a/src/harfbuzz-stream.c b/src/harfbuzz-stream.c
index 19dd430..500bb41 100644
--- a/src/harfbuzz-stream.c
+++ b/src/harfbuzz-stream.c
@@ -1,14 +1,16 @@
 /*******************************************************************
  *
+ *  Copyright 2005  David Turner, The FreeType Project (www.freetype.org)
  *  Copyright 2007  Trolltech ASA
+ *  Copyright 2007  Red Hat, Inc
  *
  *  This is part of HarfBuzz, an OpenType Layout engine library.
  *
  *  See the file name COPYING for licensing information.
  *
  ******************************************************************/
-#include "harfbuzz-stream.h"
 #include "harfbuzz-impl.h"
+#include "harfbuzz-stream-private.h"
 #include <stdlib.h>
 
 #if 0
@@ -29,53 +31,67 @@ _hb_log( const char*   format, ... )
 #define  LOG(x)  do {} while (0)
 #endif
 
-void HB_close_stream(HB_Stream stream)
+HB_INTERNAL void
+_hb_close_stream( HB_Stream stream )
 {
-    if (!stream)
-        return;
-    free(stream->base);
-    free(stream);
+  if (!stream)
+      return;
+  free(stream->base);
+  free(stream);
 }
 
 
-HB_Int _hb_stream_pos(HB_Stream stream)
+HB_INTERNAL HB_Int
+_hb_stream_pos( HB_Stream stream )
 {
-  LOG(( "stream:pos() -> %ld\n", stream->pos ));
+  LOG(( "_hb_stream_pos() -> %ld\n", stream->pos ));
   return stream->pos;
 }
 
 
-HB_Error _hb_stream_seek(HB_Stream stream, HB_UInt pos)
+HB_INTERNAL HB_Error
+_hb_stream_seek( HB_Stream stream,
+		 HB_UInt pos )
 {
-    HB_Error  error = 0;
-    
-    stream->pos = pos;
-    if (pos > stream->size)
-        error = ERR(HB_Err_Read_Error);
-    
-    LOG(( "stream:seek(%ld) -> %d\n", pos, error ));
-    return error;
+  HB_Error  error = 0;
+
+  stream->pos = pos;
+  if (pos > stream->size)
+      error = ERR(HB_Err_Read_Error);
+
+  LOG(( "_hb_stream_seek(%ld) -> 0x%04X\n", pos, error ));
+  return error;
 }
 
 
-HB_Error _hb_stream_frame_enter(HB_Stream stream, HB_UInt count)
+HB_INTERNAL HB_Error
+_hb_stream_frame_enter( HB_Stream stream,
+			HB_UInt count )
 {
-    /* check current and new position */
-    if (stream->pos + count > stream->size) 
-        return ERR(HB_Err_Read_Error);
+  HB_Error  error = HB_Err_Ok;
+
+  /* check new position, watch for overflow */
+  if (HB_UNLIKELY (stream->pos + count > stream->size ||
+		   stream->pos + count < stream->pos))
+  {
+    error = ERR(HB_Err_Read_Error);
+    goto Exit;
+  }
 
-    /* set cursor */
-    stream->cursor = stream->base + stream->pos;
-    stream->pos   += count;
+  /* set cursor */
+  stream->cursor = stream->base + stream->pos;
+  stream->pos   += count;
 
-    LOG(( "stream:frame_enter(%ld) -> OK\n", count ));
-    return HB_Err_Ok;
+Exit:
+  LOG(( "_hb_stream_frame_enter(%ld) -> 0x%04X\n", count, error ));
+  return error;
 }
 
 
-void _hb_stream_frame_exit(HB_Stream  stream)
+HB_INTERNAL void
+_hb_stream_frame_exit( HB_Stream stream )
 {
   stream->cursor = NULL;
 
-  LOG(( "stream:frame_exit()\n" ));
+  LOG(( "_hb_stream_frame_exit()\n" ));
 }
diff --git a/src/harfbuzz-stream.h b/src/harfbuzz-stream.h
index c48b5a1..25489cd 100644
--- a/src/harfbuzz-stream.h
+++ b/src/harfbuzz-stream.h
@@ -11,7 +11,7 @@
 #ifndef HARFBUZZ_STREAM_H
 #define HARFBUZZ_STREAM_H
 
-#include <harfbuzz-global.h>
+#include "harfbuzz-global.h"
 
 HB_BEGIN_HEADER
 
@@ -24,40 +24,6 @@ typedef struct HB_StreamRec_
     HB_Byte*       cursor;
 } HB_StreamRec;
 
-void HB_close_stream(HB_Stream stream);
-
-
-/* stream macros used by the OpenType parser */
-#define  FILE_Pos()      stream->pos
-#define  FILE_Seek(pos)  (error = (_hb_stream_seek( stream, pos )))
-#define  ACCESS_Frame(size)  (error = (_hb_stream_frame_enter( stream, size ))) != 0
-#define  FORGET_Frame()      _hb_stream_frame_exit( stream )
-
-#define  GET_Byte()      (*stream->cursor++)
-#define  GET_Short()     (stream->cursor += 2, (HB_Short)( \
-                              (*((stream->cursor)-2) << 8) |    \
-                               *((stream->cursor)-1)             \
-                              ))
-#define  GET_Long()      (stream->cursor += 4, (HB_Int)( \
-				(*((stream->cursor)-4) << 24) | \
-				(*((stream->cursor)-3) << 16) | \
-				(*((stream->cursor)-2) << 8) | \
-				 *((stream->cursor)-1) \
-			 ))
-
-
-#define  GET_Char()      ((HB_Char)GET_Byte())
-#define  GET_UShort()    ((HB_UShort)GET_Short())
-#define  GET_ULong()     ((HB_UInt)GET_Long())
-#define  GET_Tag4()      GET_ULong()
-
-HB_Int _hb_stream_pos( HB_Stream stream );
-
-HB_Error _hb_stream_seek( HB_Stream stream, HB_UInt pos );
-
-HB_Error _hb_stream_frame_enter( HB_Stream stream, HB_UInt size );
-
-void _hb_stream_frame_exit( HB_Stream  stream );
 
 HB_END_HEADER
 
diff --git a/src/harfbuzz.c b/src/harfbuzz.c
index 123ffce..2646163 100644
--- a/src/harfbuzz.c
+++ b/src/harfbuzz.c
@@ -10,13 +10,11 @@
  *  See the file name COPYING for licensing information.
  *
  ******************************************************************/
-#include "harfbuzz-global.c"
-#include "harfbuzz-stream.c"
-#include "harfbuzz-open.c"
+#define HB_INTERNAL static
 #include "harfbuzz-buffer.c"
 #include "harfbuzz-gdef.c"
 #include "harfbuzz-gsub.c"
 #include "harfbuzz-gpos.c"
-#ifdef HARFBUZZ_DUMP
-#include "harfbuzz-dump.c"
-#endif
+#include "harfbuzz-impl.c"
+#include "harfbuzz-open.c"
+#include "harfbuzz-stream.c"
diff --git a/src/harfbuzz.h b/src/harfbuzz.h
index 208d6e4..79a293a 100644
--- a/src/harfbuzz.h
+++ b/src/harfbuzz.h
@@ -13,16 +13,13 @@
 #ifndef HARFBUZZ_H
 #define HARFBUZZ_H
 
-#include "harfbuzz-global.h"
 #include "harfbuzz-external.h"
-#include "harfbuzz-open.h"
+#include "harfbuzz-global.h"
 #include "harfbuzz-buffer.h"
 #include "harfbuzz-gdef.h"
 #include "harfbuzz-gsub.h"
 #include "harfbuzz-gpos.h"
-#ifdef HARFBUZZ_DUMP
-#include "harfbuzz-dump.h"
-#endif
+#include "harfbuzz-open.h"
 #include "harfbuzz-shaper.h"
 
 #endif /* HARFBUZZ_OPEN_H */
commit ca04be243edfc2c586cc50c408ffaf6bc38515ce
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Oct 25 15:16:09 2007 -0400

    improve error handling
    
    Call the now-noop macro ERR() at all error sites.  The only exceptions
    are HB_Err_Ok (always) and HB_Err_Not_Covered (in most places).
    
    Also remove many redundant error types:
    
      - Replaced by HB_Err_Invalid_SubTable_Format and HB_Err_Invalid_SubTable:
    
    	HB_Err_Invalid_GSUB_SubTable_Format
    	HB_Err_Invalid_GSUB_SubTable
    	HB_Err_Invalid_GPOS_SubTable_Format
    	HB_Err_Invalid_GPOS_SubTable
    	HB_Err_Invalid_GDEF_SubTable_Format
    	HB_Err_Invalid_GDEF_SubTable
    
        It's always clear, from the function called, which one was intended.
    
      - Replaced by HB_Err_Not_Covered, but calling ERR() too:
    
    	HB_Err_Too_Many_Nested_Contexts
    	HB_Err_No_MM_Interpreter
    
        This makes the fonts work better.
    
      - Replaced by HB_Err_Not_Covered:
    
    	HB_Err_Empty_Script
    	HB_Err_Table_Missing
    
        And update the few places they are checked for.
    
      - Replaced by HB_Err_Invalid_Argument:
    
    	HB_Err_Invalid_Face_Handle
    
        It's simply yet another invalid argument case.
    
      - Renamed to HB_Err_Read_Error:
    
    	HB_Err_Invalid_Stream_Operation

diff --git a/src/harfbuzz-dump-main.c b/src/harfbuzz-dump-main.c
index 7830d37..6a320a8 100644
--- a/src/harfbuzz-dump-main.c
+++ b/src/harfbuzz-dump-main.c
@@ -238,7 +238,7 @@ main (int argc, char **argv)
       if ((error = HB_Done_GSUB_Table (gsub)))
 	croak ("HB_Done_GSUB_Table", error);
     }
-  else if (error != HB_Err_Table_Missing)
+  else if (error != HB_Err_Not_Covered)
     fprintf (stderr, "HB_Load_GSUB_Table %x\n", error);
 
   if (!(error = HB_Load_GPOS_Table (face, &gpos, NULL)))
@@ -248,7 +248,7 @@ main (int argc, char **argv)
       if ((error = HB_Done_GPOS_Table (gpos)))
 	croak ("HB_Done_GPOS_Table", error);
     }
-  else if (error != HB_Err_Table_Missing)
+  else if (error != HB_Err_Not_Covered)
     fprintf (stderr, "HB_Load_GPOS_Table %x\n", error);
 
   printf ("</OpenType>\n");
diff --git a/src/harfbuzz-gdef.c b/src/harfbuzz-gdef.c
index 11a6dd6..edf1c33 100644
--- a/src/harfbuzz-gdef.c
+++ b/src/harfbuzz-gdef.c
@@ -106,7 +106,7 @@ HB_Error  HB_Init_GDEF_Extension( HB_Engine  engine )
 
 
   if ( !_engine )
-    return HB_Err_Invalid_Engine;
+    return ERR(HB_Err_Invalid_Engine);
 
   return  HB_Register_Extension( _engine,
 				 GDEF_ID,
@@ -135,7 +135,7 @@ HB_Error  HB_New_GDEF_Table( HB_GDEFHeader** retptr )
   HB_GDEFHeader*  gdef;
 
   if ( !retptr )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   if ( ALLOC( gdef, sizeof( *gdef ) ) )
     return error;
@@ -165,7 +165,7 @@ HB_Error  HB_Load_GDEF_Table( HB_Stream stream,
 
 
   if ( !retptr )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   if (( error = HB_New_GDEF_Table ( &gdef ) ))
     return error;
@@ -521,7 +521,7 @@ static HB_Error  Load_CaretValue( HB_CaretValue*  cv,
     break;
 
   default:
-    return HB_Err_Invalid_GDEF_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;
@@ -766,7 +766,7 @@ HB_Error  HB_GDEF_Get_Glyph_Property( HB_GDEFHeader*  gdef,
 
 
   if ( !gdef || !property )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   /* first, we check for mark attach classes */
 
@@ -871,7 +871,7 @@ HB_Error  HB_GDEF_Build_ClassDefinition( HB_GDEFHeader*  gdef,
 
 
   if ( !gdef || !glyph_array || !class_array )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   gcd = &gdef->GlyphClassDef;
 
@@ -893,7 +893,7 @@ HB_Error  HB_GDEF_Build_ClassDefinition( HB_GDEFHeader*  gdef,
 
   if ( curr_class >= 5 )
   {
-    error = HB_Err_Invalid_Argument;
+    error = ERR(HB_Err_Invalid_Argument);
     goto Fail4;
   }
 
@@ -914,7 +914,7 @@ HB_Error  HB_GDEF_Build_ClassDefinition( HB_GDEFHeader*  gdef,
       {
 	if ( curr_glyph == 0xFFFF )
 	{
-	  error = HB_Err_Invalid_Argument;
+	  error = ERR(HB_Err_Invalid_Argument);
 	  goto Fail3;
 	}
 	else
@@ -930,7 +930,7 @@ HB_Error  HB_GDEF_Build_ClassDefinition( HB_GDEFHeader*  gdef,
 
       if ( curr_glyph > glyph_array[n] )
       {
-	error = HB_Err_Invalid_Argument;
+	error = ERR(HB_Err_Invalid_Argument);
 	goto Fail3;
       }
 
@@ -940,7 +940,7 @@ HB_Error  HB_GDEF_Build_ClassDefinition( HB_GDEFHeader*  gdef,
 
       if ( curr_class >= 5 )
       {
-	error = HB_Err_Invalid_Argument;
+	error = ERR(HB_Err_Invalid_Argument);
 	goto Fail3;
       }
 
@@ -955,7 +955,7 @@ HB_Error  HB_GDEF_Build_ClassDefinition( HB_GDEFHeader*  gdef,
       {
 	if ( curr_glyph == 0xFFFF )
 	{
-	  error = HB_Err_Invalid_Argument;
+	  error = ERR(HB_Err_Invalid_Argument);
 	  goto Fail3;
 	}
 	else
@@ -1100,7 +1100,7 @@ HB_Error  _HB_GDEF_Add_Glyph_Property( HB_GDEFHeader*  gdef,
     break;
 
   default:
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
   }
 
   count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount;
diff --git a/src/harfbuzz-global.c b/src/harfbuzz-global.c
index 4021043..33d414d 100644
--- a/src/harfbuzz-global.c
+++ b/src/harfbuzz-global.c
@@ -9,6 +9,7 @@
  *
  ******************************************************************/
 #include "harfbuzz-global.h"
+#include "harfbuzz-impl.h"
 
 #if 0
 #include <stdio.h>
@@ -39,7 +40,7 @@ HB_Pointer _hb_alloc(HB_UInt   size,
   {
     block = malloc( size );
     if ( !block )
-      error = HB_Err_Out_Of_Memory;
+      error = ERR(HB_Err_Out_Of_Memory);
     else
       memset( (char*)block, 0, (size_t)size );
   }
@@ -59,7 +60,7 @@ HB_Pointer _hb_realloc(HB_Pointer  block,
 
     block2 = realloc( block, new_size );
     if ( block2 == NULL )
-        error = HB_Err_Out_Of_Memory;
+        error = ERR(HB_Err_Out_Of_Memory);
     else if ( new_size > old_size )
         memset( (char*)block2 + old_size, 0, (size_t)(new_size - old_size) );
 
diff --git a/src/harfbuzz-global.h b/src/harfbuzz-global.h
index 7910e96..156416f 100644
--- a/src/harfbuzz-global.h
+++ b/src/harfbuzz-global.h
@@ -62,24 +62,23 @@ typedef hb_uint32 HB_Tag;
 #endif
 
 typedef enum {
-    HB_Err_Ok = 0,
-    HB_Err_Invalid_Stream_Operation,
-    HB_Err_Invalid_Argument,
-    HB_Err_Out_Of_Memory,
-    HB_Err_Invalid_Face_Handle, 
-    HB_Err_Table_Missing,
-    HB_Err_Invalid_SubTable_Format  = 0x1000,
-    HB_Err_Invalid_SubTable         = 0x1001,
-    HB_Err_Not_Covered              = 0x1002,
-    HB_Err_Too_Many_Nested_Contexts = 0x1003,
-    HB_Err_No_MM_Interpreter        = 0x1004,
-    HB_Err_Empty_Script             = 0x1005,
-    HB_Err_Invalid_GSUB_SubTable_Format = 0x1010,
-    HB_Err_Invalid_GSUB_SubTable        = 0x1011,
-    HB_Err_Invalid_GPOS_SubTable_Format = 0x1020,
-    HB_Err_Invalid_GPOS_SubTable        = 0x1021,
-    HB_Err_Invalid_GDEF_SubTable_Format = 0x1030,
-    HB_Err_Invalid_GDEF_SubTable        = 0x1031
+  /* no error */
+  HB_Err_Ok                           = 0x0000,
+  HB_Err_Not_Covered                  = 0xFFFF,
+
+  /* _hb_err() is called whenever returning the following errors,
+   * and in a couple places for HB_Err_Not_Covered too. */
+
+  /* programmer error */
+  HB_Err_Invalid_Argument             = 0x1A66,
+
+  /* font error */
+  HB_Err_Invalid_SubTable_Format      = 0x157F,
+  HB_Err_Invalid_SubTable             = 0x1570,
+  HB_Err_Read_Error                   = 0x6EAD,
+
+  /* system error */
+  HB_Err_Out_Of_Memory                = 0xDEAD
 } HB_Error;
 
 typedef struct {
diff --git a/src/harfbuzz-gpos.c b/src/harfbuzz-gpos.c
index 8da4540..1479f9e 100644
--- a/src/harfbuzz-gpos.c
+++ b/src/harfbuzz-gpos.c
@@ -53,7 +53,7 @@ static HB_Error  default_mmfunc( HB_Font      font,
   HB_UNUSED(metric_id);
   HB_UNUSED(metric_value);
   HB_UNUSED(data);
-  return HB_Err_No_MM_Interpreter;
+  return ERR(HB_Err_Not_Covered);
 }
 
 
@@ -70,11 +70,8 @@ HB_Error  HB_Load_GPOS_Table( HB_Stream stream,
   HB_Error   error;
 
 
-  if ( !retptr )
-    return HB_Err_Invalid_Argument;
-
-  if ( !stream )
-    return HB_Err_Invalid_Face_Handle;
+  if ( !retptr || !stream )
+    return ERR(HB_Err_Invalid_Argument);
 
 
   base_offset = FILE_Pos();
@@ -654,7 +651,7 @@ static HB_Error  Load_Anchor( HB_Anchor*  an,
     break;
 
   default:
-    return HB_Err_Invalid_GPOS_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;
@@ -872,7 +869,7 @@ static HB_Error  Load_SinglePos( HB_GPOS_SubTable* st,
   FORGET_Frame();
 
   if ( !format )
-    return HB_Err_Invalid_GPOS_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
 
   cur_offset = FILE_Pos();
   if ( FILE_Seek( new_offset ) ||
@@ -913,7 +910,7 @@ static HB_Error  Load_SinglePos( HB_GPOS_SubTable* st,
     break;
 
   default:
-    return HB_Err_Invalid_GPOS_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;
@@ -1014,7 +1011,7 @@ static HB_Error  Lookup_SinglePos( GPOS_Instance*    gpi,
 
   case 2:
     if ( index >= sp->spf.spf2.ValueCount )
-      return HB_Err_Invalid_GPOS_SubTable;
+      return ERR(HB_Err_Invalid_SubTable);
     error = Get_ValueRecord( gpi, &sp->spf.spf2.Value[index],
 			     sp->ValueFormat, POSITION( buffer->in_pos ) );
     if ( error )
@@ -1022,7 +1019,7 @@ static HB_Error  Lookup_SinglePos( GPOS_Instance*    gpi,
     break;
 
   default:
-    return HB_Err_Invalid_GPOS_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
   }
 
   (buffer->in_pos)++;
@@ -1423,7 +1420,7 @@ static HB_Error  Load_PairPos( HB_GPOS_SubTable* st,
     break;
 
   default:
-    return HB_Err_Invalid_GPOS_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;
@@ -1473,11 +1470,11 @@ static HB_Error  Lookup_PairPos1( GPOS_Instance*       gpi,
 
 
   if ( index >= ppf1->PairSetCount )
-     return HB_Err_Invalid_GPOS_SubTable;
+     return ERR(HB_Err_Invalid_SubTable);
 
   pvr = ppf1->PairSet[index].PairValueRecord;
   if ( !pvr )
-    return HB_Err_Invalid_GPOS_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
 
   glyph2 = IN_CURGLYPH();
 
@@ -1525,7 +1522,7 @@ static HB_Error  Lookup_PairPos2( GPOS_Instance*       gpi,
 
   c1r = &ppf2->Class1Record[cl1];
   if ( !c1r )
-    return HB_Err_Invalid_GPOS_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
   c2r = &c1r->Class2Record[cl2];
 
   error = Get_ValueRecord( gpi, &c2r->Value1, format1, POSITION( first_pos ) );
@@ -1597,7 +1594,7 @@ static HB_Error  Lookup_PairPos( GPOS_Instance*    gpi,
     break;
 
   default:
-    return HB_Err_Invalid_GPOS_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   /* if we don't have coverage for the second glyph don't skip it for
@@ -1802,7 +1799,7 @@ static HB_Error  Lookup_CursivePos( GPOS_Instance*    gpi,
   }
 
   if ( index >= cp->EntryExitCount )
-    return HB_Err_Invalid_GPOS_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
 
   eer = &cp->EntryExitRecord[index];
 
@@ -2118,7 +2115,7 @@ static HB_Error  Load_MarkBasePos( HB_GPOS_SubTable* st,
   FORGET_Frame();
 
   if (mbp->PosFormat != 1)
-    return HB_Err_Invalid_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
 
   cur_offset = FILE_Pos();
   if ( FILE_Seek( new_offset ) ||
@@ -2265,18 +2262,18 @@ static HB_Error  Lookup_MarkBasePos( GPOS_Instance*    gpi,
   ma = &mbp->MarkArray;
 
   if ( mark_index >= ma->MarkCount )
-    return HB_Err_Invalid_GPOS_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
 
   class       = ma->MarkRecord[mark_index].Class;
   mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;
 
   if ( class >= mbp->ClassCount )
-    return HB_Err_Invalid_GPOS_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
 
   ba = &mbp->BaseArray;
 
   if ( base_index >= ba->BaseCount )
-    return HB_Err_Invalid_GPOS_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
 
   br          = &ba->BaseRecord[base_index];
   base_anchor = &br->BaseAnchor[class];
@@ -2676,18 +2673,18 @@ static HB_Error  Lookup_MarkLigPos( GPOS_Instance*    gpi,
   ma = &mlp->MarkArray;
 
   if ( mark_index >= ma->MarkCount )
-    return HB_Err_Invalid_GPOS_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
 
   class       = ma->MarkRecord[mark_index].Class;
   mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;
 
   if ( class >= mlp->ClassCount )
-    return HB_Err_Invalid_GPOS_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
 
   la = &mlp->LigatureArray;
 
   if ( lig_index >= la->LigatureCount )
-    return HB_Err_Invalid_GPOS_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
 
   lat = &la->LigatureAttach[lig_index];
 
@@ -3016,18 +3013,18 @@ static HB_Error  Lookup_MarkMarkPos( GPOS_Instance*    gpi,
   ma1 = &mmp->Mark1Array;
 
   if ( mark1_index >= ma1->MarkCount )
-    return HB_Err_Invalid_GPOS_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
 
   class        = ma1->MarkRecord[mark1_index].Class;
   mark1_anchor = &ma1->MarkRecord[mark1_index].MarkAnchor;
 
   if ( class >= mmp->ClassCount )
-    return HB_Err_Invalid_GPOS_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
 
   ma2 = &mmp->Mark2Array;
 
   if ( mark2_index >= ma2->Mark2Count )
-    return HB_Err_Invalid_GPOS_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
 
   m2r          = &ma2->Mark2Record[mark2_index];
   mark2_anchor = &m2r->Mark2Anchor[class];
@@ -3774,7 +3771,7 @@ static HB_Error  Load_ContextPos( HB_GPOS_SubTable* st,
     return Load_ContextPos3( &cp->cpf.cpf3, stream );
 
   default:
-    return HB_Err_Invalid_GPOS_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;               /* never reached */
@@ -3912,7 +3909,7 @@ static HB_Error  Lookup_ContextPos2( GPOS_Instance*          gpi,
   pcs = &cpf2->PosClassSet[classes[0]];
   if ( !pcs )
   {
-    error = HB_Err_Invalid_GPOS_SubTable;
+    error = ERR(HB_Err_Invalid_SubTable);
     goto End;
   }
 
@@ -4050,7 +4047,7 @@ static HB_Error  Lookup_ContextPos( GPOS_Instance*    gpi,
 			       flags, context_length, nesting_level );
 
   default:
-    return HB_Err_Invalid_GPOS_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;               /* never reached */
@@ -4622,31 +4619,6 @@ static void  Free_ChainPosClassSet( HB_ChainPosClassSet*  cpcs )
 }
 
 
-static HB_Error GPOS_Load_EmptyOrClassDefinition( HB_ClassDefinition*  cd,
-					     HB_UShort             limit,
-					     HB_UInt              class_offset,
-					     HB_UInt              base_offset,
-					     HB_Stream             stream )
-{
-  HB_Error error;
-  HB_UInt               cur_offset;
-
-  cur_offset = FILE_Pos();
-
-  if ( class_offset )
-    {
-      if ( !FILE_Seek( class_offset + base_offset ) )
-	error = _HB_OPEN_Load_ClassDefinition( cd, limit, stream );
-    }
-  else
-     error = _HB_OPEN_Load_EmptyClassDefinition ( cd, stream );
-
-  if (error == HB_Err_Ok)
-    (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */
-
-  return error;
-}
-
 /* ChainContextPosFormat2 */
 
 static HB_Error  Load_ChainContextPos2( HB_ChainContextPosFormat2*  ccpf2,
@@ -4691,17 +4663,17 @@ static HB_Error  Load_ChainContextPos2( HB_ChainContextPosFormat2*  ccpf2,
 
   FORGET_Frame();
 
-  if ( ( error = GPOS_Load_EmptyOrClassDefinition( &ccpf2->BacktrackClassDef, 65535,
-					      backtrack_offset, base_offset,
-					      stream ) ) != HB_Err_Ok )
+  if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->BacktrackClassDef, 65535,
+						       backtrack_offset, base_offset,
+						       stream ) ) != HB_Err_Ok )
     goto Fail5;
-  if ( ( error = GPOS_Load_EmptyOrClassDefinition( &ccpf2->InputClassDef, count,
-					      input_offset, base_offset,
-					      stream ) ) != HB_Err_Ok )
+  if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->InputClassDef, count,
+						       input_offset, base_offset,
+						       stream ) ) != HB_Err_Ok )
     goto Fail4;
-  if ( ( error = GPOS_Load_EmptyOrClassDefinition( &ccpf2->LookaheadClassDef, 65535,
-					      lookahead_offset, base_offset,
-					      stream ) ) != HB_Err_Ok )
+  if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->LookaheadClassDef, 65535,
+						       lookahead_offset, base_offset,
+						       stream ) ) != HB_Err_Ok )
     goto Fail3;
 
   ccpf2->ChainPosClassSet   = NULL;
@@ -5032,7 +5004,7 @@ static HB_Error  Load_ChainContextPos( HB_GPOS_SubTable* st,
     return Load_ChainContextPos3( &ccp->ccpf.ccpf3, stream );
 
   default:
-    return HB_Err_Invalid_GPOS_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;               /* never reached */
@@ -5252,7 +5224,7 @@ static HB_Error  Lookup_ChainContextPos2(
   cpcs = &ccpf2->ChainPosClassSet[input_classes[0]];
   if ( !cpcs )
   {
-    error = HB_Err_Invalid_GPOS_SubTable;
+    error = ERR(HB_Err_Invalid_SubTable);
     goto End1;
   }
 
@@ -5530,7 +5502,7 @@ static HB_Error  Lookup_ChainContextPos(
 				    nesting_level );
 
   default:
-    return HB_Err_Invalid_GPOS_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;               /* never reached */
@@ -5555,7 +5527,7 @@ HB_Error  HB_GPOS_Select_Script( HB_GPOSHeader*  gpos,
 
 
   if ( !gpos || !script_index )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   sl = &gpos->ScriptList;
   sr = sl->ScriptRecord;
@@ -5588,13 +5560,13 @@ HB_Error  HB_GPOS_Select_Language( HB_GPOSHeader*  gpos,
 
 
   if ( !gpos || !language_index || !req_feature_index )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   sl = &gpos->ScriptList;
   sr = sl->ScriptRecord;
 
   if ( script_index >= sl->ScriptCount )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   s   = &sr[script_index].Script;
   lsr = s->LangSysRecord;
@@ -5636,7 +5608,7 @@ HB_Error  HB_GPOS_Select_Feature( HB_GPOSHeader*  gpos,
 
 
   if ( !gpos || !feature_index )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   sl = &gpos->ScriptList;
   sr = sl->ScriptRecord;
@@ -5645,7 +5617,7 @@ HB_Error  HB_GPOS_Select_Feature( HB_GPOSHeader*  gpos,
   fr = fl->FeatureRecord;
 
   if ( script_index >= sl->ScriptCount )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   s   = &sr[script_index].Script;
   lsr = s->LangSysRecord;
@@ -5655,7 +5627,7 @@ HB_Error  HB_GPOS_Select_Feature( HB_GPOSHeader*  gpos,
   else
   {
     if ( language_index >= s->LangSysCount )
-      return HB_Err_Invalid_Argument;
+      return ERR(HB_Err_Invalid_Argument);
 
     ls = &lsr[language_index].LangSys;
   }
@@ -5665,7 +5637,7 @@ HB_Error  HB_GPOS_Select_Feature( HB_GPOSHeader*  gpos,
   for ( n = 0; n < ls->FeatureCount; n++ )
   {
     if ( fi[n] >= fl->FeatureCount )
-      return HB_Err_Invalid_GPOS_SubTable_Format;
+      return ERR(HB_Err_Invalid_SubTable_Format);
 
     if ( feature_tag == fr[fi[n]].FeatureTag )
     {
@@ -5694,7 +5666,7 @@ HB_Error  HB_GPOS_Query_Scripts( HB_GPOSHeader*  gpos,
 
 
   if ( !gpos || !script_tag_list )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   sl = &gpos->ScriptList;
   sr = sl->ScriptRecord;
@@ -5728,13 +5700,13 @@ HB_Error  HB_GPOS_Query_Languages( HB_GPOSHeader*  gpos,
 
 
   if ( !gpos || !language_tag_list )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   sl = &gpos->ScriptList;
   sr = sl->ScriptRecord;
 
   if ( script_index >= sl->ScriptCount )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   s   = &sr[script_index].Script;
   lsr = s->LangSysRecord;
@@ -5777,7 +5749,7 @@ HB_Error  HB_GPOS_Query_Features( HB_GPOSHeader*  gpos,
 
 
   if ( !gpos || !feature_tag_list )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   sl = &gpos->ScriptList;
   sr = sl->ScriptRecord;
@@ -5786,7 +5758,7 @@ HB_Error  HB_GPOS_Query_Features( HB_GPOSHeader*  gpos,
   fr = fl->FeatureRecord;
 
   if ( script_index >= sl->ScriptCount )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   s   = &sr[script_index].Script;
   lsr = s->LangSysRecord;
@@ -5796,7 +5768,7 @@ HB_Error  HB_GPOS_Query_Features( HB_GPOSHeader*  gpos,
   else
   {
     if ( language_index >= s->LangSysCount )
-      return HB_Err_Invalid_Argument;
+      return ERR(HB_Err_Invalid_Argument);
 
     ls = &lsr[language_index].LangSys;
   }
@@ -5811,7 +5783,7 @@ HB_Error  HB_GPOS_Query_Features( HB_GPOSHeader*  gpos,
     if ( fi[n] >= fl->FeatureCount )
     {
       FREE( ftl );
-      return HB_Err_Invalid_GPOS_SubTable_Format;
+      return ERR(HB_Err_Invalid_SubTable_Format);
     }
     ftl[n] = fr[fi[n]].FeatureTag;
   }
@@ -5861,7 +5833,7 @@ static HB_Error  GPOS_Do_Glyph_Lookup( GPOS_Instance*    gpi,
   nesting_level++;
 
   if ( nesting_level > HB_MAX_NESTING_LEVEL )
-    return HB_Err_Too_Many_Nested_Contexts;
+    return ERR(HB_Err_Not_Covered);
 
   lookup_count = gpos->LookupList.LookupCount;
   if (lookup_index >= lookup_count)
@@ -5898,7 +5870,7 @@ static HB_Error  Load_DefaultPos( HB_GPOS_SubTable* st,
 {
   HB_UNUSED(st);
   HB_UNUSED(stream);
-  return HB_Err_Invalid_GPOS_SubTable_Format;
+  return ERR(HB_Err_Invalid_SubTable_Format);
 }
 
 typedef HB_Error  (*Load_Pos_Func_Type)( HB_GPOS_SubTable* st,
@@ -6061,7 +6033,7 @@ HB_Error  HB_GPOS_Add_Feature( HB_GPOSHeader*  gpos,
   if ( !gpos ||
        feature_index >= gpos->FeatureList.FeatureCount ||
        gpos->FeatureList.ApplyCount == gpos->FeatureList.FeatureCount )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   gpos->FeatureList.ApplyOrder[gpos->FeatureList.ApplyCount++] = feature_index;
 
@@ -6091,7 +6063,7 @@ HB_Error  HB_GPOS_Clear_Features( HB_GPOSHeader*  gpos )
 
 
   if ( !gpos )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   gpos->FeatureList.ApplyCount = 0;
 
@@ -6110,7 +6082,7 @@ HB_Error  HB_GPOS_Register_MM_Function( HB_GPOSHeader*  gpos,
 					void*            data )
 {
   if ( !gpos )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   gpos->mmfunc = mmfunc;
   gpos->data   = data;
@@ -6136,7 +6108,7 @@ HB_Error  HB_GPOS_Apply_String( HB_Font            font,
 
   if ( !font || !gpos ||
        !buffer || buffer->in_length == 0 || buffer->in_pos >= buffer->in_length )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   gpi.font       = font;
   gpi.gpos       = gpos;
diff --git a/src/harfbuzz-gsub.c b/src/harfbuzz-gsub.c
index 5cdd801..6375a5d 100644
--- a/src/harfbuzz-gsub.c
+++ b/src/harfbuzz-gsub.c
@@ -40,7 +40,7 @@ HB_Error  HB_Load_GSUB_Table( HB_Stream stream,
   HB_GSUBHeader*  gsub;
 
   if ( !retptr )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   base_offset = FILE_Pos();
 
@@ -232,7 +232,7 @@ static HB_Error  Load_SingleSubst( HB_GSUB_SubTable* st,
     break;
 
   default:
-    return HB_Err_Invalid_GSUB_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;
@@ -299,14 +299,14 @@ static HB_Error  Lookup_SingleSubst( HB_GSUBHeader*   gsub,
 
   case 2:
     if ( index >= ss->ssf.ssf2.GlyphCount )
-      return HB_Err_Invalid_GSUB_SubTable;
+      return ERR(HB_Err_Invalid_SubTable);
     value = ss->ssf.ssf2.Substitute[index];
     if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) )
       return error;
     break;
 
   default:
-    return HB_Err_Invalid_GSUB_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
   }
 
   if ( gdef && gdef->NewGlyphClasses )
@@ -496,7 +496,7 @@ static HB_Error  Lookup_MultipleSubst( HB_GSUBHeader*    gsub,
     return error;
 
   if ( index >= ms->SequenceCount )
-    return HB_Err_Invalid_GSUB_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
 
   count = ms->Sequence[index].GlyphCount;
   s     = ms->Sequence[index].Substitute;
@@ -975,7 +975,7 @@ static HB_Error  Lookup_LigatureSubst( HB_GSUBHeader*    gsub,
     return error;
 
   if ( index >= ls->LigatureSetCount )
-     return HB_Err_Invalid_GSUB_SubTable;
+     return ERR(HB_Err_Invalid_SubTable);
 
   lig = ls->LigatureSet[index].Ligature;
 
@@ -1807,7 +1807,7 @@ static HB_Error  Load_ContextSubst( HB_GSUB_SubTable* st,
     return Load_ContextSubst3( &cs->csf.csf3, stream );
 
   default:
-    return HB_Err_Invalid_GSUB_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;               /* never reached */
@@ -1942,7 +1942,7 @@ static HB_Error  Lookup_ContextSubst2( HB_GSUBHeader*          gsub,
   scs = &csf2->SubClassSet[classes[0]];
   if ( !scs )
   {
-    error = HB_Err_Invalid_GSUB_SubTable;
+    error = ERR(HB_Err_Invalid_SubTable);
     goto End;
   }
 
@@ -2079,7 +2079,7 @@ static HB_Error  Lookup_ContextSubst( HB_GSUBHeader*    gsub,
 				 flags, context_length, nesting_level );
 
   default:
-    return HB_Err_Invalid_GSUB_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;               /* never reached */
@@ -2652,31 +2652,6 @@ static void  Free_ChainSubClassSet( HB_ChainSubClassSet*  cscs )
   }
 }
 
-static HB_Error GSUB_Load_EmptyOrClassDefinition( HB_ClassDefinition*  cd,
-					     HB_UShort             limit,
-					     HB_UInt              class_offset,
-					     HB_UInt              base_offset,
-					     HB_Stream             stream )
-{
-  HB_Error error;
-  HB_UInt               cur_offset;
-
-  cur_offset = FILE_Pos();
-
-  if ( class_offset )
-    {
-      if ( !FILE_Seek( class_offset + base_offset ) )
-	error = _HB_OPEN_Load_ClassDefinition( cd, limit, stream );
-    }
-  else
-     error = _HB_OPEN_Load_EmptyClassDefinition ( cd, stream );
-
-  if (error == HB_Err_Ok)
-    (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */
-
-  return error;
-}
-
 
 /* ChainContextSubstFormat2 */
 
@@ -2723,18 +2698,18 @@ static HB_Error  Load_ChainContextSubst2(
 
   FORGET_Frame();
 
-  if ( ( error = GSUB_Load_EmptyOrClassDefinition( &ccsf2->BacktrackClassDef, 65535,
-					      backtrack_offset, base_offset,
-					      stream ) ) != HB_Err_Ok )
+  if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->BacktrackClassDef, 65535,
+						       backtrack_offset, base_offset,
+						       stream ) ) != HB_Err_Ok )
       goto Fail5;
 
-  if ( ( error = GSUB_Load_EmptyOrClassDefinition( &ccsf2->InputClassDef, count,
-					      input_offset, base_offset,
-					      stream ) ) != HB_Err_Ok )
+  if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->InputClassDef, count,
+						       input_offset, base_offset,
+						       stream ) ) != HB_Err_Ok )
       goto Fail4;
-  if ( ( error = GSUB_Load_EmptyOrClassDefinition( &ccsf2->LookaheadClassDef, 65535,
-					      lookahead_offset, base_offset,
-					      stream ) ) != HB_Err_Ok )
+  if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->LookaheadClassDef, 65535,
+						       lookahead_offset, base_offset,
+						       stream ) ) != HB_Err_Ok )
     goto Fail3;
 
   ccsf2->ChainSubClassSet   = NULL;
@@ -3066,7 +3041,7 @@ static HB_Error  Load_ChainContextSubst( HB_GSUB_SubTable* st,
     return Load_ChainContextSubst3( &ccs->ccsf.ccsf3, stream );
 
   default:
-    return HB_Err_Invalid_GSUB_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;               /* never reached */
@@ -3282,7 +3257,7 @@ static HB_Error  Lookup_ChainContextSubst2( HB_GSUBHeader*               gsub,
   cscs = &ccsf2->ChainSubClassSet[input_classes[0]];
   if ( !cscs )
   {
-    error = HB_Err_Invalid_GSUB_SubTable;
+    error = ERR(HB_Err_Invalid_SubTable);
     goto End1;
   }
 
@@ -3557,7 +3532,7 @@ static HB_Error  Lookup_ChainContextSubst( HB_GSUBHeader*    gsub,
 				      nesting_level );
 
   default:
-    return HB_Err_Invalid_GSUB_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;               /* never reached */
@@ -3588,7 +3563,7 @@ static HB_Error  Load_ReverseChainContextSubst( HB_GSUB_SubTable* st,
   rccs->SubstFormat = GET_UShort();
 
   if ( rccs->SubstFormat != 1 )
-    return HB_Err_Invalid_GSUB_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
 
   FORGET_Frame();
 
@@ -3863,7 +3838,7 @@ HB_Error  HB_GSUB_Select_Script( HB_GSUBHeader*  gsub,
 
 
   if ( !gsub || !script_index )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   sl = &gsub->ScriptList;
   sr = sl->ScriptRecord;
@@ -3896,13 +3871,13 @@ HB_Error  HB_GSUB_Select_Language( HB_GSUBHeader*  gsub,
 
 
   if ( !gsub || !language_index || !req_feature_index )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   sl = &gsub->ScriptList;
   sr = sl->ScriptRecord;
 
   if ( script_index >= sl->ScriptCount )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   s   = &sr[script_index].Script;
   lsr = s->LangSysRecord;
@@ -3944,7 +3919,7 @@ HB_Error  HB_GSUB_Select_Feature( HB_GSUBHeader*  gsub,
 
 
   if ( !gsub || !feature_index )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   sl = &gsub->ScriptList;
   sr = sl->ScriptRecord;
@@ -3953,7 +3928,7 @@ HB_Error  HB_GSUB_Select_Feature( HB_GSUBHeader*  gsub,
   fr = fl->FeatureRecord;
 
   if ( script_index >= sl->ScriptCount )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   s   = &sr[script_index].Script;
   lsr = s->LangSysRecord;
@@ -3963,7 +3938,7 @@ HB_Error  HB_GSUB_Select_Feature( HB_GSUBHeader*  gsub,
   else
   {
     if ( language_index >= s->LangSysCount )
-      return HB_Err_Invalid_Argument;
+      return ERR(HB_Err_Invalid_Argument);
 
     ls = &lsr[language_index].LangSys;
   }
@@ -3973,7 +3948,7 @@ HB_Error  HB_GSUB_Select_Feature( HB_GSUBHeader*  gsub,
   for ( n = 0; n < ls->FeatureCount; n++ )
   {
     if ( fi[n] >= fl->FeatureCount )
-      return HB_Err_Invalid_GSUB_SubTable_Format;
+      return ERR(HB_Err_Invalid_SubTable_Format);
 
     if ( feature_tag == fr[fi[n]].FeatureTag )
     {
@@ -4002,7 +3977,7 @@ HB_Error  HB_GSUB_Query_Scripts( HB_GSUBHeader*  gsub,
 
 
   if ( !gsub || !script_tag_list )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
 
   sl = &gsub->ScriptList;
@@ -4037,13 +4012,13 @@ HB_Error  HB_GSUB_Query_Languages( HB_GSUBHeader*  gsub,
 
 
   if ( !gsub || !language_tag_list )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   sl = &gsub->ScriptList;
   sr = sl->ScriptRecord;
 
   if ( script_index >= sl->ScriptCount )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   s   = &sr[script_index].Script;
   lsr = s->LangSysRecord;
@@ -4086,7 +4061,7 @@ HB_Error  HB_GSUB_Query_Features( HB_GSUBHeader*  gsub,
 
 
   if ( !gsub || !feature_tag_list )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   sl = &gsub->ScriptList;
   sr = sl->ScriptRecord;
@@ -4095,7 +4070,7 @@ HB_Error  HB_GSUB_Query_Features( HB_GSUBHeader*  gsub,
   fr = fl->FeatureRecord;
 
   if ( script_index >= sl->ScriptCount )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   s   = &sr[script_index].Script;
   lsr = s->LangSysRecord;
@@ -4105,7 +4080,7 @@ HB_Error  HB_GSUB_Query_Features( HB_GSUBHeader*  gsub,
   else
   {
     if ( language_index >= s->LangSysCount )
-      return HB_Err_Invalid_Argument;
+      return ERR(HB_Err_Invalid_Argument);
 
     ls = &lsr[language_index].LangSys;
   }
@@ -4120,7 +4095,7 @@ HB_Error  HB_GSUB_Query_Features( HB_GSUBHeader*  gsub,
     if ( fi[n] >= fl->FeatureCount )
     {
       FREE( ftl );
-      return HB_Err_Invalid_GSUB_SubTable_Format;
+      return ERR(HB_Err_Invalid_SubTable_Format);
     }
     ftl[n] = fr[fi[n]].FeatureTag;
   }
@@ -4172,7 +4147,7 @@ static HB_Error  GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub,
   nesting_level++;
 
   if ( nesting_level > HB_MAX_NESTING_LEVEL )
-    return HB_Err_Too_Many_Nested_Contexts;
+    return ERR(HB_Err_Not_Covered);
 
   lookup_count = gsub->LookupList.LookupCount;
   if (lookup_index >= lookup_count)
@@ -4211,7 +4186,7 @@ static HB_Error  Load_DefaultSubst( HB_GSUB_SubTable* st,
   HB_UNUSED(st);
   HB_UNUSED(stream);
 
-  return HB_Err_Invalid_GSUB_SubTable_Format;
+  return ERR(HB_Err_Invalid_SubTable_Format);
 }
 
 typedef HB_Error  (*Load_Subst_Func_Type)( HB_GSUB_SubTable* st,
@@ -4373,7 +4348,7 @@ HB_Error  HB_GSUB_Add_Feature( HB_GSUBHeader*  gsub,
   if ( !gsub ||
        feature_index >= gsub->FeatureList.FeatureCount ||
        gsub->FeatureList.ApplyCount == gsub->FeatureList.FeatureCount )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   gsub->FeatureList.ApplyOrder[gsub->FeatureList.ApplyCount++] = feature_index;
 
@@ -4403,7 +4378,7 @@ HB_Error  HB_GSUB_Clear_Features( HB_GSUBHeader*  gsub )
 
 
   if ( !gsub )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   gsub->FeatureList.ApplyCount = 0;
 
@@ -4422,7 +4397,7 @@ HB_Error  HB_GSUB_Register_Alternate_Function( HB_GSUBHeader*  gsub,
 					       void*            data )
 {
   if ( !gsub )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   gsub->altfunc = altfunc;
   gsub->data    = data;
@@ -4440,7 +4415,7 @@ HB_Error  HB_GSUB_Apply_String( HB_GSUBHeader*   gsub,
 
   if ( !gsub ||
        !buffer || buffer->in_length == 0 || buffer->in_pos >= buffer->in_length )
-    return HB_Err_Invalid_Argument;
+    return ERR(HB_Err_Invalid_Argument);
 
   lookup_count = gsub->LookupList.LookupCount;
 
diff --git a/src/harfbuzz-impl.h b/src/harfbuzz-impl.h
index b731cfe..bfada40 100644
--- a/src/harfbuzz-impl.h
+++ b/src/harfbuzz-impl.h
@@ -73,6 +73,7 @@ HB_BEGIN_HEADER
                                                     (glyph_index), (component), (ligID)  \
                                                   ) ) != HB_Err_Ok )
 
+#define ERR(err) (err)
 
 HB_END_HEADER
 
diff --git a/src/harfbuzz-open-private.h b/src/harfbuzz-open-private.h
index c38b745..79859ce 100644
--- a/src/harfbuzz-open-private.h
+++ b/src/harfbuzz-open-private.h
@@ -46,6 +46,11 @@ HB_Error  _HB_OPEN_Load_ClassDefinition( HB_ClassDefinition*  cd,
 				HB_Stream             input );
 HB_Error  _HB_OPEN_Load_EmptyClassDefinition( HB_ClassDefinition*  cd,
 				     HB_Stream             input );
+HB_Error _HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition*  cd,
+					       HB_UShort             limit,
+					       HB_UInt              class_offset,
+					       HB_UInt              base_offset,
+					       HB_Stream             stream );
 HB_Error  _HB_OPEN_Load_Device( HB_Device*  d,
 		       HB_Stream    input );
 
diff --git a/src/harfbuzz-open.c b/src/harfbuzz-open.c
index ffb5250..80f046d 100644
--- a/src/harfbuzz-open.c
+++ b/src/harfbuzz-open.c
@@ -116,7 +116,7 @@ static HB_Error  Load_Script( HB_ScriptTable*  s,
 
   if ( s->LangSysCount == 0 && s->DefaultLangSys.FeatureCount == 0 )
   {
-    error = HB_Err_Empty_Script;
+    error = ERR(HB_Err_Not_Covered);
     goto Fail2;
   }
 
@@ -230,7 +230,7 @@ HB_Error  _HB_OPEN_Load_ScriptList( HB_ScriptList*  sl,
     error = Load_Script( &sr[sl->ScriptCount].Script, stream );
     if ( error == HB_Err_Ok )
       sl->ScriptCount += 1;
-    else if ( error != HB_Err_Empty_Script )
+    else if ( error != HB_Err_Not_Covered )
       goto Fail;
 
     (void)FILE_Seek( cur_offset );
@@ -242,7 +242,7 @@ HB_Error  _HB_OPEN_Load_ScriptList( HB_ScriptList*  sl,
 #if 0
   if ( sl->ScriptCount == 0 )
   {
-    error = HB_Err_Invalid_SubTable;
+    error = ERR(HB_Err_Invalid_SubTable);
     goto Fail;
   }
 #endif
@@ -733,7 +733,7 @@ static HB_Error  Load_Coverage2( HB_CoverageFormat2*  cf2,
 	 ( rr[n].End - rr[n].Start + (long)rr[n].StartCoverageIndex ) >=
 	   0x10000L )
     {
-      error = HB_Err_Invalid_SubTable;
+      error = ERR(HB_Err_Invalid_SubTable);
       goto Fail;
     }
   }
@@ -775,7 +775,7 @@ HB_Error  _HB_OPEN_Load_Coverage( HB_Coverage*  c,
     return Load_Coverage2( &c->cf.cf2, stream );
 
   default:
-    return HB_Err_Invalid_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;               /* never reached */
@@ -910,7 +910,7 @@ HB_Error  _HB_OPEN_Coverage_Index( HB_Coverage*  c,
     return Coverage_Index2( &c->cf.cf2, glyphID, index );
 
   default:
-    return HB_Err_Invalid_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;               /* never reached */
@@ -952,7 +952,7 @@ static HB_Error  Load_ClassDef1( HB_ClassDefinition*  cd,
   /* sanity check; we are limited to 16bit integers */
 
   if ( cdf1->StartGlyph + (long)count >= 0x10000L )
-    return HB_Err_Invalid_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
 
   cdf1->ClassValueArray = NULL;
 
@@ -970,7 +970,7 @@ static HB_Error  Load_ClassDef1( HB_ClassDefinition*  cd,
     cva[n] = GET_UShort();
     if ( cva[n] >= limit )
     {
-      error = HB_Err_Invalid_SubTable;
+      error = ERR(HB_Err_Invalid_SubTable);
       goto Fail;
     }
     d[cva[n]] = TRUE;
@@ -1040,7 +1040,7 @@ static HB_Error  Load_ClassDef2( HB_ClassDefinition*  cd,
     if ( crr[n].Start > crr[n].End ||
 	 crr[n].Class >= limit )
     {
-      error = HB_Err_Invalid_SubTable;
+      error = ERR(HB_Err_Invalid_SubTable);
       goto Fail;
     }
     d[crr[n].Class] = TRUE;
@@ -1093,7 +1093,7 @@ HB_Error  _HB_OPEN_Load_ClassDefinition( HB_ClassDefinition*  cd,
     break;
 
   default:
-    error = HB_Err_Invalid_SubTable_Format;
+    error = ERR(HB_Err_Invalid_SubTable_Format);
     break;
   }
 
@@ -1132,6 +1132,31 @@ Fail:
   return error;
 }
 
+HB_Error _HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition*  cd,
+					       HB_UShort             limit,
+					       HB_UInt              class_offset,
+					       HB_UInt              base_offset,
+					       HB_Stream             stream )
+{
+  HB_Error error;
+  HB_UInt               cur_offset;
+
+  cur_offset = FILE_Pos();
+
+  if ( class_offset )
+    {
+      if ( !FILE_Seek( class_offset + base_offset ) )
+	error = _HB_OPEN_Load_ClassDefinition( cd, limit, stream );
+    }
+  else
+     error = _HB_OPEN_Load_EmptyClassDefinition ( cd, stream );
+
+  if (error == HB_Err_Ok)
+    (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */
+
+  return error;
+}
+
 void  _HB_OPEN_Free_ClassDefinition( HB_ClassDefinition*  cd )
 {
   if ( !cd->loaded )
@@ -1264,7 +1289,7 @@ HB_Error  _HB_OPEN_Get_Class( HB_ClassDefinition*  cd,
     return Get_Class2( &cd->cd.cd2, glyphID, class, index );
 
   default:
-    return HB_Err_Invalid_SubTable_Format;
+    return ERR(HB_Err_Invalid_SubTable_Format);
   }
 
   return HB_Err_Ok;               /* never reached */
@@ -1298,7 +1323,7 @@ HB_Error  _HB_OPEN_Load_Device( HB_Device*  d,
 
   if ( d->StartSize > d->EndSize ||
        d->DeltaFormat == 0 || d->DeltaFormat > 3 )
-    return HB_Err_Invalid_SubTable;
+    return ERR(HB_Err_Invalid_SubTable);
 
   d->DeltaValue = NULL;
 
diff --git a/src/harfbuzz-shaper.cpp b/src/harfbuzz-shaper.cpp
index 6dfa65d..4638978 100644
--- a/src/harfbuzz-shaper.cpp
+++ b/src/harfbuzz-shaper.cpp
@@ -966,7 +966,7 @@ HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc)
     stream = getTableStream(font, tableFunc, TTAG_GSUB);
     if (!stream || (error = HB_Load_GSUB_Table(stream, &face->gsub, face->gdef, gdefStream))) {
         face->gsub = 0;
-        if (error != HB_Err_Table_Missing) {
+        if (error != HB_Err_Not_Covered) {
             //DEBUG("error loading gsub table: %d", error);
         } else {
             //DEBUG("face doesn't have a gsub table");
diff --git a/src/harfbuzz-stream.c b/src/harfbuzz-stream.c
index ba0dc59..19dd430 100644
--- a/src/harfbuzz-stream.c
+++ b/src/harfbuzz-stream.c
@@ -8,6 +8,7 @@
  *
  ******************************************************************/
 #include "harfbuzz-stream.h"
+#include "harfbuzz-impl.h"
 #include <stdlib.h>
 
 #if 0
@@ -50,7 +51,7 @@ HB_Error _hb_stream_seek(HB_Stream stream, HB_UInt pos)
     
     stream->pos = pos;
     if (pos > stream->size)
-        error = HB_Err_Invalid_Stream_Operation;
+        error = ERR(HB_Err_Read_Error);
     
     LOG(( "stream:seek(%ld) -> %d\n", pos, error ));
     return error;
@@ -61,7 +62,7 @@ HB_Error _hb_stream_frame_enter(HB_Stream stream, HB_UInt count)
 {
     /* check current and new position */
     if (stream->pos + count > stream->size) 
-        return HB_Err_Invalid_Stream_Operation;
+        return ERR(HB_Err_Read_Error);
 
     /* set cursor */
     stream->cursor = stream->base + stream->pos;



More information about the HarfBuzz mailing list