shithub: freetype+ttf2subf

Download patch

ref: 9748807412ba3b3f43675d85739fd479626f10d2
parent: 48721c11b549480e9d3eaa3671866d9aa9d01ab1
author: David Turner <[email protected]>
date: Tue Aug 22 18:36:33 EDT 2000

the psaux module is now nearly completed
the "type1z" driver uses it to parse Type 1 charstrings
(not to parse the Type 1 token stream yet though)..

git/fs: mount .git/fs: mount/attach disallowed
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -337,14 +337,6 @@
 
   /*************************************************************************/
   /*                                                                       */
-  /* T1_MAX_STACK_DEPTH is the maximal depth of the token stack used by    */
-  /* the Type 1 parser (see t1load.c).  A minimum of 16 is required.       */
-  /*                                                                       */
-#define T1_MAX_STACK_DEPTH  16
-
-
-  /*************************************************************************/
-  /*                                                                       */
   /* T1_MAX_DICT_DEPTH is the maximal depth of nest dictionaries and       */
   /* arrays in the Type 1 stream (see t1load.c).  A minimum of 4 is        */
   /* required.                                                             */
@@ -363,9 +355,9 @@
   /*************************************************************************/
   /*                                                                       */
   /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity.        */
+  /* A minimum of 16 is required..                                         */
   /*                                                                       */
 #define T1_MAX_CHARSTRINGS_OPERANDS  32
-
 
   /*************************************************************************/
   /*                                                                       */
--- a/include/freetype/internal/ftdebug.h
+++ b/include/freetype/internal/ftdebug.h
@@ -84,6 +84,10 @@
     trace_t1load,
     trace_t1objs,
 
+    /* Postcript helper module 'psaux' */
+    trace_t1decode,
+    trace_psobjs,
+
     /* experimental Type 1 driver components */
     trace_z1driver,
     trace_z1gload,
--- a/include/freetype/internal/psaux.h
+++ b/include/freetype/internal/psaux.h
@@ -22,8 +22,8 @@
 
 
 #include <freetype/internal/ftobjs.h>
+#include <freetype/internal/t1types.h>
 
-
 #ifdef __cplusplus
   extern "C" {
 #endif
@@ -419,6 +419,7 @@
     FT_Bool          path_begun;
     FT_Bool          load_points;
     FT_Bool          no_recurse;
+    FT_Bool          shift;
 
     FT_Error         error;         /* only used for memory errors */
     FT_Bool          metrics_only;
@@ -427,7 +428,7 @@
 
 
   typedef FT_Error  (*T1_Builder_Check_Points_Func) ( T1_Builder*  builder,
-                                                      FT_Int       count );
+                                                     FT_Int       count );
                                                       
   typedef void      (*T1_Builder_Add_Point_Func)    ( T1_Builder*  builder,
                                                       FT_Pos       x,
@@ -434,7 +435,7 @@
                                                       FT_Pos       y,
                                                       FT_Byte      flag );    
   
-  typedef void      (*T1_Builder_Add_Point1_Func)   ( T1_Builder*  builder,
+  typedef FT_Error  (*T1_Builder_Add_Point1_Func)   ( T1_Builder*  builder,
                                                       FT_Pos       x,
                                                       FT_Pos       y );
                                                     
@@ -465,9 +466,106 @@
   
   } T1_Builder_Funcs;
 
+
   /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
+  /*****                         T1 DECODER                            *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+#if 0
+#define T1_MAX_CHARSTRINGS_OPERANDS   64
+#define T1_MAX_SUBRS_CALLS            16
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine   */
+  /* calls during glyph loading.                                           */
+  /*                                                                       */
+#define T1_MAX_SUBRS_CALLS  8
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity.        */
+  /* A minimum of 16 is required..                                         */
+  /*                                                                       */
+#define T1_MAX_CHARSTRINGS_OPERANDS  32
+#endif
+
+
+
+  typedef struct T1_Decoder_Zone_
+  {
+    FT_Byte*  cursor;
+    FT_Byte*  base;
+    FT_Byte*  limit;
+    
+  } T1_Decoder_Zone;
+
+
+  typedef struct T1_Decoder_        T1_Decoder;
+  typedef struct T1_Decoder_Funcs_  T1_Decoder_Funcs;
+
+  typedef  FT_Error  (*T1_Decoder_Parse_Func)( T1_Decoder*  decoder,
+                                               FT_UInt      glyph_index );
+
+  struct T1_Decoder_
+  {
+    T1_Builder               builder;
+
+    FT_Long                  stack[T1_MAX_CHARSTRINGS_OPERANDS];
+    FT_Long*                 top;
+
+    T1_Decoder_Zone          zones[T1_MAX_SUBRS_CALLS + 1];
+    T1_Decoder_Zone*         zone;
+
+    PSNames_Interface*       psnames;      /* for seac */
+    FT_UInt                  num_glyphs;
+    FT_Byte**                glyph_names;
+
+    FT_UInt                  lenIV;        /* internal for sub routine calls */
+    FT_UInt                  num_subrs;
+    FT_Byte**                subrs;
+    FT_Int*                  subrs_len;    /* array of subrs length (optional) */
+
+    FT_Matrix                font_matrix;
+
+    FT_Int                   flex_state;
+    FT_Int                   num_flex_vectors;
+    FT_Vector                flex_vectors[7];
+
+    T1_Blend*                blend;       /* for multiple master support */
+    
+    const T1_Decoder_Funcs*  funcs;
+    T1_Decoder_Parse_Func    parse_glyph;  
+  };
+
+
+  struct T1_Decoder_Funcs_
+  {
+    FT_Error     (*init)             ( T1_Decoder*            decoder,
+                                       FT_Face                face,
+                                       FT_Size                size,
+                                       FT_GlyphSlot           slot,
+                                       FT_Byte**              glyph_names,
+                                       T1_Blend*              blend,
+                                       T1_Decoder_Parse_Func  parse );
+    
+    void         (*done)             ( T1_Decoder*  decoder );
+    
+    FT_Error     (*parse_charstrings)( T1_Decoder*  decoder,
+                                       FT_Byte*     base,
+                                       FT_UInt      len );
+    
+  
+  };
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
   /*****                        PSAux Module Interface                 *****/
   /*****                                                               *****/
   /*************************************************************************/
@@ -478,6 +576,7 @@
     const PS_Table_Funcs*   t1_table_funcs;
     const T1_Parser_Funcs*  t1_parser_funcs;
     const T1_Builder_Funcs* t1_builder_funcs;
+    const T1_Decoder_Funcs* t1_decoder_funcs;
 
     void                  (*t1_decrypt)( FT_Byte*   buffer,
                                          FT_Int     length,
--- a/include/freetype/internal/t1types.h
+++ b/include/freetype/internal/t1types.h
@@ -165,6 +165,7 @@
     FT_FaceRec     root;
     T1_Font        type1;
     void*          psnames;
+    void*          psaux;
     void*          afm_data;
     FT_CharMapRec  charmaprecs[2];
     FT_CharMap     charmaps[2];
--- a/src/base/ftglyph.c
+++ b/src/base/ftglyph.c
@@ -859,335 +859,7 @@
   }
 
 
-#if 0
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /****                                                                 ****/
-  /****   EXPERIMENTAL EMBOLDENING/OUTLINING SUPPORT                    ****/
-  /****                                                                 ****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-  /* Compute the norm of a vector */
-
-#ifdef FT_CONFIG_OPTION_OLD_CALCS
-
-  static
-  FT_Pos  ft_norm( FT_Vector*  vec )
-  {
-    FT_Int64  t1, t2;
-
-
-    MUL_64( vec->x, vec->x, t1 );
-    MUL_64( vec->y, vec->y, t2 );
-    ADD_64( t1, t2, t1 );
-
-    return (FT_Pos)SQRT_64( t1 );
-  }
-
-#else /* FT_CONFIG_OPTION_OLD_CALCS */
-
-  static
-  FT_Pos  ft_norm( FT_Vector*  vec )
-  {
-    FT_F26Dot6  u, v, d;
-    FT_Int      shift;
-    FT_ULong    H, L, L2, hi, lo, med;
-
-
-    u = vec->x; if ( u < 0 ) u = -u;
-    v = vec->y; if ( v < 0 ) v = -v;
-
-    if ( u < v )
-    {
-      d = u;
-      u = v;
-      v = d;
-    }
-
-    /* check that we are not trying to normalize zero! */
-    if ( u == 0 )
-      return 0;
-
-    /* compute (u*u + v*v) on 64 bits with two 32-bit registers [H:L] */
-    hi  = (FT_ULong)u >> 16;
-    lo  = (FT_ULong)u & 0xFFFF;
-    med = hi * lo;
-
-    H     = hi * hi + ( med >> 15 );
-    med <<= 17;
-    L     = lo * lo + med;
-    if ( L < med )
-      H++;
-
-    hi  = (FT_ULong)v >> 16;
-    lo  = (FT_ULong)v & 0xFFFF;
-    med = hi * lo;
-
-    H    += hi * hi + ( med >> 15 );
-    med <<= 17;
-    L2    = lo * lo + med;
-    if ( L2 < med )
-      H++;
-
-    L += L2;
-    if ( L < L2 )
-      H++;
-
-    /* if the value is smaller than 32 bits */
-    shift = 0;
-    if ( H == 0 )
-    {
-      while ( ( L & 0xC0000000UL ) == 0 )
-      {
-        L <<= 2;
-        shift++;
-      }
-      return ( FT_Sqrt32( L ) >> shift );
-    }
-    else
-    {
-      while ( H )
-      {
-        L   = ( L >> 2 ) | ( H << 30 );
-        H >>= 2;
-        shift++;
-      }
-      return ( FT_Sqrt32( L ) << shift );
-    }
-  }
-
-#endif /* FT_CONFIG_OPTION_OLD_CALCS */
-
-
-  static
-  int  ft_test_extrema( FT_Outline*  outline,
-                        int          n )
-  {
-    FT_Vector  *prev, *cur, *next;
-    FT_Pos      product;
-    FT_Int      first, last;
-
-
-    /* we need to compute the `previous' and `next' point */
-    /* for these extrema.                                 */
-    cur   = outline->points + n;
-    prev  = cur - 1;
-    next  = cur + 1;
-
-    first = 0;
-    for ( c = 0; c < outline->n_contours; c++ )
-    {
-      last  = outline->contours[c];
-
-      if ( n == first )
-        prev = outline->points + last;
-
-      if ( n == last )
-        next = outline->points + first;
-
-      first = last + 1;
-    }
-
-    product = FT_MulDiv( cur->x - prev->x,   /* in.x  */
-                         next->y - cur->y,   /* out.y */
-                         0x40 )
-              -
-              FT_MulDiv( cur->y - prev->y,   /* in.y  */
-                         next->x - cur->x,   /* out.x */
-                         0x40 );
-
-    if ( product )
-      product = product > 0 ? 1 : -1;
-
-    return product;
-  }
-
-
-  /* Compute the orientation of path filling.  It differs between TrueType */
-  /* and Type1 formats.  We could use the `ft_outline_reverse_fill' flag,  */
-  /* but it is better to re-compute it directly (it seems that this flag   */
-  /* isn't correctly set for some weird composite glyphs currently).       */
-  /*                                                                       */
-  /* We do this by computing bounding box points, and computing their      */
-  /* curvature.                                                            */
-  /*                                                                       */
-  /* The function returns either 1 or -1.                                  */
-  /*                                                                       */
-  static
-  int  ft_get_orientation( FT_Outline*  outline )
-  {
-    FT_BBox  box;
-    FT_BBox  indices;
-    int      n, last;
-
-
-    indices.xMin = -1;
-    indices.yMin = -1;
-    indices.xMax = -1;
-    indices.yMax = -1;
-
-    box.xMin = box.yMin = 32767;
-    box.xMax = box.yMax = -32768;
-
-    /* is it empty ? */
-    if ( outline->n_contours < 1 )
-      return 1;
-
-    last = outline->contours[outline->n_contours - 1];
-
-    for ( n = 0; n <= last; n++ )
-    {
-      FT_Pos  x, y;
-
-
-      x = outline->points[n].x;
-      if ( x < box.xMin )
-      {
-        box.xMin     = x;
-        indices.xMin = n;
-      }
-      if ( x > box.xMax )
-      {
-        box.xMax     = x;
-        indices.xMax = n;
-      }
-
-      y = outline->points[n].y;
-      if ( y < box.yMin )
-      {
-        box.yMin     = y;
-        indices.yMin = n;
-      }
-      if ( y > box.yMax )
-      {
-        box.yMax     = y;
-        indices.yMax = n;
-      }
-    }
-
-    /* test orientation of the xmin */
-    n = ft_test_extrema( outline, indices.xMin );
-    if (n) goto Exit;
-    
-    n = ft_test_extrema( outline, indices.yMin );
-    if (n) goto Exit;
-    
-    n = ft_test_extrema( outline, indices.xMax );
-    if (n) goto Exit;
-    
-    n = ft_test_extrema( outline, indices.yMax );
-    if (!n)
-      n = 1;
-
-  Exit:
-    return n;
-  }
-
-
-  static
-  FT_Error  ft_embolden( FT_Face      original,
-                         FT_Outline*  outline,
-                         FT_Pos*      advance )
-  {
-    FT_Vector  u, v;
-    FT_Vector* points;
-    FT_Vector  cur, prev, next;
-    FT_Pos     distance;
-    int        c, n, first, orientation;
-
-    FT_UNUSED( advance );
-
-
-    /* compute control distance */
-    distance = FT_MulFix( original->em_size / 60,
-                          original->size->metrics.y_scale );
-
-    orientation = ft_get_orientation( &original->glyph->outline );
-
-    points = original->glyph->outline.points;
-
-    first = 0;
-    for ( c = 0; c < outline->n_contours; c++ )
-    {
-      int  last = outline->contours[c];
-
-
-      prev = points[last];
-
-      for ( n = first; n <= last; n++ )
-      {
-        FT_Pos     norm, delta, d;
-        FT_Vector  in, out;
-
-
-        cur = points[n];
-        if ( n < last ) next = points[n + 1];
-        else            next = points[first];
-
-        /* compute the in and out vectors */
-        in.x  = cur.x - prev.x;
-        in.y  = cur.y - prev.y;
-
-        out.x = next.x - cur.x;
-        out.y = next.y - cur.y;
-
-        /* compute U and V */
-        norm = ft_norm( &in );
-        u.x = orientation *  FT_DivFix( in.y, norm );
-        u.y = orientation * -FT_DivFix( in.x, norm );
-
-        norm = ft_norm( &out );
-        v.x = orientation *  FT_DivFix( out.y, norm );
-        v.y = orientation * -FT_DivFix( out.x, norm );
-
-        d = distance;
-
-        if ( ( outline->flags[n] & FT_Curve_Tag_On ) == 0 )
-          d *= 2;
-
-        /* Check discriminant for parallel vectors */
-        delta = FT_MulFix( u.x, v.y ) - FT_MulFix( u.y, v.x );
-        if ( delta > FT_BOLD_THRESHOLD || delta < -FT_BOLD_THRESHOLD )
-        {
-          /* Move point -- compute A and B */
-          FT_Pos  x, y, A, B;
-
-
-          A = d + FT_MulFix( cur.x, u.x ) + FT_MulFix( cur.y, u.y );
-          B = d + FT_MulFix( cur.x, v.x ) + FT_MulFix( cur.y, v.y );
-
-          x = FT_MulFix( A, v.y ) - FT_MulFix( B, u.y );
-          y = FT_MulFix( B, u.x ) - FT_MulFix( A, v.x );
-
-          outline->points[n].x = distance + FT_DivFix( x, delta );
-          outline->points[n].y = distance + FT_DivFix( y, delta );
-        }
-        else
-        {
-          /* Vectors are nearly parallel */
-          FT_Pos  x, y;
-
-
-          x = distance + cur.x + FT_MulFix( d, u.x + v.x ) / 2;
-          y = distance + cur.y + FT_MulFix( d, u.y + v.y ) / 2;
-
-          outline->points[n].x = x;
-          outline->points[n].y = y;
-        }
-
-        prev = cur;
-      }
-
-      first = last + 1;
-    }
-
-    if ( advance )
-      *advance = ( *advance + distance * 4 ) & -64;
-
-    return 0;
-  }
+#if 1
 
 #endif /* 0 -- EXPERIMENTAL STUFF! */
 
