shithub: freetype+ttf2subf

Download patch

ref: 52f911a12d1c552b9fad3a2fb33b9e04ff2d92ee
parent: d0cb15f1dba1e33d29bf756cee60095af519f8c0
author: Werner Lemberg <[email protected]>
date: Tue Oct 7 01:49:41 EDT 2003

Heavy modification of the PS parser to handle comments and strings
correctly.  This doesn't slow down the loading of PS fonts
significantly since charstrings aren't affected.

* include/freetype/config/ftstdlib.h (ft_xdigit): Renamed to...
(ft_isxdigit): This.  Updated all callers.
(ft_isdigit): New alias to `isdigit'.

* include/freetype/internal/psaux.h (PS_Parser_FuncsRec): Renamed
`skip_alpha' to `skip_PS_token'.
Add parameter to `to_bytes' and change some argument types.

* src/psaux/psauxmod.c (ps_parser_funcs): Updated.
* src/psaux/psobjs.c (ft_char_table): New array to map character
codes (ASCII and EBCDIC) of digits to numbers.
(OP): New auxiliary macro holding either `>=' or `<' depending on
the character encoding.
(skip_comment): New function.
(skip_spaces): Use it.
(skip_alpha): Removed.
(skip_literal_string, skip_string): New functions.
(ps_parser_skip_PS_token): New function.  This is a better
replacement of...
(ps_parser_skip_alpha): Removed.
(ps_parser_to_token, ps+parser_to_token_array): Updated.
(T1Radix): Rewritten, using `ft_char_table'.
(t1_toint): Renamed to...
(ps_toint): This.  Update all callers.
Use `ft_char_table'.
(ps_tobytes): Add parameter to handle delimiters and change some
argument types.
Use `ft_char_table'.
(t1_tofixed): Renamed to...
(ps_tofixed): This.  Update all callers.
Use `ft_char_table'.
(t1_tocoordarray): Renamed and updated to...
(ps_tocoordarray): This.  Update all callers.
(t1_tofixedarray): Renamed and updated to...
(ps_tofixedarray): This.  Update all callers.
(t1_tobool): Renamed to...
(ps_tobool): This.  Update all callers.
(ps_parser_load_field): Updated.
(ps_parser_load_field_table): Use `T1_MAX_TABLE_ELEMENTS'
everywhere.
(ps_parser_to_int, ps_parser_to_fixed, ps_parser_to_coord_array,
ps_parser_to_fixed_array): Skip spaces.  Updated.
(ps_parser_to_bytes): Add parameter to handle delimiters and change
some argument types.  Updated.
* src/psaux/psobjs.h: Updated.

* src/cid/cidload.c (cid_parse_dict): Updated.
* src/cid/cidparse.c (cid_parser_new): Check whether the `StartData'
token was really found.
* src/cid/cidparse.h (cid_parser_skip_alpha): Updated and renamed
to...
(cid_parser_skip_PS_token): This.

* src/type1/t1parse.h (T1_ParserRec): Use `FT_Bool' for boolean
fields.
(T1_Skip_Alpha): Replaced with...
(T1_Skip_PS_Token): This new macro.
* src/type1/t1parse.c (hexa_value): Removed.
(T1_Get_Private_Dict): Use `ft_isxdigit' and
`psaux->ps_parser_funcs_to_bytes' for handling ASCII hexadecimal
encoding.
After decrypting, replace the four random bytes at the beginning
with whitespace.
* src/type1/t1load.c (t1_allocate_blend): Use proper error values.
(parser_blend_design_positions, parse_blend_design_map,
parse_weight_vector): Updated.
(is_space): Handle `\f' also.
(is_name_char): Removed.
(read_binary_data): Updated.
(parse_encoding): Use `ft_isdigit'.
Updated.
(parse_subrs): Updated.
(TABLE_EXTEND): New macro.
(parse_charstrings): Updated.
Provide a workaround for buggy fonts which have more entries in the
/CharStrings dictionary then expected; the function now adds some
slots and skips entries which still exceed the new limit.
(parse_dict): Updated.
Terminate on the token `closefile'.

* src/type42/t42parse.c (T1_Skip_Alpha): Replaced with...
(T1_Skip_PS_Token): This new macro.  Updated all callers.
(t42_parse_encoding): Use `ft_isdigit'.


* src/base/ftmm.c (ft_face_get_mm_service): Return FT_Err_OK if
success.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,97 @@
+2003-10-06  Werner Lemberg  <[email protected]>
+
+	Heavy modification of the PS parser to handle comments and strings
+	correctly.  This doesn't slow down the loading of PS fonts
+	significantly since charstrings aren't affected.
+
+	* include/freetype/config/ftstdlib.h (ft_xdigit): Renamed to...
+	(ft_isxdigit): This.  Updated all callers.
+	(ft_isdigit): New alias to `isdigit'.
+
+	* include/freetype/internal/psaux.h (PS_Parser_FuncsRec): Renamed
+	`skip_alpha' to `skip_PS_token'.
+	Add parameter to `to_bytes' and change some argument types.
+
+	* src/psaux/psauxmod.c (ps_parser_funcs): Updated.
+	* src/psaux/psobjs.c (ft_char_table): New array to map character
+	codes (ASCII and EBCDIC) of digits to numbers.
+	(OP): New auxiliary macro holding either `>=' or `<' depending on
+	the character encoding.
+	(skip_comment): New function.
+	(skip_spaces): Use it.
+	(skip_alpha): Removed.
+	(skip_literal_string, skip_string): New functions.
+	(ps_parser_skip_PS_token): New function.  This is a better
+	replacement of...
+	(ps_parser_skip_alpha): Removed.
+	(ps_parser_to_token, ps+parser_to_token_array): Updated.
+	(T1Radix): Rewritten, using `ft_char_table'.
+	(t1_toint): Renamed to...
+	(ps_toint): This.  Update all callers.
+	Use `ft_char_table'.
+	(ps_tobytes): Add parameter to handle delimiters and change some
+	argument types.
+	Use `ft_char_table'.
+	(t1_tofixed): Renamed to...
+	(ps_tofixed): This.  Update all callers.
+	Use `ft_char_table'.
+	(t1_tocoordarray): Renamed and updated to...
+	(ps_tocoordarray): This.  Update all callers.
+	(t1_tofixedarray): Renamed and updated to...
+	(ps_tofixedarray): This.  Update all callers.
+	(t1_tobool): Renamed to...
+	(ps_tobool): This.  Update all callers.
+	(ps_parser_load_field): Updated.
+	(ps_parser_load_field_table): Use `T1_MAX_TABLE_ELEMENTS'
+	everywhere.
+	(ps_parser_to_int, ps_parser_to_fixed, ps_parser_to_coord_array,
+	ps_parser_to_fixed_array): Skip spaces.  Updated.
+	(ps_parser_to_bytes): Add parameter to handle delimiters and change
+	some argument types.  Updated.
+	* src/psaux/psobjs.h: Updated.
+
+	* src/cid/cidload.c (cid_parse_dict): Updated.
+	* src/cid/cidparse.c (cid_parser_new): Check whether the `StartData'
+	token was really found.
+	* src/cid/cidparse.h (cid_parser_skip_alpha): Updated and renamed
+	to...
+	(cid_parser_skip_PS_token): This.
+
+	* src/type1/t1parse.h (T1_ParserRec): Use `FT_Bool' for boolean
+	fields.
+	(T1_Skip_Alpha): Replaced with...
+	(T1_Skip_PS_Token): This new macro.
+	* src/type1/t1parse.c (hexa_value): Removed.
+	(T1_Get_Private_Dict): Use `ft_isxdigit' and
+	`psaux->ps_parser_funcs_to_bytes' for handling ASCII hexadecimal
+	encoding.
+	After decrypting, replace the four random bytes at the beginning
+	with whitespace.
+	* src/type1/t1load.c (t1_allocate_blend): Use proper error values.
+	(parser_blend_design_positions, parse_blend_design_map,
+	parse_weight_vector): Updated.
+	(is_space): Handle `\f' also.
+	(is_name_char): Removed.
+	(read_binary_data): Updated.
+	(parse_encoding): Use `ft_isdigit'.
+	Updated.
+	(parse_subrs): Updated.
+	(TABLE_EXTEND): New macro.
+	(parse_charstrings): Updated.
+	Provide a workaround for buggy fonts which have more entries in the
+	/CharStrings dictionary then expected; the function now adds some
+	slots and skips entries which still exceed the new limit.
+	(parse_dict): Updated.
+	Terminate on the token `closefile'.
+
+	* src/type42/t42parse.c (T1_Skip_Alpha): Replaced with...
+	(T1_Skip_PS_Token): This new macro.  Updated all callers.
+	(t42_parse_encoding): Use `ft_isdigit'.
+
+
+	* src/base/ftmm.c (ft_face_get_mm_service): Return FT_Err_OK if
+	success.
+
 2003-10-05  Werner Lemberg  <[email protected]>
 
 	* include/freetype/ftmodule.h: Renamed to...
--- a/include/freetype/config/ftstdlib.h
+++ b/include/freetype/config/ftstdlib.h
@@ -5,7 +5,7 @@
 /*    ANSI-specific library and header configuration file (specification   */
 /*    only).                                                               */
 /*                                                                         */
-/*  Copyright 2002 by                                                      */
+/*  Copyright 2002, 2003 by                                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -73,10 +73,11 @@
 
 #include <ctype.h>
 
-#define ft_isalnum  isalnum
-#define ft_isupper  isupper
-#define ft_islower  islower
-#define ft_xdigit   isxdigit
+#define ft_isalnum   isalnum
+#define ft_isupper   isupper
+#define ft_islower   islower
+#define ft_isdigit   isdigit
+#define ft_isxdigit  isxdigit
 
 
 #include <string.h>
--- a/include/freetype/ftoutln.h
+++ b/include/freetype/ftoutln.h
@@ -5,7 +5,7 @@
 /*    Support for the FT_Outline type used to store glyph shapes of        */
 /*    most scalable font formats (specification).                          */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002 by                                           */
+/*  Copyright 1996-2001, 2002, 2003 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -391,32 +391,33 @@
 
  /**************************************************************************
   *
-  * @enum: FT_Orientation
+  * @enum:
+  *   FT_Orientation
   *  
   * @description:
-  *   a list of values used to describe an outline's contour orientation
+  *   A list of values used to describe an outline's contour orientation.
   *
-  *   The TrueType and Postscript specifications used different conventions
-  *   to determine wether outline contours should be filled or unfilled.
+  *   The TrueType and Postscript specifications use different conventions
+  *   to determine whether outline contours should be filled or unfilled.
   *   
   * @values:
   *   FT_ORIENTATION_TRUETYPE ::
-  *     according to the TrueType specification, clockwise contours must
-  *     be filled, and counter-clockwise ones must be unfilled
+  *     According to the TrueType specification, clockwise contours must
+  *     be filled, and counter-clockwise ones must be unfilled.
   *
   *   FT_ORIENTATION_POSTSCRIPT ::
-  *     according to the Postscript specification, counter-clockwise contours
-  *     must be filled, and clockwise ones must be unfilled
+  *     According to the Postscript specification, counter-clockwise contours
+  *     must be filled, and clockwise ones must be unfilled.
   *
   *   FT_ORIENTATION_FILL_RIGHT ::
-  *     this is identical to @FT_ORIENTATION_TRUETYPE, but is used to
+  *     This is identical to @FT_ORIENTATION_TRUETYPE, but is used to
   *     remember that in TrueType, everything that is to the right of
   *     the drawing direction of a contour must be filled.
   *
   *   FT_ORIENTATION_FILL_LEFT ::
-  *     this is identical to @FT_ORIENTATION_POSTSCRIPT, but is used to
+  *     This is identical to @FT_ORIENTATION_POSTSCRIPT, but is used to
   *     remember that in Postscript, everything that is to the left of
-  *     the drawing direction of a contour must be filled
+  *     the drawing direction of a contour must be filled.
   */
   typedef enum
   {
@@ -430,22 +431,24 @@
 
  /**************************************************************************
   *
-  * @function: FT_Outline_Get_Orientation
+  * @function:
+  *   FT_Outline_Get_Orientation
   *  
   * @description:
-  *   this function analyzes a glyph outline and tries to compute its
-  *   fill orientation (see @FT_Orientation). This is done by computing
+  *   This function analyzes a glyph outline and tries to compute its
+  *   fill orientation (see @FT_Orientation).  This is done by computing
   *   the direction of each global horizontal and/or vertical extrema
   *   within the outline.
   *
-  *   note that this will return @FT_ORIENTATION_TRUETYPE for empty
+  *   Note that this will return @FT_ORIENTATION_TRUETYPE for empty
   *   outlines.
   *
   * @input:
-  *   outline :: handle to source outline
+  *   outline ::
+  *     A handle to the source outline.
   *
   * @return:
-  *   orientation
+  *   The orientation.
   *
   */
   FT_EXPORT( FT_Orientation )
--- a/include/freetype/internal/psaux.h
+++ b/include/freetype/internal/psaux.h
@@ -330,7 +330,7 @@
     void
     (*skip_spaces)( PS_Parser  parser );
     void
-    (*skip_alpha)( PS_Parser  parser );
+    (*skip_PS_token)( PS_Parser  parser );
 
     FT_Long
     (*to_int)( PS_Parser  parser );
@@ -337,11 +337,13 @@
     FT_Fixed
     (*to_fixed)( PS_Parser  parser,
                  FT_Int     power_ten );
+
     FT_Error
     (*to_bytes)( PS_Parser  parser,
                  FT_Byte*   bytes,
-                 FT_Int     max_bytes,
-                 FT_Int*    pnum_bytes );
+                 FT_Long    max_bytes,
+                 FT_Long*   pnum_bytes,
+                 FT_Bool    delimiters );
 
     FT_Int
     (*to_coord_array)( PS_Parser  parser,
--- a/src/base/ftmm.c
+++ b/src/base/ftmm.c
@@ -51,6 +51,9 @@
       FT_FACE_LOOKUP_SERVICE( face,
                               *aservice,
                               MULTI_MASTERS );
+
+      if ( aservice )
+        error = FT_Err_Ok;
     }
 
     return error;
--- a/src/base/ftpfr.c
+++ b/src/base/ftpfr.c
@@ -26,6 +26,7 @@
   {
     FT_Service_PfrMetrics  service;
 
+
     FT_FACE_LOOKUP_SERVICE( face, service, PFR_METRICS );
 
     return service;
--- a/src/cid/cidload.c
+++ b/src/cid/cidload.c
@@ -39,7 +39,7 @@
 
   /* read a single offset */
   FT_LOCAL_DEF( FT_Long )
-  cid_get_offset( FT_Byte**  start,
+  cid_get_offset( FT_Byte*  *start,
                   FT_Byte    offsize )
   {
     FT_Long   result;
@@ -164,9 +164,9 @@
 
       temp_scale = ABS( temp[3] );
 
-      /* Set Units per EM based on FontMatrix values.  We set the value to */
+      /* Set units per EM based on FontMatrix values.  We set the value to */
       /* `1000/temp_scale', because temp_scale was already multiplied by   */
