shithub: freetype+ttf2subf

Download patch

ref: 9f95babf3e1be13c2f7ecda60938698b7e2da7f6
parent: 5a1fae15a90e220e98b69ad88ee9b927aeb9c608
author: David Turner <[email protected]>
date: Fri Jun 7 03:23:06 EDT 2002

* src/type42/t42drivr.c, src/type42/t42drivr.h, src/type42/t42parse.c,
          src/type42/t42parse.h, src/type42/t42objs.h, src/type42/t42objs.c,
          src/type42/type42.c:

            updated the Type42 driver by splitting it into several files since
            it makes the code easier to read and maintain. Also fixed the bug
            that prevented the correct display of fonts with "ftview"

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2002-06-07  David Turner   <[email protected]>
+
+        * src/type42/t42drivr.c, src/type42/t42drivr.h, src/type42/t42parse.c,
+          src/type42/t42parse.h, src/type42/t42objs.h, src/type42/t42objs.c,
+          src/type42/type42.c:
+
+            updated the Type42 driver by splitting it into several files since
+            it makes the code easier to read and maintain. Also fixed the bug
+            that prevented the correct display of fonts with "ftview"
+
 2002-06-03  Werner Lemberg  <[email protected]>
 
 	Add 8bpp support.
--- a/src/type42/Jamfile
+++ b/src/type42/Jamfile
@@ -10,11 +10,11 @@
 
   if $(FT2_MULTI)
   {
-    _sources = t42drivr ;
+    _sources = t42objs t42parse t42drivr ;
   }
   else
   {
-    _sources = t42drivr ;
+    _sources = type42 ;
   }
 
   Library  $(FT2_LIB) : $(_sources).c ;
--- a/src/type42/descrip.mms
+++ b/src/type42/descrip.mms
@@ -15,7 +15,7 @@
 
 CFLAGS=$(COMP_FLAGS)$(DEBUG)/include=([--.include],[--.src.type42])
 
-OBJS=t42drivr.obj
+OBJS=type42.obj
 
 all : $(OBJS)
         library [--.lib]freetype.olb $(OBJS)
--- a/src/type42/rules.mk
+++ b/src/type42/rules.mk
@@ -26,11 +26,13 @@
 
 # Type42 driver source
 #
-T42_DRV_SRC := $(T42_DIR_)t42drivr.c
+T42_DRV_SRC := $(T42_DIR_)t42objs.c  \
+               $(T42_DIR_)t42parse.c \
+               $(T42_DIR_)t42drivr.c
 
 # Type42 driver headers
 #
-T42_DRV_H :=
+T42_DRV_H := $(T42_DRV_SRC:%.c=%.h)
 
 
 # Type42 driver object(s)
@@ -39,7 +41,7 @@
 #   T42_DRV_OBJ_S is used during `single' builds
 #
 T42_DRV_OBJ_M := $(T42_DRV_SRC:$(T42_DIR_)%.c=$(OBJ_)%.$O)
-T42_DRV_OBJ_S := $(OBJ_)t42drivr.$O
+T42_DRV_OBJ_S := $(OBJ_)type42.$O
 
 # Type42 driver source file for single build
 #
--- a/src/type42/t42drivr.c
+++ b/src/type42/t42drivr.c
@@ -1,1949 +1,11 @@
-/***************************************************************************/
-/*                                                                         */
-/*  t42drivr.c                                                             */
-/*                                                                         */
-/*    FreeType font driver for Type 42 fonts (body only).                  */
-/*                                                                         */
-/*  Copyright 2002 by Roberto Alameda.                                     */
-/*                                                                         */
-/*  This file is part of the FreeType project, and may only be used,       */
-/*  modified, and distributed under the terms of the FreeType project      */
-/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
-/*  this file you indicate that you have read the license and              */
-/*  understand and accept it fully.                                        */
-/*                                                                         */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#define FT_ERR_PREFIX  T42_Err_
-#define FT_ERR_BASE    FT_Mod_Err_Type42
-
-#include FT_CONFIG_STANDARD_LIBRARY_H
-
+#include "t42drivr.h"
+#include "t42objs.h"
 #include FT_INTERNAL_DEBUG_H
-#include FT_CONFIG_CONFIG_H
 
-#include FT_ERRORS_H
-#include FT_FREETYPE_H
-#include FT_TYPE1_TABLES_H
-#include FT_LIST_H
-
-#include FT_INTERNAL_DRIVER_H
-#include FT_INTERNAL_OBJECTS_H
-#include FT_INTERNAL_TYPE1_TYPES_H
-#include FT_INTERNAL_TYPE42_TYPES_H
-#include FT_INTERNAL_POSTSCRIPT_AUX_H
-#include FT_INTERNAL_STREAM_H
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
-  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
-  /* messages during execution.                                            */
-  /*                                                                       */
 #undef  FT_COMPONENT
 #define FT_COMPONENT  trace_t42
 