--- a/src/cid/cidgload.c
+++ b/src/cid/cidgload.c
@@ -33,7 +33,6 @@
 #include <freetype/internal/ftstream.h>
 #include <freetype/ftoutln.h>
 
-
   /*************************************************************************/
   /*                                                                       */
   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
--- /dev/null
+++ b/src/psaux/module.mk
@@ -1,0 +1,7 @@
+make_module_list: add_psaux_module
+
+add_psaux_module:
+	$(OPEN_DRIVER)psaux_module_class$(CLOSE_DRIVER)
+	$(ECHO_DRIVER)psaux     $(ECHO_DRIVER_DESC)Postscript Type 1 & Type 2 helper module$(ECHO_DRIVER_DONE)
+
+# EOF
--- /dev/null
+++ b/src/psaux/psaux.c
@@ -1,0 +1,16 @@
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#ifdef FT_FLAT_COMPILE
+
+#include "psobjs.c"
+#include "psmodule.c"
+#include "t1decode.c"
+
+#else
+
+#include <psaux/psobjs.c>
+#include <psaux/psmodule.c>
+#include <psaux/t1decode.c>
+
+#endif
+
--- /dev/null
+++ b/src/psaux/psmodule.c
@@ -1,0 +1,82 @@
+#include <psaux/psmodule.h>
+#include <psaux/psobjs.h>
+#include <psaux/t1decode.h>
+
+  static
+  const PS_Table_Funcs    ps_table_funcs =
+  {
+    PS_Table_New,
+    PS_Table_Done,
+    PS_Table_Add,
+    PS_Table_Release
+  };
+
+
+  static
+  const T1_Parser_Funcs   t1_parser_funcs =
+  {
+    T1_Init_Parser,
+    T1_Done_Parser,
+    T1_Skip_Spaces,
+    T1_Skip_Alpha,
+    T1_ToInt,
+    T1_ToFixed,
+    T1_ToCoordArray,
+    T1_ToFixedArray,
+    T1_ToToken,
+    T1_ToTokenArray,
+    T1_Load_Field,
+    T1_Load_Field_Table
+  };
+
+
+  static
+  const T1_Builder_Funcs  t1_builder_funcs =
+  {
+    T1_Builder_Init,
+    T1_Builder_Done,
+    T1_Builder_Check_Points,
+    T1_Builder_Add_Point,
+    T1_Builder_Add_Point1,
+    T1_Builder_Add_Contour,
+    T1_Builder_Start_Point,
+    T1_Builder_Close_Contour
+  };
+
+
+  static
+  const T1_Decoder_Funcs  t1_decoder_funcs =
+  {
+    T1_Decoder_Init,
+    T1_Decoder_Done,
+    T1_Decoder_Parse_Charstrings
+  };
+
+
+  static
+  const PSAux_Interface   psaux_interface =
+  {
+    &ps_table_funcs,
+    &t1_parser_funcs,
+    &t1_builder_funcs,
+    &t1_decoder_funcs,
+    
+    T1_Decrypt
+  };
+
+
+  FT_CPLUSPLUS(const FT_Module_Class)  psaux_module_class =
+  {
+    0,
+    sizeof( FT_ModuleRec ),
+    "psaux",
+    0x10000L,
+    0x20000L,
+    
+    &psaux_interface,  /* module-specific interface */
+    
+    (FT_Module_Constructor)  0,
+    (FT_Module_Destructor)   0,
+    (FT_Module_Requester)    0
+  };
+
--- /dev/null
+++ b/src/psaux/psmodule.h
@@ -1,0 +1,16 @@
+#ifndef PSMODULE_H
+#define PSMODULE_H
+
+#include <freetype/ftmodule.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+  FT_EXPORT_VAR( const FT_Module_Class )  psaux_driver_class;
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* PSMODULE_H */
--- a/src/psaux/psobjs.c
+++ b/src/psaux/psobjs.c
@@ -229,7 +229,7 @@
     FT_Memory  memory = table->memory;
 
 
