shithub: freetype+ttf2subf

Download patch

ref: 95bec28220c8f08d3db92d6048abc4756726fe2c
parent: 861ba624db9df65529a11718d3eabc45b124dbeb
author: David Turner <[email protected]>
date: Tue Feb 15 07:55:57 EST 2000

updated version of the experimental Type 1 driver
(this thing now works even better than the "regular"
driver, but is much smaller).

Provides no hinter !!

git/fs: mount .git/fs: mount/attach disallowed
--- a/src/type1z/rules.mk
+++ b/src/type1z/rules.mk
@@ -108,7 +108,7 @@
 T1Z_DRV_SRC := $(T1Z_DIR_)t1parse.c   \
                $(T1Z_DIR_)t1load.c    \
                $(T1Z_DIR_)t1driver.c  \
-   	           $(T1Z_DIR_)t1encode.c  \
+               $(T1Z_DIR_)t1afm.c     \
                $(T1Z_DIR_)t1gload.c
 
 
@@ -115,9 +115,9 @@
 # Type1 driver headers
 #
 T1Z_DRV_H := $(T1Z_DIR_)t1errors.h    \
-            $(T1Z_DIR_)t1config.h    \
-            $(T1SHARED_H)           \
-            $(T1Z_DRV_SRC:%.c=%.h)
+             $(T1Z_DIR_)t1config.h    \
+             $(T1SHARED_H)           \
+             $(T1Z_DRV_SRC:%.c=%.h)
 
 
 # driver object(s)
--- /dev/null
+++ b/src/type1z/t1afm.c
@@ -1,0 +1,222 @@
+/***************************************************************************
+ *
+ * t1afm.c  - support for reading Type 1 AFM files
+ *
+ *
+ ***************************************************************************/
+
+#include <t1afm.h>
+#include <ftstream.h>
+#include <t1types.h>
+#include <stdlib.h>  /* for qsort */
+
+  LOCAL_FUNC
+  void  T1_Done_AFM( FT_Memory memory, T1_AFM*  afm )
+  {
+    FREE( afm->kern_pairs );
+    afm->num_pairs = 0;
+  }
+
+#undef  IS_KERN_PAIR
+#define IS_KERN_PAIR(p)  ( p[0] == 'K'  &&  p[1] == 'P' )
+
+#define IS_ALPHANUM(c)  ( (c >= 'A' && c <= 'Z') || \
+                          (c >= 'a' && c <= 'z') || \
+                          (c >= '0' && c <= '9') || \
+                          (c == '_' && c == '.') )
+
+ /* read a glyph name and return the equivalent glyph index */
+  static
+  FT_UInt  afm_atoindex( FT_Byte*  *start, FT_Byte*  limit, T1_Font*  type1 )
+  {
+    FT_Byte* p = *start;
+    FT_Int   len;
+    FT_UInt  result = 0;
+    char     temp[64];
+
+    /* skip whitespace */    
+    while ( (*p == ' ' || *p == '\t' || *p == ':' || *p == ';') && p < limit )
+      p++;
+    *start = p;
+    
+    /* now, read glyph name */
+    while ( IS_ALPHANUM(*p) && p < limit ) p++;
+    len = p - *start;
+    if (len > 0 && len < 64)
+    {
+      FT_Int  n;
+      
+      /* copy glyph name to intermediate array */
+      MEM_Copy( temp, start, len );
+      temp[len] = 0;
+      
+      /* lookup glyph name in face array */
+      for ( n = 0; n < type1->num_glyphs; n++ )
+      {
+        char*  gname = (char*)type1->glyph_names;
+        
+        if ( gname && gname[0] == temp[0] && strcmp(gname,temp) == 0 )
+        {
+          result = n;
+          break;
+        }
+      }
+    }
+    *start = p;
+    return result;
+  }
+
+
+ /* read an integer */
+  static
+  int  afm_atoi( FT_Byte** start, FT_Byte*  limit )
+  {
+    FT_Byte*  p   = *start;
+    int       sum = 0;
+    
+    /* skip everything that is not a number */
+    while ( p < limit && (*p < '0' || *p > '9') )
+      p++;
+    
+    while ( p < limit && (*p >= '0' || *p < '9') )
+    {
+      sum = sum*10 + (*p - '0');
+      p++;
+    }
+    *start = p;
+    return sum;
+  }
+
+
+#undef  KERN_INDEX
+#define KERN_INDEX(g1,g2)   (((T1_ULong)g1 << 16) | g2)
+
+ /* compare two kerning pairs */
+  static
+  int  compare_kern_pairs( const void* a, const void* b )
+  {
+    T1_Kern_Pair*  pair1 = (T1_Kern_Pair*)a;
+    T1_Kern_Pair*  pair2 = (T1_Kern_Pair*)b;
+    
+    T1_ULong  index1 = KERN_INDEX(pair1->glyph1,pair1->glyph2);
+    T1_ULong  index2 = KERN_INDEX(pair2->glyph1,pair2->glyph2);
+    
+    return ( index1 < index2 ? -1 :
+           ( index1 > index2 ?  1 : 0 ));
+  }
+
+
+ /* parse an AFM file - for now, only read the kerning pairs */
+  LOCAL_FUNC
+  FT_Error  T1_Read_AFM( FT_Stream stream,
+                         FT_Face   t1_face )
+  {
+    FT_Error       error;
+    FT_Memory      memory = stream->memory;
+    FT_Byte*       start;
+    FT_Byte*       limit;
+    FT_Byte*       p;
+    FT_Int         count = 0;
+    T1_Kern_Pair*  pair;
+    T1_Font*       type1 = &((T1_Face)t1_face)->type1;
+    T1_AFM*        afm   = 0;
+    
+    if ( !ACCESS_Frame(stream->size) )
+      return error;
+      
+    start = (FT_Byte*)stream->cursor;
+    limit = (FT_Byte*)stream->limit;
+    p     = start;
+    
+    /* we are now going to count the occurences of "KP" or "KPX" in */
+    /* the AFM file..                                               */
+    count = 0;
+    for ( p = start; p < limit-3; p++ )
+    {
+      if ( IS_KERN_PAIR(p) )
+        count++;
+    }
+
+   /* Actually, kerning pairs are simply optional !! */
+    if (count == 0)
+      goto Exit;
+    
+    /* allocate the pairs */
+    if ( ALLOC(       afm, sizeof(*afm ) )                   ||
+         ALLOC_ARRAY( afm->kern_pairs, count, T1_Kern_Pair ) )
+      goto Exit;
+    
+    /* now, read each kern pair */
+    pair           = afm->kern_pairs;
+    afm->num_pairs = count;
+    
+    /* save in face object */
+    ((T1_Face)t1_face)->afm_data = afm;
+
+    for ( p = start; p < limit-3; p++ )
+    {
+      if ( IS_KERN_PAIR(p) )
+      {
+        FT_Byte*  q;
+        
+        /* skip keyword (KP or KPX) */
+        q = p+2;
+        if (*q == 'X') q++;
+        
+        pair->glyph1    = afm_atoindex( &q, limit, type1 );
+        pair->glyph2    = afm_atoindex( &q, limit, type1 );
+        pair->kerning.x = afm_atoi( &q, limit );
+        
+        pair->kerning.y = 0;
+        if ( p[2] != 'X' )
+          pair->kerning.y = afm_atoi( &q, limit );
+          
+        pair++;
+      }
+    }
+    
+    /* now, sort the kern pairs according to their glyph indices */
+    qsort( afm->kern_pairs, count, sizeof(T1_Kern_Pair), compare_kern_pairs );
+    
+  Exit:
+    if (error)
+      FREE( afm );
+
+    FORGET_Frame();
+    return error;
+  }
+
+
+ /* find the kerning for a given glyph pair */  
+  LOCAL_FUNC
+  void  T1_Get_Kerning( T1_AFM*     afm,
+                        FT_UInt     glyph1,
+                        FT_UInt     glyph2,
+                        FT_Vector*  kerning )
+  {
+    T1_Kern_Pair  *min, *mid, *max;
+    T1_ULong       index = KERN_INDEX(glyph1,glyph2);
+    
+    /* simple binary search */
+    min = afm->kern_pairs;
+    max = min + afm->num_pairs-1;
+    
+    while (min <= max)
+    {
+      T1_ULong  midi;
+      
+      mid = min + (max-min)/2;
+      midi = KERN_INDEX(mid->glyph1,mid->glyph2); 
+      if ( midi == index )
+      {
+        *kerning = mid->kerning;
+        return;
+      }
+      
+      if ( midi < index ) min = mid+1;
+                     else max = mid-1;
+    }
+    kerning->x = 0;
+    kerning->y = 0;
+  }
+
--- /dev/null
+++ b/src/type1z/t1afm.h
@@ -1,0 +1,47 @@
+/***************************************************************************
+ *
+ * t1afm.h  - support for reading Type 1 AFM files
+ *
+ *
+ ***************************************************************************/
+
+#ifndef T1AFM_H
+#define T1AFM_H
+
+#include <ftobjs.h>
+
+/* In this version, we only read the kerning table from the */
+/* AFM file. We may add support for ligatures a bit later.. */
+
+typedef struct T1_Kern_Pair_
+{
+  FT_UInt   glyph1;
+  FT_UInt   glyph2;
+  FT_Vector kerning;
+  
+} T1_Kern_Pair;
+
+
+typedef struct T1_AFM_
+{
+  FT_Int        num_pairs;
+  T1_Kern_Pair* kern_pairs;
+
+} T1_AFM;
+
+
+LOCAL_DEF
+FT_Error  T1_Read_AFM( FT_Stream stream,
+                       FT_Face   face );
+
+LOCAL_DEF
+void      T1_Done_AFM( FT_Memory  memory,
+                       T1_AFM*    afm );
+
+LOCAL_DEF
+void  T1_Get_Kerning( T1_AFM*     afm,
+                      FT_UInt     glyph1,
+                      FT_UInt     glyph2,
+                      FT_Vector*  kerning );
+
+#endif /* T1AFM_H */
--- a/src/type1z/t1config.h
+++ b/src/type1z/t1config.h
@@ -42,4 +42,11 @@
 /*                                                                 */
 #undef  T1_CONFIG_OPTION_DISABLE_HINTER
 