-      /* 1000 (in t1_tofixed(), from psobjs.c).                            */
+      /* 1000 (in `t1_tofixed', from psobjs.c).                            */
       root->units_per_EM = (FT_UShort)( FT_DivFix( 0x10000L,
                                         FT_DivFix( temp_scale, 1000 ) ) );
 
@@ -258,7 +258,7 @@
 
     parser->root.cursor = base;
     parser->root.limit  = base + size;
-    parser->root.error  = 0;
+    parser->root.error  = CID_Err_Ok;
 
     {
       FT_Byte*  cur   = base;
@@ -265,31 +265,50 @@
       FT_Byte*  limit = cur + size;
 
 
-      for ( ; cur < limit; cur++ )
+      for (;;)
       {
+        FT_Byte*  newlimit;
+
+
+        parser->root.cursor = cur;
+        cid_parser_skip_spaces( parser );
+
+        if ( parser->root.cursor >= limit )
+          newlimit = limit - 1 - 17;
+        else
+          newlimit = parser->root.cursor - 17;
+
         /* look for `%ADOBeginFontDict' */
-        if ( *cur == '%' && cur + 20 < limit &&
-             ft_strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
+        for ( ; cur < newlimit; cur++ )
         {
-          cur += 17;
-
-          /* if /FDArray was found, then cid->num_dicts is > 0, and */
-          /* we can start increasing parser->num_dict               */
-          if ( face->cid.num_dicts > 0 )
-            parser->num_dict++;
+          if ( *cur == '%'                                            &&
+               ft_strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
+          {
+            /* if /FDArray was found, then cid->num_dicts is > 0, and */
+            /* we can start increasing parser->num_dict               */
+            if ( face->cid.num_dicts > 0 )
+              parser->num_dict++;
+          }
         }
+
+        cur = parser->root.cursor;
+        /* no error can occur in cid_parser_skip_spaces */
+        if ( cur >= limit )
+          break;
+
+        cid_parser_skip_PS_token( parser );
+        if ( parser->root.cursor >= limit || parser->root.error )
+          break;
+
         /* look for immediates */
-        else if ( *cur == '/' && cur + 2 < limit )
+        if ( *cur == '/' && cur + 2 < limit )
         {
           FT_PtrDist  len;
 
 
           cur++;
-
-          parser->root.cursor = cur;
-          cid_parser_skip_alpha( parser );
-
           len = parser->root.cursor - cur;
+
           if ( len > 0 && len < 22 )
           {
             /* now compare the immediate name to the keyword table */
@@ -303,10 +322,7 @@
 
               name = (FT_Byte*)keyword->ident;
               if ( !name )
-              {
-                cid_parser_skip_alpha( parser );
                 break;
-              }
 
               if ( cur[0] == name[0]                     &&
                    len == ft_strlen( (const char*)name ) )
@@ -321,14 +337,11 @@
                 if ( n >= len )
                 {
                   /* we found it - run the parsing callback */
-                  cid_parser_skip_spaces( parser );
                   parser->root.error = cid_load_keyword( face,
                                                          loader,
                                                          keyword );
                   if ( parser->root.error )
                     return parser->root.error;
-
-                  cur = parser->root.cursor;
                   break;
                 }
               }
@@ -336,6 +349,8 @@
             }
           }
         }
+
+        cur = parser->root.cursor;
       }
     }
     return parser->root.error;
--- a/src/cid/cidparse.c
+++ b/src/cid/cidparse.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    CID-keyed Type1 parser (body).                                       */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002 by                                           */
+/*  Copyright 1996-2001, 2002, 2003 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -58,6 +58,7 @@
     FT_ULong  base_offset, offset, ps_len;
     FT_Byte   buffer[256 + 10];
     FT_Int    buff_len;
+    FT_Byte   *cur, *limit;
 
 
     FT_MEM_ZERO( parser, sizeof ( *parser ) );
@@ -67,7 +68,7 @@
 
     base_offset = FT_STREAM_POS();
 
-    /* first of all, check the font format in the  header */
+    /* first of all, check the font format in the header */
     if ( FT_FRAME_ENTER( 31 ) )
       goto Exit;
 
@@ -82,15 +83,17 @@
     if ( error )
       goto Exit;
 
-    /* now, read the rest of the file, until we find a `StartData' */
+  Again:
+    /* now, read the rest of the file until we find a `StartData' */
     buff_len = 256;
     for (;;)
     {
-      FT_Byte   *p, *limit = buffer + 256;
+      FT_Byte*  p;
       FT_ULong  top_position;
 
 
       /* fill input buffer */
+      limit     = buffer + 256;
       buff_len -= 256;
       if ( buff_len > 0 )
         FT_MEM_MOVE( buffer, limit, buff_len );
@@ -101,7 +104,7 @@
         goto Exit;
 
       top_position = FT_STREAM_POS() - buff_len;
-      buff_len = 256 + 10;
+      buff_len     = 256 + 10;
 
       /* look for `StartData' */
       for ( p = buffer; p < limit; p++ )
@@ -116,12 +119,12 @@
     }
 
   Found:
-    /* we have found the start of the binary data.  We will now        */
-    /* rewind and extract the frame of corresponding to the Postscript */
-    /* section                                                         */
+    /* we have found the start of the binary data.  We will now     */
+    /* rewind and extract the frame corresponding to the PostScript */
+    /* section                                                      */
 
     ps_len = offset - base_offset;
-    if ( FT_STREAM_SEEK( base_offset )                    ||
+    if ( FT_STREAM_SEEK( base_offset )                  ||
          FT_FRAME_EXTRACT( ps_len, parser->postscript ) )
       goto Exit;
 
@@ -131,6 +134,32 @@
     parser->root.cursor    = parser->postscript;
     parser->root.limit     = parser->root.cursor + ps_len;
     parser->num_dict       = -1;
+
+    /* finally we check whether `StartData' was real -- it could be */
+    /* in a comment or string                                       */
+
+    limit = parser->root.limit;
+    cur   = parser->root.cursor;
+
+    while ( cur < limit )
+    {
+      if ( *cur == 'S' && ft_strncmp( (char*)cur, "StartData", 9 ) == 0 )
+      {
+        limit = parser->root.limit;
+        cur   = parser->root.cursor;
+        goto Exit;
+      }
+
+      cid_parser_skip_PS_token( parser );
+      cid_parser_skip_spaces  ( parser );
+      cur = parser->root.cursor;
+    }
+
+    /* we haven't found the correct `StartData'; go back and continue */
+    /* searching                                                      */
+    FT_FRAME_RELEASE( parser->postscript );
+    if ( !FT_STREAM_SEEK( offset ) )
+      goto Again;
 
   Exit:
     return error;
--- a/src/cid/cidparse.h
+++ b/src/cid/cidparse.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    CID-keyed Type1 parser (specification).                              */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002 by                                           */
+/*  Copyright 1996-2001, 2002, 2003 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -87,8 +87,10 @@
   /*                                                                       */
   /*************************************************************************/
 
-#define cid_parser_skip_spaces( p )  (p)->root.funcs.skip_spaces( &(p)->root )
-#define cid_parser_skip_alpha( p )   (p)->root.funcs.skip_alpha ( &(p)->root )
+#define cid_parser_skip_spaces( p ) \
+          (p)->root.funcs.skip_spaces( &(p)->root )
+#define cid_parser_skip_PS_token( p ) \
+          (p)->root.funcs.skip_PS_token( &(p)->root )
 
 #define cid_parser_to_int( p )        (p)->root.funcs.to_int( &(p)->root )
 #define cid_parser_to_fixed( p, t )   (p)->root.funcs.to_fixed( &(p)->root, t )
--- a/src/psaux/psauxmod.c
+++ b/src/psaux/psauxmod.c
@@ -39,7 +39,7 @@
     ps_parser_init,
     ps_parser_done,
     ps_parser_skip_spaces,
-    ps_parser_skip_alpha,
+    ps_parser_skip_PS_token,
     ps_parser_to_int,
     ps_parser_to_fixed,
     ps_parser_to_bytes,
--- a/src/psaux/psobjs.c
+++ b/src/psaux/psobjs.c
@@ -267,31 +267,76 @@
   /*************************************************************************/
 
   /* In the PostScript Language Reference Manual (PLRM) the following */
-  /* characters are called `white-space characters'.                  */
+  /* characters are called `whitespace characters'.                   */
 #define IS_T1_WHITESPACE( c )  ( (c) == ' '  || (c) == '\t' )
 #define IS_T1_LINESPACE( c )   ( (c) == '\r' || (c) == '\n' || (c) == '\f' )
 #define IS_T1_NULLSPACE( c )   ( (c) == '\0' )
 
-  /* According to the PLRM all white-space characters are equivalent, */
-  /* except in comments and strings.                                  */
+  /* According to the PLRM all whitespace characters are equivalent, */
+  /* except in comments and strings.                                 */
 #define IS_T1_SPACE( c )  ( IS_T1_WHITESPACE( c ) || \
                             IS_T1_LINESPACE( c )  || \
                             IS_T1_NULLSPACE( c )  )
 
 