-    if ( table->init == 0xDEADBEEFL )
+    if ( (FT_ULong)table->init == 0xDEADBEEFUL )
     {
       FREE( table->block );
       FREE( table->elements );
@@ -1133,9 +1133,13 @@
       FT_Vector*  point   = outline->points + outline->n_points;
       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
 
-
-      point->x = x >> 16;
-      point->y = y >> 16;
+      if (builder->shift)
+      {
+        x >>= 16;
+        y >>= 16;
+      }
+      point->x = x;
+      point->y = y;
       *control = flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic;
 
       builder->last = *point;
--- /dev/null
+++ b/src/psaux/rules.mk
@@ -1,0 +1,70 @@
+#
+# FreeType 2 PSAUX driver configuration rules
+#
+
+
+# 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.
+
+
+# PSAUX driver directory
+#
+PSAUX_DIR  := $(SRC_)psaux
+PSAUX_DIR_ := $(PSAUX_DIR)$(SEP)
+
+
+# compilation flags for the driver
+#
+PSAUX_COMPILE := $(FT_COMPILE)
+
+
+# PSAUX driver sources (i.e., C files)
+#
+PSAUX_DRV_SRC := $(PSAUX_DIR_)psobjs.c   \
+                 $(PSAUX_DIR_)t1decode.c \
+                 $(PSAUX_DIR_)psmodule.c
+
+# PSAUX driver headers
+#
+PSAUX_DRV_H := $(PSAUX_DRV_SRC:%c=%h)
+
+
+# PSAUX driver object(s)
+#
+#   PSAUX_DRV_OBJ_M is used during `multi' builds.
+#   PSAUX_DRV_OBJ_S is used during `single' builds.
+#
+PSAUX_DRV_OBJ_M := $(PSAUX_DRV_SRC:$(PSAUX_DIR_)%.c=$(OBJ_)%.$O)
+PSAUX_DRV_OBJ_S := $(OBJ_)psaux.$O
+
+# PSAUX driver source file for single build
+#
+PSAUX_DRV_SRC_S := $(PSAUX_DIR_)psaux.c
+
+
+# PSAUX driver - single object
+#
+$(PSAUX_DRV_OBJ_S): $(PSAUX_DRV_SRC_S) $(PSAUX_DRV_SRC) \
+                   $(FREETYPE_H) $(PSAUX_DRV_H)
+	$(PSAUX_COMPILE) $T$@ $(PSAUX_DRV_SRC_S)
+
+
+# PSAUX driver - multiple objects
+#
+$(OBJ_)%.$O: $(PSAUX_DIR_)%.c $(FREETYPE_H) $(PSAUX_DRV_H)
+	$(PSAUX_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(PSAUX_DRV_OBJ_S)
+DRV_OBJS_M += $(PSAUX_DRV_OBJ_M)
+
+
+# EOF
--- /dev/null
+++ b/src/psaux/t1decode.c
@@ -1,0 +1,1026 @@
+#include <psaux/t1decode.h>
+#include <psaux/psobjs.h>
+#include <freetype/internal/t1errors.h>
+#include <freetype/ftoutln.h>
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1decode
+
+
+  typedef enum  T1_Operator_
+  {
+    op_none = 0,
+    op_endchar,
+    op_hsbw,
+    op_seac,
+    op_sbw,
+    op_closepath,
+    op_hlineto,
+    op_hmoveto,
+    op_hvcurveto,
+    op_rlineto,
+    op_rmoveto,
+    op_rrcurveto,
+    op_vhcurveto,
+    op_vlineto,
+    op_vmoveto,
+    op_dotsection,
+    op_hstem,
+    op_hstem3,
+    op_vstem,
+    op_vstem3,
+    op_div,
+    op_callothersubr,
+    op_callsubr,
+    op_pop,
+    op_return,
+    op_setcurrentpoint,
+
+    op_max    /* never remove this one */
+
+  } T1_Operator;
+
+  static
+  const FT_Int  t1_args_count[op_max] =
+  {
+    0, /* none */
+    0, /* endchar */
+    2, /* hsbw */
+    5, /* seac */
+    4, /* sbw */
+    0, /* closepath */
+    1, /* hlineto */
+    1, /* hmoveto */
+    4, /* hvcurveto */
+    2, /* rlineto */
+    2, /* rmoveto */
+    6, /* rrcurveto */
+    4, /* vhcurveto */
+    1, /* vlineto */
+    1, /* vmoveto */
+    0, /* dotsection */
+    2, /* hstem */
+    6, /* hstem3 */
+    2, /* vstem */
+    6, /* vstem3 */
+    2, /* div */
+   -1, /* callothersubr */
+    1, /* callsubr */
+    0, /* pop */
+    0, /* return */
+    2  /* setcurrentpoint */
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    lookup_glyph_by_stdcharcode                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Looks up a given glyph by its StandardEncoding charcode.  Used     */
+  /*    to implement the SEAC Type 1 operator.                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: The current face object.                               */
+  /*                                                                       */
+  /*    charcode :: The character code to look for.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A glyph index in the font face.  Returns -1 if the corresponding   */
+  /*    glyph wasn't found.                                                */
+  /*                                                                       */
+  static
+  FT_Int  t1_lookup_glyph_by_stdcharcode( T1_Decoder*  decoder,
+                                          FT_Int       charcode )
+  {
+    FT_UInt             n;
+    const FT_String*    glyph_name;
+    PSNames_Interface*  psnames = decoder->psnames;
+
+
+    /* check range of standard char code */
+    if ( charcode < 0 || charcode > 255 )
+      return -1;
+
+    glyph_name = psnames->adobe_std_strings(
+                   psnames->adobe_std_encoding[charcode]);
+
+    for ( n = 0; n < decoder->num_glyphs; n++ )
+    {
+      FT_String*  name = (FT_String*)decoder->glyph_names[n];
+
+
+      if ( name && strcmp( name,glyph_name ) == 0 )
+        return n;
+    }
+
+    return -1;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    t1operator_seac                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Implements the `seac' Type 1 operator for a Type 1 decoder.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    decoder :: The current CID decoder.                                */
+  /*                                                                       */
+  /*    asb     :: The accent's side bearing.                              */
+  /*                                                                       */
+  /*    adx     :: The horizontal offset of the accent.                    */
+  /*                                                                       */
+  /*    ady     :: The vertical offset of the accent.                      */
+  /*                                                                       */
+  /*    bchar   :: The base character's StandardEncoding charcode.         */
+  /*                                                                       */
+  /*    achar   :: The accent character's StandardEncoding charcode.       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  t1operator_seac( T1_Decoder*  decoder,
+                             FT_Pos       asb,
+                             FT_Pos       adx,
+                             FT_Pos       ady,
+                             FT_Int       bchar,
+                             FT_Int       achar )
+  {
+    FT_Error     error;
+    FT_Int       bchar_index, achar_index, n_base_points;
+    FT_Outline*  base = decoder->builder.base;
+    FT_Vector    left_bearing, advance;
+
+
+    /* seac weirdness */
+    adx += decoder->builder.left_bearing.x;
+
+    bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar );
+    achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar );
+
+    if ( bchar_index < 0 || achar_index < 0 )
+    {
+      FT_ERROR(( "t1operator_seac:" ));
+      FT_ERROR(( " invalid seac character code arguments\n" ));
+      return T1_Err_Syntax_Error;
+    }
+
+    /* if we are trying to load a composite glyph, do not load the */
+    /* accent character and return the array of subglyphs.         */
+    if ( decoder->builder.no_recurse )
+    {
+      FT_GlyphSlot     glyph  = (FT_GlyphSlot)decoder->builder.glyph;
+      FT_GlyphLoader*  loader = glyph->loader;
+      FT_SubGlyph*     subg;
+
+
+      /* reallocate subglyph array if necessary */
+      error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
+      if ( error )
+        goto Exit;
+
+      subg = loader->current.subglyphs;
+
+      /* subglyph 0 = base character */
+      subg->index = bchar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
+                    FT_SUBGLYPH_FLAG_USE_MY_METRICS;
+      subg->arg1  = 0;
+      subg->arg2  = 0;
+      subg++;
+
+      /* subglyph 1 = accent character */
+      subg->index = achar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
+      subg->arg1  = adx - asb;
+      subg->arg2  = ady;
+
+      /* set up remaining glyph fields */
+      glyph->num_subglyphs = 2;
+      glyph->subglyphs     = loader->base.subglyphs;
+      glyph->format        = ft_glyph_format_composite;
+
+      loader->current.num_subglyphs = 2;
+    }
+
+    /* First load `bchar' in builder */
+    /* now load the unscaled outline */
+
+    FT_GlyphLoader_Prepare( decoder->builder.loader );  /* prepare loader */
+
+    error = T1_Decoder_Parse_Glyph( decoder, bchar_index );
+    if ( error )
+      goto Exit;
+
+    n_base_points = base->n_points;
+
+    /* save the left bearing and width of the base character */
+    /* as they will be erased by the next load.              */
+
+    left_bearing = decoder->builder.left_bearing;
+    advance      = decoder->builder.advance;
+
+    decoder->builder.left_bearing.x = 0;
+    decoder->builder.left_bearing.y = 0;
+
+    /* Now load `achar' on top of */
+    /* the base outline           */
+    error = T1_Decoder_Parse_Glyph( decoder, achar_index );
+    if ( error )
+      goto Exit;
+
+    /* restore the left side bearing and   */
+    /* advance width of the base character */
+
+    decoder->builder.left_bearing = left_bearing;
+    decoder->builder.advance      = advance;
+
+    /* Finally, move the accent */
+    if ( decoder->builder.load_points )
+    {
+      FT_Outline  dummy;
+
+
+      dummy.n_points = base->n_points - n_base_points;
+      dummy.points   = base->points   + n_base_points;
+      FT_Outline_Translate( &dummy, adx - asb, ady );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Decoder_Parse_Charstrings                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Parses a given Type 1 charstrings program.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    decoder         :: The current Type 1 decoder.                     */
+  /*                                                                       */
+  /*    charstring_base :: The base address of the charstring stream.      */
+  /*                                                                       */
+  /*    charstring_len  :: The length in bytes of the charstring stream.   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Free error code.  0 means success.                                 */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  T1_Decoder_Parse_Charstrings( T1_Decoder*  decoder,
+                                          FT_Byte*     charstring_base,
+                                          FT_UInt      charstring_len )
+  {
+    FT_Error          error;
+    T1_Decoder_Zone*  zone;
+    FT_Byte*          ip;
+    FT_Byte*          limit;
+    T1_Builder*       builder = &decoder->builder;
+    FT_Outline*       outline;
+    FT_Pos            x, y;
+
+    /* we don't want to touch the source code -- use macro trick */
+#define  start_point   T1_Builder_Start_Point
+#define  check_points  T1_Builder_Check_Points
+#define  add_point     T1_Builder_Add_Point
+#define  add_point1    T1_Builder_Add_Point1
+#define  add_contour   T1_Builder_Add_Contour
+#define  close_contour T1_Builder_Close_Contour
+
+    /* First of all, initialize the decoder */
+    decoder->top  = decoder->stack;
+    decoder->zone = decoder->zones;
+    zone          = decoder->zones;
+
+    builder->path_begun  = 0;
+
+    zone->base           = charstring_base;
+    limit = zone->limit  = charstring_base + charstring_len;
+    ip    = zone->cursor = zone->base;
+
+    error   = FT_Err_Ok;
+    outline = builder->current;
+
+    x = builder->pos_x;
+    y = builder->pos_y;
+
+    /* now, execute loop */
+    while ( ip < limit )
+    {
+      FT_Long*     top   = decoder->top;
+      T1_Operator  op    = op_none;
+      FT_Long      value = 0;
+
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* Decode operator or operand                                        */
+      /*                                                                   */
+      /*                                                                   */
+
+      /* first of all, decompress operator or value */
+      switch ( *ip++ )
+      {
+      case 1:
+        op = op_hstem;
+        break;
+
+      case 3:
+        op = op_vstem;
+        break;
+      case 4:
+        op = op_vmoveto;
+        break;
+      case 5:
+        op = op_rlineto;
+        break;
+      case 6:
+        op = op_hlineto;
+        break;
+      case 7:
+        op = op_vlineto;
+        break;
+      case 8:
+        op = op_rrcurveto;
+        break;
+      case 9:
+        op = op_closepath;
+        break;
+      case 10:
+        op = op_callsubr;
+        break;
+      case 11:
+        op = op_return;
+        break;
+
+      case 13:
+        op = op_hsbw;
+        break;
+      case 14:
+        op = op_endchar;
+        break;
+
+      case 21:
+        op = op_rmoveto;
+        break;
+      case 22:
+        op = op_hmoveto;
+        break;
+
+      case 30:
+        op = op_vhcurveto;
+        break;
+      case 31:
+        op = op_hvcurveto;
+        break;
+
+      case 12:
+        if ( ip > limit )
+        {
+          FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+EOF)\n" ));
+          goto Syntax_Error;
+        }
+
+        switch ( *ip++ )
+        {
+        case 0:
+          op = op_dotsection;
+          break;
+        case 1:
+          op = op_vstem3;
+          break;
+        case 2:
+          op = op_hstem3;
+          break;
+        case 6:
+          op = op_seac;
+          break;
+        case 7:
+          op = op_sbw;
+          break;
+        case 12:
+          op = op_div;
+          break;
+        case 16:
+          op = op_callothersubr;
+          break;
+        case 17:
+          op = op_pop;
+          break;
+        case 33:
+          op = op_setcurrentpoint;
+          break;
+
+        default:
+          FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+%d)\n",
+                     ip[-1] ));
+          goto Syntax_Error;
+        }
+        break;
+
+      case 255:    /* four bytes integer */
+        if ( ip + 4 > limit )
+        {
+          FT_ERROR(( "T1_Parse_CharStrings: unexpected EOF in integer\n" ));
+          goto Syntax_Error;
+        }
+
+        value = ( (FT_Long)ip[0] << 24 ) |
+                ( (FT_Long)ip[1] << 16 ) |
+                ( (FT_Long)ip[2] << 8  ) |
+                           ip[3];
+        ip += 4;
+        break;
+
+      default:
+        if ( ip[-1] >= 32 )
+        {
+          if ( ip[-1] < 247 )
+            value = (FT_Long)ip[-1] - 139;
+          else
+          {
+            if ( ++ip > limit )
+            {
+              FT_ERROR(( "T1_Parse_CharStrings:" ));
+              FT_ERROR(( " unexpected EOF in integer\n" ));
+              goto Syntax_Error;
+            }
+
+          if ( ip[-2] < 251 )
+            value =  ( ( (FT_Long)ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
+          else
+            value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
+          }
+        }
+        else
+        {
+          FT_ERROR(( "T1_Parse_CharStrings: invalid byte (%d)\n",
+                     ip[-1] ));
+          goto Syntax_Error;
+        }
+      }
+
+      /*********************************************************************/
+      /*                                                                   */
+      /*  Push value on stack, or process operator                         */
+      /*                                                                   */
+      /*                                                                   */
+      if ( op == op_none )
+      {
+        if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
+        {
+          FT_ERROR(( "T1_Parse_CharStrings: stack overflow!\n" ));
+          goto Syntax_Error;
+        }
+
+        FT_TRACE4(( " %ld", value ));
+
+        *top++       = value;
+        decoder->top = top;
+      }
+      else if ( op == op_callothersubr )  /* callothersubr */
+      {
+        FT_TRACE4(( " callothersubr" ));
+
+        if ( top - decoder->stack < 2 )
+          goto Stack_Underflow;
+
+        top -= 2;
+        switch ( top[1] )
+        {
+        case 1:                     /* start flex feature */
+          if ( top[0] != 0 )
+            goto Unexpected_OtherSubr;
+
+          decoder->flex_state        = 1;
+          decoder->num_flex_vectors  = 0;
+          if ( start_point( builder, x, y ) ||
+               check_points( builder, 6 )   )
+            goto Memory_Error;
+          break;
+
+        case 2:                     /* add flex vectors */
+          {
+            FT_Int  index;
+
+            if ( top[0] != 0 )
+              goto Unexpected_OtherSubr;
+
+            /* note that we should not add a point for index 0; */
+            /* this will move our current position to the flex  */
+            /* point without adding any point to the outline    */
+            index = decoder->num_flex_vectors++;
+            if ( index > 0 && index < 7 )
+              add_point( builder,
+                         x,
+                         y,
+                         (FT_Byte)( index == 3 || index == 6 ) );
+          }
+          break;
+
+        case 0:                     /* end flex feature */
+          if ( top[0] != 3 )
+            goto Unexpected_OtherSubr;
+
+          if ( decoder->flex_state       == 0 ||
+               decoder->num_flex_vectors != 7 )
+          {
+            FT_ERROR(( "T1_Parse_CharStrings: unexpected flex end\n" ));
+            goto Syntax_Error;
+          }
+
+          /* now consume the remaining `pop pop setcurpoint' */
+          if ( ip + 6 > limit ||
+               ip[0] != 12 || ip[1] != 17 || /* pop */
+               ip[2] != 12 || ip[3] != 17 || /* pop */
+               ip[4] != 12 || ip[5] != 33 )  /* setcurpoint */
+          {
+            FT_ERROR(( "T1_Parse_CharStrings: invalid flex charstring\n" ));
+            goto Syntax_Error;
+          }
+
+          ip += 6;
+          decoder->flex_state = 0;
+          break;
+
+        case 3:                     /* change hints */
+          if ( top[0] != 1 )
+            goto Unexpected_OtherSubr;
+
+          /* eat the following `pop' */
+          if ( ip + 2 > limit )
+          {
+            FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+%d)\n",
+                       ip[-1] ));
+            goto Syntax_Error;
+          }
+
+          if ( ip[0] != 12 || ip[1] != 17 )
+          {
+            FT_ERROR(( "T1_Parse_CharStrings:" ));
+            FT_ERROR(( " `pop' expected, found (%d %d)\n",
+                       ip[0], ip[1] ));
+            goto Syntax_Error;
+          }
+          ip += 2;
+          break;
+
+        case 12:
+        case 13:
+          /* counter control hints, clear stack */
+          top = decoder->stack;
+          break;
+
+        case 14:
+        case 15:
+        case 16:
+        case 17:
+        case 18:                    /* multiple masters */
+          {
+            T1_Blend*  blend = decoder->blend;
+            FT_UInt    num_points, nn, mm;
+            FT_Long*   delta;
+            FT_Long*   values;
+
+
+            if ( !blend )
+            {
+              FT_ERROR(( "T1_Parse_CharStrings:" ));
+              FT_ERROR(( " unexpected multiple masters operator!\n" ));
+              goto Syntax_Error;
+            }
+
+            num_points = top[1] - 13 + ( top[1] == 18 );
+            if ( top[0] != (FT_Int)( num_points * blend->num_designs ) )
+            {
+              FT_ERROR(( "T1_Parse_CharStrings:" ));
+              FT_ERROR(( " incorrect number of mm arguments\n" ));
+              goto Syntax_Error;
+            }
+
+            top -= blend->num_designs*num_points;
+            if ( top < decoder->stack )
+              goto Stack_Underflow;
+
+            /* we want to compute:                                   */
+            /*                                                       */
+            /*  a0*w0 + a1*w1 + ... + ak*wk                          */
+            /*                                                       */
+            /* but we only have the a0, a1-a0, a2-a0, .. ak-a0       */
+            /* however, given that w0 + w1 + ... + wk == 1, we can   */
+            /* rewrite it easily as:                                 */
+            /*                                                       */
+            /*  a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk       */
+            /*                                                       */
+            /* where k == num_designs-1                              */
+            /*                                                       */
+            /* I guess that's why it's written in this `compact'     */
+            /* form.                                                 */
+            /*                                                       */
+            delta  = top + num_points;
+            values = top;
+            for ( nn = 0; nn < num_points; nn++ )
+            {
+              FT_Int  tmp = values[0];
+
+
+              for ( mm = 1; mm < blend->num_designs; mm++ )
+                tmp += FT_MulFix( *delta++, blend->weight_vector[mm] );
+
+              *values++ = tmp;
+            }
+            /* note that `top' will be incremented later by calls to `pop' */
+            break;
+          }
+
+        default:
+        Unexpected_OtherSubr:
+          FT_ERROR(( "T1_Parse_CharStrings: invalid othersubr [%d %d]!\n",
+                     top[0], top[1] ));
+          goto Syntax_Error;
+        }
+        decoder->top = top;
+      }
+      else  /* general operator */
+      {
+        FT_Int  num_args = t1_args_count[op];
+
+
+        if ( top - decoder->stack < num_args )
+          goto Stack_Underflow;
+
+        top -= num_args;
+
+        switch ( op )
+        {
+        case op_endchar:
+          FT_TRACE4(( " endchar" ));
+
+          close_contour( builder );
+
+          /* add current outline to the glyph slot */
+          FT_GlyphLoader_Add( builder->loader );
+
+          /* return now! */
+          FT_TRACE4(( "\n\n" ));
+          return FT_Err_Ok;
+
+        case op_hsbw:
+          FT_TRACE4(( " hsbw" ));
+
+          builder->left_bearing.x += top[0];
+          builder->advance.x       = top[1];
+          builder->advance.y       = 0;
+
+          builder->last.x = x = top[0];
+          builder->last.y = y = 0;
+
+          /* the `metrics_only' indicates that we only want to compute */
+          /* the glyph's metrics (lsb + advance width), not load the   */
+          /* rest of it; so exit immediately                           */
+          if ( builder->metrics_only )
+            return FT_Err_Ok;
+
+          break;
+
+        case op_seac:
+          /* return immediately after the processing */
+          return t1operator_seac( decoder, top[0], top[1],
+                                           top[2], top[3], top[4] );
+
+        case op_sbw:
+          FT_TRACE4(( " sbw" ));
+
+          builder->left_bearing.x += top[0];
+          builder->left_bearing.y += top[1];
+          builder->advance.x       = top[2];
+          builder->advance.y       = top[3];
+
+          builder->last.x = x = top[0];
+          builder->last.y = y = top[1];
+
+          /* the `metrics_only' indicates that we only want to compute */
+          /* the glyph's metrics (lsb + advance width), not load the   */
+          /* rest of it; so exit immediately                           */
+          if ( builder->metrics_only )
+            return FT_Err_Ok;
+
+          break;
+
+        case op_closepath:
+          FT_TRACE4(( " closepath" ));
+
+          close_contour( builder );
+          builder->path_begun = 0;
+          break;
+
+        case op_hlineto:
+          FT_TRACE4(( " hlineto" ));
+
+          if ( start_point( builder, x, y ) )
+            goto Memory_Error;
+
+          x += top[0];
+          goto Add_Line;
+
+        case op_hmoveto:
+          FT_TRACE4(( " hmoveto" ));
+
+          x += top[0];
+          builder->path_begun = 0;
+          break;
+
+        case op_hvcurveto:
+          FT_TRACE4(( " hvcurveto" ));
+
+          if ( start_point( builder, x, y ) ||
+               check_points( builder, 3 )   )
+            goto Memory_Error;
+
+          x += top[0];
+          add_point( builder, x, y, 0 );
+          x += top[1];
+          y += top[2];
+          add_point( builder, x, y, 0 );
+          y += top[3];
+          add_point( builder, x, y, 1 );
+          break;
+
+        case op_rlineto:
+          FT_TRACE4(( " rlineto" ));
+
+          if ( start_point( builder, x, y ) )
+            goto Memory_Error;
+
+          x += top[0];
+          y += top[1];
+
+        Add_Line:
+          if ( add_point1( builder, x, y ) )
+            goto Memory_Error;
+          break;
+
+        case op_rmoveto:
+          FT_TRACE4(( " rmoveto" ));
+
+          x += top[0];
+          y += top[1];
+          builder->path_begun = 0;
+          break;
+
+        case op_rrcurveto:
+          FT_TRACE4(( " rcurveto" ));
+
+          if ( start_point( builder, x, y ) ||
+               check_points( builder, 3 )   )
+            goto Memory_Error;
+
+          x += top[0];
+          y += top[1];
+          add_point( builder, x, y, 0 );
+
+          x += top[2];
+          y += top[3];
+          add_point( builder, x, y, 0 );
+
+          x += top[4];
+          y += top[5];
+          add_point( builder, x, y, 1 );
+          break;
+
+        case op_vhcurveto:
+          FT_TRACE4(( " vhcurveto" ));
+
+          if ( start_point( builder, x, y ) ||
+               check_points( builder, 3 )   )
+            goto Memory_Error;
+
+          y += top[0];
+          add_point( builder, x, y, 0 );
+          x += top[1];
+          y += top[2];
+          add_point( builder, x, y, 0 );
+          x += top[3];
+          add_point( builder, x, y, 1 );
+          break;
+
+        case op_vlineto:
+          FT_TRACE4(( " vlineto" ));
+
+          if ( start_point( builder, x, y ) )
+            goto Memory_Error;
+
+          y += top[0];
+          goto Add_Line;
+
+        case op_vmoveto:
+          FT_TRACE4(( " vmoveto" ));
+
+          y += top[0];
+          builder->path_begun = 0;
+          break;
+
+        case op_div:
+          FT_TRACE4(( " div" ));
+
+          if ( top[1] )
+          {
+            *top = top[0] / top[1];
+            ++top;
+          }
+          else
+          {
+            FT_ERROR(( "T1_Parse_CharStrings: division by 0\n" ));
+            goto Syntax_Error;
+          }
+          break;
+
+        case op_callsubr:
+          {
+            FT_Int  index;
+
+
+            FT_TRACE4(( " callsubr" ));
+
+            index = top[0];
+            if ( index < 0 || index >= (FT_Int)decoder->num_subrs )
+            {
+              FT_ERROR(( "T1_Parse_CharStrings: invalid subrs index\n" ));
+              goto Syntax_Error;
+            }
+
+            if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
+            {
+              FT_ERROR(( "T1_Parse_CharStrings: too many nested subrs\n" ));
+              goto Syntax_Error;
+            }
+
+            zone->cursor = ip;  /* save current instruction pointer */
+
+            zone++;
+            zone->base   = decoder->subrs[index] + decoder->lenIV;
+            
+            if (decoder->subrs_len)
+              zone->limit  = zone->base + decoder->subrs_len[index];
+            else
+              zone->limit  = decoder->subrs[index+1];
+              
+            zone->cursor = zone->base;
+
+            if ( !zone->base )
+            {
+              FT_ERROR(( "T1_Parse_CharStrings: invoking empty subrs!\n" ));
+              goto Syntax_Error;
+            }
+
+            decoder->zone = zone;
+            ip            = zone->base;
+            limit         = zone->limit;
+            break;
+          }
+
+        case op_pop:
+          FT_TRACE4(( " pop" ));
+
+          /* theorically, the arguments are already on the stack */
+          top++;
+          break;
+
+        case op_return:
+          FT_TRACE4(( " return" ));
+
+          if ( zone <= decoder->zones )
+          {
+            FT_ERROR(( "T1_Parse_CharStrings: unexpected return\n" ));
+            goto Syntax_Error;
+          }
+
+          zone--;
+          ip            = zone->cursor;
+          limit         = zone->limit;
+          decoder->zone = zone;
+          break;
+
+        case op_dotsection:
+          FT_TRACE4(( " dotsection" ));
+
+          break;
+
+        case op_hstem:
+          FT_TRACE4(( " hstem" ));
+
+          break;
+
+        case op_hstem3:
+          FT_TRACE4(( " hstem3" ));
+
+          break;
+
+        case op_vstem:
+          FT_TRACE4(( " vstem" ));
+
+          break;
+
+        case op_vstem3:
+          FT_TRACE4(( " vstem3" ));
+
+          break;
+
+        case op_setcurrentpoint:
+          FT_TRACE4(( " setcurrentpoint" ));
+
+          FT_ERROR(( "T1_Parse_CharStrings:" ));
+          FT_ERROR(( " unexpected `setcurrentpoint'\n" ));
+          goto Syntax_Error;
+
+        default:
+          FT_ERROR(( "T1_Parse_CharStrings: unhandled opcode %d\n", op ));
+          goto Syntax_Error;
+        }
+
+        decoder->top = top;
+
+      } /* general operator processing */
+
+    } /* while ip < limit */
+
+    FT_TRACE4(( "..end..\n\n" ));
+    return error;
+
+  Syntax_Error:
+    return T1_Err_Syntax_Error;
+
+  Stack_Underflow:
+    return T1_Err_Stack_Underflow;
+
+  Memory_Error:
+    return builder->error;
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  T1_Decoder_Parse_Glyph( T1_Decoder*  decoder,
+                                    FT_UInt      glyph )
+  {
+    return decoder->parse_glyph( decoder, glyph );
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  T1_Decoder_Init( T1_Decoder*             decoder,
+                             FT_Face                 face,
+                             FT_Size                 size,
+                             FT_GlyphSlot            slot,
+                             FT_Byte**               glyph_names,
+                             T1_Blend*               blend,
+                             T1_Decoder_Parse_Func   parse_glyph )
+  {
+    MEM_Set( decoder, 0, sizeof(*decoder) );
+    
+    /* retrieve PSNames interface from list of current modules */
+    {
+      PSNames_Interface*  psnames = 0;
+      
+      psnames = (PSNames_Interface*)FT_Get_Module_Interface(
+                   FT_FACE_LIBRARY(face), "psnames" );
+      if (!psnames)
+      {
+        FT_ERROR(( "T1_Decoder_Init: the 'psnames' module is not available\n" ));
+        return FT_Err_Unimplemented_Feature;
+      }
+      
+      decoder->psnames = psnames;
+    }
+    T1_Builder_Init( &decoder->builder, face, size, slot );
+    
+    decoder->num_glyphs  = face->num_glyphs;
+    decoder->glyph_names = glyph_names;
+    decoder->blend       = blend;
+    decoder->parse_glyph = parse_glyph;
+    
+    decoder->funcs       = &t1_decoder_funcs;
+    return 0;
+  }
+
+
+  LOCAL_FUNC
+  void  T1_Decoder_Done( T1_Decoder*  decoder )
+  {
+    T1_Builder_Done( &decoder->builder );
+  }
+
--- /dev/null
+++ b/src/psaux/t1decode.h
@@ -1,0 +1,32 @@
+#ifndef T1DECODE_H
+#define T1DECODE_H
+
+#include <freetype/internal/psaux.h>
+#include <freetype/internal/psnames.h>
+#include <freetype/internal/t1types.h>
+
+  LOCAL_DEF
+  const T1_Decoder_Funcs   t1_decoder_funcs;
+
+  LOCAL_DEF
+  FT_Error   T1_Decoder_Parse_Glyph( T1_Decoder*  decoder,
+                                     FT_UInt      glyph_index );
+
+  LOCAL_DEF
+  FT_Error   T1_Decoder_Parse_Charstrings( T1_Decoder* decoder,
+                                           FT_Byte*    base,
+                                           FT_UInt     len );
+
+  LOCAL_DEF
+  FT_Error  T1_Decoder_Init( T1_Decoder*            decoder,
+                             FT_Face                face,
+                             FT_Size                size,
+                             FT_GlyphSlot           slot,
+                             FT_Byte**              glyph_names,
+                             T1_Blend*              blend,
+                             T1_Decoder_Parse_Func  parse_glyph );
+
+  LOCAL_DEF
+  void  T1_Decoder_Done( T1_Decoder*  decoder );
+
+#endif /* T1DECODE_H */
--- a/src/type1z/z1gload.c
+++ b/src/type1z/z1gload.c
@@ -30,7 +30,9 @@
 #include <freetype/internal/ftdebug.h>
 #include <freetype/internal/ftstream.h>
 #include <freetype/ftoutln.h>
+#include <freetype/internal/psaux.h>
 
+
 #include <string.h>     /* for strcmp() */
 
 
@@ -44,1240 +46,11 @@
 #define FT_COMPONENT  trace_z1gload
 
 
-  typedef enum  Z1_Operator_
-  {
-    op_none = 0,
-    op_endchar,
-    op_hsbw,
-    op_seac,
-    op_sbw,
-    op_closepath,
-    op_hlineto,
-    op_hmoveto,
-    op_hvcurveto,
-    op_rlineto,
-    op_rmoveto,
-    op_rrcurveto,
-    op_vhcurveto,
-    op_vlineto,
-    op_vmoveto,
-    op_dotsection,
-    op_hstem,
-    op_hstem3,
-    op_vstem,
-    op_vstem3,
-    op_div,
-    op_callothersubr,
-    op_callsubr,
-    op_pop,
-    op_return,
-    op_setcurrentpoint,
 
-    op_max    /* never remove this one */
-
-  } Z1_Operator;
-
-  static
-  const FT_Int  t1_args_count[op_max] =
-  {
-    0, /* none */
-    0, /* endchar */
-    2, /* hsbw */
-    5, /* seac */
-    4, /* sbw */
-    0, /* closepath */
-    1, /* hlineto */
-    1, /* hmoveto */
-    4, /* hvcurveto */
-    2, /* rlineto */
-    2, /* rmoveto */
-    6, /* rrcurveto */
-    4, /* vhcurveto */
-    1, /* vlineto */
-    1, /* vmoveto */
-    0, /* dotsection */
-    2, /* hstem */
-    6, /* hstem3 */
-    2, /* vstem */
-    6, /* vstem3 */
-    2, /* div */
-   -1, /* callothersubr */
-    1, /* callsubr */
-    0, /* pop */
-    0, /* return */
-    2  /* setcurrentpoint */
-  };
-
-
   /*************************************************************************/
   /*************************************************************************/
   /*************************************************************************/
   /**********                                                      *********/
-  /**********                                                      *********/
-  /**********             GENERIC CHARSTRING PARSING               *********/
-  /**********                                                      *********/
-  /**********                                                      *********/
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Z1_Init_Builder                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Initializes a given glyph builder.                                 */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    builder :: A pointer to the glyph builder to initialize.           */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    face    :: The current face object.                                */
-  /*                                                                       */
-  /*    size    :: The current size object.                                */
-  /*                                                                       */
-  /*    glyph   :: The current glyph object.                               */
-  /*                                                                       */
-  LOCAL_FUNC
-  void  Z1_Init_Builder( Z1_Builder*   builder,
-                         T1_Face       face,
-                         Z1_Size       size,
-                         Z1_GlyphSlot  glyph )
-  {
-    builder->path_begun  = 0;
-    builder->load_points = 1;
-
-    builder->face   = face;
-    builder->glyph  = glyph;
-    builder->memory = face->root.memory;
-
-    if ( glyph )
-    {
-      FT_GlyphLoader*  loader = glyph->root.loader;
-
-
-      builder->loader  = loader;
-      builder->current = &loader->current.outline;
-      builder->base    = &loader->base.outline;
-
-      FT_GlyphLoader_Rewind( loader );
-    }
-
-    if ( size )
-    {
-      builder->scale_x = size->root.metrics.x_scale;
-      builder->scale_y = size->root.metrics.y_scale;
-    }
-
-    builder->pos_x = 0;
-    builder->pos_y = 0;
-
-    builder->left_bearing.x = 0;
-    builder->left_bearing.y = 0;
-    builder->advance.x      = 0;
-    builder->advance.y      = 0;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Z1_Done_Builder                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Finalizes a given glyph builder.  Its contents can still be used   */
-  /*    after the call, but the function saves important information       */
-  /*    within the corresponding glyph slot.                               */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    builder :: A pointer to the glyph builder to finalize.             */
-  /*                                                                       */
-  LOCAL_FUNC
-  void Z1_Done_Builder( Z1_Builder*  builder )
-  {
-    Z1_GlyphSlot  glyph = builder->glyph;
-
-
-    if ( glyph )
-      glyph->root.outline = *builder->base;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Z1_Init_Decoder                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Initializes a given glyph decoder.                                 */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    decoder :: A pointer to the glyph builder to initialize.           */
-  /*                                                                       */
-  LOCAL_FUNC
-  void  Z1_Init_Decoder( Z1_Decoder* decoder )
-  {
-    decoder->top              = 0;
-    decoder->zone             = 0;
-    decoder->flex_state       = 0;
-    decoder->num_flex_vectors = 0;
-    decoder->blend            = 0;
-
-    /* Clear loader */
-    MEM_Set( &decoder->builder, 0, sizeof ( decoder->builder ) );
-  }
-
-
-  /* check that there is enough space for `count' more points */
-  static
-  FT_Error  check_points( Z1_Builder*  builder,
-                          FT_Int       count )
-  {
-    return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
-  }
-
-
-  /* add a new point; do not check space */
-  static
-  void  add_point( Z1_Builder*  builder,
-                   FT_Pos       x,
-                   FT_Pos       y,
-                   FT_Byte      flag )
-  {
-    FT_Outline*  outline = builder->current;
-
-
-    if ( builder->load_points )
-    {
-      FT_Vector*  point   = outline->points + outline->n_points;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
-
-
-      point->x = x;
-      point->y = y;
-      *control = flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic;
-
-      builder->last = *point;
-    }
-
-    outline->n_points++;
-  }
-
-
-  /* check space for a new on-curve point, then add it */
-  static
-  FT_Error  add_point1( Z1_Builder*  builder,
-                        FT_Pos       x,
-                        FT_Pos       y )
-  {
-    FT_Error  error;
-
-
-    error = check_points( builder, 1 );
-    if ( !error )
-      add_point( builder, x, y, 1 );
-
-    return error;
-  }
-
-
-  /* check space for a new contour, then add it */
-  static
-  FT_Error  add_contour( Z1_Builder*  builder )
-  {
-    FT_Outline*  outline = builder->current;
-    FT_Error     error;
-
-
-    if ( !builder->load_points )
-    {
-      outline->n_contours++;
-      return FT_Err_Ok;
-    }
-
-    /* reallocate contours array if necessary */
-    error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
-    if ( !error )
-    {
-      if ( outline->n_contours > 0 )
-        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
-
-      outline->n_contours++;
-    }
-
-    return error;
-  }
-
-
-  /* if a path was begun, add its first on-curve point */
-  static
-  FT_Error  start_point( Z1_Builder*  builder,
-                         FT_Pos       x,
-                         FT_Pos       y )
-  {
-    /* test whether we are building a new contour */
-    if ( !builder->path_begun )
-    {
-      FT_Error  error;
-
-
-      builder->path_begun = 1;
-      error = add_contour( builder );
-      if ( error )
-        return error;
-    }
-    return add_point1( builder, x, y );
-  }
-
-
-  /* close the current contour */
-  static
-  void  close_contour( Z1_Builder*  builder )
-  {
-    FT_Outline*  outline = builder->current;
-
-
-    /* XXX: we must not include the last point in the path if it */
-    /*      is located on the first point                        */
-    if ( outline->n_points > 1 )
-    {
-      FT_Int      first = 0;
-      FT_Vector*  p1    = outline->points + first;
-      FT_Vector*  p2    = outline->points + outline->n_points-1;
-
-
-      if ( outline->n_contours > 1 )
-      {
-        first = outline->contours[outline->n_contours - 2] + 1;
-        p1    = outline->points + first;
-      }
-
-      if ( p1->x == p2->x && p1->y == p2->y )
-        outline->n_points--;
-    }
-
-    if ( outline->n_contours > 0 )
-      outline->contours[outline->n_contours - 1] = outline->n_points - 1;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    lookup_glyph_by_stdcharcode                                        */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Looks up a given glyph by its StandardEncoding charcode.  Used     */
-  /*    to implement the SEAC Type 1 operator.                             */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    face     :: The current face object.                               */
-  /*                                                                       */
-  /*    charcode :: The character code to look for.                        */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    A glyph index in the font face.  Returns -1 if the corresponding   */
-  /*    glyph wasn't found.                                                */
-  /*                                                                       */
-  static
-  FT_Int  lookup_glyph_by_stdcharcode( T1_Face  face,
-                                       FT_Int   charcode )
-  {
-    FT_Int              n;
-    const FT_String*    glyph_name;
-    PSNames_Interface*  psnames = (PSNames_Interface*)face->psnames;
-
-
-    /* check range of standard char code */
-    if ( charcode < 0 || charcode > 255 )
-      return -1;
-
-    glyph_name = psnames->adobe_std_strings(
-                   psnames->adobe_std_encoding[charcode]);
-
-    for ( n = 0; n < face->type1.num_glyphs; n++ )
-    {
-      FT_String*  name = (FT_String*)face->type1.glyph_names[n];
-
-
-      if ( name && strcmp( name,glyph_name ) == 0 )
-        return n;
-    }
-
-    return -1;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    t1operator_seac                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Implements the `seac' Type 1 operator for a Type 1 decoder.        */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    decoder :: The current CID decoder.                                */
-  /*                                                                       */
-  /*    asb     :: The accent's side bearing.                              */
-  /*                                                                       */
-  /*    adx     :: The horizontal offset of the accent.                    */
-  /*                                                                       */
-  /*    ady     :: The vertical offset of the accent.                      */
-  /*                                                                       */
-  /*    bchar   :: The base character's StandardEncoding charcode.         */
-  /*                                                                       */
-  /*    achar   :: The accent character's StandardEncoding charcode.       */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  static
-  FT_Error  t1operator_seac( Z1_Decoder*  decoder,
-                             FT_Pos       asb,
-                             FT_Pos       adx,
-                             FT_Pos       ady,
-                             FT_Int       bchar,
-                             FT_Int       achar )
-  {
-    FT_Error     error;
-    FT_Int       bchar_index, achar_index, n_base_points;
-    FT_Outline*  base = decoder->builder.base;
-    FT_Vector    left_bearing, advance;
-    T1_Face      face  = decoder->builder.face;
-    T1_Font*     type1 = &face->type1;
-
-
-    /* seac weirdness */
-    adx += decoder->builder.left_bearing.x;
-
-    bchar_index = lookup_glyph_by_stdcharcode( face, bchar );
-    achar_index = lookup_glyph_by_stdcharcode( face, achar );
-
-    if ( bchar_index < 0 || achar_index < 0 )
-    {
-      FT_ERROR(( "t1operator_seac:" ));
-      FT_ERROR(( " invalid seac character code arguments\n" ));
-      return T1_Err_Syntax_Error;
-    }
-
-    /* if we are trying to load a composite glyph, do not load the */
-    /* accent character and return the array of subglyphs.         */
-    if ( decoder->builder.no_recurse )
-    {
-      FT_GlyphSlot     glyph  = (FT_GlyphSlot)decoder->builder.glyph;
-      FT_GlyphLoader*  loader = glyph->loader;
-      FT_SubGlyph*     subg;
-
-
-      /* reallocate subglyph array if necessary */
-      error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
-      if ( error )
-        goto Exit;
-
-      subg = loader->current.subglyphs;
-
-      /* subglyph 0 = base character */
-      subg->index = bchar_index;
-      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
-                    FT_SUBGLYPH_FLAG_USE_MY_METRICS;
-      subg->arg1  = 0;
-      subg->arg2  = 0;
-      subg++;
-
-      /* subglyph 1 = accent character */
-      subg->index = achar_index;
-      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
-      subg->arg1  = adx - asb;
-      subg->arg2  = ady;
-
-      /* set up remaining glyph fields */
-      glyph->num_subglyphs = 2;
-      glyph->subglyphs     = loader->base.subglyphs;
-      glyph->format        = ft_glyph_format_composite;
-
-      loader->current.num_subglyphs = 2;
-    }
-
-    /* First load `bchar' in builder */
-    /* now load the unscaled outline */
-
-    FT_GlyphLoader_Prepare( decoder->builder.loader );  /* prepare loader */
-
-    error = Z1_Parse_CharStrings( decoder,
-                                  type1->charstrings    [bchar_index],
-                                  type1->charstrings_len[bchar_index],
-                                  type1->num_subrs,
-                                  type1->subrs,
-                                  type1->subrs_len );
-    if ( error )
-      goto Exit;
-
-    n_base_points = base->n_points;
-
-    /* save the left bearing and width of the base character */
-    /* as they will be erased by the next load.              */
-
-    left_bearing = decoder->builder.left_bearing;
-    advance      = decoder->builder.advance;
-
-    decoder->builder.left_bearing.x = 0;
-    decoder->builder.left_bearing.y = 0;
-
-    /* Now load `achar' on top of */
-    /* the base outline           */
-    error = Z1_Parse_CharStrings( decoder,
-                                  type1->charstrings    [achar_index],
-                                  type1->charstrings_len[achar_index],
-                                  type1->num_subrs,
-                                  type1->subrs,
-                                  type1->subrs_len );
-    if ( error )
-      return error;
-
-    /* restore the left side bearing and   */
-    /* advance width of the base character */
-
-    decoder->builder.left_bearing = left_bearing;
-    decoder->builder.advance      = advance;
-
-    /* Finally, move the accent */
-    if ( decoder->builder.load_points )
-    {
-      FT_Outline  dummy;
-
-
-      dummy.n_points = base->n_points - n_base_points;
-      dummy.points   = base->points   + n_base_points;
-      FT_Outline_Translate( &dummy, adx - asb, ady );
-    }
-
-  Exit:
-    return error;
-  }
-
-
-#define USE_ARGS( n )  do                            \
-                       {                             \
-                         top -= n;                   \
-                         if ( top < decoder->stack ) \
-                           goto Stack_Underflow;     \
-                       } while ( 0 )
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Z1_Parse_CharStrings                                               */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Parses a given Type 1 charstrings program.                         */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    decoder         :: The current Type 1 decoder.                     */
-  /*                                                                       */
-  /*    charstring_base :: The base address of the charstring stream.      */
-  /*                                                                       */
-  /*    charstring_len  :: The length in bytes of the charstring stream.   */
-  /*                                                                       */
-  /*    num_subrs       :: The number of sub-routines.                     */
-  /*                                                                       */
-  /*    subrs_base      :: An array of sub-routines addresses.             */
-  /*                                                                       */
-  /*    subrs_len       :: An array of sub-routines lengths.               */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    Free error code.  0 means success.                                 */
-  /*                                                                       */
-  LOCAL_FUNC
-  FT_Error  Z1_Parse_CharStrings( Z1_Decoder*  decoder,
-                                  FT_Byte*     charstring_base,
-                                  FT_Int       charstring_len,
-                                  FT_Int       num_subrs,
-                                  FT_Byte**    subrs_base,
-                                  FT_Int*      subrs_len )
-  {
-    FT_Error          error;
-    Z1_Decoder_Zone*  zone;
-    FT_Byte*          ip;
-    FT_Byte*          limit;
-    Z1_Builder*       builder = &decoder->builder;
-    FT_Outline*       outline;
-    FT_Pos            x, y;
-
-
-    /* First of all, initialize the decoder */
-    decoder->top  = decoder->stack;
-    decoder->zone = decoder->zones;
-    zone          = decoder->zones;
-
-    builder->path_begun  = 0;
-
-    zone->base           = charstring_base;
-    limit = zone->limit  = charstring_base + charstring_len;
-    ip    = zone->cursor = zone->base;
-
-    error   = T1_Err_Ok;
-    outline = builder->current;
-
-    x = builder->pos_x;
-    y = builder->pos_y;
-
-    /* now, execute loop */
-    while ( ip < limit )
-    {
-      FT_Int*      top   = decoder->top;
-      Z1_Operator  op    = op_none;
-      FT_Long      value = 0;
-
-
-      /*********************************************************************/
-      /*                                                                   */
-      /* Decode operator or operand                                        */
-      /*                                                                   */
-      /*                                                                   */
-
-      /* first of all, decompress operator or value */
-      switch ( *ip++ )
-      {
-      case 1:
-        op = op_hstem;
-        break;
-
-      case 3:
-        op = op_vstem;
-        break;
-      case 4:
-        op = op_vmoveto;
-        break;
-      case 5:
-        op = op_rlineto;
-        break;
-      case 6:
-        op = op_hlineto;
-        break;
-      case 7:
-        op = op_vlineto;
-        break;
-      case 8:
-        op = op_rrcurveto;
-        break;
-      case 9:
-        op = op_closepath;
-        break;
-      case 10:
-        op = op_callsubr;
-        break;
-      case 11:
-        op = op_return;
-        break;
-
-      case 13:
-        op = op_hsbw;
-        break;
-      case 14:
-        op = op_endchar;
-        break;
-
-      case 21:
-        op = op_rmoveto;
-        break;
-      case 22:
-        op = op_hmoveto;
-        break;
-
-      case 30:
-        op = op_vhcurveto;
-        break;
-      case 31:
-        op = op_hvcurveto;
-        break;
-
-      case 12:
-        if ( ip > limit )
-        {
-          FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+EOF)\n" ));
-          goto Syntax_Error;
-        }
-
-        switch ( *ip++ )
-        {
-        case 0:
-          op = op_dotsection;
-          break;
-        case 1:
-          op = op_vstem3;
-          break;
-        case 2:
-          op = op_hstem3;
-          break;
-        case 6:
-          op = op_seac;
-          break;
-        case 7:
-          op = op_sbw;
-          break;
-        case 12:
-          op = op_div;
-          break;
-        case 16:
-          op = op_callothersubr;
-          break;
-        case 17:
-          op = op_pop;
-          break;
-        case 33:
-          op = op_setcurrentpoint;
-          break;
-
-        default:
-          FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+%d)\n",
-                     ip[-1] ));
-          goto Syntax_Error;
-        }
-        break;
-
-      case 255:    /* four bytes integer */
-        if ( ip + 4 > limit )
-        {
-          FT_ERROR(( "Z1_Parse_CharStrings: unexpected EOF in integer\n" ));
-          goto Syntax_Error;
-        }
-
-        value = ( (FT_Long)ip[0] << 24 ) |
-                ( (FT_Long)ip[1] << 16 ) |
-                ( (FT_Long)ip[2] << 8  ) |
-                           ip[3];
-        ip += 4;
-        break;
-
-      default:
-        if ( ip[-1] >= 32 )
-        {
-          if ( ip[-1] < 247 )
-            value = (FT_Long)ip[-1] - 139;
-          else
-          {
-            if ( ++ip > limit )
-            {
-              FT_ERROR(( "Z1_Parse_CharStrings:" ));
-              FT_ERROR(( " unexpected EOF in integer\n" ));
-              goto Syntax_Error;
-            }
-
-          if ( ip[-2] < 251 )
-            value =  ( (FT_Long)( ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
-          else
-            value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
-          }
-        }
-        else
-        {
-          FT_ERROR(( "Z1_Parse_CharStrings: invalid byte (%d)\n",
-                     ip[-1] ));
-          goto Syntax_Error;
-        }
-      }
-
-      /*********************************************************************/
-      /*                                                                   */
-      /*  Push value on stack, or process operator                         */
-      /*                                                                   */
-      /*                                                                   */
-      if ( op == op_none )
-      {
-        if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
-        {
-          FT_ERROR(( "Z1_Parse_CharStrings: stack overflow!\n" ));
-          goto Syntax_Error;
-        }
-
-        FT_TRACE4(( " %ld", value ));
-
-        *top++       = value;
-        decoder->top = top;
-      }
-      else if ( op == op_callothersubr )  /* callothersubr */
-      {
-        FT_TRACE4(( " callothersubr" ));
-
-        if ( top - decoder->stack < 2 )
-          goto Stack_Underflow;
-
-        top -= 2;
-        switch ( top[1] )
-        {
-        case 1:                     /* start flex feature */
-          if ( top[0] != 0 )
-            goto Unexpected_OtherSubr;
-
-          decoder->flex_state        = 1;
-          decoder->num_flex_vectors  = 0;
-          if ( start_point( builder, x, y ) ||
-               check_points( builder, 6 )   )
-            goto Memory_Error;
-          break;
-
-        case 2:                     /* add flex vectors */
-          {
-            FT_Int  index;
-
-            if ( top[0] != 0 )
-              goto Unexpected_OtherSubr;
-
-            /* note that we should not add a point for index 0; */
-            /* this will move our current position to the flex  */
-            /* point without adding any point to the outline    */
-            index = decoder->num_flex_vectors++;
-            if ( index > 0 && index < 7 )
-              add_point( builder,
-                         x,
-                         y,
-                         (FT_Byte)( index == 3 || index == 6 ) );
-          }
-          break;
-
-        case 0:                     /* end flex feature */
-          if ( top[0] != 3 )
-            goto Unexpected_OtherSubr;
-
-          if ( decoder->flex_state       == 0 ||
-               decoder->num_flex_vectors != 7 )
-          {
-            FT_ERROR(( "Z1_Parse_CharStrings: unexpected flex end\n" ));
-            goto Syntax_Error;
-          }
-
-          /* now consume the remaining `pop pop setcurpoint' */
-          if ( ip + 6 > limit ||
-               ip[0] != 12 || ip[1] != 17 || /* pop */
-               ip[2] != 12 || ip[3] != 17 || /* pop */
-               ip[4] != 12 || ip[5] != 33 )  /* setcurpoint */
-          {
-            FT_ERROR(( "Z1_Parse_CharStrings: invalid flex charstring\n" ));
-            goto Syntax_Error;
-          }
-
-          ip += 6;
-          decoder->flex_state = 0;
-          break;
-
-        case 3:                     /* change hints */
-          if ( top[0] != 1 )
-            goto Unexpected_OtherSubr;
-
-          /* eat the following `pop' */
-          if ( ip + 2 > limit )
-          {
-            FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+%d)\n",
-                       ip[-1] ));
-            goto Syntax_Error;
-          }
-
-          if ( ip[0] != 12 || ip[1] != 17 )
-          {
-            FT_ERROR(( "Z1_Parse_CharStrings:" ));
-            FT_ERROR(( " `pop' expected, found (%d %d)\n",
-                       ip[0], ip[1] ));
-            goto Syntax_Error;
-          }
-          ip += 2;
-          break;
-
-        case 12:
-        case 13:
-          /* counter control hints, clear stack */
-          top = decoder->stack;
-          break;
-
-        case 14:
-        case 15:
-        case 16:
-        case 17:
-        case 18:                    /* multiple masters */
-          {
-            T1_Blend*  blend = decoder->blend;
-            FT_UInt    num_points, nn, mm;
-            FT_Int*    delta;
-            FT_Int*    values;
-
-
-            if ( !blend )
-            {
-              FT_ERROR(( "Z1_Parse_CharStrings:" ));
-              FT_ERROR(( " unexpected multiple masters operator!\n" ));
-              goto Syntax_Error;
-            }
-
-            num_points = top[1] - 13 + ( top[1] == 18 );
-            if ( top[0] != (FT_Int)( num_points * blend->num_designs ) )
-            {
-              FT_ERROR(( "Z1_Parse_CharStrings:" ));
-              FT_ERROR(( " incorrect number of mm arguments\n" ));
-              goto Syntax_Error;
-            }
-
-            top -= blend->num_designs*num_points;
-            if ( top < decoder->stack )
-              goto Stack_Underflow;
-
-            /* we want to compute:                                   */
-            /*                                                       */
-            /*  a0*w0 + a1*w1 + ... + ak*wk                          */
-            /*                                                       */
-            /* but we only have the a0, a1-a0, a2-a0, .. ak-a0       */
-            /* however, given that w0 + w1 + ... + wk == 1, we can   */
-            /* rewrite it easily as:                                 */
-            /*                                                       */
-            /*  a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk       */
-            /*                                                       */
-            /* where k == num_designs-1                              */
-            /*                                                       */
-            /* I guess that's why it's written in this `compact'     */
-            /* form.                                                 */
-            /*                                                       */
-            delta  = top + num_points;
-            values = top;
-            for ( nn = 0; nn < num_points; nn++ )
-            {
-              FT_Int  tmp = values[0];
-
-
-              for ( mm = 1; mm < blend->num_designs; mm++ )
-                tmp += FT_MulFix( *delta++, blend->weight_vector[mm] );
-
-              *values++ = tmp;
-            }
-            /* note that `top' will be incremented later by calls to `pop' */
-            break;
-          }
-
-        default:
-        Unexpected_OtherSubr:
-          FT_ERROR(( "Z1_Parse_CharStrings: invalid othersubr [%d %d]!\n",
-                     top[0], top[1] ));
-          goto Syntax_Error;
-        }
-        decoder->top = top;
-      }
-      else  /* general operator */
-      {
-        FT_Int  num_args = t1_args_count[op];
-
-
-        if ( top - decoder->stack < num_args )
-          goto Stack_Underflow;
-
-        top -= num_args;
-
-        switch ( op )
-        {
-        case op_endchar:
-          FT_TRACE4(( " endchar" ));
-
-          close_contour( builder );
-
-          /* add current outline to the glyph slot */
-          FT_GlyphLoader_Add( builder->loader );
-
-          /* return now! */
-          FT_TRACE4(( "\n\n" ));
-          return T1_Err_Ok;
-
-        case op_hsbw:
-          FT_TRACE4(( " hsbw" ));
-
-          builder->left_bearing.x += top[0];
-          builder->advance.x       = top[1];
-          builder->advance.y       = 0;
-
-          builder->last.x = x = top[0];
-          builder->last.y = y = 0;
-
-          /* the `metrics_only' indicates that we only want to compute */
-          /* the glyph's metrics (lsb + advance width), not load the   */
-          /* rest of it; so exit immediately                           */
-          if ( builder->metrics_only )
-            return T1_Err_Ok;
-
-          break;
-
-        case op_seac:
-          /* return immediately after the processing */
-          return t1operator_seac( decoder, top[0], top[1],
-                                           top[2], top[3], top[4] );
-
-        case op_sbw:
-          FT_TRACE4(( " sbw" ));
-
-          builder->left_bearing.x += top[0];
-          builder->left_bearing.y += top[1];
-          builder->advance.x       = top[2];
-          builder->advance.y       = top[3];
-
-          builder->last.x = x = top[0];
-          builder->last.y = y = top[1];
-
-          /* the `metrics_only' indicates that we only want to compute */
-          /* the glyph's metrics (lsb + advance width), not load the   */
-          /* rest of it; so exit immediately                           */
-          if ( builder->metrics_only )
-            return T1_Err_Ok;
-
-          break;
-
-        case op_closepath:
-          FT_TRACE4(( " closepath" ));
-
-          close_contour( builder );
-          builder->path_begun = 0;
-          break;
-
-        case op_hlineto:
-          FT_TRACE4(( " hlineto" ));
-
-          if ( start_point( builder, x, y ) )
-            goto Memory_Error;
-
-          x += top[0];
-          goto Add_Line;
-
-        case op_hmoveto:
-          FT_TRACE4(( " hmoveto" ));
-
-          x += top[0];
-          builder->path_begun = 0;
-          break;
-
-        case op_hvcurveto:
-          FT_TRACE4(( " hvcurveto" ));
-
-          if ( start_point( builder, x, y ) ||
-               check_points( builder, 3 )   )
-            goto Memory_Error;
-
-          x += top[0];
-          add_point( builder, x, y, 0 );
-          x += top[1];
-          y += top[2];
-          add_point( builder, x, y, 0 );
-          y += top[3];
-          add_point( builder, x, y, 1 );
-          break;
-
-        case op_rlineto:
-          FT_TRACE4(( " rlineto" ));
-
-          if ( start_point( builder, x, y ) )
-            goto Memory_Error;
-
-          x += top[0];
-          y += top[1];
-
-        Add_Line:
-          if ( add_point1( builder, x, y ) )
-            goto Memory_Error;
-          break;
-
-        case op_rmoveto:
-          FT_TRACE4(( " rmoveto" ));
-
-          x += top[0];
-          y += top[1];
-          builder->path_begun = 0;
-          break;
-
-        case op_rrcurveto:
-          FT_TRACE4(( " rcurveto" ));
-
-          if ( start_point( builder, x, y ) ||
-               check_points( builder, 3 )   )
-            goto Memory_Error;
-
-          x += top[0];
-          y += top[1];
-          add_point( builder, x, y, 0 );
-
-          x += top[2];
-          y += top[3];
-          add_point( builder, x, y, 0 );
-
-          x += top[4];
-          y += top[5];
-          add_point( builder, x, y, 1 );
-          break;
-
-        case op_vhcurveto:
-          FT_TRACE4(( " vhcurveto" ));
-
-          if ( start_point( builder, x, y ) ||
-               check_points( builder, 3 )   )
-            goto Memory_Error;
-
-          y += top[0];
-          add_point( builder, x, y, 0 );
-          x += top[1];
-          y += top[2];
-          add_point( builder, x, y, 0 );
-          x += top[3];
-          add_point( builder, x, y, 1 );
-          break;
-
-        case op_vlineto:
-          FT_TRACE4(( " vlineto" ));
-
-          if ( start_point( builder, x, y ) )
-            goto Memory_Error;
-
-          y += top[0];
-          goto Add_Line;
-
-        case op_vmoveto:
-          FT_TRACE4(( " vmoveto" ));
-
-          y += top[0];
-          builder->path_begun = 0;
-          break;
-
-        case op_div:
-          FT_TRACE4(( " div" ));
-
-          if ( top[1] )
-          {
-            *top = top[0] / top[1];
-            ++top;
-          }
-          else
-          {
-            FT_ERROR(( "Z1_Parse_CharStrings: division by 0\n" ));
-            goto Syntax_Error;
-          }
-          break;
-
-        case op_callsubr:
-          {
-            FT_Int  index;
-
-
-            FT_TRACE4(( " callsubr" ));
-
-            index = top[0];
-            if ( index < 0 || index >= num_subrs )
-            {
-              FT_ERROR(( "Z1_Parse_CharStrings: invalid subrs index\n" ));
-              goto Syntax_Error;
-            }
-
-            if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
-            {
-              FT_ERROR(( "Z1_Parse_CharStrings: too many nested subrs\n" ));
-              goto Syntax_Error;
-            }
-
-            zone->cursor = ip;  /* save current instruction pointer */
-
-            zone++;
-            zone->base   = subrs_base[index];
-            zone->limit  = zone->base + subrs_len[index];
-            zone->cursor = zone->base;
-
-            if ( !zone->base )
-            {
-              FT_ERROR(( "Z1_Parse_CharStrings: invoking empty subrs!\n" ));
-              goto Syntax_Error;
-            }
-
-            decoder->zone = zone;
-            ip            = zone->base;
-            limit         = zone->limit;
-            break;
-          }
-
-        case op_pop:
-          FT_TRACE4(( " pop" ));
-
-          /* theorically, the arguments are already on the stack */
-          top++;
-          break;
-
-        case op_return:
-          FT_TRACE4(( " return" ));
-
-          if ( zone <= decoder->zones )
-          {
-            FT_ERROR(( "Z1_Parse_CharStrings: unexpected return\n" ));
-            goto Syntax_Error;
-          }
-
-          zone--;
-          ip            = zone->cursor;
-          limit         = zone->limit;
-          decoder->zone = zone;
-          break;
-
-        case op_dotsection:
-          FT_TRACE4(( " dotsection" ));
-
-          break;
-
-        case op_hstem:
-          FT_TRACE4(( " hstem" ));
-
-          break;
-
-        case op_hstem3:
-          FT_TRACE4(( " hstem3" ));
-
-          break;
-
-        case op_vstem:
-          FT_TRACE4(( " vstem" ));
-
-          break;
-
-        case op_vstem3:
-          FT_TRACE4(( " vstem3" ));
-
-          break;
-
-        case op_setcurrentpoint:
-          FT_TRACE4(( " setcurrentpoint" ));
-
-          FT_ERROR(( "Z1_Parse_CharStrings:" ));
-          FT_ERROR(( " unexpected `setcurrentpoint'\n" ));
-          goto Syntax_Error;
-
-        default:
-          FT_ERROR(( "Z1_Parse_CharStrings: unhandled opcode %d\n", op ));
-          goto Syntax_Error;
-        }
-
-        decoder->top = top;
-
-      } /* general operator processing */
-
-    } /* while ip < limit */
-
-    FT_TRACE4(( "..end..\n\n" ));
-    return error;
-
-  Syntax_Error:
-    return T1_Err_Syntax_Error;
-
-  Stack_Underflow:
-    return T1_Err_Stack_Underflow;
-
-  Memory_Error:
-    return builder->error;
-  }
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-  /**********                                                      *********/
   /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
   /**********                                                      *********/
   /**********    The following code is in charge of computing      *********/