+/* Define this configuration macro if you want to prevent the      */
+/* compilation of "t1afm", which is in charge of reading Type1     */
+/* AFM files into an existing face. Note that when set, the T1     */
+/* driver will be unable to produce kerning distances..            */
+/*                                                                 */
+#undef  T1_CONFIG_OPTION_NO_AFM
+
 #endif /* T1CONFIG_H */
--- a/src/type1z/t1driver.c
+++ b/src/type1z/t1driver.c
@@ -17,13 +17,16 @@
 
 #include <t1driver.h>
 #include <t1gload.h>
+#include <t1afm.h>
 
 #include <ftdebug.h>
 #include <ftstream.h>
+#include <psnames.h>
 
 #undef  FT_COMPONENT
 #define FT_COMPONENT  trace_t1driver
 
+#ifndef T1_CONFIG_OPTION_NO_AFM
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -52,15 +55,68 @@
   /*    time).                                                             */
   /*                                                                       */
   static
-  void*  Get_Interface( FT_Driver*        driver,
-                        const FT_String*  interface )
+  FTDriver_Interface  Get_Interface( FT_Driver         driver,
+                                     const FT_String*  interface )
   {
-    UNUSED(driver);
-    UNUSED(interface);
+    if ( strcmp( (const char*)interface, "attach_file" ) == 0 )
+      return (FTDriver_Interface)T1_Read_AFM;
+      
     return 0;
   }
 
 
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Kerning                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to return the kerning vector between two      */
+  /*    glyphs of the same face.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to the source face object.                 */
+  /*                                                                       */
+  /*    left_glyph  :: The index of the left glyph in the kern pair.       */
+  /*                                                                       */
+  /*    right_glyph :: The index of the right glyph in the kern pair.      */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    kerning     :: The kerning vector.  This is in font units for      */
+  /*                   scalable formats, and in pixels for fixed-sizes     */
+  /*                   formats.                                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only horizontal layouts (left-to-right & right-to-left) are        */
+  /*    supported by this function.  Other layouts, or more sophisticated  */
+  /*    kernings are out of scope of this method (the basic driver         */
+  /*    interface is meant to be simple).                                  */
+  /*                                                                       */
+  /*    They can be implemented by format-specific interfaces.             */
+  /*                                                                       */
+  static
+  T1_Error  Get_Kerning( T1_Face     face,
+                         T1_UInt     left_glyph,
+                         T1_UInt     right_glyph,
+                         T1_Vector*  kerning )
+  {
+    T1_AFM*  afm;
+    
+    kerning->x = 0;
+    kerning->y = 0;
+
+    afm = (T1_AFM*)face->afm_data;
+    if (afm)
+      T1_Get_Kerning( afm, left_glyph, right_glyph, kerning );
+
+    return T1_Err_Ok;
+  }
+#endif
+
   /******************************************************************/
   /*                                                                */
   /* <Function> Set_Char_Sizes                                      */
