shithub: freetype+ttf2subf

Download patch

ref: 04aa800ce982d340befbec799ed9d3735eb6bd64
parent: 3581d06464d3c964c112aeb9b28678f88fefed87
author: David Turner <[email protected]>
date: Wed May 31 23:27:48 EDT 2000

added a CID-keyed font driver in "src/cid"
fixed two bugs in the smooth renderer

git/fs: mount .git/fs: mount/attach disallowed
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,12 @@
 LATEST_CHANGES
 
+  - added the CID-keyed Type 1 driver in "src/cid". Works pretty well for
+    only 13 Kb of code ;-) Doesn't read AFM files though, nor the really
+    useful CMAP files..
+
+  - fixed two bugs in the smooth renderer (src/base/ftgrays.c). Thanks to
+    Boris Letocha for spotting them and providing a fix..
+
   - fixed potential "divide by zero" bugs in ftcalc.c.. my god..
 
   - added source code for the OpenType/CFF driver (still incomplete though..)
--- a/demos/src/ftlint.c
+++ b/demos/src/ftlint.c
@@ -81,6 +81,20 @@
     for ( file_index = 2; file_index < argc; file_index++ )
     {
       fname = argv[file_index];
+      
+      /* try to open the file with no extra extension first */
+      error = FT_New_Face( library, fname, 0, &face );
+      if (!error) goto Success;
+
+      if ( error == FT_Err_Unknown_File_Format )
+      {
+        printf( "unknown format\n" );
+        continue;
+      }
+
+      /* ok, we could not load the file, try to add an extension to */
+      /* its name if possible..                                     */
+      
       i     = strlen( fname );
       while ( i > 0 && fname[i] != '\\' && fname[i] != '/' )
       {
@@ -124,7 +138,7 @@
       error = FT_New_Face( library, filename, 0, &face );
       if (error)
       {
-        if (error == FT_Err_Invalid_File_Format)
+        if (error == FT_Err_Unknown_File_Format)
           printf( "unknown format\n" );
         else
           printf( "could not find/open file (error: %d)\n", error );
@@ -132,6 +146,7 @@
       }
       if (error) Panic( "Could not open file" );
 
+  Success:
       num_glyphs = face->num_glyphs;
 
       error = FT_Set_Char_Size( face, ptsize << 6, ptsize << 6, 72, 72 );
--- a/demos/src/ftstring.c
+++ b/demos/src/ftstring.c
@@ -59,9 +59,9 @@
 
   static grColor  fore_color = { 255 };
 
-  static int  graph_init = 0;
+  static int  graph_init  = 0;
   static int  render_mode = 1;
-  static int  use_grays   = 0;
+  static int  use_grays   = 1;
 
   /* the standard raster's interface */
   static FT_Raster_Funcs  std_raster;
--- a/demos/src/ftview.c
+++ b/demos/src/ftview.c
@@ -74,7 +74,7 @@
   int  graph_init = 0;
 
   int  render_mode = 1;
-  int  use_grays   = 0;
+  int  use_grays   = 1;
 
   /* the standard raster's interface */
   FT_Raster_Funcs  std_raster;
@@ -618,6 +618,16 @@
     hinted      = 1;
     file_loaded = 0;
 
+    filename[128] = '\0';
+    alt_filename[128] = '\0';
+
+    strncpy( filename, argv[file], 128 );
+    strncpy( alt_filename, argv[file], 128 );
+
+    /* try to load the file name as is, first */
+    error = FT_New_Face( library, argv[file], 0, &face );
+    if (!error) goto Success;
+
 #ifndef macintosh
     i = strlen( argv[file] );
     while ( i > 0 && argv[file][i] != '\\' && argv[file][i] != '/' )
@@ -628,12 +638,6 @@
     }
 #endif
 
-    filename[128] = '\0';
-    alt_filename[128] = '\0';
-
-    strncpy( filename, argv[file], 128 );
-    strncpy( alt_filename, argv[file], 128 );
-
 #ifndef macintosh
     if ( i >= 0 )
     {
@@ -647,6 +651,7 @@
     error = FT_New_Face( library, filename, 0, &face );
     if (error) goto Display_Font;
 
+ Success:
     file_loaded++;
 
     error = Reset_Scale( ptsize );
--- a/include/freetype/config/ftmodule.h
+++ b/include/freetype/config/ftmodule.h
@@ -1,4 +1,5 @@
 FT_DRIVER(cff_driver_interface)
+FT_DRIVER(t1cid_driver_interface)
 FT_DRIVER(psnames_driver_interface)
 FT_DRIVER(sfnt_driver_interface)
 FT_DRIVER(tt_driver_interface)
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -394,6 +394,12 @@
 /*                                                                 */
 #undef  T1_CONFIG_OPTION_NO_AFM
 
-
+/*******************************************************************/
+/* Define this configuration macro if you want to prevent the      */
+/* compilation of the multiple-masters support in the Type 1 driver*/
+/* AFM files into an existing face. Note that when set, the T1     */
+/* driver will be unable to produce kerning distances..            */
+/*                                                                 */
+#undef  T1_CONFIG_OPTION_NO_MM_SUPPORT
 
 #endif /* FTOPTION_H */
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -612,6 +612,7 @@
     FT_CharMap       charmap;
     FT_ListRec       sizes_list;
 
+    void*            autohint_globals;
     void*            extensions;
 
     FT_UShort        max_points;
@@ -934,11 +935,15 @@
   /*                FT_Load_Glyph() API function) and can be expressed     */
   /*                either in 26.6 fractional pixels or font units.        */
   /*                                                                       */
-  /*    metrics2 :: This field can be used to return alternate glyph       */
-  /*                metrics after a single load.  It can contain either    */
-  /*                the glyph's metrics in font units, or the scaled but   */
-  /*                unhinted ones.  See the load flags that apply when     */
-  /*                calling the API function FT_Load_Glyph().              */
+  /*    metrics2 :: This field is used to return alternate glyph metrics   */
+  /*                for scalable formats. Only four fields in it are       */
+  /*                valid: horiBearingX, horiAdvance, vertBearingY and     */
+  /*                vertAdvance. All other fields should be ignored.       */
+  /*                By default, it contains the glyph metrics expressed    */
+  /*                in font units. However, when FT_Load_Glyph() is called */
+  /*                with FT_LOAD_LINEAR set, the metrics are expressed     */
+  /*                in 16.16 unhinted pixel values.. This can be useful    */
+  /*                to perform WYSIWYG glyph layout..                      */
   /*                                                                       */
   /*    generic  :: A typeless pointer which is unused by the FreeType     */
   /*                library or any of its drivers.  It can be used by      */
@@ -954,7 +959,6 @@
   /*                if it is a fixed-width one.  The nature of the last    */
   /*                loaded glyph can be retrieved through the result value */
   /*                returned by FT_Load_Glyph().                           */
-  /*                                                                       */
   /*                                                                       */
 
   enum
--- a/include/freetype/internal/t1types.h
+++ b/include/freetype/internal/t1types.h
@@ -344,7 +344,14 @@
   } T1_Font;
 
 
+  typedef struct CID_Subrs_
+  {
+    FT_UInt    num_subrs;
+    FT_Byte**  code;
+    
+  } CID_Subrs;
 
+
 /*************************************************************************/
 /*************************************************************************/
 /*************************************************************************/
@@ -372,8 +379,8 @@
 
 
   typedef struct T1_FaceRec_*   T1_Face;
+  typedef struct CID_FaceRec_*  CID_Face;
 
-
   /***************************************************/
   /*                                                 */
   /*  T1_Face :                                      */
@@ -396,5 +403,14 @@
 
   } T1_FaceRec;
 
+
+  typedef struct CID_FaceRec_
+  {
+    FT_FaceRec    root;
+    void*         psnames;
+    CID_Info      cid;
+    CID_Subrs*    subrs;
+  
+  } CID_FaceRec;
 
 #endif /* T1TYPES_H */
--- a/include/freetype/t1tables.h
+++ b/include/freetype/t1tables.h
@@ -69,7 +69,7 @@
     FT_Int       unique_id;
     FT_Int       lenIV;
 
-    FT_Byte      num_blues;
+    FT_Byte      num_blue_values;
     FT_Byte      num_other_blues;
     FT_Byte      num_family_blues;
     FT_Byte      num_family_other_blues;
@@ -92,8 +92,8 @@
     FT_Bool      force_bold;
     FT_Bool      round_stem_up;
 
-    FT_Short     stem_snap_widths [13];  /* reserve one place for the std */
-    FT_Short     stem_snap_heights[13];  /* reserve one place for the std */
+    FT_Short     snap_widths [13];  /* reserve one place for the std */
+    FT_Short     snap_heights[13];  /* reserve one place for the std */
 
     FT_Long      language_group;
     FT_Long      password;
@@ -181,9 +181,17 @@
 
   typedef struct CID_FontDict_
   {
-    T1_FontInfo   font_info;
     T1_Private    private_dict;
 
+    FT_UInt       len_buildchar;
+    FT_Fixed      forcebold_threshold;
+    FT_Pos        stroke_width;
+    FT_Fixed      expansion_factor;
+    
+    FT_Byte       paint_type;
+    FT_Byte       font_type;
+    FT_Matrix     font_matrix;
+
     FT_UInt       num_subrs;
     FT_ULong      subrmap_offset;
     FT_Int        sd_bytes;
@@ -201,6 +209,8 @@
     FT_String*  ordering;
     FT_Int      supplement;
 
+    T1_FontInfo font_info;
+    FT_BBox     font_bbox;
     FT_ULong    uid_base;
 
     FT_Int      num_xuid;
@@ -212,8 +222,10 @@
     FT_Int      gd_bytes;
     FT_ULong    cid_count;
 
-    FT_Int         num_font_dicts;
+    FT_Int         num_dicts;
     CID_FontDict*  font_dicts;
+
+    FT_ULong    data_offset;
 
   } CID_Info;
 
--- a/src/base/ftgrays.c
+++ b/src/base/ftgrays.c
@@ -300,7 +300,7 @@
     /* in during the render phase.  This means that:                       */
     /*                                                                     */
     /* . the new vertical position must be within min_ey..max_ey - 1.      */
-    /* . the new horizontal position must be strictly less than max_ey     */
+    /* . the new horizontal position must be strictly less than max_ex     */
     /*                                                                     */
     /* Note that if a cell is to the left of the clipping region, it is    */
     /* actually set to the (min_ex-1) horizontal position.                 */
@@ -1198,7 +1198,7 @@
         coverage = -coverage;
 
       while ( coverage >= 512 )
-        coverage -= 512;
+        coverage = 512-coverage;
 
       if ( coverage > 256 )
         coverage = 0;
@@ -1216,6 +1216,7 @@
     }
 
     y += ras.min_ey;
+    x += ras.min_ex;
 
     if ( coverage )
     {
@@ -1330,9 +1331,9 @@
       else
       {
         /* draw a gray span until the end of the clipping region */
-        if ( cover && x < ras.max_ex )
+        if ( cover && x < ras.max_ex - ras.min_ex )
           grays_hline( RAS_VAR_ x, y,
-                       cover * ( ONE_PIXEL * 2 ), ras.max_ex - x );
+                       cover * ( ONE_PIXEL * 2 ), ras.max_ex - x - ras.min_ex );
         cover = 0;
       }
 