@@ -1291,37 +64,53 @@
   /*************************************************************************/
 
 
+  static
+  FT_Error  Z1_Parse_Glyph( T1_Decoder*  decoder,
+                            FT_UInt      glyph_index )
+  {
+    T1_Face  face  = (T1_Face)decoder->builder.face;
+    T1_Font* type1 = &face->type1;
+    
+    return decoder->funcs->parse_charstrings( decoder,
+                                        type1->charstrings    [glyph_index],
+                                        type1->charstrings_len[glyph_index] );
+  }
+
   LOCAL_FUNC
   FT_Error  Z1_Compute_Max_Advance( T1_Face  face,
                                     FT_Int*  max_advance )
   {
-    FT_Error    error;
-    Z1_Decoder  decoder;
-    FT_Int      glyph_index;
-    T1_Font*    type1 = &face->type1;
+    FT_Error          error;
+    T1_Decoder        decoder;
+    FT_Int            glyph_index;
+    T1_Font*          type1 = &face->type1;
+    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
 
 
     *max_advance = 0;
 
     /* Initialize load decoder */
-    Z1_Init_Decoder( &decoder );
-    Z1_Init_Builder( &decoder.builder, face, 0, 0 );
+    error = psaux->t1_decoder_funcs->init( &decoder,
+                                           (FT_Face)face,
+                                           0, /* size       */
+                                           0, /* glyph slot */
+                                           (FT_Byte**)type1->glyph_names,
+                                           face->blend,
+                                           Z1_Parse_Glyph );
 
-    decoder.blend                = face->blend;
     decoder.builder.metrics_only = 1;
     decoder.builder.load_points  = 0;
 
+    decoder.num_subrs = type1->num_subrs;
+    decoder.subrs     = type1->subrs;
+    decoder.subrs_len = type1->subrs_len;
+
     /* for each glyph, parse the glyph charstring and extract */
     /* the advance width                                      */
     for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
     {
       /* now get load the unscaled outline */
-      error = Z1_Parse_CharStrings( &decoder,
-                                    type1->charstrings    [glyph_index],
-                                    type1->charstrings_len[glyph_index],
-                                    type1->num_subrs,
-                                    type1->subrs,
-                                    type1->subrs_len );
+      error = Z1_Parse_Glyph( &decoder, glyph_index );
       /* ignore the error if one occured - skip to next glyph */
     }
 
@@ -1353,11 +142,13 @@
                            FT_Int        glyph_index,
                            FT_Int        load_flags )
   {
-    FT_Error    error;
-    Z1_Decoder  decoder;
-    T1_Face     face = (T1_Face)glyph->root.face;
-    FT_Bool     hinting;
-    T1_Font*    type1 = &face->type1;
+    FT_Error                error;
+    T1_Decoder              decoder;
+    T1_Face                 face = (T1_Face)glyph->root.face;
+    FT_Bool                 hinting;
+    T1_Font*                type1         = &face->type1;
+    PSAux_Interface*        psaux         = (PSAux_Interface*)face->psaux;
+    const T1_Decoder_Funcs* decoder_funcs = psaux->t1_decoder_funcs;
 
 
     if ( load_flags & FT_LOAD_NO_RECURSE )
@@ -1374,22 +165,30 @@
 
     glyph->root.format = ft_glyph_format_outline;
 
-    Z1_Init_Decoder( &decoder );
-    Z1_Init_Builder( &decoder.builder, face, size, glyph );
-
-    decoder.blend              = ((T1_Face)glyph->root.face)->blend;
+    error = decoder_funcs->init( &decoder,
+                                 (FT_Face)face,
+                                 (FT_Size)size,
+                                 (FT_GlyphSlot)glyph,
+                                 (FT_Byte**)type1->glyph_names,
+                                 face->blend,
+                                 Z1_Parse_Glyph );
+    if (error)
+      goto Exit;
+                      
     decoder.builder.no_recurse = ( load_flags & FT_LOAD_NO_RECURSE ) != 0;
 
+    decoder.num_subrs = type1->num_subrs;
+    decoder.subrs     = type1->subrs;
+    decoder.subrs_len = type1->subrs_len;
+   
+
     /* now load the unscaled outline */
-    error = Z1_Parse_CharStrings( &decoder,
-                                  type1->charstrings    [glyph_index],
-                                  type1->charstrings_len[glyph_index],
-                                  type1->num_subrs,
-                                  type1->subrs,
-                                  type1->subrs_len );
+    error = Z1_Parse_Glyph( &decoder, glyph_index );
+    if (error)
+      goto Exit;
 
     /* save new glyph tables */
-    Z1_Done_Builder( &decoder.builder );
+    decoder_funcs->done( &decoder );
 
     /* now, set the metrics -- this is rather simple, as   */
     /* the left side bearing is the xMin, and the top side */
@@ -1485,6 +284,7 @@
         metrics->horiBearingY = cbox.yMax;
       }
     }