@@ -130,7 +186,172 @@
     return T1_Reset_Size(size);
   }
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Char_Index                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Uses a charmap to return a given character code's glyph index.     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charmap  :: A handle to the source charmap object.                 */
+  /*    charcode :: The character code.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index.  0 means `undefined character code'.                  */
+  /*                                                                       */
+  static
+  T1_UInt  Get_Char_Index( FT_CharMap  charmap,
+                           T1_Long     charcode )
+  {
+    T1_Face             face;
+    T1_UInt             result = 0;
+    PSNames_Interface*  psnames;
 
+    face = (T1_Face)charmap->face;
+    psnames = (PSNames_Interface*)face->psnames;
+    if (psnames)    
+      switch (charmap->encoding)
+      {
+       /********************************************************************/
+       /*                                                                  */
+       /* Unicode encoding support                                         */
+       /*                                                                  */
+        case ft_encoding_unicode:
+          {
+            /* use the "psnames" module to synthetize the Unicode charmap */
+            result = psnames->lookup_unicode( &face->unicode_map,
+                                              (T1_ULong)charcode );
+
+            /* the function returns 0xFFFF when the Unicode charcode has */
+            /* no corresponding glyph..                                  */
+            if (result == 0xFFFF)
+              result = 0;
+            goto Exit;
+          }
+  
+       /********************************************************************/
+       /*                                                                  */
+       /* Custom Type 1 encoding                                           */
+       /*                                                                  */
+        case ft_encoding_adobe_custom:
+          {
+            T1_Encoding*  encoding = &face->type1.encoding;
+            if (charcode >= encoding->code_first &&
+                charcode <= encoding->code_last)
+            {
+              result = encoding->char_index[charcode];
+            }
+            goto Exit;
+          }
+          
+       /********************************************************************/
+       /*                                                                  */
+       /* Adobe Standard & Expert encoding support                         */
+       /*                                                                  */
+       default:
+         if (charcode < 256)
+         {
+           FT_UInt      code;
+           FT_Int       n;
+           const char*  glyph_name;
+           
+           code = psnames->adobe_std_encoding[charcode];
+           if (charmap->encoding == ft_encoding_adobe_expert)
+             code = psnames->adobe_expert_encoding[charcode];
+           
+           glyph_name = psnames->adobe_std_strings(code);
+           if (!glyph_name) break;
+           
+           for ( n = 0; n < face->type1.num_glyphs; n++ )
+           {
+             const char*  gname = face->type1.glyph_names[n];
+             
+             if ( gname && gname[0] == glyph_name[0] &&
+                  strcmp( gname, glyph_name ) == 0 )
+             {
+               result = n;
+               break;
+             }
+           }
+         }
+      }
+  Exit:      
+    return result;
+  }
+
+
+  static
+  T1_Error   Init_Face( FT_Stream  stream,
+                        FT_Int     face_index,
+                        T1_Face    face )
+  {
+    T1_Error  error;
+    
+    error = T1_Init_Face(stream, face_index, face);
+    if (!error)
+    {
+      FT_Face      root    = &face->root;
+      FT_CharMap   charmap = face->charmaprecs;
+
+      /* synthetize a Unicode charmap if there is support in the "psnames" */
+      /* module..                                                          */
+      if (face->psnames)
+      {
+        PSNames_Interface*  psnames = (PSNames_Interface*)face->psnames;
+        if (psnames->unicode_value)
+        {
+          error = psnames->build_unicodes( root->memory,
+                                           face->type1.num_glyphs,
+                                           (const char**)face->type1.glyph_names,
+                                           &face->unicode_map );
+          if (!error)
+          {
+            root->charmap        = charmap;
+            charmap->face        = (FT_Face)face;
+            charmap->encoding    = ft_encoding_unicode;
+            charmap->platform_id = 3;
+            charmap->encoding_id = 1;
+            charmap++;
+          }
+          
+          /* simply clear the error in case of failure (which really) */
+          /* means that out of memory or no unicode glyph names       */
+          error = 0;
+        }
+      }
+
+      /* now, support either the standard, expert, or custom encodings */
+      charmap->face        = (FT_Face)face;
+      charmap->platform_id = 7;  /* a new platform id for Adobe fonts ?? */
+      
+      switch (face->type1.encoding_type)
+      {
+        case t1_encoding_standard:
+          charmap->encoding    = ft_encoding_adobe_standard;
+          charmap->encoding_id = 0;
+          break;
+        
+        case t1_encoding_expert:
+          charmap->encoding    = ft_encoding_adobe_expert;
+          charmap->encoding_id = 1;
+          break;
+        
+        default:
+          charmap->encoding    = ft_encoding_adobe_custom;
+          charmap->encoding_id = 2;
+          break;
+      }
+      
+      root->charmaps = face->charmaps;
+      root->num_charmaps = charmap - face->charmaprecs + 1;
+      face->charmaps[0] = &face->charmaprecs[0];
+      face->charmaps[1] = &face->charmaprecs[1];
+    }
+    return error;
+  }
+
   /******************************************************************/
   /*                                                                */
   /* <Struct> FT_DriverInterface                                    */