+  /* The following array is used by various functions to quickly convert */
+  /* digits (both decimal and non-decimal) into numbers.                 */
+
+#if 'A' == 65
+  /* ASCII */
+
+  char ft_char_table[128] =
+  {
+    /* 0x00 */
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
+    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
+    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
+  };
+
+  /* no character >= 0x80 can represent a valid number */
+#define OP  >=
+
+#endif /* 'A' == 65 */
+
+#if 'A' == 193
+  /* EBCDIC */
+
+  char ft_char_table[128] =
+  {
+    /* 0x80 */
+    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
+    -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
+    -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
+    -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
+    -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
+     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
+  }
+
+  /* no character < 0x80 can represent a valid number */
+#define OP  <
+
+#endif /* 'A' == 193 */
+
+
+  /* first character must be already part of the comment */
+
   static void
-  skip_spaces( FT_Byte**  acur,
-               FT_Byte*   limit )
+  skip_comment( FT_Byte*  *acur,
+                FT_Byte*   limit )
   {
-    FT_Byte* cur = *acur;
+    FT_Byte*  cur = *acur;
 
 
     while ( cur < limit )
     {
-      FT_Byte  c = *cur;
-
-
-      if ( !IS_T1_SPACE( c ) )
+      if ( IS_T1_LINESPACE( *cur ) )
         break;
       cur++;
     }
@@ -301,8 +346,8 @@
 
 
   static void
-  skip_alpha( FT_Byte**  acur,
-              FT_Byte*   limit )
+  skip_spaces( FT_Byte*  *acur,
+               FT_Byte*   limit )
   {
     FT_Byte*  cur = *acur;
 
@@ -309,11 +354,46 @@
 
     while ( cur < limit )
     {
-      FT_Byte  c = *cur;
+      if ( !IS_T1_SPACE( *cur ) )
+      {
+        if ( *cur == '%' )
+          /* According to the PLRM, a comment is equal to a space. */
+          skip_comment( &cur, limit );
+        else
+          break;
+      }
+      cur++;
+    }
 
+    *acur = cur;
+  }
 
-      if ( IS_T1_SPACE( c ) )
-        break;
+
+  /* first character must be `(' */
+
+  static void
+  skip_literal_string( FT_Byte*  *acur,
+                       FT_Byte*   limit )
+  {
+    FT_Byte*  cur   = *acur;
+    FT_Int    embed = 0;
+
+
+    while ( cur < limit )
+    {
+      if ( *cur == '\\' )
+        cur++;
+      else if ( *cur == '(' )
+        embed++;
+      else if ( *cur == ')' )
+      {
+        embed--;
+        if ( embed == 0 )
+        {
+          cur++;
+          break;
+        }
+      }
       cur++;
     }
 
@@ -321,20 +401,145 @@
   }
 
 
+  /* first character must be `<' */
+
+  static void
+  skip_string( PS_Parser  parser )
+  {
+    FT_Byte*  cur   = parser->cursor;
+    FT_Byte*  limit = parser->limit;
+
+
+    cur++;
+
+    while ( cur < limit )
+    {
+      int  d;
+
+
+      /* All whitespace characters are ignored. */
+      skip_spaces( &cur, limit );
+      if ( cur >= limit )
+        break;
+
+      if ( *cur OP 0x80 )
+        break;
+
+      d = ft_char_table[*cur & 0x7F];
+      if ( d < 0 || d >= 16 )
+        break;
+    }
+
+    if ( cur < limit && *cur != '>' )
+      parser->error = PSaux_Err_Invalid_File_Format;
+    else
+      cur++;
+
+    parser->cursor = cur;
+  }
+
+
+  /***********************************************************************/
+  /*                                                                     */
+  /* All exported parsing routines handle leading whitespace and stop at */
+  /* the first character which isn't part of the just handled token.     */
+  /*                                                                     */
+  /***********************************************************************/
+
+
   FT_LOCAL_DEF( void )
-  ps_parser_skip_spaces( PS_Parser  parser )
+  ps_parser_skip_PS_token( PS_Parser  parser )
   {
-    skip_spaces( &parser->cursor, parser->limit );
+    /* Note: PostScript allows any non-delimiting, non-whitespace        */
+    /*       character in a name (PS Ref Manual, 3rd ed, p31).           */
+    /*       PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */
+
+    FT_Byte*  cur   = parser->cursor;
+    FT_Byte*  limit = parser->limit;
+
+
+    skip_spaces( &cur, limit );             /* this also skips comments */
+    if ( cur >= limit )
+      goto Exit;
+
+    /* self-delimiting, single-character tokens */
+    if ( *cur == '[' || *cur == ']' ||
+         *cur == '{' || *cur == '}' )
+    {
+      cur++;
+      goto Exit;
+    }
+
+    if ( *cur == '(' )                              /* (...) */
+    {
+      skip_literal_string( &cur, limit );
+      goto Exit;
+    }
+
+    if ( *cur == '<' )                              /* <...> */
+    {
+      if ( cur + 1 < limit && *(cur + 1) == '<' )   /* << */
+      {
+        cur++;
+        cur++;
+        goto Exit;
+      }
+      parser->cursor = cur;
+      skip_string( parser );
+      return;
+    }
+
+    if ( *cur == '>' )
+    {
+      cur++;
+      if ( cur >= limit || *cur != '>' )             /* >> */
+      {
+        parser->error = PSaux_Err_Invalid_File_Format;
+        goto Exit;
+      }
+      cur++;
+      goto Exit;
+    }
+
+    if ( *cur == '/' )
+      cur++;
+
+    /* anything else */
+    while ( cur < limit )
+    {
+      if ( IS_T1_SPACE( *cur )        ||
+           *cur == '('                ||
+           *cur == '/'                ||
+           *cur == '%'                ||
+           *cur == '[' || *cur == ']' ||
+           *cur == '{' || *cur == '}' ||
+           *cur == '<' || *cur == '>' )
+        break;
+
+      if ( *cur == ')' )
+      {
+        parser->error = PSaux_Err_Invalid_File_Format;
+        goto Exit;
+      }
+
+      cur++;
+    }
+
+  Exit:
+    parser->cursor = cur;
   }
 
 
   FT_LOCAL_DEF( void )
-  ps_parser_skip_alpha( PS_Parser  parser )
+  ps_parser_skip_spaces( PS_Parser  parser )
   {
-    skip_alpha( &parser->cursor, parser->limit );
+    skip_spaces( &parser->cursor, parser->limit );
   }
 
 
+  /* `token' here means either something between balanced delimiters */
+  /* or the next token; the delimiters are not removed.              */
+
   FT_LOCAL_DEF( void )
   ps_parser_to_token( PS_Parser  parser,
                       T1_Token   token )
@@ -349,72 +554,87 @@
     token->start = 0;
     token->limit = 0;
 
-    /* first of all, skip space */
+    /* first of all, skip leading whitespace */
     ps_parser_skip_spaces( parser );
 
     cur   = parser->cursor;
     limit = parser->limit;
 
-    if ( cur < limit )
+    if ( cur >= limit )
+      return;
+
+    switch ( *cur )
     {
-      switch ( *cur )
-      {
-        /************* check for strings ***********************/
-      case '(':
-        token->type = T1_TOKEN_TYPE_STRING;
-        ender = ')';
-        goto Lookup_Ender;
+      /************* check for literal string *****************/
+    case '(':
+      token->type  = T1_TOKEN_TYPE_STRING;
+      token->start = cur;
+      skip_literal_string( &cur, limit );
+      if ( cur < limit )
+        token->limit = cur;
+      break;
 
-        /************* check for programs/array ****************/
-      case '{':
-        token->type = T1_TOKEN_TYPE_ARRAY;
-        ender = '}';
-        goto Lookup_Ender;
+      /************* check for programs/array *****************/
+    case '{':
+      token->type = T1_TOKEN_TYPE_ARRAY;
+      ender = '}';
+      goto Lookup_Ender;
 
-        /************* check for table/array ******************/
-      case '[':
-        token->type = T1_TOKEN_TYPE_ARRAY;
-        ender = ']';
+      /************* check for table/array ********************/
+    case '[':
+      token->type = T1_TOKEN_TYPE_ARRAY;
+      ender = ']';
+      /* fall through */
 
-      Lookup_Ender:
-        embed   = 1;
-        starter = *cur++;
-        token->start = cur;
-        while ( cur < limit )
+    Lookup_Ender:
+      embed        = 1;
+      starter      = *cur;
+      token->start = cur++;
+
+      /* we need this to catch `[ ]' */
+      parser->cursor = cur;
+      ps_parser_skip_spaces( parser );
+      cur = parser->cursor;
+
+      while ( cur < limit && !parser->error )
+      {
+        if ( *cur == starter )
+          embed++;
+        else if ( *cur == ender )
         {
-          if ( *cur == starter )
-            embed++;
-          else if ( *cur == ender )
+          embed--;
+          if ( embed <= 0 )
           {
-            embed--;
-            if ( embed <= 0 )
-            {
-              token->limit = cur++;
-              break;
-            }
+            token->limit = ++cur;
+            break;
           }
-          cur++;
         }
-        break;
 
-        /* **************** otherwise, it's any token **********/
-      default:
-        token->start = cur++;
-        token->type  = T1_TOKEN_TYPE_ANY;
-        while ( cur < limit && !IS_T1_SPACE( *cur ) )
-          cur++;
+        parser->cursor = cur;
+        ps_parser_skip_PS_token( parser );
+        /* we need this to catch `[XXX ]' */
+        ps_parser_skip_spaces  ( parser );
+        cur = parser->cursor;
+      }
+      break;
 
+      /* ************ otherwise, it is any token **************/
+    default:
+      token->start = cur;
+      token->type  = T1_TOKEN_TYPE_ANY;
+      ps_parser_skip_PS_token( parser );
+      cur = parser->cursor;
+      if ( !parser->error )
         token->limit = cur;
-      }
+    }
 
-      if ( !token->limit )
-      {
-        token->start = 0;
-        token->type  = T1_TOKEN_TYPE_NONE;
-      }
-
-      parser->cursor = cur;
+    if ( !token->limit )
+    {
+      token->start = 0;
+      token->type  = T1_TOKEN_TYPE_NONE;
     }
+
+    parser->cursor = cur;
   }
 
 
@@ -429,7 +649,9 @@
 
     *pnum_tokens = -1;
 
+    /* this also handles leading whitespace */
     ps_parser_to_token( parser, &master );