+  Exit:
     return error;
   }
 
--- a/src/type1z/z1gload.h
+++ b/src/type1z/z1gload.h
@@ -36,138 +36,10 @@
 #endif
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Structure>                                                           */
-  /*    Z1_Builder                                                         */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A structure used during glyph loading to store its outline.        */
-  /*                                                                       */
-  /* <Fields>                                                              */
-  /*    memory       :: The current memory object.                         */
-  /*                                                                       */
-  /*    face         :: The current face object.                           */
-  /*                                                                       */
-  /*    glyph        :: The current glyph slot.                            */
-  /*                                                                       */
-  /*    loader       :: The current glyph loader.                          */
-  /*                                                                       */
-  /*    current      :: The current glyph outline.                         */
-  /*                                                                       */
-  /*    base         :: The base glyph outline.                            */
-  /*                                                                       */
-  /*    last         :: The last point position.                           */
-  /*                                                                       */
-  /*    scale_x      :: The horizontal scale (FUnits to sub-pixels).       */
-  /*                                                                       */
-  /*    scale_y      :: The vertical scale (FUnits to sub-pixels).         */
-  /*                                                                       */
-  /*    pos_x        :: The horizontal translation (for composite glyphs). */
-  /*                                                                       */
-  /*    pos_y        :: The vertical translation (for composite glyphs).   */
-  /*                                                                       */
-  /*    left_bearing :: The left side bearing point.                       */
-  /*                                                                       */
-  /*    advance      :: The horizontal advance vector.                     */
-  /*                                                                       */
-  /*    no_recurse   ::                                                    */
-  /*                                                                       */
-  /*    bbox         :: The glyph's bounding box.                          */
-  /*                                                                       */
-  /*    path_begun   :: A flag which indicates that a new path has begun.  */
-  /*                                                                       */
-  /*    load_points  :: A flag which indicates, if not set, that no points */
-  /*                    are loaded.                                        */
-  /*                                                                       */
-  /*    error        :: The current error code.                            */
-  /*                                                                       */
-  /*    metrics_only :: A flag whether to compute metrics only.            */
-  /*                                                                       */
-  typedef struct  Z1_Builder_
-  {
-    FT_Memory        memory;
-    T1_Face          face;
-    Z1_GlyphSlot     glyph;
-    FT_GlyphLoader*  loader;
 
-    FT_Outline*      current;       /* the current glyph outline   */
-    FT_Outline*      base;          /* the composite glyph outline */
-
-    FT_Vector        last;
-
-    FT_Fixed         scale_x;
-    FT_Fixed         scale_y;
-
-    FT_Pos           pos_x;
-    FT_Pos           pos_y;
-
-    FT_Vector        left_bearing;
-    FT_Vector        advance;
-
-    FT_BBox          bbox;          /* bounding box */
-    FT_Bool          path_begun;
-    FT_Bool          load_points;
-    FT_Bool          no_recurse;
-
-    FT_Error         error;         /* only used for memory errors */
-    FT_Bool          metrics_only;
-
-  } Z1_Builder;
-
-
-  /* execution context charstring zone */
-  typedef struct  Z1_Decoder_Zone_
-  {
-    FT_Byte*  base;
-    FT_Byte*  limit;
-    FT_Byte*  cursor;
-
-  } Z1_Decoder_Zone;
-
-
-  typedef struct  Z1_Decoder_
-  {
-    Z1_Builder        builder;
-
-    FT_Int            stack[T1_MAX_CHARSTRINGS_OPERANDS];
-    FT_Int*           top;
-
-    Z1_Decoder_Zone   zones[T1_MAX_SUBRS_CALLS + 1];
-    Z1_Decoder_Zone*  zone;
-
-    FT_Int            flex_state;
-    FT_Int            num_flex_vectors;
-    FT_Vector         flex_vectors[7];
-
-    T1_Blend*         blend;  /* for multiple masters */
-
-  } Z1_Decoder;
-
-
   LOCAL_DEF