@@ -206,7 +427,7 @@
   /*                                                                */
 
   EXPORT_FUNC
-  const  FT_DriverInterface  t1_driver_interface =
+  const  FT_DriverInterface  t1z_driver_interface =
   {
     sizeof( FT_DriverRec ),
     sizeof( T1_FaceRec ),
@@ -214,18 +435,28 @@
     sizeof( T1_GlyphSlotRec ),
     
     "type1",
-    100,  /* driver version == 1.0          */
-    200,  /* requires FreeType 2.0 or above */
+    100,
+    200,
 
     0,   /* format interface */
 
     (FTDriver_initDriver)           T1_Init_Driver,
     (FTDriver_doneDriver)           T1_Done_Driver,
+
+#ifdef T1_CONFIG_OPTION_NO_AFM
+    (FTDriver_getInterface)         0,
+#else
     (FTDriver_getInterface)         Get_Interface,
+#endif
 
-    (FTDriver_initFace)             T1_Init_Face,
+    (FTDriver_initFace)             Init_Face,
     (FTDriver_doneFace)             T1_Done_Face,
+
+#ifdef T1_CONFIG_OPTION_NO_AFM    
     (FTDriver_getKerning)           0,
+#else
+    (FTDriver_getKerning)           Get_Kerning,
+#endif
 
     (FTDriver_initSize)             T1_Init_Size,
     (FTDriver_doneSize)             T1_Done_Size,
@@ -236,36 +467,38 @@
     (FTDriver_doneGlyphSlot)        T1_Done_GlyphSlot,
     (FTDriver_loadGlyph)            T1_Load_Glyph,
 
-    (FTDriver_getCharIndex)         0,
+    (FTDriver_getCharIndex)         Get_Char_Index,
   };
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    getDriverInterface                                                 */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    This function is used when compiling the font driver as a          */
-  /*    shared library (`.DLL' or `.so').  It will be used by the          */
-  /*    high-level library of FreeType to retrieve the address of the      */
-  /*    driver's generic interface.                                        */
-  /*                                                                       */
-  /*    It shouldn't be implemented in a static build, as each driver must */
-  /*    have the same function as an exported entry point.                 */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    The address of the TrueType's driver generic interface.  The       */
-  /*    format-specific interface can then be retrieved through the method */
-  /*    interface->get_format_interface.                                   */
-  /*                                                                       */
-#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
 
+  /******************************************************************/
+  /*                                                                */
+  /*  <Function> Get_FreeType_Driver_Interface                      */
+  /*                                                                */
+  /*  <Description>                                                 */
+  /*     This function is used when compiling the TrueType driver   */
+  /*     as a shared library (.DLL or .so). It will be used by the  */
+  /*     high-level library of FreeType to retrieve the address of  */
+  /*     the driver's generic interface.                            */
+  /*                                                                */
+  /*     It shouldn't be implemented in a static build, as each     */
+  /*     driver must have the same function as an exported entry    */
+  /*     point.                                                     */
+  /*                                                                */
+  /*  <Return>                                                      */
+  /*     address of TrueType's driver generic interface. The        */
+  /*     forma-specific interface can then be retrieved through     */
+  /*     the method interface->get_format_interface..               */
+  /*                                                                */
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+  
   EXPORT_FUNC
   FT_DriverInterface*  getDriverInterface( void )
   {
     return &t1_driver_interface;
   }
-
-#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */
+  
+#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
 
 
--- a/src/type1z/t1driver.h
+++ b/src/type1z/t1driver.h
@@ -22,7 +22,7 @@
 #include <t1errors.h>
 
   EXPORT_DEF
-  const  FT_DriverInterface  t1_driver_interface;
+  const  FT_DriverInterface  t1z_driver_interface;
 
 #endif /* T1DRIVER_H */
 
--- a/src/type1z/t1gload.c
+++ b/src/type1z/t1gload.c
@@ -17,9 +17,75 @@
 
 #include <t1gload.h>
 #include <ftdebug.h>
-#include <t1encode.h>
 #include <ftstream.h>
 
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1gload
+
+  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 T1_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 */
+  };
+
+
   /**********************************************************************/
   /**********************************************************************/
   /**********************************************************************/
@@ -264,10 +330,10 @@
     if (outline->n_contours > 0)
       outline->contours[ outline->n_contours-1 ] = outline->n_points-1;
 
+    outline->n_contours++;
     return T1_Err_Ok;
   }
 
-
   /* if a path was begun, add its first on-curve point */
   static
   T1_Error  start_point( T1_Builder*  builder,
@@ -274,7 +340,16 @@
                          T1_Pos       x,
                          T1_Pos       y )
   {
-    return builder->path_begun && add_point1( builder, x, y );
+    /* test wether we're building a new contour */
+    if (!builder->path_begun)
+    {
+      T1_Error  error;
+    
+      builder->path_begun = 1;
+      error = add_contour( builder );
+      if (error) return error;
+    }
+    return add_point1( builder, x, y );
   }
 
 