--- /dev/null
+++ b/src/cid/cidafm.c
@@ -1,0 +1,228 @@
+/***************************************************************************
+ *
+ * t1afm.c  - support for reading Type 1 AFM files
+ *
+ *
+ ***************************************************************************/
+
+#include <cidafm.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1types.h>
+#include <stdlib.h>  /* for qsort */
+
+  LOCAL_FUNC
+  void  CID_Done_AFM( FT_Memory memory, T1_AFM*  afm )
+  {
+    FREE( afm->kern_pairs );
+    afm->num_pairs = 0;
+  }
+
+#undef  IS_KERN_PAIR
+#define IS_KERN_PAIR(p)  ( p[0] == 'K'  &&  p[1] == 'P' )
+
+#define IS_ALPHANUM(c)  ( (c >= 'A' && c <= 'Z') || \
+                          (c >= 'a' && c <= 'z') || \
+                          (c >= '0' && c <= '9') || \
+                          (c == '_' && c == '.') )
+
+ /* read a glyph name and return the equivalent glyph index */
+  static
+  FT_UInt  afm_atoindex( FT_Byte*  *start, FT_Byte*  limit, T1_Font*  type1 )
+  {
+    FT_Byte* p = *start;
+    FT_Int   len;
+    FT_UInt  result = 0;
+    char     temp[64];
+
+    /* skip whitespace */
+    while ( (*p == ' ' || *p == '\t' || *p == ':' || *p == ';') && p < limit )
+      p++;
+    *start = p;
+
+    /* now, read glyph name */
+    while ( IS_ALPHANUM(*p) && p < limit ) p++;
+    len = p - *start;
+    if (len > 0 && len < 64)
+    {
+      FT_Int  n;
+
+      /* copy glyph name to intermediate array */
+      MEM_Copy( temp, *start, len );
+      temp[len] = 0;
+
+      /* lookup glyph name in face array */
+      for ( n = 0; n < type1->num_glyphs; n++ )
+      {
+        char*  gname = (char*)type1->glyph_names[n];
+
+        if ( gname && gname[0] == temp[0] && strcmp(gname,temp) == 0 )
+        {
+          result = n;
+          break;
+        }
+      }
+    }
+    *start = p;
+    return result;
+  }
+
+
+ /* read an integer */
+  static
+  int  afm_atoi( FT_Byte** start, FT_Byte*  limit )
+  {
+    FT_Byte*  p    = *start;
+    int       sum  = 0;
+    int       sign = 1;
+
+    /* skip everything that is not a number */
+    while ( p < limit && (*p < '0' || *p > '9') )
+    {
+      sign = 1;
+      if (*p == '-')
+        sign = -1;
+
+      p++;
+    }
+
+    while ( p < limit && (*p >= '0' && *p < '9') )
+    {
+      sum = sum*10 + (*p - '0');
+      p++;
+    }
+    *start = p;
+    return sum*sign;
+  }
+
+
+#undef  KERN_INDEX
+#define KERN_INDEX(g1,g2)   (((FT_ULong)g1 << 16) | g2)
+
+ /* compare two kerning pairs */
+  static
+  int  compare_kern_pairs( const void* a, const void* b )
+  {
+    T1_Kern_Pair*  pair1 = (T1_Kern_Pair*)a;
+    T1_Kern_Pair*  pair2 = (T1_Kern_Pair*)b;
+
+    FT_ULong  index1 = KERN_INDEX(pair1->glyph1,pair1->glyph2);
+    FT_ULong  index2 = KERN_INDEX(pair2->glyph1,pair2->glyph2);
+
+    return ( index1 - index2 );
+  }
+
+
+ /* parse an AFM file - for now, only read the kerning pairs */
+  LOCAL_FUNC
+  FT_Error  CID_Read_AFM( FT_Face   t1_face,
+                         FT_Stream stream )
+  {
+    FT_Error       error;
+    FT_Memory      memory = stream->memory;
+    FT_Byte*       start;
+    FT_Byte*       limit;
+    FT_Byte*       p;
+    FT_Int         count = 0;
+    T1_Kern_Pair*  pair;
+    T1_Font*       type1 = &((T1_Face)t1_face)->type1;
+    T1_AFM*        afm   = 0;
+
+    if ( ACCESS_Frame(stream->size) )
+      return error;
+
+    start = (FT_Byte*)stream->cursor;
+    limit = (FT_Byte*)stream->limit;
+    p     = start;
+
+    /* we are now going to count the occurences of "KP" or "KPX" in */
+    /* the AFM file..                                               */
+    count = 0;
+    for ( p = start; p < limit-3; p++ )
+    {
+      if ( IS_KERN_PAIR(p) )
+        count++;
+    }
+
+   /* Actually, kerning pairs are simply optional !! */
+    if (count == 0)
+      goto Exit;
+
+    /* allocate the pairs */
+    if ( ALLOC(       afm, sizeof(*afm ) )                   ||
+         ALLOC_ARRAY( afm->kern_pairs, count, T1_Kern_Pair ) )
+      goto Exit;
+
+    /* now, read each kern pair */
+    pair           = afm->kern_pairs;
+    afm->num_pairs = count;
+
+    /* save in face object */
+    ((T1_Face)t1_face)->afm_data = afm;
+
+    for ( p = start; p < limit-3; p++ )
+    {
+      if ( IS_KERN_PAIR(p) )
+      {
+        FT_Byte*  q;
+
+        /* skip keyword (KP or KPX) */
+        q = p+2;
+        if (*q == 'X') q++;
+
+        pair->glyph1    = afm_atoindex( &q, limit, type1 );
+        pair->glyph2    = afm_atoindex( &q, limit, type1 );
+        pair->kerning.x = afm_atoi( &q, limit );
+
+        pair->kerning.y = 0;
+        if ( p[2] != 'X' )
+          pair->kerning.y = afm_atoi( &q, limit );
+
+        pair++;
+      }
+    }
+
+    /* now, sort the kern pairs according to their glyph indices */
+    qsort( afm->kern_pairs, count, sizeof(T1_Kern_Pair), compare_kern_pairs );
+
+  Exit:
+    if (error)
+      FREE( afm );
+
+    FORGET_Frame();
+    return error;
+  }
+
+
+ /* find the kerning for a given glyph pair */
+  LOCAL_FUNC
+  void  CID_Get_Kerning( T1_AFM*     afm,
+                        FT_UInt     glyph1,
+                        FT_UInt     glyph2,
+                        FT_Vector*  kerning )
+  {
+    T1_Kern_Pair  *min, *mid, *max;
+    FT_ULong       index = KERN_INDEX(glyph1,glyph2);
+
+    /* simple binary search */
+    min = afm->kern_pairs;
+    max = min + afm->num_pairs-1;
+
+    while (min <= max)
+    {
+      FT_ULong  midi;
+
+      mid = min + (max-min)/2;
+      midi = KERN_INDEX(mid->glyph1,mid->glyph2);
+      if ( midi == index )
+      {
+        *kerning = mid->kerning;
+        return;
+      }
+
+      if ( midi < index ) min = mid+1;
+                     else max = mid-1;
+    }
+    kerning->x = 0;
+    kerning->y = 0;
+  }
+
--- /dev/null
+++ b/src/cid/cidafm.h
@@ -1,0 +1,49 @@
+/***************************************************************************
+ *
+ * t1afm.h  - support for reading Type 1 AFM files
+ *
+ *
+ ***************************************************************************/
+
+#ifndef T1AFM_H
+#define T1AFM_H
+
+#include <freetype/internal/ftobjs.h>
+
+/* In this version, we only read the kerning table from the */
+/* AFM file. We may add support for ligatures a bit later.. */
+
+typedef struct T1_Kern_Pair_
+{
+  FT_UInt   glyph1;
+  FT_UInt   glyph2;
+  FT_Vector kerning;
+
+} T1_Kern_Pair;
+
+
+typedef struct T1_AFM_
+{
+  FT_Int        num_pairs;
+  T1_Kern_Pair* kern_pairs;
+
+} T1_AFM;
+
+#if 0
+
+LOCAL_DEF
+FT_Error  CID_Read_AFM( FT_Face   face,
+                        FT_Stream stream );
+
+LOCAL_DEF
+void      CID_Done_AFM( FT_Memory  memory,
+                        T1_AFM*    afm );
+
+LOCAL_DEF
+void  CID_Get_Kerning( T1_AFM*     afm,
+                       FT_UInt     glyph1,
+                       FT_UInt     glyph2,
+                       FT_Vector*  kerning );
+#endif
+
+#endif /* T1AFM_H */
--- /dev/null
+++ b/src/cid/cidgload.c
@@ -1,0 +1,1484 @@
+/*******************************************************************
+ *
+ *  cidgload.c                                                   1.0
+ *
+ *    CID-Keyed Type1 Glyph Loader.
+ *
+ *  Copyright 1996-1999 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.
+ *
+ ******************************************************************/
+
+#include <cidgload.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1gload
+
+ /* forward */
+  static
+  FT_Error  cid_load_glyph( CID_Decoder*  decoder, FT_UInt  glyph_index );
+
+
+  typedef enum T1_Operator_
+  {
+    op_none = 0,
+    op_endchar,
+    op_hsbw,
+    op_seac,
+    op_sbw,
+    op_closepath,
+    op_hlineto,
+    op_hmoveto,
+    op_hvcurveto,
+    op_rlineto,
+    op_rmoveto,
+    op_rrcurveto,
+    op_vhcurveto,
+    op_vlineto,
+    op_vmoveto,
+    op_dotsection,
+    op_hstem,
+    op_hstem3,
+    op_vstem,
+    op_vstem3,
+    op_div,
+    op_callothersubr,
+    op_callsubr,
+    op_pop,
+    op_return,
+    op_setcurrentpoint,
+
+    op_max    /* never remove this one */
+
+  } T1_Operator;
+
+  static const FT_Int  t1_args_count[ op_max ] =
+  {
+    0, /* none */
+    0, /* endchar */
+    2, /* hsbw */
+    5, /* seac */
+    4, /* sbw */
+    0, /* closepath */
+    1, /* hlineto */
+    1, /* hmoveto */
+    4, /* hvcurveto */
+    2, /* rlineto */
+    2, /* rmoveto */
+    6, /* rrcurveto */
+    4, /* vhcurveto */
+    1, /* vlineto */
+    1, /* vmoveto */
+    0, /* dotsection */
+    2, /* hstem */
+    6, /* hstem3 */
+    2, /* vstem */
+    6, /* vstem3 */
+    2, /* div */
+   -1, /* callothersubr */
+    1, /* callsubr */
+    0, /* pop */
+    0, /* return */
+    2  /* setcurrentpoint */
+  };
+
+
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********                                                   *********/
+  /**********                                                   *********/
+  /**********           GENERIC CHARSTRINGS PARSING             *********/
+  /**********                                                   *********/
+  /**********                                                   *********/
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********************************************************************/
+
+/*********************************************************************
+ *
+ * <Function>
+ *    CID_Init_Builder
+ *
+ * <Description>
+ *    Initialise a given glyph builder.
+ *
+ * <Input>
+ *    builder :: glyph builder to initialise
+ *    face    :: current face object
+ *    size    :: current size object
+ *    glyph   :: current glyph object
+ *
+ *********************************************************************/
+
+  LOCAL_FUNC
+  void  CID_Init_Builder( CID_Builder*   builder,
+                          CID_Face       face,
+                          T1_Size        size,
+                          T1_GlyphSlot   glyph )
+  {
+    builder->path_begun  = 0;
+    builder->load_points = 1;
+
+    builder->face   = face;
+    builder->glyph  = glyph;
+    builder->memory = face->root.memory;
+
+    if (glyph)
+    {
+      builder->base         = glyph->root.outline;
+      builder->max_points   = glyph->max_points;
+      builder->max_contours = glyph->max_contours;
+    }
+
+    if (size)
+    {
+      builder->scale_x = size->root.metrics.x_scale;
+      builder->scale_y = size->root.metrics.y_scale;
+    }
+
+    builder->pos_x = 0;
+    builder->pos_y = 0;
+
+    builder->left_bearing.x = 0;
+    builder->left_bearing.y = 0;
+    builder->advance.x      = 0;
+    builder->advance.y      = 0;
+
+    builder->base.n_points   = 0;
+    builder->base.n_contours = 0;
+    builder->current         = builder->base;
+  }
+
+
+/*********************************************************************
+ *
+ * <Function>
+ *    CID_Done_Builder
+ *
+ * <Description>
+ *    Finalise a given glyph builder. Its content can still be
+ *    used after the call, but the function saves important information
+ *    within the corresponding glyph slot.
+ *
+ * <Input>
+ *    builder :: glyph builder to initialise
+ *
+ *********************************************************************/
+
+  LOCAL_FUNC
+  void CID_Done_Builder( CID_Builder*  builder )
+  {
+    T1_GlyphSlot  glyph = builder->glyph;
+
+    if (glyph)
+    {
+      glyph->root.outline = builder->base;
+      glyph->max_points   = builder->max_points;
+      glyph->max_contours = builder->max_contours;
+    }
+  }
+
+
+
+/*********************************************************************
+ *
+ * <Function>
+ *    CID_Init_Decoder
+ *
+ * <Description>
+ *    Initialise a given Type 1 decoder for parsing
+ *
+ * <Input>
+ *    decoder :: Type 1 decoder to initialise
+ *    funcs   :: hinter functions interface
+ *
+ *********************************************************************/
+
+  LOCAL_FUNC
+  void  CID_Init_Decoder( CID_Decoder* decoder )
+  {
+    MEM_Set( decoder, 0, sizeof(*decoder) );
+    decoder->font_matrix.xx = 0x10000;
+    decoder->font_matrix.yy = 0x10000;
+  }
+
+
+
+  /* check that there is enough room for "count" more points */
+  static
+  FT_Error  check_points( CID_Builder*  builder,
+                          FT_Int       count )
+  {
+    FT_Outline*  base    = &builder->base;
+    FT_Outline*  outline = &builder->current;
+
+    if (!builder->load_points)
+      return T1_Err_Ok;
+
+    count += base->n_points + outline->n_points;
+
+    /* realloc points table if necessary */
+    if ( count >= builder->max_points )
+    {
+      FT_Error   error;
+      FT_Memory  memory    = builder->memory;
+      FT_Int     increment = outline->points - base->points;
+      FT_Int     current   = builder->max_points;
+
+      while ( builder->max_points < count )
+        builder->max_points += 8;
+
+      if ( REALLOC_ARRAY( base->points, current,
+                          builder->max_points, T1_Vector )  ||
+
+           REALLOC_ARRAY( base->tags, current,
+                          builder->max_points, FT_Byte )    )
+      {
+        builder->error = error;
+        return error;
+      }
+
+      outline->points = base->points + increment;
+      outline->tags  = base->tags  + increment;
+    }
+    return T1_Err_Ok;
+  }
+
+
+  /* add a new point, do not check room */
+  static
+  void  add_point( CID_Builder*  builder,
+                   FT_Pos       x,
+                   FT_Pos       y,
+                   FT_Byte      flag )
+  {
+    FT_Outline*  outline = &builder->current;
+
+    if (builder->load_points)
+    {
+      FT_Vector*  point   = outline->points + outline->n_points;
+      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
+
+      point->x = x;
+      point->y = y;
+      *control = ( flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic );
+
+      builder->last = *point;
+    }
+
+    outline->n_points++;
+  }
+
+
+  /* check room for a new on-curve point, then add it */
+  static
+  FT_Error  add_point1( CID_Builder*  builder,
+                        FT_Pos       x,
+                        FT_Pos       y )
+  {
+    FT_Error  error;
+
+    error = check_points(builder,1);
+    if (!error)
+      add_point( builder, x, y, 1 );
+
+    return error;
+  }
+
+
+  /* check room for a new contour, then add it */
+  static
+  FT_Error  add_contour( CID_Builder*  builder )
+  {
+    FT_Outline*  base    = &builder->base;
+    FT_Outline*  outline = &builder->current;
+
+    if (!builder->load_points)
+    {
+      outline->n_contours++;
+      return T1_Err_Ok;
+    }
+
+    /* realloc contours array if necessary */
+    if ( base->n_contours + outline->n_contours >= builder->max_contours &&
+         builder->load_points )
+    {
+      FT_Error  error;
+      FT_Memory memory = builder->memory;
+      FT_Int    increment = outline->contours - base->contours;
+      FT_Int    current   = builder->max_contours;
+
+      builder->max_contours += 4;
+
+      if ( REALLOC_ARRAY( base->contours,
+                          current, builder->max_contours, FT_Short ) )
+      {
+        builder->error = error;
+        return error;
+      }
+
+      outline->contours = base->contours + increment;
+    }
+
+    if (outline->n_contours > 0)
+      outline->contours[ outline->n_contours-1 ] = outline->n_points-1;
+
+    outline->n_contours++;
+    return T1_Err_Ok;
+  }
+
+  /* if a path was begun, add its first on-curve point */
+  static
+  FT_Error  start_point( CID_Builder*  builder,
+                         T1_Pos       x,
+                         T1_Pos       y )
+  {
+    /* test wether we're building a new contour */
+    if (!builder->path_begun)
+    {
+      FT_Error  error;
+
+      builder->path_begun = 1;
+      error = add_contour( builder );
+      if (error) return error;
+    }
+    return add_point1( builder, x, y );
+  }
+
+
+  /* close the current contour */
+  static
+  void  close_contour( CID_Builder*  builder )
+  {
+    FT_Outline*  outline = &builder->current;
+
+    if ( outline->n_contours > 0 )
+      outline->contours[outline->n_contours-1] = outline->n_points-1;
+  }
+
+#if 0
+/*********************************************************************
+ *
+ * <Function>
+ *    lookup_glyph_by_stdcharcode
+ *
+ * <Description>
+ *    Lookup a given glyph by its StandardEncoding charcode. Used
+ *    to implement the SEAC Type 1 operator.
+ *
+ * <Input>
+ *    face     :: current face object
+ *    charcode :: charcode to look for
+ *
+ * <Return>
+ *    glyph index in font face. Returns -1 if the corresponding
+ *    glyph wasn't found.
+ *
+ *********************************************************************/
+
+  static
+  FT_Int    lookup_glyph_by_stdcharcode( CID_Face  face,
+                                         FT_Int    charcode )
+  {
+    FT_Int              n;
+    const FT_String*    glyph_name;
+    PSNames_Interface*  psnames = (PSNames_Interface*)face->psnames;
+
+    /* check range of standard char code */
+    if (charcode < 0 || charcode > 255)
+      return -1;
+
+    glyph_name = psnames->adobe_std_strings(
+                    psnames->adobe_std_encoding[charcode]);
+
+    for ( n = 0; n < face->cid.cid_count; n++ )
+    {
+      T1_String*  name = (T1_String*)face->type1.glyph_names[n];
+
+      if ( name && strcmp(name,glyph_name) == 0 )
+        return n;
+    }
+
+    return -1;
+  }
+#endif
+
+
+/*********************************************************************
+ *
+ * <Function>
+ *    t1operator_seac
+ *
+ * <Description>
+ *    Implements the "seac" Type 1 operator for a Type 1 decoder
+ *
+ * <Input>
+ *    decoder  :: current Type 1 decoder
+ *    asb      :: accent's side bearing
+ *    adx      :: horizontal position of accent
+ *    ady      :: vertical position of accent
+ *    bchar    :: base character's StandardEncoding charcode
+ *    achar    :: accent character's StandardEncoding charcode
+ *
+ * <Return>
+ *    Error code. 0 means success.
+ *
+ *********************************************************************/
+
+  static
+  FT_Error  t1operator_seac( CID_Decoder*  decoder,
+                             FT_Pos       asb,
+                             FT_Pos       adx,
+                             FT_Pos       ady,
+                             FT_Int       bchar,
+                             FT_Int       achar )
+  {
+    FT_Error     error;
+    FT_Int       bchar_index, achar_index, n_base_points;
+    FT_Outline*  cur  = &decoder->builder.current;
+    FT_Outline*  base = &decoder->builder.base;
+    FT_Vector    left_bearing, advance;
+
+    bchar_index = bchar;
+    achar_index = achar;
+
+    if (bchar_index < 0 || achar_index < 0)
+    {
+      FT_ERROR(( "T1.Parse_Seac : invalid seac character code arguments\n" ));
+      return T1_Err_Syntax_Error;
+    }
+
+    /* First load "bchar" in builder */
+    /* now load the unscaled outline */
+    cur->n_points   = 0;
+    cur->n_contours = 0;
+    cur->points     = base->points   + base->n_points;
+    cur->tags       = base->tags    + base->n_points;
+    cur->contours   = base->contours + base->n_contours;
+
+    error = cid_load_glyph( decoder, bchar_index );
+    if (error) return error;
+
+    n_base_points   = cur->n_points;
+
+    if ( decoder->builder.no_recurse )
+    {
+      /* if we're trying to load a composite glyph, do not load the */
+      /* accent character and return the array of subglyphs..       */
+      FT_GlyphSlot  glyph = (FT_GlyphSlot)decoder->builder.glyph;
+      FT_SubGlyph*  subg;
+
+      /* reallocate subglyph array if necessary */
+      if (glyph->max_subglyphs < 2)
+      {
+        FT_Memory  memory = decoder->builder.face->root.memory;
+
+        if ( REALLOC_ARRAY( glyph->subglyphs, glyph->max_subglyphs,
+                            2, FT_SubGlyph ) )
+          return error;
+
+        glyph->max_subglyphs = 2;
+      }
+
+      subg = glyph->subglyphs;
+
+      /* subglyph 0 = base character */
+      subg->index = bchar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
+                    FT_SUBGLYPH_FLAG_USE_MY_METRICS;
+      subg->arg1  = 0;
+      subg->arg2  = 0;
+      subg++;
+
+      /* subglyph 1 = accent character */
+      subg->index = achar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
+      subg->arg1  = adx - asb;
+      subg->arg2  = ady;
+
+      /* set up remaining glyph fields */
+      glyph->num_subglyphs = 2;
+      glyph->format        = ft_glyph_format_composite;
+    }
+    else
+    {
+      /* save the left bearing and width of the base character */
+      /* as they will be erase by the next load..              */
+      left_bearing = decoder->builder.left_bearing;
+      advance      = decoder->builder.advance;
+
+      decoder->builder.left_bearing.x = 0;
+      decoder->builder.left_bearing.y = 0;
+
+      /* Now load "achar" on top of */
+      /* the base outline           */
+      /*                            */
+      cur->n_points   = 0;
+      cur->n_contours = 0;
+      cur->points     = base->points   + base->n_points;
+      cur->tags      = base->tags    + base->n_points;
+      cur->contours   = base->contours + base->n_contours;
+
+      error = cid_load_glyph( decoder, achar_index );
+      if (error) return error;
+
+      /* adjust contours in accented character outline */
+      if (decoder->builder.load_points)
+      {
+        FT_Int  n;
+
+        for ( n = 0; n < cur->n_contours; n++ )
+          cur->contours[n] += n_base_points;
+      }
+
+      /* restore the left side bearing and   */
+      /* advance width of the base character */
+      decoder->builder.left_bearing = left_bearing;
+      decoder->builder.advance      = advance;
+
+      /* Finally, move the accent */
+      if (decoder->builder.load_points)
+        FT_Outline_Translate( cur, adx - asb, ady );
+    }
+    return T1_Err_Ok;
+  }
+
+/*********************************************************************
+ *
+ * <Function>
+ *    CID_Parse_CharStrings
+ *
+ * <Description>
+ *    Parses a given Type 1 charstrings program
+ *
+ * <Input>
+ *    decoder          :: current Type 1 decoder
+ *    charstring_base  :: base of the charstring stream
+ *    charstring_len   :: length in bytes of the charstring stream
+ *    num_subrs        :: number of sub-routines
+ *    subrs_base       :: array of sub-routines addresses
+ *    subrs_len        :: array of sub-routines lengths
+ *
+ * <Return>
+ *    Error code. 0 means success.
+ *
+ *********************************************************************/
+
+#define USE_ARGS(n)  top -= n; if (top < decoder->stack) goto Stack_Underflow
+
+  LOCAL_FUNC
+  FT_Error   CID_Parse_CharStrings( CID_Decoder*  decoder,
+                                    FT_Byte*     charstring_base,
+                                    FT_Int       charstring_len )
+  {
+    FT_Error            error;
+    CID_Decoder_Zone*    zone;
+    FT_Byte*            ip;
+    FT_Byte*            limit;
+    CID_Builder*         builder = &decoder->builder;
+    FT_Outline*         outline;
+    T1_Pos              x, y;
+
+    /* First of all, initialise the decoder */
+    decoder->top  = decoder->stack;
+    decoder->zone = decoder->zones;
+    zone          = decoder->zones;
+
+    builder->path_begun  = 0;
+
+    zone->base           = charstring_base;
+    limit = zone->limit  = charstring_base + charstring_len;
+    ip    = zone->cursor = zone->base;
+
+    error   = T1_Err_Ok;
+    outline = &builder->current;
+
+    x = builder->pos_x;
+    y = builder->pos_y;
+
+    /* now, execute loop */
+    while ( ip < limit )
+    {
+      FT_Int*      top      = decoder->top;
+      T1_Operator  op       = op_none;
+      FT_Long      value    = 0;
+
+      /********************************************************************/
+      /*                                                                  */
+      /* Decode operator or operand                                       */
+      /*                                                                  */
+      /*                                                                  */
+
+      /* First of all, decompress operator or value */
+      switch (*ip++)
+      {
+        case 1:  op = op_hstem;     break;
+
+        case 3:  op = op_vstem;     break;
+        case 4:  op = op_vmoveto;   break;
+        case 5:  op = op_rlineto;   break;
+        case 6:  op = op_hlineto;   break;
+        case 7:  op = op_vlineto;   break;
+        case 8:  op = op_rrcurveto; break;
+        case 9:  op = op_closepath; break;
+        case 10: op = op_callsubr;  break;
+        case 11: op = op_return;    break;
+
+        case 13: op = op_hsbw;      break;
+        case 14: op = op_endchar;   break;
+
+        case 21: op = op_rmoveto;   break;
+        case 22: op = op_hmoveto;   break;
+
+        case 30: op = op_vhcurveto; break;
+        case 31: op = op_hvcurveto; break;
+
+        case 12:
+          {
+            if (ip > limit)
+            {
+              FT_ERROR(( "T1.Parse_CharStrings : invalid escape (12+EOF)\n" ));
+              goto Syntax_Error;
+            }
+
+            switch (*ip++)
+            {
+              case 0:  op = op_dotsection;      break;
+              case 1:  op = op_vstem3;          break;
+              case 2:  op = op_hstem3;          break;
+              case 6:  op = op_seac;            break;
+              case 7:  op = op_sbw;             break;
+              case 12: op = op_div;             break;
+              case 16: op = op_callothersubr;   break;
+              case 17: op = op_pop;             break;
+              case 33: op = op_setcurrentpoint; break;
+
+              default:
+                FT_ERROR(( "T1.Parse_CharStrings : invalid escape (12+%d)\n",
+                         ip[-1] ));
+                goto Syntax_Error;
+            }
+          }
+          break;
+
+        case 255:    /* four bytes integer */
+          {
+            if (ip+4 > limit)
+            {
+              FT_ERROR(( "T1.Parse_CharStrings : unexpected EOF in integer\n" ));
+              goto Syntax_Error;
+            }
+
+            value = ((long)ip[0] << 24) |
+                    ((long)ip[1] << 16) |
+                    ((long)ip[2] << 8)  |
+                           ip[3];
+            ip += 4;
+          }
+          break;
+
+        default:
+          if (ip[-1] >= 32)
+          {
+            if (ip[-1] < 247)
+              value = (long)ip[-1] - 139;
+            else
+            {
+              if (++ip > limit)
+              {
+                FT_ERROR(( "T1.Parse_CharStrings : unexpected EOF in integer\n" ));
+                goto Syntax_Error;
+              }
+
+              if (ip[-2] < 251)
+                value =  ((long)(ip[-2]-247) << 8) + ip[-1] + 108;
+              else
+                value = -((((long)ip[-2]-251) << 8) + ip[-1] + 108 );
+            }
+          }
+          else
+          {
+            FT_ERROR(( "T1.Parse_CharStrings : invalid byte (%d)\n",
+                     ip[-1] ));
+            goto Syntax_Error;
+          }
+      }
+
+      /********************************************************************/
+      /*                                                                  */
+      /*  Push value on stack, or process operator                        */
+      /*                                                                  */
+      /*                                                                  */
+      if ( op == op_none )
+      {
+        if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
+        {
+          FT_ERROR(( "T1.Parse_CharStrings : Stack overflow !!\n" ));
+          goto Syntax_Error;
+        }
+
+        FT_TRACE4(( " %ld", value ));
+        *top++       = value;
+        decoder->top = top;
+      }
+      else if ( op == op_callothersubr )  /* callothersubr */
+      {
+        FT_TRACE4(( " callothersubr" ));
+        if ( top - decoder->stack < 2 )
+          goto Stack_Underflow;
+
+        top -= 2;
+        switch ( top[1] )
+        {
+          case 1: /* start flex feature ---------------------- */
+            {
+              if ( top[0] != 0 ) goto Unexpected_OtherSubr;
+
+              decoder->flex_state        = 1;
+              decoder->num_flex_vectors  = 0;
+              if ( start_point(builder, x, y) ||
+                   check_points(builder,6) ) goto Memory_Error;
+            }
+            break;
+
+          case 2: /* add flex vectors ------------------------ */
+            {
+              FT_Int      index;
+
+              if ( top[0] != 0 ) goto Unexpected_OtherSubr;
+
+              /* note that we should not add a point for index 0 */
+              /* this will move our current position to the flex */
+              /* point without adding any point to the outline   */
+              index = decoder->num_flex_vectors++;
+              if (index > 0 && index < 7)
+                add_point( builder,
+                           x,
+                           y,
+                           (FT_Byte)( index==3 || index==6 ) );
+            }
+            break;
+
+          case 0: /* end flex feature ------------------------- */
+            {
+              if ( top[0] != 3 ) goto Unexpected_OtherSubr;
+
+              if ( decoder->flex_state       == 0 ||
+                   decoder->num_flex_vectors != 7 )
+              {
+                FT_ERROR(( "T1.Parse_CharStrings: unexpected flex end\n" ));
+                goto Syntax_Error;
+              }
+
+              /* now consume the remaining "pop pop setcurpoint" */
+              if ( ip+6 > limit ||
+                   ip[0] != 12  || ip[1] != 17 || /* pop */
+                   ip[2] != 12  || ip[3] != 17 || /* pop */
+                   ip[4] != 12  || ip[5] != 33 )  /* setcurpoint */
+              {
+                FT_ERROR(( "T1.Parse_CharStrings: invalid flex charstring\n" ));
+                goto Syntax_Error;
+              }
+
+              ip += 6;
+              decoder->flex_state = 0;
+              break;
+            }
+
+          case 3:  /* change hints ---------------------------- */
+            {
+              if ( top[0] != 1 ) goto Unexpected_OtherSubr;
+
+              /* eat the following "pop" */
+              if (ip+2 > limit)
+              {
+                FT_ERROR(( "T1.Parse_CharStrings: invalid escape (12+%d)\n",
+                         ip[-1] ));
+                goto Syntax_Error;
+              }
+
+              if (ip[0] != 12 || ip[1] != 17)
+              {
+                FT_ERROR(( "T1.Parse_CharStrings: 'pop' expected, found (%d %d)\n",
+                         ip[0], ip[1] ));
+                goto Syntax_Error;
+              }
+              ip += 2;
+              break;;
+            }
+
+          case 12:
+          case 13:
+            {
+              /* counter control hints, clear stack */
+              top = decoder->stack;
+              break;
+            }
+#if 0          
+          case 14:
+          case 15:
+          case 16:
+          case 17:
+          case 18: /* multiple masters */
+            {
+              T1_Blend*  blend = decoder->blend;
+              FT_UInt    num_points, nn, mm;
+              FT_Int*    delta;
+              FT_Int*    values;
+              
+              if (!blend)
+              {
+                FT_ERROR(( "T1.Parse_CharStrings: unexpected multiple masters operator !!\n" ));
+                goto Syntax_Error;
+              }
+              
+              num_points = top[1] - 13 + (top[1] == 18);
+              if (top[0] != num_points*blend->num_designs)
+              {
+                FT_ERROR(( "T1.Parse_CharStrings: incorrect number of mm arguments\n" ));
+                goto Syntax_Error;
+              }
+              
+              top       -= blend->num_designs*num_points;
+              if (top < decoder->stack)
+                goto Stack_Underflow;
+
+              /* we want to compute:                                   */
+              /*                                                       */
+              /*  a0*w0 + a1*w1 + ... + ak*wk                          */
+              /*                                                       */
+              /* but we only have the a0, a1-a0, a2-a0, .. ak-a0       */
+              /* however, given that w0 + w1 + ... + wk == 1, we can   */
+              /* rewrite it easily as:                                 */
+              /*                                                       */
+              /*  a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk       */
+              /*                                                       */
+              /* where k == num_designs-1                              */
+              /*                                                       */
+              /* I guess that's why it's written in this "compact"     */
+              /* form..                                                */
+              /*                                                       */
+              /*                                                       */
+              delta  = top + num_points;
+              values = top;
+              for ( nn = 0; nn < num_points; nn++ )
+              {
+                FT_Int  x = values[0];
+                for ( mm = 1; mm < blend->num_designs; mm++ )
+                  x += FT_MulFix( *delta++, blend->weight_vector[mm] );
+
+                *values++ = x;
+              }
+              /* note that "top" will be incremented later by calls to "pop" */
+              break;
+            }
+#endif          
+          default:
+          Unexpected_OtherSubr:
+            FT_ERROR(( "T1.Parse_CharStrings: invalid othersubr [%d %d]!!\n",
+                       top[0], top[1] ));
+            goto Syntax_Error;
+        }
+        decoder->top = top;
+      }
+      else  /* general operator */
+      {
+        FT_Int  num_args = t1_args_count[op];
+
+        if ( top - decoder->stack < num_args )
+          goto Stack_Underflow;
+
+        top -= num_args;
+
+        switch (op)
+        {
+          case op_endchar: /*************************************************/
+          {
+            FT_TRACE4(( " endchar" ));
+            close_contour( builder );
+
+            /* add current outline to the glyph slot */
+            builder->base.n_points   += builder->current.n_points;
+            builder->base.n_contours += builder->current.n_contours;
+
+            /* return now !! */
+            FT_TRACE4(( "\n\n" ));
+            return T1_Err_Ok;
+          }
+
+
+          case op_hsbw: /****************************************************/
+          {
+            FT_TRACE4(( " hsbw" ));
+            builder->left_bearing.x += top[0];
+            builder->advance.x       = top[1];
+            builder->advance.y       = 0;
+
+            builder->last.x = x = top[0];
+            builder->last.y = y = 0;
+
+            /* the "metrics_only" indicates that we only want to compute */
+            /* the glyph's metrics (lsb + advance width), not load the   */
+            /* rest of it.. so exit immediately                          */
+            if (builder->metrics_only)
+              return T1_Err_Ok;
+
+            break;
+          }
+
+
+          case op_seac: /****************************************************/
+            /* return immediately after the processing */
+            return t1operator_seac( decoder, top[0], top[1],
+                                             top[2], top[3], top[4] );
+
+          case op_sbw:  /****************************************************/
+          {
+            FT_TRACE4(( " sbw" ));
+            builder->left_bearing.x += top[0];
+            builder->left_bearing.y += top[1];
+            builder->advance.x       = top[2];
+            builder->advance.y       = top[3];
+
+            builder->last.x = x = top[0];
+            builder->last.y = y = top[1];
+
+            /* the "metrics_only" indicates that we only want to compute */
+            /* the glyph's metrics (lsb + advance width), not load the   */
+            /* rest of it.. so exit immediately                          */
+            if (builder->metrics_only)
+              return T1_Err_Ok;
+
+            break;
+          }
+
+
+          case op_closepath:  /**********************************************/
+          {
+            FT_TRACE4(( " closepath" ));
+            close_contour( builder );
+            builder->path_begun = 0;
+          }
+          break;
+
+
+          case op_hlineto:  /************************************************/
+          {
+            FT_TRACE4(( " hlineto" ));
+            if ( start_point( builder, x, y ) ) goto Memory_Error;
+
+            x += top[0];
+            goto Add_Line;
+          }
+
+
+          case op_hmoveto:  /************************************************/
+          {
+            FT_TRACE4(( " hmoveto" ));
+            x += top[0];
+            break;
+          }
+
+
+          case op_hvcurveto:  /**********************************************/
+          {
+            FT_TRACE4(( " hvcurveto" ));
+            if ( start_point( builder, x, y ) ||
+                 check_points( builder, 3 )   ) goto Memory_Error;
+
+            x += top[0];
+            add_point( builder, x, y, 0 );
+            x += top[1];
+            y += top[2];
+            add_point( builder, x, y, 0 );
+            y += top[3];
+            add_point( builder, x, y, 1 );
+            break;
+          }
+
+
+          case op_rlineto: /*************************************************/
+          {
+            FT_TRACE4(( " rlineto" ));
+            if ( start_point( builder, x, y ) ) goto Memory_Error;
+
+            x += top[0];
+            y += top[1];
+   Add_Line:
+            if (add_point1( builder, x, y )) goto Memory_Error;
+            break;
+          }
+
+
+          case op_rmoveto: /*************************************************/
+          {
+            FT_TRACE4(( " rmoveto" ));
+            x += top[0];
+            y += top[1];
+            break;
+          }
+
+          case op_rrcurveto: /***********************************************/
+          {
+            FT_TRACE4(( " rcurveto" ));
+            if ( start_point( builder, x, y ) ||
+                 check_points( builder, 3 )   ) goto Memory_Error;
+
+            x += top[0];
+            y += top[1];
+            add_point( builder, x, y, 0 );
+
+            x += top[2];
+            y += top[3];
+            add_point( builder, x, y, 0 );
+
+            x += top[4];
+            y += top[5];
+            add_point( builder, x, y, 1 );
+            break;
+          }
+
+
+          case op_vhcurveto:  /**********************************************/
+          {
+            FT_TRACE4(( " vhcurveto" ));
+            if ( start_point( builder, x, y ) ||
+                 check_points( builder, 3 )   ) goto Memory_Error;
+
+            y += top[0];
+            add_point( builder, x, y, 0 );
+            x += top[1];
+            y += top[2];
+            add_point( builder, x, y, 0 );
+            x += top[3];
+            add_point( builder, x, y, 1 );
+            break;
+          }
+
+
+          case op_vlineto:  /************************************************/
+            {
+              FT_TRACE4(( " vlineto" ));
+              if ( start_point( builder, x, y ) ) goto Memory_Error;
+
+              y += top[0];
+              goto Add_Line;
+            }
+
+
+          case op_vmoveto:  /************************************************/
+            {
+              FT_TRACE4(( " vmoveto" ));
+              y += top[0];
+              break;
+            }
+
+
+          case op_div:  /****************************************************/
+          {
+            FT_TRACE4(( " div" ));
+            if (top[1])
+              *top++ = top[0] / top[1];
+            else
+            {
+              FT_ERROR(( "T1.Parse_CharStrings : division by 0\n" ));
+              goto Syntax_Error;
+            }
+            break;
+          }
+
+
+          case op_callsubr:  /***********************************************/
+          {
+            FT_Int  index;
+
+            FT_TRACE4(( " callsubr" ));
+            index = top[0];
+            if ( index < 0 || index >= decoder->subrs->num_subrs )
+            {
+              FT_ERROR(( "T1.Parse_CharStrings : invalid subrs index\n" ));
+              goto Syntax_Error;
+            }
+
+            if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
+            {
+              FT_ERROR(( "T1.Parse_CharStrings : too many nested subrs\n" ));
+              goto Syntax_Error;
+            }
+
+            zone->cursor = ip;  /* save current instruction pointer */
+
+            zone++;
+            zone->base    = decoder->subrs->code[index] + decoder->lenIV;
+            zone->limit   = decoder->subrs->code[index+1];
+            zone->cursor  = zone->base;
+
+            if (!zone->base)
+            {
+              FT_ERROR(( "T1.Parse_CharStrings : invoking empty subrs !!\n" ));
+              goto Syntax_Error;
+            }
+
+            decoder->zone = zone;
+            ip            = zone->base;
+            limit         = zone->limit;
+            break;
+          }
+
+
+          case op_pop:  /****************************************************/
+          {
+            FT_TRACE4(( " pop" ));
+            /* theorically, the arguments are already on the stack */
+            top++;
+            break;
+          }
+
+
+          case op_return:  /************************************************/
+          {
+            FT_TRACE4(( " return" ));
+            if ( zone <= decoder->zones )
+            {
+              FT_ERROR(( "T1.Parse_CharStrings : unexpected return\n" ));
+              goto Syntax_Error;
+            }
+
+            zone--;
+            ip            = zone->cursor;
+            limit         = zone->limit;
+            decoder->zone = zone;
+            break;
+          }
+
+          case op_dotsection:  /*********************************************/
+          {
+            FT_TRACE4(( " dotsection" ));
+            break;
+          }
+
+          case op_hstem:  /**************************************************/
+          {
+            FT_TRACE4(( " hstem" ));
+            break;
+          }
+
+          case op_hstem3:  /*************************************************/
+          {
+            FT_TRACE4(( " hstem3" ));
+            break;
+          }
+
+          case op_vstem:  /**************************************************/
+          {
+            FT_TRACE4(( " vstem" ));
+            break;
+          }
+
+          case op_vstem3:  /*************************************************/
+          {
+            FT_TRACE4(( " vstem3" ));
+            break;
+          }
+
+          case op_setcurrentpoint:  /*****************************************/
+          {
+            FT_TRACE4(( " setcurrentpoint" ));
+            FT_ERROR(( "T1.Parse_CharStrings : unexpected SETCURRENTPOINT\n" ));
+            goto Syntax_Error;
+          }
+
+          default:
+            FT_ERROR(( "T1.Parse_CharStrings : unhandled opcode %d\n", op ));
+            goto Syntax_Error;
+        }
+
+        decoder->top = top;
+
+      } /* general operator processing */
+
+
+    } /* while ip < limit */
+    FT_TRACE4(( "..end..\n\n" ));
+    return error;
+
+  Syntax_Error:
+    return T1_Err_Syntax_Error;
+
+  Stack_Underflow:
+    return T1_Err_Stack_Underflow;
+
+  Memory_Error:
+    return builder->error;
+  }
+
+
+
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********                                                   *********/
+  /**********                                                   *********/
+  /**********           COMPUTE THE MAXIMUM ADVANCE WIDTH       *********/
+  /**********                                                   *********/
+  /**********   The following code is in charge of computing    *********/
+  /**********   the maximum advance width of the font. It       *********/
+  /**********   quickly process each glyph charstring to        *********/
+  /**********   extract the value from either a "sbw" or "seac" *********/
+  /**********   operator.                                       *********/
+  /**********                                                   *********/
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********************************************************************/
+
+#if 0
+  LOCAL_FUNC
+  FT_Error  CID_Compute_Max_Advance( CID_Face  face,
+                                     FT_Int   *max_advance )
+  {
+    FT_Error    error;
+    CID_Decoder  decoder;
+    FT_Int      glyph_index;
+
+    *max_advance = 0;
+
+    /* Initialise load decoder */
+    CID_Init_Decoder( &decoder );
+    CID_Init_Builder( &decoder.builder, face, 0, 0 );
+
+    decoder.builder.metrics_only = 1;
+    decoder.builder.load_points  = 0;
+
+    /* For each glyph, parse the glyph charstring and extract */
+    /* the advance width..                                    */
+    for ( glyph_index = 0; glyph_index < face->root.num_glyphs; glyph_index++ )
+    {
+      /* now get load the unscaled outline */
+      error = cid_load_glyph( &decoder, glyph_index );
+      /* ignore the error if one occured - skip to next glyph */
+    }
+
+    *max_advance = decoder.builder.advance.x;
+    return T1_Err_Ok;
+  }
+#endif
+
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********                                                   *********/
+  /**********                                                   *********/
+  /**********              UNHINTED GLYPH LOADER                *********/
+  /**********                                                   *********/
+  /**********   The following code is in charge of loading a    *********/
+  /**********   single outline. It completely ignores hinting   *********/
+  /**********   and is used when FT_LOAD_NO_HINTING is set.     *********/
+  /**********                                                   *********/
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********************************************************************/
+
+  static
+  FT_Error  cid_load_glyph( CID_Decoder*  decoder, FT_UInt  glyph_index )
+  {
+    CID_Face  face = decoder->builder.face;
+    CID_Info* cid  = &face->cid;
+    FT_Byte*  p;
+    FT_UInt   entry_len = cid->fd_bytes + cid->gd_bytes;
+    FT_UInt   fd_select;
+    FT_ULong  off1, glyph_len;
+    FT_Stream stream = face->root.stream;
+    FT_Error  error  = 0;
+
+    /* read the CID font dict index and charstring offset from the CIDMap */
+    if ( FILE_Seek( cid->data_offset + cid->cidmap_offset +
+                    glyph_index * entry_len) ||
+         ACCESS_Frame( 2*entry_len )         )
+      goto Exit;           
+
+    p = (FT_Byte*)stream->cursor;
+    fd_select = (FT_UInt) cid_get_offset( &p, cid->fd_bytes );
+    off1      = (FT_ULong)cid_get_offset( &p, cid->gd_bytes );
+    p        += cid->fd_bytes;
+    glyph_len = cid_get_offset( &p, cid->gd_bytes ) - off1;
+
+    FORGET_Frame();
+
+    /* now, if the glyph is not empty, set up the subrs array, and parse */
+    /* the charstrings                                                   */
+    if (glyph_len > 0)
+    {
+      CID_FontDict* dict;
+      FT_Byte*      charstring;
+      FT_UInt       lenIV;
+      FT_Memory     memory = face->root.memory;
+
+      /* setup subrs */
+      decoder->subrs = face->subrs + fd_select;
+
+      /* setup font matrix */            
+      dict                 = cid->font_dicts + fd_select;
+      decoder->font_matrix = dict->font_matrix;
+      lenIV                = dict->private_dict.lenIV;
+      decoder->lenIV       = lenIV;
+      
+      /* the charstrings are encoded (stupid !!)  */
+      /* load the charstrings, then execute it    */
+      
+      if ( ALLOC( charstring, glyph_len ) )
+        goto Exit;
+        
+      if ( !FILE_Read_At( cid->data_offset + off1, charstring, glyph_len ) )
+      {
+        cid_decrypt( charstring, glyph_len, 4330 );
+        error = CID_Parse_CharStrings( decoder,
+                                       charstring + lenIV,
+                                       glyph_len  - lenIV );
+      }
+
+      FREE( charstring );
+    }
+
+  Exit:
+    return error;
+  }  
+  
+  
+
+  LOCAL_FUNC
+  FT_Error  CID_Load_Glyph( T1_GlyphSlot  glyph,
+                            T1_Size       size,
+                            FT_Int        glyph_index,
+                            FT_Int        load_flags )
+  {
+    FT_Error        error;
+    CID_Decoder     decoder;
+    CID_Face        face = (CID_Face)glyph->root.face;
+    T1_Bool         hinting;
+
+    if (load_flags & FT_LOAD_NO_RECURSE)
+      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+    glyph->x_scale = size->root.metrics.x_scale;
+    glyph->y_scale = size->root.metrics.y_scale;
+
+    glyph->root.outline.n_points   = 0;
+    glyph->root.outline.n_contours = 0;
+
+    hinting = ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
+              ( load_flags & FT_LOAD_NO_HINTING ) == 0;
+
+    glyph->root.format = ft_glyph_format_none;
+
+    {
+      CID_Init_Decoder( &decoder );
+      CID_Init_Builder( &decoder.builder, face, size, glyph );
+
+      /* set up the decoder */
+      decoder.builder.no_recurse = (FT_Bool)!!(load_flags & FT_LOAD_NO_RECURSE);
+
+      error = cid_load_glyph( &decoder, glyph_index );
+
+      /* save new glyph tables */
+      CID_Done_Builder( &decoder.builder );
+    }
+
+    /* Now, set the metrics.. - this is rather simple, as : */
+    /* the left side bearing is the xMin, and the top side  */
+    /* bearing the yMax..                                   */
+    if (!error)
+    {
+      /* for composite glyphs, return only the left side bearing and the */
+      /* advance width..                                                 */
+      if ( load_flags & FT_LOAD_NO_RECURSE )
+      {
+        glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+        glyph->root.metrics.horiAdvance  = decoder.builder.advance.x;
+      }
+      else
+      {
+        FT_BBox           cbox;
+        FT_Glyph_Metrics* metrics = &glyph->root.metrics;
+
+        /* copy the _unscaled_ advance width */
+        metrics->horiAdvance  = decoder.builder.advance.x;
+
+        /* make up vertical metrics */
+        metrics->vertBearingX = 0;
+        metrics->vertBearingY = 0;
+        metrics->vertAdvance  = 0;
+
+        glyph->root.format = ft_glyph_format_outline;
+
+        glyph->root.outline.flags &= ft_outline_owner;
+        if ( size && size->root.metrics.y_ppem < 24 )
+          glyph->root.outline.flags |= ft_outline_high_precision;
+
+        glyph->root.outline.flags |= ft_outline_reverse_fill;
+
+        /*
+        glyph->root.outline.second_pass    = TRUE;
+        glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 );
+        glyph->root.outline.dropout_mode   = 2;
+        */
+
+        if ( (load_flags & FT_LOAD_NO_SCALE) == 0 )
+        {
+          /* scale the outline and the metrics */
+          FT_Int       n;
+          FT_Outline*  cur = &decoder.builder.base;
+          T1_Vector*   vec = cur->points;
+          T1_Fixed     x_scale = glyph->x_scale;
+          T1_Fixed     y_scale = glyph->y_scale;
+
+          /* First of all, scale the points */
+          for ( n = cur->n_points; n > 0; n--, vec++ )
+          {
+            vec->x = FT_MulFix( vec->x, x_scale );
+            vec->y = FT_MulFix( vec->y, y_scale );
+          }
+
+          FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+          /* Then scale the metrics */
+          metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
+
+          metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+          metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+          metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  x_scale );
+        }
+
+        /* apply the font matrix */
+        FT_Outline_Transform( &glyph->root.outline, &decoder.font_matrix );
+
+        /* compute the other metrics */
+        FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+        /* grid fit the bounding box if necessary */
+        if (hinting)
+        {
+          cbox.xMin &= -64;
+          cbox.yMin &= -64;
+          cbox.xMax = ( cbox.xMax+63 ) & -64;
+          cbox.yMax = ( cbox.yMax+63 ) & -64;
+        }
+
+        metrics->width  = cbox.xMax - cbox.xMin;
+        metrics->height = cbox.yMax - cbox.yMin;
+
+        metrics->horiBearingX = cbox.xMin;
+        metrics->horiBearingY = cbox.yMax;
+      }
+    }
+    return error;
+  }
+
--- /dev/null
+++ b/src/cid/cidgload.h
@@ -1,0 +1,188 @@
+/*******************************************************************
+ *
+ *  cidgload.h                                                   1.0
+ *
+ *    CID-Keyed Type1 Glyph Loader.
+ *
+ *  Copyright 1996-1998 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.
+ *
+ *
+ *  The Type 1 glyph loader uses three distinct objects to build
+ *  scaled and hinted outlines from a charstrings program. These are :
+ *
+ *  - a glyph builder, CID_Builder, used to store the built outline
+ *
+ *  - a glyph hinter, T1_Hinter, used to record and apply the stem
+ *    hints
+ *
+ *  - a charstrings interpreter, CID_Decoder, used to parse the
+ *    Type 1 charstrings stream, manage a stack and call the builder
+ *    and/or hinter depending on the opcodes.
+ *
+ *  Ideally, a Type 2 glyph loader would only need to have its own
+ *  T2_Decoder object (assuming the hinter is able to manage all
+ *  kinds of hints).
+ *
+ ******************************************************************/
+
+#ifndef CIDGLOAD_H
+#define CIDGLOAD_H
+
+#include <cidobjs.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+/*************************************************************************/
+/*                                                                       */
+/* <Structure> CID_Builder                                                */
+/*                                                                       */
+/* <Description>                                                         */
+/*     a structure used during glyph loading to store its outline.       */
+/*                                                                       */
+/* <Fields>                                                              */
+/*    system :: current system object                                    */
+/*    face   :: current face object                                      */
+/*    glyph  :: current glyph slot                                       */
+/*                                                                       */
+/*    current :: current glyph outline                                   */
+/*    base    :: base glyph outline                                      */
+/*                                                                       */
+/*    max_points   :: maximum points in builder outline                  */
+/*    max_contours :: maximum contours in builder outline                */
+/*                                                                       */
+/*    last     :: last point position                                    */
+/*                                                                       */
+/*    scale_x  :: horizontal scale ( FUnits to sub-pixels )              */
+/*    scale_y  :: vertical scale   ( FUnits to sub-pixels )              */
+/*    pos_x    :: horizontal translation (composite glyphs)              */
+/*    pos_y    :: vertical translation   (composite glyph)               */
+/*                                                                       */
+/*    left_bearing  :: left side bearing point                           */
+/*    advance       :: horizontal advance vector                         */
+/*                                                                       */
+/*    path_begun    :: flag, indicates that a new path has begun         */
+/*    load_points   :: flag, if not set, no points are loaded            */
+/*                                                                       */
+/*    error         :: an error code that is only used to report         */
+/*                     memory allocation problems..                      */
+/*                                                                       */
+/*    metrics_only  :: a boolean indicating that we only want to         */
+/*                     compute the metrics of a given glyph, not load    */
+/*                     all of its points..                               */
+/*                                                                       */
+
+  typedef struct CID_Builder_
+  {
+    FT_Memory     memory;
+    CID_Face      face;
+    T1_GlyphSlot  glyph;
+
+    FT_Outline    current;       /* the current glyph outline   */
+    FT_Outline    base;          /* the composite glyph outline */
+
+    FT_Int        max_points;    /* capacity of base outline in points   */
+    FT_Int        max_contours;  /* capacity of base outline in contours */
+
+    T1_Vector     last;
+
+    T1_Fixed      scale_x;
+    T1_Fixed      scale_y;
+
+    T1_Pos        pos_x;
+    T1_Pos        pos_y;
+
+    T1_Vector     left_bearing;
+    T1_Vector     advance;
+
+    T1_BBox       bbox;          /* bounding box */
+    T1_Bool       path_begun;
+    T1_Bool       load_points;
+    T1_Bool       no_recurse;
+
+    FT_Error      error;         /* only used for memory errors */
+    T1_Bool       metrics_only;
+
+  } CID_Builder;
+
+
+  /* execution context charstring zone */
+  typedef struct CID_Decoder_Zone_
+  {
+    FT_Byte*  base;
+    FT_Byte*  limit;
+    FT_Byte*  cursor;
+
+  } CID_Decoder_Zone;
+
+
+  typedef struct CID_Decoder_
+  {
+    CID_Builder        builder;
+
+    FT_Int             stack[ T1_MAX_CHARSTRINGS_OPERANDS ];
+    FT_Int*            top;
+
+    CID_Decoder_Zone   zones[ T1_MAX_SUBRS_CALLS+1 ];
+    CID_Decoder_Zone*  zone;
+
+    FT_Matrix          font_matrix;
+    CID_Subrs*         subrs;
+    FT_UInt            lenIV;
+
+    FT_Int             flex_state;
+    FT_Int             num_flex_vectors;
+    FT_Vector          flex_vectors[7];
+
+  } CID_Decoder;
+
+
+
+  LOCAL_DEF
+  void  CID_Init_Builder( CID_Builder*             builder,
+                          CID_Face                 face,
+                          T1_Size                  size,
+                          T1_GlyphSlot             glyph );
+
+  LOCAL_DEF
+  void CID_Done_Builder( CID_Builder*  builder );
+
+
+  LOCAL_DEF
+  void  CID_Init_Decoder( CID_Decoder* decoder );
+
+
+#if 0
+  /* Compute the maximum advance width of a font through quick parsing */
+  LOCAL_DEF
+  FT_Error  CID_Compute_Max_Advance( CID_Face  face,
+                                     FT_Int   *max_advance );
+#endif
+
+  /* This function is exported, because it is used by the T1Dump utility */
+  LOCAL_DEF
+  FT_Error   CID_Parse_CharStrings( CID_Decoder*  decoder,
+                                    FT_Byte*      charstring_base,
+                                    FT_Int        charstring_len );
+
+  LOCAL_DEF
+  FT_Error  CID_Load_Glyph( T1_GlyphSlot  glyph,
+                            T1_Size       size,
+                            FT_Int        glyph_index,
+                            FT_Int        load_flags );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* T1GLOAD_H */
--- /dev/null
+++ b/src/cid/cidload.c
@@ -1,0 +1,503 @@
+/*******************************************************************
+ *
+ *  cidload.h                                                    2.0
+ *
+ *    CID-keyed foint loader
+ *
+ *  Copyright 1996-2000 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ *  This file is part of the FreeType project, and may only be used
+ *  modified and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ *
+ *  This is the new and improved Type 1 data loader for FreeType 2.
+ *  The old loader has several problems: it is slow, complex, difficult
+ *  to maintain, and contains incredible hacks to make it accept some
+ *  ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5%
+ *  of the Type 1 fonts on my machine still aren't loaded correctly
+ *  with it.
+ *
+ *  This version is much simpler, much faster and also easier to
+ *  read and maintain by a great order of magnitude. The idea behind
+ *  it is to _not_ try to read the Type 1 token stream with a state
+ *  machine (i.e. a Postscript-like interpreter) but rather to perform
+ *  simple pattern-matching.
+ *
+ *  Indeed, nearly all data definitions follow a simple pattern
+ *  like :
+ *
+ *      ..... /Field <data> ....
+ *
+ *  where <data> can be a number, a boolean, a string, or an
+ *  array of numbers. There are a few exceptions, namely the
+ *  encoding, font name, charstrings and subrs and they are
+ *  handled with a special pattern-matching routine.
+ *
+ *  All other common cases are handled very simply. The matching
+ *  rules are defined in the file "t1tokens.h" through the use
+ *  of several macros calls T1_FIELD_XXX
+ *
+ *  The function "parse_dict" simply scans *linearly* a given
+ *  dictionary (either the top-level or private one) and calls
+ *  the appropriate callback when it encounters an immediate
+ *  keyword.
+ *
+ *  This is by far the fastest way one can find to parse and read
+ *  all data :-)
+ *
+ *  This led to tremendous code size reduction. Note that later,
+ *  the glyph loader will also be _greatly_ simplified, and the
+ *  automatic hinter will replace the clumsy "t1hinter"..
+ *
+ ******************************************************************/
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/config/ftconfig.h>
+#include <freetype/ftmm.h>
+
+#include <freetype/internal/t1types.h>
+#include <t1errors.h>
+#include <cidload.h>
+#include <stdio.h>
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1load
+
+ /* reads a single offset */
+  LOCAL_FUNC
+  FT_Long  cid_get_offset( FT_Byte** start, FT_Byte  offsize )
+  {
+    FT_Long  result;
+    FT_Byte* p = *start;
+    
+    for ( result = 0; offsize > 0; offsize-- )
+      result = (result << 8) | *p++;
+      
+    *start = p;
+    return result;
+  }
+
+
+  LOCAL_FUNC
+  void  cid_decrypt( FT_Byte*   buffer,
+                     FT_Int     length,
+                     FT_UShort  seed )
+  {
+    while ( length > 0 )
+    {
+      FT_Byte  plain;
+
+      plain     = (*buffer ^ (seed >> 8));
+      seed      = (*buffer+seed)*52845+22719;
+      *buffer++ = plain;
+      length--;
+    }
+  }
+
+
+
+ /***************************************************************************/
+ /***************************************************************************/
+ /*****                                                                 *****/
+ /*****                      TYPE 1 SYMBOL PARSING                      *****/
+ /*****                                                                 *****/
+ /***************************************************************************/
+ /***************************************************************************/
+
+
+  static  FT_Error   cid_load_keyword( CID_Face             face,
+                                       CID_Loader*          loader,
+                                       const T1_Field_Rec*  keyword )
+  {
+    FT_Error    error;
+    CID_Parser* parser = &loader->parser;
+    FT_Byte*    object;
+    CID_Info*   cid = &face->cid;
+
+    /* if the keyword has a dedicated callback, call it */
+    if (keyword->type == t1_field_callback)
+    {
+      error = keyword->reader( face, parser );
+      goto Exit;
+    }
+
+    /* we must now compute the address of our target object */
+    switch (keyword->location)
+    {
+      case t1_field_cid_info:
+          object = (FT_Byte*)cid;
+          break;
+          
+      case t1_field_font_info:
+          object = (FT_Byte*)&cid->font_info;
+          break;
+          
+      default:
+        {
+          CID_FontDict*  dict;
+          
+          if ( parser->num_dict < 0 )
+          {
+            FT_ERROR(( "CID.Load_Keyword: invalid use of '%s' !!\n", keyword->ident ));
+            error = T1_Err_Syntax_Error;
+            goto Exit;
+          }
+          
+          dict = cid->font_dicts + parser->num_dict;
+          switch (keyword->location)
+          {
+            case t1_field_private:
+              object = (FT_Byte*)&dict->private_dict;
+              break;
+              
+            default:
+              object = (FT_Byte*)dict;
+          }
+        }
+    }
+    
+    /* now, load the keyword data in the object's field(s) */
+    if ( keyword->type == t1_field_integer_array ||
+         keyword->type == t1_field_fixed_array   )
+      error = CID_Load_Field_Table( parser, keyword, object );
+    else
+      error = CID_Load_Field( parser, keyword, object );
+    
+  Exit:
+    return error;
+  }                                
+
+
+  static
+  FT_Error  parse_font_bbox( CID_Face  face, CID_Parser*  parser )
+  {
+    FT_Short      temp[4];
+    T1_BBox*      bbox = &face->cid.font_bbox;
+
+    (void)CID_ToCoordArray( parser, 4, temp );
+    bbox->xMin = temp[0];
+    bbox->yMin = temp[1];
+    bbox->xMax = temp[2];
+    bbox->yMax = temp[3];
+    
+    return 0;
+  }
+
+  static
+  FT_Error  parse_font_matrix( CID_Face  face, CID_Parser*  parser )
+  {
+    FT_Matrix*     matrix;
+    CID_FontDict*  dict;
+    T1_Fixed       temp[4];
+
+    if (parser->num_dict >= 0)
+    {
+      dict   = face->cid.font_dicts + parser->num_dict;
+      matrix = &dict->font_matrix;
+      
+      (void)CID_ToFixedArray( parser, 4, temp, 3 );
+      matrix->xx = temp[0];
+      matrix->yx = temp[1];
+      matrix->xy = temp[2];
+      matrix->yy = temp[3];
+    }
+    return 0;
+  }
+
+  static
+  FT_Error  parse_fd_array( CID_Face   face, CID_Parser*  parser )
+  {
+    CID_Info*  cid    = &face->cid;
+    FT_Memory  memory = face->root.memory;
+    FT_Error   error;
+    FT_Long    num_dicts;
+    
+    num_dicts = CID_ToInt(parser);
+    if ( !cid->font_dicts )
+    {
+      FT_Int  n;
+      
+      if ( ALLOC_ARRAY( cid->font_dicts, num_dicts, CID_FontDict ) )
+        goto Exit;
+      
+      cid->num_dicts = (FT_UInt)num_dicts;
+      
+      /* don't forget to set a few defauts !! */
+      for ( n = 0; n < cid->num_dicts; n++ )
+      {
+        CID_FontDict*  dict = cid->font_dicts + n;
+        
+        /* default value for lenIV !! */
+        dict->private_dict.lenIV = 4;
+      }
+    }
+    
+  Exit:
+    return error;
+  }
+
+
+
+  static
+  const T1_Field_Rec   t1_field_records[] = 
+  {
+    #include <cidtokens.h>
+    { 0, 0, 0, 0, 0, 0 }
+  };
+
+
+  static
+  int  is_space( char c )
+  {
+    return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
+  }
+
+  static
+  int  is_alpha( char c )
+  {
+    return ( (c >= 'A' && c <= 'Z') ||
+             (c >= 'a' && c <= 'z') ||
+             (c >= '0' && c <= '9') ||
+             (c == '.')             ||
+             (c == '_') );
+  }
+
+  static
+  void  skip_whitespace( CID_Parser* parser )
+  {
+    FT_Byte*  cur = parser->cursor;
+
+    while ( cur < parser->limit && is_space(*cur) )
+      cur++;
+
+    parser->cursor = cur;
+  }
+
+
+
+  static
+  FT_Error  parse_dict( CID_Face    face,
+                        CID_Loader*  loader,
+                        FT_Byte*    base,
+                        FT_Long     size )
+  {
+    CID_Parser*  parser   = &loader->parser;
+
+    parser->cursor = base;
+    parser->limit  = base + size;
+    parser->error  = 0;
+
+    {
+      FT_Byte*  cur     = base;
+      FT_Byte*  limit   = cur + size;
+
+      for ( ;cur < limit; cur++ )
+      {
+        /* look for %ADOBegin... */
+        if ( *cur == '%' && cur + 20 < limit &&
+             strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
+        {
+          cur += 17;
+          
+          /* if /FDArray was found, then cid->num_dicts is > 0, and */
+          /* we can start increasing parser->num_dict               */
+          if ( face->cid.num_dicts > 0 )
+            parser->num_dict++;
+        }
+        /* look for immediates */
+        else if (*cur == '/' && cur+2 < limit)
+        {
+          FT_Byte* cur2;
+          FT_Int   len;
+
+          cur  ++;
+          cur2 = cur;
+          while (cur2 < limit && is_alpha(*cur2)) cur2++;
+          len  = cur2-cur;
+
+          if (len > 0 && len < 22)
+          {
+            /* now, compare the immediate name to the keyword table */
+            const T1_Field_Rec*  keyword = t1_field_records;
+
+            for (;;)
+            {
+              FT_Byte*  name;
+
+              name = (FT_Byte*)keyword->ident;
+              if (!name) break;
+
+              if ( cur[0] == name[0] &&
+                   len == (FT_Int)strlen((const char*)name) )
+              {
+                FT_Int  n;
+                for ( n = 1; n < len; n++ )
+                  if (cur[n] != name[n])
+                    break;
+
+                if (n >= len)
+                {
+                  /* we found it - run the parsing callback !! */
+                  parser->cursor = cur2;
+                  skip_whitespace( parser );
+                  parser->error = cid_load_keyword( face, loader, keyword );
+                  if (parser->error)
+                    return parser->error;
+
+                  cur = parser->cursor;
+                  break;
+                }
+              }
+              keyword++;
+            }
+          }
+        }
+      }
+    }
+    return parser->error;
+  }
+
+
+
+  /* read the subrmap and the subrs of each font dict */
+  static
+  FT_Error  cid_read_subrs( CID_Face   face )
+  {
+    CID_Info*   cid    = &face->cid;
+    FT_Memory   memory = face->root.memory;
+    FT_Stream   stream = face->root.stream;
+    FT_Error    error;
+    FT_UInt     n;
+    CID_Subrs*  subr;
+    FT_UInt     max_offsets = 0;
+    FT_ULong*   offsets = 0;
+    
+    if ( ALLOC_ARRAY( face->subrs, cid->num_dicts, CID_Subrs ) )
+      goto Exit;
+      
+    subr = face->subrs;
+    for ( n = 0; n < cid->num_dicts; n++, subr++ )
+    {
+      CID_FontDict*  dict      = cid->font_dicts + n;
+      FT_UInt        count, num_subrs = dict->num_subrs;
+      FT_ULong       data_len;
+      FT_Byte*       p;
+      
+      /* reallocate offsets array if needed */
+      if ( num_subrs+1 > max_offsets )
+      {
+        FT_UInt  new_max = (num_subrs+1+3) & -4;
+        if ( REALLOC_ARRAY( offsets, max_offsets, new_max, FT_ULong ) )
+          goto Fail;
+          
+        max_offsets = new_max;
+      }
+      
+      /* read the subrmap's offsets */
+      if ( FILE_Seek( cid->data_offset + dict->subrmap_offset ) ||
+           ACCESS_Frame( (num_subrs+1) * dict->sd_bytes )       )
+        goto Fail;
+        
+      p = (FT_Byte*)stream->cursor;
+      for ( count = 0; count <= num_subrs; count++ )
+        offsets[count] = cid_get_offset( &p, dict->sd_bytes );
+        
+      FORGET_Frame();
+      
+      /* now, compute the size of subrs charstrings, allocate and read them */
+      data_len = offsets[num_subrs] - offsets[0];
+      
+      if ( ALLOC_ARRAY( subr->code, num_subrs+1, FT_Byte* ) ||
+           ALLOC( subr->code[0], data_len )                 )
+        goto Fail;
+
+      if ( FILE_Seek( cid->data_offset + offsets[0] ) ||
+           FILE_Read( subr->code[0], data_len )  )
+        goto Exit;
+
+      /* set up pointers */
+      for ( count = 1; count <= num_subrs; count++ )
+      {
+        FT_UInt  len;
+        
+        len = offsets[count] - offsets[count-1];
+        subr->code[count] = subr->code[count-1] + len;
+      }
+
+      /* decrypt subroutines */        
+      for ( count = 0; count < num_subrs; count++ )
+      {
+        FT_UInt  len;
+        
+        len = offsets[count+1] - offsets[count];
+        cid_decrypt( subr->code[count], len, 4330 );
+      }
+
+      subr->num_subrs = num_subrs;
+    }
+
+  Exit:
+    FREE( offsets );
+    return error;
+    
+  Fail:
+    if (face->subrs)
+    {
+      for ( n = 0; n < cid->num_dicts; n++ )
+      {
+        if (face->subrs[n].code)
+          FREE( face->subrs[n].code[0] );
+          
+        FREE( face->subrs[n].code );
+      }
+      FREE( face->subrs );
+    }
+    goto Exit;
+  }
+
+  static
+  void t1_init_loader( CID_Loader* loader, CID_Face  face )
+  {
+    UNUSED(face);
+
+    MEM_Set( loader, 0, sizeof(*loader) );
+  }
+
+  static
+  void t1_done_loader( CID_Loader* loader )
+  {
+    CID_Parser*  parser = &loader->parser;
+
+    /* finalize parser */
+    CID_Done_Parser( parser );
+  }
+
+  LOCAL_FUNC
+  FT_Error  T1_Open_Face( CID_Face  face )
+  {
+    CID_Loader  loader;
+    CID_Parser* parser;
+    FT_Error   error;
+
+    t1_init_loader( &loader, face );
+
+    parser = &loader.parser;
+    error = CID_New_Parser( parser, face->root.stream, face->root.memory );
+    if (error) goto Exit;
+
+    error = parse_dict( face, &loader,
+                        parser->postscript,
+                        parser->postscript_len );
+    if (error) goto Exit;
+
+    face->cid.data_offset = loader.parser.data_offset;
+    error = cid_read_subrs( face );
+   
+  Exit:
+    t1_done_loader( &loader );
+    return error;
+  }
--- /dev/null
+++ b/src/cid/cidload.h
@@ -1,0 +1,54 @@
+/*******************************************************************
+ *
+ *  t1load.h                                                    2.0
+ *
+ *    Type1 Loader.
+ *
+ *  Copyright 1996-2000 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ *  This file is part of the FreeType project, and may only be used
+ *  modified and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ ******************************************************************/
+
+#ifndef T1LOAD_H
+#define T1LOAD_H
+
+#include <freetype/internal/ftstream.h>
+#include <cidparse.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+  typedef struct CID_Loader_
+  {
+    CID_Parser        parser;          /* parser used to read the stream */
+
+    FT_Int           num_chars;       /* number of characters in encoding */
+
+  } CID_Loader;
+
+  LOCAL_DEF
+  FT_Long  cid_get_offset( FT_Byte** start, FT_Byte  offsize );
+
+  LOCAL_DEF
+  void  cid_decrypt( FT_Byte*   buffer,
+                     FT_Int     length,
+                     FT_UShort  seed );
+
+  LOCAL_DEF
+  FT_Error  T1_Open_Face( CID_Face  face );
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* T1LOAD_H */
+
+
+/* END */
--- /dev/null
+++ b/src/cid/cidobjs.c
@@ -1,0 +1,473 @@
+/*******************************************************************
+ *
+ *  t1objs.c                                                     1.0
+ *
+ *    Type1 Objects manager.
+ *
+ *  Copyright 1996-1998 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.
+ *
+ ******************************************************************/
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+
+#include <cidgload.h>
+#include <cidload.h>
+#include <freetype/internal/psnames.h>
+#include <cidafm.h>
+
+/* Required by tracing mode */
+#undef   FT_COMPONENT
+#define  FT_COMPONENT  trace_t1objs
+
+/*******************************************************************
+ *                                                                 *
+ *                         SIZE  FUNCTIONS                         *
+ *                                                                 *
+ *                                                                 *
+ *******************************************************************/
+
+/*******************************************************************
+ *
+ * <Function>  T1_Done_Size
+ *
+ * <Description>
+ *    The TrueDoc instance object destructor. Used to discard
+ *    a given instance object..
+ *
+ * <Input>
+ *    instance   :: handle to the target instance object
+ *
+ * <Return>
+ *    TrueDoc error code. 0 means success
+ *
+ ******************************************************************/
+
+  LOCAL_FUNC
+  void  T1_Done_Size( T1_Size  size )
+  {
+    UNUSED(size);
+  }
+
+
+/*******************************************************************
+ *
+ *  <Function> T1_Init_Size
+ *
+ *  <Description>
+ *     The instance object constructor
+ *
+ *  <Input>
+ *     instance  : handle to new instance object
+ *     face      : pointer to parent face object
+ *
+ *  <Return>
+ *     TrueDoc error code. 0 means success.
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  FT_Error  T1_Init_Size( T1_Size  size )
+  {
+    size->valid = 0;
+    return T1_Err_Ok;
+  }
+
+
+/*******************************************************************
+ *
+ *  <Function> T1_Reset_Size
+ *
+ *  <Description>
+ *     Resets an instance to a new pointsize/transform.
+ *     This function is in charge of resetting the blue zones,
+ *     As well as the stem snap tables for a given size..
+ *
+ *  <Input>
+ *     instance   the instance object to destroy
+ *
+ *  <Output>
+ *     Error code.
+ *
+ ******************************************************************/
+
+  LOCAL_FUNC
+  FT_Error  T1_Reset_Size( T1_Size  size )
+  {
+    UNUSED(size);
+    return 0;
+  }
+
+
+/*******************************************************************
+ *                                                                 *
+ *                         FACE  FUNCTIONS                         *
+ *                                                                 *
+ *                                                                 *
+ *******************************************************************/
+
+/*******************************************************************
+ *
+ *  <Function> T1_Done_Face
+ *
+ *  <Description>
+ *     The face object destructor.
+ *
+ *  <Input>
+ *     face  :: typeless pointer to the face object to destroy
+ *
+ *  <Return>
+ *     Error code.
+ *
+ ******************************************************************/
+
+  LOCAL_FUNC
+  void  T1_Done_Face( CID_Face  face )
+  {
+    FT_Memory  memory;
+
+    if (face)
+    {
+      CID_Info*      cid   = &face->cid;
+      T1_FontInfo*   info  = &cid->font_info;
+
+      memory = face->root.memory;
+      
+      /* release FontInfo strings */
+      FREE( info->version );
+      FREE( info->notice );
+      FREE( info->full_name );
+      FREE( info->family_name );
+      FREE( info->weight );
+      
+      /* release font dictionaries */
+      FREE( cid->font_dicts );
+      cid->num_dicts = 0;
+      
+      /* release other strings */
+      FREE( cid->cid_font_name );
+      FREE( cid->registry );
+      FREE( cid->ordering );
+      
+      face->root.family_name = 0;
+      face->root.style_name  = 0;
+    }
+  }
+
+/*******************************************************************
+ *
+ *  <Function>  T1_Init_Face
+ *
+ *  <Description>
+ *     The face object constructor.
+ *
+ *  <Input>
+ *     face  ::  face record to build
+ *     Input ::  input stream where to load font data
+ *
+ *  <Return>
+ *     Error code.
+ *
+ ******************************************************************/
+
+  LOCAL_FUNC
+  FT_Error  T1_Init_Face( FT_Stream      stream,
+                          CID_Face       face,
+                          FT_Int         face_index,
+                          FT_Int         num_params,
+                          FT_Parameter*  params )
+  {
+    FT_Error      error;
+    PSNames_Interface*  psnames;
+
+    UNUSED(num_params);
+    UNUSED(params);
+    UNUSED(face_index);
+    UNUSED(stream);
+
+    face->root.num_faces = 1;
+
+    psnames = (PSNames_Interface*)face->psnames;
+    if (!psnames)
+    {
+      /* look-up the PSNames driver */
+      FT_Driver  psnames_driver;
+
+      psnames_driver = FT_Get_Driver( face->root.driver->library, "psnames" );
+      if (psnames_driver)
+        face->psnames = (PSNames_Interface*)
+                            (psnames_driver->interface.format_interface);
+    }
+
+    /* open the tokenizer, this will also check the font format */
+    if ( FILE_Seek(0) )
+      goto Exit;
+      
+    error = T1_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(( "T1.Init_Face : invalid face index\n" ));
+      error = T1_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 */
+      {
+        FT_Face  root = (FT_Face)&face->root;
+
+        root->num_glyphs   = face->cid.cid_count;
+        root->num_charmaps = 0;
+
+        root->face_index = face_index;
+        root->face_flags = FT_FACE_FLAG_SCALABLE;
+
+        root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
+
+        if ( face->cid.font_info.is_fixed_pitch )
+          root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+        /* XXX : TO DO - add kerning with .afm support */
+
+        /* get style name - be careful, some broken fonts only */
+        /* have a /FontName dictionary entry .. !!             */
+        root->family_name = face->cid.font_info.family_name;
+        if (root->family_name)
+        {
+          char*  full   = face->cid.font_info.full_name;
+          char*  family = root->family_name;
+
+          while ( *family && *full == *family )
+          {
+            family++;
+            full++;
+          }
+
+          root->style_name = ( *full == ' ' ? full+1 : "Regular" );
+        }
+        else
+        {
+          /* do we have a /FontName ?? */
+          if (face->cid.cid_font_name)
+          {
+            root->family_name = face->cid.cid_font_name;
+            root->style_name  = "Regular";
+          }
+        }
+
+        /* no embedded bitmap support */
+        root->num_fixed_sizes = 0;
+        root->available_sizes = 0;
+
+        root->bbox         = face->cid.font_bbox;
+        root->units_per_EM = 1000;
+        root->ascender     =  (FT_Short)face->cid.font_bbox.yMax;
+        root->descender    = -(FT_Short)face->cid.font_bbox.yMin;
+        root->height       = ((root->ascender + root->descender)*12)/10;
+
+#if 0
+        /* now compute the maximum advance width */
+
+        root->max_advance_width = face->type1.private_dict.standard_width[0];
+
+        /* compute max advance width for proportional fonts */
+        if (!face->type1.font_info.is_fixed_pitch)
+        {
+          FT_Int  max_advance;
+
+          error = T1_Compute_Max_Advance( face, &max_advance );
+
+          /* in case of error, keep the standard width */
+          if (!error)
+            root->max_advance_width = max_advance;
+          else
+            error = 0;   /* clear error */
+        }
+
+        root->max_advance_height = root->height;
+#endif
+        root->underline_position  = face->cid.font_info.underline_position;
+        root->underline_thickness = face->cid.font_info.underline_thickness;
+
+        root->max_points   = 0;
+        root->max_contours = 0;
+      }
+    }
+
+#if 0
+    /* charmap support - synthetize unicode charmap when possible */
+    {
+      FT_Face      root    = &face->root;
+      FT_CharMap   charmap = face->charmaprecs;
+
+      /* synthesize a Unicode charmap if there is support in the "psnames" */
+      /* module..                                                          */
+      if (face->psnames)
+      {
+        PSNames_Interface*  psnames = (PSNames_Interface*)face->psnames;
+        if (psnames->unicode_value)
+        {
+          error = psnames->build_unicodes( root->memory,
+                                           face->type1.num_glyphs,
+                                           (const char**)face->type1.glyph_names,
+                                           &face->unicode_map );
+          if (!error)
+          {
+            root->charmap        = charmap;
+            charmap->face        = (FT_Face)face;
+            charmap->encoding    = ft_encoding_unicode;
+            charmap->platform_id = 3;
+            charmap->encoding_id = 1;
+            charmap++;
+          }
+
+          /* simply clear the error in case of failure (which really) */
+          /* means that out of memory or no unicode glyph names       */
+          error = 0;
+        }
+      }
+
+      /* now, support either the standard, expert, or custom encodings */
+      charmap->face        = (FT_Face)face;
+      charmap->platform_id = 7;  /* a new platform id for Adobe fonts ?? */
+
+      switch (face->type1.encoding_type)
+      {
+        case t1_encoding_standard:
+          charmap->encoding    = ft_encoding_adobe_standard;
+          charmap->encoding_id = 0;
+          break;
+
+        case t1_encoding_expert:
+          charmap->encoding    = ft_encoding_adobe_expert;
+          charmap->encoding_id = 1;
+          break;
+
+        default:
+          charmap->encoding    = ft_encoding_adobe_custom;
+          charmap->encoding_id = 2;
+          break;
+      }
+
+      root->charmaps = face->charmaps;
+      root->num_charmaps = charmap - face->charmaprecs + 1;
+      face->charmaps[0] = &face->charmaprecs[0];
+      face->charmaps[1] = &face->charmaprecs[1];
+    }
+#endif    
+  Exit:
+    return error;
+  }
+
+
+/*******************************************************************
+ *
+ *  Function    :  Glyph_Destroy
+ *
+ *  Description :  The glyph object destructor.
+ *
+ *  Input  :  _glyph  typeless pointer to the glyph record to destroy
+ *
+ *  Output :  Error code.
+ *
+ ******************************************************************/
+
+  LOCAL_FUNC
+  void  T1_Done_GlyphSlot( T1_GlyphSlot  glyph )
+  {
+    FT_Memory  memory  = glyph->root.face->memory;
+    FT_Library library = glyph->root.face->driver->library;
+
+	/* the bitmaps are created on demand */
+	FREE( glyph->root.bitmap.buffer );
+    FT_Outline_Done( library, &glyph->root.outline );
+    return;
+  }
+
+
+/*******************************************************************
+ *
+ *  Function    :  Glyph_Create
+ *
+ *  Description :  The glyph object constructor.
+ *
+ *  Input  :  glyph   glyph record to build.
+ *            face    the glyph's parent face.
+ *
+ *  Output :  Error code.
+ *
+ ******************************************************************/
+
+  LOCAL_FUNC
+  FT_Error  T1_Init_GlyphSlot( T1_GlyphSlot  glyph )
+  {
+    FT_Library  library = glyph->root.face->driver->library;
+
+    glyph->max_points         = 0;
+    glyph->max_contours       = 0;
+    glyph->root.bitmap.buffer = 0;
+
+    return FT_Outline_New( library, 0, 0, &glyph->root.outline );
+  }
+
+
+/*******************************************************************
+ *
+ *  <Function>  T1_Init_Driver
+ *
+ *  <Description>
+ *     Initialise a given Type 1 driver object
+ *
+ *  <Input>
+ *     driver ::  handle to target driver object
+ *
+ *  <Return>
+ *     Error code.
+ *
+ ******************************************************************/
+
+  LOCAL_FUNC
+  FT_Error  T1_Init_Driver( T1_Driver  driver )
+  {
+    UNUSED(driver);
+    return T1_Err_Ok;
+  }
+
+
+
+/*******************************************************************
+ *
+ *  <Function> T1_Done_Driver
+ *
+ *  <Description>
+ *     finalise a given Type 1 driver
+ *
+ *  <Input>
+ *     driver  :: handle to target Type 1 driver
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  void  T1_Done_Driver( T1_Driver  driver )
+  {
+    UNUSED(driver);
+  }
+
+
+/* END */
--- /dev/null
+++ b/src/cid/cidobjs.h
@@ -1,0 +1,304 @@
+/*******************************************************************
+ *
+ *  t1objs.h                                                    1.0
+ *
+ *    Type1 objects definition.
+ *
+ *  Copyright 1996-1999 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 T1OBJS_H
+#define T1OBJS_H
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/config/ftconfig.h>
+#include <t1errors.h>
+#include <freetype/internal/t1types.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+  /* The following structures must be defined by the hinter */
+  typedef struct T1_Size_Hints_   T1_Size_Hints;
+  typedef struct T1_Glyph_Hints_  T1_Glyph_Hints;
+
+  /***********************************************************************/
+  /*                                                                     */
+  /* <Type> T1_Driver                                                    */
+  /*                                                                     */
+  /* <Description>                                                       */
+  /*    A handle to a Type 1 driver object.                              */
+  /*                                                                     */
+  typedef struct T1_DriverRec_   *T1_Driver;
+
+
+  /***********************************************************************/
+  /*                                                                     */
+  /* <Type> T1_Size                                                      */
+  /*                                                                     */
+  /* <Description>                                                       */
+  /*    A handle to a Type 1 size object.                                */
+  /*                                                                     */
+  typedef struct T1_SizeRec_*  T1_Size;
+
+
+  /***********************************************************************/
+  /*                                                                     */
+  /* <Type> T1_GlyphSlot                                                 */
+  /*                                                                     */
+  /* <Description>                                                       */
+  /*    A handle to a Type 1 glyph slot object.                          */
+  /*                                                                     */
+  typedef struct T1_GlyphSlotRec_*  T1_GlyphSlot;
+
+
+  /***********************************************************************/
+  /*                                                                     */
+  /* <Type> T1_CharMap                                                   */
+  /*                                                                     */
+  /* <Description>                                                       */
+  /*    A handle to a Type 1 character mapping object.                   */
+  /*                                                                     */
+  /* <Note>                                                              */
+  /*    The Type 1 format doesn't use a charmap but an encoding table.   */
+  /*    The driver is responsible for making up charmap objects          */
+  /*    corresponding to these tables..                                  */
+  /*                                                                     */
+  typedef struct T1_CharMapRec_*   T1_CharMap;
+
+
+
+ /**************************************************************************/
+ /*                                                                        */
+ /*    NOW BEGINS THE TYPE1 SPECIFIC STUFF ..............................  */
+ /*                                                                        */
+ /**************************************************************************/
+
+
+  /***************************************************/
+  /*                                                 */
+  /*  T1_Size :                                      */
+  /*                                                 */
+  /*    Type 1 size record..                         */
+  /*                                                 */
+
+  typedef struct T1_SizeRec_
+  {
+    FT_SizeRec      root;
+    T1_Bool         valid;
+    T1_Size_Hints*  hints;  /* defined in the hinter. This allows */
+                            /* us to experiment with different    */
+                            /* hinting schemes without having to  */
+                            /* change 't1objs' each time..        */
+  } T1_SizeRec;
+
+
+
+  /***************************************************/
+  /*                                                 */
+  /*  T1_GlyphSlot :                                 */
+  /*                                                 */
+  /*    TrueDoc glyph record..                       */
+  /*                                                 */
+
+  typedef struct T1_GlyphSlotRec_
+  {
+    FT_GlyphSlotRec  root;
+
+    T1_Bool          hint;
+    T1_Bool          scaled;
+
+    FT_Int           max_points;
+    FT_Int           max_contours;
+
+    FT_Fixed         x_scale;
+    FT_Fixed         y_scale;
+
+    T1_Glyph_Hints*  hints;  /* defined in the hinter */
+
+  } T1_GlyphSlotRec;
+
+
+/*******************************************************************
+ *
+ *  <Function>  T1_Init_Face
+ *
+ *  <Description>
+ *     Initialise a given Type 1 face object
+ *
+ *  <Input>
+ *     face_index :: index of font face in resource
+ *     resource   :: source font resource
+ *     face       ::  face record to build
+ *
+ *  <Return>
+ *     Error code.
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  FT_Error  T1_Init_Face( FT_Stream     stream,
+                          CID_Face      face,
+                          FT_Int        face_index,
+                          FT_Int        num_params,
+                          FT_Parameter* params );
+
+
+
+/*******************************************************************
+ *
+ *  <Function> T1_Done_Face
+ *
+ *  <Description>
+ *     Finalise a given face object
+ *
+ *  <Input>
+ *     face  :: handle  to the face object to destroy
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  void  T1_Done_Face( CID_Face  face );
+
+
+
+/*******************************************************************
+ *
+ *  <Function> T1_Init_Size
+ *
+ *  <Description>
+ *     Initialise a new Type 1 size object
+ *
+ *  <Input>
+ *     size  :: handle to size object
+ *
+ *  <Return>
+ *     Type 1 error code. 0 means success.
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  FT_Error  T1_Init_Size( T1_Size  size );
+
+
+
+/*******************************************************************
+ *
+ * <Function>  T1_Done_Size
+ *
+ * <Description>
+ *    The Type 1 size object finaliser.
+ *
+ * <Input>
+ *    size   :: handle to the target size object.
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  void  T1_Done_Size( T1_Size  size );
+
+
+/*******************************************************************
+ *
+ * <Function>  T1_Reset_Size
+ *
+ * <Description>
+ *    Reset a Type 1 size when resolutions and character dimensions
+ *    have been changed..
+ *
+ * <Input>
+ *    size   :: handle to the target size object.
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  FT_Error  T1_Reset_Size( T1_Size  size );
+
+
+
+/*******************************************************************
+ *
+ *  <Function> T1_Init_GlyphSlot
+ *
+ *  <Description> The TrueType glyph slot initialiser
+ *
+ *  <Input>  glyph ::  glyph record to build.
+ *
+ *  <Output> Error code.
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  FT_Error  T1_Init_GlyphSlot( T1_GlyphSlot  slot );
+
+
+
+/*******************************************************************
+ *
+ *  <Function> T1_Done_GlyphSlot
+ *
+ *  <Description> The Type 1 glyph slot finaliser
+ *
+ *  <Input>  glyph  :: handle to glyph slot object
+ *
+ *  <Output>  Error code.
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  void  T1_Done_GlyphSlot( T1_GlyphSlot  slot );
+
+
+
+/*******************************************************************
+ *
+ *  <Function>  T1_Init_Driver
+ *
+ *  <Description>
+ *     Initialise a given Type 1 driver object
+ *
+ *  <Input>
+ *     driver ::  handle to target driver object
+ *
+ *  <Return>
+ *     Error code.
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  FT_Error  T1_Init_Driver( T1_Driver  driver );
+
+
+
+/*******************************************************************
+ *
+ *  <Function> T1_Done_Driver
+ *
+ *  <Description>
+ *     finalise a given Type 1 driver
+ *
+ *  <Input>
+ *     driver  :: handle to target Type 1 driver
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  void  T1_Done_Driver( T1_Driver  driver );
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* T1OBJS_H */
+
+
+/* END */
--- /dev/null
+++ b/src/cid/cidparse.c
@@ -1,0 +1,936 @@
+/*******************************************************************
+ *
+ *  cidparse.c                                                   2.0
+ *
+ *    CID-keyed Type1 parser.
+ *
+ *  Copyright 1996-1998 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.
+ *
+ *  The Type 1 parser is in charge of the following:
+ *
+ *   - provide an implementation of a growing sequence of
+ *     objects called a T1_Table (used to build various tables
+ *     needed by the loader).
+ *
+ *   - opening .pfb and .pfa files to extract their top-level
+ *     and private dictionaries
+ *
+ *   - read numbers, arrays & strings from any dictionary
+ *
+ *  See "t1load.c" to see how data is loaded from the font file
+ *
+ ******************************************************************/
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftstream.h>
+#include <t1errors.h>
+#include <cidparse.h>
+
+#undef FT_COMPONENT
+#define FT_COMPONENT  trace_t1load
+
+#if 0
+/*************************************************************************/
+/*************************************************************************/
+/*************************************************************************/
+/*****                                                               *****/
+/*****           IMPLEMENTATION OF T1_TABLE OBJECT                   *****/
+/*****                                                               *****/
+/*****                                                               *****/
+/*************************************************************************/
+/*************************************************************************/
+/*************************************************************************/
+
+
+/*************************************************************************/
+/*                                                                       */
+/* <Function> T1_New_Table                                               */
+/*                                                                       */
+/* <Description>                                                         */
+/*    Initialise a T1_Table.                                             */
+/*                                                                       */
+/* <Input>                                                               */
+/*    table  :: address of target table                                  */
+/*    count  :: table size = maximum number of elements                  */
+/*    memory :: memory object to use for all subsequent reallocations    */
+/*                                                                       */
+/* <Return>                                                              */
+/*    Error code. 0 means success                                        */
+/*                                                                       */
+
+  LOCAL_FUNC
+  FT_Error  T1_New_Table( T1_Table*  table,
+                          FT_Int     count,
+                          FT_Memory  memory )
+  {
+	 FT_Error  error;
+
+	 table->memory = memory;
+	 if ( ALLOC_ARRAY( table->elements, count, FT_Byte*  ) ||
+          ALLOC_ARRAY( table->lengths, count, FT_Byte* ) )
+       goto Exit;
+
+	table->max_elems = count;
+    table->init      = 0xdeadbeef;
+	table->num_elems = 0;
+	table->block     = 0;
+	table->capacity  = 0;
+	table->cursor    = 0;
+
+  Exit:
+    if (error) FREE(table->elements);
+
+	return error;
+  }
+
+
+
+/*************************************************************************/
+/*                                                                       */
+/* <Function> T1_Add_Table                                               */
+/*                                                                       */
+/* <Description>                                                         */
+/*    Adds an object to a T1_Table, possibly growing its memory block    */
+/*                                                                       */
+/* <Input>                                                               */
+/*    table  :: target table                                             */
+/*    index  :: index of object in table                                 */
+/*    object :: address of object to copy in memory                      */
+/*    length :: length in bytes of source object                         */
+/*                                                                       */
+/* <Return>                                                              */
+/*    Error code. 0 means success. An error is returned when a           */
+/*    realloc failed..                                                   */
+/*                                                                       */
+
+
+      static void  shift_elements( T1_Table*  table, FT_Byte*  old_base )
+      {
+        FT_Long    delta  = table->block - old_base;
+        FT_Byte**  offset = table->elements;
+        FT_Byte**  limit  = offset + table->max_elems;
+
+        if (delta)
+          for ( ; offset < limit; offset++ )
+          {
+            if (offset[0])
+              offset[0] += delta;
+          }
+      }
+
+      static
+      FT_Error  reallocate_t1_table( T1_Table*  table,
+                                     FT_Int     new_size )
+      {
+        FT_Memory  memory   = table->memory;
+        FT_Byte*   old_base = table->block;
+        FT_Error   error;
+
+        /* realloc the base block */
+        if ( REALLOC( table->block, table->capacity, new_size ) )
+          return error;
+
+        table->capacity = new_size;
+
+        /* shift all offsets when needed */
+        if (old_base)
+          shift_elements( table, old_base );
+
+        return T1_Err_Ok;
+      }
+
+
+
+  LOCAL_FUNC
+  FT_Error  T1_Add_Table( T1_Table*  table,
+                          FT_Int     index,
+                          void*      object,
+                          FT_Int     length )
+  {
+	if (index < 0 || index > table->max_elems)
+    {
+	  FT_ERROR(( "T1.Add_Table: invalid index\n" ));
+	  return T1_Err_Syntax_Error;
+    }
+
+    /* grow the base block if needed */
+    if ( table->cursor + length > table->capacity )
+    {
+      FT_Error  error;
+      FT_Int    new_size = table->capacity;
+
+      while ( new_size < table->cursor+length )
+        new_size += 1024;
+
+      error = reallocate_t1_table( table, new_size );
+      if (error) return error;
+    }
+
+    /* add the object to the base block and adjust offset */
+    table->elements[ index ] = table->block + table->cursor;
+    table->lengths [ index ] = length;
+    MEM_Copy( table->block + table->cursor, object, length );
+
+    table->cursor += length;
+    return T1_Err_Ok;
+  }
+
+
+/*************************************************************************/
+/*                                                                       */
+/* <Function> T1_Done_Table                                              */
+/*                                                                       */
+/* <Description>                                                         */
+/*    Finalise a T1_Table. (realloc it to its current cursor).           */
+/*                                                                       */
+/* <Input>                                                               */
+/*    table :: target table                                              */
+/*                                                                       */
+/* <Note>                                                                */
+/*    This function does NOT release the heap's memory block. It is up   */
+/*    to the caller to clean it, or reference it in its own structures.  */
+/*                                                                       */
+#if 0
+  LOCAL_FUNC
+  void  T1_Done_Table( T1_Table*  table )
+  {
+    FT_Memory  memory = table->memory;
+    FT_Error   error;
+    FT_Byte*   old_base;
+
+    /* should never fail, as rec.cursor <= rec.size */
+    old_base = table->block;
+    if (!old_base)
+      return;
+
+    (void)REALLOC( table->block, table->capacity, table->cursor );
+    table->capacity = table->cursor;
+
+    if (old_base != table->block)
+      shift_elements( table, old_base );
+  }
+#endif
+
+  LOCAL_FUNC
+  void  T1_Release_Table( T1_Table*  table )
+  {
+    FT_Memory  memory = table->memory;
+
+    if (table->init == (FT_Long)0xdeadbeef)
+    {
+      FREE( table->block );
+      FREE( table->elements );
+      FREE( table->lengths );
+      table->init = 0;
+    }
+  }
+
+#endif
+
+/*************************************************************************/
+/*************************************************************************/
+/*************************************************************************/
+/*****                                                               *****/
+/*****               INPUT STREAM PARSER                             *****/
+/*****                                                               *****/
+/*****                                                               *****/
+/*************************************************************************/
+/*************************************************************************/
+/*************************************************************************/
+
+  #define IS_T1_WHITESPACE(c)  ( (c) == ' '  || (c) == '\t' )
+  #define IS_T1_LINESPACE(c)   ( (c) == '\r' || (c) == '\n' )
+
+  #define IS_T1_SPACE(c)  ( IS_T1_WHITESPACE(c) || IS_T1_LINESPACE(c) )
+
+  LOCAL_FUNC
+  void     CID_Skip_Spaces( CID_Parser*  parser )
+  {
+    FT_Byte* cur   = parser->cursor;
+    FT_Byte* limit = parser->limit;
+
+    while (cur < limit)
+    {
+      FT_Byte  c = *cur;
+      if (!IS_T1_SPACE(c))
+        break;
+      cur++;
+    }
+    parser->cursor = cur;
+  }
+
+  LOCAL_FUNC
+  void  CID_ToToken( CID_Parser*    parser,
+                     T1_Token_Rec*  token )
+  {
+    FT_Byte*  cur;
+    FT_Byte*  limit;
+    FT_Byte   starter, ender;
+    FT_Int    embed;
+
+    token->type  = t1_token_none;
+    token->start = 0;
+    token->limit = 0;
+
+    /* first of all, skip space */
+    CID_Skip_Spaces(parser);
+
+    cur   = parser->cursor;
+    limit = parser->limit;
+
+    if ( cur < limit )
+    {
+      switch (*cur)
+      {
+        /************* check for strings ***********************/
+        case '(':
+          token->type = t1_token_string;
+          ender = ')';
+          goto Lookup_Ender;
+
+        /************* check for programs/array ****************/
+        case '{':
+          token->type = t1_token_array;
+          ender = '}';
+          goto Lookup_Ender;
+
+        /************* check for table/array ******************/
+        case '[':
+          token->type = t1_token_array;
+          ender = ']';
+
+        Lookup_Ender:
+          embed   = 1;
+          starter = *cur++;
+          token->start = cur;
+          while (cur < limit)
+          {
+            if (*cur == starter)
+              embed++;
+            else if (*cur == ender)
+            {
+              embed--;
+              if (embed <= 0)
+              {
+                token->limit = cur++;
+                break;
+              }
+            }
+            cur++;
+          }
+          break;
+
+        /* **************** otherwise, it's any token **********/
+        default:
+          token->start = cur++;
+          token->type  = t1_token_any;
+          while (cur < limit && !IS_T1_SPACE(*cur))
+            cur++;
+
+          token->limit = cur;
+      }
+
+      if (!token->limit)
+      {
+        token->start = 0;
+        token->type  = t1_token_none;
+      }
+
+      parser->cursor = cur;
+    }
+  }
+
+
+  LOCAL_FUNC
+  void  CID_ToTokenArray( CID_Parser*    parser,
+                          T1_Token_Rec*  tokens,
+                          FT_UInt        max_tokens,
+                          FT_Int        *pnum_tokens )
+  {
+    T1_Token_Rec  master;
+
+    *pnum_tokens = -1;
+
+    CID_ToToken( parser, &master );
+    if (master.type == t1_token_array)
+    {
+      FT_Byte*       old_cursor = parser->cursor;
+      FT_Byte*       old_limit  = parser->limit;
+      T1_Token_Rec*  cur        = tokens;
+      T1_Token_Rec*  limit      = cur + max_tokens;
+
+      parser->cursor = master.start;
+      parser->limit  = master.limit;
+
+      while (parser->cursor < parser->limit)
+      {
+        T1_Token_Rec  token;
+        
+        CID_ToToken( parser, &token );
+        if (!token.type)
+          break;
+          
+        if (cur < limit)
+          *cur = token;
+          
+        cur++;
+      }
+
+      *pnum_tokens = cur - tokens;
+
+      parser->cursor = old_cursor;
+      parser->limit  = old_limit;
+    }
+  }
+
+
+  static
+  FT_Long  t1_toint( FT_Byte* *cursor,
+                     FT_Byte*  limit )
+  {
+    FT_Long  result = 0;
+    FT_Byte* cur    = *cursor;
+    FT_Byte  c, d;
+
+    for (; cur < limit; cur++)
+    {
+      c = *cur;
+      d = (FT_Byte)(c - '0');
+      if (d < 10) break;
+
+      if ( c=='-' )
+      {
+        cur++;
+        break;
+      }
+    }
+
+    if (cur < limit)
+    {
+      do
+      {
+        d = (FT_Byte)(cur[0] - '0');
+        if (d >= 10)
+          break;
+
+        result = result*10 + d;
+        cur++;
+
+      } while (cur < limit);
+
+      if (c == '-')
+        result = -result;
+    }
+
+    *cursor = cur;
+    return result;
+  }
+
+
+  static
+  FT_Long  t1_tofixed( FT_Byte* *cursor,
+                       FT_Byte*  limit,
+                       FT_Long   power_ten )
+  {
+    FT_Byte* cur    = *cursor;
+    FT_Long  num, divider, result;
+    FT_Int   sign   = 0;
+    FT_Byte  d;
+
+    if (cur >= limit) return 0;
+
+    /* first of all, read the integer part */
+    result  = t1_toint( &cur, limit ) << 16;
+    num     = 0;
+    divider = 1;
+
+    if (result < 0)
+    {
+      sign   = 1;
+      result = -result;
+    }
+    if (cur >= limit) goto Exit;
+
+    /* read decimal part, if any */
+    if (*cur == '.' && cur+1 < limit)
+    {
+      cur++;
+
+      for (;;)
+      {
+        d = (FT_Byte)(*cur - '0');
+        if (d >= 10) break;
+
+        if (divider < 10000000L)
+        {
+          num      = num*10 + d;
+          divider *= 10;
+        }
+        cur++;
+        if (cur >= limit) break;
+      }
+    }
+
+    /* read exponent, if any */
+    if ( cur+1 < limit && (*cur == 'e' || *cur == 'E'))
+    {
+      cur++;
+      power_ten += t1_toint( &cur, limit );
+    }
+
+  Exit:
+    /* raise to power of ten if needed */
+    while (power_ten > 0)
+    {
+      result = result*10;
+      num    = num*10;
+      power_ten--;
+    }
+
+    while (power_ten < 0)
+    {
+      result  = result/10;
+      divider = divider*10;
+      power_ten++;
+    }
+
+    if (num)
+      result += FT_DivFix( num, divider );
+
+    if (sign)
+      result = -result;
+
+    *cursor = cur;
+    return result;
+  }
+
+
+  static
+  int  t1_tobool( FT_Byte* *cursor, FT_Byte* limit )
+  {
+    FT_Byte*  cur    = *cursor;
+    T1_Bool   result = 0;
+
+    /* return 1 if we find a "true", 0 otherwise */
+    if ( cur+3 < limit &&
+         cur[0] == 't' &&
+         cur[1] == 'r' &&
+         cur[2] == 'u' &&
+         cur[3] == 'e' )
+    {
+      result = 1;
+      cur   += 5;
+    }
+    else if ( cur+4 < limit &&
+              cur[0] == 'f' &&
+              cur[1] == 'a' &&
+              cur[2] == 'l' &&
+              cur[3] == 's' &&
+              cur[4] == 'e' )
+    {
+      result = 0;
+      cur   += 6;
+    }
+    *cursor = cur;
+    return result;
+  }
+
+
+  static
+  FT_Int  t1_tocoordarray( FT_Byte*  *cursor,
+                           FT_Byte*   limit,
+                           FT_Int     max_coords,
+                           FT_Short*  coords )
+  {
+    FT_Byte*  cur   = *cursor;
+    FT_Int    count = 0;
+    FT_Byte   c, ender;
+
+    if (cur >= limit) goto Exit;
+
+    /* check for the beginning of an array. If not, only one number will be read */
+    c     = *cur;
+    ender = 0;
+
+    if (c == '[')
+      ender = ']';
+
+    if (c == '{')
+      ender = '}';
+
+    if (ender)
+      cur++;
+
+    /* now, read the coordinates */
+    for ( ; cur < limit; )
+    {
+      /* skip whitespace in front of data */
+      for (;;)
+      {
+        c = *cur;
+        if ( c != ' ' && c != '\t' ) break;
+
+        cur++;
+        if (cur >= limit) goto Exit;
+      }
+
+      if (count >= max_coords || c == ender)
+        break;
+
+      coords[count] = (T1_Short)(t1_tofixed(&cur,limit,0) >> 16);
+      count++;
+
+      if (!ender)
+        break;
+    }
+
+  Exit:
+    *cursor = cur;
+    return count;
+  }
+
+
+
+  static
+  FT_Int  t1_tofixedarray( FT_Byte*  *cursor,
+                           FT_Byte*   limit,
+                           FT_Int     max_values,
+                           FT_Fixed*  values,
+                           FT_Int     power_ten )
+  {
+    FT_Byte*  cur   = *cursor;
+    FT_Int    count = 0;
+    FT_Byte   c, ender;
+
+    if (cur >= limit) goto Exit;
+
+    /* check for the beginning of an array. If not, only one number will be read */
+    c     = *cur;
+    ender = 0;
+
+    if (c == '[')
+      ender = ']';
+
+    if (c == '{')
+      ender = '}';
+
+    if (ender)
+      cur++;
+
+    /* now, read the values */
+    for ( ; cur < limit; )
+    {
+      /* skip whitespace in front of data */
+      for (;;)
+      {
+        c = *cur;
+        if ( c != ' ' && c != '\t' ) break;
+
+        cur++;
+        if (cur >= limit) goto Exit;
+      }
+
+      if (count >= max_values || c == ender)
+        break;
+
+      values[count] = t1_tofixed(&cur,limit,power_ten);
+      count++;
+
+      if (!ender)
+        break;
+    }
+
+  Exit:
+    *cursor = cur;
+    return count;
+  }
+
+
+
+ /* Loads a simple field (i.e. non-table) into the current list of objects */
+  LOCAL_FUNC
+  FT_Error  CID_Load_Field( CID_Parser*          parser,
+                            const T1_Field_Rec*  field,
+                            void*                object )
+  {
+    T1_Token_Rec  token;
+    FT_Byte*      cur;
+    FT_Byte*      limit;
+    FT_UInt       count;
+    FT_UInt       index;
+    FT_Error      error;
+
+    CID_ToToken( parser, &token );
+    if (!token.type)
+      goto Fail;
+
+    count = 1;
+    index = 0;
+    cur   = token.start;
+    limit = token.limit;
+
+    {
+      FT_Byte*   q = (FT_Byte*)object + field->offset;
+      FT_Long    val;
+      T1_String* string;
+
+      switch (field->type)
+      {
+        case t1_field_bool:
+          {
+            val = t1_tobool( &cur, limit );
+            goto Store_Integer;
+          }
+
+        case t1_field_fixed:
+          {
+            val = t1_tofixed( &cur, limit, 0 );
+            goto Store_Integer;
+          }
+
+        case t1_field_integer:
+          {
+            val = t1_toint( &cur, limit );
+          Store_Integer:
+            switch (field->size)
+            {
+              case 1:  *(FT_Byte*)  q = (FT_Byte)val;   break;
+              case 2:  *(FT_UShort*)q = (FT_UShort)val; break;
+              default: *(FT_Long*)  q = val;
+            }
+          }
+          break;
+
+        case t1_field_string:
+          {
+            FT_Memory  memory = parser->memory;
+            FT_UInt    len    = limit-cur;
+            
+            if ( ALLOC( string, len+1 ) )
+              goto Exit;
+              
+            MEM_Copy( string, cur, len );
+            string[len] = 0;              
+
+            *(T1_String**)q = string;
+          }
+          break;
+          
+        default:
+          /* an error occured */
+          goto Fail;
+      }
+    }
+    error    = 0;
+
+  Exit:
+    return error;
+  Fail:
+    error = T1_Err_Invalid_File_Format;
+    goto Exit;
+  }
+
+
+#define CID_MAX_TABLE_ELEMENTS  32
+
+  LOCAL_FUNC
+  FT_Error  CID_Load_Field_Table( CID_Parser*          parser,
+                                  const T1_Field_Rec*  field,
+                                  void*                object )
+  {
+    T1_Token_Rec  elements[CID_MAX_TABLE_ELEMENTS];
+    T1_Token_Rec* token;
+    FT_Int        num_elements;
+    FT_Error      error = 0;
+    FT_Byte*      old_cursor;
+    FT_Byte*      old_limit;
+    T1_Field_Rec  fieldrec = *(T1_Field_Rec*)field;
+
+    fieldrec.type = t1_field_integer;
+    if (field->type == t1_field_fixed_array )
+      fieldrec.type = t1_field_fixed;    
+      
+    CID_ToTokenArray( parser, elements, 32, &num_elements );
+    if (num_elements < 0)
+      goto Fail;
+
+    if (num_elements > CID_MAX_TABLE_ELEMENTS)
+      num_elements = CID_MAX_TABLE_ELEMENTS;
+
+    old_cursor = parser->cursor;
+    old_limit  = parser->limit;
+
+    /* we store the elements count */
+    if (field->count_offset)
+      *(FT_Byte*)((FT_Byte*)object + field->count_offset) = num_elements;
+
+    /* we now load each element, adjusting the field.offset on each one */
+    token = elements;
+    for ( ; num_elements > 0; num_elements--, token++ )
+    {
+      parser->cursor = token->start;
+      parser->limit  = token->limit;
+      CID_Load_Field( parser, &fieldrec, object );
+      fieldrec.offset += fieldrec.size;
+    }
+
+    parser->cursor = old_cursor;
+    parser->limit  = old_limit;
+
+  Exit:
+    return error;
+  Fail:
+    error = T1_Err_Invalid_File_Format;
+    goto Exit;
+  }
+
+
+
+
+
+
+
+  LOCAL_FUNC
+  FT_Long  CID_ToInt  ( CID_Parser*  parser )
+  {
+    return t1_toint( &parser->cursor, parser->limit );
+  }
+
+
+  LOCAL_FUNC
+  FT_Int  CID_ToCoordArray( CID_Parser* parser,
+                            FT_Int      max_coords,
+                            FT_Short*   coords )
+  {
+    return t1_tocoordarray( &parser->cursor, parser->limit, max_coords, coords );
+  }
+
+
+  LOCAL_FUNC
+  FT_Int  CID_ToFixedArray( CID_Parser* parser,
+                            FT_Int      max_values,
+                            FT_Fixed*   values,
+                            FT_Int      power_ten )
+  {
+    return t1_tofixedarray( &parser->cursor, parser->limit, max_values, values, power_ten );
+  }
+
+
+#if 0
+ /* return the value of an hexadecimal digit */
+ static
+ int  hexa_value( char c )
+ {
+   unsigned int  d;
+
+   d = (unsigned int)(c-'0');
+   if ( d <= 9 ) return (int)d;
+
+   d = (unsigned int)(c-'a');
+   if ( d <= 5 ) return (int)(d+10);
+
+   d = (unsigned int)(c-'A');
+   if ( d <= 5 ) return (int)(d+10);
+
+   return -1;
+ }
+#endif
+
+
+  LOCAL_FUNC
+  FT_Error  CID_New_Parser( CID_Parser*  parser,
+                            FT_Stream    stream,
+                            FT_Memory    memory )
+  {
+    FT_Error  error;
+    FT_ULong  base_offset, offset, ps_len;
+    FT_Byte   buffer[ 256 + 10 ];
+    FT_Int    buff_len;
+
+    MEM_Set( parser, 0, sizeof(*parser ) );
+    parser->stream = stream;
+    parser->memory = memory;
+
+    base_offset = FILE_Pos();
+
+    /* first of all, check the font format in the  header */
+    if ( ACCESS_Frame(31) )
+      goto Exit;
+
+    if ( strncmp( stream->cursor, "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) )
+    {
+      FT_ERROR(( "Not a valid CID-keyed font\n" ));
+      error = FT_Err_Unknown_File_Format;
+    }
+
+    FORGET_Frame();
+    if (error) goto Exit;
+
+    /* now, read the rest of the file, until we find a "StartData" */
+    buff_len = 256;
+    for (;;)
+    {
+      FT_Byte *p, *limit = buffer + 256;
+      
+      /* fill input buffer */
+      buff_len -= 256;
+      if (buff_len > 0)
+        MEM_Move( buffer, limit, buff_len );
+        
+      if ( FILE_Read( buffer, 256+10-buff_len ) )
+        goto Exit;
+      
+      buff_len = 256+10;
+      
+      /* look for "StartData" */
+      for ( p = buffer; p < limit; p++ )
+      {
+        if ( p[0] == 'S' && strncmp( (char*)p, "StartData", 9 ) == 0 )
+        {
+          /* save offset of binary data after "StartData" */
+          offset = FILE_Pos() - ( limit-p ) + 10;
+          goto Found;
+        }
+      }
+    }
+    
+  Found:
+    /* all right, we found the start of the binary data. We will now rewind */
+    /* and extract the frame of corresponding to the Postscript section     */
+    ps_len = offset - base_offset;
+    if ( FILE_Seek( base_offset )                    ||
+         EXTRACT_Frame( ps_len, parser->postscript ) )
+      goto Exit;
+
+    parser->data_offset    = offset;
+    parser->postscript_len = ps_len;
+    parser->cursor         = parser->postscript;
+    parser->limit          = parser->cursor + ps_len;
+    parser->num_dict       = -1;
+
+  Exit:
+    return error;   
+  }
+    
+
+
+  LOCAL_FUNC
+  void  CID_Done_Parser( CID_Parser*  parser )
+  {
+    /* always free the private dictionary */
+    if (parser->postscript)
+    {
+      FT_Stream  stream = parser->stream;
+      RELEASE_Frame( parser->postscript );
+    }
+  }
+
--- /dev/null
+++ b/src/cid/cidparse.h
@@ -1,0 +1,347 @@
+/*******************************************************************
+ *
+ *  cidparse.h                                                   2.0
+ *
+ *    CID-Keyed Type1 parser.
+ *
+ *  Copyright 1996-1998 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.
+ *
+ *  The Type 1 parser is in charge of the following:
+ *
+ *   - provide an implementation of a growing sequence of
+ *     objects called a T1_Table (used to build various tables
+ *     needed by the loader).
+ *
+ *   - opening .pfb and .pfa files to extract their top-level
+ *     and private dictionaries
+ *
+ *   - read numbers, arrays & strings from any dictionary
+ *
+ *  See "t1load.c" to see how data is loaded from the font file
+ *
+ ******************************************************************/
+
+#ifndef CIDPARSE_H
+#define CIDPARSE_H
+
+#include <freetype/internal/t1types.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+  
+
+#if 0
+/*************************************************************************
+ *
+ * <Struct> T1_Table
+ *
+ * <Description>
+ *    A T1_Table is a simple object used to store an array of objects
+ *    in a single memory block.
+ *
+ * <Fields>
+ *    block     :: address in memory of the growheap's block. This
+ *                 can change between two object adds, due to the use
+ *                 of 'realloc'.
+ *
+ *    cursor    :: current top of the grow heap within its block
+ *
+ *    capacity  :: current size of the heap block. Increments by 1 Kb
+ *
+ *    init      :: boolean. set when the table has been initialized
+ *                 (the table user should set this field)
+ *
+ *    max_elems :: maximum number of elements in table
+ *    num_elems :: current number of elements in table
+ *
+ *    elements  :: table of element addresses within the block
+ *    lengths   :: table of element sizes within the block
+ *
+ *    memory    :: memory object used for memory operations (alloc/realloc)
+ */
+
+  typedef struct T1_Table_
+  {
+    FT_Byte*   block;          /* current memory block           */
+    FT_Int     cursor;         /* current cursor in memory block */
+    FT_Int     capacity;       /* current size of memory block   */
+    FT_Long    init;
+
+    FT_Int     max_elems;
+    FT_Int     num_elems;
+    FT_Byte**  elements;       /* addresses of table elements */
+    FT_Int*    lengths;        /* lengths of table elements   */
+
+    FT_Memory  memory;
+
+  } T1_Table;
+
+
+  LOCAL_DEF
+  FT_Error  T1_New_Table( T1_Table*  table,
+                          FT_Int     count,
+                          FT_Memory  memory );
+
+
+  LOCAL_DEF
+  FT_Error  T1_Add_Table( T1_Table*  table,
+                          FT_Int     index,
+                          void*      object,
+                          FT_Int     length );
+
+  LOCAL_DEF
+  void  T1_Release_Table( T1_Table*  table );
+#endif
+
+/*************************************************************************
+ *
+ * <Struct> CID_Parser
+ *
+ * <Description>
+ *    A CID_Parser is an object used to parse a Type 1 fonts very
+ *    quickly.
+ *
+ * <Fields>
+ *    stream        :: current input stream
+ *    memory        :: current memory object
+ *
+ *    base_dict     :: pointer to top-level dictionary
+ *    base_len      :: length in bytes of top dict
+ *
+ *    private_dict  :: pointer to private dictionary
+ *    private_len   :: length in bytes of private dict
+ *
+ *    in_pfb        :: boolean. Indicates that we're in a .pfb file
+ *    in_memory     :: boolean. Indicates a memory-based stream
+ *    single_block  :: boolean. Indicates that the private dict
+ *                     is stored in lieu of the base dict
+ *
+ *    cursor        :: current parser cursor
+ *    limit         :: current parser limit (first byte after current
+ *                     dictionary).
+ *
+ *    error         :: current parsing error
+ */
+
+  typedef struct CID_Parser_
+  {
+    FT_Stream  stream;
+    FT_Memory  memory;
+
+    FT_Byte*   postscript;
+    FT_Int     postscript_len;
+
+    FT_ULong   data_offset;
+
+    FT_Byte*   cursor;
+    FT_Byte*   limit;
+    FT_Error   error;
+
+    CID_Info*  cid;
+    FT_Int     num_dict;
+
+  } CID_Parser;
+
+
+  LOCAL_DEF
+  FT_Error  CID_New_Parser( CID_Parser*  parser,
+                            FT_Stream    stream,
+                            FT_Memory    memory );
+
+  LOCAL_DEF
+  void  CID_Done_Parser( CID_Parser*  parser );
+
+
+ /*************************************************************************
+  *
+  *     PARSING ROUTINES
+  *
+  *************************************************************************/
+
+  LOCAL_DEF
+  FT_Long  CID_ToInt  ( CID_Parser*  parser );
+
+  LOCAL_DEF
+  FT_Int  CID_ToCoordArray( CID_Parser* parser,
+                            FT_Int     max_coords,
+                            FT_Short*  coords );
+
+  LOCAL_DEF
+  FT_Int  CID_ToFixedArray( CID_Parser* parser,
+                            FT_Int     max_values,
+                            T1_Fixed*  values,
+                            FT_Int     power_ten );
+
+  LOCAL_DEF
+  void      CID_Skip_Spaces( CID_Parser*  parser );
+
+
+
+  /* simple enumeration type used to identify token types */
+  typedef enum T1_Token_Type_
+  {
+    t1_token_none = 0,
+    t1_token_any,
+    t1_token_string,
+    t1_token_array,
+    
+    /* do not remove */
+    t1_token_max
+    
+  } T1_Token_Type;
+
+  /* a simple structure used to identify tokens */
+  typedef struct T1_Token_Rec_
+  {
+    FT_Byte*       start;   /* first character of token in input stream */
+    FT_Byte*       limit;   /* first character after the token          */
+    T1_Token_Type  type;    /* type of token..                          */
+  
+  } T1_Token_Rec;  
+
+
+  LOCAL_DEF
+  void      CID_ToToken( CID_Parser*    parser,
+                        T1_Token_Rec* token );
+
+
+
+
+
+
+
+  /* enumeration type used to identify object fields */
+  typedef enum T1_Field_Type_
+  {
+    t1_field_none = 0,
+    t1_field_bool,
+    t1_field_integer,
+    t1_field_fixed,
+    t1_field_string,
+    t1_field_integer_array,
+    t1_field_fixed_array,
+    t1_field_callback,
+        
+    /* do not remove */
+    t1_field_max
+    
+  } T1_Field_Type;
+
+  typedef enum T1_Field_Location_
+  {
+    t1_field_cid_info,
+    t1_field_font_dict,
+    t1_field_font_info,
+    t1_field_private,
+    
+    /* do not remove */
+    t1_field_location_max
+  
+  } T1_Field_Location;
+
+
+  typedef FT_Error  (*CID_Field_Parser)( CID_Face     face,
+                                         CID_Parser*  parser );
+
+  /* structure type used to model object fields */
+  typedef struct T1_Field_Rec_
+  {
+    const char*        ident;         /* field identifier                     */
+    T1_Field_Location  location;
+    T1_Field_Type      type;          /* type of field                        */
+    CID_Field_Parser   reader;
+    T1_UInt            offset;        /* offset of field in object            */
+    FT_UInt            size;          /* size of field in bytes               */
+    FT_UInt            array_max;     /* maximum number of elements for array */
+    FT_UInt            count_offset;  /* offset of element count for arrays   */
+   
+  } T1_Field_Rec;
+
+#define T1_FIELD_REF(s,f)  (((s*)0)->f)
+
+#define T1_NEW_SIMPLE_FIELD( _ident, _type, _fname )   \
+   { _ident, T1CODE, _type,                            \
+     0,                                                \
+     (FT_UInt)(char*)&T1_FIELD_REF(T1TYPE,_fname),     \
+     sizeof(T1_FIELD_REF(T1TYPE,_fname)),              \
+     0, 0 },
+
+#define T1_NEW_CALLBACK_FIELD( _ident, _reader )  \
+   { _ident, T1CODE, t1_field_callback,           \
+     _reader,                                     \
+     0, 0, 0, 0 },
+
+#define T1_NEW_TABLE_FIELD( _ident, _type, _fname, _max )   \
+   { _ident, T1CODE, _type,                                 \
+     0,                                                     \
+     (FT_UInt)(char*)&T1_FIELD_REF(T1TYPE,_fname),          \
+     sizeof(T1_FIELD_REF(T1TYPE,_fname)[0]),                \
+     _max,                                                  \
+     (FT_UInt)(char*)&T1_FIELD_REF(T1TYPE,num_ ## _fname) },
+
+#define T1_NEW_TABLE_FIELD2( _ident, _type, _fname, _max )   \
+   { _ident, T1CODE, _type,                                  \
+     0,                                                      \
+     (FT_UInt)(char*)&T1_FIELD_REF(T1TYPE,_fname),           \
+     sizeof(T1_FIELD_REF(T1TYPE,_fname)[0]),                 \
+     _max, 0 },
+
+
+#define T1_FIELD_BOOL( _ident, _fname )       \
+           T1_NEW_SIMPLE_FIELD( _ident, t1_field_bool, _fname )
+
+#define T1_FIELD_NUM( _ident, _fname )       \
+           T1_NEW_SIMPLE_FIELD( _ident, t1_field_integer, _fname )
+
+#define T1_FIELD_FIXED( _ident, _fname )       \
+           T1_NEW_SIMPLE_FIELD( _ident, t1_field_fixed, _fname )
+
+#define T1_FIELD_STRING( _ident, _fname )       \
+           T1_NEW_SIMPLE_FIELD( _ident, t1_field_string, _fname )
+
+#define T1_FIELD_NUM_TABLE( _ident, _fname, _fmax )   \
+           T1_NEW_TABLE_FIELD( _ident, t1_field_integer_array, _fname, _fmax )
+           
+#define T1_FIELD_FIXED_TABLE( _ident, _fname, _fmax )   \
+           T1_NEW_TABLE_FIELD( _ident, t1_field_fixed_array, _fname, _fmax )
+
+#define T1_FIELD_NUM_TABLE2( _ident, _fname, _fmax )  \
+           T1_NEW_TABLE_FIELD2( _ident, t1_field_integer_array, _fname, _fmax )
+
+#define T1_FIELD_FIXED_TABLE2( _ident, _fname, _fmax )   \
+           T1_NEW_TABLE_FIELD2( _ident, t1_field_fixed_array, _fname, _fmax )
+
+#define T1_FIELD_CALLBACK( _ident, _name )  \
+           T1_NEW_CALLBACK_FIELD( _ident, parse_ ## _name )
+
+  LOCAL_DEF
+  FT_Error  CID_Load_Field( CID_Parser*           parser,
+                            const T1_Field_Rec*  field,
+                            void*                object );
+
+  LOCAL_DEF
+  FT_Error  CID_Load_Field_Table( CID_Parser*           parser,
+                                  const T1_Field_Rec*  field,
+                                  void*                object );
+
+
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* CIDPARSE_H */
+
+
+/* END */
+
--- /dev/null
+++ b/src/cid/cidriver.c
@@ -1,0 +1,428 @@
+/*******************************************************************
+ *
+ *  t1driver.c
+ *
+ *    High-level Type1 driver interface for FreeType 2.0
+ *
+ *  Copyright 1996-1998 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.
+ *
+ ******************************************************************/
+
+#include <cidriver.h>
+#include <cidgload.h>
+#include <cidafm.h>
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/psnames.h>
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1driver
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Interface                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Each driver can provide one or more extensions to the base         */
+  /*    FreeType API.  These can be used to access format specific         */
+  /*    features (e.g., all TrueType/OpenType resources share a common     */
+  /*    file structure and common tables which can be accessed through the */
+  /*    `sfnt' interface), or more simply generic ones (e.g., the          */
+  /*    `postscript names' interface which can be used to retrieve the     */
+  /*     PostScript name of a given glyph index).                          */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    driver    :: A handle to a driver object.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    interface :: A string designing the interface.  Examples are       */
+  /*                 `sfnt', `post_names', `charmaps', etc.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A typeless pointer to the extension's interface (normally a table  */
+  /*    of function pointers).  Returns NULL if the requested extension    */
+  /*    isn't available (i.e., wasn't compiled in the driver at build      */
+  /*    time).                                                             */
+  /*                                                                       */
+  static
+  FTDriver_Interface  Get_Interface( FT_Driver         driver,
+                                     const FT_String*  interface )
+  {
+    UNUSED(driver);
+    UNUSED(interface);
+    
+    return 0;
+  }
+
+
+#ifdef xxxT1_CONFIG_OPTION_NO_AFM
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Kerning                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to return the kerning vector between two      */
+  /*    glyphs of the same face.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to the source face object.                 */
+  /*                                                                       */
+  /*    left_glyph  :: The index of the left glyph in the kern pair.       */
+  /*                                                                       */
+  /*    right_glyph :: The index of the right glyph in the kern pair.      */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    kerning     :: The kerning vector.  This is in font units for      */
+  /*                   scalable formats, and in pixels for fixed-sizes     */
+  /*                   formats.                                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only horizontal layouts (left-to-right & right-to-left) are        */
+  /*    supported by this function.  Other layouts, or more sophisticated  */
+  /*    kernings are out of scope of this method (the basic driver         */
+  /*    interface is meant to be simple).                                  */
+  /*                                                                       */
+  /*    They can be implemented by format-specific interfaces.             */
+  /*                                                                       */
+  static
+  FT_Error  Get_Kerning( T1_Face     face,
+                         FT_UInt     left_glyph,
+                         FT_UInt     right_glyph,
+                         T1_Vector*  kerning )
+  {
+    T1_AFM*  afm;
+
+    kerning->x = 0;
+    kerning->y = 0;
+
+    afm = (T1_AFM*)face->afm_data;
+    if (afm)
+      CID_Get_Kerning( afm, left_glyph, right_glyph, kerning );
+
+    return T1_Err_Ok;
+  }
+#endif
+
+  /******************************************************************/
+  /*                                                                */
+  /* <Function> Set_Char_Sizes                                      */
+  /*                                                                */
+  /* <Description>                                                  */
+  /*    A driver method used to reset a size's character sizes      */
+  /*    (horizontal and vertical) expressed in fractional points.   */
+  /*                                                                */
+  /* <Input>                                                        */
+  /*    size        :: handle to target size object                 */
+  /*    char_width  :: character width expressed in 26.6 points     */
+  /*    char_height :: character height expressed in 26.6 points    */
+  /*                                                                */
+  /* <Return>                                                       */
+  /*    FreeType error code. 0 means success                        */
+  /*                                                                */
+  static
+  FT_Error  Set_Char_Sizes( T1_Size      size,
+                            T1_F26Dot6   char_width,
+                            T1_F26Dot6   char_height,
+                            FT_UInt      horz_resolution,
+                            FT_UInt      vert_resolution )
+  {
+    UNUSED(char_width);
+    UNUSED(char_height);
+    UNUSED(horz_resolution);
+    UNUSED(vert_resolution);
+
+    size->valid = FALSE;
+    return T1_Reset_Size( size );
+  }
+
+
+  /******************************************************************/
+  /*                                                                */
+  /* <Function> Set_Pixel_Sizes                                     */
+  /*                                                                */
+  /* <Description>                                                  */
+  /*    A driver method used to reset a size's character sizes      */
+  /*    (horizontal and vertical) expressed in integer pixels.      */
+  /*                                                                */
+  /* <Input>                                                        */
+  /*    size         :: handle to target size object                */
+  /*                                                                */
+  /*    pixel_width  :: character width expressed in 26.6 points    */
+  /*                                                                */
+  /*    pixel_height :: character height expressed in 26.6 points   */
+  /*                                                                */
+  /*    char_size    :: the corresponding character size in points  */
+  /*                    This value is only sent to the TrueType     */
+  /*                    bytecode interpreter, even though 99% of    */
+  /*                    glyph programs will simply ignore it. A     */
+  /*                    safe value there is the maximum of the      */
+  /*                    pixel width and height (multiplied by       */
+  /*                    64 to make it a 26.6 fixed float !)         */
+  /* <Return>                                                       */
+  /*    FreeType error code. 0 means success                        */
+  /*                                                                */
+  static
+  FT_Error  Set_Pixel_Sizes( T1_Size     size,
+                             FT_Int      pixel_width,
+                             FT_Int      pixel_height )
+  {
+    UNUSED(pixel_width);
+    UNUSED(pixel_height);
+
+    size->valid = FALSE;
+    return T1_Reset_Size(size);
+  }
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Char_Index                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Uses a charmap to return a given character code's glyph index.     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charmap  :: A handle to the source charmap object.                 */
+  /*    charcode :: The character code.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index.  0 means `undefined character code'.                  */
+  /*                                                                       */
+  static
+  FT_UInt  Get_Char_Index( FT_CharMap  charmap,
+                           FT_Long     charcode )
+  {
+    T1_Face             face;
+    FT_UInt             result = 0;
+    PSNames_Interface*  psnames;
+
+    face = (T1_Face)charmap->face;
+    psnames = (PSNames_Interface*)face->psnames;
+    if (psnames)
+      switch (charmap->encoding)
+      {
+       /********************************************************************/
+       /*                                                                  */
+       /* Unicode encoding support                                         */
+       /*                                                                  */
+        case ft_encoding_unicode:
+          {
+            /* use the "psnames" module to synthetize the Unicode charmap */
+            result = psnames->lookup_unicode( &face->unicode_map,
+                                              (FT_ULong)charcode );
+
+            /* the function returns 0xFFFF when the Unicode charcode has */
+            /* no corresponding glyph..                                  */
+            if (result == 0xFFFF)
+              result = 0;
+            goto Exit;
+          }
+
+       /********************************************************************/
+       /*                                                                  */
+       /* Custom Type 1 encoding                                           */
+       /*                                                                  */
+        case ft_encoding_adobe_custom:
+          {
+            T1_Encoding*  encoding = &face->type1.encoding;
+            if (charcode >= encoding->code_first &&
+                charcode <= encoding->code_last)
+            {
+              result = encoding->char_index[charcode];
+            }
+            goto Exit;
+          }
+
+       /********************************************************************/
+       /*                                                                  */
+       /* Adobe Standard & Expert encoding support                         */
+       /*                                                                  */
+       default:
+         if (charcode < 256)
+         {
+           FT_UInt      code;
+           FT_Int       n;
+           const char*  glyph_name;
+
+           code = psnames->adobe_std_encoding[charcode];
+           if (charmap->encoding == ft_encoding_adobe_expert)
+             code = psnames->adobe_expert_encoding[charcode];
+
+           glyph_name = psnames->adobe_std_strings(code);
+           if (!glyph_name) break;
+
+           for ( n = 0; n < face->type1.num_glyphs; n++ )
+           {
+             const char*  gname = face->type1.glyph_names[n];
+
+             if ( gname && gname[0] == glyph_name[0] &&
+                  strcmp( gname, glyph_name ) == 0 )
+             {
+               result = n;
+               break;
+             }
+           }
+         }
+      }
+  Exit:
+    return result;
+  }
+
+
+  /******************************************************************/
+  /*                                                                */
+  /* <Struct> FT_DriverInterface                                    */
+  /*                                                                */
+  /* <Description>                                                  */
+  /*    A structure used to hold a font driver's basic interface    */
+  /*    used by the high-level parts of FreeType (or other apps)    */
+  /*                                                                */
+  /*    Most scalable drivers provide a specialized interface to    */
+  /*    access format-specific features. It can be retrieved with   */
+  /*    a call to the "get_format_interface", and should be defined */
+  /*    in each font driver header (e.g. ttdriver.h, t1driver.h,..) */
+  /*                                                                */
+  /*    All fields are function pointers ..                         */
+  /*                                                                */
+  /*                                                                */
+  /* <Fields>                                                       */
+  /*                                                                */
+  /*    new_engine ::                                               */
+  /*        used to create and initialise a new driver object       */
+  /*                                                                */
+  /*    done_engine ::                                              */
+  /*        used to finalise and destroy a given driver object      */
+  /*                                                                */
+  /*    get_format_interface ::                                     */
+  /*        return a typeless pointer to the format-specific        */
+  /*        driver interface.                                       */
+  /*                                                                */
+  /*    new_face ::                                                 */
+  /*        create a new face object from a resource                */
+  /*                                                                */
+  /*    done_face ::                                                */
+  /*        discards a face object, as well as all child objects    */
+  /*        ( sizes, charmaps, glyph slots )                        */
+  /*                                                                */
+  /*    get_face_properties ::                                      */
+  /*        return generic face properties                          */
+  /*                                                                */
+  /*    get_kerning ::                                              */
+  /*        return the kerning vector corresponding to a pair       */
+  /*        of glyphs, expressed in unscaled font units.            */
+  /*                                                                */
+  /*    new_size ::                                                 */
+  /*        create and initialise a new scalable size object.       */
+  /*                                                                */
+  /*    new_fixed_size ::                                           */
+  /*        create and initialise a new fixed-size object.          */
+  /*                                                                */
+  /*    done_size ::                                                */
+  /*        finalize a given face size object.                      */
+  /*                                                                */
+  /*    set_size_resolutions ::                                     */
+  /*        reset a scalable size object's output resolutions       */
+  /*                                                                */
+  /*    set_size_char_sizes ::                                      */
+  /*        reset a scalable size object's character size           */
+  /*                                                                */
+  /*    set_pixel_sizes ::                                          */
+  /*        reset a face size object's pixel dimensions. Applies    */
+  /*        to both scalable and fixed faces.                       */
+  /*                                                                */
+  /*    new_glyph_slot ::                                           */
+  /*        create and initialise a new glyph slot                  */
+  /*                                                                */
+  /*    done_glyph_slot ::                                          */
+  /*        discard a given glyph slot                              */
+  /*                                                                */
+  /*    load_glyph ::                                               */
+  /*        load a given glyph into a given slot                    */
+  /*                                                                */
+  /*    get_glyph_metrics ::                                        */
+  /*        return a loaded glyph's metrics.                        */
+  /*                                                                */
+
+  const  FT_DriverInterface  t1cid_driver_interface =
+  {
+    sizeof( FT_DriverRec ),
+    sizeof( CID_FaceRec ),
+    sizeof( T1_SizeRec ),
+    sizeof( T1_GlyphSlotRec ),
+
+    "type1",
+    100,
+    200,
+
+    0,   /* format interface */
+
+    (FTDriver_initDriver)           T1_Init_Driver,
+    (FTDriver_doneDriver)           T1_Done_Driver,
+
+    (FTDriver_getInterface)         Get_Interface,
+
+    (FTDriver_initFace)             T1_Init_Face,
+    (FTDriver_doneFace)             T1_Done_Face,
+
+#ifndef xxxxT1_CONFIG_OPTION_NO_AFM
+    (FTDriver_getKerning)           0,
+#else
+    (FTDriver_getKerning)           Get_Kerning,
+#endif
+
+    (FTDriver_initSize)             T1_Init_Size,
+    (FTDriver_doneSize)             T1_Done_Size,
+    (FTDriver_setCharSizes)         Set_Char_Sizes,
+    (FTDriver_setPixelSizes)        Set_Pixel_Sizes,
+
+    (FTDriver_initGlyphSlot)        T1_Init_GlyphSlot,
+    (FTDriver_doneGlyphSlot)        T1_Done_GlyphSlot,
+    (FTDriver_loadGlyph)            CID_Load_Glyph,
+
+    (FTDriver_getCharIndex)         Get_Char_Index,
+  };
+
+
+  /******************************************************************/
+  /*                                                                */
+  /*  <Function> Get_FreeType_Driver_Interface                      */
+  /*                                                                */
+  /*  <Description>                                                 */
+  /*     This function is used when compiling the TrueType driver   */
+  /*     as a shared library (.DLL or .so). It will be used by the  */
+  /*     high-level library of FreeType to retrieve the address of  */
+  /*     the driver's generic interface.                            */
+  /*                                                                */
+  /*     It shouldn't be implemented in a static build, as each     */
+  /*     driver must have the same function as an exported entry    */
+  /*     point.                                                     */
+  /*                                                                */
+  /*  <Return>                                                      */
+  /*     address of TrueType's driver generic interface. The        */
+  /*     forma-specific interface can then be retrieved through     */
+  /*     the method interface->get_format_interface..               */
+  /*                                                                */
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+  EXPORT_FUNC(FT_DriverInterface*)  getDriverInterface( void )
+  {
+    return &t1cid_driver_interface;
+  }
+
+#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
--- /dev/null
+++ b/src/cid/cidriver.h
@@ -1,0 +1,27 @@
+/*******************************************************************
+ *
+ *  t1driver.h
+ *
+ *    High-level Type1 driver interface for FreeType 2.0
+ *
+ *  Copyright 1996-1998 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 T1DRIVER_H
+#define T1DRIVER_H
+
+#include <cidobjs.h>
+#include <t1errors.h>
+
+  FT_EXPORT_VAR(const  FT_DriverInterface)  t1cid_driver_interface;
+
+#endif /* T1DRIVER_H */
+
--- /dev/null
+++ b/src/cid/cidtokens.h
@@ -1,0 +1,94 @@
+/*******************************************************************
+ *
+ *  t1tokens.h
+ *
+ *  Type 1 tokens definition
+ *
+ *  Copyright 2000 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.
+ *
+ *  This file only contains macros that are expanded when compiling
+ *  the "t1load.c" source file.
+ *
+ ******************************************************************/
+
+#define T1TYPE  CID_Info
+#define T1CODE  t1_field_cid_info
+
+  T1_FIELD_STRING  ( "CIDFontName", cid_font_name )
+  T1_FIELD_NUM     ( "CIDFontVersion", cid_version )
+  T1_FIELD_NUM     ( "CIDFontType", cid_font_type )
+  T1_FIELD_STRING  ( "Registry", registry )
+  T1_FIELD_STRING  ( "Ordering", ordering )
+  T1_FIELD_NUM     ( "Supplement", supplement )
+  T1_FIELD_CALLBACK( "FontBBox", font_bbox )
+  T1_FIELD_NUM     ( "UIDBase", uid_base )
+  T1_FIELD_CALLBACK( "FDArray", fd_array )
+  T1_FIELD_NUM     ( "CIDMapOffset", cidmap_offset )
+  T1_FIELD_NUM     ( "FDBytes", fd_bytes )
+  T1_FIELD_NUM     ( "GDBytes", gd_bytes )
+  T1_FIELD_NUM     ( "CIDCount", cid_count )
+  
+#undef  T1TYPE
+#undef  T1CODE
+#define T1TYPE  T1_FontInfo
+#define T1CODE  t1_field_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_FIXED ( "ItalicAngle", italic_angle )
+  T1_FIELD_BOOL  ( "isFixedPitch", is_fixed_pitch )
+  T1_FIELD_NUM   ( "UnderlinePosition", underline_position )
+  T1_FIELD_NUM   ( "UnderlineThickness", underline_thickness )
+
+#undef  T1TYPE
+#undef  T1CODE
+#define T1TYPE CID_FontDict
+#define T1CODE t1_field_font_dict
+
+  T1_FIELD_CALLBACK( "FontMatrix", font_matrix )
+  T1_FIELD_NUM     ( "PaintType", paint_type )
+  T1_FIELD_NUM     ( "FontType", font_type )
+  T1_FIELD_NUM     ( "SubrMapOffset", subrmap_offset )
+  T1_FIELD_NUM     ( "SDBytes", sd_bytes )
+  T1_FIELD_NUM     ( "SubrCount", num_subrs )
+  T1_FIELD_NUM     ( "lenBuildCharArray", len_buildchar )
+  T1_FIELD_FIXED   ( "ForceBoldThreshold", forcebold_threshold )
+  T1_FIELD_FIXED   ( "ExpansionFactor", expansion_factor )
+  T1_FIELD_NUM     ( "StrokeWidth", stroke_width )
+  
+#undef  T1TYPE
+#undef  T1CODE
+#define T1TYPE  T1_Private
+#define T1CODE  t1_field_private
+
+  T1_FIELD_NUM  ( "UniqueID", unique_id )
+  T1_FIELD_NUM  ( "lenIV", lenIV )
+  T1_FIELD_NUM  ( "LanguageGroup", language_group )
+  T1_FIELD_NUM  ( "password", password )
+  
+  T1_FIELD_FIXED( "BlueScale", blue_scale )
+  T1_FIELD_NUM  ( "BlueShift", blue_shift )
+  T1_FIELD_NUM  ( "BlueFuzz",  blue_fuzz )
+  
+  T1_FIELD_NUM_TABLE( "BlueValues", blue_values, 14 )
+  T1_FIELD_NUM_TABLE( "OtherBlues", other_blues, 10 )
+  T1_FIELD_NUM_TABLE( "FamilyBlues", family_blues, 14 )
+  T1_FIELD_NUM_TABLE( "FamilyOtherBlues", family_other_blues, 10 )
+
+  T1_FIELD_NUM_TABLE2( "StdHW", standard_width,  1 )
+  T1_FIELD_NUM_TABLE2( "StdVW", standard_height, 1 )
+  T1_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2 )
+  
+  T1_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12 )
+  T1_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12 )
+
+
--- /dev/null
+++ b/src/cid/module.mk
@@ -1,0 +1,6 @@
+make_module_list: add_type1cid_driver
+
+add_type1cid_driver:
+	$(OPEN_DRIVER)t1cid_driver_interface$(CLOSE_DRIVER)
+	$(ECHO_DRIVER)cid       $(ECHO_DRIVER_DESC)Postscript CID-keyed fonts, no known extension$(ECHO_DRIVER_DONE)
+# EOF
--- /dev/null
+++ b/src/cid/rules.mk
@@ -1,0 +1,97 @@
+#
+# FreeType 2 driver configuration rules
+#
+
+
+# Copyright 1996-2000 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used modified
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT.  By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+#****************************************************************************
+#*                                                                          *
+#*  The "Type1z" driver is an experimental replacement for the current      *
+#*  Type 1 driver.  It features a very different loading mechanism that     *
+#*  is much faster than the one used by the `normal' driver, and also       *
+#*  deals nicely with nearly broken Type 1 font files. It is also           *
+#*  much smaller...                                                         *
+#*                                                                          *
+#*  Note that it may become a permanent replacement of the current          *
+#*  "src/type1" driver in the future..                                      *
+#*                                                                          *
+#****************************************************************************
+
+# Type1z driver directory
+#
+CID_DIR  := $(SRC_)cid
+CID_DIR_ := $(CID_DIR)$(SEP)
+
+
+# additional include flags used when compiling the driver
+#
+CID_INCLUDE := $(SHARED) $(CID_DIR)
+CID_COMPILE := $(FT_COMPILE) $(CID_INCLUDE:%=$I%)
+
+
+# Type1 driver sources (i.e., C files)
+#
+CID_DRV_SRC := $(CID_DIR_)cidparse.c  \
+               $(CID_DIR_)cidload.c   \
+               $(CID_DIR_)cidriver.c  \
+               $(CID_DIR_)cidgload.c  \
+               $(CID_DIR_)cidafm.c
+
+# Type1 driver headers
+#
+CID_DRV_H := $(CID_DIR_)t1errors.h   \
+             $(CID_DIR_)cidtokens.h  \
+             $(T1SHARED_H)          \
+             $(CID_DRV_SRC:%.c=%.h)
+
+
+# driver object(s)
+#
+#   CID_DRV_OBJ_M is used during `debug' builds
+#   CID_DRV_OBJ_S is used during `release' builds
+#
+CID_DRV_OBJ_M := $(CID_DRV_SRC:$(CID_DIR_)%.c=$(OBJ_)%.$O) \
+                 $(T1SHARED:$(T1SHARED_DIR_)%.c=$(OBJ_)%.$O)
+CID_DRV_OBJ_S := $(OBJ_)type1cid.$O
+
+
+# driver source file(s)
+#
+CID_DRV_SRC_M := $(CID_DRV_SRC) $(T1SHARED_SRC)
+CID_DRV_SRC_S := $(CID_DIR_)type1cid.c
+
+
+# driver - single object
+#
+#  the driver is recompiled if any of the header or source files is changed
+#
+$(CID_DRV_OBJ_S): $(BASE_H) $(CID_DRV_H) $(CID_DRV_SRC) $(CID_DRV_SRC_S)
+	$(CID_COMPILE) $T$@ $(CID_DRV_SRC_S)
+
+
+# driver - multiple objects
+#
+#   All objects are recompiled if any of the header files is changed
+#
+$(OBJ_)t1%.$O: $(CID_DIR_)t1%.c $(BASE_H) $(CID_DRV_H)
+	$(CID_COMPILE) $T$@ $<
+
+$(OBJ_)t1%.$O: $(T1SHARED_DIR_)t1%.c $(BASE_H) $(T1SHARED_H)
+	$(CID_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(CID_DRV_OBJ_S)
+DRV_OBJS_M += $(CID_DRV_OBJ_M)
+
+# EOF
--- /dev/null
+++ b/src/cid/t1errors.h
@@ -1,0 +1,75 @@
+/*******************************************************************
+ *
+ *  t1errors.h
+ *
+ *    Type1 Error ID definitions
+ *
+ *  Copyright 1996-1998 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 T1ERRORS_H
+#define T1ERRORS_H
+
+#include <freetype/fterrors.h>
+
+  /************************ error codes declaration **************/
+
+  /* The error codes are grouped in 'classes' used to indicate the */
+  /* 'level' at which the error happened.                          */
+  /* The class is given by an error code's high byte.              */
+
+
+/* ------------- Success is always 0 -------- */
+
+#define  T1_Err_Ok                       FT_Err_Ok
+
+/* ----------- high level API errors -------- */
+
+#define  T1_Err_Invalid_File_Format      FT_Err_Invalid_File_Format
+#define  T1_Err_Invalid_Argument         FT_Err_Invalid_Argument
+#define  T1_Err_Invalid_Driver_Handle    FT_Err_Invalid_Driver_Handle
+#define  T1_Err_Invalid_Face_Handle      FT_Err_Invalid_Face_Handle
+#define  T1_Err_Invalid_Size_Handle      FT_Err_Invalid_Size_Handle
+#define  T1_Err_Invalid_Glyph_Handle     FT_Err_Invalid_Slot_Handle
+#define  T1_Err_Invalid_CharMap_Handle   FT_Err_Invalid_CharMap_Handle
+#define  T1_Err_Invalid_Glyph_Index      FT_Err_Invalid_Glyph_Index
+
+#define  T1_Err_Unimplemented_Feature    FT_Err_Unimplemented_Feature
+#define  T1_Err_Unavailable_Outline      FT_Err_Unavailable_Outline
+#define  T1_Err_Unavailable_Bitmap       FT_Err_Unavailable_Bitmap
+#define  T1_Err_Unavailable_Pixmap       FT_Err_Unavailable_Pixmap
+#define  T1_Err_File_Is_Not_Collection   FT_Err_File_Is_Not_Collection
+
+#define  T1_Err_Invalid_Engine           FT_Err_Invalid_Driver_Handle
+
+/* ------------- internal errors ------------ */
+
+#define  T1_Err_Out_Of_Memory            FT_Err_Out_Of_Memory
+#define  T1_Err_Unlisted_Object          FT_Err_Unlisted_Object
+
+/* ------------ general glyph outline errors ------ */
+
+#define  T1_Err_Too_Many_Points          FT_Err_Too_Many_Points
+#define  T1_Err_Too_Many_Contours        FT_Err_Too_Many_Contours
+#define  T1_Err_Too_Many_Hints           FT_Err_Too_Many_Hints
+#define  T1_Err_Invalid_Composite        FT_Err_Invalid_Composite
+#define  T1_Err_Too_Many_Edges           FT_Err_Too_Many_Edges
+#define  T1_Err_Too_Many_Strokes         FT_Err_Too_Many_Strokes
+
+
+#define  T1_Err_Syntax_Error             FT_Err_Invalid_File_Format
+#define  T1_Err_Stack_Underflow          FT_Err_Invalid_File_Format
+#define  T1_Err_Stack_Overflow           FT_Err_Invalid_File_Format
+
+#endif /* TDERRORS_H */
+
+
+/* END */
--- /dev/null
+++ b/src/cid/type1cid.c
@@ -1,0 +1,41 @@
+/***************************************************************************/
+/*                                                                         */
+/*  type1.c                                                                */
+/*                                                                         */
+/*  FreeType Type 1 driver component                                       */
+/*                                                                         */
+/*  Copyright 1996-1998 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.                                        */
+/*                                                                         */
+/*                                                                         */
+/*  This file is used to compile the FreeType Type 1  font driver.         */
+/*  It relies on all components included in the "base" layer (see          */
+/*  the file "ftbase.c"). Source code is located in "freetype/ttlib"       */
+/*  and contains :                                                         */
+/*                                                                         */
+/*     - a driver interface                                                */
+/*     - an object manager                                                 */
+/*     - a table loader                                                    */
+/*     - a glyph loader                                                    */
+/*     - a glyph hinter                                                    */
+/*                                                                         */
+/***************************************************************************/
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <cidparse.c>
+#include <cidload.c>
+#include <cidobjs.c>
+#include <cidriver.c>
+#include <cidgload.c>
+
+#if 0
+#include <cidafm.c>
+#endif
+
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -993,13 +993,12 @@
       for ( u = 0; u < num_points + 2; u++ )
       {
         glyph->outline.points[u] = loader->base.cur[u];
-        glyph->outline.tags [u] = loader->base.tags[u];
+        glyph->outline.tags  [u] = loader->base.tags[u];
       }
 
       for ( u = 0; u < num_contours; u++ )
         glyph->outline.contours[u] = loader->base.contours[u];
 
-      /* glyph->outline.second_pass = TRUE; */
       glyph->outline.flags      &= ~ft_outline_single_pass;
       glyph->outline.n_points    = num_points;
       glyph->outline.n_contours  = num_contours;
@@ -1029,6 +1028,8 @@
     {
       TT_Pos  left_bearing;
       TT_Pos  advance;
+      
+      TT_Pos  lsb2, adv2;
 
       left_bearing = loader->left_bearing;
       advance      = loader->advance;
@@ -1042,14 +1043,22 @@
            (loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH) == 0 )
         advance = face->horizontal.advance_Width_Max;
 
-      if ( !(loader->load_flags & FT_LOAD_NO_SCALE) )
+      lsb2 = left_bearing;
+      adv2 = advance;
+      
+      /* if necessary, scale the horizontal left bearing and advance */
+      /* to get their values in 16.16 format..                       */
+      if ( !(loader->load_flags & FT_LOAD_NO_SCALE) &&
+             loader->load_flags & FT_LOAD_LINEAR    )
       {
-        left_bearing = FT_MulFix( left_bearing, x_scale );
-        advance      = FT_MulFix( advance, x_scale );
+        FT_Pos  em_size    = face->root.units_per_EM;
+        FT_Pos  pixel_size = (FT_Pos)face->root.size->metrics.x_ppem << 16;
+        
+        lsb2 = FT_MulDiv( lsb2, pixel_size, em_size );
+        adv2 = FT_MulDiv( adv2, pixel_size, em_size );
       }
-
-      glyph->metrics2.horiBearingX = left_bearing;
-      glyph->metrics2.horiAdvance  = advance;
+      glyph->metrics2.horiBearingX = lsb2;
+      glyph->metrics2.horiAdvance  = adv2;
     }
 
     glyph->metrics.horiBearingX = bbox.xMin;
@@ -1131,8 +1140,25 @@
         advance = advance_height;
       }
 
-      glyph->metrics2.vertBearingY = Top;
-      glyph->metrics2.vertAdvance  = advance;
+      /* compute metrics2 fields */
+      {
+       FT_Pos  vtb2 = top_bearing;
+       FT_Pos  adv2 = advance_height;
+        
+        /* scale to 16.16 format if required */
+        if ( !(loader->load_flags & FT_LOAD_NO_SCALE) &&
+               loader->load_flags & FT_LOAD_LINEAR    )
+        {               
+          FT_Pos  em_size = face->root.units_per_EM;
+          FT_Pos  pixel_size = face->root.size->metrics.y_ppem;
+          
+          vtb2 = FT_MulDiv( vtb2, pixel_size, em_size );
+          adv2 = FT_MulDiv( adv2, pixel_size, em_size );
+        }
+        
+        glyph->metrics2.vertBearingY = vtb2;
+        glyph->metrics2.vertAdvance  = adv2;
+      }
 
       /* XXX: for now, we have no better algorithm for the lsb, but it    */
       /*      should work fine.                                           */
@@ -1306,7 +1332,7 @@
     /* clear all outline flags, except the "owner" one */
     glyph->outline.flags &= ft_outline_owner;
 
-    if (size && size->root.metrics.y_ppem < 24 )
+    if ( size && size->root.metrics.y_ppem < 24 )
       glyph->outline.flags |= ft_outline_high_precision;
 
     /************************************************************************/
--- a/src/type1/t1hinter.c
+++ b/src/type1/t1hinter.c
@@ -127,7 +127,7 @@
     /* First of all, check the sizes of the /BlueValues and /OtherBlues */
     /* tables. They all must contain an even number of arguments        */
     if ( priv->num_other_blues & 1 ||
-         priv->num_blues       & 1 )
+         priv->num_blue_values & 1 )
     {
       FT_ERROR(( "T1.Copy_Blues : odd number of blue values\n" ));
       return T1_Err_Syntax_Error;
@@ -141,7 +141,7 @@
       blues[n] = priv->other_blues[n];
 
     /* Add the first blue zone in /BlueValues to the table */
-    num_top = priv->num_blues - 2;
+    num_top = priv->num_blue_values - 2;
     if ( num_top >= 0 )
     {
       blues[ num_bottom ] = priv->blue_values[0];
@@ -294,7 +294,7 @@
     standard_width = priv->standard_width[0];
     n_zones        = priv->num_snap_widths;
     base_zone      = hints->snap_widths;
-    orgs           = priv->stem_snap_widths;
+    orgs           = priv->snap_widths;
     scale          = size->root.metrics.x_scale;
 
     while (direction < 2)
@@ -461,7 +461,7 @@
       standard_width = priv->standard_height[0];
       n_zones        = priv->num_snap_heights;
       base_zone      = hints->snap_heights;
-      orgs           = priv->stem_snap_heights;
+      orgs           = priv->snap_heights;
       scale          = size->root.metrics.y_scale;
     }
 
--- a/src/type1/t1load.c
+++ b/src/type1/t1load.c
@@ -428,7 +428,7 @@
 
 
       case imm_BlueValues:
-        CopyArray( parser, &priv->num_blues,
+        CopyArray( parser, &priv->num_blue_values,
                    priv->blue_values, 14 );
         break;
 
@@ -478,13 +478,13 @@
 
       case imm_StemSnapH:
         CopyArray( parser, &priv->num_snap_widths,
-                   priv->stem_snap_widths, 12 );
+                   priv->snap_widths, 12 );
         break;
 
 
       case imm_StemSnapV:
         CopyArray( parser, &priv->num_snap_heights,
-                   priv->stem_snap_heights, 12 );
+                   priv->snap_heights, 12 );
         break;
 
 