-  void  Z1_Init_Builder( Z1_Builder*   builder,
-                         T1_Face       face,
-                         Z1_Size       size,
-                         Z1_GlyphSlot  glyph );
-
-  LOCAL_DEF
-  void  Z1_Done_Builder( Z1_Builder*  builder );
-
-  LOCAL_DEF
-  void  Z1_Init_Decoder( Z1_Decoder*  decoder );
-
-  LOCAL_DEF
   FT_Error  Z1_Compute_Max_Advance( T1_Face  face,
                                     FT_Int*  max_advance );
-
-  LOCAL_DEF
-  FT_Error   Z1_Parse_CharStrings( Z1_Decoder*  decoder,
-                                   FT_Byte*     charstring_base,
-                                   FT_Int       charstring_len,
-                                   FT_Int       num_subrs,
-                                   FT_Byte**    subrs_base,
-                                   FT_Int*      subrs_len );
 
   LOCAL_DEF
   FT_Error  Z1_Load_Glyph( Z1_GlyphSlot  glyph,
--- a/src/type1z/z1load.c
+++ b/src/type1z/z1load.c
@@ -634,7 +634,7 @@
     }
 
     Z1_ToToken( parser, &master );
-    if ( master.type != t1_token_array )
+    if ( master.type != z1_token_array )
     {
       FT_ERROR(( "parse_weight_vector: incorrect format!\n" ));
       error = T1_Err_Invalid_File_Format;
@@ -699,42 +699,42 @@
 
 #define Z1_NEW_STRING( _name, _field )              \
           static                                    \
-          const Z1_Field_Rec  t1_field_ ## _field = \
+          const Z1_Field_Rec  z1_field_ ## _field = \
             Z1_FIELD_STRING( _field );
 
 #define Z1_NEW_BOOL( _name, _field )                \
           static                                    \
-          const Z1_Field_Rec  t1_field_ ## _field = \
+          const Z1_Field_Rec  z1_field_ ## _field = \
             Z1_FIELD_BOOL( _field );
 
 #define Z1_NEW_NUM( _name, _field )                 \
           static                                    \
-          const Z1_Field_Rec  t1_field_ ## _field = \
+          const Z1_Field_Rec  z1_field_ ## _field = \
             Z1_FIELD_NUM( _field );
 
 #define Z1_NEW_FIXED( _name, _field )                 \
           static                                      \
-          const Z1_Field_Rec  t1_field_ ## _field =   \
+          const Z1_Field_Rec  z1_field_ ## _field =   \
             Z1_FIELD_FIXED( _field, _power );
 
 #define Z1_NEW_NUM_TABLE( _name, _field, _max, _count )         \
           static                                                \
-          const Z1_Field_Rec  t1_field_ ## _field =             \
+          const Z1_Field_Rec  z1_field_ ## _field =             \
             Z1_FIELD_NUM_ARRAY( _field, _count, _max );
 
 #define Z1_NEW_FIXED_TABLE( _name, _field, _max, _count )         \
           static                                                  \
-          const Z1_Field_Rec  t1_field_ ## _field =               \
+          const Z1_Field_Rec  z1_field_ ## _field =               \
             Z1_FIELD_FIXED_ARRAY( _field, _count, _max );
 
 #define Z1_NEW_NUM_TABLE2( _name, _field, _max )         \
           static                                         \
-          const Z1_Field_Rec  t1_field_ ## _field =      \
+          const Z1_Field_Rec  z1_field_ ## _field =      \
             Z1_FIELD_NUM_ARRAY2( _field, _max );
 
 #define Z1_NEW_FIXED_TABLE2( _name, _field, _max )         \
           static                                           \
-          const Z1_Field_Rec  t1_field_ ## _field =        \
+          const Z1_Field_Rec  z1_field_ ## _field =        \
             Z1_FIELD_FIXED_ARRAY2( _field, _max );
 
 
@@ -808,29 +808,29 @@
 
 #define Z1_KEYWORD_TYPE1( name, f )                                    \
         {                                                              \
-          name, t1_keyword_field, t1_keyword_type1, 0, &t1_field_ ## f \
+          name, t1_keyword_field, t1_keyword_type1, 0, &z1_field_ ## f \
         }
 
 #define Z1_KEYWORD_FONTINFO( name, f )                                     \
         {                                                                  \
-          name, t1_keyword_field, t1_keyword_font_info, 0, &t1_field_ ## f \
+          name, t1_keyword_field, t1_keyword_font_info, 0, &z1_field_ ## f \
         }
 
 #define Z1_KEYWORD_PRIVATE( name, f )                                    \
         {                                                                \
-          name, t1_keyword_field, t1_keyword_private, 0, &t1_field_ ## f \
+          name, t1_keyword_field, t1_keyword_private, 0, &z1_field_ ## f \
         }
 
 #define Z1_KEYWORD_FONTINFO_TABLE( name, f )                     \
         {                                                        \
           name, t1_keyword_field_table, t1_keyword_font_info, 0, \
-          &t1_field_ ## f                                        \
+          &z1_field_ ## f                                        \
         }
 
 #define Z1_KEYWORD_PRIVATE_TABLE( name, f )                    \
         {                                                      \
           name, t1_keyword_field_table, t1_keyword_private, 0, \
-          &t1_field_ ## f                                      \
+          &z1_field_ ## f                                      \
         }
 
 
@@ -1518,7 +1518,7 @@
             Z1_ToToken( &loader->parser, &token );
 
             /* if the last token was an array, skip it! */
-            if ( token.type == t1_token_array )
+            if ( token.type == z1_token_array )
               cur2 = parser->cursor;
           }
           cur = cur2;