@@ -312,20 +387,22 @@
   T1_Int    lookup_glyph_by_stdcharcode( T1_Face  face,
                                          T1_Int   charcode )
   {
-    T1_Int            n;
-    const T1_String*  glyph_name;
+    T1_Int              n;
+    const T1_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 = t1_standard_strings[t1_standard_encoding[charcode]];
+    glyph_name = psnames->adobe_std_strings(
+                    psnames->adobe_std_encoding[charcode]);
     
     for ( n = 0; n < face->type1.num_glyphs; n++ )
     {
       T1_String*  name = (T1_String*)face->type1.glyph_names[n];
       
-      if ( name && name[0] == glyph_name[0] && strcmp(name,glyph_name) == 0 )
+      if ( name && strcmp(name,glyph_name) == 0 )
         return n;
     }
 
@@ -506,62 +583,364 @@
     while ( ip < limit )
     {
       T1_Int*      top      = decoder->top;
+      T1_Operator  op       = op_none;
+      T1_Long      value    = 0;
 
+      /********************************************************************/
+      /*                                                                  */
+      /* Decode operator or operand                                       */
+      /*                                                                  */
+      /*                                                                  */
+
       /* First of all, decompress operator or value */
       switch (*ip++)
       {
-        case 1:   /* hstem */
-        case 3:   /* vstem */
+        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:
           {
-   Clear_Stack:
-            top = decoder->stack;
-            break;
+            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 4:   /* vmoveto */
+        case 255:    /* four bytes integer */
           {
-            USE_ARGS(1);
-            y += top[0];
-            builder->path_begun = 1;
-            goto Clear_Stack;
+            if (ip+4 > limit)
+            {
+              FT_ERROR(( "T1.Parse_CharStrings : unexpected EOF in integer\n" ));
+              goto Syntax_Error;
+            }
+
+            value = ((long)ip[0] << 24) |
+                    ((long)ip[1] << 16) |
+                    ((long)ip[2] << 8)  |
+                           ip[3];
+            ip += 4;
           }
+          break;
+
+        default:
+          if (ip[-1] >= 32)
+          {
+            if (ip[-1] < 247)
+              value = (long)ip[-1] - 139;
+            else
+            {
+              if (++ip > limit)
+              {
+                FT_ERROR(( "T1.Parse_CharStrings : unexpected EOF in integer\n" ));
+                goto Syntax_Error;
+              }
+
+              if (ip[-2] < 251)
+                value =  ((long)(ip[-2]-247) << 8) + ip[-1] + 108;
+              else
+                value = -((((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;
           
-        case 5:   /* rlineto */
+        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 ------------------------ */
+            {
+              T1_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,
+                           (T1_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: 'pop' expected, found (%d %d)\n",
+                         ip[0], ip[1] ));
+                goto Syntax_Error;
+              }
+              ip += 2;
+              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 */
+      {
+        T1_Int  num_args = t1_args_count[op];
+
+        if ( top - decoder->stack < num_args )
+          goto Stack_Underflow;
+
+        top -= num_args;
+
+        switch (op)
+        {
+          case op_endchar: /*************************************************/
           {
-            if ( start_point( builder, x, y ) ) goto Memory_Error;
+            FT_TRACE4(( " endchar" ));
+            close_contour( builder );  
+
+            /* add current outline to the glyph slot */
+            builder->base.n_points   += builder->current.n_points;
+            builder->base.n_contours += builder->current.n_contours;
+            
+            /* 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;
               
-            USE_ARGS(2);
-            x += top[0];
-            y += top[1];
-   Add_Line:
-            if (add_point1( builder, top[0], top[1] )) goto Memory_Error;
-            goto Clear_Stack;
+            break;
           }
-          
-        case 6:   /* hlineto */
+
+
+          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;
-              
-            USE_ARGS(1);
+
             x += top[0];
             goto Add_Line;
           }
-          
-        case 7:   /* vlineto */
+
+
+          case op_hmoveto:  /************************************************/
           {
+            FT_TRACE4(( " hmoveto" ));
+            x += top[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;
               
-            USE_ARGS(1);
-            y += top[0];
-            goto Add_Line;
+            x += top[0];
+            y += top[1];
+   Add_Line:
+            if (add_point1( builder, x, y )) goto Memory_Error;
+            break;
           }
-          
-        case 8:   /* rrcurveto */
+
+
+          case op_rmoveto: /*************************************************/
           {
+            FT_TRACE4(( " rmoveto" ));
+            x += top[0];
+            y += top[1];
+            break;
+          }
+
+          case op_rrcurveto: /***********************************************/
+          {
+            FT_TRACE4(( " rcurveto" ));
             if ( start_point( builder, x, y ) ||
                  check_points( builder, 3 )   ) goto Memory_Error;
               
-            USE_ARGS(6);
             x += top[0];
             y += top[1];
             add_point( builder, x, y, 0 );
@@ -573,22 +952,64 @@
             x += top[4];
             y += top[5];
             add_point( builder, x, y, 1 );
-            goto Clear_Stack;
+            break;
           }    
-          
-        case 9:   /* closepath */
+
+
+          case op_vhcurveto:  /**********************************************/
           {
-            close_contour( builder );
-            builder->path_begun = 0;
+            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;
           }
-          break;
-          
-        case 10:  /* callsubr  */
+
+
+          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];
+              break;
+            }
+
+
+          case op_div:  /****************************************************/
           {
+            FT_TRACE4(( " div" ));
+            if (top[1])
+              *top++ = top[0] / top[1];
+            else
+            {
+              FT_ERROR(( "T1.Parse_CharStrings : division by 0\n" ));
+              goto Syntax_Error;
+            }
+            break;
+          }
+
+
+          case op_callsubr:  /***********************************************/
+          {
             T1_Int  index;
 
-            USE_ARGS(1);
-            
+            FT_TRACE4(( " callsubr" ));
             index = top[0];
             if ( index < 0 || index >= num_subrs )
             {
@@ -618,13 +1039,21 @@
             decoder->zone = zone;
             ip            = zone->base;
             limit         = zone->limit;
-            
-            /* do not clear stack */
+            break;
           }
-          break;
-          
-        case 11:  /* return */
+
+
+          case op_pop:  /****************************************************/
           {
+            FT_TRACE4(( " pop" ));
+            FT_ERROR(( "T1.Parse_CharStrings : unexpected POP\n" ));
+            goto Syntax_Error;
+          }
+
+
+          case op_return:  /************************************************/
+          {
+            FT_TRACE4(( " return" ));
             if ( zone <= decoder->zones )
             {
               FT_ERROR(( "T1.Parse_CharStrings : unexpected return\n" ));
@@ -635,306 +1064,58 @@
             ip            = zone->cursor;
             limit         = zone->limit;
             decoder->zone = zone;
+            break;
           }
-          break;
-          
-        case 13:  /* hsbw */
+
+          case op_dotsection:  /*********************************************/
           {
-            USE_ARGS(2);
-            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;
-              
-            goto Clear_Stack;
+            FT_TRACE4(( " dotsection" ));
+            break;
           }
 
-        case 14:  /* endchar */
+          case op_hstem:  /**************************************************/
           {
-            close_contour( builder );  
-
-            /* add current outline to the glyph slot */
-            builder->base.n_points   += builder->current.n_points;
-            builder->base.n_contours += builder->current.n_contours;
-            
-            /* return now !! */
-            return T1_Err_Ok;
+            FT_TRACE4(( " hstem" ));
+            break;
           }
-          
-        case 21:  /* rmoveto */
+
+          case op_hstem3:  /*************************************************/
           {
-            USE_ARGS(2);
-            x += top[0];
-            y += top[1];
-            goto Clear_Stack;
+            FT_TRACE4(( " hstem3" ));
+            break;
           }
-          
-        case 22:  /* hmoveto */
+
+          case op_vstem:  /**************************************************/
           {
-            USE_ARGS(1);
-            x += top[0];
-            goto Clear_Stack;
+            FT_TRACE4(( " vstem" ));
+            break;
           }
-          
-        case 30:  /* vhcurveto */
+
+          case op_vstem3:  /*************************************************/
           {
-            if ( start_point( builder, x, y ) ||
-                 check_points( builder, 3 )   ) goto Memory_Error;
-                 
-            USE_ARGS(4);
-            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 );
-            goto Clear_Stack;
+            FT_TRACE4(( " vstem3" ));
+            break;
           }
-          
-        case 31:  /* hvcurveto */
+
+          case op_setcurrentpoint:  /*****************************************/
           {
-            if ( start_point( builder, x, y ) ||
-                 check_points( builder, 3 )   ) goto Memory_Error;
-                 
-            USE_ARGS(4);
-            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 );
-            goto Clear_Stack;
+            FT_TRACE4(( " setcurrentpoint" ));
+            FT_ERROR(( "T1.Parse_CharStrings : unexpected SETCURRENTPOINT\n" ));
+            goto Syntax_Error;
           }
-          
 
-        case 12:
-          {
-            if (ip > limit)
-            {
-              FT_ERROR(( "T1.Parse_CharStrings : invalid escape (12+EOF)\n" ));
-              goto Syntax_Error;
-            }
+          default:
+            FT_ERROR(( "T1.Parse_CharStrings : unhandled opcode %d\n", op ));
+            goto Syntax_Error;
+        }
 
-            switch (*ip++)
-            {
-              case 0:  /* dotsection */
-              case 1:  /* vstem3 */
-              case 2:  /* hstem3 */
-                  goto Clear_Stack;
-                  
-              case 6:  /* seac */
-                {
-                  USE_ARGS(5);
-                  
-                  /* return immediately to implement an accented character */
-                  return t1operator_seac( decoder,
-                                          top[0], top[1], top[3],
-                                          top[4], top[5] );
-                }
-                  
-              case 7:  /* sbw */
-                {
-                  USE_ARGS(4);
-                  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;
-              
-                  goto Clear_Stack;
-                }
-                  
-              case 12: /* div */
-                {
-                  USE_ARGS(2);
-                  top[0] /= top[1];
-                  top++;
-                }
-                break;
-                  
-              case 16: /* callothersubr */
-                {
-                  USE_ARGS(1);
-                  switch (top[0])
-                  {
-                    case 1: /* start flex feature ---------------------- */
-                      {
-                        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 ------------------------ */
-                      {
-                        T1_Int      index;
-                        
-                        /* 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,
-                                     (T1_Byte)( index==3 || index==6 ) );
-                      }
-                      break;
-                      
-                    case 0: /* end flex feature ------------------------- */
-                      {
-                        USE_ARGS(3);  /* ignore parameters */
-                        
-                        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;
-                        decoder->top        = top;
-                        
-                        goto Clear_Stack;
-                      }
-                      
-                    case 3:  /* change hints ---------------------------- */
-                      {
-                        /* 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: 'pop' expected, found (%d %d)\n",
-                                   ip[0], ip[1] ));
-                          goto Syntax_Error;
-                        }
-                        ip += 2;
-                        goto Clear_Stack;
-                      }
-                      
-                    default:
-                      FT_ERROR(( "T1.Parse_CharStrings: invalid othersubr %d !!\n",
-                                 top[0] ));
-                      goto Syntax_Error;
-                  }
-                }
+        decoder->top = top;
+      
+      } /* general operator processing */
 
-              case 17:  /* pop - should not happen !! */
-                {
-                  FT_ERROR(( "T1.Parse_CharStrings : 'pop' should not happen !!\n" ));
-                  goto Syntax_Error;
-                }
-                
-              case 33: /* setcurrentpoint */
-                {
-                  FT_ERROR(( "T1.Parse_CharStrings : 'setcurrentpoint' should not happen !!\n" ));
-                  goto Syntax_Error;
-                }  
-
-              default:
-                FT_ERROR(( "T1.Parse_CharStrings : invalid escape (12+%d)\n",
-                         ip[-1] ));
-                goto Syntax_Error;
-            }
-          }
-          break;  /* escape - 12 */
-
-        case 255:    /* four bytes integer */
-          {
-            if (ip+4 > limit)
-            {
-              FT_ERROR(( "T1.Parse_CharStrings : unexpected EOF in integer\n" ));
-              goto Syntax_Error;
-            }
-
-            *top++ = ((long)ip[0] << 24) |
-                     ((long)ip[1] << 16) |
-                     ((long)ip[2] << 8)  |
-                            ip[3];
-            ip += 4;
-          }
-          break;
-
-        default:
-          {
-            T1_Long  v, v2;
-            
-            v = ip[-1];
-            if (v < 32)
-            {
-              FT_ERROR(( "T1.Parse_CharStrings : invalid byte (%d)\n",
-                         ip[-1] ));
-              goto Syntax_Error;
-            }
-            
-            /* compute value ----  */
-            /*                     */
-            if (v < 247)   /* 1-byte value */
-              v -= 139;
-            else
-            {
-              if (++ip > limit)  /* 2-bytes value, check limits */
-              {
-                FT_ERROR(( "T1.Parse_CharStrings : unexpected EOF in integer\n" ));
-                goto Syntax_Error;
-              }
-              
-              v2 = ip[-1] + 108;
-              if (v < 251)
-                v = ((v-247) << 8) + v2;
-              else
-                v = -(((v-251) << 8) + v2);
-            }
-            
-            /* store value - is there enough room  ?*/
-            if ( top >= decoder->stack + T1_MAX_CHARSTRINGS_OPERANDS )
-            {
-              FT_ERROR(( "T1.Parse_CharStrings : Stack overflow !!\n" ));
-              goto Syntax_Error;
-            }
-            
-            *top++ = v;
-            decoder->top = top;
-          }
-      } /* big switch */
       
     } /* while ip < limit */
+    FT_TRACE4(( "..end..\n\n" ));
     return error;
 
   Syntax_Error:
--- a/src/type1z/t1load.c
+++ b/src/type1z/t1load.c
@@ -63,10 +63,8 @@
 
 #include <t1types.h>
 #include <t1errors.h>
-#include <t1encode.h>
 #include <t1config.h>
 #include <t1load.h>
-
 #include <stdio.h>
 
 #undef  FT_COMPONENT
@@ -345,8 +343,12 @@
         {
           if ( cur[1] == 'e' &&
                cur[2] == 'f' &&
+               is_space(cur[-1]) &&
                is_space(cur[3]) )
-            break;
+          {
+              FT_TRACE6(( "encoding end\n" ));
+              break;
+          }
         }
         
         /* otherwise, we must find a number before anything else */
@@ -382,6 +384,7 @@
       }
       
       face->type1.encoding_type = t1_encoding_array;
+      parser->cursor            = cur;
     }
     /* Otherwise, we should have either "StandardEncoding" or */
     /* "ExpertEncoding"                                       */
@@ -433,6 +436,10 @@
       index = T1_ToInt(parser);
       if (!read_binary_data(parser,&size,&base)) return;
       
+      T1_Decrypt( base, size, 4330 );      
+      size -= face->type1.lenIV;
+      base += face->type1.lenIV;
+
       error = T1_Add_Table( table, index, base, size );
       if (error) goto Fail;
     }
@@ -481,7 +488,7 @@
       cur = parser->cursor;
       if (cur >= limit) break;
 
-      /* we stop when we find a "def" */
+      /* we stop when we find a "def" or "end" keyword */
       if (*cur    == 'd' && 
            cur+3 < limit &&
            cur[1] == 'e' &&
@@ -488,6 +495,12 @@
            cur[2] == 'f' )
         break;
 
+      if (*cur == 'e'   &&
+          cur+3 < limit &&
+          cur[1] == 'n' &&
+          cur[2] == 'd' )
+        break;
+
       if (*cur != '/')
         skip_blackspace(parser);
       else
@@ -497,6 +510,7 @@
         
         while (cur2 < limit && is_alpha(*cur2)) cur2++;
         len = cur2-cur-1;
+        
         error = T1_Add_Table( name_table, n, cur+1, len+1 );
         if (error) goto Fail;
        
@@ -505,7 +519,11 @@
        
         parser->cursor = cur2; 
         if (!read_binary_data(parser,&size,&base)) return;
-      
+
+        T1_Decrypt( base, size, 4330 );      
+        size -= face->type1.lenIV;
+        base += face->type1.lenIV;
+
         error = T1_Add_Table( code_table, n, base, size );
         if (error) goto Fail;
         
@@ -514,6 +532,7 @@
           break;
       }
     }
+    loader->num_glyphs = n;
     return;
     
   Fail:
@@ -562,7 +581,7 @@
   T1_Error  parse_dict( T1_Face     face,
                         T1_Loader*  loader,
                         T1_Byte*    base,
-                        T1_Int      size )
+                        T1_Long     size )
   {
     T1_Parser*  parser = &loader->parser;
     
@@ -571,8 +590,8 @@
     parser->error  = 0;
     
     {
-      T1_Byte*  cur   = base;
-      T1_Byte*  limit = cur + size;
+      T1_Byte*  cur     = base;
+      T1_Byte*  limit   = cur + size;
       
       for ( ;cur < limit; cur++ )
       {
@@ -587,7 +606,7 @@
           while (cur2 < limit && is_alpha(*cur2)) cur2++;
           len  = cur2-cur;
           
-          if (len > 0)
+          if (len > 0 && len < 20)
           {
             /* now, compare the immediate name to the keyword table */
             T1_KeyWord*  keyword = (T1_KeyWord*)t1_keywords;
@@ -617,6 +636,7 @@
                     return parser->error;
 
                   cur = parser->cursor;
+                  break;
                 }
               }
               keyword++;
@@ -631,9 +651,11 @@
   static
   void t1_init_loader( T1_Loader* loader, T1_Face  face )
   {
+    MEM_Set( loader, 0, sizeof(*loader) );
     loader->num_glyphs = 0;
     loader->num_chars  = 0;
-    
+
+    /* initialize the tables - simply set their 'init' field to 0 */    
     loader->encoding_table.init = 0;
     loader->charstrings.init    = 0;
     loader->glyph_names.init    = 0;
@@ -684,6 +706,18 @@
     /* now, propagate the subrs, charstrings and glyphnames tables */
     /* to the Type1 data                                           */
     type1->num_glyphs = loader.num_glyphs;
+    
+    if ( !loader.subrs.init )
+    {
+      FT_ERROR(( "T1.Open_Face: no subrs array in face !!\n" ));
+      error = FT_Err_Invalid_File_Format;
+    }
+    
+    if ( !loader.charstrings.init )
+    {
+      FT_ERROR(( "T1.Open_Face: no charstrings array in face !!\n" ));
+      error = FT_Err_Invalid_File_Format;
+    }
     
     loader.subrs.init  = 0;
     type1->num_subrs   = loader.num_subrs;
--- a/src/type1z/t1objs.c
+++ b/src/type1z/t1objs.c
@@ -20,6 +20,7 @@
 
 #include <t1gload.h>
 #include <t1load.h>
+#include <psnames.h>
 
 /* Required by tracing mode */
 #undef   FT_COMPONENT
@@ -164,11 +165,24 @@
                           T1_Face    face )
   {
     T1_Error      error;
+    PSNames_Interface*  psnames;
 
     (void)face_index;
     (void)face;
 
     face->root.num_faces = 1;
+
+    psnames = (PSNames_Interface*)face->psnames;
+    if (!psnames)
+    {
+      /* look-up the PSNames driver */
+      FT_Driver  psnames_driver;
+      
+      psnames_driver = FT_Get_Driver( face->root.driver->library, "psnames" );
+      if (psnames_driver)
+        face->psnames = (PSNames_Interface*)
+                            (psnames_driver->interface.format_interface);
+    }
 
     /* open the tokenizer, this will also check the font format */
     error = T1_Open_Face( face );
--- a/src/type1z/t1parse.c
+++ b/src/type1z/t1parse.c
@@ -367,9 +367,18 @@
       cur++;
 
     /* now, read the coordinates */
-    for ( ; cur < limit; cur++ )
+    for ( ; cur < limit; )
     {
-      c = *cur;
+      /* skip whitespace in front of data */
+      for (;;)
+      {
+        c = *cur;
+        if ( c != ' ' && c != '\t' ) break;
+        
+        cur++;
+        if (cur >= limit) goto Exit;
+      }
+      
       if (count >= max_coords || c == ender)
         break;
       
@@ -414,9 +423,18 @@
       cur++;
 
     /* now, read the values */
-    for ( ; cur < limit; cur++ )
+    for ( ; cur < limit; )
     {
-      c = *cur;
+      /* skip whitespace in front of data */
+      for (;;)
+      {
+        c = *cur;
+        if ( c != ' ' && c != '\t' ) break;
+        
+        cur++;
+        if (cur >= limit) goto Exit;
+      }
+
       if (count >= max_values || c == ender)
         break;
       
@@ -442,11 +460,20 @@
     T1_String*  result;
     FT_Error    error;
 
-    /* first of all, skip everything until we encounter a string */
-    while ( cur < limit && *cur != '(' ) cur++;
-    cur++;
-    if (cur >= limit) return 0;
+    /* XXX : some stupid fonts have a "Notice" or "Copyright" string     */
+    /*       that simply doesn't begin with an opening parenthesis, even */
+    /*       though they have a closing one !!! E.g. "amuncial.pfb"      */
+    /*                                                                   */
+    /*       We must deal with these ill-fated cases there. Note that    */
+    /*       these fonts didn't work with the old Type 1 driver as the   */
+    /*       notice/copyright was not recognized as a valid string token */
+    /*       and made the old token parser commit errors..               */
+
+    while ( cur < limit && (*cur == ' ' || *cur == '\t')) cur++;
+    if (cur+1 >= limit) return 0;
     
+    if (*cur == '(') cur++;  /* skip the opening parenthesis, if there is one */
+    
     *cursor = cur;
     count   = 0;
     
@@ -470,7 +497,7 @@
     /* now copy the string */
     MEM_Copy( result, *cursor, len );
     result[len] = '\0';
-
+    *cursor = cur;
     return result;    
   }
 
@@ -632,43 +659,44 @@
     else
       parser->in_pfb = 1;
 
-   /* now, try to load the "size" bytes of the "base" dictionary we */
-   /* found previously                                              */
-
-   /* if it's a memory-based resource, set up pointers */
-   if ( !stream->read )
-   {
-     parser->base_dict = (T1_Byte*)stream->base + stream->pos;
-     parser->base_len  = size;
-     parser->in_memory = 1;
-
-     /* check that the "size" field is valid */
-     if ( FILE_Skip(size) ) goto Exit;
-   }
-   else
-   {
-     /* read segment in memory */
-     if ( ALLOC( parser->base_dict, size )     ||
-          FILE_Read( parser->base_dict, size ) )
-       goto Exit;
-   }
-
-   /* Now check font format, we must see a '%!PS-AdobeFont-1' */
-   /* or a '%!FontType'                                       */
-   {
-     if ( size <= 16 ||
-          ( strncmp( (const char*)parser->base_dict, "%!PS-AdobeFont-1", 16 ) &&
-            strncmp( (const char*)parser->base_dict, "%!FontType", 10 )       ) )
-     {
-       FT_TRACE2(( "Not a Type1 font\n" ));
-       error = T1_Err_Invalid_File_Format;
-     }
-     else
-     {
-       parser->cursor = parser->base_dict;
-       parser->limit  = parser->cursor + parser->base_len;
-     }
-   }
+    /* now, try to load the "size" bytes of the "base" dictionary we */
+    /* found previously                                              */
+ 
+    /* if it's a memory-based resource, set up pointers */
+    if ( !stream->read )
+    {
+      parser->base_dict = (T1_Byte*)stream->base + stream->pos;
+      parser->base_len  = size;
+      parser->in_memory = 1;
+ 
+      /* check that the "size" field is valid */
+      if ( FILE_Skip(size) ) goto Exit;
+    }
+    else
+    {
+      /* read segment in memory */
+      if ( ALLOC( parser->base_dict, size )     ||
+           FILE_Read( parser->base_dict, size ) )
+        goto Exit;
+      parser->base_len = size;
+    }
+ 
+    /* Now check font format, we must see a '%!PS-AdobeFont-1' */
+    /* or a '%!FontType'                                       */
+    {
+      if ( size <= 16 ||
+           ( strncmp( (const char*)parser->base_dict, "%!PS-AdobeFont-1", 16 ) &&
+             strncmp( (const char*)parser->base_dict, "%!FontType", 10 )       ) )
+      {
+        FT_TRACE2(( "Not a Type1 font\n" ));
+        error = T1_Err_Invalid_File_Format;
+      }
+      else
+      {
+        parser->cursor = parser->base_dict;
+        parser->limit  = parser->cursor + parser->base_len;
+      }
+    }
 
   Exit:
     if (error && !parser->in_memory)
--- a/src/type1z/type1z.c
+++ b/src/type1z/type1z.c
@@ -34,5 +34,8 @@
 #include <t1objs.c>
 #include <t1driver.c>
 #include <t1gload.c>
-#include <t1encode.c>
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+#include <t1afm.c>
+#endif