+
     if ( master.type == T1_TOKEN_TYPE_ARRAY )
     {
       FT_Byte*  old_cursor = parser->cursor;
@@ -438,8 +660,9 @@
       T1_Token  limit      = cur + max_tokens;
 
 
-      parser->cursor = master.start;
-      parser->limit  = master.limit;
+      /* don't include outermost delimiters */
+      parser->cursor = master.start + 1;
+      parser->limit  = master.limit - 1;
 
       while ( parser->cursor < parser->limit )
       {
@@ -464,37 +687,35 @@
   }
 
 
+  /* first character must be already part of the number */
+
   static FT_Long
   T1Radix( FT_Long    radixBase,
-           FT_Byte**  cur,
+           FT_Byte*  *acur,
            FT_Byte*   limit )
   {
-    FT_Long  result = 0;
-    FT_Byte  radixEndChar0 =
-               (FT_Byte)( radixBase > 10 ? '9' + 1 : '0' + radixBase );
-    FT_Byte  radixEndChar1 =
-               (FT_Byte)( 'A' + radixBase - 10 );
-    FT_Byte  radixEndChar2 =
-               (FT_Byte)( 'a' + radixBase - 10 );
+    FT_Long   result = 0;
+    FT_Byte*  cur    = *acur;
 
 
-    while( *cur < limit )
+    if ( radixBase < 2 || radixBase > 36 )
+      return 0;
+
+    while ( cur < limit )
     {
-      if ( (*cur)[0] >= '0' && (*cur)[0] < radixEndChar0 )
-        result = result * radixBase + (*cur)[0] - '0';
+      int  d;
 
-      else if ( radixBase > 10 &&
-                (*cur)[0] >= 'A' && (*cur)[0] < radixEndChar1 )
-        result = result * radixBase + ( (*cur)[0] - 'A' + 10 );
 
-      else if ( radixBase > 10 &&
-                (*cur)[0] >= 'a' && (*cur)[0] < radixEndChar2 )
-        result = result * radixBase + ( (*cur)[0] - 'a' + 10 );
+      if ( *cur OP 0x80 )
+        break;
 
-      else
-        return result;
+      d = ft_char_table[*cur & 0x7F];
+      if ( d < 0 || d >= radixBase )
+        break;
 
-      (*cur)++;
+      result = result * radixBase + d;
+
+      cur++;
     }
 
     return result;
@@ -501,113 +722,126 @@
   }
 
 
+  /* first character must be already part of the number */
+
   static FT_Long
-  t1_toint( FT_Byte**  cursor,
+  ps_toint( FT_Byte*  *acur,
             FT_Byte*   limit )
   {
     FT_Long   result = 0;
-    FT_Byte*  cur    = *cursor;
-    FT_Byte   c      = '\0', d;
+    FT_Byte*  cur    = *acur;
+    FT_Byte   c;
 
 
-    for ( ; cur < limit; cur++ )
+    if ( cur >= limit )
+      goto Exit;
+
+    c = *cur;
+    if ( c == '-' )
+      cur++;
+
+    while ( cur < limit )
     {
-      c = *cur;
-      d = (FT_Byte)( c - '0' );
-      if ( d < 10 )
-        break;
+      int  d;
 
-      if ( c == '-' )
+
+      if ( *cur == '#' )
       {
         cur++;
+        result = T1Radix( result, &cur, limit );
         break;
       }
-    }
 
-    if ( cur < limit )
-    {
-      do
-      {
-        d = (FT_Byte)( cur[0] - '0' );
-        if ( d >= 10 )
-        {
-          if ( cur[0] == '#' )
-          {
-            cur++;
-            result = T1Radix( result, &cur, limit );
-          }
-          break;
-        }
+      if ( *cur OP 0x80 )
+        break;
 
-        result = result * 10 + d;
-        cur++;
+      d = ft_char_table[*cur & 0x7F];
+      if ( d < 0 || d >= 10 )
+        break;
+      result = result * 10 + d;
 
-      } while ( cur < limit );
+      cur++;
+    };
 
-      if ( c == '-' )
-        result = -result;
-    }
+    if ( c == '-' )
+      result = -result;
 
-    *cursor = cur;
+  Exit:
+    *acur = cur;
     return result;
   }
 
 
-  /* <...>: hexadecimal string */
+  /* first character must be `<' if `delimiters' is non-zero */
+
   static FT_Error
-  ps_tobytes( FT_Byte**  cursor,
+  ps_tobytes( FT_Byte*  *acur,
               FT_Byte*   limit,
-              FT_Int     max_bytes,
+              FT_Long    max_bytes,
               FT_Byte*   bytes,
-              FT_Int*    pnum_bytes )
+              FT_Long*   pnum_bytes,
+              FT_Bool    delimiters )
   {
     FT_Error  error = PSaux_Err_Ok;
 
-    FT_Byte*  cur = *cursor;
-    FT_Int    n   = 0;
-    FT_Byte   b;
+    FT_Byte*  cur = *acur;
+    FT_Long   n;
 
 
-    skip_spaces( &cur, limit );
+    if ( cur >= limit )
+      goto Exit;
 
-    if ( *cur != '<' )
+    if ( delimiters )
     {
-      error = PSaux_Err_Invalid_File_Format;
-      goto Exit;
+      if ( *cur != '<' )
+      {
+        error = PSaux_Err_Invalid_File_Format;
+        goto Exit;
+      }
+
+      cur++;
     }
 
-    cur++;
+    max_bytes = max_bytes * 2;
 
-    for ( ; cur < limit; n++ )
+    for ( n = 0; cur < limit; n++, cur++ )
     {
-      FT_Byte*  cur2 = cur;
+      int  d;
 
 
-      if ( n + 1 > max_bytes * 2 )
+      if ( n >= max_bytes )
+        /* buffer is full */
         goto Exit;
 
-      /* All white-space charcters are ignored. */
+      /* All whitespace characters are ignored. */
       skip_spaces( &cur, limit );
+      if ( cur >= limit )
+        break;
 
-      b = (FT_Byte) T1Radix( 16, &cur, cur + 1 );
+      if ( *cur OP 0x80 )
+        break;
 
-      if ( cur == cur2 )
+      d = ft_char_table[*cur & 0x7F];
+      if ( d < 0 || d >= 16 )
         break;
 
       /* <f> == <f0> != <0f> */
-      bytes[n / 2] = (FT_Byte)( ( n % 2 ) ? bytes[n / 2] + b
-                                          : b * 16 );
+      bytes[n / 2] = (FT_Byte)( ( n % 2 ) ? bytes[n / 2] + d
+                                          : d * 16 );
     }
 
-    skip_spaces( &cur, limit );
-
-    if ( *cur != '>' )
+    if ( delimiters )
     {
-      error = PSaux_Err_Invalid_File_Format;
-      goto Exit;
+      if ( cur < limit && *cur != '>' )
+      {
+        error = PSaux_Err_Invalid_File_Format;
+        goto Exit;
+      }
+
+      cur++;
     }
 
-    *cursor = ++cur;
+    *acur = cur;
 
   Exit:
     *pnum_bytes = ( n + 1 ) / 2;
@@ -616,15 +850,16 @@
   }
 
 
+  /* first character must be already part of the number */
+
   static FT_Long
-  t1_tofixed( FT_Byte**  cursor,
+  ps_tofixed( FT_Byte*  *acur,
               FT_Byte*   limit,
               FT_Long    power_ten )
   {
-    FT_Byte*  cur  = *cursor;
+    FT_Byte*  cur  = *acur;
     FT_Long   num, divider, result;
     FT_Int    sign = 0;
-    FT_Byte   d;
 
 
     if ( cur >= limit )
@@ -631,7 +866,7 @@
       return 0;
 
     /* first of all, check the sign */
-    if ( *cur == '-' )
+    if ( *cur == '-' && cur + 1 < limit )
     {
       sign = 1;
       cur++;
@@ -639,7 +874,7 @@
 
     /* then, read the integer part, if any */
     if ( *cur != '.' )
-      result = t1_toint( &cur, limit ) << 16;
+      result = ps_toint( &cur, limit ) << 16;
     else
       result = 0;
 
@@ -656,10 +891,16 @@
 
       for (;;)
       {
-        d = (FT_Byte)( *cur - '0' );
-        if ( d >= 10 )
+        int  d;
+
+
+        if ( *cur OP 0x80 )
           break;
 
+        d = ft_char_table[*cur & 0x7F];
+        if ( d < 0 || d >= 10 )
+          break;
+
         if ( divider < 10000000L )
         {
           num      = num * 10 + d;
@@ -676,7 +917,7 @@
     if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) )
     {
       cur++;
-      power_ten += t1_toint( &cur, limit );
+      power_ten += ps_toint( &cur, limit );
     }
 
   Exit:
@@ -701,18 +942,20 @@
     if ( sign )
       result = -result;
 
-    *cursor = cur;
+    *acur = cur;
     return result;
   }
 
 
+  /* first character must be a delimiter or a part of a number */
+
   static FT_Int
-  t1_tocoordarray( FT_Byte**  cursor,
+  ps_tocoordarray( FT_Byte*  *acur,
                    FT_Byte*   limit,
                    FT_Int     max_coords,
                    FT_Short*  coords )
   {
-    FT_Byte*  cur   = *cursor;
+    FT_Byte*  cur   = *acur;
     FT_Int    count = 0;
     FT_Byte   c, ender;
 
@@ -720,8 +963,8 @@
     if ( cur >= limit )
       goto Exit;
 
-    /* check for the beginning of an array; if not, only one number will */
-    /* be read                                                           */
+    /* check for the beginning of an array; otherwise, only one number */
+    /* will be read                                                    */
     c     = *cur;
     ender = 0;
 
@@ -735,24 +978,23 @@
       cur++;
 
     /* now, read the coordinates */
-    for ( ; cur < limit; )
+    while ( cur < limit )
     {
       /* skip whitespace in front of data */
-      for (;;)
-      {
-        c = *cur;
-        if ( c != ' ' && c != '\t' )
-          break;
+      skip_spaces( &cur, limit );
+      if ( cur >= limit )
+        goto Exit;
 
+      if ( count >= max_coords )
+        break;
+
+      if ( c == ender )
+      {
         cur++;
-        if ( cur >= limit )
-          goto Exit;
+        break;
       }
 
-      if ( count >= max_coords || c == ender )
-        break;
-
-      coords[count] = (FT_Short)( t1_tofixed( &cur, limit, 0 ) >> 16 );
+      coords[count] = (FT_Short)( ps_tofixed( &cur, limit, 0 ) >> 16 );
       count++;
 
       if ( !ender )
@@ -760,27 +1002,30 @@
     }
 
   Exit:
-    *cursor = cur;
+    *acur = cur;
     return count;
   }
 
 
+  /* first character must be a delimiter or a part of a number */
+
   static FT_Int
-  t1_tofixedarray( FT_Byte**  cursor,
+  ps_tofixedarray( FT_Byte*  *acur,
                    FT_Byte*   limit,
                    FT_Int     max_values,
                    FT_Fixed*  values,
                    FT_Int     power_ten )
   {
-    FT_Byte*  cur   = *cursor;
+    FT_Byte*  cur   = *acur;
     FT_Int    count = 0;
     FT_Byte   c, ender;
 
 
-    if ( cur >= limit ) goto Exit;
+    if ( cur >= limit )
+      goto Exit;
 
-    /* check for the beginning of an array. If not, only one number will */
-    /* be read                                                           */
+    /* Check for the beginning of an array.  Otherwise, only one number */
+    /* will be read.                                                    */
     c     = *cur;
     ender = 0;
 
@@ -794,24 +1039,23 @@
       cur++;
 
     /* now, read the values */
-    for ( ; cur < limit; )
+    while ( cur < limit )
     {
       /* skip whitespace in front of data */
-      for (;;)
-      {
-        c = *cur;
-        if ( c != ' ' && c != '\t' )
-          break;
+      skip_spaces( &cur, limit );
+      if ( cur >= limit )
+        goto Exit;
 
+      if ( count >= max_values )
+        break;
+
+      if ( c == ender )
+      {
         cur++;
-        if ( cur >= limit )
-          goto Exit;
+        break;
       }
 
-      if ( count >= max_values || c == ender )
-        break;
-
-      values[count] = t1_tofixed( &cur, limit, power_ten );
+      values[count] = ps_tofixed( &cur, limit, power_ten );
       count++;
 
       if ( !ender )
@@ -819,7 +1063,7 @@
     }
 
   Exit:
-    *cursor = cur;
+    *acur = cur;
     return count;
   }
 
@@ -827,7 +1071,7 @@
 #if 0
 
   static FT_String*
-  t1_tostring( FT_Byte**  cursor,
+  ps_tostring( FT_Byte**  cursor,
                FT_Byte*   limit,
                FT_Memory  memory )
   {
@@ -887,40 +1131,41 @@
 
 
   static int
-  t1_tobool( FT_Byte**  cursor,
+  ps_tobool( FT_Byte*  *acur,
              FT_Byte*   limit )
   {
-    FT_Byte*  cur    = *cursor;
+    FT_Byte*  cur    = *acur;
     FT_Bool   result = 0;
 
 
     /* return 1 if we find `true', 0 otherwise */
     if ( cur + 3 < limit &&
-         cur[0] == 't' &&
-         cur[1] == 'r' &&
-         cur[2] == 'u' &&
-         cur[3] == 'e' )
+         cur[0] == 't'   &&
+         cur[1] == 'r'   &&
+         cur[2] == 'u'   &&
+         cur[3] == 'e'   )
     {
       result = 1;
       cur   += 5;
     }
     else if ( cur + 4 < limit &&
-              cur[0] == 'f' &&
-              cur[1] == 'a' &&
-              cur[2] == 'l' &&
-              cur[3] == 's' &&
-              cur[4] == 'e' )
+              cur[0] == 'f'   &&
+              cur[1] == 'a'   &&
+              cur[2] == 'l'   &&
+              cur[3] == 's'   &&
+              cur[4] == 'e'   )
     {
       result = 0;
       cur   += 6;
     }
 
-    *cursor = cur;
+    *acur = cur;
     return result;
   }
 
 
-  /* Load a simple field (i.e. non-table) into the current list of objects */
+  /* load a simple field (i.e. non-table) into the current list of objects */
+
   FT_LOCAL_DEF( FT_Error )
   ps_parser_load_field( PS_Parser       parser,
                         const T1_Field  field,
@@ -936,6 +1181,7 @@
     FT_Error     error;
 
 
+    /* this also skips leading whitespace */
     ps_parser_to_token( parser, &token );
     if ( !token.type )
       goto Fail;
@@ -945,7 +1191,7 @@
     cur   = token.start;
     limit = token.limit;
 
-    /* we must detect arrays */
+    /* we must detect arrays in /FontBBox */
     if ( field->type == T1_FIELD_TYPE_BBOX )
     {
       T1_TokenRec  token2;
@@ -953,8 +1199,9 @@
       FT_Byte*     old_limit = parser->limit;
 
 
-      parser->cursor = token.start;
-      parser->limit  = token.limit;
+      /* don't include delimiters */
+      parser->cursor = token.start + 1;
+      parser->limit  = token.limit - 1;
 
       ps_parser_to_token( parser, &token2 );
       parser->cursor = old_cur;
@@ -966,12 +1213,16 @@
     else if ( token.type == T1_TOKEN_TYPE_ARRAY )
     {
     FieldArray:
-      /* if this is an array, and we have no blend, an error occurs */
+      /* if this is an array and we have no blend, an error occurs */
       if ( max_objects == 0 )
         goto Fail;
 
       count = max_objects;
-      idx = 1;
+      idx   = 1;
+
+      /* don't include delimiters */
+      cur++;
+      limit--;
     }
 
     for ( ; count > 0; count--, idx++ )
@@ -981,23 +1232,25 @@
       FT_String*  string;
 
 
+      skip_spaces( &cur, limit );
+
       switch ( field->type )
       {
       case T1_FIELD_TYPE_BOOL:
-        val = t1_tobool( &cur, limit );
+        val = ps_tobool( &cur, limit );
         goto Store_Integer;
 
       case T1_FIELD_TYPE_FIXED:
-        val = t1_tofixed( &cur, limit, 0 );
+        val = ps_tofixed( &cur, limit, 0 );
         goto Store_Integer;
 
       case T1_FIELD_TYPE_FIXED_1000:
-        val = t1_tofixed( &cur, limit, 3 );
+        val = ps_tofixed( &cur, limit, 3 );
         goto Store_Integer;
 
       case T1_FIELD_TYPE_INTEGER:
-        val = t1_toint( &cur, limit );
-        goto Store_Integer;
+        val = ps_toint( &cur, limit );
+        /* fall through */
 
       Store_Integer:
         switch ( field->size )
@@ -1026,15 +1279,25 @@
           FT_UInt    len    = (FT_UInt)( limit - cur );
 
 
-          /* with synthetic fonts, it's possible to find a field twice */
+          if ( cur >= limit )
+            break;
+
+          /* with synthetic fonts, it is possible to find a field twice */
           if ( *(FT_String**)q )
             break;
 
           if ( field->type == T1_FIELD_TYPE_KEY )
           {
+            /* don't include leading `/' */
             len--;
             cur++;
           }
+          else
+          {
+            /* don't include delimiting parentheses */
+            cur++;
+            len -= 2;
+          }
 
           if ( FT_ALLOC( string, len + 1 ) )
             goto Exit;
@@ -1052,10 +1315,7 @@
           FT_BBox*  bbox = (FT_BBox*)q;
 
 
-          /* we need the '[' and ']' delimiters */
-          token.start--;
-          token.limit++;
-          (void)t1_tofixedarray( &token.start, token.limit, 4, temp, 0 );
+          (void)ps_tofixedarray( &token.start, token.limit, 4, temp, 0 );
 
           bbox->xMin = FT_RoundFix( temp[0] );
           bbox->yMin = FT_RoundFix( temp[1] );
@@ -1070,7 +1330,7 @@
       }
     }
 
-#if 0  /* obsolete - keep for reference */
+#if 0  /* obsolete -- keep for reference */
     if ( pflags )
       *pflags |= 1L << field->flag_bit;
 #else
@@ -1113,7 +1373,8 @@
       fieldrec.type = T1_FIELD_TYPE_FIXED;
 #endif
 
-    ps_parser_to_token_array( parser, elements, 32, &num_elements );
+    ps_parser_to_token_array( parser, elements,
+                              T1_MAX_TABLE_ELEMENTS, &num_elements );
     if ( num_elements < 0 )
       goto Fail;
 
@@ -1159,7 +1420,8 @@
   FT_LOCAL_DEF( FT_Long )
   ps_parser_to_int( PS_Parser  parser )
   {
-    return t1_toint( &parser->cursor, parser->limit );
+    ps_parser_skip_spaces( parser );
+    return ps_toint( &parser->cursor, parser->limit );
   }
 
 
@@ -1166,14 +1428,17 @@
   FT_LOCAL_DEF( FT_Error )
   ps_parser_to_bytes( PS_Parser  parser,
                       FT_Byte*   bytes,
-                      FT_Int     max_bytes,
-                      FT_Int*    pnum_bytes )
+                      FT_Long    max_bytes,
+                      FT_Long*   pnum_bytes,
+                      FT_Bool    delimiters )
   {
+    ps_parser_skip_spaces( parser );
     return ps_tobytes( &parser->cursor,
                        parser->limit,
                        max_bytes,
                        bytes,
-                       pnum_bytes );
+                       pnum_bytes,
+                       delimiters );
   }
 
 
@@ -1181,7 +1446,8 @@
   ps_parser_to_fixed( PS_Parser  parser,
                       FT_Int     power_ten )
   {
-    return t1_tofixed( &parser->cursor, parser->limit, power_ten );
+    ps_parser_skip_spaces( parser );
+    return ps_tofixed( &parser->cursor, parser->limit, power_ten );
   }
 
 
@@ -1190,7 +1456,8 @@
                             FT_Int     max_coords,
                             FT_Short*  coords )
   {
-    return t1_tocoordarray( &parser->cursor, parser->limit,
+    ps_parser_skip_spaces( parser );
+    return ps_tocoordarray( &parser->cursor, parser->limit,
                             max_coords, coords );
   }
 
@@ -1201,7 +1468,8 @@
                             FT_Fixed*  values,
                             FT_Int     power_ten )
   {
-    return t1_tofixedarray( &parser->cursor, parser->limit,
+    ps_parser_skip_spaces( parser );
+    return ps_tofixedarray( &parser->cursor, parser->limit,
                             max_values, values, power_ten );
   }
 
@@ -1211,7 +1479,7 @@
   FT_LOCAL_DEF( FT_String* )
   T1_ToString( PS_Parser  parser )
   {
-    return t1_tostring( &parser->cursor, parser->limit, parser->memory );
+    return ps_tostring( &parser->cursor, parser->limit, parser->memory );
   }
 
 
@@ -1218,7 +1486,7 @@
   FT_LOCAL_DEF( FT_Bool )
   T1_ToBool( PS_Parser  parser )
   {
-    return t1_tobool( &parser->cursor, parser->limit );
+    return ps_tobool( &parser->cursor, parser->limit );
   }
 
 #endif /* 0 */
@@ -1230,7 +1498,7 @@
                   FT_Byte*   limit,
                   FT_Memory  memory )
   {
-    parser->error  = 0;
+    parser->error  = PSaux_Err_Ok;
     parser->base   = base;
     parser->limit  = limit;
     parser->cursor = base;
--- a/src/psaux/psobjs.h
+++ b/src/psaux/psobjs.h
@@ -78,7 +78,7 @@
   ps_parser_skip_spaces( PS_Parser  parser );
 
   FT_LOCAL( void )
-  ps_parser_skip_alpha( PS_Parser  parser );
+  ps_parser_skip_PS_token( PS_Parser  parser );
 
   FT_LOCAL( void )
   ps_parser_to_token( PS_Parser  parser,
@@ -111,8 +111,9 @@
   FT_LOCAL( FT_Error )
   ps_parser_to_bytes( PS_Parser  parser,
                       FT_Byte*   bytes,
-                      FT_Int     max_bytes,
-                      FT_Int*    pnum_bytes );
+                      FT_Long    max_bytes,
+                      FT_Long*   pnum_bytes,
+                      FT_Bool    delimiters );
 
 
   FT_LOCAL( FT_Fixed )
--- a/src/type1/t1load.c
+++ b/src/type1/t1load.c
@@ -41,12 +41,11 @@
   /*                                                                       */
   /* All other common cases are handled very simply.  The matching rules   */
   /* are defined in the file `t1tokens.h' through the use of several       */
-  /* macros calls PARSE_XXX.                                               */
+  /* macros calls PARSE_XXX.  This file is included twice here; the first  */
+  /* time to generate parsing callback functions, the second time to       */
+  /* generate a table of keywords (with pointers to the associated         */
+  /* callback functions).                                                  */
   /*                                                                       */
-  /* This file is included twice here; the first time to generate parsing  */
-  /* callback functions, the second to generate a table of keywords (with  */
-  /* pointers to the associated callback).                                 */
-  /*                                                                       */
   /* The function `parse_dict' simply scans *linearly* a given dictionary  */
   /* (either the top-level or private one) and calls the appropriate       */
   /* callback when it encounters an immediate keyword.                     */
@@ -71,7 +70,6 @@
 #include "t1errors.h"
 
 
-
   /*************************************************************************/
   /*                                                                       */
   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
@@ -100,7 +98,7 @@
   {
     PS_Blend   blend;
     FT_Memory  memory = face->root.memory;
-    FT_Error   error  = 0;
+    FT_Error   error  = T1_Err_Ok;
 
 
     blend = face->blend;
@@ -174,7 +172,7 @@
     return error;
 
   Fail:
-    error = -1;
+    error = T1_Err_Invalid_File_Format;
     goto Exit;
   }
 
@@ -205,8 +203,10 @@
         axis->minimum = map->design_points[0];
         axis->maximum = map->design_points[map->num_points - 1];
       }
-      error = 0;
+
+      error = T1_Err_Ok;
     }
+
     return error;
   }
 
@@ -253,6 +253,7 @@
 
       error = T1_Err_Ok;
     }
+
     return error;
   }
 
@@ -289,7 +290,7 @@
           FT_Fixed  p_design = designs[p];
 
 
-          /* exact match ? */
+          /* exact match? */
           if ( design == p_design )
           {
             the_blend = blends[p];
@@ -305,7 +306,7 @@
           before = p;
         }
 
-        /* now, interpolate if needed */
+        /* now interpolate if necessary */
         if ( before < 0 )
           the_blend = blends[0];
 
@@ -386,9 +387,9 @@
   parse_blend_axis_types( T1_Face    face,
                           T1_Loader  loader )
   {
-    T1_TokenRec  axis_tokens[ T1_MAX_MM_AXIS ];
+    T1_TokenRec  axis_tokens[T1_MAX_MM_AXIS];
     FT_Int       n, num_axis;
-    FT_Error     error = 0;
+    FT_Error     error = T1_Err_Ok;
     PS_Blend     blend;
     FT_Memory    memory;
 
@@ -448,16 +449,16 @@
   parse_blend_design_positions( T1_Face    face,
                                 T1_Loader  loader )
   {
-    T1_TokenRec  design_tokens[ T1_MAX_MM_DESIGNS ];
+    T1_TokenRec  design_tokens[T1_MAX_MM_DESIGNS];
     FT_Int       num_designs;
     FT_Int       num_axis;
     T1_Parser    parser = &loader->parser;
 
-    FT_Error     error = 0;
+    FT_Error     error = T1_Err_Ok;
     PS_Blend     blend;
 
 
-    /* get the array of design tokens - compute number of designs */
+    /* get the array of design tokens -- compute number of designs */
     T1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs );
     if ( num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS )
     {
@@ -479,7 +480,7 @@
 
       for ( n = 0; n < (FT_UInt)num_designs; n++ )
       {
-        T1_TokenRec  axis_tokens[ T1_MAX_MM_DESIGNS ];
+        T1_TokenRec  axis_tokens[T1_MAX_MM_DESIGNS];
         T1_Token     token;
         FT_Int       axis, n_axis;
 
@@ -486,8 +487,8 @@
 
         /* read axis/coordinates tokens */
         token = design_tokens + n;
-        parser->root.cursor = token->start - 1;
-        parser->root.limit  = token->limit + 1;
+        parser->root.cursor = token->start;
+        parser->root.limit  = token->limit;
         T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
 
         if ( n == 0 )
@@ -505,7 +506,7 @@
           goto Exit;
         }
 
-        /* now, read each axis token into the design position */
+        /* now read each axis token into the design position */
         for ( axis = 0; axis < n_axis; axis++ )
         {
           T1_Token  token2 = axis_tokens + axis;
@@ -530,7 +531,7 @@
   parse_blend_design_map( T1_Face    face,
                           T1_Loader  loader )
   {
-    FT_Error     error  = 0;
+    FT_Error     error  = T1_Err_Ok;
     T1_Parser    parser = &loader->parser;
     PS_Blend     blend;
     T1_TokenRec  axis_tokens[T1_MAX_MM_AXIS];
@@ -548,6 +549,7 @@
       error = T1_Err_Invalid_File_Format;
       goto Exit;
     }
+
     old_cursor = parser->root.cursor;
     old_limit  = parser->root.limit;
 
@@ -556,29 +558,22 @@
       goto Exit;
     blend = face->blend;
 
-    /* now, read each axis design map */
+    /* now read each axis design map */
     for ( n = 0; n < num_axis; n++ )
     {
       PS_DesignMap  map = blend->design_map + n;
-      T1_Token      token;
+      T1_Token      axis_token;
+      T1_TokenRec   point_tokens[T1_MAX_MM_MAP_POINTS];
       FT_Int        p, num_points;
 
 
-      token = axis_tokens + n;
-      parser->root.cursor = token->start;
-      parser->root.limit  = token->limit;
+      axis_token = axis_tokens + n;
 
-      /* count the number of map points */
-      {
-        FT_Byte*  ptr   = token->start;
-        FT_Byte*  limit = token->limit;
+      parser->root.cursor = axis_token->start;
+      parser->root.limit  = axis_token->limit;
+      T1_ToTokenArray( parser, point_tokens,
+                       T1_MAX_MM_MAP_POINTS, &num_points );
 
-
-        num_points = 0;
-        for ( ; ptr < limit; ptr++ )
-          if ( ptr[0] == '[' )
-            num_points++;
-      }
       if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
       {
         FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
@@ -594,6 +589,15 @@
 
       for ( p = 0; p < num_points; p++ )
       {
+        T1_Token  point_token;
+
+
+        point_token = point_tokens + p;
+
+        /* don't include delimiting brackets */
+        parser->root.cursor = point_token->start + 1;
+        parser->root.limit  = point_token->limit - 1;
+
         map->design_points[p] = T1_ToInt( parser );
         map->blend_points [p] = T1_ToFixed( parser, 0 );
       }
@@ -611,7 +615,7 @@
   parse_weight_vector( T1_Face    face,
                        T1_Loader  loader )
   {
-    FT_Error     error  = 0;
+    FT_Error     error  = T1_Err_Ok;
     T1_Parser    parser = &loader->parser;
     PS_Blend     blend  = face->blend;
     T1_TokenRec  master;
@@ -638,8 +642,9 @@
     old_cursor = parser->root.cursor;
     old_limit  = parser->root.limit;
 
-    parser->root.cursor = master.start;
-    parser->root.limit  = master.limit;
+    /* don't include the delimiting brackets */
+    parser->root.cursor = master.start + 1;
+    parser->root.limit  = master.limit - 1;
 
     for ( n = 0; n < blend->num_designs; n++ )
     {
@@ -675,6 +680,8 @@
 #endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */
 
 
+
+
   /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
@@ -683,15 +690,6 @@
   /*************************************************************************/
   /*************************************************************************/
 
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* First of all, define the token field static variables.  This is a set */
-  /* of T1_FieldRec variables used later.                                  */
-  /*                                                                       */
-  /*************************************************************************/
-
-
   static FT_Error
   t1_load_keyword( T1_Face         face,
                    T1_Loader       loader,
@@ -774,33 +772,13 @@
   static int
   is_space( FT_Byte  c )
   {
-    return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
+    return ( c == ' '  || c == '\t' ||
+             c == '\r' || c == '\n' || c == '\f' ||
+             c == '\0' );
   }
 
 
   static int
-  is_name_char( FT_Byte  c )
-  {
-    /* Note: PostScript allows any non-delimiting, non-whitespace      */
-    /*       in a name (PS Ref Manual, 3rd Ed, p31)                    */
-    /*       PostScript delimiters include (,),<,>,[,],{,},/ and %     */
-
-    return ( c != '(' &&
-             c != ')' &&
-             c != '<' &&
-             c != '>' &&
-             c != '[' &&
-             c != ']' &&
-             c != '{' &&
-             c != '}' &&
-             c != '/' &&
-             c != '%' &&
-             ! is_space( c )
-             );
- }
-
-
-  static int
   read_binary_data( T1_Parser  parser,
                     FT_Long*   size,
                     FT_Byte**  base )
@@ -815,14 +793,14 @@
     /*                                          */
 
     T1_Skip_Spaces( parser );
+
     cur = parser->root.cursor;
 
-    if ( cur < limit && (FT_Byte)( *cur - '0' ) < 10 )
+    if ( cur < limit && ft_isdigit( *cur ) )
     {
       *size = T1_ToInt( parser );
 
-      T1_Skip_Spaces( parser );
-      T1_Skip_Alpha ( parser );  /* `RD' or `-|' or something else */
+      T1_Skip_PS_Token( parser );   /* `RD' or `-|' or something else */
 
       /* there is only one whitespace char after the */
       /* `RD' or `-|' token                          */
@@ -838,9 +816,8 @@
   }
 
 
-  /* we will now define the routines used to handle */
-  /* the `/Encoding', `/Subrs', and `/CharStrings'  */
-  /* dictionaries                                   */
+  /* We now define the routines to handle the `/Encoding', `/Subrs', */
+  /* and `/CharStrings' dictionaries.                                */
 
   static void
   parse_font_matrix( T1_Face    face,
@@ -855,7 +832,7 @@
 
 
     if ( matrix->xx || matrix->yx )
-      /* with synthetic fonts, it's possible we get here twice  */
+      /* with synthetic fonts it is possible we get here twice */
       return;
 
     (void)T1_ToFixedArray( parser, 6, temp, 3 );
@@ -895,28 +872,25 @@
   parse_encoding( T1_Face    face,
                   T1_Loader  loader )
   {
-    T1_Parser      parser = &loader->parser;
-    FT_Byte*       cur    = parser->root.cursor;
-    FT_Byte*       limit  = parser->root.limit;
+    T1_Parser  parser = &loader->parser;
+    FT_Byte*   cur;
+    FT_Byte*   limit  = parser->root.limit;
 
-    PSAux_Service  psaux  = (PSAux_Service)face->psaux;
+    PSAux_Service  psaux = (PSAux_Service)face->psaux;
 
 
-    /* skip whitespace */
-    while ( is_space( *cur ) )
+    T1_Skip_Spaces( parser );
+    cur = parser->root.cursor;
+    if ( cur >= limit )
     {
-      cur++;
-      if ( cur >= limit )
-      {
-        FT_ERROR(( "parse_encoding: out of bounds!\n" ));
-        parser->root.error = T1_Err_Invalid_File_Format;
-        return;
-      }
+      FT_ERROR(( "parse_encoding: out of bounds!\n" ));
+      parser->root.error = T1_Err_Invalid_File_Format;
+      return;
     }
 
     /* if we have a number, then the encoding is an array, */
     /* and we must load it now                             */
-    if ( (FT_Byte)( *cur - '0' ) < 10 )
+    if ( ft_isdigit( *cur ) )
     {
       T1_Encoding  encode     = &face->type1.encoding;
       FT_Int       count, n;
@@ -926,18 +900,19 @@
 
 
       if ( encode->char_index )
-        /*  with synthetic fonts, it's possible we get here twice  */
+        /* with synthetic fonts it is possible we get here twice */
         return;
 
-      /* read the number of entries in the encoding, should be 256 */
+      /* read the number of entries in the encoding; should be 256 */
       count = (FT_Int)T1_ToInt( parser );
-      if ( parser->root.error )
+      T1_Skip_Spaces( parser );
+      if ( parser->root.cursor >= limit )
         return;
 
       /* we use a T1_Table to store our charnames */
       loader->num_chars = encode->num_chars = count;
-      if ( FT_NEW_ARRAY( encode->char_index, count ) ||
-           FT_NEW_ARRAY( encode->char_name,  count ) ||
+      if ( FT_NEW_ARRAY( encode->char_index, count )     ||
+           FT_NEW_ARRAY( encode->char_name,  count )     ||
            FT_SET_ERROR( psaux->ps_table_funcs->init(
                            char_table, count, memory ) ) )
       {
@@ -954,86 +929,74 @@
         T1_Add_Table( char_table, n, notdef, 8 );
       }
 
-      /* Now, we will need to read a record of the form         */
+      /* Now we need to read a record of the form               */
       /* ... charcode /charname ... for each entry in our table */
       /*                                                        */
       /* We simply look for a number followed by an immediate   */
       /* name.  Note that this ignores correctly the sequence   */
-      /* that is often seen in type1 fonts:                     */
+      /* that is often seen in Type 1 fonts:                    */
       /*                                                        */
       /*   0 1 255 { 1 index exch /.notdef put } for dup        */
       /*                                                        */
       /* used to clean the encoding array before anything else. */
-      /*                                                        */
-      /* We stop when we encounter a `def'.                     */
 
-      cur   = parser->root.cursor;
-      limit = parser->root.limit;
-      n     = 0;
+      n = 0;
 
-      for ( ; cur < limit; )
+      while ( parser->root.cursor < limit )
       {
-        FT_Byte  c;
+        T1_Skip_Spaces( parser );
+        cur = parser->root.cursor;
 
-
-        c = *cur;
-
         /* we stop when we encounter a `def' */
-        if ( c == 'd' && cur + 3 < limit )
+        if ( *cur == 'd' && cur + 3 < limit )
         {
-          if ( cur[1] == 'e'       &&
-               cur[2] == 'f'       &&
-               is_space( cur[-1] ) &&
-               is_space( cur[3] )  )
+          if ( cur[1] == 'e'      &&
+               cur[2] == 'f'      &&
+               is_space( cur[3] ) )
           {
             FT_TRACE6(( "encoding end\n" ));
+            cur += 3;
             break;
           }
         }
 
         /* otherwise, we must find a number before anything else */
-        if ( (FT_Byte)( c - '0' ) < 10 )
+        if ( ft_isdigit( *cur ) )
         {
           FT_Int  charcode;
 
 
-          parser->root.cursor = cur;
           charcode = (FT_Int)T1_ToInt( parser );
-          cur      = parser->root.cursor;
+          T1_Skip_Spaces( parser );
+          cur = parser->root.cursor;
 
-          /* skip whitespace */
-          while ( cur < limit && is_space( *cur ) )
-            cur++;
-
-          if ( cur < limit && *cur == '/' )
+          if ( *cur == '/' && cur + 2 < limit )
           {
-            /* bingo, we have an immediate name -- it must be a */
-            /* character name                                   */
-            FT_Byte*    cur2 = cur + 1;
             FT_PtrDist  len;
 
 
-            while ( cur2 < limit && is_name_char( *cur2 ) )
-              cur2++;
+            cur++;
 
-            len = cur2 - cur - 1;
+            parser->root.cursor = cur;
+            T1_Skip_PS_Token( parser );
 
+            len = parser->root.cursor - cur;
+
             parser->root.error = T1_Add_Table( char_table, charcode,
-                                               cur + 1, len + 1 );
+                                               cur, len + 1 );
             char_table->elements[charcode][len] = '\0';
             if ( parser->root.error )
               return;
-
-            cur = cur2;
           }
         }
         else
-          cur++;
+          T1_Skip_PS_Token( parser );
       }
 
       face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;
       parser->root.cursor       = cur;
     }
+
     /* Otherwise, we should have either `StandardEncoding', */
     /* `ExpertEncoding', or `ISOLatin1Encoding'             */
     else
@@ -1063,35 +1026,38 @@
   parse_subrs( T1_Face    face,
                T1_Loader  loader )
   {
-    T1_Parser      parser = &loader->parser;
-    PS_Table       table  = &loader->subrs;
-    FT_Memory      memory = parser->root.memory;
-    FT_Error       error;
-    FT_Int         n;
+    T1_Parser  parser = &loader->parser;
+    PS_Table   table  = &loader->subrs;
+    FT_Memory  memory = parser->root.memory;
+    FT_Error   error;
+    FT_Int     n;
 
     PSAux_Service  psaux  = (PSAux_Service)face->psaux;
 
 
     if ( loader->num_subrs )
-      /*  with synthetic fonts, it's possible we get here twice  */
+      /* with synthetic fonts it is possible we get here twice */
       return;
 
-    if ( parser->root.cursor + 2 > parser->root.limit &&
-         parser->root.cursor[0] == '['                &&
-         parser->root.cursor[1] == ']'                )
+    T1_Skip_Spaces( parser );
+
+    /* test for empty array */
+    if ( parser->root.cursor < parser->root.limit &&
+         *parser->root.cursor == '['              )
     {
-      /* empty array */
+      T1_Skip_PS_Token( parser );
+      T1_Skip_Spaces  ( parser );
+      if ( parser->root.cursor >= parser->root.limit ||
+           *parser->root.cursor != ']'              )
+        parser->root.error = T1_Err_Invalid_File_Format;
       return;
     }
 
     loader->num_subrs = (FT_Int)T1_ToInt( parser );
-    if ( parser->root.error )
-      return;
 
     /* position the parser right before the `dup' of the first subr */
-    T1_Skip_Spaces( parser );
-    T1_Skip_Alpha( parser );      /* `array' */
-    T1_Skip_Spaces( parser );
+    T1_Skip_PS_Token( parser );         /* `array' */
+    T1_Skip_Spaces  ( parser );
 
     /* initialize subrs array */
     error = psaux->ps_table_funcs->init( table, loader->num_subrs, memory );
@@ -1113,6 +1079,8 @@
       if ( ft_strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 )
         break;
 
+      T1_Skip_PS_Token( parser );       /* `dup' */
+
       idx = T1_ToInt( parser );
 
       if ( !read_binary_data( parser, &size, &base ) )
@@ -1122,14 +1090,13 @@
       /* (bound to `noaccess put') or by two separate tokens:  */
       /* `noaccess' & `put'.  We position the parser right     */
       /* before the next `dup', if any.                        */
-      T1_Skip_Spaces( parser );
-      T1_Skip_Alpha( parser );    /* `NP' or `I' or `noaccess' */
-      T1_Skip_Spaces( parser );
+      T1_Skip_PS_Token( parser );   /* `NP' or `I' or `noaccess' */
+      T1_Skip_Spaces  ( parser );
 
       if ( ft_strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 )
       {
-        T1_Skip_Alpha( parser );  /* skip `put' */
-        T1_Skip_Spaces( parser );
+        T1_Skip_PS_Token( parser ); /* skip `put' */
+        T1_Skip_Spaces  ( parser );
       }
 
       /* some fonts use a value of -1 for lenIV to indicate that */
@@ -1164,6 +1131,9 @@
   }
 
 
+#define TABLE_EXTEND  5
+
+
   static void
   parse_charstrings( T1_Face    face,
                      T1_Loader  loader )
@@ -1185,7 +1155,7 @@
 
 
     if ( loader->num_glyphs )
-      /*  with synthetic fonts, it's possible we get here twice  */
+      /* with synthetic fonts it is possible we get here twice */
       return;
 
     loader->num_glyphs = (FT_Int)T1_ToInt( parser );
@@ -1192,18 +1162,17 @@
     if ( parser->root.error )
       return;
 
-    /* initialize tables (leaving room for addition of .notdef, */
-    /* if necessary).                                           */
+    /* initialize tables, leaving room for addition of .notdef, */
+    /* if necessary, and a few other glyphs to handle buggy     */
+    /* fonts which have more glyphs than specified.             */
 
-    error = psaux->ps_table_funcs->init( code_table,
-                                         loader->num_glyphs + 1,
-                                         memory );
+    error = psaux->ps_table_funcs->init(
+              code_table, loader->num_glyphs + 1 + TABLE_EXTEND, memory );
     if ( error )
       goto Fail;
 
-    error = psaux->ps_table_funcs->init( name_table,
-                                         loader->num_glyphs + 1,
-                                         memory );
+    error = psaux->ps_table_funcs->init(
+              name_table, loader->num_glyphs + 1 + TABLE_EXTEND, memory );
     if ( error )
       goto Fail;
 
@@ -1235,30 +1204,35 @@
         break;
 
       /* we stop when we find a `def' or `end' keyword */
-      if ( *cur   == 'd'   &&
-           cur + 3 < limit &&
-           cur[1] == 'e'   &&
-           cur[2] == 'f'   )
-        break;
+      if ( cur + 3 < limit && is_space( cur[3] ) )
+      {
+        if ( cur[0] == 'd' &&
+             cur[1] == 'e' &&
+             cur[2] == 'f' )
+          break;
 
-      if ( *cur   == 'e'   &&
-           cur + 3 < limit &&
-           cur[1] == 'n'   &&
-           cur[2] == 'd'   )
-        break;
+        if ( cur[0] == 'e' &&
+             cur[1] == 'n' &&
+             cur[2] == 'd' )
+          break;
+      }
 
       if ( *cur != '/' )
-        T1_Skip_Alpha( parser );
+        T1_Skip_PS_Token( parser );
       else
       {
-        FT_Byte*    cur2 = cur + 1;
         FT_PtrDist  len;
 
 
-        while ( cur2 < limit && is_name_char( *cur2 ) )
-          cur2++;
-        len = cur2 - cur - 1;
+        T1_Skip_PS_Token( parser );
+        if ( cur >= limit )
+        {
+          error = T1_Err_Invalid_File_Format;
+          goto Fail;
+        }
 
+        len = parser->root.cursor - cur;
+
         error = T1_Add_Table( name_table, n, cur + 1, len + 1 );
         if ( error )
           goto Fail;
@@ -1274,11 +1248,11 @@
           notdef_found = 1;
         }
 
-        parser->root.cursor = cur2;
         if ( !read_binary_data( parser, &size, &base ) )
           return;
 
-        if ( face->type1.private_dict.lenIV >= 0 )
+        if ( face->type1.private_dict.lenIV >= 0   &&
+             n < loader->num_glyphs + TABLE_EXTEND )
         {
           FT_Byte*  temp;
 
@@ -1299,8 +1273,6 @@
           goto Fail;
 
         n++;
-        if ( n >= loader->num_glyphs )
-          break;
       }
     }
 
@@ -1311,11 +1283,11 @@
                     (const char*)name_table->elements[0] ) &&
          notdef_found                                      )
     {
-      /* Swap glyph in index 0 with /.notdef glyph.  First, add index 0    */
-      /* name and code entries to swap_table. Then place notdef_index name */
-      /* and code entries into swap_table.  Then swap name and code        */
-      /* entries at indices notdef_index and 0 using values stored in      */
-      /* swap_table.                                                       */
+      /* Swap glyph in index 0 with /.notdef glyph.  First, add index 0  */
+      /* name and code entries to swap_table.  Then place notdef_index   */
+      /* name and code entries into swap_table.  Then swap name and code */
+      /* entries at indices notdef_index and 0 using values stored in    */
+      /* swap_table.                                                     */
 
       /* Index 0 name */
       error = T1_Add_Table( swap_table, 0,
@@ -1426,6 +1398,14 @@
   }
 
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define the token field static variables.  This is a set of            */
+  /* T1_FieldRec variables.                                                */
+  /*                                                                       */
+  /*************************************************************************/
+
+
   static
   const T1_FieldRec  t1_keywords[] =
   {
@@ -1462,120 +1442,134 @@
               FT_Byte*   keyword_flags )
   {
     T1_Parser  parser = &loader->parser;
+    FT_Byte*   limit;
 
 
     parser->root.cursor = base;
     parser->root.limit  = base + size;
-    parser->root.error  = 0;
+    parser->root.error  = T1_Err_Ok;
 
+    limit = parser->root.limit;
+
+    while ( parser->root.cursor < limit )
     {
-      FT_Byte*  cur   = base;
-      FT_Byte*  limit = cur + size;
+      FT_Byte*  cur;
 
 
-      for ( ; cur < limit; cur++ )
+      T1_Skip_Spaces( parser );
+      cur = parser->root.cursor;
+
+      /* look for `FontDirectory', which causes problems for some fonts */
+      if ( *cur == 'F' && cur + 25 < limit                    &&
+           ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
       {
-        /* look for `FontDirectory', which causes problems on some fonts */
-        if ( *cur == 'F' && cur + 25 < limit                    &&
-             ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
-        {
-          FT_Byte*  cur2;
+        FT_Byte*  cur2;
 
 
-          /* skip the `FontDirectory' keyword */
-          cur += 13;
-          cur2 = cur;
+        /* skip the `FontDirectory' keyword */
+        T1_Skip_PS_Token( parser );
+        T1_Skip_Spaces  ( parser );
+        cur = cur2 = parser->root.cursor;
 
-          /* lookup the `known' keyword */
-          while ( cur < limit && *cur != 'k'           &&
-                  ft_strncmp( (char*)cur, "known", 5 ) )
-            cur++;
+        /* look up the `known' keyword */
+        while ( cur < limit )
+        {
+          if ( *cur == 'k' && cur + 5 < limit       &&
+               ft_strncmp( (char*)cur, "known", 5 ) )
+            break;
 
-          if ( cur < limit )
-          {
-            T1_TokenRec  token;
+          T1_Skip_PS_Token( parser );
+          T1_Skip_Spaces  ( parser );
+          cur = parser->root.cursor;
+        }
 
+        if ( cur < limit )
+        {
+          T1_TokenRec  token;
 
-            /* skip the `known' keyword and the token following it */
-            cur += 5;
-            loader->parser.root.cursor = cur;
-            T1_ToToken( &loader->parser, &token );
 
-            /* if the last token was an array, skip it! */
-            if ( token.type == T1_TOKEN_TYPE_ARRAY )
-              cur2 = parser->root.cursor;
-          }
-          cur = cur2;
+          /* skip the `known' keyword and the token following it */
+          T1_Skip_PS_Token( parser );
+          T1_ToToken( parser, &token );
+
+          /* if the last token was an array, skip it! */
+          if ( token.type == T1_TOKEN_TYPE_ARRAY )
+            cur2 = parser->root.cursor;
         }
-        /* look for immediates */
-        else if ( *cur == '/' && cur + 2 < limit )
-        {
-          FT_Byte*    cur2;
-          FT_PtrDist  len;
+        parser->root.cursor = cur2;
+      }
 
+      /* look for `closefile' which ends the eexec section */
+      else if ( *cur == 'c' && cur + 9 < limit &&
+                ft_strncmp( (char*)cur, "closefile", 9 ) == 0 )
+        break;
 
-          cur++;
-          cur2 = cur;
-          while ( cur2 < limit && is_name_char( *cur2 ) )
-            cur2++;
+      /* look for immediates */
+      else if ( *cur == '/' && cur + 2 < limit )
+      {
+        FT_PtrDist  len;
 
-          len = cur2 - cur;
-          if ( len > 0 && len < 22 )
-          {
-            {
-              /* now, compare the immediate name to the keyword table */
-              T1_Field  keyword      = (T1_Field)t1_keywords;
-              FT_Byte*  keyword_flag = keyword_flags;
 
+        cur++;
 
-              for (;;)
-              {
-                FT_Byte*  name;
+        parser->root.cursor = cur;
+        T1_Skip_PS_Token( parser );
 
+        len = parser->root.cursor - cur;
 
-                name = (FT_Byte*)keyword->ident;
-                if ( !name )
-                  break;
+        if ( len > 0 && len < 22 )
+        {
+          /* now compare the immediate name to the keyword table */
+          T1_Field  keyword      = (T1_Field)t1_keywords;
+          FT_Byte*  keyword_flag = keyword_flags;
 
-                if ( cur[0] == name[0]                     &&
-                     len == ft_strlen( (const char*)name ) )
-                {
-                  FT_PtrDist  n;
 
+          for (;;)
+          {
+            FT_Byte*  name;
 
-                  for ( n = 1; n < len; n++ )
-                    if ( cur[n] != name[n] )
-                      break;
 
-                  if ( n >= len )
-                  {
-                    /* we found it -- run the parsing callback! */
-                    parser->root.cursor = cur2;
-                    T1_Skip_Spaces( parser );
-                    
-                    /* we only record the first instance of any      */
-                    /* field to deal adequately with synthetic fonts */
-                    if ( keyword_flag[0] == 0 )
-                    {
-                      parser->root.error = t1_load_keyword( face,
-                                                            loader,
-                                                            keyword );
-                      if ( parser->root.error )
-                        return parser->root.error;
-                    }
-                    keyword_flag[0] = 1;
+            name = (FT_Byte*)keyword->ident;
+            if ( !name )
+            {
+              T1_Skip_PS_Token( parser );
+              break;
+            }
 
-                    cur = parser->root.cursor;
-                    break;
-                  }
+            if ( cur[0] == name[0]                     &&
+                 len == ft_strlen( (const char*)name ) )
+            {
+              FT_PtrDist  n;
+
+
+              for ( n = 1; n < len; n++ )
+                if ( cur[n] != name[n] )
+                  break;
+
+              if ( n >= len )
+              {
+                /* We found it -- run the parsing callback!      */
+                /* We only record the first instance of any      */
+                /* field to deal adequately with synthetic fonts */
+                if ( keyword_flag[0] == 0 )
+                {
+                  parser->root.error = t1_load_keyword( face,
+                                                        loader,
+                                                        keyword );
+                  if ( parser->root.error )
+                    return parser->root.error;
                 }
-                keyword++;
-                keyword_flag++;
+                keyword_flag[0] = 1;
+                break;
               }
             }
+            keyword++;
+            keyword_flag++;
           }
         }
       }
+      else
+        T1_Skip_PS_Token( parser );
     }
     return parser->root.error;
   }
@@ -1742,16 +1736,21 @@
               if ( ft_strcmp( (const char*)".notdef",
                               (const char*)glyph_name ) != 0 )
               {
-                if ( charcode < min_char ) min_char = charcode;
-                if ( charcode > max_char ) max_char = charcode;
+                if ( charcode < min_char )
+                  min_char = charcode;
+                if ( charcode > max_char )
+                  max_char = charcode;
               }
               break;
             }
           }
       }
-      /* Yes, this happens: Certain PDF-embedded fonts have only a ".notdef"
-       * glyph defined!
+
+      /*
+       *  Yes, this happens: Certain PDF-embedded fonts have only a
+       *  `.notdef' glyph defined!
        */
+
       if ( min_char > max_char )
       {
         min_char = 0;
--- a/src/type1/t1parse.c
+++ b/src/type1/t1parse.c
@@ -104,7 +104,7 @@
     FT_Long    size;
 
 
-    psaux->ps_parser_funcs->init( &parser->root,0, 0, memory );
+    psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
 
     parser->stream       = stream;
     parser->base_len     = 0;
@@ -219,29 +219,6 @@
   }
 
 
-  /* return the value of an hexadecimal digit */
-  static int
-  hexa_value( char  c )
-  {
-    unsigned int  d;
-
-
-    d = (unsigned int)( c - '0' );
-    if ( d <= 9 )
-      return (int)d;
-
-    d = (unsigned int)( c - 'a' );
-    if ( d <= 5 )
-      return (int)( d + 10 );
-
-    d = (unsigned int)( c - 'A' );
-    if ( d <= 5 )
-      return (int)( d + 10 );
-
-    return -1;
-  }
-
-
   FT_LOCAL_DEF( FT_Error )
   T1_Get_Private_Dict( T1_Parser      parser,
                        PSAux_Service  psaux )
@@ -248,7 +225,7 @@
   {
     FT_Stream  stream = parser->stream;
     FT_Memory  memory = parser->root.memory;
-    FT_Error   error  = 0;
+    FT_Error   error  = T1_Err_Ok;
     FT_Long    size;
 
 
@@ -302,7 +279,8 @@
           break;
         }
 
-        if ( FT_STREAM_READ( parser->private_dict + parser->private_len, size ) )
+        if ( FT_STREAM_READ( parser->private_dict + parser->private_len,
+                             size ) )
           goto Fail;
 
         parser->private_len += size;
@@ -310,9 +288,9 @@
     }
     else
     {
-      /* we have already `loaded' the whole PFA font file into memory; */
+      /* We have already `loaded' the whole PFA font file into memory; */
       /* if this is a memory resource, allocate a new block to hold    */
-      /* the private dict. Otherwise, simply overwrite into the base   */
+      /* the private dict.  Otherwise, simply overwrite into the base  */
       /* dictionary block in the heap.                                 */
 
       /* first of all, look at the `eexec' keyword */
@@ -330,7 +308,7 @@
           if ( cur[1] == 'e' && cur[2] == 'x' &&
                cur[3] == 'e' && cur[4] == 'c' )
           {
-            cur += 6; /* we skip the newling after the `eexec' */
+            cur += 6; /* we skip the newline after the `eexec' */
 
             /* XXX: Some fonts use DOS-linefeeds, i.e. \r\n; we need to */
             /*      skip the extra \n if we find it                     */
@@ -379,51 +357,38 @@
       /* the `eexec' keyword); if they all are hexadecimal digits, then   */
       /* we have a case of ASCII storage                                  */
 
-      if ( ( hexa_value( cur[0] ) | hexa_value( cur[1] ) |
-             hexa_value( cur[2] ) | hexa_value( cur[3] ) ) < 0 )
-
-        /* binary encoding -- `simply' copy the private dict */
-        FT_MEM_COPY( parser->private_dict, cur, size );
-
-      else
+      if ( ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) &&
+           ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) )
       {
         /* ASCII hexadecimal encoding */
+        FT_Long  len;
 
-        FT_Byte*  write;
-        FT_Int    count;
 
+        parser->root.cursor = cur;
+        (void)psaux->ps_parser_funcs->to_bytes( &parser->root,
+                                                parser->private_dict,
+                                                parser->private_len,
+                                                &len,
+                                                0 );
+        parser->private_len = len;
 
-        write = parser->private_dict;
-        count = 0;
-
-        for ( ;cur < limit; cur++ )
-        {
-          int  hex1;
-
-
-          /* check for newline */
-          if ( cur[0] == '\r' || cur[0] == '\n' )
-            continue;
-
-          /* exit if we have a non-hexadecimal digit that isn't a newline */
-          hex1 = hexa_value( cur[0] );
-          if ( hex1 < 0 || cur + 1 >= limit )
-            break;
-
-          /* otherwise, store byte */
-          *write++ = (FT_Byte)( ( hex1 << 4 ) | hexa_value( cur[1] ) );
-          count++;
-          cur++;
-        }
-
         /* put a safeguard */
-        parser->private_len = write - parser->private_dict;
-        *write++ = 0;
+        parser->private_dict[len] = '\0';
       }
+      else
+        /* binary encoding -- copy the private dict */
+        FT_MEM_COPY( parser->private_dict, cur, size );
     }
 
     /* we now decrypt the encoded binary private dictionary */
     psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U );
+
+    /* replace the four random bytes at the beginning with whitespace */
+    parser->private_dict[0] = ' ';
+    parser->private_dict[1] = ' ';
+    parser->private_dict[2] = ' ';
+    parser->private_dict[3] = ' ';
+
     parser->root.base   = parser->private_dict;
     parser->root.cursor = parser->private_dict;
     parser->root.limit  = parser->root.cursor + parser->private_len;
--- a/src/type1/t1parse.h
+++ b/src/type1/t1parse.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Type 1 parser (specification).                                       */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002 by                                           */
+/*  Copyright 1996-2001, 2002, 2003 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -69,9 +69,9 @@
     FT_Byte*      private_dict;
     FT_Long       private_len;
 
-    FT_Byte       in_pfb;
-    FT_Byte       in_memory;
-    FT_Byte       single_block;
+    FT_Bool       in_pfb;
+    FT_Bool       in_memory;
+    FT_Bool       single_block;
 
   } T1_ParserRec, *T1_Parser;
 
@@ -91,8 +91,8 @@
           } while ( 0 )
 
 
-#define T1_Skip_Spaces( p )  (p)->root.funcs.skip_spaces( &(p)->root )
-#define T1_Skip_Alpha( p )   (p)->root.funcs.skip_alpha ( &(p)->root )
+#define T1_Skip_Spaces( p )    (p)->root.funcs.skip_spaces( &(p)->root )
+#define T1_Skip_PS_Token( p )  (p)->root.funcs.skip_PS_token( &(p)->root )
 
 #define T1_ToInt( p )       (p)->root.funcs.to_int( &(p)->root )
 #define T1_ToFixed( p, t )  (p)->root.funcs.to_fixed( &(p)->root, t )
--- a/src/type42/t42parse.c
+++ b/src/type42/t42parse.c
@@ -111,8 +111,8 @@
               (p)->funcs.release( p ); \
           } while ( 0 )
 
-#define T1_Skip_Spaces( p )  (p)->root.funcs.skip_spaces( &(p)->root )
-#define T1_Skip_Alpha( p )   (p)->root.funcs.skip_alpha ( &(p)->root )
+#define T1_Skip_Spaces( p )    (p)->root.funcs.skip_spaces( &(p)->root )
+#define T1_Skip_PS_Token( p )  (p)->root.funcs.skip_PS_token( &(p)->root )
 
 #define T1_ToInt( p )       (p)->root.funcs.to_int( &(p)->root )
 #define T1_ToFixed( p, t )  (p)->root.funcs.to_fixed( &(p)->root, t )
@@ -318,7 +318,7 @@
 
     /* if we have a number, then the encoding is an array, */
     /* and we must load it now                             */
-    if ( (FT_Byte)( *cur - '0' ) < 10 )
+    if ( ft_isdigit( *cur ) )
     {
       T1_Encoding  encode     = &face->type1.encoding;
       FT_Int       count, n;
@@ -394,7 +394,7 @@
         }
 
         /* otherwise, we must find a number before anything else */
-        if ( (FT_Byte)( c - '0' ) < 10 )
+        if ( ft_isdigit( c ) )
         {
           FT_Int  charcode;
 
@@ -571,7 +571,7 @@
         }
 
       default:
-        if ( !ft_xdigit( *cur ) || !ft_xdigit( *(cur + 1) ) )
+        if ( !ft_isxdigit( *cur ) || !ft_isxdigit( *(cur + 1) ) )
         {
           FT_ERROR(( "t42_parse_sfnts: found non-hex characters in string" ));
           error = T42_Err_Invalid_File_Format;
@@ -705,7 +705,7 @@
         break;
 
       if ( *cur != '/' )
-        T1_Skip_Alpha( parser );
+        T1_Skip_PS_Token( parser );
       else
       {
         FT_Byte*  cur2 = cur + 1;