--- a/src/type1z/z1load.h
+++ b/src/type1z/z1load.h
@@ -20,7 +20,7 @@
 #define Z1LOAD_H
 
 #include <freetype/internal/ftstream.h>
-#include <freetype/internal/t1types.h>
+#include <freetype/internal/psaux.h>
 #include <freetype/ftmm.h>
 
 
--- a/src/type1z/z1objs.c
+++ b/src/type1z/z1objs.c
@@ -36,6 +36,7 @@
 
 
 #include <freetype/internal/psnames.h>
+#include <freetype/internal/psaux.h>
 
 
   /*************************************************************************/
@@ -158,6 +159,7 @@
   {
     FT_Error            error;
     PSNames_Interface*  psnames;
+    PSAux_Interface*    psaux;
 
     FT_UNUSED( num_params );
     FT_UNUSED( params );
@@ -174,6 +176,15 @@
                 FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psnames" );
 
       face->psnames = psnames;
+    }
+
+    psaux = (PSAux_Interface*)face->psaux;
+    if (!psaux)
+    {
+      psaux = (PSAux_Interface*)
+              FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psaux" );
+              
+      face->psaux = psaux;
     }
 
     /* open the tokenizer, this will also check the font format */
--- a/src/type1z/z1parse.c
+++ b/src/type1z/z1parse.c
@@ -326,7 +326,7 @@
     FT_Int    embed;
 
 