--- a/src/type1z/t1tokens.h
+++ b/src/type1z/t1tokens.h
@@ -43,7 +43,7 @@
   T1_PRIVATE_NUM  ( "BlueShift", blue_shift )
   T1_PRIVATE_NUM  ( "BlueFuzz",  blue_fuzz )
   
-  T1_PRIVATE_NUM_TABLE( "BlueValues", blue_values, 14, num_blues )
+  T1_PRIVATE_NUM_TABLE( "BlueValues", blue_values, 14, num_blue_values )
   T1_PRIVATE_NUM_TABLE( "OtherBlues", other_blues, 10, num_other_blues )
   T1_PRIVATE_NUM_TABLE( "FamilyBlues", family_blues, 14, num_family_blues )
   T1_PRIVATE_NUM_TABLE( "FamilyOtherBlues", family_other_blues, 10, num_family_other_blues )
@@ -52,8 +52,8 @@
   T1_PRIVATE_NUM_TABLE2( "StdVW", standard_height, 1 )
   T1_PRIVATE_NUM_TABLE2( "MinFeature", min_feature, 2 )
   
-  T1_PRIVATE_NUM_TABLE ( "StemSnapH", stem_snap_widths, 12, num_snap_widths )
-  T1_PRIVATE_NUM_TABLE ( "StemSnapV", stem_snap_heights, 12, num_snap_heights )
+  T1_PRIVATE_NUM_TABLE ( "StemSnapH", snap_widths, 12, num_snap_widths )
+  T1_PRIVATE_NUM_TABLE ( "StemSnapV", snap_heights, 12, num_snap_heights )
 
 #undef  T1TYPE
 #define T1TYPE  T1_Font