-
-  /********************* Data Definitions ******************/
-
-  typedef struct  T42_DriverRec_
-  {
-    FT_DriverRec     root;
-    FT_Driver_Class  ttclazz;
-    void*            extension_component;
-
-  } T42_DriverRec, *T42_Driver;
-
-
-  typedef struct  T42_SizeRec_
-  {
-    FT_SizeRec  root;
-    FT_Size     ttsize;
-
-  } T42_SizeRec, *T42_Size;
-
-
-  typedef struct  T42_GlyphSlotRec_
-  {
-    FT_GlyphSlotRec  root;
-    FT_GlyphSlot     ttslot;
-
-  } T42_GlyphSlotRec, *T42_GlyphSlot;
-
-
-  /*********** Parser definitions *************/
-
-  typedef struct  T42_ParserRec_
-  {
-    PS_ParserRec  root;
-    FT_Stream     stream;
-
-    FT_Byte*      base_dict;
-    FT_Int        base_len;
-
-    FT_Byte       in_memory;
-
-  } T42_ParserRec, *T42_Parser;
-
-
-  typedef struct  T42_Loader_
-  {
-    T42_ParserRec  parser;          /* parser used to read the stream */
-
-    FT_Int         num_chars;       /* number of characters in encoding */
-    PS_TableRec    encoding_table;  /* PS_Table used to store the       */
-                                    /* encoding character names         */
-
-    FT_Int         num_glyphs;
-    PS_TableRec    glyph_names;
-    PS_TableRec    charstrings;
-
-  } T42_LoaderRec, *T42_Loader;
-
-
-  /*********************** Prototypes *********************/
-
-  static void
-  parse_font_name( T42_Face    face,
-                   T42_Loader  loader );
-  static void
-  parse_font_bbox( T42_Face    face,
-                   T42_Loader  loader );
-  static void
-  parse_font_matrix( T42_Face    face,
-                     T42_Loader  loader );
-  static void
-  parse_encoding( T42_Face    face,
-                  T42_Loader  loader );
-  static void
-  parse_charstrings( T42_Face    face,
-                     T42_Loader  loader );
-  static void
-  parse_sfnts( T42_Face    face,
-               T42_Loader  loader );
-
-
-  static const
-  T1_FieldRec  t42_keywords[] = {
-
-#undef  FT_STRUCTURE
-#define FT_STRUCTURE  T1_FontInfo
-#undef  T1CODE
-#define T1CODE        T1_FIELD_LOCATION_FONT_INFO
-
-    T1_FIELD_STRING   ( "version",            version )
-    T1_FIELD_STRING   ( "Notice",             notice )
-    T1_FIELD_STRING   ( "FullName",           full_name )
-    T1_FIELD_STRING   ( "FamilyName",         family_name )
-    T1_FIELD_STRING   ( "Weight",             weight )
-    T1_FIELD_NUM      ( "ItalicAngle",        italic_angle )
-    T1_FIELD_TYPE_BOOL( "isFixedPitch",       is_fixed_pitch )
-    T1_FIELD_NUM      ( "UnderlinePosition",  underline_position )
-    T1_FIELD_NUM      ( "UnderlineThickness", underline_thickness )
-
-#undef  FT_STRUCTURE
-#define FT_STRUCTURE  T42_FontRec
-#undef  T1CODE
-#define T1CODE        T1_FIELD_LOCATION_FONT_DICT
-
-    T1_FIELD_NUM( "PaintType",   paint_type )
-    T1_FIELD_NUM( "FontType",    font_type )
-    T1_FIELD_NUM( "StrokeWidth", stroke_width )
-
-    T1_FIELD_CALLBACK( "FontName",    parse_font_name )
-    T1_FIELD_CALLBACK( "FontBBox",    parse_font_bbox )
-    T1_FIELD_CALLBACK( "FontMatrix",  parse_font_matrix )
-    T1_FIELD_CALLBACK( "Encoding",    parse_encoding )
-    T1_FIELD_CALLBACK( "CharStrings", parse_charstrings )
-    T1_FIELD_CALLBACK( "sfnts",       parse_sfnts )
-
-    { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 }
-  };
-
-
-#define T1_Add_Table( p, i, o, l )  (p)->funcs.add( (p), i, o, l )
-#define T1_Done_Table( p )          \
-          do                        \
-          {                         \
-            if ( (p)->funcs.done )  \
-              (p)->funcs.done( p ); \
-          } while ( 0 )
-#define T1_Release_Table( p )          \
-          do                           \
-          {                            \
-            if ( (p)->funcs.release )  \
-              (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_ToInt( p )       (p)->root.funcs.to_int( &(p)->root )
-#define T1_ToFixed( p, t )  (p)->root.funcs.to_fixed( &(p)->root, t )
-
-#define T1_ToCoordArray( p, m, c )                           \
-          (p)->root.funcs.to_coord_array( &(p)->root, m, c )
-#define T1_ToFixedArray( p, m, f, t )                           \
-          (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
-#define T1_ToToken( p, t )                          \
-          (p)->root.funcs.to_token( &(p)->root, t )
-#define T1_ToTokenArray( p, t, m, c )                           \
-          (p)->root.funcs.to_token_array( &(p)->root, t, m, c )
-
-#define T1_Load_Field( p, f, o, m, pf )                         \
-          (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )
-#define T1_Load_Field_Table( p, f, o, m, pf )                         \
-          (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )
-
-
-  /********************* Parsing Functions ******************/
-
   static FT_Error
-  T42_New_Parser( T42_Parser     parser,
-                  FT_Stream      stream,
-                  FT_Memory      memory,
-                  PSAux_Service  psaux )
-  {
-    FT_Error  error = T42_Err_Ok;
-    FT_Long   size;
-
-
-    psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
-
-    parser->stream    = stream;
-    parser->base_len  = 0;
-    parser->base_dict = 0;
-    parser->in_memory = 0;
-
-    /*******************************************************************/
-    /*                                                                 */
-    /* Here a short summary of what is going on:                       */
-    /*                                                                 */
-    /*   When creating a new Type 42 parser, we try to locate and load */
-    /*   the base dictionary, loading the whole font into memory.      */
-    /*                                                                 */
-    /*   When `loading' the base dictionary, we only setup pointers in */
-    /*   the case of a memory-based stream.  Otherwise, we allocate    */
-    /*   and load the base dictionary in it.                           */
-    /*                                                                 */
-    /*   parser->in_memory is set if we have a memory stream.          */
-    /*                                                                 */
-
-    if ( FT_STREAM_SEEK( 0L ) )
-      goto Exit;
-
-    size = stream->size;
-
-    /* now, try to load `size' bytes of the `base' dictionary we */
-    /* found previously                                          */
-
-    /* if it is a memory-based resource, set up pointers */
-    if ( !stream->read )
-    {
-      parser->base_dict = (FT_Byte*)stream->base + stream->pos;
-      parser->base_len  = size;
-      parser->in_memory = 1;
-
-      /* check that the `size' field is valid */
-      if ( FT_STREAM_SKIP( size ) )
-        goto Exit;
-    }
-    else
-    {
-      /* read segment in memory */
-      if (FT_ALLOC( parser->base_dict, size )       ||
-          FT_STREAM_READ( parser->base_dict, size ) )
-        goto Exit;
-      parser->base_len = size;
-    }
-
-    /* Now check font format; we must see `%!PS-TrueTypeFont' */
-    if (size <= 17                                    ||
-        ( ft_strncmp( (const char*)parser->base_dict,
-                      "%!PS-TrueTypeFont", 17) )      )
-      error = T42_Err_Unknown_File_Format;
-    else
-    {
-      parser->root.base   = parser->base_dict;
-      parser->root.cursor = parser->base_dict;
-      parser->root.limit  = parser->root.cursor + parser->base_len;
-    }
-
-  Exit:
-    if ( error && !parser->in_memory )
-      FT_FREE( parser->base_dict );
-
-    return error;
-  }
-
-
-  static void
-  T42_Finalize_Parser( T42_Parser  parser )
-  {
-    FT_Memory  memory = parser->root.memory;
-
-
-    /* free the base dictionary only when we have a disk stream */
-    if ( !parser->in_memory )
-      FT_FREE( parser->base_dict );
-
-    parser->root.funcs.done( &parser->root );
-  }
-
-
-  static int
-  is_alpha( FT_Byte  c )
-  {
-    /* Note: we must accept "+" as a valid character, as it is used in */
-    /*       embedded type1 fonts in PDF documents.                    */
-    /*                                                                 */
-    return ( ft_isalnum( c ) ||
-             c == '.'        ||
-             c == '_'        ||
-             c == '-'        ||
-             c == '+'        );
-  }
-
-
-  static int
-  is_space( FT_Byte  c )
-  {
-    return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
-  }
-
-
-  static void
-  parse_font_name( T42_Face    face,
-                   T42_Loader  loader )
-  {
-    T42_Parser  parser = &loader->parser;
-    FT_Error    error;
-    FT_Memory   memory = parser->root.memory;
-    FT_Int      len;
-    FT_Byte*    cur;
-    FT_Byte*    cur2;
-    FT_Byte*    limit;
-
-
-    T1_Skip_Spaces( parser );
-
-    cur   = parser->root.cursor;
-    limit = parser->root.limit;
-
-    if ( cur >= limit - 1              ||
-         ( *cur != '/' && *cur != '(') )
-      return;
-
-    cur++;
-    cur2 = cur;
-    while ( cur2 < limit && is_alpha( *cur2 ) )
-      cur2++;
-
-    len = (FT_Int)( cur2 - cur );
-    if ( len > 0 )
-    {
-      if ( FT_ALLOC( face->type42.font_name, len + 1 ) )
-      {
-        parser->root.error = error;
-        return;
-      }
-
-      FT_MEM_COPY( face->type42.font_name, cur, len );
-      face->type42.font_name[len] = '\0';
-    }
-    parser->root.cursor = cur2;
-  }
-
-
-  static void
-  parse_font_bbox( T42_Face   face,
-                  T42_Loader  loader )
-  {
-    T42_Parser  parser = &loader->parser;
-    FT_BBox*    bbox   = &face->type42.font_bbox;
-
-    bbox->xMin = T1_ToInt( parser );
-    bbox->yMin = T1_ToInt( parser );
-    bbox->xMax = T1_ToInt( parser );
-    bbox->yMax = T1_ToInt( parser );
-  }
-
-
-  static void
-  parse_font_matrix( T42_Face    face,
-                     T42_Loader  loader )
-  {
-    T42_Parser  parser = &loader->parser;
-    FT_Matrix*  matrix = &face->type42.font_matrix;
-    FT_Vector*  offset = &face->type42.font_offset;
-    FT_Face     root   = (FT_Face)&face->root;
-    FT_Fixed    temp[6];
-    FT_Fixed    temp_scale;
-
-
-    (void)T1_ToFixedArray( parser, 6, temp, 3 );
-
-    temp_scale = ABS( temp[3] );
-
-    /* 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).                              */
-
-    root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L,
-                                                 temp_scale ) >> 16 );
-
-    /* we need to scale the values by 1.0/temp_scale */
-    if ( temp_scale != 0x10000L ) {
-      temp[0] = FT_DivFix( temp[0], temp_scale );
-      temp[1] = FT_DivFix( temp[1], temp_scale );
-      temp[2] = FT_DivFix( temp[2], temp_scale );
-      temp[4] = FT_DivFix( temp[4], temp_scale );
-      temp[5] = FT_DivFix( temp[5], temp_scale );
-      temp[3] = 0x10000L;
-    }
-
-    matrix->xx = temp[0];
-    matrix->yx = temp[1];
-    matrix->xy = temp[2];
-    matrix->yy = temp[3];
-
-    /* note that the offsets must be expressed in integer font units */
-    offset->x  = temp[4] >> 16;
-    offset->y  = temp[5] >> 16;
-  }
-
-
-  static void
-  parse_encoding( T42_Face    face,
-                  T42_Loader  loader )
-  {
-    T42_Parser     parser = &loader->parser;
-    FT_Byte*       cur    = parser->root.cursor;
-    FT_Byte*       limit  = parser->root.limit;
-
-    PSAux_Service  psaux  = (PSAux_Service)face->psaux;
-
-
-    /* skip whitespace */
-    while ( is_space( *cur ) )
-    {
-      cur++;
-      if ( cur >= limit )
-      {
-        FT_ERROR(( "parse_encoding: out of bounds!\n" ));
-        parser->root.error = T42_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 )
-    {
-      T1_Encoding  encode     = &face->type42.encoding;
-      FT_Int       count, n;
-      PS_Table     char_table = &loader->encoding_table;
-      FT_Memory    memory     = parser->root.memory;
-      FT_Error     error;
-
-
-      /* read the number of entries in the encoding, should be 256 */
-      count = T1_ToInt( parser );
-      if ( parser->root.error )
-        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 ) ||
-           FT_SET_ERROR( psaux->ps_table_funcs->init(
-                           char_table, count, memory ) ) )
-      {
-        parser->root.error = error;
-        return;
-      }
-
-      /* We need to `zero' out encoding_table.elements */
-      for ( n = 0; n < count; n++ )
-      {
-        char*  notdef = (char *)".notdef";
-
-
-        T1_Add_Table( char_table, n, notdef, 8 );
-      }
-
-      /* Now, we will 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:                     */
-      /*                                                        */
-      /*   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;
-
-      for ( ; cur < limit; )
-      {
-        FT_Byte  c;
-
-
-        c = *cur;
-
-        /* we stop when we encounter a `def' */
-        if ( c == 'd' && cur + 3 < limit )
-        {
-          if ( cur[1] == 'e'       &&
-               cur[2] == 'f'       &&
-               is_space( cur[-1] ) &&
-               is_space( cur[3] )  )
-          {
-            FT_TRACE6(( "encoding end\n" ));
-            break;
-          }
-        }
-
-        /* otherwise, we must find a number before anything else */
-        if ( (FT_Byte)( c - '0' ) < 10 )
-        {
-          FT_Int  charcode;
-
-
-          parser->root.cursor = cur;
-          charcode = T1_ToInt( parser );
-          cur      = parser->root.cursor;
-
-          /* skip whitespace */
-          while ( cur < limit && is_space( *cur ) )
-            cur++;
-
-          if ( cur < limit && *cur == '/' )
-          {
-            /* bingo, we have an immediate name -- it must be a */
-            /* character name                                   */
-            FT_Byte*  cur2 = cur + 1;
-            FT_Int    len;
-
-
-            while ( cur2 < limit && is_alpha( *cur2 ) )
-              cur2++;
-
-            len = (FT_Int)( cur2 - cur - 1 );
-
-            parser->root.error = T1_Add_Table( char_table, charcode,
-                                               cur + 1, len + 1 );
-            char_table->elements[charcode][len] = '\0';
-            if ( parser->root.error )
-              return;
-
-            cur = cur2;
-          }
-        }
-        else
-          cur++;
-      }
-
-      face->type42.encoding_type = T1_ENCODING_TYPE_ARRAY;
-      parser->root.cursor        = cur;
-    }
-    /* Otherwise, we should have either `StandardEncoding', */
-    /* `ExpertEncoding', or `ISOLatin1Encoding'             */
-    else
-    {
-      if ( cur + 17 < limit                                            &&
-           ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
-        face->type42.encoding_type = T1_ENCODING_TYPE_STANDARD;
-
-      else if ( cur + 15 < limit                                          &&
-                ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
-        face->type42.encoding_type = T1_ENCODING_TYPE_EXPERT;
-
-      else if ( cur + 18 < limit                                             &&
-                ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
-        face->type42.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
-
-      else {
-        FT_ERROR(( "parse_encoding: invalid token!\n" ));
-        parser->root.error = T42_Err_Invalid_File_Format;
-      }
-    }
-  }
-
-
-  static FT_UInt
-  hexval( FT_Byte  v )
-  {
-    FT_UInt  d;
-    
-    d = (FT_UInt)( v - 'A' );
-    if ( d < 6 )
-    {
-      d += 10;
-      goto Exit;
-    }
-      
-    d = (FT_UInt)( v - 'a' );
-    if ( d < 6 )
-    {
-      d += 10;
-      goto Exit;
-    }
-      
-    d = (FT_UInt)( v - '0' );
-    if ( d < 10 )
-      goto Exit;
-      
-    d = 0;
- 
-  Exit:         
-    return d;
-  }
-
-
-  static void
-  parse_sfnts( T42_Face    face,
-               T42_Loader  loader )
-  {
-    T42_Parser  parser = &loader->parser;
-    FT_Memory   memory = parser->root.memory;
-    FT_Byte*    cur    = parser->root.cursor;
-    FT_Byte*    limit  = parser->root.limit;
-    FT_Error    error;
-    FT_Int      num_tables = 0, status;
-    FT_ULong    count, ttf_size = 0, string_size = 0;
-    FT_Bool     in_string  = 0;
-    FT_Byte     v = 0;
-
-
-    /* The format is `/sfnts [ <...> <...> ... ] def' */
-
-    while ( is_space( *cur ) )
-      cur++;
-
-    if (*cur++ == '[')
-    {
-      status = 0;
-      count = 0;
-    }
-    else
-    {
-      FT_ERROR(( "parse_sfnts: can't find begin of sfnts vector!\n" ));
-      error = T42_Err_Invalid_File_Format;
-      goto Fail;
-    }
-
-    while ( cur < limit - 2 )
-    {
-      while ( is_space( *cur ) )
-        cur++;
-
-      switch ( *cur )
-      {
-      case ']':
-        parser->root.cursor = cur++;
-        return;
-
-      case '<':
-        in_string   = 1;
-        string_size = 0;
-        cur++;
-        continue;
-
-      case '>':
-        if ( !in_string )
-        {
-          FT_ERROR(( "parse_sfnts: found unpaired `>'!\n" ));
-          error = T42_Err_Invalid_File_Format;
-          goto Fail;
-        }
-
-        /* A string can have, as a last byte,         */
-        /* a zero byte for padding.  If so, ignore it */
-        if ( ( v == 0 ) && ( string_size % 2 == 1 ) )
-          count--;
-        in_string = 0;
-        cur++;
-        continue;
-
-      case '%':
-        if ( !in_string )
-        {
-          /* Comment found; skip till end of line */
-          while ( *cur != '\n' )
-            cur++;
-          continue;
-        }
-        else
-        {
-          FT_ERROR(( "parse_sfnts: found `%' in string!\n" ));
-          error = T42_Err_Invalid_File_Format;
-          goto Fail;
-        }
-
-      default:
-        if ( !ft_xdigit( *cur ) || !ft_xdigit( *(cur + 1) ) )
-        {
-          FT_ERROR(( "parse_sfnts: found non-hex characters in string" ));
-          error = T42_Err_Invalid_File_Format;
-          goto Fail;
-        }
-
-        v = (FT_Byte)( 16 * hexval( *cur++ ) + hexval( *cur++ ) );
-        string_size++;
-      }
-
-      switch ( status )
-      {
-      case 0: /* The '[' was read, so load offset table, 12 bytes */
-        if ( count < 12 )
-        {
-          face->ttf_data[count++] = v;
-          continue;
-        }
-        else
-        {
-          num_tables = 16 * face->ttf_data[4] + face->ttf_data[5];
-          status     = 1;
-          ttf_size   = 12 + 16 * num_tables;
-
-          if ( FT_REALLOC( face->ttf_data, 12, ttf_size ) )
-            goto Fail;
-        }
-        /* No break, fall-through */
-
-      case 1: /* The offset table is read; read now the table directory */
-        if ( count < ttf_size )
-        {
-          face->ttf_data[count++] = v;
-          continue;
-        }
-        else
-        {
-          int      i;
-          FT_ULong len;
-
-
-          for ( i = 0; i < num_tables; i++ )
-          {
-            len  = face->ttf_data[12 + 16*i + 12 + 0] << 24;
-            len += face->ttf_data[12 + 16*i + 12 + 1] << 16;
-            len += face->ttf_data[12 + 16*i + 12 + 2] << 8;
-            len += face->ttf_data[12 + 16*i + 12 + 3];
-
-            /* Pad to a 4-byte boundary length */
-            ttf_size += ( len + 3 ) & ~3;
-          }
-
-          status         = 2;
-          face->ttf_size = ttf_size;
-
-          if ( FT_REALLOC( face->ttf_data, 12 + 16 * num_tables,
-                           ttf_size + 1 ) )
-            goto Fail;
-        }
-        /* No break, fall-through */
-
-      case 2: /* We are reading normal tables; just swallow them */
-        face->ttf_data[count++] = v;
-
-      }
-    }
-
-    /* If control reaches this point, the format was not valid */
-    error = T42_Err_Invalid_File_Format;
-
-  Fail:
-    parser->root.error = error;
-  }
-
-
-  static void
-  parse_charstrings( T42_Face    face,
-                     T42_Loader  loader )
-  {
-    T42_Parser     parser     = &loader->parser;
-    PS_Table       code_table = &loader->charstrings;
-    PS_Table       name_table = &loader->glyph_names;
-    FT_Memory      memory     = parser->root.memory;
-    FT_Error       error;
-
-    PSAux_Service  psaux      = (PSAux_Service)face->psaux;
-
-    FT_Byte*       cur;
-    FT_Byte*       limit      = parser->root.limit;
-    FT_Int         n;
-
-
-    loader->num_glyphs = T1_ToInt( parser );
-    if ( parser->root.error )
-      return;
-
-    /* initialize tables */
-
-    error = psaux->ps_table_funcs->init( code_table,
-                                         loader->num_glyphs,
-                                         memory );
-    if ( error )
-      goto Fail;
-
-    error = psaux->ps_table_funcs->init( name_table,
-                                         loader->num_glyphs,
-                                         memory );
-    if ( error )
-      goto Fail;
-
-    n = 0;
-
-    for (;;)
-    {
-      /* the format is simple:                    */
-      /*   `/glyphname' + index + def             */
-      /*                                          */
-      /* note that we stop when we find an `end'  */
-      /*                                          */
-      T1_Skip_Spaces( parser );
-
-      cur = parser->root.cursor;
-      if ( cur >= limit )
-        break;
-
-      /* we stop when we find an `end' keyword */
-      if ( *cur   == 'e'   &&
-           cur + 3 < limit &&
-           cur[1] == 'n'   &&
-           cur[2] == 'd'   )
-        break;
-
-      if ( *cur != '/' )
-        T1_Skip_Alpha( parser );
-      else
-      {
-        FT_Byte*  cur2 = cur + 1;
-        FT_Int    len;
-
-
-        while ( cur2 < limit && is_alpha( *cur2 ) )
-          cur2++;
-        len = (FT_Int)( cur2 - cur - 1 );
-
-        error = T1_Add_Table( name_table, n, cur + 1, len + 1 );
-        if ( error )
-          goto Fail;
-
-        /* add a trailing zero to the name table */
-        name_table->elements[n][len] = '\0';
-
-        parser->root.cursor = cur2;
-        T1_Skip_Spaces( parser );
-
-        cur2 = cur = parser->root.cursor;
-        if ( cur >= limit )
-          break;
-
-        while ( cur2 < limit && is_alpha( *cur2 ) )
-          cur2++;
-        len = (FT_Int)( cur2 - cur );
-
-        error = T1_Add_Table( code_table, n, cur, len + 1 );
-        if ( error )
-          goto Fail;
-
-        code_table->elements[n][len] = '\0';
-
-        n++;
-        if ( n >= loader->num_glyphs )
-          break;
-      }
-    }
-
-    /* Index 0 must be a .notdef element */
-    if ( ft_strcmp( (char *)name_table->elements[0], ".notdef" ) )
-    {
-      FT_ERROR(( "parse_charstrings: Index 0 is not `.notdef'!\n" ));
-      error = T42_Err_Invalid_File_Format;
-      goto Fail;
-    }
-
-    loader->num_glyphs = n;
-    return;
-
-  Fail:
-    parser->root.error = error;
-  }
-
-
-  static FT_Error
-  t42_load_keyword( T42_Face    face,
-                    T42_Loader  loader,
-                    T1_Field    field )
-  {
-    FT_Error  error;
-    void*     dummy_object;
-    void**    objects;
-    FT_UInt   max_objects = 0;
-
-
-    /* if the keyword has a dedicated callback, call it */
-    if ( field->type == T1_FIELD_TYPE_CALLBACK ) {
-      field->reader( (FT_Face)face, loader );
-      error = loader->parser.root.error;
-      goto Exit;
-    }
-
-    /* now, the keyword is either a simple field, or a table of fields; */
-    /* we are now going to take care of it                              */
-    switch ( field->location )
-    {
-    case T1_FIELD_LOCATION_FONT_INFO:
-      dummy_object = &face->type42.font_info;
-      objects      = &dummy_object;
-      break;
-
-    default:
-      dummy_object = &face->type42;
-      objects      = &dummy_object;
-    }
-
-    if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
-         field->type == T1_FIELD_TYPE_FIXED_ARRAY   )
-      error = T1_Load_Field_Table( &loader->parser, field,
-                                   objects, max_objects, 0 );
-    else
-      error = T1_Load_Field( &loader->parser, field,
-                             objects, max_objects, 0 );
-
-   Exit:
-    return error;
-  }
-
-
-  static FT_Error
-  parse_dict( T42_Face    face,
-              T42_Loader  loader,
-              FT_Byte*    base,
-              FT_Long     size )
-  {
-    T42_Parser  parser = &loader->parser;
-    FT_Byte*    cur    = base;
-    FT_Byte*    limit  = cur + size;
-    FT_UInt     n_keywords = sizeof ( t42_keywords ) / 
-                             sizeof ( t42_keywords[0] );
-
-
-    parser->root.cursor = base;
-    parser->root.limit  = base + size;
-    parser->root.error  = 0;
-
-    for ( ; cur < limit; cur++ )
-    {
-      /* 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;
-
-
-        /* skip the `FontDirectory' keyword */
-        cur += 13;
-        cur2 = cur;
-
-        /* lookup the `known' keyword */
-        while ( cur < limit && *cur != 'k'           &&
-                ft_strncmp( (char*)cur, "known", 5 ) )
-          cur++;
-
-        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;
-      }
-      /* look for immediates */
-      else if ( *cur == '/' && cur + 2 < limit )
-      {
-        FT_Byte*  cur2;
-        FT_UInt    i, len;
-
-
-        cur++;
-        cur2 = cur;
-        while ( cur2 < limit && is_alpha( *cur2 ) )
-          cur2++;
-
-        len  = (FT_UInt)( cur2 - cur );
-        if ( len > 0 && len < 22 ) /* XXX What shall it this 22? */
-        {
-          /* now, compare the immediate name to the keyword table */
-
-          /* Loop through all known keywords */
-          for ( i = 0; i < n_keywords; i++ )
-          {
-            T1_Field  keyword = (T1_Field)&t42_keywords[i];
-            FT_Byte   *name   = (FT_Byte*)keyword->ident;
-
-
-            if ( !name )
-              continue;
-
-            if ( ( len == ft_strlen( (const char *)name ) ) &&
-                 ( ft_memcmp( cur, name, len ) == 0 )       )
-            {
-              /* we found it -- run the parsing callback! */
-              parser->root.cursor = cur2;
-              T1_Skip_Spaces( parser );
-              parser->root.error = t42_load_keyword(face,
-                                                    loader,
-                                                    keyword );
-              if ( parser->root.error )
-                return parser->root.error;
-              cur = parser->root.cursor;
-              break;
-            }
-          }
-        }
-      }
-    }
-    return parser->root.error;
-  }
-
-
-  static void
-  t42_init_loader( T42_Loader  loader,
-                   T42_Face    face )
-  {
-    FT_UNUSED( face );
-
-    FT_MEM_SET( loader, 0, sizeof ( *loader ) );
-    loader->num_glyphs = 0;
-    loader->num_chars  = 0;
-
-    /* initialize the tables -- simply set their `init' field to 0 */
-    loader->encoding_table.init = 0;
-    loader->charstrings.init    = 0;
-    loader->glyph_names.init    = 0;
-  }
-
-
-  static void
-  t42_done_loader( T42_Loader  loader )
-  {
-    T42_Parser  parser = &loader->parser;
-
-
-    /* finalize tables */
-    T1_Release_Table( &loader->encoding_table );
-    T1_Release_Table( &loader->charstrings );
-    T1_Release_Table( &loader->glyph_names );
-
-    /* finalize parser */
-    T42_Finalize_Parser( parser );
-  }
-
-
-  static FT_Error
-  T42_Open_Face( T42_Face  face )
-  {
-    T42_LoaderRec  loader;
-    T42_Parser     parser;
-    T42_Font       type42 = &face->type42;
-    FT_Memory      memory = face->root.memory;
-    FT_Error       error;
-
-    PSAux_Service  psaux  = (PSAux_Service)face->psaux;
-
-
-    t42_init_loader( &loader, face );
-
-    parser = &loader.parser;
-
-    if ( FT_ALLOC( face->ttf_data, 12 ) )
-      goto Exit;
-
-    error = T42_New_Parser( parser,
-                            face->root.stream,
-                            memory,
-                            psaux);
-    if ( error )
-      goto Exit;
-
-    error = parse_dict( face, &loader, parser->base_dict, parser->base_len );
-
-    if ( type42->font_type != 42 )
-    {
-      error = T42_Err_Unknown_File_Format;
-      goto Exit;
-    }
-
-    /* now, propagate the charstrings and glyphnames tables */
-    /* to the Type42 data                                   */
-    type42->num_glyphs = loader.num_glyphs;
-
-    if ( !loader.charstrings.init ) {
-      FT_ERROR(( "T42_Open_Face: no charstrings array in face!\n" ));
-      error = T42_Err_Invalid_File_Format;
-    }
-
-    loader.charstrings.init   = 0;
-    type42->charstrings_block = loader.charstrings.block;
-    type42->charstrings       = loader.charstrings.elements;
-    type42->charstrings_len   = loader.charstrings.lengths;
-
-    /* we copy the glyph names `block' and `elements' fields; */
-    /* the `lengths' field must be released later             */
-    type42->glyph_names_block   = loader.glyph_names.block;
-    type42->glyph_names         = (FT_String**)loader.glyph_names.elements;
-    loader.glyph_names.block    = 0;
-    loader.glyph_names.elements = 0;
-
-    /* we must now build type42.encoding when we have a custom array */
-    if ( type42->encoding_type == T1_ENCODING_TYPE_ARRAY )
-    {
-      FT_Int    charcode, idx, min_char, max_char;
-      FT_Byte*  char_name;
-      FT_Byte*  glyph_name;
-
-
-      /* OK, we do the following: for each element in the encoding   */
-      /* table, look up the index of the glyph having the same name  */
-      /* as defined in the CharStrings array.                        */
-      /* The index is then stored in type42.encoding.char_index, and */
-      /* the name in type42.encoding.char_name                       */
-
-      min_char = +32000;
-      max_char = -32000;
-
-      charcode = 0;
-      for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
-      {
-        type42->encoding.char_index[charcode] = 0;
-        type42->encoding.char_name [charcode] = (char *)".notdef";
-
-        char_name = loader.encoding_table.elements[charcode];
-        if ( char_name )
-          for ( idx = 0; idx < type42->num_glyphs; idx++ )
-          {
-            glyph_name = (FT_Byte*)type42->glyph_names[idx];
-            if ( ft_strcmp( (const char*)char_name,
-                            (const char*)glyph_name ) == 0 )
-            {
-              type42->encoding.char_index[charcode] = (FT_UShort)idx;
-              type42->encoding.char_name [charcode] = (char*)glyph_name;
-
-              /* Change min/max encoded char only if glyph name is */
-              /* not /.notdef                                      */
-              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;
-              }
-              break;
-            }
-          }
-      }
-      type42->encoding.code_first = min_char;
-      type42->encoding.code_last  = max_char;
-      type42->encoding.num_chars  = loader.num_chars;
-    }
-
-  Exit:
-    t42_done_loader( &loader );
-    return error;
-  }
-
-
-  /***************** Driver Functions *************/
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    The face object constructor.                                       */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    stream     ::  input stream where to load font data.               */
-  /*                                                                       */
-  /*    face_index :: The index of the font face in the resource.          */
-  /*                                                                       */
-  /*    num_params :: Number of additional generic parameters.  Ignored.   */
-  /*                                                                       */
-  /*    params     :: Additional generic parameters.  Ignored.             */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    face       :: The face record to build.                            */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  static FT_Error
-  T42_Face_Init( FT_Stream      stream,
-                 T42_Face       face,
-                 FT_Int         face_index,
-                 FT_Int         num_params,
-                 FT_Parameter*  params)
-  {
-    FT_Error          error;
-    PSNames_Service   psnames;
-    PSAux_Service     psaux;
-    FT_Face           root    = (FT_Face)&face->root;
-    FT_CharMap        charmap = face->charmaprecs;
-
-    FT_UNUSED( num_params );
-    FT_UNUSED( params );
-    FT_UNUSED( face_index );
-    FT_UNUSED( stream );
-
-
-    face->ttf_face       = NULL;
-    face->root.num_faces = 1;
-
-    /* XXX */
-    psnames = (PSNames_Service)face->psnames;
-    if ( !psnames )
-    {
-      psnames = (PSNames_Service)
-                FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
-                                         "psnames" );
-      face->psnames = psnames;
-    }
-
-    psaux = (PSAux_Service)face->psaux;
-    if ( !psaux )
-    {
-      psaux = (PSAux_Service)
-              FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
-                                       "psaux" );
-      face->psaux = psaux;
-    }
-
-    /* open the tokenizer, this will also check the font format */
-    error = T42_Open_Face( face );
-    if ( error )
-      goto Exit;
-
-    /* if we just wanted to check the format, leave successfully now */
-    if ( face_index < 0 )
-      goto Exit;
-
-    /* check the face index */
-    if ( face_index != 0 )
-    {
-      FT_ERROR(( "T42_Face_Init: invalid face index\n" ));
-      error = T42_Err_Invalid_Argument;
-      goto Exit;
-    }
-
-    /* Now, load the font program into the face object */
-
-    /* Init the face object fields */
-    /* Now set up root face fields */
-
-    root->num_glyphs   = face->type42.num_glyphs;
-    root->num_charmaps = 1;
-    root->face_index  = face_index;
-
-    root->face_flags  = FT_FACE_FLAG_SCALABLE;
-    root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
-    root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
-
-    if ( face->type42.font_info.is_fixed_pitch )
-      root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
-
-    /* XXX: TODO -- add kerning with .afm support */
-
-    /* get style name -- be careful, some broken fonts only */
-    /* have a `/FontName' dictionary entry!                 */
-    root->family_name = face->type42.font_info.family_name;
-    if ( root->family_name )
-    {
-      char*  full   = face->type42.font_info.full_name;
-      char*  family = root->family_name;
-
-
-      if ( full )
-      {
-        while ( *family && *full == *family )
-        {
-          family++;
-          full++;
-        }
-
-        root->style_name = ( *full == ' ' ? full + 1
-                                          : (char *)"Regular" );
-      }
-      else
-        root->style_name = (char *)"Regular";
-    }
-    else
-    {
-      /* do we have a `/FontName'? */
-      if ( face->type42.font_name )
-      {
-        root->family_name = face->type42.font_name;
-        root->style_name  = (char *)"Regular";
-      }
-    }
-
-    /* no embedded bitmap support */
-    root->num_fixed_sizes = 0;
-    root->available_sizes = 0;
-
-    /* Load the TTF font embedded in the T42 font */
-    error = FT_New_Memory_Face( FT_FACE_LIBRARY( face ),
-                                face->ttf_data,
-                                face->ttf_size,
-                                0,
-                                &face->ttf_face );
-    if ( error )
-      goto Exit;
-
-    /* Ignore info in FontInfo dictionary and use the info from the  */
-    /* loaded TTF font.  The PostScript interpreter also ignores it. */
-    root->bbox         = face->ttf_face->bbox;
-    root->units_per_EM = face->ttf_face->units_per_EM;
-
-    root->ascender  = face->ttf_face->ascender;
-    root->descender = face->ttf_face->descender;
-    root->height    = face->ttf_face->height;
-
-    root->max_advance_width = face->ttf_face->max_advance_width;
-    root->max_advance_height = face->ttf_face->max_advance_height;
-
-    root->underline_position  = face->type42.font_info.underline_position;
-    root->underline_thickness = face->type42.font_info.underline_thickness;
-
-    root->internal->max_points   = 0;
-    root->internal->max_contours = 0;
-
-    /* compute style flags */
-    root->style_flags = 0;
-    if ( face->type42.font_info.italic_angle )
-      root->style_flags |= FT_STYLE_FLAG_ITALIC;
-
-    if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD )
-      root->style_flags |= FT_STYLE_FLAG_BOLD;
-
-    if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL )
-      root->face_flags |= FT_FACE_FLAG_VERTICAL;
-
-    /* XXX: Add support for new cmaps code in FT 2.1.0 */
-
-    /* charmap support -- synthetize unicode charmap if possible */
-
-    /* synthesize a Unicode charmap if there is support in the `PSNames' */
-    /* module                                                            */
-    if ( psnames && psnames->unicode_value )
-    {
-      error = psnames->build_unicodes( root->memory,
-                                       face->type42.num_glyphs,
-                                       (const char**)face->type42.glyph_names,
-                                       &face->unicode_map );
-      if ( !error )
-      {
-        root->charmap        = charmap;
-        charmap->face        = (FT_Face)face;
-        charmap->encoding    = ft_encoding_unicode;
-        charmap->platform_id = 3;
-        charmap->encoding_id = 1;
-        charmap++;
-      }
-
-      /* XXX: Is the following code correct?  It is used in t1objs.c */
-
-      /* simply clear the error in case of failure (which really) */
-      /* means that out of memory or no unicode glyph names       */
-      error = T42_Err_Ok;
-    }
-
-    /* now, support either the standard, expert, or custom encoding */
-    charmap->face        = (FT_Face)face;
-    charmap->platform_id = 7;  /* a new platform id for Adobe fonts? */
-
-    switch ( face->type42.encoding_type )
-    {
-    case T1_ENCODING_TYPE_STANDARD:
-      charmap->encoding    = ft_encoding_adobe_standard;
-      charmap->encoding_id = 0;
-      break;
-
-    case T1_ENCODING_TYPE_EXPERT:
-      charmap->encoding    = ft_encoding_adobe_expert;
-      charmap->encoding_id = 1;
-      break;
-
-    case T1_ENCODING_TYPE_ARRAY:
-      charmap->encoding    = ft_encoding_adobe_custom;
-      charmap->encoding_id = 2;
-      break;
-
-    case T1_ENCODING_TYPE_ISOLATIN1:
-      charmap->encoding    = ft_encoding_latin_1;
-      charmap->encoding_id = 3;
-      break;
-
-    default:
-      FT_ERROR(( "T42_Face_Init: invalid encoding\n" ));
-      error = T42_Err_Invalid_File_Format;
-      goto Exit;
-    }
-
-    root->charmaps     = face->charmaps;
-    root->num_charmaps = charmap - face->charmaprecs + 1;
-    face->charmaps[0]  = &face->charmaprecs[0];
-    face->charmaps[1]  = &face->charmaprecs[1];
-
-  Exit:
-    return error;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*   T42_Face_Done                                                       */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    The face object destructor.                                        */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    face :: A typeless pointer to the face object to destroy.          */
-  /*                                                                       */
-  static void
-  T42_Face_Done( T42_Face  face )
-  {
-    T42_Font     type42;
-    PS_FontInfo  info;
-    FT_Memory    memory;
-
-
-    if ( face )
-    {
-      type42 = &face->type42;
-      info   = &type42->font_info;
-      memory = face->root.memory;
-
-      /* delete internal ttf face prior to freeing face->ttf_data */
-      if ( face->ttf_face )
-        FT_Done_Face( face->ttf_face );
-
-      /* release font info strings */
-      FT_FREE( info->version );
-      FT_FREE( info->notice );
-      FT_FREE( info->full_name );
-      FT_FREE( info->family_name );
-      FT_FREE( info->weight );
-
-      /* release top dictionary */
-      FT_FREE( type42->charstrings_len );
-      FT_FREE( type42->charstrings );
-      FT_FREE( type42->glyph_names );
-
-      FT_FREE( type42->charstrings_block );
-      FT_FREE( type42->glyph_names_block );
-
-      FT_FREE( type42->encoding.char_index );
-      FT_FREE( type42->encoding.char_name );
-      FT_FREE( type42->font_name );
-
-      FT_FREE( face->ttf_data );
-
-#if 0
-      /* release afm data if present */
-      if ( face->afm_data )
-        T1_Done_AFM( memory, (T1_AFM*)face->afm_data );
-#endif
-
-      /* release unicode map, if any */
-      FT_FREE( face->unicode_map.maps );
-      face->unicode_map.num_maps = 0;
-
-      face->root.family_name = 0;
-      face->root.style_name  = 0;
-    }
-  }
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    T42_Driver_Init                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Initializes a given Type 42 driver object.                         */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    driver :: A handle to the target driver object.                    */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  static FT_Error
-  T42_Driver_Init( T42_Driver  driver )
-  {
-    FT_Module  ttmodule;
-
-
-    ttmodule = FT_Get_Module( driver->root.root.library, "truetype" );
-    driver->ttclazz = (FT_Driver_Class)ttmodule->clazz;
-
-    return T42_Err_Ok;
-  }
-
-
-  static void
-  T42_Driver_Done( T42_Driver  driver )
-  {
-    FT_UNUSED( driver );
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Get_Char_Index                                                     */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Uses a charmap to return a given character code's glyph index.     */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    charmap  :: A handle to the source charmap object.                 */
-  /*                                                                       */
-  /*    charcode :: The character code.                                    */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    Glyph index.  0 means `undefined character code'.                  */
-  /*                                                                       */
-  static FT_UInt
-  Get_Char_Index( FT_CharMap  charmap,
-                  FT_Long     charcode )
-  {
-    T42_Face         face;
-    FT_UInt          result = 0;
-    PSNames_Service  psnames;
-
-
-    face    = (T42_Face)charmap->face;
-    psnames = (PSNames_Service)face->psnames;
-    if (!psnames )
-      goto Exit;
-
-    switch ( charmap->encoding )
-    {
-      /*******************************************************************/
-      /*                                                                 */
-      /* Unicode encoding support                                        */
-      /*                                                                 */
-    case ft_encoding_unicode:
-      /* if this charmap is used, we ignore the encoding of the font and */
-      /* use the `PSNames' module to synthetize the Unicode charmap      */
-      result = psnames->lookup_unicode( &face->unicode_map,
-                                        (FT_ULong)charcode );
-
-      /* the function returns 0xFFFF if the Unicode charcode has */
-      /* no corresponding glyph                                  */
-      if ( result == 0xFFFFU )
-        result = 0;
-
-      /* The result returned is the index (position)in the CharStrings */
-      /* array.  This must be used now to get the value associated to  */
-      /* that glyph_name, which is the real index within the truetype  */
-      /* structure.                                                    */
-      result = ft_atoi( (const char*)face->type42.charstrings[result] );
-      goto Exit;
-
-      /*******************************************************************/
-      /*                                                                 */
-      /* ISOLatin1 encoding support                                      */
-      /*                                                                 */
-    case ft_encoding_latin_1:
-      /* ISOLatin1 is the first page of Unicode */
-      if ( charcode < 256 && psnames->unicode_value )
-      {
-        result = psnames->lookup_unicode( &face->unicode_map,
-                                          (FT_ULong)charcode );
-
-        /* the function returns 0xFFFF if the Unicode charcode has */
-        /* no corresponding glyph                                  */
-        if ( result == 0xFFFFU )
-          result = 0;
-      }
-      goto Exit;
-
-      /*******************************************************************/
-      /*                                                                 */
-      /* Custom Type 1 encoding                                          */
-      /*                                                                 */
-    case ft_encoding_adobe_custom:
-      {
-        T1_Encoding  encoding = &face->type42.encoding;
-
-
-        if ( charcode >= encoding->code_first &&
-             charcode <= encoding->code_last  )
-        {
-          FT_UInt idx = encoding->char_index[charcode];
-
-
-          result = ft_atoi( (const char *)face->type42.charstrings[idx] );
-        }
-        goto Exit;
-      }
-
-      /*******************************************************************/
-      /*                                                                 */
-      /* Adobe Standard & Expert encoding support                        */
-      /*                                                                 */
-    default:
-      if ( charcode < 256 )
-      {
-        FT_UInt      code;
-        FT_Int       n;
-        const char*  glyph_name;
-
-
-        code = psnames->adobe_std_encoding[charcode];
-        if ( charmap->encoding == ft_encoding_adobe_expert )
-          code = psnames->adobe_expert_encoding[charcode];
-
-        glyph_name = psnames->adobe_std_strings( code );
-        if ( !glyph_name )
-          break;
-
-        for ( n = 0; n < face->type42.num_glyphs; n++ )
-        {
-          const char*  gname = face->type42.glyph_names[n];
-
-          if ( gname && ( ft_strcmp( gname, glyph_name ) == 0 ) )
-          {
-            result = ft_atoi( (const char *)face->type42.charstrings[n] );
-            break;
-          }
-        }
-      }
-    }
-
-  Exit:
-    return result;
-  }
-
-
-  static FT_Error
-  T42_Size_Init( T42_Size  size )
-  {
-    FT_Face   face    = size->root.face;
-    T42_Face  t42face = (T42_Face)face;
-    FT_Size   ttsize;
-    FT_Error  error   = T42_Err_Ok;
-
-
-    if ( face->size == NULL )
-    {
-      /* First size for this face */
-      size->ttsize = t42face->ttf_face->size;
-    }
-    else
-    {
-      error = FT_New_Size( t42face->ttf_face, &ttsize );
-      size->ttsize = ttsize;
-    }
-
-    return error;
-  }
-
-
-  static void
-  T42_Size_Done( T42_Size  size )
-  {
-    FT_Face      face    = size->root.face;
-    T42_Face     t42face = (T42_Face)face;
-    FT_ListNode  node;
-
-
-    node = FT_List_Find( &t42face->ttf_face->sizes_list, size->ttsize );
-    if ( node )
-      FT_Done_Size( size->ttsize );
-  }
-
-
-  static FT_Error
-  T42_GlyphSlot_Init( T42_GlyphSlot  slot )
-  {
-    FT_Face       face    = slot->root.face;
-    T42_Face      t42face = (T42_Face)face;
-    FT_GlyphSlot  ttslot;
-    FT_Error      error   = T42_Err_Ok;
-
-
-    if ( face->glyph == NULL )
-    {
-      /* First glyph slot for this face */
-      slot->ttslot = t42face->ttf_face->glyph;
-    }
-    else
-    {
-      error = FT_New_GlyphSlot( t42face->ttf_face, &ttslot );
-      slot->ttslot = ttslot;
-    }
-
-    return error;
-  }
-
-
-  static void
-  T42_GlyphSlot_Done( T42_GlyphSlot slot )
-  {
-    FT_Face       face    = slot->root.face;
-    T42_Face      t42face = (T42_Face)face;
-    FT_GlyphSlot  cur     = t42face->ttf_face->glyph;
-
-
-    while ( cur )
-    {
-      if ( cur == slot->ttslot )
-      {
-        FT_Done_GlyphSlot( slot->ttslot );
-        break;
-      }
-
-      cur = cur->next;
-    }
-  }
-
-
-  static FT_Error
-  T42_Char_Size( T42_Size    size,
-                 FT_F26Dot6  char_width,
-                 FT_F26Dot6  char_height,
-                 FT_UInt     horz_resolution,
-                 FT_UInt     vert_resolution )
-  {
-    FT_Face   face    = size->root.face;
-    T42_Face  t42face = (T42_Face)face;
-
-
-    return FT_Set_Char_Size( t42face->ttf_face,
-                             char_width,
-                             char_height,
-                             horz_resolution,
-                             vert_resolution );
-  }
-
-
-  static FT_Error
-  T42_Pixel_Size( T42_Size  size,
-                  FT_UInt   pixel_width,
-                  FT_UInt   pixel_height )
-  {
-    FT_Face   face    = size->root.face;
-    T42_Face  t42face = (T42_Face)face;
-
-
-    return FT_Set_Pixel_Sizes( t42face->ttf_face,
-                               pixel_width,
-                               pixel_height );
-  }
-
-
-  static void
-  ft_glyphslot_clear( FT_GlyphSlot  slot )
-  {
-    /* free bitmap if needed */
-    if ( slot->flags & FT_GLYPH_OWN_BITMAP )
-    {
-      FT_Memory  memory = FT_FACE_MEMORY( slot->face );
-
-
-      FT_FREE( slot->bitmap.buffer );
-      slot->flags &= ~FT_GLYPH_OWN_BITMAP;
-    }
-
-    /* clear all public fields in the glyph slot */
-    FT_MEM_SET( &slot->metrics, 0, sizeof ( slot->metrics ) );
-    FT_MEM_SET( &slot->outline, 0, sizeof ( slot->outline ) );
-    FT_MEM_SET( &slot->bitmap,  0, sizeof ( slot->bitmap )  );
-
-    slot->bitmap_left   = 0;
-    slot->bitmap_top    = 0;
-    slot->num_subglyphs = 0;
-    slot->subglyphs     = 0;
-    slot->control_data  = 0;
-    slot->control_len   = 0;
-    slot->other         = 0;
-    slot->format        = ft_glyph_format_none;
-
-    slot->linearHoriAdvance = 0;
-    slot->linearVertAdvance = 0;
-  }
-
-
-  static FT_Error
-  T42_Load_Glyph( FT_GlyphSlot  glyph,
-                  FT_Size       size,
-                  FT_Int        glyph_index,
-                  FT_Int        load_flags )
-  {
-    FT_Error         error;
-    T42_GlyphSlot    t42slot = (T42_GlyphSlot)glyph;
-    T42_Size         t42size = (T42_Size)size;
-    FT_Driver_Class  ttclazz = ((T42_Driver)glyph->face->driver)->ttclazz;
-
-
-    ft_glyphslot_clear( t42slot->ttslot );
-    error = ttclazz->load_glyph( t42slot->ttslot,
-                                 t42size->ttsize,
-                                 glyph_index,
-                                 load_flags | FT_LOAD_NO_BITMAP );
-
-    if ( !error )
-    {
-      glyph->metrics = t42slot->ttslot->metrics;
-
-      glyph->linearHoriAdvance = t42slot->ttslot->linearHoriAdvance;
-      glyph->linearVertAdvance = t42slot->ttslot->linearVertAdvance;
-
-      glyph->format  = t42slot->ttslot->format;
-      glyph->outline = t42slot->ttslot->outline;
-
-      glyph->bitmap      = t42slot->ttslot->bitmap;
-      glyph->bitmap_left = t42slot->ttslot->bitmap_left;
-      glyph->bitmap_top  = t42slot->ttslot->bitmap_top;
-    }
-
-    return error;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Get_Next_Char                                                      */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Uses a charmap to return the next encoded char.                    */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    charmap  :: A handle to the source charmap object.                 */
-  /*                                                                       */
-  /*    charcode :: The character code.                                    */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    Next char code.  0 means `no more char codes'.                     */
-  /*                                                                       */
-  static FT_Long
-  Get_Next_Char( FT_CharMap  charmap,
-                 FT_Long     charcode )
-  {
-    T42_Face         face;
-    PSNames_Service  psnames;
-
-
-    face    = (T42_Face)charmap->face;
-    psnames = (PSNames_Service)face->psnames;
-
-    if ( psnames )
-      switch ( charmap->encoding )
-      {
-        /*******************************************************************/
-        /*                                                                 */
-        /* Unicode encoding support                                        */
-        /*                                                                 */
-      case ft_encoding_unicode:
-        /* use the `PSNames' module to synthetize the Unicode charmap */
-        return psnames->next_unicode( &face->unicode_map,
-                                      (FT_ULong)charcode );
-
-        /*******************************************************************/
-        /*                                                                 */
-        /* ISOLatin1 encoding support                                      */
-        /*                                                                 */
-      case ft_encoding_latin_1:
-        {
-          FT_ULong code;
-
-
-          /* use the `PSNames' module to synthetize the Unicode charmap */
-          code = psnames->next_unicode( &face->unicode_map,
-                                        (FT_ULong)charcode );
-          if ( code < 256 )
-            return code;
-          break;
-        }
-
-        /*******************************************************************/
-        /*                                                                 */
-        /* Custom Type 1 encoding                                          */
-        /*                                                                 */
-      case ft_encoding_adobe_custom:
-        {
-          T1_Encoding  encoding = &face->type42.encoding;
-
-
-          charcode++;
-          if ( charcode < encoding->code_first )
-            charcode = encoding->code_first;
-          while ( charcode <= encoding->code_last  ) {
-            if ( encoding->char_index[charcode] )
-              return charcode;
-            charcode++;
-          }
-        }
-
-
-        /*******************************************************************/
-        /*                                                                 */
-        /* Adobe Standard & Expert encoding support                        */
-        /*                                                                 */
-      default:
-        while ( ++charcode < 256 )
-        {
-          FT_UInt      code;
-          FT_Int       n;
-          const char*  glyph_name;
-
-
-          code = psnames->adobe_std_encoding[charcode];
-          if ( charmap->encoding == ft_encoding_adobe_expert )
-            code = psnames->adobe_expert_encoding[charcode];
-
-          glyph_name = psnames->adobe_std_strings( code );
-          if ( !glyph_name )
-            continue;
-
-          for ( n = 0; n < face->type42.num_glyphs; n++ )
-          {
-            const char*  gname = face->type42.glyph_names[n];
-
-
-            if ( gname && gname[0] == glyph_name[0]  &&
-                 ft_strcmp( gname, glyph_name ) == 0 )
-              return charcode;
-          }
-        }
-      }
-
-    return 0;
-  }
-
-
-  static FT_Error
   t42_get_glyph_name( T42_Face    face,
                       FT_UInt     glyph_index,
                       FT_Pointer  buffer,
@@ -1952,7 +14,7 @@
     FT_String*  gname;
 
 
-    gname = face->type42.glyph_names[glyph_index];
+    gname = face->type1.glyph_names[glyph_index];
 
     if ( buffer_max > 0 )
     {
@@ -1961,11 +23,12 @@
   
       if ( len >= buffer_max )
         len = buffer_max - 1;
+        
       FT_MEM_COPY( buffer, gname, len );
       ((FT_Byte*)buffer)[len] = 0;
     }
 
-    return T42_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -1972,7 +35,7 @@
   static const char*
   t42_get_ps_name( T42_Face  face )
   {
-    return (const char*)face->type42.font_name;
+    return (const char*)face->type1.font_name;
   }
 
 
@@ -1984,12 +47,12 @@
     FT_String*  gname;
 
 
-    for ( i = 0; i < face->type42.num_glyphs; i++ )
+    for ( i = 0; i < face->type1.num_glyphs; i++ )
     {
-      gname = face->type42.glyph_names[i];
+      gname = face->type1.glyph_names[i];
 
       if ( !ft_strcmp( glyph_name, gname ) )
-        return ft_atoi( (const char *)face->type42.charstrings[i] );
+        return ft_atoi( (const char *)face->type1.charstrings[i] );
     }
 
     return 0;
@@ -1997,8 +60,8 @@
 
 
   static FT_Module_Interface
-  Get_Interface( FT_Driver         driver,
-                 const FT_String*  t42_interface )
+  T42_Get_Interface( FT_Driver         driver,
+                     const FT_String*  t42_interface )
   {
     FT_UNUSED( driver );
 
@@ -2037,7 +100,7 @@
 
       (FT_Module_Constructor)T42_Driver_Init,
       (FT_Module_Destructor) T42_Driver_Done,
-      (FT_Module_Requester)  Get_Interface,
+      (FT_Module_Requester)  T42_Get_Interface,
     },
 
     sizeof ( T42_FaceRec ),
@@ -2051,10 +114,10 @@
     (FT_Slot_InitFunc)        T42_GlyphSlot_Init,
     (FT_Slot_DoneFunc)        T42_GlyphSlot_Done,
 
-    (FT_Size_ResetPointsFunc) T42_Char_Size,
-    (FT_Size_ResetPixelsFunc) T42_Pixel_Size,
-    (FT_Slot_LoadFunc)        T42_Load_Glyph,
-    (FT_CharMap_CharIndexFunc)Get_Char_Index,
+    (FT_Size_ResetPointsFunc) T42_Size_SetChars,
+    (FT_Size_ResetPixelsFunc) T42_Size_SetPixels,
+    (FT_Slot_LoadFunc)        T42_GlyphSlot_Load,
+    (FT_CharMap_CharIndexFunc)T42_CMap_CharIndex,
 
     (FT_Face_GetKerningFunc)  0,
     (FT_Face_AttachFunc)      0,
@@ -2061,8 +124,6 @@
 
     (FT_Face_GetAdvancesFunc) 0,
 
-    (FT_CharMap_CharNextFunc) Get_Next_Char
+    (FT_CharMap_CharNextFunc) T42_CMap_CharNext,
   };
 