-    token->type  = t1_token_none;
+    token->type  = z1_token_none;
     token->start = 0;
     token->limit = 0;
 
@@ -342,19 +342,19 @@
       {
         /************* check for strings ***********************/
       case '(':
-        token->type = t1_token_string;
+        token->type = z1_token_string;
         ender = ')';
         goto Lookup_Ender;
 
         /************* check for programs/array ****************/
       case '{':
-        token->type = t1_token_array;
+        token->type = z1_token_array;
         ender = '}';
         goto Lookup_Ender;
 
         /************* check for table/array ******************/
       case '[':
-        token->type = t1_token_array;
+        token->type = z1_token_array;
         ender = ']';
 
       Lookup_Ender:
@@ -381,7 +381,7 @@
         /* **************** otherwise, it's any token **********/
       default:
         token->start = cur++;
-        token->type  = t1_token_any;
+        token->type  = z1_token_any;
         while ( cur < limit && !IS_Z1_SPACE( *cur ) )
           cur++;
 
@@ -391,7 +391,7 @@
       if ( !token->limit )
       {
         token->start = 0;
-        token->type  = t1_token_none;
+        token->type  = z1_token_none;
       }
 
       parser->cursor = cur;
@@ -411,7 +411,7 @@
     *pnum_tokens = -1;
 
     Z1_ToToken( parser, &master );
-    if ( master.type == t1_token_array )
+    if ( master.type == z1_token_array )
     {
       FT_Byte*       old_cursor = parser->cursor;
       FT_Byte*       old_limit  = parser->limit;
@@ -819,7 +819,7 @@
     cur   = token.start;
     limit = token.limit;
 
-    if ( token.type == t1_token_array )
+    if ( token.type == z1_token_array )
     {
       /* if this is an array, and we have no blend, an error occurs */
       if ( max_objects == 0 )
@@ -837,15 +837,15 @@
 
       switch ( field->type )
       {
-      case t1_field_bool:
+      case z1_field_bool:
         val = t1_tobool( &cur, limit );
         goto Store_Integer;
 
-      case t1_field_fixed:
+      case z1_field_fixed:
         val = t1_tofixed( &cur, limit, 3 );
         goto Store_Integer;
 
-      case t1_field_integer:
+      case z1_field_integer:
         val = t1_toint( &cur, limit );
 
       Store_Integer:
@@ -868,7 +868,7 @@
         }
         break;
 
-      case t1_field_string:
+      case z1_field_string:
         {
           FT_Memory  memory = parser->memory;
           FT_UInt    len    = limit-cur;
--- a/src/type1z/z1parse.h
+++ b/src/type1z/z1parse.h
@@ -30,13 +30,13 @@
   /* simple enumeration type used to identify token types */
   typedef enum  Z1_Token_Type_
   {
-    t1_token_none = 0,
-    t1_token_any,
-    t1_token_string,
-    t1_token_array,
+    z1_token_none = 0,
+    z1_token_any,
+    z1_token_string,
+    z1_token_array,
 
     /* do not remove */
-    t1_token_max
+    z1_token_max
 
   } Z1_Token_Type;
 
@@ -54,16 +54,16 @@
   /* enumeration type used to identify object fields */
   typedef enum  Z1_Field_Type_
   {
-    t1_field_none = 0,
-    t1_field_bool,
-    t1_field_integer,
-    t1_field_fixed,
-    t1_field_string,
-    t1_field_integer_array,
-    t1_field_fixed_array,
+    z1_field_none = 0,
+    z1_field_bool,
+    z1_field_integer,
+    z1_field_fixed,
+    z1_field_string,
+    z1_field_integer_array,
+    z1_field_fixed_array,
 
     /* do not remove */
-    t1_field_max
+    z1_field_max
 
   } Z1_Field_Type;
 
@@ -83,7 +83,7 @@
 
 #define Z1_FIELD_BOOL( _fname )        \
           {                            \
-            t1_field_bool,             \
+            z1_field_bool,             \
             FT_FIELD_OFFSET( _fname ), \
             FT_FIELD_SIZE( _fname ),   \
             0, 0, 0                    \
@@ -91,7 +91,7 @@
 
 #define Z1_FIELD_NUM( _fname )         \
           {                            \
-            t1_field_integer,          \
+            z1_field_integer,          \
             FT_FIELD_OFFSET( _fname ), \
             FT_FIELD_SIZE( _fname ),   \
             0, 0, 0                    \
@@ -99,7 +99,7 @@
 
 #define Z1_FIELD_FIXED( _fname, _power ) \
           {                              \
-            t1_field_fixed,              \
+            z1_field_fixed,              \
             FT_FIELD_OFFSET( _fname ),   \
             FT_FIELD_SIZE( _fname ),     \
             0, 0, 0                      \
@@ -107,7 +107,7 @@
 
 #define Z1_FIELD_STRING( _fname )      \
           {                            \
-            t1_field_string,           \
+            z1_field_string,           \
             FT_FIELD_OFFSET( _fname ), \
             FT_FIELD_SIZE( _fname ),   \
             0, 0, 0                    \
@@ -115,7 +115,7 @@
 
 #define Z1_FIELD_NUM_ARRAY( _fname, _fcount, _fmax )  \
           {                                           \
-            t1_field_integer,                         \
+            z1_field_integer,                         \
             FT_FIELD_OFFSET( _fname ),                \
             FT_FIELD_SIZE_DELTA( _fname ),            \
             _fmax,                                    \
@@ -125,7 +125,7 @@
 
 #define Z1_FIELD_FIXED_ARRAY( _fname, _fcount, _fmax ) \
           {                                            \
-            t1_field_fixed,                            \
+            z1_field_fixed,                            \
             FT_FIELD_OFFSET( _fname ),                 \
             FT_FIELD_SIZE_DELTA( _fname ),             \
             _fmax,                                     \
@@ -135,7 +135,7 @@
 
 #define Z1_FIELD_NUM_ARRAY2( _fname, _fmax ) \
           {                                  \
-            t1_field_integer,                \
+            z1_field_integer,                \
             FT_FIELD_OFFSET( _fname ),       \
             FT_FIELD_SIZE_DELTA( _fname ),   \
             _fmax,                           \
@@ -144,7 +144,7 @@
 
 #define Z1_FIELD_FIXED_ARRAY2( _fname, _fmax ) \
           {                                    \
-            t1_field_fixed,                    \
+            z1_field_fixed,                    \
             FT_FIELD_OFFSTE( _fname ),         \
             FT_FIELD_SIZE_DELTA( _fname ),     \
             _fmax,                             \