-
-/* END */
--- /dev/null
+++ b/src/type42/t42drivr.h
@@ -1,0 +1,38 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t42drivr.h                                                             */
+/*                                                                         */
+/*    High-level Type 42 driver interface (specification).                 */
+/*                                                                         */
+/*  Copyright 1996-2001, 2002 by                                           */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __T42DRIVER_H__
+#define __T42DRIVER_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_EXPORT_VAR( const FT_Driver_ClassRec )  t42_driver_class;
+
+
+FT_END_HEADER
+
+#endif /* __T42DRIVER_H__ */
+
+
+/* END */
--- /dev/null
+++ b/src/type42/t42objs.c
@@ -1,0 +1,881 @@
+#include "t42objs.h"
+#include "t42parse.h"
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_LIST_H
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t42
+
+
+  static FT_Error
+  T42_Open_Face( T42_Face  face )
+  {
+    T42_LoaderRec  loader;
+    T42_Parser     parser;
+    T1_Font        type1 = &face->type1;
+    FT_Memory      memory = face->root.memory;
+    FT_Error       error;
+
+    PSAux_Service  psaux  = (PSAux_Service)face->psaux;
+
+
+    t42_loader_init( &loader, face );
+
+    parser = &loader.parser;
+
+    if ( FT_ALLOC( face->ttf_data, 12 ) )
+      goto Exit;
+
+    error = t42_parser_init( parser,
+                             face->root.stream,
+                             memory,
+                             psaux);
+    if ( error )
+      goto Exit;
+
+    error = t42_parse_dict( face, &loader, parser->base_dict, parser->base_len );
+
+    if ( type1->font_type != 42 )
+    {
+      error = FT_Err_Unknown_File_Format;
+      goto Exit;
+    }
+
+    /* now, propagate the charstrings and glyphnames tables */
+    /* to the Type1 data                                    */
+    type1->num_glyphs = loader.num_glyphs;
+
+    if ( !loader.charstrings.init ) {
+      FT_ERROR(( "T42_Open_Face: no charstrings array in face!\n" ));
+      error = FT_Err_Invalid_File_Format;
+    }
+
+    loader.charstrings.init   = 0;
+    type1->charstrings_block = loader.charstrings.block;
+    type1->charstrings       = loader.charstrings.elements;
+    type1->charstrings_len   = loader.charstrings.lengths;
+
+    /* we copy the glyph names `block' and `elements' fields; */
+    /* the `lengths' field must be released later             */
+    type1->glyph_names_block   = loader.glyph_names.block;
+    type1->glyph_names         = (FT_String**)loader.glyph_names.elements;
+    loader.glyph_names.block    = 0;
+    loader.glyph_names.elements = 0;
+
+    /* we must now build type1.encoding when we have a custom array */
+    if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY )
+    {
+      FT_Int    charcode, idx, min_char, max_char;
+      FT_Byte*  char_name;
+      FT_Byte*  glyph_name;
+
+
+      /* OK, we do the following: for each element in the encoding   */
+      /* table, look up the index of the glyph having the same name  */
+      /* as defined in the CharStrings array.                        */
+      /* The index is then stored in type1.encoding.char_index, and  */
+      /* the name in type1.encoding.char_name                        */
+
+      min_char = +32000;
+      max_char = -32000;
+
+      charcode = 0;
+      for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
+      {
+        type1->encoding.char_index[charcode] = 0;
+        type1->encoding.char_name [charcode] = (char *)".notdef";
+
+        char_name = loader.encoding_table.elements[charcode];
+        if ( char_name )
+          for ( idx = 0; idx < type1->num_glyphs; idx++ )
+          {
+            glyph_name = (FT_Byte*)type1->glyph_names[idx];
+            if ( ft_strcmp( (const char*)char_name,
+                            (const char*)glyph_name ) == 0 )
+            {
+              type1->encoding.char_index[charcode] = (FT_UShort)idx;
+              type1->encoding.char_name [charcode] = (char*)glyph_name;
+
+              /* Change min/max encoded char only if glyph name is */
+              /* not /.notdef                                      */
+              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;
+              }
+              break;
+            }
+          }
+      }
+      type1->encoding.code_first = min_char;
+      type1->encoding.code_last  = max_char;
+      type1->encoding.num_chars  = loader.num_chars;
+    }
+
+  Exit:
+    t42_loader_done( &loader );
+    return error;
+  }
+
+
+  /***************** Driver Functions *************/
+
+
+  FT_LOCAL_DEF( FT_Error )
+  T42_Face_Init( FT_Stream      stream,
+                 T42_Face       face,
+                 FT_Int         face_index,
+                 FT_Int         num_params,
+                 FT_Parameter*  params)
+  {
+    FT_Error          error;
+    PSNames_Service   psnames;
+    PSAux_Service     psaux;
+    FT_Face           root    = (FT_Face)&face->root;
+
+    FT_UNUSED( num_params );
+    FT_UNUSED( params );
+    FT_UNUSED( face_index );
+    FT_UNUSED( stream );
+
+
+    face->ttf_face       = NULL;
+    face->root.num_faces = 1;
+
+    face->psnames = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
+                                             "psnames" );
+    psnames = (PSNames_Service)face->psnames;
+
+    face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
+                                           "psaux" );
+    psaux = (PSAux_Service)face->psaux;
+
+    /* open the tokenizer, this will also check the font format */
+    error = T42_Open_Face( face );
+    if ( error )
+      goto Exit;
+
+    /* if we just wanted to check the format, leave successfully now */
+    if ( face_index < 0 )
+      goto Exit;
+
+    /* check the face index */
+    if ( face_index != 0 )
+    {
+      FT_ERROR(( "T42_Face_Init: invalid face index\n" ));
+      error = FT_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    /* Now, load the font program into the face object */
+
+    /* Init the face object fields */
+    /* Now set up root face fields */
+
+    root->num_glyphs   = face->type1.num_glyphs;
+    root->num_charmaps = 0;
+    root->face_index  = face_index;
+
+    root->face_flags  = FT_FACE_FLAG_SCALABLE;
+    root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
+    root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
+
+    if ( face->type1.font_info.is_fixed_pitch )
+      root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+    /* XXX: TODO -- add kerning with .afm support */
+
+    /* get style name -- be careful, some broken fonts only */
+    /* have a `/FontName' dictionary entry!                 */
+    root->family_name = face->type1.font_info.family_name;
+    if ( root->family_name )
+    {
+      char*  full   = face->type1.font_info.full_name;
+      char*  family = root->family_name;
+
+
+      if ( full )
+      {
+        while ( *family && *full == *family )
+        {
+          family++;
+          full++;
+        }
+
+        root->style_name = ( *full == ' ' ? full + 1
+                                          : (char *)"Regular" );
+      }
+      else
+        root->style_name = (char *)"Regular";
+    }
+    else
+    {
+      /* do we have a `/FontName'? */
+      if ( face->type1.font_name )
+      {
+        root->family_name = face->type1.font_name;
+        root->style_name  = (char *)"Regular";
+      }
+    }
+
+    /* no embedded bitmap support */
+    root->num_fixed_sizes = 0;
+    root->available_sizes = 0;
+
+    /* Load the TTF font embedded in the T42 font */
+    error = FT_New_Memory_Face( FT_FACE_LIBRARY( face ),
+                                face->ttf_data,
+                                face->ttf_size,
+                                0,
+                                &face->ttf_face );
+    if ( error )
+      goto Exit;
+
+    /* Ignore info in FontInfo dictionary and use the info from the  */
+    /* loaded TTF font.  The PostScript interpreter also ignores it. */
+    root->bbox         = face->ttf_face->bbox;
+    root->units_per_EM = face->ttf_face->units_per_EM;
+
+    root->ascender  = face->ttf_face->ascender;
+    root->descender = face->ttf_face->descender;
+    root->height    = face->ttf_face->height;
+
+    root->max_advance_width = face->ttf_face->max_advance_width;
+    root->max_advance_height = face->ttf_face->max_advance_height;
+
+    root->underline_position  = face->type1.font_info.underline_position;
+    root->underline_thickness = face->type1.font_info.underline_thickness;
+
+    root->internal->max_points   = 0;
+    root->internal->max_contours = 0;
+
+    /* compute style flags */
+    root->style_flags = 0;
+    if ( face->type1.font_info.italic_angle )
+      root->style_flags |= FT_STYLE_FLAG_ITALIC;
+
+    if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD )
+      root->style_flags |= FT_STYLE_FLAG_BOLD;
+
+    if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL )
+      root->face_flags |= FT_FACE_FLAG_VERTICAL;
+
+#ifdef FT_CONFIG_OPTION_USE_CMAPS
+
+    {
+      if ( psnames && psaux )
+      {
+        FT_CharMapRec    charmap;
+        T1_CMap_Classes  cmap_classes = psaux->t1_cmap_classes;
+        FT_CMap_Class    clazz;
+
+
+        charmap.face = root;
+
+        /* first of all, try to synthetize a Unicode charmap */
+        charmap.platform_id = 3;
+        charmap.encoding_id = 1;
+        charmap.encoding    = ft_encoding_unicode;
+
+        FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );
+
+        /* now, generate an Adobe Standard encoding when appropriate */
+        charmap.platform_id = 7;
+        clazz               = NULL;
+
+        switch ( face->type1.encoding_type )
+        {
+        case T1_ENCODING_TYPE_STANDARD:
+          charmap.encoding    = ft_encoding_adobe_standard;
+          charmap.encoding_id = 0;
+          clazz               = cmap_classes->standard;
+          break;
+
+        case T1_ENCODING_TYPE_EXPERT:
+          charmap.encoding    = ft_encoding_adobe_expert;
+          charmap.encoding_id = 1;
+          clazz               = cmap_classes->expert;
+          break;
+
+        case T1_ENCODING_TYPE_ARRAY:
+          charmap.encoding    = ft_encoding_adobe_custom;
+          charmap.encoding_id = 2;
+          clazz               = cmap_classes->custom;
+          break;
+
+        case T1_ENCODING_TYPE_ISOLATIN1:
+          charmap.encoding    = ft_encoding_latin_1;
+          charmap.encoding_id = 3;
+          clazz               = cmap_classes->unicode;
+          break;
+
+        default:
+          ;
+        }
+
+        if ( clazz )
+          FT_CMap_New( clazz, NULL, &charmap, NULL );
+
+	/* Select default charmap */
+	if (root->num_charmaps)
+	  root->charmap = root->charmaps[0];
+      }
+    }
+
+#else /* !FT_CONFIG_OPTION_USE_CMAPS */
+
+    /* charmap support -- synthetize unicode charmap if possible */
+    {
+      FT_CharMap        charmap = face->charmaprecs;
+      
+      /* synthesize a Unicode charmap if there is support in the `PSNames' */
+      /* module                                                            */
+      if ( psnames && psnames->unicode_value )
+      {
+	error = psnames->build_unicodes( root->memory,
+					 face->type1.num_glyphs,
+					 (const char**)face->type1.glyph_names,
+					 &face->unicode_map );
+	if ( !error )
+	{
+	  root->charmap        = charmap;
+	  charmap->face        = (FT_Face)face;
+	  charmap->encoding    = ft_encoding_unicode;
+	  charmap->platform_id = 3;
+	  charmap->encoding_id = 1;
+	  charmap++;
+	}
+	
+	/* XXX: Is the following code correct?  It is used in t1objs.c */
+	
+	/* simply clear the error in case of failure (which really) */
+	/* means that out of memory or no unicode glyph names       */
+	error = FT_Err_Ok;
+      }
+      
+      /* now, support either the standard, expert, or custom encoding */
+      charmap->face        = (FT_Face)face;
+      charmap->platform_id = 7;  /* a new platform id for Adobe fonts? */
+      
+      switch ( face->type1.encoding_type )
+      {
+      case T1_ENCODING_TYPE_STANDARD:
+	charmap->encoding    = ft_encoding_adobe_standard;
+	charmap->encoding_id = 0;
+	break;
+	
+      case T1_ENCODING_TYPE_EXPERT:
+	charmap->encoding    = ft_encoding_adobe_expert;
+	charmap->encoding_id = 1;
+	break;
+	
+      case T1_ENCODING_TYPE_ARRAY:
+	charmap->encoding    = ft_encoding_adobe_custom;
+	charmap->encoding_id = 2;
+	break;
+	
+      case T1_ENCODING_TYPE_ISOLATIN1:
+	charmap->encoding    = ft_encoding_latin_1;
+	charmap->encoding_id = 3;
+	break;
+	
+      default:
+	FT_ERROR(( "T42_Face_Init: invalid encoding\n" ));
+	error = FT_Err_Invalid_File_Format;
+	goto Exit;
+      }
+      
+      root->charmaps     = face->charmaps;
+      root->num_charmaps = charmap - face->charmaprecs + 1;
+      face->charmaps[0]  = &face->charmaprecs[0];
+      face->charmaps[1]  = &face->charmaprecs[1];
+    }
+
+#endif /* !FT_CONFIG_OPTION_USE_CMAPS */
+
+  Exit:
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  T42_Face_Done( T42_Face  face )
+  {
+    T1_Font      type1;
+    PS_FontInfo  info;
+    FT_Memory    memory;
+
+
+    if ( face )
+    {
+      type1 = &face->type1;
+      info   = &type1->font_info;
+      memory = face->root.memory;
+
+      /* delete internal ttf face prior to freeing face->ttf_data */
+      if ( face->ttf_face )
+        FT_Done_Face( face->ttf_face );
+
+      /* release font info strings */
+      FT_FREE( info->version );
+      FT_FREE( info->notice );
+      FT_FREE( info->full_name );
+      FT_FREE( info->family_name );
+      FT_FREE( info->weight );
+
+      /* release top dictionary */
+      FT_FREE( type1->charstrings_len );
+      FT_FREE( type1->charstrings );
+      FT_FREE( type1->glyph_names );
+
+      FT_FREE( type1->charstrings_block );
+      FT_FREE( type1->glyph_names_block );
+
+      FT_FREE( type1->encoding.char_index );
+      FT_FREE( type1->encoding.char_name );
+      FT_FREE( type1->font_name );
+
+      FT_FREE( face->ttf_data );
+
+#if 0
+      /* release afm data if present */
+      if ( face->afm_data )
+        T1_Done_AFM( memory, (T1_AFM*)face->afm_data );
+#endif
+
+      /* release unicode map, if any */
+      FT_FREE( face->unicode_map.maps );
+      face->unicode_map.num_maps = 0;
+
+      face->root.family_name = 0;
+      face->root.style_name  = 0;
+    }
+  }
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T42_Driver_Init                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given Type 42 driver object.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target driver object.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF( FT_Error )
+  T42_Driver_Init( T42_Driver  driver )
+  {
+    FT_Module  ttmodule;
+
+
+    ttmodule = FT_Get_Module( FT_MODULE(driver)->library, "truetype" );
+    driver->ttclazz = (FT_Driver_Class)ttmodule->clazz;
+
+    return FT_Err_Ok;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  T42_Driver_Done( T42_Driver  driver )
+  {
+    FT_UNUSED( driver );
+  }
+
+
+  FT_LOCAL_DEF( FT_UInt )
+  T42_CMap_CharIndex( FT_CharMap  charmap,
+                      FT_Long     charcode )
+  {
+    T42_Face         face;
+    FT_UInt          result = 0;
+    PSNames_Service  psnames;
+
+
+    face    = (T42_Face)charmap->face;
+    psnames = (PSNames_Service)face->psnames;
+    if (!psnames )
+      goto Exit;
+
+    switch ( charmap->encoding )
+    {
+      /*******************************************************************/
+      /*                                                                 */
+      /* Unicode encoding support                                        */
+      /*                                                                 */
+    case ft_encoding_unicode:
+      /* if this charmap is used, we ignore the encoding of the font and */
+      /* use the `PSNames' module to synthetize the Unicode charmap      */
+      result = psnames->lookup_unicode( &face->unicode_map,
+                                        (FT_ULong)charcode );
+
+      /* the function returns 0xFFFF if the Unicode charcode has */
+      /* no corresponding glyph                                  */
+      if ( result == 0xFFFFU )
+        result = 0;
+
+      /* The result returned is the index (position)in the CharStrings */
+      /* array.  This must be used now to get the value associated to  */
+      /* that glyph_name, which is the real index within the truetype  */
+      /* structure.                                                    */
+      result = ft_atoi( (const char*)face->type1.charstrings[result] );
+      goto Exit;
+
+      /*******************************************************************/
+      /*                                                                 */
+      /* ISOLatin1 encoding support                                      */
+      /*                                                                 */
+    case ft_encoding_latin_1:
+      /* ISOLatin1 is the first page of Unicode */
+      if ( charcode < 256 && psnames->unicode_value )
+      {
+        result = psnames->lookup_unicode( &face->unicode_map,
+                                          (FT_ULong)charcode );
+
+        /* the function returns 0xFFFF if the Unicode charcode has */
+        /* no corresponding glyph                                  */
+        if ( result == 0xFFFFU )
+          result = 0;
+      }
+      goto Exit;
+
+      /*******************************************************************/
+      /*                                                                 */
+      /* Custom Type 1 encoding                                          */
+      /*                                                                 */
+    case ft_encoding_adobe_custom:
+      {
+        T1_Encoding  encoding = &face->type1.encoding;
+
+
+        if ( charcode >= encoding->code_first &&
+             charcode <= encoding->code_last  )
+        {
+          FT_UInt idx = encoding->char_index[charcode];
+
+
+          result = ft_atoi( (const char *)face->type1.charstrings[idx] );
+        }
+        goto Exit;
+      }
+
+      /*******************************************************************/
+      /*                                                                 */
+      /* Adobe Standard & Expert encoding support                        */
+      /*                                                                 */
+    default:
+      if ( charcode < 256 )
+      {
+        FT_UInt      code;
+        FT_Int       n;
+        const char*  glyph_name;
+
+
+        code = psnames->adobe_std_encoding[charcode];
+        if ( charmap->encoding == ft_encoding_adobe_expert )
+          code = psnames->adobe_expert_encoding[charcode];
+
+        glyph_name = psnames->adobe_std_strings( code );
+        if ( !glyph_name )
+          break;
+
+        for ( n = 0; n < face->type1.num_glyphs; n++ )
+        {
+          const char*  gname = face->type1.glyph_names[n];
+
+          if ( gname && ( ft_strcmp( gname, glyph_name ) == 0 ) )
+          {
+            result = ft_atoi( (const char *)face->type1.charstrings[n] );
+            break;
+          }
+        }
+      }
+    }
+
+  Exit:
+    return result;
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  T42_Size_Init( T42_Size  size )
+  {
+    FT_Face   face = size->root.face;
+    T42_Face  t42face = (T42_Face)face;
+    FT_Size   ttsize;
+    FT_Error  error   = FT_Err_Ok;
+
+
+    error = FT_New_Size( t42face->ttf_face, &ttsize );
+    size->ttsize = ttsize;
+
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  T42_Size_Done( T42_Size  size )
+  {
+    FT_Face      face    = size->root.face;
+    T42_Face     t42face = (T42_Face)face;
+    FT_ListNode  node;
+
+
+    node = FT_List_Find( &t42face->ttf_face->sizes_list, size->ttsize );
+    if ( node )
+    {
+      FT_Done_Size( size->ttsize );
+      size->ttsize = NULL;
+    }
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  T42_GlyphSlot_Init( T42_GlyphSlot  slot )
+  {
+    FT_Face       face    = slot->root.face;
+    T42_Face      t42face = (T42_Face)face;
+    FT_GlyphSlot  ttslot;
+    FT_Error      error   = FT_Err_Ok;
+
+
+    if ( face->glyph == NULL )
+    {
+      /* First glyph slot for this face */
+      slot->ttslot = t42face->ttf_face->glyph;
+    }
+    else
+    {
+      error = FT_New_GlyphSlot( t42face->ttf_face, &ttslot );
+      slot->ttslot = ttslot;
+    }
+
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  T42_GlyphSlot_Done( T42_GlyphSlot slot )
+  {
+    FT_Face       face    = slot->root.face;
+    T42_Face      t42face = (T42_Face)face;
+    FT_GlyphSlot  cur     = t42face->ttf_face->glyph;
+
+
+    while ( cur )
+    {
+      if ( cur == slot->ttslot )
+      {
+        FT_Done_GlyphSlot( slot->ttslot );
+        break;
+      }
+
+      cur = cur->next;
+    }
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  T42_Size_SetChars( T42_Size    size,
+                     FT_F26Dot6  char_width,
+                     FT_F26Dot6  char_height,
+                     FT_UInt     horz_resolution,
+                     FT_UInt     vert_resolution )
+  {
+    FT_Face   face    = size->root.face;
+    T42_Face  t42face = (T42_Face)face;
+
+
+    return FT_Set_Char_Size( t42face->ttf_face,
+                             char_width,
+                             char_height,
+                             horz_resolution,
+                             vert_resolution );
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  T42_Size_SetPixels( T42_Size  size,
+                      FT_UInt   pixel_width,
+                      FT_UInt   pixel_height )
+  {
+    FT_Face   face    = size->root.face;
+    T42_Face  t42face = (T42_Face)face;
+
+
+    return FT_Set_Pixel_Sizes( t42face->ttf_face,
+                               pixel_width,
+                               pixel_height );
+  }
+
+
+  static void
+  ft_glyphslot_clear( FT_GlyphSlot  slot )
+  {
+    /* free bitmap if needed */
+    if ( slot->flags & FT_GLYPH_OWN_BITMAP )
+    {
+      FT_Memory  memory = FT_FACE_MEMORY( slot->face );
+
+
+      FT_FREE( slot->bitmap.buffer );
+      slot->flags &= ~FT_GLYPH_OWN_BITMAP;
+    }
+
+    /* clear all public fields in the glyph slot */
+    FT_MEM_SET( &slot->metrics, 0, sizeof ( slot->metrics ) );
+    FT_MEM_SET( &slot->outline, 0, sizeof ( slot->outline ) );
+    FT_MEM_SET( &slot->bitmap,  0, sizeof ( slot->bitmap )  );
+
+    slot->bitmap_left   = 0;
+    slot->bitmap_top    = 0;
+    slot->num_subglyphs = 0;
+    slot->subglyphs     = 0;
+    slot->control_data  = 0;
+    slot->control_len   = 0;
+    slot->other         = 0;
+    slot->format        = ft_glyph_format_none;
+
+    slot->linearHoriAdvance = 0;
+    slot->linearVertAdvance = 0;
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  T42_GlyphSlot_Load( FT_GlyphSlot  glyph,
+                      FT_Size       size,
+                      FT_Int        glyph_index,
+                      FT_Int        load_flags )
+  {
+    FT_Error         error;
+    T42_GlyphSlot    t42slot = (T42_GlyphSlot)glyph;
+    T42_Size         t42size = (T42_Size)size;
+    FT_Driver_Class  ttclazz = ((T42_Driver)glyph->face->driver)->ttclazz;
+
+
+    ft_glyphslot_clear( t42slot->ttslot );
+    error = ttclazz->load_glyph( t42slot->ttslot,
+                                 t42size->ttsize,
+                                 glyph_index,
+                                 load_flags | FT_LOAD_NO_BITMAP );
+
+    if ( !error )
+    {
+      glyph->metrics = t42slot->ttslot->metrics;
+
+      glyph->linearHoriAdvance = t42slot->ttslot->linearHoriAdvance;
+      glyph->linearVertAdvance = t42slot->ttslot->linearVertAdvance;
+
+      glyph->format  = t42slot->ttslot->format;
+      glyph->outline = t42slot->ttslot->outline;
+
+      glyph->bitmap      = t42slot->ttslot->bitmap;
+      glyph->bitmap_left = t42slot->ttslot->bitmap_left;
+      glyph->bitmap_top  = t42slot->ttslot->bitmap_top;
+    }
+
+    return error;
+  }
+
+
+
+  FT_LOCAL_DEF( FT_Long )
+  T42_CMap_CharNext( FT_CharMap  charmap,
+                     FT_Long     charcode )
+  {
+    T42_Face         face;
+    PSNames_Service  psnames;
+
+
+    face    = (T42_Face)charmap->face;
+    psnames = (PSNames_Service)face->psnames;
+
+    if ( psnames )
+      switch ( charmap->encoding )
+      {
+        /*******************************************************************/
+        /*                                                                 */
+        /* Unicode encoding support                                        */
+        /*                                                                 */
+      case ft_encoding_unicode:
+        /* use the `PSNames' module to synthetize the Unicode charmap */
+        return psnames->next_unicode( &face->unicode_map,
+                                      (FT_ULong)charcode );
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* ISOLatin1 encoding support                                      */
+        /*                                                                 */
+      case ft_encoding_latin_1:
+        {
+          FT_ULong code;
+
+
+          /* use the `PSNames' module to synthetize the Unicode charmap */
+          code = psnames->next_unicode( &face->unicode_map,
+                                        (FT_ULong)charcode );
+          if ( code < 256 )
+            return code;
+          break;
+        }
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* Custom Type 1 encoding                                          */
+        /*                                                                 */
+      case ft_encoding_adobe_custom:
+        {
+          T1_Encoding  encoding = &face->type1.encoding;
+
+
+          charcode++;
+          if ( charcode < encoding->code_first )
+            charcode = encoding->code_first;
+          while ( charcode <= encoding->code_last  ) {
+            if ( encoding->char_index[charcode] )
+              return charcode;
+            charcode++;
+          }
+        }
+
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* Adobe Standard & Expert encoding support                        */
+        /*                                                                 */
+      default:
+        while ( ++charcode < 256 )
+        {
+          FT_UInt      code;
+          FT_Int       n;
+          const char*  glyph_name;
+
+
+          code = psnames->adobe_std_encoding[charcode];
+          if ( charmap->encoding == ft_encoding_adobe_expert )
+            code = psnames->adobe_expert_encoding[charcode];
+
+          glyph_name = psnames->adobe_std_strings( code );
+          if ( !glyph_name )
+            continue;
+
+          for ( n = 0; n < face->type1.num_glyphs; n++ )
+          {
+            const char*  gname = face->type1.glyph_names[n];
+
+
+            if ( gname && gname[0] == glyph_name[0]  &&
+                 ft_strcmp( gname, glyph_name ) == 0 )
+              return charcode;
+          }
+        }
+      }
+
+    return 0;
+  }
+
--- /dev/null
+++ b/src/type42/t42objs.h
@@ -1,0 +1,130 @@
+#ifndef __TYPE42_OBJS_H__
+#define __TYPE42_OBJS_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_TYPE1_TABLES_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DRIVER_H
+#include FT_INTERNAL_POSTSCRIPT_NAMES_H
+#include FT_INTERNAL_POSTSCRIPT_HINTS_H
+
+FT_BEGIN_HEADER
+
+ /* Type42 face */
+  typedef struct  T42_FaceRec_
+  {
+    FT_FaceRec     root;
+    T1_FontRec     type1;
+    const void*    psnames;
+    const void*    psaux;
+    const void*    afm_data;
+
+    FT_CharMapRec  charmaprecs[2];
+    FT_CharMap     charmaps[2];
+    PS_Unicodes    unicode_map;
+
+    FT_Byte*       ttf_data;
+    FT_ULong       ttf_size;
+    FT_Face        ttf_face;
+
+  } T42_FaceRec, *T42_Face;
+
+
+
+ /* Type42 size */
+  typedef struct  T42_SizeRec_
+  {
+    FT_SizeRec  root;
+    FT_Size     ttsize;
+
+  } T42_SizeRec, *T42_Size;
+
+
+ /* Type42 slot */
+  typedef struct  T42_GlyphSlotRec_
+  {
+    FT_GlyphSlotRec  root;
+    FT_GlyphSlot     ttslot;
+
+  } T42_GlyphSlotRec, *T42_GlyphSlot;
+
+
+ /* Type 42 driver */
+  typedef struct  T42_DriverRec_
+  {
+    FT_DriverRec     root;
+    FT_Driver_Class  ttclazz;
+    void*            extension_component;
+
+  } T42_DriverRec, *T42_Driver;
+
+ /* */
+
+  FT_LOCAL( FT_Error )
+  T42_Face_Init( FT_Stream      stream,
+                 T42_Face       face,
+                 FT_Int         face_index,
+                 FT_Int         num_params,
+                 FT_Parameter*  params );
+
+
+  FT_LOCAL( void )
+  T42_Face_Done( T42_Face  face );
+
+
+  FT_LOCAL( FT_Error )
+  T42_Size_Init( T42_Size  size );
+
+
+  FT_LOCAL( FT_Error )
+  T42_Size_SetChars( T42_Size    size,
+                     FT_F26Dot6  char_width,
+                     FT_F26Dot6  char_height,
+                     FT_UInt     horz_resolution,
+                     FT_UInt     vert_resolution );
+
+  FT_LOCAL( FT_Error )
+  T42_Size_SetPixels( T42_Size  size,
+                      FT_UInt   pixel_width,
+                      FT_UInt   pixel_height );
+
+  FT_LOCAL( void )
+  T42_Size_Done( T42_Size  size );
+
+
+  FT_LOCAL( FT_Error )
+  T42_GlyphSlot_Init( T42_GlyphSlot  slot );
+
+
+  FT_LOCAL( FT_Error )
+  T42_GlyphSlot_Load( FT_GlyphSlot  glyph,
+                      FT_Size       size,
+                      FT_Int        glyph_index,
+                      FT_Int        load_flags );
+
+  FT_LOCAL( void )
+  T42_GlyphSlot_Done( T42_GlyphSlot slot );
+
+
+  FT_LOCAL( FT_UInt )
+  T42_CMap_CharIndex( FT_CharMap  charmap,
+                      FT_Long     charcode );
+
+  FT_LOCAL( FT_Long )
+  T42_CMap_CharNext( FT_CharMap  charmap,
+                     FT_Long     charcode );
+
+
+  FT_LOCAL( FT_Error )
+  T42_Driver_Init( T42_Driver  driver );
+
+  FT_LOCAL( void )
+  T42_Driver_Done( T42_Driver  driver );
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __TYPE42_OBJS_H__ */
--- /dev/null
+++ b/src/type42/t42parse.c
@@ -1,0 +1,1083 @@
+#include "t42parse.h"
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_LIST_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t42
+
+  static void
+  t42_parse_font_name( T42_Face    face,
+                       T42_Loader  loader );
+                       
+  static void
+  t42_parse_font_bbox( T42_Face    face,
+                       T42_Loader  loader );
+                       
+  static void
+  t42_parse_font_matrix( T42_Face    face,
+                         T42_Loader  loader );
+  static void
+  t42_parse_encoding( T42_Face    face,
+                      T42_Loader  loader );
+                      
+  static void
+  t42_parse_charstrings( T42_Face    face,
+                         T42_Loader  loader );
+                         
+  static void
+  t42_parse_sfnts( T42_Face    face,
+                   T42_Loader  loader );
+
+
+  static const
+  T1_FieldRec  t42_keywords[] = {
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  T1_FontInfo
+#undef  T1CODE
+#define T1CODE        T1_FIELD_LOCATION_FONT_INFO
+
+    T1_FIELD_STRING   ( "version",            version )
+    T1_FIELD_STRING   ( "Notice",             notice )
+    T1_FIELD_STRING   ( "FullName",           full_name )
+    T1_FIELD_STRING   ( "FamilyName",         family_name )
+    T1_FIELD_STRING   ( "Weight",             weight )
+    T1_FIELD_NUM      ( "ItalicAngle",        italic_angle )
+    T1_FIELD_TYPE_BOOL( "isFixedPitch",       is_fixed_pitch )
+    T1_FIELD_NUM      ( "UnderlinePosition",  underline_position )
+    T1_FIELD_NUM      ( "UnderlineThickness", underline_thickness )
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  T1_FontRec
+#undef  T1CODE
+#define T1CODE        T1_FIELD_LOCATION_FONT_DICT
+
+    T1_FIELD_NUM( "PaintType",   paint_type )
+    T1_FIELD_NUM( "FontType",    font_type )
+    T1_FIELD_NUM( "StrokeWidth", stroke_width )
+
+    T1_FIELD_CALLBACK( "FontName",    t42_parse_font_name )
+    T1_FIELD_CALLBACK( "FontBBox",    t42_parse_font_bbox )
+    T1_FIELD_CALLBACK( "FontMatrix",  t42_parse_font_matrix )
+    T1_FIELD_CALLBACK( "Encoding",    t42_parse_encoding )
+    T1_FIELD_CALLBACK( "CharStrings", t42_parse_charstrings )
+    T1_FIELD_CALLBACK( "sfnts",       t42_parse_sfnts )
+
+    { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 }
+  };
+
+
+#define T1_Add_Table( p, i, o, l )  (p)->funcs.add( (p), i, o, l )
+#define T1_Done_Table( p )          \
+          do                        \
+          {                         \
+            if ( (p)->funcs.done )  \
+              (p)->funcs.done( p ); \
+          } while ( 0 )
+#define T1_Release_Table( p )          \
+          do                           \
+          {                            \
+            if ( (p)->funcs.release )  \
+              (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_ToInt( p )       (p)->root.funcs.to_int( &(p)->root )
+#define T1_ToFixed( p, t )  (p)->root.funcs.to_fixed( &(p)->root, t )
+
+#define T1_ToCoordArray( p, m, c )                           \
+          (p)->root.funcs.to_coord_array( &(p)->root, m, c )
+#define T1_ToFixedArray( p, m, f, t )                           \
+          (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
+#define T1_ToToken( p, t )                          \
+          (p)->root.funcs.to_token( &(p)->root, t )
+#define T1_ToTokenArray( p, t, m, c )                           \
+          (p)->root.funcs.to_token_array( &(p)->root, t, m, c )
+
+#define T1_Load_Field( p, f, o, m, pf )                         \
+          (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )
+#define T1_Load_Field_Table( p, f, o, m, pf )                         \
+          (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )
+
+
+  /********************* Parsing Functions ******************/
+
+  FT_LOCAL_DEF( FT_Error )
+  t42_parser_init( T42_Parser     parser,
+                   FT_Stream      stream,
+                   FT_Memory      memory,
+                   PSAux_Service  psaux )
+  {
+    FT_Error  error = FT_Err_Ok;
+    FT_Long   size;
+
+
+    psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
+
+    parser->stream    = stream;
+    parser->base_len  = 0;
+    parser->base_dict = 0;
+    parser->in_memory = 0;
+
+    /*******************************************************************/
+    /*                                                                 */
+    /* Here a short summary of what is going on:                       */
+    /*                                                                 */
+    /*   When creating a new Type 42 parser, we try to locate and load */
+    /*   the base dictionary, loading the whole font into memory.      */
+    /*                                                                 */
+    /*   When `loading' the base dictionary, we only setup pointers in */
+    /*   the case of a memory-based stream.  Otherwise, we allocate    */
+    /*   and load the base dictionary in it.                           */
+    /*                                                                 */
+    /*   parser->in_memory is set if we have a memory stream.          */
+    /*                                                                 */
+
+    if ( FT_STREAM_SEEK( 0L ) )
+      goto Exit;
+
+    size = stream->size;
+
+    /* now, try to load `size' bytes of the `base' dictionary we */
+    /* found previously                                          */
+
+    /* if it is a memory-based resource, set up pointers */
+    if ( !stream->read )
+    {
+      parser->base_dict = (FT_Byte*)stream->base + stream->pos;
+      parser->base_len  = size;
+      parser->in_memory = 1;
+
+      /* check that the `size' field is valid */
+      if ( FT_STREAM_SKIP( size ) )
+        goto Exit;
+    }
+    else
+    {
+      /* read segment in memory */
+      if ( FT_ALLOC( parser->base_dict, size )      ||
+          FT_STREAM_READ( parser->base_dict, size ) )
+        goto Exit;
+
+      parser->base_len = size;
+    }
+
+    /* Now check font format; we must see `%!PS-TrueTypeFont' */
+    if (size <= 17                                    ||
+        ( ft_strncmp( (const char*)parser->base_dict,
+                      "%!PS-TrueTypeFont", 17) )      )
+      error = FT_Err_Unknown_File_Format;
+    else
+    {
+      parser->root.base   = parser->base_dict;
+      parser->root.cursor = parser->base_dict;
+      parser->root.limit  = parser->root.cursor + parser->base_len;
+    }
+
+  Exit:
+    if ( error && !parser->in_memory )
+      FT_FREE( parser->base_dict );
+
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  t42_parser_done( T42_Parser  parser )
+  {
+    FT_Memory  memory = parser->root.memory;
+
+
+    /* free the base dictionary only when we have a disk stream */
+    if ( !parser->in_memory )
+      FT_FREE( parser->base_dict );
+
+    parser->root.funcs.done( &parser->root );
+  }
+
+
+  static int
+  t42_is_alpha( FT_Byte  c )
+  {
+    /* Note: we must accept "+" as a valid character, as it is used in */
+    /*       embedded type1 fonts in PDF documents.                    */
+    /*                                                                 */
+    return ( ft_isalnum( c ) ||
+             c == '.'        ||
+             c == '_'        ||
+             c == '-'        ||
+             c == '+'        );
+  }
+
+
+  static int
+  t42_is_space( FT_Byte  c )
+  {
+    return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
+  }
+
+
+  static void
+  t42_parse_font_name( T42_Face    face,
+                       T42_Loader  loader )
+  {
+    T42_Parser  parser = &loader->parser;
+    FT_Error    error;
+    FT_Memory   memory = parser->root.memory;
+    FT_Int      len;
+    FT_Byte*    cur;
+    FT_Byte*    cur2;
+    FT_Byte*    limit;
+
+
+    T1_Skip_Spaces( parser );
+
+    cur   = parser->root.cursor;
+    limit = parser->root.limit;
+
+    if ( cur >= limit - 1              ||
+         ( *cur != '/' && *cur != '(') )
+      return;
+
+    cur++;
+    cur2 = cur;
+    while ( cur2 < limit && t42_is_alpha( *cur2 ) )
+      cur2++;
+
+    len = (FT_Int)( cur2 - cur );
+    if ( len > 0 )
+    {
+      if ( FT_ALLOC( face->type1.font_name, len + 1 ) )
+      {
+        parser->root.error = error;
+        return;
+      }
+
+      FT_MEM_COPY( face->type1.font_name, cur, len );
+      face->type1.font_name[len] = '\0';
+    }
+    parser->root.cursor = cur2;
+  }
+
+
+  static void
+  t42_parse_font_bbox( T42_Face   face,
+                       T42_Loader  loader )
+  {
+    T42_Parser  parser = &loader->parser;
+    FT_BBox*    bbox   = &face->type1.font_bbox;
+
+    bbox->xMin = T1_ToInt( parser );
+    bbox->yMin = T1_ToInt( parser );
+    bbox->xMax = T1_ToInt( parser );
+    bbox->yMax = T1_ToInt( parser );
+  }
+
+
+  static void
+  t42_parse_font_matrix( T42_Face    face,
+                         T42_Loader  loader )
+  {
+    T42_Parser  parser = &loader->parser;
+    FT_Matrix*  matrix = &face->type1.font_matrix;
+    FT_Vector*  offset = &face->type1.font_offset;
+    FT_Face     root   = (FT_Face)&face->root;
+    FT_Fixed    temp[6];
+    FT_Fixed    temp_scale;
+
+
+    (void)T1_ToFixedArray( parser, 6, temp, 3 );
+
+    temp_scale = ABS( temp[3] );
+
+    /* 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).                              */
+
+    root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L,
+                                                 temp_scale ) >> 16 );
+
+    /* we need to scale the values by 1.0/temp_scale */
+    if ( temp_scale != 0x10000L ) {
+      temp[0] = FT_DivFix( temp[0], temp_scale );
+      temp[1] = FT_DivFix( temp[1], temp_scale );
+      temp[2] = FT_DivFix( temp[2], temp_scale );
+      temp[4] = FT_DivFix( temp[4], temp_scale );
+      temp[5] = FT_DivFix( temp[5], temp_scale );
+      temp[3] = 0x10000L;
+    }
+
+    matrix->xx = temp[0];
+    matrix->yx = temp[1];
+    matrix->xy = temp[2];
+    matrix->yy = temp[3];
+
+    /* note that the offsets must be expressed in integer font units */
+    offset->x  = temp[4] >> 16;
+    offset->y  = temp[5] >> 16;
+  }
+
+
+  static void
+  t42_parse_encoding( T42_Face    face,
+                      T42_Loader  loader )
+  {
+    T42_Parser     parser = &loader->parser;
+    FT_Byte*       cur    = parser->root.cursor;
+    FT_Byte*       limit  = parser->root.limit;
+
+    PSAux_Service  psaux  = (PSAux_Service)face->psaux;
+
+
+    /* skip whitespace */
+    while ( t42_is_space( *cur ) )
+    {
+      cur++;
+      if ( cur >= limit )
+      {
+        FT_ERROR(( "t42_parse_encoding: out of bounds!\n" ));
+        parser->root.error = FT_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 )
+    {
+      T1_Encoding  encode     = &face->type1.encoding;
+      FT_Int       count, n;
+      PS_Table     char_table = &loader->encoding_table;
+      FT_Memory    memory     = parser->root.memory;
+      FT_Error     error;
+
+
+      /* read the number of entries in the encoding, should be 256 */
+      count = T1_ToInt( parser );
+      if ( parser->root.error )
+        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 ) ||
+           FT_SET_ERROR( psaux->ps_table_funcs->init(
+                           char_table, count, memory ) ) )
+      {
+        parser->root.error = error;
+        return;
+      }
+
+      /* We need to `zero' out encoding_table.elements */
+      for ( n = 0; n < count; n++ )
+      {
+        char*  notdef = (char *)".notdef";
+
+
+        T1_Add_Table( char_table, n, notdef, 8 );
+      }
+
+      /* Now, we will 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:                     */
+      /*                                                        */
+      /*   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;
+
+      for ( ; cur < limit; )
+      {
+        FT_Byte  c;
+
+
+        c = *cur;
+
+        /* we stop when we encounter a `def' */
+        if ( c == 'd' && cur + 3 < limit )
+        {
+          if ( cur[1] == 'e'       &&
+               cur[2] == 'f'       &&
+               t42_is_space( cur[-1] ) &&
+               t42_is_space( cur[3] )  )
+          {
+            FT_TRACE6(( "encoding end\n" ));
+            break;
+          }
+        }
+
+        /* otherwise, we must find a number before anything else */
+        if ( (FT_Byte)( c - '0' ) < 10 )
+        {
+          FT_Int  charcode;
+
+
+          parser->root.cursor = cur;
+          charcode = T1_ToInt( parser );
+          cur      = parser->root.cursor;
+
+          /* skip whitespace */
+          while ( cur < limit && t42_is_space( *cur ) )
+            cur++;
+
+          if ( cur < limit && *cur == '/' )
+          {
+            /* bingo, we have an immediate name -- it must be a */
+            /* character name                                   */
+            FT_Byte*  cur2 = cur + 1;
+            FT_Int    len;
+
+
+            while ( cur2 < limit && t42_is_alpha( *cur2 ) )
+              cur2++;
+
+            len = (FT_Int)( cur2 - cur - 1 );
+
+            parser->root.error = T1_Add_Table( char_table, charcode,
+                                               cur + 1, len + 1 );
+            char_table->elements[charcode][len] = '\0';
+            if ( parser->root.error )
+              return;
+
+            cur = cur2;
+          }
+        }
+        else
+          cur++;
+      }
+
+      face->type1.encoding_type  = T1_ENCODING_TYPE_ARRAY;
+      parser->root.cursor        = cur;
+    }
+    /* Otherwise, we should have either `StandardEncoding', */
+    /* `ExpertEncoding', or `ISOLatin1Encoding'             */
+    else
+    {
+      if ( cur + 17 < limit                                            &&
+           ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
+        face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;
+
+      else if ( cur + 15 < limit                                          &&
+                ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
+        face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;
+
+      else if ( cur + 18 < limit                                             &&
+                ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
+        face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
+
+      else {
+        FT_ERROR(( "t42_parse_encoding: invalid token!\n" ));
+        parser->root.error = FT_Err_Invalid_File_Format;
+      }
+    }
+  }
+
+
+  static FT_UInt
+  t42_hexval( FT_Byte  v )
+  {
+    FT_UInt  d;
+    
+    d = (FT_UInt)( v - 'A' );
+    if ( d < 6 )
+    {
+      d += 10;
+      goto Exit;
+    }
+      
+    d = (FT_UInt)( v - 'a' );
+    if ( d < 6 )
+    {
+      d += 10;
+      goto Exit;
+    }
+      
+    d = (FT_UInt)( v - '0' );
+    if ( d < 10 )
+      goto Exit;
+      
+    d = 0;
+ 
+  Exit:         
+    return d;
+  }
+
+
+  static void
+  t42_parse_sfnts( T42_Face    face,
+                   T42_Loader  loader )
+  {
+    T42_Parser  parser = &loader->parser;
+    FT_Memory   memory = parser->root.memory;
+    FT_Byte*    cur    = parser->root.cursor;
+    FT_Byte*    limit  = parser->root.limit;
+    FT_Error    error;
+    FT_Int      num_tables = 0, status;
+    FT_ULong    count, ttf_size = 0, string_size = 0;
+    FT_Bool     in_string  = 0;
+    FT_Byte     v = 0;
+
+
+    /* The format is `/sfnts [ <...> <...> ... ] def' */
+
+    while ( t42_is_space( *cur ) )
+      cur++;
+
+    if (*cur++ == '[')
+    {
+      status = 0;
+      count = 0;
+    }
+    else
+    {
+      FT_ERROR(( "t42_parse_sfnts: can't find begin of sfnts vector!\n" ));
+      error = FT_Err_Invalid_File_Format;
+      goto Fail;
+    }
+
+    while ( cur < limit - 2 )
+    {
+      while ( t42_is_space( *cur ) )
+        cur++;
+
+      switch ( *cur )
+      {
+      case ']':
+        parser->root.cursor = cur++;
+        return;
+
+      case '<':
+        in_string   = 1;
+        string_size = 0;
+        cur++;
+        continue;
+
+      case '>':
+        if ( !in_string )
+        {
+          FT_ERROR(( "t42_parse_sfnts: found unpaired `>'!\n" ));
+          error = FT_Err_Invalid_File_Format;
+          goto Fail;
+        }
+
+        /* A string can have, as a last byte,         */
+        /* a zero byte for padding.  If so, ignore it */
+        if ( ( v == 0 ) && ( string_size % 2 == 1 ) )
+          count--;
+        in_string = 0;
+        cur++;
+        continue;
+
+      case '%':
+        if ( !in_string )
+        {
+          /* Comment found; skip till end of line */
+          while ( *cur != '\n' )
+            cur++;
+          continue;
+        }
+        else
+        {
+          FT_ERROR(( "t42_parse_sfnts: found `%' in string!\n" ));
+          error = FT_Err_Invalid_File_Format;
+          goto Fail;
+        }
+
+      default:
+        if ( !ft_xdigit( *cur ) || !ft_xdigit( *(cur + 1) ) )
+        {
+          FT_ERROR(( "t42_parse_sfnts: found non-hex characters in string" ));
+          error = FT_Err_Invalid_File_Format;
+          goto Fail;
+        }
+
+        v = (FT_Byte)( 16 * t42_hexval( *cur++ ) + t42_hexval( *cur++ ) );
+        string_size++;
+      }
+
+      switch ( status )
+      {
+      case 0: /* The '[' was read, so load offset table, 12 bytes */
+        if ( count < 12 )
+        {
+          face->ttf_data[count++] = v;
+          continue;
+        }
+        else
+        {
+          num_tables = 16 * face->ttf_data[4] + face->ttf_data[5];
+          status     = 1;
+          ttf_size   = 12 + 16 * num_tables;
+
+          if ( FT_REALLOC( face->ttf_data, 12, ttf_size ) )
+            goto Fail;
+        }
+        /* No break, fall-through */
+
+      case 1: /* The offset table is read; read now the table directory */
+        if ( count < ttf_size )
+        {
+          face->ttf_data[count++] = v;
+          continue;
+        }
+        else
+        {
+          int      i;
+          FT_ULong len;
+
+
+          for ( i = 0; i < num_tables; i++ )
+          {
+            FT_Byte*  p = face->ttf_data + 12 + 16*i + 12;
+            
+            len = FT_PEEK_ULONG( p );
+
+            /* Pad to a 4-byte boundary length */
+            ttf_size += ( len + 3 ) & ~3;
+          }
+
+          status         = 2;
+          face->ttf_size = ttf_size;
+
+          if ( FT_REALLOC( face->ttf_data, 12 + 16 * num_tables,
+                           ttf_size + 1 ) )
+            goto Fail;
+        }
+        /* No break, fall-through */
+
+      case 2: /* We are reading normal tables; just swallow them */
+        face->ttf_data[count++] = v;
+
+      }
+    }
+
+    /* If control reaches this point, the format was not valid */
+    error = FT_Err_Invalid_File_Format;
+
+  Fail:
+    parser->root.error = error;
+  }
+
+
+  static void
+  t42_parse_charstrings( T42_Face    face,
+                         T42_Loader  loader )
+  {
+    T42_Parser     parser     = &loader->parser;
+    PS_Table       code_table = &loader->charstrings;
+    PS_Table       name_table = &loader->glyph_names;
+    FT_Memory      memory     = parser->root.memory;
+    FT_Error       error;
+
+    PSAux_Service  psaux      = (PSAux_Service)face->psaux;
+
+    FT_Byte*       cur;
+    FT_Byte*       limit      = parser->root.limit;
+    FT_Int         n;
+
+
+    loader->num_glyphs = T1_ToInt( parser );
+    if ( parser->root.error )
+      return;
+
+    /* initialize tables */
+
+    error = psaux->ps_table_funcs->init( code_table,
+                                         loader->num_glyphs,
+                                         memory );
+    if ( error )
+      goto Fail;
+
+    error = psaux->ps_table_funcs->init( name_table,
+                                         loader->num_glyphs,
+                                         memory );
+    if ( error )
+      goto Fail;
+
+    n = 0;
+
+    for (;;)
+    {
+      /* the format is simple:                    */
+      /*   `/glyphname' + index + def             */
+      /*                                          */
+      /* note that we stop when we find an `end'  */
+      /*                                          */
+      T1_Skip_Spaces( parser );
+
+      cur = parser->root.cursor;
+      if ( cur >= limit )
+        break;
+
+      /* we stop when we find an `end' keyword */
+      if ( *cur   == 'e'   &&
+           cur + 3 < limit &&
+           cur[1] == 'n'   &&
+           cur[2] == 'd'   )
+        break;
+
+      if ( *cur != '/' )
+        T1_Skip_Alpha( parser );
+      else
+      {
+        FT_Byte*  cur2 = cur + 1;
+        FT_Int    len;
+
+
+        while ( cur2 < limit && t42_is_alpha( *cur2 ) )
+          cur2++;
+        len = (FT_Int)( cur2 - cur - 1 );
+
+        error = T1_Add_Table( name_table, n, cur + 1, len + 1 );
+        if ( error )
+          goto Fail;
+
+        /* add a trailing zero to the name table */
+        name_table->elements[n][len] = '\0';
+
+        parser->root.cursor = cur2;
+        T1_Skip_Spaces( parser );
+
+        cur2 = cur = parser->root.cursor;
+        if ( cur >= limit )
+          break;
+
+        while ( cur2 < limit && t42_is_alpha( *cur2 ) )
+          cur2++;
+        len = (FT_Int)( cur2 - cur );
+
+        error = T1_Add_Table( code_table, n, cur, len + 1 );
+        if ( error )
+          goto Fail;
+
+        code_table->elements[n][len] = '\0';
+
+        n++;
+        if ( n >= loader->num_glyphs )
+          break;
+      }
+    }
+
+    /* Index 0 must be a .notdef element */
+    if ( ft_strcmp( (char *)name_table->elements[0], ".notdef" ) )
+    {
+      FT_ERROR(( "t42_parse_charstrings: Index 0 is not `.notdef'!\n" ));
+      error = FT_Err_Invalid_File_Format;
+      goto Fail;
+    }
+
+    loader->num_glyphs = n;
+    return;
+
+  Fail:
+    parser->root.error = error;
+  }
+
+
+  static FT_Error
+  t42_load_keyword( T42_Face    face,
+                    T42_Loader  loader,
+                    T1_Field    field )
+  {
+    FT_Error  error;
+    void*     dummy_object;
+    void**    objects;
+    FT_UInt   max_objects = 0;
+
+
+    /* if the keyword has a dedicated callback, call it */
+    if ( field->type == T1_FIELD_TYPE_CALLBACK ) {
+      field->reader( (FT_Face)face, loader );
+      error = loader->parser.root.error;
+      goto Exit;
+    }
+
+    /* now, the keyword is either a simple field, or a table of fields; */
+    /* we are now going to take care of it                              */
+    switch ( field->location )
+    {
+    case T1_FIELD_LOCATION_FONT_INFO:
+      dummy_object = &face->type1.font_info;
+      objects      = &dummy_object;
+      break;
+
+    default:
+      dummy_object = &face->type1;
+      objects      = &dummy_object;
+    }
+
+    if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
+         field->type == T1_FIELD_TYPE_FIXED_ARRAY   )
+      error = T1_Load_Field_Table( &loader->parser, field,
+                                   objects, max_objects, 0 );
+    else
+      error = T1_Load_Field( &loader->parser, field,
+                             objects, max_objects, 0 );
+
+   Exit:
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  t42_parse_dict( T42_Face    face,
+                  T42_Loader  loader,
+                  FT_Byte*    base,
+                  FT_Long     size )
+  {
+    T42_Parser  parser = &loader->parser;
+    FT_Byte*    cur    = base;
+    FT_Byte*    limit  = cur + size;
+    FT_UInt     n_keywords = sizeof ( t42_keywords ) / 
+                             sizeof ( t42_keywords[0] );
+
+
+    parser->root.cursor = base;
+    parser->root.limit  = base + size;
+    parser->root.error  = 0;
+
+    for ( ; cur < limit; cur++ )
+    {
+      /* 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;
+
+
+        /* skip the `FontDirectory' keyword */
+        cur += 13;
+        cur2 = cur;
+
+        /* lookup the `known' keyword */
+        while ( cur < limit && *cur != 'k'           &&
+                ft_strncmp( (char*)cur, "known", 5 ) )
+          cur++;
+
+        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;
+      }
+      /* look for immediates */
+      else if ( *cur == '/' && cur + 2 < limit )
+      {
+        FT_Byte*  cur2;
+        FT_UInt    i, len;
+
+
+        cur++;
+        cur2 = cur;
+        while ( cur2 < limit && t42_is_alpha( *cur2 ) )
+          cur2++;
+
+        len  = (FT_UInt)( cur2 - cur );
+        if ( len > 0 && len < 22 ) /* XXX What shall it this 22? */
+        {
+          /* now, compare the immediate name to the keyword table */
+
+          /* Loop through all known keywords */
+          for ( i = 0; i < n_keywords; i++ )
+          {
+            T1_Field  keyword = (T1_Field)&t42_keywords[i];
+            FT_Byte   *name   = (FT_Byte*)keyword->ident;
+
+
+            if ( !name )
+              continue;
+
+            if ( ( len == ft_strlen( (const char *)name ) ) &&
+                 ( ft_memcmp( cur, name, len ) == 0 )       )
+            {
+              /* we found it -- run the parsing callback! */
+              parser->root.cursor = cur2;
+              T1_Skip_Spaces( parser );
+              parser->root.error = t42_load_keyword(face,
+                                                    loader,
+                                                    keyword );
+              if ( parser->root.error )
+                return parser->root.error;
+              cur = parser->root.cursor;
+              break;
+            }
+          }
+        }
+      }
+    }
+    return parser->root.error;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  t42_loader_init( T42_Loader  loader,
+                   T42_Face    face )
+  {
+    FT_UNUSED( face );
+
+    FT_MEM_SET( loader, 0, sizeof ( *loader ) );
+    loader->num_glyphs = 0;
+    loader->num_chars  = 0;
+
+    /* initialize the tables -- simply set their `init' field to 0 */
+    loader->encoding_table.init = 0;
+    loader->charstrings.init    = 0;
+    loader->glyph_names.init    = 0;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  t42_loader_done( T42_Loader  loader )
+  {
+    T42_Parser  parser = &loader->parser;
+
+
+    /* finalize tables */
+    T1_Release_Table( &loader->encoding_table );
+    T1_Release_Table( &loader->charstrings );
+    T1_Release_Table( &loader->glyph_names );
+
+    /* finalize parser */
+    t42_parser_done( parser );
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  T42_Open_Face( T42_Face  face )
+  {
+    T42_LoaderRec  loader;
+    T42_Parser     parser;
+    T1_Font        type1 = &face->type1;
+    FT_Memory      memory = face->root.memory;
+    FT_Error       error;
+
+    PSAux_Service  psaux  = (PSAux_Service)face->psaux;
+
+
+    t42_loader_init( &loader, face );
+
+    parser = &loader.parser;
+
+    if ( FT_ALLOC( face->ttf_data, 12 ) )
+      goto Exit;
+
+    error = t42_parser_init( parser,
+                             face->root.stream,
+                             memory,
+                             psaux);
+    if ( error )
+      goto Exit;
+
+    error = t42_parse_dict( face, &loader, parser->base_dict, parser->base_len );
+
+    if ( type1->font_type != 42 )
+    {
+      error = FT_Err_Unknown_File_Format;
+      goto Exit;
+    }
+
+    /* now, propagate the charstrings and glyphnames tables */
+    /* to the Type1 data                                    */
+    type1->num_glyphs = loader.num_glyphs;
+
+    if ( !loader.charstrings.init ) {
+      FT_ERROR(( "T42_Open_Face: no charstrings array in face!\n" ));
+      error = FT_Err_Invalid_File_Format;
+    }
+
+    loader.charstrings.init   = 0;
+    type1->charstrings_block = loader.charstrings.block;
+    type1->charstrings       = loader.charstrings.elements;
+    type1->charstrings_len   = loader.charstrings.lengths;
+
+    /* we copy the glyph names `block' and `elements' fields; */
+    /* the `lengths' field must be released later             */
+    type1->glyph_names_block   = loader.glyph_names.block;
+    type1->glyph_names         = (FT_String**)loader.glyph_names.elements;
+    loader.glyph_names.block    = 0;
+    loader.glyph_names.elements = 0;
+
+    /* we must now build type1.encoding when we have a custom array */
+    if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY )
+    {
+      FT_Int    charcode, idx, min_char, max_char;
+      FT_Byte*  char_name;
+      FT_Byte*  glyph_name;
+
+
+      /* OK, we do the following: for each element in the encoding   */
+      /* table, look up the index of the glyph having the same name  */
+      /* as defined in the CharStrings array.                        */
+      /* The index is then stored in type1.encoding.char_index, and  */
+      /* the name in type1.encoding.char_name                        */
+
+      min_char = +32000;
+      max_char = -32000;
+
+      charcode = 0;
+      for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
+      {
+        type1->encoding.char_index[charcode] = 0;
+        type1->encoding.char_name [charcode] = (char *)".notdef";
+
+        char_name = loader.encoding_table.elements[charcode];
+        if ( char_name )
+          for ( idx = 0; idx < type1->num_glyphs; idx++ )
+          {
+            glyph_name = (FT_Byte*)type1->glyph_names[idx];
+            if ( ft_strcmp( (const char*)char_name,
+                            (const char*)glyph_name ) == 0 )
+            {
+              type1->encoding.char_index[charcode] = (FT_UShort)idx;
+              type1->encoding.char_name [charcode] = (char*)glyph_name;
+
+              /* Change min/max encoded char only if glyph name is */
+              /* not /.notdef                                      */
+              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;
+              }
+              break;
+            }
+          }
+      }
+      type1->encoding.code_first = min_char;
+      type1->encoding.code_last  = max_char;
+      type1->encoding.num_chars  = loader.num_chars;
+    }
+
+  Exit:
+    t42_loader_done( &loader );
+    return error;
+  }
+
--- /dev/null
+++ b/src/type42/t42parse.h
@@ -1,0 +1,66 @@
+#ifndef __TYPE42_PARSE_H__
+#define __TYPE42_PARSE_H__
+
+#include "t42objs.h"
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+FT_BEGIN_HEADER
+
+  typedef struct  T42_ParserRec_
+  {
+    PS_ParserRec  root;
+    FT_Stream     stream;
+
+    FT_Byte*      base_dict;
+    FT_Int        base_len;
+
+    FT_Byte       in_memory;
+
+  } T42_ParserRec, *T42_Parser;
+
+
+  typedef struct  T42_Loader_
+  {
+    T42_ParserRec  parser;          /* parser used to read the stream */
+
+    FT_Int         num_chars;       /* number of characters in encoding */
+    PS_TableRec    encoding_table;  /* PS_Table used to store the       */
+                                    /* encoding character names         */
+
+    FT_Int         num_glyphs;
+    PS_TableRec    glyph_names;
+    PS_TableRec    charstrings;
+
+  } T42_LoaderRec, *T42_Loader;
+
+
+  FT_LOCAL( FT_Error )
+  t42_parser_init( T42_Parser     parser,
+                   FT_Stream      stream,
+                   FT_Memory      memory,
+                   PSAux_Service  psaux );
+
+  FT_LOCAL( void )
+  t42_parser_done( T42_Parser  parser );
+
+
+  FT_LOCAL( FT_Error )
+  t42_parse_dict( T42_Face    face,
+                  T42_Loader  loader,
+                  FT_Byte*    base,
+                  FT_Long     size );
+
+
+  FT_LOCAL( void )
+  t42_loader_init( T42_Loader  loader,
+                   T42_Face    face );
+
+  FT_LOCAL( void )
+  t42_loader_done( T42_Loader  loader );
+
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __TYPE42_PARSE_H__ */
--- /dev/null
+++ b/src/type42/type42.c
@@ -1,0 +1,17 @@
+/***************************************************************************/
+/*                                                                         */
+/*  type42c                                                                */
+/*                                                                         */
+/*    FreeType Type 42 driver component                                    */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "t42objs.c"
+#include "t42parse.c"
+#include "t42drivr.c"
+
+/* END */