shithub: freetype+ttf2subf

Download patch

ref: a4e2894e03de65c5e0cd14b11b6fa30b14ed6769
parent: 3a3ffedcb25e01fe6bef195fec6a5152e25777d7
author: David Turner <[email protected]>
date: Wed Oct 25 20:30:33 EDT 2000

simple renaming of directories:

  "type1z"  -> "type1"
  "raster1" -> "raster"

note that I didn't rename all files. We'll have to endure
the "z1..." crazyness unless we perform a _big_ sed on
the sources :-)

git/fs: mount .git/fs: mount/attach disallowed
--- /dev/null
+++ b/src/raster/ftraster.c
@@ -1,0 +1,3293 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftraster.c                                                             */
+/*                                                                         */
+/*    The FreeType glyph rasterizer (body).                                */
+/*                                                                         */
+/*  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 a rewrite of the FreeType 1.x scan-line converter             */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+#  include "ftraster.h"
+#else
+#  include <raster/ftraster.h>
+#endif
+#include <freetype/internal/ftcalc.h>      /* for FT_MulDiv() only */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* A simple technical note on how the raster works                       */
+  /* -----------------------------------------------                       */
+  /*                                                                       */
+  /*   Converting an outline into a bitmap is achieved in several steps:   */
+  /*                                                                       */
+  /*   1 - Decomposing the outline into successive `profiles'.  Each       */
+  /*       profile is simply an array of scanline intersections on a given */
+  /*       dimension.  A profile's main attributes are                     */
+  /*                                                                       */
+  /*       o its scanline position boundaries, i.e. `Ymin' and `Ymax'.     */
+  /*                                                                       */
+  /*       o an array of intersection coordinates for each scanline        */
+  /*         between `Ymin' and `Ymax'.                                    */
+  /*                                                                       */
+  /*       o a direction, indicating whether it was built going `up' or    */
+  /*         `down', as this is very important for filling rules.          */
+  /*                                                                       */
+  /*   2 - Sweeping the target map's scanlines in order to compute segment */
+  /*       `spans' which are then filled.  Additionally, this pass         */
+  /*       performs drop-out control.                                      */
+  /*                                                                       */
+  /*   The outline data is parsed during step 1 only.  The profiles are    */
+  /*   built from the bottom of the render pool, used as a stack.  The     */
+  /*   following graphics shows the profile list under construction:       */
+  /*                                                                       */
+  /*     ____________________________________________________________ _ _  */
+  /*    |         |                   |         |                 |        */
+  /*    | profile | coordinates for   | profile | coordinates for |-->     */
+  /*    |    1    |  profile 1        |    2    |  profile 2      |-->     */
+  /*    |_________|___________________|_________|_________________|__ _ _  */
+  /*                                                                       */
+  /*    ^                                                         ^        */
+  /*    |                                                         |        */
+  /*  start of render pool                                       top       */
+  /*                                                                       */
+  /*   The top of the profile stack is kept in the `top' variable.         */
+  /*                                                                       */
+  /*   As you can see, a profile record is pushed on top of the render     */
+  /*   pool, which is then followed by its coordinates/intersections.  If  */
+  /*   a change of direction is detected in the outline, a new profile is  */
+  /*   generated until the end of the outline.                             */
+  /*                                                                       */
+  /*   Note that when all profiles have been generated, the function       */
+  /*   Finalize_Profile_Table() is used to record, for each profile, its   */
+  /*   bottom-most scanline as well as the scanline above its upmost       */
+  /*   boundary.  These positions are called `y-turns' because they (sort  */
+  /*   of) correspond to local extrema.  They are stored in a sorted list  */
+  /*   built from the top of the render pool as a downwards stack:         */
+  /*                                                                       */
+  /*      _ _ _______________________________________                      */
+  /*                            |                    |                     */
+  /*                         <--| sorted list of     |                     */
+  /*                         <--|  extrema scanlines |                     */
+  /*      _ _ __________________|____________________|                     */
+  /*                                                                       */
+  /*                            ^                    ^                     */
+  /*                            |                    |                     */
+  /*                         maxBuff           sizeBuff = end of pool      */
+  /*                                                                       */
+  /*   This list is later used during the sweep phase in order to          */
+  /*   optimize performance (see technical note on the sweep below).       */
+  /*                                                                       */
+  /*   Of course, the raster detects whether the two stacks collide and    */
+  /*   handles the situation propertly.                                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  CONFIGURATION MACROS                                               **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* define DEBUG_RASTER if you want to compile a debugging version */
+#define xxxDEBUG_RASTER
+
+  /* The default render pool size in bytes */
+#define RASTER_RENDER_POOL  8192
+
+  /* undefine FT_RASTER_OPTION_ANTI_ALIASING if you do not want to support */
+  /* 5-levels anti-aliasing                                                */
+#ifdef FT_CONFIG_OPTION_5_GRAY_LEVELS
+#define FT_RASTER_OPTION_ANTI_ALIASING
+#endif
+
+  /* The size of the two-lines intermediate bitmap used */
+  /* for anti-aliasing, in bytes.                       */
+#define RASTER_GRAY_LINES  2048
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  OTHER MACROS (do not change)                                       **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_raster
+
+
+#ifdef _STANDALONE_
+
+
+  /* This macro is used to indicate that a function parameter is unused. */
+  /* Its purpose is simply to reduce compiler warnings.  Note also that  */
+  /* simply defining it as `(void)x' doesn't avoid warnings with certain */
+  /* ANSI compilers (e.g. LCC).                                          */
+#define FT_UNUSED( x )  (x) = (x)
+
+  /* Disable the tracing mechanism for simplicity -- developers can      */
+  /* activate it easily by redefining these two macros.                  */
+#ifndef FT_ERROR
+#define FT_ERROR( x )  do ; while ( 0 )     /* nothing */
+#endif
+
+#ifndef FT_TRACE
+#define FT_TRACE( x )  do ; while ( 0 )     /* nothing */
+#endif
+
+#define Raster_Err_None          0
+#define Raster_Err_Not_Ini      -1
+#define Raster_Err_Overflow     -2
+#define Raster_Err_Neg_Height   -3
+#define Raster_Err_Invalid      -4
+#define Raster_Err_Unsupported  -5
+
+
+#else /* _STANDALONE_ */
+
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftdebug.h> /* for FT_TRACE() and FT_ERROR() */
+
+#define Raster_Err_None         FT_Err_Ok
+#define Raster_Err_Not_Ini      FT_Err_Raster_Uninitialized
+#define Raster_Err_Overflow     FT_Err_Raster_Overflow
+#define Raster_Err_Neg_Height   FT_Err_Raster_Negative_Height
+#define Raster_Err_Invalid      FT_Err_Invalid_Outline
+#define Raster_Err_Unsupported  FT_Err_Cannot_Render_Glyph
+
+
+#endif /* _STANDALONE_ */
+
+
+  /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is       */
+  /* typically a small value and the result of a*b is known to fit into */
+  /* 32 bits.                                                           */
+#define FMulDiv( a, b, c )  ( (a) * (b) / (c) )
+
+  /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
+  /* for clipping computations.  It simply uses the FT_MulDiv() function   */
+  /* defined in `ftcalc.h'.                                                */
+#define SMulDiv  FT_MulDiv
+
+  /* The rasterizer is a very general purpose component; please leave */
+  /* the following redefinitions there (you never know your target    */
+  /* environment).                                                    */
+
+#ifndef TRUE
+#define TRUE   1
+#endif
+
+#ifndef FALSE
+#define FALSE  0
+#endif
+
+#ifndef NULL
+#define NULL  (void*)0
+#endif
+
+#ifndef SUCCESS
+#define SUCCESS  0
+#endif
+
+#ifndef FAILURE
+#define FAILURE  1
+#endif
+
+
+#define MaxBezier  32   /* The maximum number of stacked Bezier curves. */
+                        /* Setting this constant to more than 32 is a   */
+                        /* pure waste of space.                         */
+
+#define Pixel_Bits  6   /* fractional bits of *input* coordinates */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  SIMPLE TYPE DECLARATIONS                                           **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  typedef int             Int;
+  typedef unsigned int    UInt;
+  typedef short           Short;
+  typedef unsigned short  UShort, *PUShort;
+  typedef long            Long, *PLong;
+  typedef unsigned long   ULong;
+
+  typedef unsigned char   Byte, *PByte;
+  typedef char            Bool;
+
+  typedef struct  TPoint_
+  {
+    Long  x;
+    Long  y;
+
+  } TPoint;
+
+
+  typedef enum  TFlow_
+  {
+    Flow_None = 0,
+    Flow_Up   = 1,
+    Flow_Down = -1
+
+  } TFlow;
+
+
+  /* States of each line, arc, and profile */
+  typedef enum  TStates_
+  {
+    Unknown,
+    Ascending,
+    Descending,
+    Flat
+
+  } TStates;
+
+
+  typedef struct TProfile_  TProfile;
+  typedef TProfile*         PProfile;
+
+  struct  TProfile_
+  {
+    FT_F26Dot6  X;           /* current coordinate during sweep        */
+    PProfile    link;        /* link to next profile - various purpose */
+    PLong       offset;      /* start of profile's data in render pool */
+    Int         flow;        /* Profile orientation: Asc/Descending    */
+    Long        height;      /* profile's height in scanlines          */
+    Long        start;       /* profile's starting scanline            */
+
+    UShort      countL;      /* number of lines to step before this    */
+                             /* profile becomes drawable               */
+
+    PProfile    next;        /* next profile in same contour, used     */
+                             /* during drop-out control                */
+  };
+
+  typedef PProfile   TProfileList;
+  typedef PProfile*  PProfileList;
+
+
+  /* Simple record used to implement a stack of bands, required */
+  /* by the sub-banding mechanism                               */
+  typedef struct  TBand_
+  {
+    Short  y_min;   /* band's minimum */
+    Short  y_max;   /* band's maximum */
+
+  } TBand;
+
+
+#define AlignProfileSize \
+          ( ( sizeof ( TProfile ) + sizeof ( long ) - 1 ) / sizeof ( long ) )
+
+
+#ifdef TT_STATIC_RASTER
+
+
+#define RAS_ARGS       /* void */
+#define RAS_ARG        /* void */
+
+#define RAS_VARS       /* void */
+#define RAS_VAR        /* void */
+
+#define FT_UNUSED_RASTER  do ; while ( 0 )
+
+
+#else /* TT_STATIC_RASTER */
+
+
+#define RAS_ARGS       TRaster_Instance*  raster,
+#define RAS_ARG        TRaster_Instance*  raster
+
+#define RAS_VARS       raster,
+#define RAS_VAR        raster
+
+#define FT_UNUSED_RASTER  FT_UNUSED( raster )
+
+
+#endif /* TT_STATIC_RASTER */
+
+
+  typedef struct TRaster_Instance_  TRaster_Instance;
+
+
+  /* prototypes used for sweep function dispatch */
+  typedef void  Function_Sweep_Init( RAS_ARGS Short*  min,
+                                              Short*  max );
+
+  typedef void  Function_Sweep_Span( RAS_ARGS Short       y,
+                                              FT_F26Dot6  x1,
+                                              FT_F26Dot6  x2,
+                                              PProfile    left,
+                                              PProfile    right );
+
+  typedef void  Function_Sweep_Step( RAS_ARG );
+
+
+  /* NOTE: These operations are only valid on 2's complement processors */
+
+#define FLOOR( x )    ( (x) & -ras.precision )
+#define CEILING( x )  ( ( (x) + ras.precision - 1 ) & -ras.precision )
+#define TRUNC( x )    ( (signed long)(x) >> ras.precision_bits )
+#define FRAC( x )     ( (x) & ( ras.precision - 1 ) )
+#define SCALED( x )   ( ( (x) << ras.scale_shift ) - ras.precision_half )
+
+  /* Note that I have moved the location of some fields in the */
+  /* structure to ensure that the most used variables are used */
+  /* at the top.  Thus, their offset can be coded with less    */
+  /* opcodes, and it results in a smaller executable.          */
+
+  struct  TRaster_Instance_
+  {
+    Int       precision_bits;       /* precision related variables         */
+    Int       precision;
+    Int       precision_half;
+    Long      precision_mask;
+    Int       precision_shift;
+    Int       precision_step;
+    Int       precision_jitter;
+
+    Int       scale_shift;          /* == precision_shift   for bitmaps    */
+                                    /* == precision_shift+1 for pixmaps    */
+
+    PLong     buff;                 /* The profiles buffer                 */
+    PLong     sizeBuff;             /* Render pool size                    */
+    PLong     maxBuff;              /* Profiles buffer size                */
+    PLong     top;                  /* Current cursor in buffer            */
+
+    FT_Error  error;
+
+    Int       numTurns;             /* number of Y-turns in outline        */
+
+    TPoint*   arc;                  /* current Bezier arc pointer          */
+
+    UShort    bWidth;               /* target bitmap width                 */
+    PByte     bTarget;              /* target bitmap buffer                */
+    PByte     gTarget;              /* target pixmap buffer                */
+
+    Long      lastX, lastY, minY, maxY;
+
+    UShort    num_Profs;            /* current number of profiles          */
+
+    Bool      fresh;                /* signals a fresh new profile which   */
+                                    /* 'start' field must be completed     */
+    Bool      joint;                /* signals that the last arc ended     */
+                                    /* exactly on a scanline.  Allows      */
+                                    /* removal of doublets                 */
+    PProfile  cProfile;             /* current profile                     */
+    PProfile  fProfile;             /* head of linked list of profiles     */
+    PProfile  gProfile;             /* contour's first profile in case     */
+                                    /* of impact                           */
+
+    TStates   state;                /* rendering state                     */
+
+    FT_Bitmap   target;             /* description of target bit/pixmap    */
+    FT_Outline  outline;
+
+    Long      traceOfs;             /* current offset in target bitmap     */
+    Long      traceG;               /* current offset in target pixmap     */
+
+    Short     traceIncr;            /* sweep's increment in target bitmap  */
+
+    Short     gray_min_x;           /* current min x during gray rendering */
+    Short     gray_max_x;           /* current max x during gray rendering */
+
+    /* dispatch variables */
+
+    Function_Sweep_Init*  Proc_Sweep_Init;
+    Function_Sweep_Span*  Proc_Sweep_Span;
+    Function_Sweep_Span*  Proc_Sweep_Drop;
+    Function_Sweep_Step*  Proc_Sweep_Step;
+
+    Byte      dropOutControl;       /* current drop_out control method     */
+
+    Bool      second_pass;          /* indicates wether a horizontal pass  */
+                                    /* should be performed to control      */
+                                    /* drop-out accurately when calling    */
+                                    /* Render_Glyph.  Note that there is   */
+                                    /* no horizontal pass during gray      */
+                                    /* rendering.                          */
+
+    TPoint    arcs[2 * MaxBezier + 1]; /* The Bezier stack                 */
+
+    TBand     band_stack[16];       /* band stack used for sub-banding     */
+    Int       band_top;             /* band stack top                      */
+
+    Int       count_table[256];     /* Look-up table used to quickly count */
+                                    /* set bits in a gray 2x2 cell         */
+
+    void*     memory;
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+    Byte      grays[5];             /* Palette of gray levels used for     */
+                                    /* render.                             */
+
+    Byte      gray_lines[RASTER_GRAY_LINES];
+                                /* Intermediate table used to render the   */
+                                /* graylevels pixmaps.                     */
+                                /* gray_lines is a buffer holding two      */
+                                /* monochrome scanlines                    */
+
+    Short     gray_width;       /* width in bytes of one monochrome        */
+                                /* intermediate scanline of gray_lines.    */
+                                /* Each gray pixel takes 2 bits long there */
+
+                       /* The gray_lines must hold 2 lines, thus with size */
+                       /* in bytes of at least `gray_width*2'.             */
+
+#endif /* FT_RASTER_ANTI_ALIASING */
+
+#if 0
+    PByte       flags;              /* current flags table                 */
+    PUShort     outs;               /* current outlines table              */
+    FT_Vector*  coords;
+
+    UShort      nPoints;            /* number of points in current glyph   */
+    Short       nContours;          /* number of contours in current glyph */
+#endif
+
+  };
+
+
+#ifdef FT_CONFIG_OPTION_STATIC_RASTER
+
+  static TRaster_Instance  cur_ras;
+#define ras  cur_ras
+
+#else
+
+#define ras  (*raster)
+
+#endif /* FT_CONFIG_OPTION_STATIC_RASTER */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  PROFILES COMPUTATION                                               **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Set_High_Precision                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets precision variables according to param flag.                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    High :: Set to True for high precision (typically for ppem < 18),  */
+  /*            false otherwise.                                           */
+  /*                                                                       */
+  static
+  void  Set_High_Precision( RAS_ARGS Int  High )
+  {
+    if ( High )
+    {
+      ras.precision_bits   = 10;
+      ras.precision_step   = 128;
+      ras.precision_jitter = 24;
+    }
+    else
+    {
+      ras.precision_bits   = 6;
+      ras.precision_step   = 32;
+      ras.precision_jitter = 2;
+    }
+
+    FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
+
+    ras.precision       = 1L << ras.precision_bits;
+    ras.precision_half  = ras.precision / 2;
+    ras.precision_shift = ras.precision_bits - Pixel_Bits;
+    ras.precision_mask  = -ras.precision;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    New_Profile                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new profile in the render pool.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    aState :: The state/orientation of the new profile.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   SUCCESS on success.  FAILURE in case of overflow or of incoherent   */
+  /*   profile.                                                            */
+  /*                                                                       */
+  static
+  Bool  New_Profile( RAS_ARGS TStates  aState )
+  {
+    if ( !ras.fProfile )
+    {
+      ras.cProfile  = (PProfile)ras.top;
+      ras.fProfile  = ras.cProfile;
+      ras.top      += AlignProfileSize;
+    }
+
+    if ( ras.top >= ras.maxBuff )
+    {
+      ras.error = Raster_Err_Overflow;
+      return FAILURE;
+    }
+
+    switch ( aState )
+    {
+    case Ascending:
+      ras.cProfile->flow = Flow_Up;
+      FT_TRACE6(( "New ascending profile = %lx\n", (long)ras.cProfile ));
+      break;
+
+    case Descending:
+      ras.cProfile->flow = Flow_Down;
+      FT_TRACE6(( "New descending profile = %lx\n", (long)ras.cProfile ));
+      break;
+
+    default:
+      FT_ERROR(( "New_Profile: invalid profile direction!\n" ));
+      ras.error = Raster_Err_Invalid;
+      return FAILURE;
+    }
+
+    ras.cProfile->start  = 0;
+    ras.cProfile->height = 0;
+    ras.cProfile->offset = ras.top;
+    ras.cProfile->link   = (PProfile)0;
+    ras.cProfile->next   = (PProfile)0;
+
+    if ( !ras.gProfile )
+      ras.gProfile = ras.cProfile;
+
+    ras.state = aState;
+    ras.fresh = TRUE;
+    ras.joint = FALSE;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    End_Profile                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes the current profile.                                     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success.  FAILURE in case of overflow or incoherency.   */
+  /*                                                                       */
+  static
+  Bool  End_Profile( RAS_ARG )
+  {
+    Long      h;
+    PProfile  oldProfile;
+
+
+    h = ras.top - ras.cProfile->offset;
+
+    if ( h < 0 )
+    {
+      FT_ERROR(( "End_Profile: negative height encountered!\n" ));
+      ras.error = Raster_Err_Neg_Height;
+      return FAILURE;
+    }
+
+    if ( h > 0 )
+    {
+      FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ld\n",
+                  (long)ras.cProfile, ras.cProfile->start, h ));
+
+      oldProfile           = ras.cProfile;
+      ras.cProfile->height = h;
+      ras.cProfile         = (PProfile)ras.top;
+
+      ras.top             += AlignProfileSize;
+
+      ras.cProfile->height = 0;
+      ras.cProfile->offset = ras.top;
+      oldProfile->next     = ras.cProfile;
+      ras.num_Profs++;
+    }
+
+    if ( ras.top >= ras.maxBuff )
+    {
+      FT_TRACE1(( "overflow in End_Profile\n" ));
+      ras.error = Raster_Err_Overflow;
+      return FAILURE;
+    }
+
+    ras.joint = FALSE;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Insert_Y_Turn                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Inserts a salient into the sorted list placed on top of the render */
+  /*    pool.                                                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    New y scanline position.                                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
+  /*                                                                       */
+  static
+  Bool  Insert_Y_Turn( RAS_ARGS Int  y )
+  {
+    PLong     y_turns;
+    Int       y2, n;
+
+
+    n       = ras.numTurns - 1;
+    y_turns = ras.sizeBuff - ras.numTurns;
+
+    /* look for first y value that is <= */
+    while ( n >= 0 && y < y_turns[n] )
+      n--;
+
+    /* if it is <, simply insert it, ignore if == */
+    if ( n >= 0 && y > y_turns[n] )
+      while ( n >= 0 )
+      {
+        y2 = y_turns[n];
+        y_turns[n] = y;
+        y = y2;
+        n--;
+      }
+
+    if ( n < 0 )
+    {
+      if ( ras.maxBuff <= ras.top )
+      {
+        ras.error = Raster_Err_Overflow;
+        return FAILURE;
+      }
+      ras.maxBuff--;
+      ras.numTurns++;
+      ras.sizeBuff[-ras.numTurns] = y;
+    }
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Finalize_Profile_Table                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Adjusts all links in the profiles list.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
+  /*                                                                       */
+  static
+  Bool  Finalize_Profile_Table( RAS_ARG )
+  {
+    Int       bottom, top;
+    UShort    n;
+    PProfile  p;
+
+
+    n = ras.num_Profs;
+
+    if ( n > 1 )
+    {
+      p = ras.fProfile;
+      while ( n > 0 )
+      {
+        if ( n > 1 )
+          p->link = (PProfile)( p->offset + p->height );
+        else
+          p->link = NULL;
+
+        switch ( p->flow )
+        {
+        case Flow_Down:
+          bottom     = p->start - p->height+1;
+          top        = p->start;
+          p->start   = bottom;
+          p->offset += p->height - 1;
+          break;
+
+        case Flow_Up:
+        default:
+          bottom = p->start;
+          top    = p->start + p->height - 1;
+        }
+
+        if ( Insert_Y_Turn( RAS_VARS bottom )   ||
+             Insert_Y_Turn( RAS_VARS top + 1 )  )
+          return FAILURE;
+
+        p = p->link;
+        n--;
+      }
+    }
+    else
+      ras.fProfile = NULL;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Split_Conic                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Subdivides one conic Bezier into two joint sub-arcs in the Bezier  */
+  /*    stack.                                                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    None (subdivided Bezier is taken from the top of the stack).       */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This routine is the `beef' of this component.  It is  _the_ inner  */
+  /*    loop that should be optimized to hell to get the best performance. */
+  /*                                                                       */
+  static
+  void  Split_Conic( TPoint*  base )
+  {
+    Long  a, b;
+
+
+    base[4].x = base[2].x;
+    b = base[1].x;
+    a = base[3].x = ( base[2].x + b ) / 2;
+    b = base[1].x = ( base[0].x + b ) / 2;
+    base[2].x = ( a + b ) / 2;
+
+    base[4].y = base[2].y;
+    b = base[1].y;
+    a = base[3].y = ( base[2].y + b ) / 2;
+    b = base[1].y = ( base[0].y + b ) / 2;
+    base[2].y = ( a + b ) / 2;
+
+    /* hand optimized.  gcc doesn't seem to be too good at common      */
+    /* expression substitution and instruction scheduling ;-)          */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Split_Cubic                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Subdivides a third-order Bezier arc into two joint sub-arcs in the */
+  /*    Bezier stack.                                                      */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This routine is the `beef' of the component.  It is one of _the_   */
+  /*    inner loops that should be optimized like hell to get the best     */
+  /*    performance.                                                       */
+  /*                                                                       */
+  static
+  void  Split_Cubic( TPoint*  base )
+  {
+    Long  a, b, c, d;
+
+
+    base[6].x = base[3].x;
+    c = base[1].x;
+    d = base[2].x;
+    base[1].x = a = ( base[0].x + c + 1 ) >> 1;
+    base[5].x = b = ( base[3].x + d + 1 ) >> 1;
+    c = ( c + d + 1 ) >> 1;
+    base[2].x = a = ( a + c + 1 ) >> 1;
+    base[4].x = b = ( b + c + 1 ) >> 1;
+    base[3].x = ( a + b + 1 ) >> 1;
+
+    base[6].y = base[3].y;
+    c = base[1].y;
+    d = base[2].y;
+    base[1].y = a = ( base[0].y + c + 1 ) >> 1;
+    base[5].y = b = ( base[3].y + d + 1 ) >> 1;
+    c = ( c + d + 1 ) >> 1;
+    base[2].y = a = ( a + c + 1 ) >> 1;
+    base[4].y = b = ( b + c + 1 ) >> 1;
+    base[3].y = ( a + b + 1 ) >> 1;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Line_Up                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the x-coordinates of an ascending line segment and stores */
+  /*    them in the render pool.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    x1   :: The x-coordinate of the segment's start point.             */
+  /*                                                                       */
+  /*    y1   :: The y-coordinate of the segment's start point.             */
+  /*                                                                       */
+  /*    x2   :: The x-coordinate of the segment's end point.               */
+  /*                                                                       */
+  /*    y2   :: The y-coordinate of the segment's end point.               */
+  /*                                                                       */
+  /*    miny :: A lower vertical clipping bound value.                     */
+  /*                                                                       */
+  /*    maxy :: An upper vertical clipping bound value.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on render pool overflow.               */
+  /*                                                                       */
+  static
+  Bool  Line_Up( RAS_ARGS Long  x1,
+                          Long  y1,
+                          Long  x2,
+                          Long  y2,
+                          Long  miny,
+                          Long  maxy )
+  {
+    Long   Dx, Dy;
+    Int    e1, e2, f1, f2, size;     /* XXX: is `Short' sufficient? */
+    Long   Ix, Rx, Ax;
+
+    PLong  top;
+
+
+    Dx = x2 - x1;
+    Dy = y2 - y1;
+
+    if ( Dy <= 0 || y2 < miny || y1 > maxy )
+      return SUCCESS;
+
+    if ( y1 < miny )
+    {
+      /* Take care: miny-y1 can be a very large value; we use     */
+      /*            a slow MulDiv function to avoid clipping bugs */
+      x1 += SMulDiv( Dx, miny - y1, Dy );
+      e1  = TRUNC( miny );
+      f1  = 0;
+    }
+    else
+    {
+      e1 = TRUNC( y1 );
+      f1 = FRAC( y1 );
+    }
+
+    if ( y2 > maxy )
+    {
+      /* x2 += FMulDiv( Dx, maxy - y2, Dy );  UNNECESSARY */
+      e2  = TRUNC( maxy );
+      f2  = 0;
+    }
+    else
+    {
+      e2 = TRUNC( y2 );
+      f2 = FRAC( y2 );
+    }
+
+    if ( f1 > 0 )
+    {
+      if ( e1 == e2 )
+        return SUCCESS;
+      else
+      {
+        x1 += FMulDiv( Dx, ras.precision - f1, Dy );
+        e1 += 1;
+      }
+    }
+    else
+      if ( ras.joint )
+      {
+        ras.top--;
+        ras.joint = FALSE;
+      }
+
+    ras.joint = ( f2 == 0 );
+
+    if ( ras.fresh )
+    {
+      ras.cProfile->start = e1;
+      ras.fresh           = FALSE;
+    }
+
+    size = e2 - e1 + 1;
+    if ( ras.top + size >= ras.maxBuff )
+    {
+      ras.error = Raster_Err_Overflow;
+      return FAILURE;
+    }
+
+    if ( Dx > 0 )
+    {
+      Ix = ( ras.precision * Dx ) / Dy;
+      Rx = ( ras.precision * Dx ) % Dy;
+      Dx = 1;
+    }
+    else
+    {
+      Ix = -( ( ras.precision * -Dx ) / Dy );
+      Rx =    ( ras.precision * -Dx ) % Dy;
+      Dx = -1;
+    }
+
+    Ax  = -Dy;
+    top = ras.top;
+
+    while ( size > 0 )
+    {
+      *top++ = x1;
+
+      x1 += Ix;
+      Ax += Rx;
+      if ( Ax >= 0 )
+      {
+        Ax -= Dy;
+        x1 += Dx;
+      }
+      size--;
+    }
+
+    ras.top = top;
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Line_Down                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the x-coordinates of an descending line segment and       */
+  /*    stores them in the render pool.                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    x1   :: The x-coordinate of the segment's start point.             */
+  /*                                                                       */
+  /*    y1   :: The y-coordinate of the segment's start point.             */
+  /*                                                                       */
+  /*    x2   :: The x-coordinate of the segment's end point.               */
+  /*                                                                       */
+  /*    y2   :: The y-coordinate of the segment's end point.               */
+  /*                                                                       */
+  /*    miny :: A lower vertical clipping bound value.                     */
+  /*                                                                       */
+  /*    maxy :: An upper vertical clipping bound value.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on render pool overflow.               */
+  /*                                                                       */
+  static
+  Bool  Line_Down( RAS_ARGS Long  x1,
+                            Long  y1,
+                            Long  x2,
+                            Long  y2,
+                            Long  miny,
+                            Long  maxy )
+  {
+    Bool  result, fresh;
+
+
+    fresh  = ras.fresh;
+
+    result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
+
+    if ( fresh && !ras.fresh )
+      ras.cProfile->start = -ras.cProfile->start;
+
+    return result;
+  }
+
+
+  /* A function type describing the functions used to split Bezier arcs */
+  typedef void  (*TSplitter)( TPoint*  base );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Bezier_Up                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the x-coordinates of an ascending Bezier arc and stores   */
+  /*    them in the render pool.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
+  /*                                                                       */
+  /*    splitter :: The function to split Bezier arcs.                     */
+  /*                                                                       */
+  /*    miny     :: A lower vertical clipping bound value.                 */
+  /*                                                                       */
+  /*    maxy     :: An upper vertical clipping bound value.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on render pool overflow.               */
+  /*                                                                       */
+  static
+  Bool  Bezier_Up( RAS_ARGS Int        degree,
+                            TSplitter  splitter,
+                            Long       miny,
+                            Long       maxy )
+  {
+    Long   y1, y2, e, e2, e0;
+    Short  f1;
+
+    TPoint*  arc;
+    TPoint*  start_arc;
+
+    PLong top;
+
+
+    arc = ras.arc;
+    y1  = arc[degree].y;
+    y2  = arc[0].y;
+    top = ras.top;
+
+    if ( y2 < miny || y1 > maxy )
+      goto Fin;
+
+    e2 = FLOOR( y2 );
+
+    if ( e2 > maxy )
+      e2 = maxy;
+
+    e0 = miny;
+
+    if ( y1 < miny )
+      e = miny;
+    else
+    {
+      e  = CEILING( y1 );
+      f1 = FRAC( y1 );
+      e0 = e;
+
+      if ( f1 == 0 )
+      {
+        if ( ras.joint )
+        {
+          top--;
+          ras.joint = FALSE;
+        }
+
+        *top++ = arc[degree].x;
+
+        e += ras.precision;
+      }
+    }
+
+    if ( ras.fresh )
+    {
+      ras.cProfile->start = TRUNC( e0 );
+      ras.fresh = FALSE;
+    }
+
+    if ( e2 < e )
+      goto Fin;
+
+    if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
+    {
+      ras.top   = top;
+      ras.error = Raster_Err_Overflow;
+      return FAILURE;
+    }
+
+    start_arc = arc;
+
+    while ( arc >= start_arc && e <= e2 )
+    {
+      ras.joint = FALSE;
+
+      y2 = arc[0].y;
+
+      if ( y2 > e )
+      {
+        y1 = arc[degree].y;
+        if ( y2 - y1 >= ras.precision_step )
+        {
+          splitter( arc );
+          arc += degree;
+        }
+        else
+        {
+          *top++ = arc[degree].x + FMulDiv( arc[0].x-arc[degree].x,
+                                            e - y1, y2 - y1 );
+          arc -= degree;
+          e   += ras.precision;
+        }
+      }
+      else
+      {
+        if ( y2 == e )
+        {
+          ras.joint  = TRUE;
+          *top++     = arc[0].x;
+
+          e += ras.precision;
+        }
+        arc -= degree;
+      }
+    }
+
+  Fin:
+    ras.top  = top;
+    ras.arc -= degree;
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Bezier_Down                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the x-coordinates of an descending Bezier arc and stores  */
+  /*    them in the render pool.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
+  /*                                                                       */
+  /*    splitter :: The function to split Bezier arcs.                     */
+  /*                                                                       */
+  /*    miny     :: A lower vertical clipping bound value.                 */
+  /*                                                                       */
+  /*    maxy     :: An upper vertical clipping bound value.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on render pool overflow.               */
+  /*                                                                       */
+  static
+  Bool  Bezier_Down( RAS_ARGS Int        degree,
+                              TSplitter  splitter,
+                              Long       miny,
+                              Long       maxy )
+  {
+    TPoint*  arc = ras.arc;
+    Bool     result, fresh;
+
+
+    arc[0].y = -arc[0].y;
+    arc[1].y = -arc[1].y;
+    arc[2].y = -arc[2].y;
+    if ( degree > 2 )
+      arc[3].y = -arc[3].y;
+
+    fresh = ras.fresh;
+
+    result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );
+
+    if ( fresh && !ras.fresh )
+      ras.cProfile->start = -ras.cProfile->start;
+
+    arc[0].y = -arc[0].y;
+    return result;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Line_To                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Injects a new line segment and adjusts Profiles list.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*   x :: The x-coordinate of the segment's end point (its start point   */
+  /*        is stored in `LastX').                                         */
+  /*                                                                       */
+  /*   y :: The y-coordinate of the segment's end point (its start point   */
+  /*        is stored in `LastY').                                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
+  /*   profile.                                                            */
+  /*                                                                       */
+  static
+  Bool  Line_To( RAS_ARGS Long  x,
+                          Long  y )
+  {
+    /* First, detect a change of direction */
+
+    switch ( ras.state )
+    {
+    case Unknown:
+      if ( y > ras.lastY )
+      {
+        if ( New_Profile( RAS_VARS Ascending ) )
+          return FAILURE;
+      }
+      else
+      {
+        if ( y < ras.lastY )
+          if ( New_Profile( RAS_VARS Descending ) )
+            return FAILURE;
+      }
+      break;
+
+    case Ascending:
+      if ( y < ras.lastY )
+      {
+        if ( End_Profile( RAS_VAR )             ||
+             New_Profile( RAS_VARS Descending ) )
+          return FAILURE;
+      }
+      break;
+
+    case Descending:
+      if ( y > ras.lastY )
+      {
+        if ( End_Profile( RAS_VAR )            ||
+             New_Profile( RAS_VARS Ascending ) )
+          return FAILURE;
+      }
+      break;
+
+    default:
+      ;
+    }
+
+    /* Then compute the lines */
+
+    switch ( ras.state )
+    {
+    case Ascending:
+      if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
+                    x, y, ras.minY, ras.maxY ) )
+        return FAILURE;
+      break;
+
+    case Descending:
+      if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
+                      x, y, ras.minY, ras.maxY ) )
+        return FAILURE;
+      break;
+
+    default:
+      ;
+    }
+
+    ras.lastX = x;
+    ras.lastY = y;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Conic_To                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Injects a new conic arc and adjusts the profile list.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*   cx :: The x-coordinate of the arc's new control point.              */
+  /*                                                                       */
+  /*   cy :: The y-coordinate of the arc's new control point.              */
+  /*                                                                       */
+  /*   x  :: The x-coordinate of the arc's end point (its start point is   */
+  /*         stored in `LastX').                                           */
+  /*                                                                       */
+  /*   y  :: The y-coordinate of the arc's end point (its start point is   */
+  /*         stored in `LastY').                                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
+  /*   profile.                                                            */
+  /*                                                                       */
+  static
+  Bool  Conic_To( RAS_ARGS Long  cx,
+                           Long  cy,
+                           Long  x,
+                           Long  y )
+  {
+    Long     y1, y2, y3, x3, ymin, ymax;
+    TStates  state_bez;
+
+
+    ras.arc      = ras.arcs;
+    ras.arc[2].x = ras.lastX;
+    ras.arc[2].y = ras.lastY;
+    ras.arc[1].x = cx; ras.arc[1].y = cy;
+    ras.arc[0].x = x;  ras.arc[0].y = y;
+
+    do
+    {
+      y1 = ras.arc[2].y;
+      y2 = ras.arc[1].y;
+      y3 = ras.arc[0].y;
+      x3 = ras.arc[0].x;
+
+      /* first, categorize the Bezier arc */
+
+      if ( y1 <= y3 )
+      {
+        ymin = y1;
+        ymax = y3;
+      }
+      else
+      {
+        ymin = y3;
+        ymax = y1;
+      }
+
+      if ( y2 < ymin || y2 > ymax )
+      {
+        /* this arc has no given direction, split it! */
+        Split_Conic( ras.arc );
+        ras.arc += 2;
+      }
+      else if ( y1 == y3 )
+      {
+        /* this arc is flat, ignore it and pop it from the Bezier stack */
+        ras.arc -= 2;
+      }
+      else
+      {
+        /* the arc is y-monotonous, either ascending or descending */
+        /* detect a change of direction                            */
+        state_bez = y1 < y3 ? Ascending : Descending;
+        if ( ras.state != state_bez )
+        {
+          /* finalize current profile if any */
+          if ( ras.state != Unknown   &&
+               End_Profile( RAS_VAR ) )
+            goto Fail;
+
+          /* create a new profile */
+          if ( New_Profile( RAS_VARS state_bez ) )
+            goto Fail;
+        }
+
+        /* now call the appropriate routine */
+        if ( state_bez == Ascending )
+        {
+          if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
+            goto Fail;
+        }
+        else
+          if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
+            goto Fail;
+      }
+
+    } while ( ras.arc >= ras.arcs );
+
+    ras.lastX = x3;
+    ras.lastY = y3;
+
+    return SUCCESS;
+
+  Fail:
+    return FAILURE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Cubic_To                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Injects a new cubic arc and adjusts the profile list.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*   cx1 :: The x-coordinate of the arc's first new control point.       */
+  /*                                                                       */
+  /*   cy1 :: The y-coordinate of the arc's first new control point.       */
+  /*                                                                       */
+  /*   cx2 :: The x-coordinate of the arc's second new control point.      */
+  /*                                                                       */
+  /*   cy2 :: The y-coordinate of the arc's second new control point.      */
+  /*                                                                       */
+  /*   x   :: The x-coordinate of the arc's end point (its start point is  */
+  /*          stored in `LastX').                                          */
+  /*                                                                       */
+  /*   y   :: The y-coordinate of the arc's end point (its start point is  */
+  /*          stored in `LastY').                                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
+  /*   profile.                                                            */
+  /*                                                                       */
+  static
+  Bool  Cubic_To( RAS_ARGS Long  cx1,
+                           Long  cy1,
+                           Long  cx2,
+                           Long  cy2,
+                           Long  x,
+                           Long  y )
+  {
+    Long     y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;
+    TStates  state_bez;
+
+
+    ras.arc      = ras.arcs;
+    ras.arc[3].x = ras.lastX;
+    ras.arc[3].y = ras.lastY;
+    ras.arc[2].x = cx1; ras.arc[2].y = cy1;
+    ras.arc[1].x = cx2; ras.arc[1].y = cy2;
+    ras.arc[0].x = x;   ras.arc[0].y = y;
+
+    do
+    {
+      y1 = ras.arc[3].y;
+      y2 = ras.arc[2].y;
+      y3 = ras.arc[1].y;
+      y4 = ras.arc[0].y;
+      x4 = ras.arc[0].x;
+
+      /* first, categorize the Bezier arc */
+
+      if ( y1 <= y4 )
+      {
+        ymin1 = y1;
+        ymax1 = y4;
+      }
+      else
+      {
+        ymin1 = y4;
+        ymax1 = y1;
+      }
+
+      if ( y2 <= y3 )
+      {
+        ymin2 = y2;
+        ymax2 = y3;
+      }
+      else
+      {
+        ymin2 = y3;
+        ymax2 = y2;
+      }
+
+      if ( ymin2 < ymin1 || ymax2 > ymax1 )
+      {
+        /* this arc has no given direction, split it! */
+        Split_Cubic( ras.arc );
+        ras.arc += 3;
+      }
+      else if ( y1 == y4 )
+      {
+        /* this arc is flat, ignore it and pop it from the Bezier stack */
+        ras.arc -= 3;
+      }
+      else
+      {
+        state_bez = ( y1 <= y4 ) ? Ascending : Descending;
+
+        /* detect a change of direction */
+        if ( ras.state != state_bez )
+        {
+          if ( ras.state != Unknown   &&
+               End_Profile( RAS_VAR ) )
+            goto Fail;
+
+          if ( New_Profile( RAS_VARS state_bez ) )
+            goto Fail;
+        }
+
+        /* compute intersections */
+        if ( state_bez == Ascending )
+        {
+          if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
+            goto Fail;
+        }
+        else
+          if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
+            goto Fail;
+      }
+
+    } while ( ras.arc >= ras.arcs );
+
+    ras.lastX = x4;
+    ras.lastY = y4;
+
+    return SUCCESS;
+
+  Fail:
+    return FAILURE;
+  }
+
+
+#undef  SWAP_
+#define SWAP_( x, y )  do                \
+                       {                 \
+                         Long  swap = x; \
+                                         \
+                                         \
+                         x = y;          \
+                         y = swap;       \
+                       } while ( 0 )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Decompose_Curve                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Scans the outline arays in order to emit individual segments and   */
+  /*    Beziers by calling Line_To() and Bezier_To().  It handles all      */
+  /*    weird cases, like when the first point is off the curve, or when   */
+  /*    there are simply no `on' points in the contour!                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    first   :: The index of the first point in the contour.            */
+  /*                                                                       */
+  /*    last    :: The index of the last point in the contour.             */
+  /*                                                                       */
+  /*    flipped :: If set, flip the direction of the curve.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on error.                              */
+  /*                                                                       */
+  static
+  Bool  Decompose_Curve( RAS_ARGS UShort  first,
+                                  UShort  last,
+                                  int     flipped )
+  {
+    FT_Vector   v_last;
+    FT_Vector   v_control;
+    FT_Vector   v_start;
+
+    FT_Vector*  points;
+    FT_Vector*  point;
+    FT_Vector*  limit;
+    char*       tags;
+
+    char        tag;       /* current point's state           */
+
+
+    points = ras.outline.points;
+    limit  = points + last;
+
+    v_start.x = SCALED( points[first].x );
+    v_start.y = SCALED( points[first].y );
+    v_last.x  = SCALED( points[last].x );
+    v_last.y  = SCALED( points[last].y );
+
+    if ( flipped )
+    {
+      SWAP_( v_start.x, v_start.y );
+      SWAP_( v_last.x, v_last.y );
+    }
+
+    v_control = v_start;
+
+    point = points + first;
+    tags  = ras.outline.tags  + first;
+    tag   = FT_CURVE_TAG( tags[0] );
+
+    /* A contour cannot start with a cubic control point! */
+    if ( tag == FT_Curve_Tag_Cubic )
+      goto Invalid_Outline;
+
+    /* check first point to determine origin */
+    if ( tag == FT_Curve_Tag_Conic )
+    {
+      /* first point is conic control.  Yes, this happens. */
+      if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_Curve_Tag_On )
+      {
+        /* start at last point if it is on the curve */
+        v_start = v_last;
+        limit--;
+      }
+      else
+      {
+        /* if both first and last points are conic,         */
+        /* start at their middle and record its position    */
+        /* for closure                                      */
+        v_start.x = ( v_start.x + v_last.x ) / 2;
+        v_start.y = ( v_start.y + v_last.y ) / 2;
+
+        v_last = v_start;
+      }
+      point--;
+      tags--;
+    }
+
+    ras.lastX = v_start.x;
+    ras.lastY = v_start.y;
+
+    while ( point < limit )
+    {
+      point++;
+      tags++;
+
+      tag = FT_CURVE_TAG( tags[0] );
+
+      switch ( tag )
+      {
+      case FT_Curve_Tag_On:  /* emit a single line_to */
+        {
+          Long  x, y;
+
+
+          x = SCALED( point->x );
+          y = SCALED( point->y );
+          if ( flipped )
+            SWAP_( x, y );
+
+          if ( Line_To( RAS_VARS x, y ) )
+            goto Fail;
+          continue;
+        }
+
+      case FT_Curve_Tag_Conic:  /* consume conic arcs */
+        v_control.x = SCALED( point[0].x );
+        v_control.y = SCALED( point[0].y );
+
+        if ( flipped )
+          SWAP_( v_control.x, v_control.y );
+
+      Do_Conic:
+        if ( point < limit )
+        {
+          FT_Vector  v_middle;
+          Long       x, y;
+
+
+          point++;
+          tags++;
+          tag = FT_CURVE_TAG( tags[0] );
+
+          x = SCALED( point[0].x );
+          y = SCALED( point[0].y );
+
+          if ( flipped )
+            SWAP_( x, y );
+
+          if ( tag == FT_Curve_Tag_On )
+          {
+            if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) )
+              goto Fail;
+            continue;
+          }
+
+          if ( tag != FT_Curve_Tag_Conic )
+            goto Invalid_Outline;
+
+          v_middle.x = ( v_control.x + x ) / 2;
+          v_middle.y = ( v_control.y + y ) / 2;
+
+          if ( Conic_To( RAS_VARS v_control.x, v_control.y,
+                                  v_middle.x,  v_middle.y ) )
+            goto Fail;
+
+          v_control.x = x;
+          v_control.y = y;
+
+          goto Do_Conic;
+        }
+
+        if ( Conic_To( RAS_VARS v_control.x, v_control.y,
+                                v_start.x,   v_start.y ) )
+          goto Fail;
+
+        goto Close;
+
+      default:  /* FT_Curve_Tag_Cubic */
+        {
+          Long  x1, y1, x2, y2, x3, y3;
+
+
+          if ( point + 1 > limit                             ||
+               FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
+            goto Invalid_Outline;
+
+          point += 2;
+          tags  += 2;
+
+          x1 = SCALED( point[-2].x );
+          y1 = SCALED( point[-2].y );
+          x2 = SCALED( point[-1].x );
+          y2 = SCALED( point[-1].y );
+          x3 = SCALED( point[ 0].x );
+          y3 = SCALED( point[ 0].y );
+
+          if ( flipped )
+          {
+            SWAP_( x1, y1 );
+            SWAP_( x2, y2 );
+            SWAP_( x3, y3 );
+          }
+
+          if ( point <= limit )
+          {
+            if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) )
+              goto Fail;
+            continue;
+          }
+
+          if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) )
+            goto Fail;
+          goto Close;
+        }
+      }
+    }
+
+    /* close the contour with a line segment */
+    if ( Line_To( RAS_VARS v_start.x, v_start.y ) )
+      goto Fail;
+
+  Close:
+    return SUCCESS;
+
+  Invalid_Outline:
+    ras.error = Raster_Err_Invalid;
+
+  Fail:
+    return FAILURE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Convert_Glyph                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts a glyph into a series of segments and arcs and makes a    */
+  /*    profiles list with them.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    flipped :: If set, flip the direction of curve.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE if any error was encountered during    */
+  /*    rendering.                                                         */
+  /*                                                                       */
+  static
+  Bool  Convert_Glyph( RAS_ARGS int  flipped )
+  {
+    Short     i;
+    UShort    start;
+
+    PProfile  lastProfile;
+
+
+    ras.fProfile = NULL;
+    ras.joint    = FALSE;
+    ras.fresh    = FALSE;
+
+    ras.maxBuff  = ras.sizeBuff - AlignProfileSize;
+
+    ras.numTurns = 0;
+
+    ras.cProfile         = (PProfile)ras.top;
+    ras.cProfile->offset = ras.top;
+    ras.num_Profs        = 0;
+
+    start = 0;
+
+    for ( i = 0; i < ras.outline.n_contours; i++ )
+    {
+      ras.state    = Unknown;
+      ras.gProfile = NULL;
+
+      if ( Decompose_Curve( RAS_VARS start, ras.outline.contours[i], flipped ) )
+        return FAILURE;
+
+      start = ras.outline.contours[i] + 1;
+
+      /* We must now see whether the extreme arcs join or not */
+      if ( FRAC( ras.lastY ) == 0 &&
+           ras.lastY >= ras.minY  &&
+           ras.lastY <= ras.maxY  )
+        if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow )
+          ras.top--;
+        /* Note that ras.gProfile can be nil if the contour was too small */
+        /* to be drawn.                                                   */
+
+      lastProfile = ras.cProfile;
+      if ( End_Profile( RAS_VAR ) )
+        return FAILURE;
+
+      /* close the `next profile in contour' linked list */
+      if ( ras.gProfile )
+        lastProfile->next = ras.gProfile;
+    }
+
+    if ( Finalize_Profile_Table( RAS_VAR ) )
+      return FAILURE;
+
+    return ( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  SCAN-LINE SWEEPS AND DRAWING                                       **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Init_Linked                                                          */
+  /*                                                                       */
+  /*    Initializes an empty linked list.                                  */
+  /*                                                                       */
+  static
+  void  Init_Linked( TProfileList*  l )
+  {
+    *l = NULL;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  InsNew                                                               */
+  /*                                                                       */
+  /*    Inserts a new profile in a linked list.                            */
+  /*                                                                       */
+  static
+  void  InsNew( PProfileList  list,
+                PProfile      profile )
+  {
+    PProfile  *old, current;
+    Long       x;
+
+
+    old     = list;
+    current = *old;
+    x       = profile->X;
+
+    while ( current )
+    {
+      if ( x < current->X )
+        break;
+      old     = &current->link;
+      current = *old;
+    }
+
+    profile->link = current;
+    *old          = profile;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  DelOld                                                               */
+  /*                                                                       */
+  /*    Removes an old profile from a linked list.                         */
+  /*                                                                       */
+  static
+  void  DelOld( PProfileList  list,
+                PProfile      profile )
+  {
+    PProfile  *old, current;
+
+
+    old     = list;
+    current = *old;
+
+    while ( current )
+    {
+      if ( current == profile )
+      {
+        *old = current->link;
+        return;
+      }
+
+      old     = &current->link;
+      current = *old;
+    }
+
+    /* we should never get there, unless the profile was not part of */
+    /* the list.                                                     */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Update                                                               */
+  /*                                                                       */
+  /*    Update all X offsets of a drawing list.                            */
+  /*                                                                       */
+  static
+  void  Update( PProfile  first )
+  {
+    PProfile  current = first;
+
+
+    while ( current )
+    {
+      current->X       = *current->offset;
+      current->offset += current->flow;
+      current->height--;
+      current = current->link;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Sort                                                                 */
+  /*                                                                       */
+  /*    Sorts a trace list.  In 95%, the list is already sorted.  We need  */
+  /*    an algorithm which is fast in this case.  Bubble sort is enough    */
+  /*    and simple.                                                        */
+  /*                                                                       */
+  static
+  void  Sort( PProfileList  list )
+  {
+    PProfile  *old, current, next;
+
+
+    /* First, set the new X coordinate of each profile */
+    Update( *list );
+
+    /* Then sort them */
+    old     = list;
+    current = *old;
+
+    if ( !current )
+      return;
+
+    next = current->link;
+
+    while ( next )
+    {
+      if ( current->X <= next->X )
+      {
+        old     = &current->link;
+        current = *old;
+
+        if ( !current )
+          return;
+      }
+      else
+      {
+        *old          = next;
+        current->link = next->link;
+        next->link    = current;
+
+        old     = list;
+        current = *old;
+      }
+
+      next = current->link;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Vertical Sweep Procedure Set                                         */
+  /*                                                                       */
+  /*  These four routines are used during the vertical black/white sweep   */
+  /*  phase by the generic Draw_Sweep() function.                          */
+  /*                                                                       */
+  /*************************************************************************/
+
+  static
+  void  Vertical_Sweep_Init( RAS_ARGS Short*  min,
+                                      Short*  max )
+  {
+    Long  pitch = ras.target.pitch;
+
+    FT_UNUSED( max );
+
+
+    ras.traceIncr = (Short)-pitch;
+    ras.traceOfs  = -*min * pitch;
+    if ( pitch > 0 )
+      ras.traceOfs += ( ras.target.rows - 1 ) * pitch;
+
+    ras.gray_min_x = 0;
+    ras.gray_max_x = 0;
+  }
+
+
+  static
+  void  Vertical_Sweep_Span( RAS_ARGS Short       y,
+                                      FT_F26Dot6  x1,
+                                      FT_F26Dot6  x2,
+                                      PProfile    left,
+                                      PProfile    right )
+  {
+    Long   e1, e2;
+    Short  c1, c2;
+    Byte   f1, f2;
+    Byte*  target;
+
+    FT_UNUSED( y );
+    FT_UNUSED( left );
+    FT_UNUSED( right );
+
+
+    /* Drop-out control */
+
+    e1 = TRUNC( CEILING( x1 ) );
+
+    if ( x2 - x1 - ras.precision <= ras.precision_jitter )
+      e2 = e1;
+    else
+      e2 = TRUNC( FLOOR( x2 ) );
+
+    if ( e2 >= 0 && e1 < ras.bWidth )
+    {
+      if ( e1 < 0 )
+        e1 = 0;
+      if ( e2 >= ras.bWidth )
+        e2 = ras.bWidth - 1;
+
+      c1 = (Short)( e1 >> 3 );
+      c2 = (Short)( e2 >> 3 );
+
+      f1 =    (unsigned char)0xFF >> ( e1 & 7 );
+      f2 = ~( (unsigned char)0x7F >> ( e2 & 7 ) );
+
+      if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
+      if ( ras.gray_max_x < c2 ) ras.gray_max_x = c2;
+
+      target = ras.bTarget + ras.traceOfs + c1;
+      c2 -= c1;
+
+      if ( c2 > 0 )
+      {
+        target[0] |= f1;
+
+        /* memset() is slower than the following code on many platforms. */
+        /* This is due to the fact that, in the vast majority of cases,  */
+        /* the span length in bytes is relatively small.                 */
+        c2--;
+        while ( c2 > 0 )
+        {
+          *(++target) = 0xFF;
+          c2--;
+        }
+        target[1] |= f2;
+      }
+      else
+        *target |= ( f1 & f2 );
+    }
+  }
+
+
+  static
+  void Vertical_Sweep_Drop( RAS_ARGS Short       y,
+                                     FT_F26Dot6  x1,
+                                     FT_F26Dot6  x2,
+                                     PProfile    left,
+                                     PProfile    right )
+  {
+    Long   e1, e2;
+    Short  c1, f1;
+
+
+    /* Drop-out control */
+
+    e1 = CEILING( x1 );
+    e2 = FLOOR  ( x2 );
+
+    if ( e1 > e2 )
+    {
+      if ( e1 == e2 + ras.precision )
+      {
+        switch ( ras.dropOutControl )
+        {
+        case 1:
+          e1 = e2;
+          break;
+
+        case 4:
+          e1 = CEILING( (x1 + x2 + 1) / 2 );
+          break;
+
+        case 2:
+        case 5:
+          /* Drop-out Control Rule #4 */
+
+          /* The spec is not very clear regarding rule #4.  It      */
+          /* presents a method that is way too costly to implement  */
+          /* while the general idea seems to get rid of `stubs'.    */
+          /*                                                        */
+          /* Here, we only get rid of stubs recognized if:          */
+          /*                                                        */
+          /*  upper stub:                                           */
+          /*                                                        */
+          /*   - P_Left and P_Right are in the same contour         */
+          /*   - P_Right is the successor of P_Left in that contour */
+          /*   - y is the top of P_Left and P_Right                 */
+          /*                                                        */
+          /*  lower stub:                                           */
+          /*                                                        */
+          /*   - P_Left and P_Right are in the same contour         */
+          /*   - P_Left is the successor of P_Right in that contour */
+          /*   - y is the bottom of P_Left                          */
+          /*                                                        */
+
+          /* FIXXXME: uncommenting this line solves the disappearing */
+          /*          bit problem in the `7' of verdana 10pts, but   */
+          /*          makes a new one in the `C' of arial 14pts      */
+
+#if 0
+          if ( x2 - x1 < ras.precision_half )
+#endif
+          {
+            /* upper stub test */
+            if ( left->next == right && left->height <= 0 )
+              return;
+
+            /* lower stub test */
+            if ( right->next == left && left->start == y )
+              return;
+          }
+
+          /* check that the rightmost pixel isn't set */
+
+          e1 = TRUNC( e1 );
+
+          c1 = (Short)( e1 >> 3 );
+          f1 = e1 &  7;
+
+          if ( e1 >= 0 && e1 < ras.bWidth                      &&
+               ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
+            return;
+
+          if ( ras.dropOutControl == 2 )
+            e1 = e2;
+          else
+            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+          break;
+
+        default:
+          return;  /* unsupported mode */
+        }
+      }
+      else
+        return;
+    }
+
+    e1 = TRUNC( e1 );
+
+    if ( e1 >= 0 && e1 < ras.bWidth )
+    {
+      c1 = (Short)( e1 >> 3 );
+      f1 = e1 & 7;
+
+      if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
+      if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1;
+
+      ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
+    }
+  }
+
+
+  static
+  void Vertical_Sweep_Step( RAS_ARG )
+  {
+    ras.traceOfs += ras.traceIncr;
+  }
+
+
+  /***********************************************************************/
+  /*                                                                     */
+  /*  Horizontal Sweep Procedure Set                                     */
+  /*                                                                     */
+  /*  These four routines are used during the horizontal black/white     */
+  /*  sweep phase by the generic Draw_Sweep() function.                  */
+  /*                                                                     */
+  /***********************************************************************/
+
+  static
+  void  Horizontal_Sweep_Init( RAS_ARGS Short*  min,
+                                        Short*  max )
+  {
+    /* nothing, really */
+    FT_UNUSED( raster );
+    FT_UNUSED( min );
+    FT_UNUSED( max );
+  }
+
+
+  static
+  void  Horizontal_Sweep_Span( RAS_ARGS Short       y,
+                                        FT_F26Dot6  x1,
+                                        FT_F26Dot6  x2,
+                                        PProfile    left,
+                                        PProfile    right )
+  {
+    Long   e1, e2;
+    PByte  bits;
+    Byte   f1;
+
+    FT_UNUSED( left );
+    FT_UNUSED( right );
+
+
+    if ( x2 - x1 < ras.precision )
+    {
+      e1 = CEILING( x1 );
+      e2 = FLOOR  ( x2 );
+
+      if ( e1 == e2 )
+      {
+        bits = ras.bTarget + ( y >> 3 );
+        f1   = (Byte)( 0x80 >> ( y & 7 ) );
+
+        e1 = TRUNC( e1 );
+
+        if ( e1 >= 0 && e1 < ras.target.rows )
+        {
+          PByte  p;
+
+
+          p = bits - e1*ras.target.pitch;
+          if ( ras.target.pitch > 0 )
+            p += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+          p[0] |= f1;
+        }
+      }
+    }
+  }
+
+
+  static
+  void  Horizontal_Sweep_Drop( RAS_ARGS Short       y,
+                                        FT_F26Dot6  x1,
+                                        FT_F26Dot6  x2,
+                                        PProfile    left,
+                                        PProfile    right )
+  {
+    Long   e1, e2;
+    PByte  bits;
+    Byte   f1;
+
+
+    /* During the horizontal sweep, we only take care of drop-outs */
+
+    e1 = CEILING( x1 );
+    e2 = FLOOR  ( x2 );
+
+    if ( e1 > e2 )
+    {
+      if ( e1 == e2 + ras.precision )
+      {
+        switch ( ras.dropOutControl )
+        {
+        case 1:
+          e1 = e2;
+          break;
+
+        case 4:
+          e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+          break;
+
+        case 2:
+        case 5:
+
+          /* Drop-out Control Rule #4 */
+
+          /* The spec is not very clear regarding rule #4.  It      */
+          /* presents a method that is way too costly to implement  */
+          /* while the general idea seems to get rid of `stubs'.    */
+          /*                                                        */
+
+          /* rightmost stub test */
+          if ( left->next == right && left->height <= 0 )
+            return;
+
+          /* leftmost stub test */
+          if ( right->next == left && left->start == y )
+            return;
+
+          /* check that the rightmost pixel isn't set */
+
+          e1 = TRUNC( e1 );
+
+          bits = ras.bTarget + ( y >> 3 );
+          f1   = (Byte)( 0x80 >> ( y & 7 ) );
+
+          bits -= e1 * ras.target.pitch;
+          if ( ras.target.pitch > 0 )
+            bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+          if ( e1 >= 0              &&
+               e1 < ras.target.rows &&
+               *bits & f1 )
+            return;
+
+          if ( ras.dropOutControl == 2 )
+            e1 = e2;
+          else
+            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+          break;
+
+        default:
+          return;  /* unsupported mode */
+        }
+      }
+      else
+        return;
+    }
+
+    bits = ras.bTarget + ( y >> 3 );
+    f1   = (Byte)( 0x80 >> ( y & 7 ) );
+
+    e1 = TRUNC( e1 );
+
+    if ( e1 >= 0 && e1 < ras.target.rows )
+    {
+      bits -= e1 * ras.target.pitch;
+      if ( ras.target.pitch > 0 )
+        bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+      bits[0] |= f1;
+    }
+  }
+
+
+  static
+  void Horizontal_Sweep_Step( RAS_ARG )
+  {
+    /* Nothing, really */
+    FT_UNUSED( raster );
+  }
+
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Vertical Gray Sweep Procedure Set                                    */
+  /*                                                                       */
+  /*  These two routines are used during the vertical gray-levels sweep    */
+  /*  phase by the generic Draw_Sweep() function.                          */
+  /*                                                                       */
+  /*  NOTES                                                                */
+  /*                                                                       */
+  /*  - The target pixmap's width *must* be a multiple of 4.               */
+  /*                                                                       */
+  /*  - You have to use the function Vertical_Sweep_Span() for the gray    */
+  /*    span call.                                                         */
+  /*                                                                       */
+  /*************************************************************************/
+
+  static
+  void  Vertical_Gray_Sweep_Init( RAS_ARGS Short*  min,
+                                           Short*  max )
+  {
+    Long  pitch, byte_len;
+
+
+    *min = *min & -2;
+    *max = ( *max + 3 ) & -2;
+
+    ras.traceOfs  = 0;
+    pitch         = ras.target.pitch;
+    byte_len      = -pitch;
+    ras.traceIncr = (Short)byte_len;
+    ras.traceG    = ( *min / 2 ) * byte_len;
+
+    if ( pitch > 0 )
+    {
+      ras.traceG += ( ras.target.rows - 1 ) * pitch;
+      byte_len    = -byte_len;
+    }
+
+    ras.gray_min_x =  (Short)byte_len;
+    ras.gray_max_x = -(Short)byte_len;
+  }
+
+
+  static
+  void  Vertical_Gray_Sweep_Step( RAS_ARG )
+  {
+    Int    c1, c2;
+    PByte  pix, bit, bit2;
+    Int*   count = ras.count_table;
+    Byte*  grays;
+
+
+    ras.traceOfs += ras.gray_width;
+
+    if ( ras.traceOfs > ras.gray_width )
+    {
+      pix   = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
+      grays = ras.grays;
+
+      if ( ras.gray_max_x >= 0 )
+      {
+        Long   last_pixel = ras.target.width - 1;
+        Int    last_cell  = last_pixel >> 2;
+        Int    last_bit   = last_pixel & 3;
+        Bool   over       = 0;
+
+
+        if ( ras.gray_max_x >= last_cell && last_bit != 3 )
+        {
+          ras.gray_max_x = last_cell - 1;
+          over = 1;
+        }
+
+        if ( ras.gray_min_x < 0 )
+          ras.gray_min_x = 0;
+
+        bit   = ras.bTarget + ras.gray_min_x;
+        bit2  = bit + ras.gray_width;
+
+        c1 = ras.gray_max_x - ras.gray_min_x;
+
+        while ( c1 >= 0 )
+        {
+          c2 = count[*bit] + count[*bit2];
+
+          if ( c2 )
+          {
+            pix[0] = grays[(c2 >> 12) & 0x000F];
+            pix[1] = grays[(c2 >> 8 ) & 0x000F];
+            pix[2] = grays[(c2 >> 4 ) & 0x000F];
+            pix[3] = grays[ c2        & 0x000F];
+
+            *bit  = 0;
+            *bit2 = 0;
+          }
+
+          bit++;
+          bit2++;
+          pix += 4;
+          c1--;
+        }
+
+        if ( over )
+        {
+          c2 = count[*bit] + count[*bit2];
+          if ( c2 )
+          {
+            switch ( last_bit )
+            {
+            case 2:
+              pix[2] = grays[(c2 >> 4 ) & 0x000F];
+            case 1:
+              pix[1] = grays[(c2 >> 8 ) & 0x000F];
+            default:
+              pix[0] = grays[(c2 >> 12) & 0x000F];
+            }
+
+            *bit  = 0;
+            *bit2 = 0;
+          }
+        }
+      }
+
+      ras.traceOfs = 0;
+      ras.traceG  += ras.traceIncr;
+
+      ras.gray_min_x =  32000;
+      ras.gray_max_x = -32000;
+    }
+  }
+
+
+  static
+  void  Horizontal_Gray_Sweep_Span( RAS_ARGS Short       y,
+                                             FT_F26Dot6  x1,
+                                             FT_F26Dot6  x2,
+                                             PProfile    left,
+                                             PProfile    right )
+  {
+    /* nothing, really */
+    FT_UNUSED( raster );
+    FT_UNUSED( y );
+    FT_UNUSED( x1 );
+    FT_UNUSED( x2 );
+    FT_UNUSED( left );
+    FT_UNUSED( right );
+  }
+
+
+  static
+  void  Horizontal_Gray_Sweep_Drop( RAS_ARGS Short       y,
+                                             FT_F26Dot6  x1,
+                                             FT_F26Dot6  x2,
+                                             PProfile    left,
+                                             PProfile    right )
+  {
+    Long   e1, e2;
+    PByte  pixel;
+    Byte   color;
+
+
+    /* During the horizontal sweep, we only take care of drop-outs */
+    e1 = CEILING( x1 );
+    e2 = FLOOR  ( x2 );
+
+    if ( e1 > e2 )
+    {
+      if ( e1 == e2 + ras.precision )
+      {
+        switch ( ras.dropOutControl )
+        {
+        case 1:
+          e1 = e2;
+          break;
+
+        case 4:
+          e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+          break;
+
+        case 2:
+        case 5:
+
+          /* Drop-out Control Rule #4 */
+
+          /* The spec is not very clear regarding rule #4.  It      */
+          /* presents a method that is way too costly to implement  */
+          /* while the general idea seems to get rid of `stubs'.    */
+          /*                                                        */
+
+          /* rightmost stub test */
+          if ( left->next == right && left->height <= 0 )
+            return;
+
+          /* leftmost stub test */
+          if ( right->next == left && left->start == y )
+            return;
+
+          if ( ras.dropOutControl == 2 )
+            e1 = e2;
+          else
+            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+          break;
+
+        default:
+          return;  /* unsupported mode */
+        }
+      }
+      else
+        return;
+    }
+
+    if ( e1 >= 0 )
+    {
+      if ( x2 - x1 >= ras.precision_half )
+        color = ras.grays[2];
+      else
+        color = ras.grays[1];
+
+      e1 = TRUNC( e1 ) / 2;
+      if ( e1 < ras.target.rows )
+      {
+        pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;
+        if ( ras.target.pitch > 0 )
+          pixel += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+        if ( pixel[0] == ras.grays[0] )
+          pixel[0] = color;
+      }
+    }
+  }
+
+
+#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Generic Sweep Drawing routine                                        */
+  /*                                                                       */
+  /*************************************************************************/
+
+  static
+  Bool  Draw_Sweep( RAS_ARG )
+  {
+    Short         y, y_change, y_height;
+
+    PProfile      P, Q, P_Left, P_Right;
+
+    Short         min_Y, max_Y, top, bottom, dropouts;
+
+    Long          x1, x2, xs, e1, e2;
+
+    TProfileList  wait;
+    TProfileList  draw_left, draw_right;
+
+
+    /* Init empty linked lists */
+
+    Init_Linked( &wait );
+
+    Init_Linked( &draw_left  );
+    Init_Linked( &draw_right );
+
+    /* first, compute min and max Y */
+
+    P     = ras.fProfile;
+    max_Y = (Short)TRUNC( ras.minY );
+    min_Y = (Short)TRUNC( ras.maxY );
+
+    while ( P )
+    {
+      Q = P->link;
+
+      bottom = (Short)P->start;
+      top    = (Short)P->start + P->height - 1;
+
+      if ( min_Y > bottom ) min_Y = bottom;
+      if ( max_Y < top    ) max_Y = top;
+
+      P->X = 0;
+      InsNew( &wait, P );
+
+      P = Q;
+    }
+
+    /* Check the Y-turns */
+    if ( ras.numTurns == 0 )
+    {
+      ras.error = Raster_Err_Invalid;
+      return FAILURE;
+    }
+
+    /* Now inits the sweep */
+
+    ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );
+
+    /* Then compute the distance of each profile from min_Y */
+
+    P = wait;
+
+    while ( P )
+    {
+      P->countL = P->start - min_Y;
+      P = P->link;
+    }
+
+    /* Let's go */
+
+    y        = min_Y;
+    y_height = 0;
+
+    if ( ras.numTurns > 0 &&
+         ras.sizeBuff[-ras.numTurns] == min_Y )
+      ras.numTurns--;
+
+    while ( ras.numTurns > 0 )
+    {
+      /* look in the wait list for new activations */
+
+      P = wait;
+
+      while ( P )
+      {
+        Q = P->link;
+        P->countL -= y_height;
+        if ( P->countL == 0 )
+        {
+          DelOld( &wait, P );
+
+          switch ( P->flow )
+          {
+          case Flow_Up:
+            InsNew( &draw_left,  P );
+            break;
+
+          case Flow_Down:
+            InsNew( &draw_right, P );
+            break;
+          }
+        }
+
+        P = Q;
+      }
+
+      /* Sort the drawing lists */
+
+      Sort( &draw_left );
+      Sort( &draw_right );
+
+      y_change = (Short)ras.sizeBuff[-ras.numTurns--];
+      y_height = y_change - y;
+
+      while ( y < y_change )
+      {
+        /* Let's trace */
+
+        dropouts = 0;
+
+        P_Left  = draw_left;
+        P_Right = draw_right;
+
+        while ( P_Left )
+        {
+          x1 = P_Left ->X;
+          x2 = P_Right->X;
+
+          if ( x1 > x2 )
+          {
+            xs = x1;
+            x1 = x2;
+            x2 = xs;
+          }
+
+          if ( x2 - x1 <= ras.precision )
+          {
+            e1 = FLOOR( x1 );
+            e2 = CEILING( x2 );
+
+            if ( ras.dropOutControl != 0                 &&
+                 ( e1 > e2 || e2 == e1 + ras.precision ) )
+            {
+              /* a drop out was detected */
+
+              P_Left ->X = x1;
+              P_Right->X = x2;
+
+              /* mark profile for drop-out processing */
+              P_Left->countL = 1;
+              dropouts++;
+
+              goto Skip_To_Next;
+            }
+          }
+
+          ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
+
+        Skip_To_Next:
+
+          P_Left  = P_Left->link;
+          P_Right = P_Right->link;
+        }
+
+        /* now perform the dropouts _after_ the span drawing -- */
+        /* drop-outs processing has been moved out of the loop  */
+        /* for performance tuning                               */
+        if ( dropouts > 0 )
+          goto Scan_DropOuts;
+
+      Next_Line:
+
+        ras.Proc_Sweep_Step( RAS_VAR );
+
+        y++;
+
+        if ( y < y_change )
+        {
+          Sort( &draw_left  );
+          Sort( &draw_right );
+        }
+      }
+
+      /* Now finalize the profiles that needs it */
+
+      P = draw_left;
+      while ( P )
+      {
+        Q = P->link;
+        if ( P->height == 0 )
+          DelOld( &draw_left, P );
+        P = Q;
+      }
+
+      P = draw_right;
+      while ( P )
+      {
+        Q = P->link;
+        if ( P->height == 0 )
+          DelOld( &draw_right, P );
+        P = Q;
+      }
+    }
+
+    /* for gray-scaling, flushes the bitmap scanline cache */
+    while ( y <= max_Y )
+    {
+      ras.Proc_Sweep_Step( RAS_VAR );
+      y++;
+    }
+
+    return SUCCESS;
+
+  Scan_DropOuts:
+
+    P_Left  = draw_left;
+    P_Right = draw_right;
+
+    while ( P_Left )
+    {
+      if ( P_Left->countL )
+      {
+        P_Left->countL = 0;
+#if 0
+        dropouts--;  /* -- this is useful when debugging only */
+#endif
+        ras.Proc_Sweep_Drop( RAS_VARS y,
+                                      P_Left->X,
+                                      P_Right->X,
+                                      P_Left,
+                                      P_Right );
+      }
+
+      P_Left  = P_Left->link;
+      P_Right = P_Right->link;
+    }
+
+    goto Next_Line;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Render_Single_Pass                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Performs one sweep with sub-banding.                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    flipped :: If set, flip the direction of the outline.              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Renderer error code.                                               */
+  /*                                                                       */
+  static
+  int  Render_Single_Pass( RAS_ARGS Bool  flipped )
+  {
+    Short  i, j, k;
+
+
+    while ( ras.band_top >= 0 )
+    {
+      ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;
+      ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;
+
+      ras.top = ras.buff;
+
+      ras.error = Raster_Err_None;
+
+      if ( Convert_Glyph( RAS_VARS flipped ) )
+      {
+        if ( ras.error != Raster_Err_Overflow )
+          return FAILURE;
+
+        ras.error = Raster_Err_None;
+
+        /* sub-banding */
+
+#ifdef DEBUG_RASTER
+        ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );
+#endif
+
+        i = ras.band_stack[ras.band_top].y_min;
+        j = ras.band_stack[ras.band_top].y_max;
+
+        k = ( i + j ) / 2;
+
+        if ( ras.band_top >= 7 || k < i )
+        {
+          ras.band_top = 0;
+          ras.error    = Raster_Err_Invalid;
+
+          return ras.error;
+        }
+
+        ras.band_stack[ras.band_top + 1].y_min = k;
+        ras.band_stack[ras.band_top + 1].y_max = j;
+
+        ras.band_stack[ras.band_top].y_max = k - 1;
+
+        ras.band_top++;
+      }
+      else
+      {
+        if ( ras.fProfile )
+          if ( Draw_Sweep( RAS_VAR ) )
+             return ras.error;
+        ras.band_top--;
+      }
+    }
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Render_Glyph                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Renders a glyph in a bitmap.  Sub-banding if needed.               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  Render_Glyph( RAS_ARG )
+  {
+    FT_Error  error;
+
+
+    Set_High_Precision( RAS_VARS ras.outline.flags &
+                        ft_outline_high_precision );
+    ras.scale_shift    = ras.precision_shift;
+    ras.dropOutControl = 2;
+    ras.second_pass    = !( ras.outline.flags & ft_outline_single_pass );
+
+    /* Vertical Sweep */
+    ras.Proc_Sweep_Init = Vertical_Sweep_Init;
+    ras.Proc_Sweep_Span = Vertical_Sweep_Span;
+    ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
+    ras.Proc_Sweep_Step = Vertical_Sweep_Step;
+
+    ras.band_top            = 0;
+    ras.band_stack[0].y_min = 0;
+    ras.band_stack[0].y_max = ras.target.rows - 1;
+
+    ras.bWidth  = ras.target.width;
+    ras.bTarget = (Byte*)ras.target.buffer;
+
+    if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
+      return error;
+
+    /* Horizontal Sweep */
+    if ( ras.second_pass && ras.dropOutControl != 0 )
+    {
+      ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
+      ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
+      ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
+      ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
+
+      ras.band_top            = 0;
+      ras.band_stack[0].y_min = 0;
+      ras.band_stack[0].y_max = ras.target.width - 1;
+
+      if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
+        return error;
+    }
+
+    return FT_Err_Ok;
+  }
+
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Render_Gray_Glyph                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Renders a glyph with grayscaling.  Sub-banding if needed.          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  Render_Gray_Glyph( RAS_ARG )
+  {
+    Long      pixel_width;
+    FT_Error  error;
+
+
+    Set_High_Precision( RAS_VARS ras.outline.flags &
+                        ft_outline_high_precision );
+    ras.scale_shift    = ras.precision_shift + 1;
+    ras.dropOutControl = 2;
+    ras.second_pass    = !( ras.outline.flags & ft_outline_single_pass );
+
+    /* Vertical Sweep */
+
+    ras.band_top            = 0;
+    ras.band_stack[0].y_min = 0;
+    ras.band_stack[0].y_max = 2 * ras.target.rows - 1;
+
+    ras.bWidth  = ras.gray_width;
+    pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );
+
+    if ( ras.bWidth > pixel_width )
+      ras.bWidth = pixel_width;
+
+    ras.bWidth  = ras.bWidth * 8;
+    ras.bTarget = (Byte*)ras.gray_lines;
+    ras.gTarget = (Byte*)ras.target.buffer;
+
+    ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;
+    ras.Proc_Sweep_Span = Vertical_Sweep_Span;
+    ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
+    ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;
+
+    error = Render_Single_Pass( RAS_VARS 0 );
+    if ( error )
+      return error;
+
+    /* Horizontal Sweep */
+    if ( ras.second_pass && ras.dropOutControl != 0 )
+    {
+      ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
+      ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;
+      ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;
+      ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
+
+      ras.band_top            = 0;
+      ras.band_stack[0].y_min = 0;
+      ras.band_stack[0].y_max = ras.target.width * 2 - 1;
+
+      error = Render_Single_Pass( RAS_VARS 1 );
+      if ( error )
+        return error;
+    }
+
+    return FT_Err_Ok;
+  }
+
+#else /* FT_RASTER_OPTION_ANTI_ALIASING */
+
+  LOCAL_FUNC
+  FT_Error  Render_Gray_Glyph( RAS_ARG )
+  {
+    FT_UNUSED_RASTER;
+
+    return FT_Err_Cannot_Render_Glyph;
+  }
+
+#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
+
+
+  static
+  void  ft_black_init( TRaster_Instance*  raster )
+  {
+    FT_UInt  n;
+    FT_ULong c;
+
+
+    /* setup count table */
+    for ( n = 0; n < 256; n++ )
+    {
+      c = ( n & 0x55 ) + ( ( n & 0xAA ) >> 1 );
+
+      c = ( ( c << 6 ) & 0x3000 ) |
+          ( ( c << 4 ) & 0x0300 ) |
+          ( ( c << 2 ) & 0x0030 ) |
+                   (c  & 0x0003 );
+
+      raster->count_table[n] = c;
+    }
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+    /* set default 5-levels gray palette */
+    for ( n = 0; n < 5; n++ )
+      raster->grays[n] = n * 255 / 4;
+
+    raster->gray_width = RASTER_GRAY_LINES / 2;
+
+#endif
+  }
+
+
+  /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
+  /****                         a static object.                  *****/
+
+
+#ifdef _STANDALONE_
+
+
+  static
+  int  ft_black_new( void*      memory,
+                     FT_Raster  *araster )
+  {
+     static FT_RasterRec_  the_raster;
+
+
+     *araster = &the_raster;
+     memset( &the_raster, sizeof ( the_raster ), 0 );
+     ft_black_init( &the_raster );
+
+     return 0;
+  }
+
+
+  static
+  void  ft_black_done( FT_Raster  raster )
+  {
+    /* nothing */
+    raster->init = 0;
+  }
+
+
+#else /* _STANDALONE_ */
+
+
+  static
+  int  ft_black_new( FT_Memory           memory,
+                     TRaster_Instance**  araster )
+  {
+    FT_Error           error;
+    TRaster_Instance*  raster;
+
+
+    *araster = 0;
+    if ( !ALLOC( raster, sizeof ( *raster ) ) )
+    {
+      raster->memory = memory;
+      ft_black_init( raster );
+
+      *araster = raster;
+    }
+
+    return error;
+  }
+
+
+  static
+  void ft_black_done( TRaster_Instance*  raster )
+  {
+    FT_Memory  memory = (FT_Memory)raster->memory;
+    FREE( raster );
+  }
+
+
+#endif /* _STANDALONE_ */
+
+
+  static
+  void ft_black_reset( TRaster_Instance*  raster,
+                       const char*        pool_base,
+                       long               pool_size )
+  {
+    if ( raster && pool_base && pool_size >= 4096 )
+    {
+      /* save the pool */
+      raster->buff     = (PLong)pool_base;
+      raster->sizeBuff = raster->buff + pool_size / sizeof ( Long );
+    }
+  }
+
+
+  static
+  void ft_black_set_mode( TRaster_Instance* raster,
+                          unsigned long     mode,
+                          const char*       palette )
+  {
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+    if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )
+    {
+      /* set 5-levels gray palette */
+      raster->grays[0] = palette[0];
+      raster->grays[1] = palette[1];
+      raster->grays[2] = palette[2];
+      raster->grays[3] = palette[3];
+      raster->grays[4] = palette[4];
+    }
+
+#else
+
+    FT_UNUSED( raster );
+    FT_UNUSED( mode );
+    FT_UNUSED( palette );
+
+#endif
+  }
+
+
+  static
+  int  ft_black_render( TRaster_Instance*  raster,
+                        FT_Raster_Params*  params )
+  {
+    FT_Outline*  outline    = (FT_Outline*)params->source;
+    FT_Bitmap*   target_map = params->target;
+
+
+    if ( !raster || !raster->buff || !raster->sizeBuff )
+      return Raster_Err_Not_Ini;
+
+    /* return immediately if the outline is empty */
+    if ( outline->n_points == 0 || outline->n_contours <= 0 )
+      return Raster_Err_None;
+
+    if ( !outline || !outline->contours || !outline->points )
+      return Raster_Err_Invalid;
+
+    if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 )
+      return Raster_Err_Invalid;
+
+    if ( !target_map || !target_map->buffer )
+      return Raster_Err_Invalid;
+
+    /* this version of the raster does not support direct rendering, sorry */
+    if ( params->flags & ft_raster_flag_direct )
+      return Raster_Err_Unsupported;
+
+    ras.outline  = *outline;
+    ras.target   = *target_map;
+
+    return ( ( params->flags & ft_raster_flag_aa )
+               ? Render_Gray_Glyph( raster )
+               : Render_Glyph( raster ) );
+  }
+
+
+  const FT_Raster_Funcs  ft_standard_raster =
+  {
+    ft_glyph_format_outline,
+    (FT_Raster_New_Func)     ft_black_new,
+    (FT_Raster_Reset_Func)   ft_black_reset,
+    (FT_Raster_Set_Mode_Func)ft_black_set_mode,
+    (FT_Raster_Render_Func)  ft_black_render,
+    (FT_Raster_Done_Func)    ft_black_done
+  };
+
+
+/* END */
--- /dev/null
+++ b/src/raster/ftraster.h
@@ -1,0 +1,50 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftraster.h                                                             */
+/*                                                                         */
+/*    The FreeType glyph rasterizer (specification).                       */
+/*                                                                         */
+/*  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 FTRASTER_H
+#define FTRASTER_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+#include <freetype/ftimage.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Uncomment the following line if you are using ftraster.c as a         */
+  /* standalone module, fully independent of FreeType.                     */
+  /*                                                                       */
+/* #define _STANDALONE_ */
+
+#ifndef FT_EXPORT_VAR
+#define FT_EXPORT_VAR( x )  extern x
+#endif
+
+  FT_EXPORT_VAR( const FT_Raster_Funcs )  ft_standard_raster;
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* FTRASTER_H */
+
+
+/* END */
--- /dev/null
+++ b/src/raster/ftrend1.c
@@ -1,0 +1,276 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftrend1.c                                                              */
+/*                                                                         */
+/*    The FreeType glyph rasterizer interface (body).                      */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/ftoutln.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ftrend1.h"
+#include "ftraster.h"
+
+#else
+
+#include <raster/ftrend1.h>
+#include <raster/ftraster.h>
+
+#endif
+
+
+  /* initialize renderer -- init its raster */
+  static
+  FT_Error  ft_raster1_init( FT_Renderer  render )
+  {
+    FT_Library  library = FT_MODULE_LIBRARY( render );
+
+
+    render->clazz->raster_class->raster_reset( render->raster,
+                                               library->raster_pool,
+                                               library->raster_pool_size );
+
+    return FT_Err_Ok;
+  }
+
+
+  /* set render-specific mode */
+  static
+  FT_Error  ft_raster1_set_mode( FT_Renderer  render,
+                                 FT_ULong     mode_tag,
+                                 FT_Pointer   data )
+  {
+    /* we simply pass it to the raster */
+    return render->clazz->raster_class->raster_set_mode( render->raster,
+                                                         mode_tag,
+                                                         data );
+  }
+
+
+  /* transform a given glyph image */
+  static
+  FT_Error  ft_raster1_transform( FT_Renderer   render,
+                                  FT_GlyphSlot  slot,
+                                  FT_Matrix*    matrix,
+                                  FT_Vector*    delta )
+  {
+    FT_Error error = FT_Err_Ok;
+
+
+    if ( slot->format != render->glyph_format )
+    {
+      error = FT_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    if ( matrix )
+      FT_Outline_Transform( &slot->outline, matrix );
+
+    if ( delta )
+      FT_Outline_Translate( &slot->outline, delta->x, delta->y );
+
+  Exit:
+    return error;
+  }
+
+
+  /* return the glyph's control box */
+  static
+  void  ft_raster1_get_cbox( FT_Renderer   render,
+                             FT_GlyphSlot  slot,
+                             FT_BBox*      cbox )
+  {
+    MEM_Set( cbox, 0, sizeof ( *cbox ) );
+
+    if ( slot->format == render->glyph_format )
+      FT_Outline_Get_CBox( &slot->outline, cbox );
+  }
+
+
+  /* convert a slot's glyph image into a bitmap */
+  static
+  FT_Error  ft_raster1_render( FT_Renderer   render,
+                               FT_GlyphSlot  slot,
+                               FT_UInt       mode,
+                               FT_Vector*    origin )
+  {
+    FT_Error     error;
+    FT_Outline*  outline;
+    FT_BBox      cbox;
+    FT_UInt      width, height, pitch;
+    FT_Bitmap*   bitmap;
+    FT_Memory    memory;
+
+    FT_Raster_Params  params;
+
+
+    /* check glyph image format */
+    if ( slot->format != render->glyph_format )
+    {
+      error = FT_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    /* check rendering mode */
+    if ( mode != ft_render_mode_mono )
+    {
+      /* raster1 is only capable of producing monochrome bitmaps */
+      if ( render->clazz == &ft_raster1_renderer_class )
+        return FT_Err_Cannot_Render_Glyph;
+    }
+    else
+    {
+      /* raster5 is only capable of producing 5-gray-levels bitmaps */
+      if ( render->clazz == &ft_raster5_renderer_class )
+        return FT_Err_Cannot_Render_Glyph;
+    }
+
+    outline = &slot->outline;
+
+    /* translate the outline to the new origin if needed */
+    if ( origin )
+      FT_Outline_Translate( outline, origin->x, origin->y );
+
+    /* compute the control box, and grid fit it */
+    FT_Outline_Get_CBox( outline, &cbox );
+
+    cbox.xMin &= -64;
+    cbox.yMin &= -64;
+    cbox.xMax  = ( cbox.xMax + 63 ) & -64;
+    cbox.yMax  = ( cbox.yMax + 63 ) & -64;
+
+    width  = ( cbox.xMax - cbox.xMin ) >> 6;
+    height = ( cbox.yMax - cbox.yMin ) >> 6;
+    bitmap = &slot->bitmap;
+    memory = render->root.memory;
+
+    /* release old bitmap buffer */
+    if ( slot->flags & ft_glyph_own_bitmap )
+    {
+      FREE( bitmap->buffer );
+      slot->flags &= ~ft_glyph_own_bitmap;
+    }
+
+    /* allocate new one, depends on pixel format */
+    if ( !( mode & ft_render_mode_mono ) )
+    {
+      /* we pad to 32 bits, only for backwards compatibility with FT 1.x */
+      pitch = ( width + 3 ) & -4;
+      bitmap->pixel_mode = ft_pixel_mode_grays;
+      bitmap->num_grays  = 256;
+    }
+    else
+    {
+      pitch = ( width + 7 ) >> 3;
+      bitmap->pixel_mode = ft_pixel_mode_mono;
+    }
+
+    bitmap->width = width;
+    bitmap->rows  = height;
+    bitmap->pitch = pitch;
+
+    if ( ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
+      goto Exit;
+
+    slot->flags |= ft_glyph_own_bitmap;
+
+    /* translate outline to render it into the bitmap */
+    FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin );
+
+    /* set up parameters */
+    params.target = bitmap;
+    params.source = outline;
+    params.flags  = 0;
+
+    if ( bitmap->pixel_mode == ft_pixel_mode_grays )
+      params.flags |= ft_raster_flag_aa;
+
+    /* render outline into the bitmap */
+    error = render->raster_render( render->raster, &params );
+    if ( error )
+      goto Exit;
+
+    slot->format      = ft_glyph_format_bitmap;
+    slot->bitmap_left = cbox.xMin >> 6;
+    slot->bitmap_top  = cbox.yMax >> 6;
+
+  Exit:
+    return error;
+  }
+
+
+  FT_CPLUSPLUS( const FT_Renderer_Class )  ft_raster1_renderer_class =
+  {
+    {
+      ft_module_renderer,
+      sizeof( FT_RendererRec ),
+
+      "raster1",
+      0x10000L,
+      0x20000L,
+
+      0,    /* module specific interface */
+
+      (FT_Module_Constructor)ft_raster1_init,
+      (FT_Module_Destructor) 0,
+      (FT_Module_Requester)  0
+    },
+
+    ft_glyph_format_outline,
+
+    (FTRenderer_render)   ft_raster1_render,
+    (FTRenderer_transform)ft_raster1_transform,
+    (FTRenderer_getCBox)  ft_raster1_get_cbox,
+    (FTRenderer_setMode)  ft_raster1_set_mode,
+
+    (FT_Raster_Funcs*)    &ft_standard_raster
+  };
+
+
+  /* This renderer is _NOT_ part of the default modules; you will need */
+  /* to register it by hand in your application.  It should only be    */
+  /* used for backwards-compatibility with FT 1.x anyway.              */
+  /*                                                                   */
+  FT_CPLUSPLUS( const FT_Renderer_Class )  ft_raster5_renderer_class =
+  {
+    {
+      ft_module_renderer,
+      sizeof( FT_RendererRec ),
+
+      "raster5",
+      0x10000L,
+      0x20000L,
+
+      0,    /* module specific interface */
+
+      (FT_Module_Constructor)ft_raster1_init,
+      (FT_Module_Destructor) 0,
+      (FT_Module_Requester)  0
+    },
+
+    ft_glyph_format_outline,
+
+    (FTRenderer_render)   ft_raster1_render,
+    (FTRenderer_transform)ft_raster1_transform,
+    (FTRenderer_getCBox)  ft_raster1_get_cbox,
+    (FTRenderer_setMode)  ft_raster1_set_mode,
+
+    (FT_Raster_Funcs*)    &ft_standard_raster
+  };
+
+
+/* END */
--- /dev/null
+++ b/src/raster/ftrend1.h
@@ -1,0 +1,48 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftrend1.h                                                              */
+/*                                                                         */
+/*    The FreeType glyph rasterizer interface (specification).             */
+/*                                                                         */
+/*  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 FTREND1_H
+#define FTREND1_H
+
+
+#include <freetype/ftrender.h>
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  FT_EXPORT_VAR( const FT_Renderer_Class )  ft_raster1_renderer_class;
+
+  /* this renderer is _NOT_ part of the default modules, you'll need */
+  /* to register it by hand in your application.  It should only be  */
+  /* used for backwards-compatibility with FT 1.x anyway.            */
+  /*                                                                 */
+  FT_EXPORT_VAR( const FT_Renderer_Class )  ft_raster5_renderer_class;
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* FTREND1_H */
+
+
+/* END */
--- /dev/null
+++ b/src/raster/module.mk
@@ -1,0 +1,22 @@
+#
+# FreeType 2 renderer module definition
+#
+
+
+# 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.
+
+
+make_module_list: add_raster_module
+
+add_raster_module:
+	$(OPEN_DRIVER)ft_raster1_renderer_class$(CLOSE_DRIVER)
+	$(ECHO_DRIVER)raster    $(ECHO_DRIVER_DESC)monochrome bitmap renderer$(ECHO_DRIVER_DONE)
+
+# EOF
--- /dev/null
+++ b/src/raster/raster.c
@@ -1,0 +1,35 @@
+/***************************************************************************/
+/*                                                                         */
+/*  raster1.c                                                              */
+/*                                                                         */
+/*    FreeType monochrome rasterer module component (body only).           */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ftraster.c"
+#include "ftrend1.c"
+
+#else
+
+#include <raster/ftraster.c>
+#include <raster/ftrend1.c>
+
+#endif
+
+
+/* END */
--- /dev/null
+++ b/src/raster/rules.mk
@@ -1,0 +1,69 @@
+#
+# FreeType 2 renderer module build 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.
+
+
+# raster1 driver directory
+#
+RAS1_DIR  := $(SRC_)raster
+RAS1_DIR_ := $(RAS1_DIR)$(SEP)
+
+# compilation flags for the driver
+#
+RAS1_COMPILE := $(FT_COMPILE)
+
+
+# raster1 driver sources (i.e., C files)
+#
+RAS1_DRV_SRC := $(RAS1_DIR_)ftraster.c \
+                $(RAS1_DIR_)ftrend1.c
+
+
+# raster1 driver headers
+#
+RAS1_DRV_H := $(RAS1_DRV_SRC:%.c=%.h)
+
+
+# raster1 driver object(s)
+#
+#   RAS1_DRV_OBJ_M is used during `multi' builds.
+#   RAS1_DRV_OBJ_S is used during `single' builds.
+#
+RAS1_DRV_OBJ_M := $(RAS1_DRV_SRC:$(RAS1_DIR_)%.c=$(OBJ_)%.$O)
+RAS1_DRV_OBJ_S := $(OBJ_)raster.$O
+
+# raster1 driver source file for single build
+#
+RAS1_DRV_SRC_S := $(RAS1_DIR_)raster.c
+
+
+# raster1 driver - single object
+#
+$(RAS1_DRV_OBJ_S): $(RAS1_DRV_SRC_S) $(RAS1_DRV_SRC) \
+                   $(FREETYPE_H) $(RAS1_DRV_H)
+	$(RAS1_COMPILE) $T$@ $(RAS1_DRV_SRC_S)
+
+
+# raster1 driver - multiple objects
+#
+$(OBJ_)%.$O: $(RAS1_DIR_)%.c $(FREETYPE_H) $(RAS1_DRV_H)
+	$(RAS1_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(RAS1_DRV_OBJ_S)
+DRV_OBJS_M += $(RAS1_DRV_OBJ_M)
+
+
+# EOF
--- a/src/raster1/module.mk
+++ /dev/null
@@ -1,22 +1,0 @@
-#
-# FreeType 2 renderer module definition
-#
-
-
-# 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.
-
-
-make_module_list: add_raster1_module
-
-add_raster1_module:
-	$(OPEN_DRIVER)ft_raster1_renderer_class$(CLOSE_DRIVER)
-	$(ECHO_DRIVER)raster1   $(ECHO_DRIVER_DESC)monochrome bitmap renderer$(ECHO_DRIVER_DONE)
-
-# EOF
--- a/src/raster1/rules.mk
+++ /dev/null
@@ -1,69 +1,0 @@
-#
-# FreeType 2 renderer module build 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.
-
-
-# raster1 driver directory
-#
-RAS1_DIR  := $(SRC_)raster1
-RAS1_DIR_ := $(RAS1_DIR)$(SEP)
-
-# compilation flags for the driver
-#
-RAS1_COMPILE := $(FT_COMPILE)
-
-
-# raster1 driver sources (i.e., C files)
-#
-RAS1_DRV_SRC := $(RAS1_DIR_)ftraster.c \
-                $(RAS1_DIR_)ftrend1.c
-
-
-# raster1 driver headers
-#
-RAS1_DRV_H := $(RAS1_DRV_SRC:%.c=%.h)
-
-
-# raster1 driver object(s)
-#
-#   RAS1_DRV_OBJ_M is used during `multi' builds.
-#   RAS1_DRV_OBJ_S is used during `single' builds.
-#
-RAS1_DRV_OBJ_M := $(RAS1_DRV_SRC:$(RAS1_DIR_)%.c=$(OBJ_)%.$O)
-RAS1_DRV_OBJ_S := $(OBJ_)raster1.$O
-
-# raster1 driver source file for single build
-#
-RAS1_DRV_SRC_S := $(RAS1_DIR_)raster1.c
-
-
-# raster1 driver - single object
-#
-$(RAS1_DRV_OBJ_S): $(RAS1_DRV_SRC_S) $(RAS1_DRV_SRC) \
-                   $(FREETYPE_H) $(RAS1_DRV_H)
-	$(RAS1_COMPILE) $T$@ $(RAS1_DRV_SRC_S)
-
-
-# raster1 driver - multiple objects
-#
-$(OBJ_)%.$O: $(RAS1_DIR_)%.c $(FREETYPE_H) $(RAS1_DRV_H)
-	$(RAS1_COMPILE) $T$@ $<
-
-
-# update main driver object lists
-#
-DRV_OBJS_S += $(RAS1_DRV_OBJ_S)
-DRV_OBJS_M += $(RAS1_DRV_OBJ_M)
-
-
-# EOF
--- /dev/null
+++ b/src/type1/module.mk
@@ -1,0 +1,22 @@
+#
+# FreeType 2 Type1z module definition
+#
+
+
+# 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.
+
+
+make_module_list: add_type1_driver
+
+add_type1_driver:
+	$(OPEN_DRIVER)t1_driver_class$(CLOSE_DRIVER)
+	$(ECHO_DRIVER)type1     $(ECHO_DRIVER_DESC)Postscript font files with extension *.pfa or *.pfb$(ECHO_DRIVER_DONE)
+
+# EOF
--- /dev/null
+++ b/src/type1/rules.mk
@@ -1,0 +1,72 @@
+#
+# FreeType 2 Type1z 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.
+
+
+# Type1 driver directory
+#
+T1_DIR  := $(SRC_)type1
+T1_DIR_ := $(T1_DIR)$(SEP)
+
+
+# compilation flags for the driver
+#
+T1_COMPILE := $(FT_COMPILE)
+
+
+# Type1 driver sources (i.e., C files)
+#
+T1_DRV_SRC := $(T1_DIR_)z1parse.c  \
+              $(T1_DIR_)z1load.c   \
+              $(T1_DIR_)z1driver.c \
+              $(T1_DIR_)z1afm.c    \
+              $(T1_DIR_)z1gload.c  \
+              $(T1_DIR_)z1objs.c
+
+# Type1 driver headers
+#
+T1_DRV_H := $(T1_DRV_SRC:%.c=%.h) \
+             $(T1_DIR_)z1tokens.h
+
+
+# Type1z driver object(s)
+#
+#   T1_DRV_OBJ_M is used during `multi' builds
+#   T1_DRV_OBJ_S is used during `single' builds
+#
+T1_DRV_OBJ_M := $(T1_DRV_SRC:$(T1_DIR_)%.c=$(OBJ_)%.$O)
+T1_DRV_OBJ_S := $(OBJ_)type1.$O
+
+# Type1z driver source file for single build
+#
+T1_DRV_SRC_S := $(T1_DIR_)type1.c
+
+
+# Type1z driver - single object
+#
+$(T1_DRV_OBJ_S): $(T1_DRV_SRC_S) $(T1_DRV_SRC) $(FREETYPE_H) $(T1_DRV_H)
+	$(T1_COMPILE) $T$@ $(T1_DRV_SRC_S)
+
+
+# Type1z driver - multiple objects
+#
+$(OBJ_)%.$O: $(T1_DIR_)%.c $(FREETYPE_H) $(T1_DRV_H)
+	$(T1_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(T1_DRV_OBJ_S)
+DRV_OBJS_M += $(T1_DRV_OBJ_M)
+
+# EOF
--- /dev/null
+++ b/src/type1/type1.c
@@ -1,0 +1,49 @@
+/***************************************************************************/
+/*                                                                         */
+/*  type1z.c                                                               */
+/*                                                                         */
+/*    FreeType experimental Type 1 driver component (body only).           */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1parse.c"
+#include "z1load.c"
+#include "z1objs.c"
+#include "z1driver.c"
+#include "z1gload.c"
+
+#ifndef Z1_CONFIG_OPTION_NO_AFM
+#include "z1afm.c"
+#endif
+
+#else /* FT_FLAT_COMPILE */
+
+#include <type1z/z1parse.c>
+#include <type1z/z1load.c>
+#include <type1z/z1objs.c>
+#include <type1z/z1driver.c>
+#include <type1z/z1gload.c>
+
+#ifndef Z1_CONFIG_OPTION_NO_AFM
+#include <type1z/z1afm.c>
+#endif
+
+#endif /* FT_FLAT_COMPILE */
+
+
+/* END */
--- /dev/null
+++ b/src/type1/z1afm.c
@@ -1,0 +1,293 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1afm.c                                                                */
+/*                                                                         */
+/*    AFM support for Type 1 fonts (body).                                 */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1afm.h"
+
+#else
+
+#include <type1z/z1afm.h>
+
+#endif
+
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1types.h>
+
+#include <stdlib.h>  /* for qsort()   */
+#include <string.h>  /* for strcmp()  */
+#include <ctype.h>   /* for isalnum() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_z1afm
+
+
+  LOCAL_FUNC
+  void  Z1_Done_AFM( FT_Memory  memory,
+                     Z1_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 )  ( isalnum( c ) || \
+                            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 && !isdigit( *p ) )
+    {
+      sign = 1;
+      if ( *p == '-' )
+        sign = -1;
+
+      p++;
+    }
+
+    while ( p < limit && isdigit( *p ) )
+    {
+      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 */
+  LOCAL_FUNC_X
+  int  compare_kern_pairs( const void*  a,
+                           const void*  b )
+  {
+    Z1_Kern_Pair*  pair1 = (Z1_Kern_Pair*)a;
+    Z1_Kern_Pair*  pair2 = (Z1_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  Z1_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;
+    Z1_Kern_Pair*  pair;
+    T1_Font*       type1 = &((T1_Face)t1_face)->type1;
+    Z1_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, Z1_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 ( Z1_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  Z1_Get_Kerning( Z1_AFM*     afm,
+                        FT_UInt     glyph1,
+                        FT_UInt     glyph2,
+                        FT_Vector*  kerning )
+  {
+    Z1_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;
+  }
+
+
+/* END */
--- /dev/null
+++ b/src/type1/z1afm.h
@@ -1,0 +1,79 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1afm.h                                                                */
+/*                                                                         */
+/*    AFM support for Type 1 fonts (specification).                        */
+/*                                                                         */
+/*  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 Z1AFM_H
+#define Z1AFM_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1objs.h"
+
+#else
+
+#include <type1z/z1objs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  typedef struct  Z1_Kern_Pair_
+  {
+    FT_UInt    glyph1;
+    FT_UInt    glyph2;
+    FT_Vector  kerning;
+
+  } Z1_Kern_Pair;
+
+
+  typedef struct  Z1_AFM_
+  {
+    FT_Int         num_pairs;
+    Z1_Kern_Pair*  kern_pairs;
+
+  } Z1_AFM;
+
+
+  LOCAL_DEF
+  FT_Error  Z1_Read_AFM( FT_Face    face,
+                         FT_Stream  stream );
+
+  LOCAL_DEF
+  void  Z1_Done_AFM( FT_Memory  memory,
+                     Z1_AFM*    afm );
+
+  LOCAL_DEF
+  void  Z1_Get_Kerning( Z1_AFM*     afm,
+                        FT_UInt     glyph1,
+                        FT_UInt     glyph2,
+                        FT_Vector*  kerning );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* Z1AFM_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1/z1driver.c
@@ -1,0 +1,340 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1driver.c                                                             */
+/*                                                                         */
+/*    Experimental Type 1 driver interface (body).                         */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1driver.h"
+#include "z1gload.h"
+#include "z1load.h"
+#include "z1afm.h"
+
+#else
+
+#include <type1z/z1driver.h>
+#include <type1z/z1gload.h>
+#include <type1z/z1load.h>
+#include <type1z/z1afm.h>
+
+#endif
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/psnames.h>
+
+#include <string.h>     /* for strcmp() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_z1driver
+
+
+  static
+  FT_Error  get_z1_glyph_name( T1_Face     face,
+                               FT_UInt     glyph_index,
+                               FT_Pointer  buffer,
+                               FT_UInt     buffer_max )
+  {
+    FT_String*  gname;
+    
+
+    gname = face->type1.glyph_names[glyph_index];
+
+    if ( buffer_max > 0 )
+    {
+      FT_UInt  len = strlen( gname );
+      
+
+      if (len >= buffer_max)
+        len = buffer_max - 1;
+        
+      MEM_Copy( buffer, gname, len );
+      ((FT_Byte*)buffer)[len] = 0;
+    }
+
+    return T1_Err_Ok;
+  }                                  
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <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
+  FT_Module_Interface  Get_Interface( FT_Driver         driver,
+                                      const FT_String*  interface )
+  {
+    FT_UNUSED( driver );
+    FT_UNUSED( interface );
+
+    if ( strcmp( (const char*)interface, "glyph_name" ) == 0 )
+      return (FT_Module_Interface)get_z1_glyph_name;
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+    if ( strcmp( (const char*)interface, "get_mm" ) == 0 )
+      return (FT_Module_Interface)Z1_Get_Multi_Master;
+
+    if ( strcmp( (const char*)interface, "set_mm_design") == 0 )
+      return (FT_Module_Interface)Z1_Set_MM_Design;
+
+    if ( strcmp( (const char*)interface, "set_mm_blend") == 0 )
+      return (FT_Module_Interface)Z1_Set_MM_Blend;
+#endif
+    return 0;
+  }
+
+
+#ifndef Z1_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,
+                         FT_Vector*  kerning )
+  {
+    Z1_AFM*  afm;
+
+
+    kerning->x = 0;
+    kerning->y = 0;
+
+    afm = (Z1_AFM*)face->afm_data;
+    if ( afm )
+      Z1_Get_Kerning( afm, left_glyph, right_glyph, kerning );
+
+    return T1_Err_Ok;
+  }
+
+
+#endif /* T1_CONFIG_OPTION_NO_AFM */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <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 if 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;
+  }
+
+
+  FT_CPLUSPLUS( const FT_Driver_Class )  t1_driver_class =
+  {
+    {
+      ft_module_font_driver | ft_module_driver_scalable,
+      sizeof( FT_DriverRec ),
+
+      "type1",
+      0x10000L,
+      0x20000L,
+
+      0,   /* format interface */
+
+      (FT_Module_Constructor)Z1_Init_Driver,
+      (FT_Module_Destructor) Z1_Done_Driver,
+      (FT_Module_Requester)  Get_Interface,
+    },
+
+    sizeof( T1_FaceRec ),
+    sizeof( Z1_SizeRec ),
+    sizeof( Z1_GlyphSlotRec ),
+
+    (FTDriver_initFace)     Z1_Init_Face,
+    (FTDriver_doneFace)     Z1_Done_Face,
+    (FTDriver_initSize)     0,
+    (FTDriver_doneSize)     0,
+    (FTDriver_initGlyphSlot)0,
+    (FTDriver_doneGlyphSlot)0,
+
+    (FTDriver_setCharSizes) 0,
+    (FTDriver_setPixelSizes)0,
+    (FTDriver_loadGlyph)    Z1_Load_Glyph,
+    (FTDriver_getCharIndex) Get_Char_Index,
+
+#ifdef Z1_CONFIG_OPTION_NO_AFM
+    (FTDriver_getKerning)   0,
+    (FTDriver_attachFile)   0,
+#else
+    (FTDriver_getKerning)   Get_Kerning,
+    (FTDriver_attachFile)   Z1_Read_AFM,
+#endif
+    (FTDriver_getAdvances)  0
+  };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+  EXPORT_FUNC( const FT_Driver_Class* )  getDriverClass( void )
+  {
+    return &t1z_driver_class;
+  }
+
+#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
--- /dev/null
+++ b/src/type1/z1driver.h
@@ -1,0 +1,39 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1driver.h                                                             */
+/*                                                                         */
+/*    High-level experimental Type 1 driver interface (specification).     */
+/*                                                                         */
+/*  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 Z1DRIVER_H
+#define Z1DRIVER_H
+
+#include <freetype/internal/ftdriver.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  FT_EXPORT_VAR( const  FT_Driver_Class )  t1_driver_class;
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* Z1DRIVER_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1/z1gload.c
@@ -1,0 +1,309 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1gload.c                                                              */
+/*                                                                         */
+/*    Experimental Type 1 Glyph Loader (body).                             */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1gload.h"
+
+#else
+
+#include <type1z/z1gload.h>
+
+#endif
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/ftoutln.h>
+#include <freetype/internal/psaux.h>
+
+
+#include <string.h>     /* for strcmp() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_z1gload
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
+  /**********                                                      *********/
+  /**********    The following code is in charge of computing      *********/
+  /**********    the maximum advance width of the font.  It        *********/
+  /**********    quickly processes each glyph charstring to        *********/
+  /**********    extract the value from either a `sbw' or `seac'   *********/
+  /**********    operator.                                         *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  LOCAL_FUNC_X
+  FT_Error  Z1_Parse_Glyph( T1_Decoder*  decoder,
+                            FT_UInt      glyph_index )
+  {
+    T1_Face   face  = (T1_Face)decoder->builder.face;
+    T1_Font*  type1 = &face->type1;
+
+
+    decoder->font_matrix = type1->font_matrix;
+    decoder->font_offset = type1->font_offset;
+
+    return decoder->funcs.parse_charstrings(
+                      decoder,
+                      type1->charstrings    [glyph_index],
+                      type1->charstrings_len[glyph_index] );
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  Z1_Compute_Max_Advance( T1_Face  face,
+                                    FT_Int*  max_advance )
+  {
+    FT_Error          error;
+    T1_Decoder        decoder;
+    FT_Int            glyph_index;
+    T1_Font*          type1 = &face->type1;
+    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
+
+
+    *max_advance = 0;
+
+    /* initialize load decoder */
+    error = psaux->t1_decoder_funcs->init( &decoder,
+                                           (FT_Face)face,
+                                           0, /* size       */
+                                           0, /* glyph slot */
+                                           (FT_Byte**)type1->glyph_names,
+                                           face->blend,
+                                           Z1_Parse_Glyph );
+    if ( error )
+      return error;
+      
+    decoder.builder.metrics_only = 1;
+    decoder.builder.load_points  = 0;
+
+    decoder.num_subrs = type1->num_subrs;
+    decoder.subrs     = type1->subrs;
+    decoder.subrs_len = type1->subrs_len;
+
+    /* for each glyph, parse the glyph charstring and extract */
+    /* the advance width                                      */
+    for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
+    {
+      /* now get load the unscaled outline */
+      error = Z1_Parse_Glyph( &decoder, glyph_index );
+      /* ignore the error if one occured - skip to next glyph */
+    }
+
+    *max_advance = decoder.builder.advance.x;
+    return FT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********               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.       *********/
+  /**********                                                      *********/
+  /**********      The Type 1 hinter is located in `t1hint.c'      *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  LOCAL_FUNC
+  FT_Error  Z1_Load_Glyph( Z1_GlyphSlot  glyph,
+                           Z1_Size       size,
+                           FT_Int        glyph_index,
+                           FT_Int        load_flags )
+  {
+    FT_Error                error;
+    T1_Decoder              decoder;
+    T1_Face                 face = (T1_Face)glyph->root.face;
+    FT_Bool                 hinting;
+    T1_Font*                type1         = &face->type1;
+    PSAux_Interface*        psaux         = (PSAux_Interface*)face->psaux;
+    const T1_Decoder_Funcs* decoder_funcs = psaux->t1_decoder_funcs;
+
+    FT_Matrix               font_matrix;
+    FT_Vector               font_offset;
+
+    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_outline;
+
+    error = decoder_funcs->init( &decoder,
+                                 (FT_Face)face,
+                                 (FT_Size)size,
+                                 (FT_GlyphSlot)glyph,
+                                 (FT_Byte**)type1->glyph_names,
+                                 face->blend,
+                                 Z1_Parse_Glyph );
+    if ( error )
+      goto Exit;
+                      
+    decoder.builder.no_recurse = ( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
+
+    decoder.num_subrs = type1->num_subrs;
+    decoder.subrs     = type1->subrs;
+    decoder.subrs_len = type1->subrs_len;
+   
+
+    /* now load the unscaled outline */
+    error = Z1_Parse_Glyph( &decoder, glyph_index );
+    if ( error )
+      goto Exit;
+
+    font_matrix = decoder.font_matrix;
+    font_offset = decoder.font_offset;
+
+    /* save new glyph tables */
+    decoder_funcs->done( &decoder );
+
+    /* 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 )
+    {
+      glyph->root.outline.flags &= ft_outline_owner;
+      glyph->root.outline.flags |= ft_outline_reverse_fill;
+      
+      /* for composite glyphs, return only left side bearing and */
+      /* 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;
+        glyph->root.linearHoriAdvance = decoder.builder.advance.x;
+
+        /* make up vertical metrics */
+        metrics->vertBearingX = 0;
+        metrics->vertBearingY = 0;
+        metrics->vertAdvance  = 0;
+
+        glyph->root.linearVertAdvance = 0;
+
+        glyph->root.format = ft_glyph_format_outline;
+
+        if ( size && size->root.metrics.y_ppem < 24 )
+          glyph->root.outline.flags |= ft_outline_high_precision;
+
+        /* apply the font matrix */
+        FT_Outline_Transform( &glyph->root.outline, &font_matrix );
+
+        FT_Outline_Translate( &glyph->root.outline,
+                              font_offset.x,
+                              font_offset.y );
+
+#if 0
+
+        glyph->root.outline.second_pass    = TRUE;
+        glyph->root.outline.high_precision = size->root.metrics.y_ppem < 24;
+        glyph->root.outline.dropout_mode   = 2;
+
+#endif /* 0 */
+
+        if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+        {
+          /* scale the outline and the metrics */
+          FT_Int       n;
+          FT_Outline*  cur = decoder.builder.base;
+          FT_Vector*   vec = cur->points;
+          FT_Fixed     x_scale = glyph->x_scale;
+          FT_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->vertAdvance  = FT_MulFix( metrics->vertAdvance,  y_scale );
+
+          metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+          metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+        }
+
+        /* 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;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+/* END */
--- /dev/null
+++ b/src/type1/z1gload.h
@@ -1,0 +1,58 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1gload.h                                                              */
+/*                                                                         */
+/*    Experimental Type 1 Glyph Loader (specification).                    */
+/*                                                                         */
+/*  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 Z1GLOAD_H
+#define Z1GLOAD_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1objs.h"
+
+#else
+
+#include <type1z/z1objs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  LOCAL_DEF
+  FT_Error  Z1_Compute_Max_Advance( T1_Face  face,
+                                    FT_Int*  max_advance );
+
+  LOCAL_DEF
+  FT_Error  Z1_Load_Glyph( Z1_GlyphSlot  glyph,
+                           Z1_Size       size,
+                           FT_Int        glyph_index,
+                           FT_Int        load_flags );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* Z1GLOAD_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1/z1load.c
@@ -1,0 +1,1702 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1load.c                                                               */
+/*                                                                         */
+/*    Experimental Type 1 font loader (body).                              */
+/*                                                                         */
+/*  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 by 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; 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 PARSE_XXX.                                               */
+  /*                                                                       */
+  /* This file is included twice here; the first time to generate parsing  */
+  /* callback functions, the second to generate a table of keywords (with  */
+  /* pointers to the associated callback).                                 */
+  /*                                                                       */
+  /* The function `parse_dict' simply scans *linearly* a given dictionary  */
+  /* (either the top-level or private one) and calls the appropriate       */
+  /* callback when it encounters an immediate keyword.                     */
+  /*                                                                       */
+  /* 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 <freetype/internal/t1errors.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1load.h"
+
+#else
+
+#include <type1z/z1load.h>
+
+#endif
+
+
+#include <string.h>     /* for strncmp(), strcmp() */
+#include <ctype.h>      /* for isalnum()           */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_z1load
+
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    MULTIPLE MASTERS SUPPORT                   *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  static
+  FT_Error  t1_allocate_blend( T1_Face  face,
+                               FT_UInt  num_designs,
+                               FT_UInt  num_axis )
+  {
+    T1_Blend*  blend;
+    FT_Memory  memory = face->root.memory;
+    FT_Error   error  = 0;
+
+
+    blend = face->blend;
+    if ( !blend )
+    {
+      if ( ALLOC( blend, sizeof ( *blend ) ) )
+        goto Exit;
+
+      face->blend = blend;
+    }
+
+    /* allocate design data if needed */
+    if ( num_designs > 0 )
+    {
+      if ( blend->num_designs == 0 )
+      {
+        FT_UInt  nn;
+        
+
+        /* allocate the blend `private' and `font_info' dictionaries */
+        if ( ALLOC_ARRAY( blend->font_infos[1], num_designs, T1_FontInfo )  ||
+             ALLOC_ARRAY( blend->privates[1], num_designs, T1_Private )     ||
+             ALLOC_ARRAY( blend->weight_vector, num_designs * 2, FT_Fixed ) )
+          goto Exit;
+
+        blend->default_weight_vector = blend->weight_vector + num_designs;
+
+        blend->font_infos[0] = &face->type1.font_info;
+        blend->privates  [0] = &face->type1.private_dict;
+        
+        for ( nn = 2; nn <= num_designs; nn++ )
+        {
+          blend->privates[nn]   = blend->privates  [nn - 1] + 1;
+          blend->font_infos[nn] = blend->font_infos[nn - 1] + 1;
+        }
+        
+        blend->num_designs   = num_designs;
+      }
+      else if ( blend->num_designs != num_designs )
+        goto Fail;
+    }
+
+    /* allocate axis data if needed */
+    if ( num_axis > 0 )
+    {
+      if ( blend->num_axis != 0 && blend->num_axis != num_axis )
+        goto Fail;
+
+      blend->num_axis = num_axis;
+    }
+
+    /* allocate the blend design pos table if needed */
+    num_designs = blend->num_designs;
+    num_axis    = blend->num_axis;
+    if ( num_designs && num_axis && blend->design_pos[0] == 0 )
+    {
+      FT_UInt  n;
+
+
+      if ( ALLOC_ARRAY( blend->design_pos[0],
+                        num_designs * num_axis, FT_Fixed ) )
+        goto Exit;
+
+      for ( n = 1; n < num_designs; n++ )
+        blend->design_pos[n] = blend->design_pos[0] + num_axis * n;
+    }
+
+  Exit:
+    return error;
+
+  Fail:
+    error = -1;
+    goto Exit;
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  Z1_Get_Multi_Master( T1_Face           face,
+                                 FT_Multi_Master*  master )
+  {
+    T1_Blend*  blend = face->blend;
+    FT_UInt    n;
+    FT_Error   error;
+
+
+    error = T1_Err_Invalid_Argument;
+
+    if ( blend )
+    {
+      master->num_axis    = blend->num_axis;
+      master->num_designs = blend->num_designs;
+
+      for ( n = 0; n < blend->num_axis; n++ )
+      {
+        FT_MM_Axis*    axis = master->axis + n;
+        T1_DesignMap*  map = blend->design_map + n;
+
+
+        axis->name    = blend->axis_names[n];
+        axis->minimum = map->design_points[0];
+        axis->maximum = map->design_points[map->num_points - 1];
+      }
+      error = 0;
+    }
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  Z1_Set_MM_Blend( T1_Face    face,
+                             FT_UInt    num_coords,
+                             FT_Fixed*  coords )
+  {
+    T1_Blend*  blend = face->blend;
+    FT_Error   error;
+    FT_UInt    n, m;
+
+
+    error = T1_Err_Invalid_Argument;
+
+    if ( blend && blend->num_axis == num_coords )
+    {
+      /* recompute the weight vector from the blend coordinates */
+      error = FT_Err_Ok;
+
+      for ( n = 0; n < blend->num_designs; n++ )
+      {
+        FT_Fixed  result = 0x10000L;  /* 1.0 fixed */
+
+
+        for ( m = 0; m < blend->num_axis; m++ )
+        {
+          FT_Fixed  factor;
+
+
+          /* get current blend axis position */
+          factor = coords[m];
+          if ( factor < 0 )        factor = 0;
+          if ( factor > 0x10000L ) factor = 0x10000L;
+
+          if ( ( n & ( 1 << m ) ) == 0 )
+            factor = 0x10000L - factor;
+
+          result = FT_MulFix( result, factor );
+        }
+        blend->weight_vector[n] = result;
+      }
+
+      error = FT_Err_Ok;
+    }
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  Z1_Set_MM_Design( T1_Face   face,
+                              FT_UInt   num_coords,
+                              FT_Long*  coords )
+  {
+    T1_Blend*  blend = face->blend;
+    FT_Error   error;
+    FT_UInt    n, p;
+
+
+    error = T1_Err_Invalid_Argument;
+    if ( blend && blend->num_axis == num_coords )
+    {
+      /* compute the blend coordinates through the blend design map */
+      FT_Fixed  final_blends[T1_MAX_MM_DESIGNS];
+
+
+      for ( n = 0; n < blend->num_axis; n++ )
+      {
+        FT_Long        design  = coords[n];
+        FT_Fixed       the_blend;
+        T1_DesignMap*  map     = blend->design_map + n;
+        FT_Fixed*      designs = map->design_points;
+        FT_Fixed*      blends  = map->blend_points;
+        FT_Int         before  = -1, after = -1;
+
+        for ( p = 0; p < map->num_points; p++ )
+        {
+          FT_Fixed  p_design = designs[p];
+
+
+          /* exact match ? */
+          if ( design == p_design )
+          {
+            the_blend = blends[p];
+            goto Found;
+          }
+
+          if ( design < p_design )
+          {
+            after = p;
+            break;
+          }
+
+          before = p;
+        }
+
+        /* now, interpolate if needed */
+        if ( before < 0 )
+          the_blend = blends[0];
+
+        else if ( after < 0 )
+          the_blend = blends[map->num_points - 1];
+
+        else
+          the_blend = FT_MulDiv( design         - designs[before],
+                                 blends [after] - blends [before],
+                                 designs[after] - designs[before] );
+
+      Found:
+        final_blends[n] = the_blend;
+      }
+
+      error = Z1_Set_MM_Blend( face, num_coords, final_blends );
+    }
+
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  void  Z1_Done_Blend( T1_Face  face )
+  {
+    FT_Memory  memory = face->root.memory;
+    T1_Blend*  blend  = face->blend;
+
+
+    if ( blend )
+    {
+      FT_UInt  num_designs = blend->num_designs;
+      FT_UInt  num_axis    = blend->num_axis;
+      FT_UInt  n;
+
+
+      /* release design pos table */
+      FREE( blend->design_pos[0] );
+      for ( n = 1; n < num_designs; n++ )
+        blend->design_pos[n] = 0;
+
+      /* release blend `private' and `font info' dictionaries */
+      FREE( blend->privates[1] );
+      FREE( blend->font_infos[1] );
+
+      for ( n = 0; n < num_designs; n++ )
+      {
+        blend->privates  [n] = 0;
+        blend->font_infos[n] = 0;
+      }
+
+      /* release weight vectors */
+      FREE( blend->weight_vector );
+      blend->default_weight_vector = 0;
+
+      /* release axis names */
+      for ( n = 0; n < num_axis; n++ )
+        FREE( blend->axis_names[n] );
+
+      /* release design map */
+      for ( n = 0; n < num_axis; n++ )
+      {
+        T1_DesignMap*  dmap = blend->design_map + n;
+
+
+        FREE( dmap->design_points );
+        dmap->num_points = 0;
+      }
+
+      FREE( face->blend );
+    }
+  }
+
+
+  static
+  void  parse_blend_axis_types( T1_Face     face,
+                                Z1_Loader*  loader )
+  {
+    T1_Token   axis_tokens[ T1_MAX_MM_AXIS ];
+    FT_Int     n, num_axis;
+    FT_Error   error = 0;
+    T1_Blend*  blend;
+    FT_Memory  memory;
+
+
+    /* take an array of objects */
+    Z1_ToTokenArray( &loader->parser, axis_tokens,
+                     T1_MAX_MM_AXIS, &num_axis );
+    if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
+    {
+      FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n",
+                 num_axis ));
+      error = T1_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    /* allocate blend if necessary */
+    error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
+    if ( error )
+      goto Exit;
+
+    blend  = face->blend;
+    memory = face->root.memory;
+
+    /* each token is an immediate containing the name of the axis */
+    for ( n = 0; n < num_axis; n++ )
+    {
+      T1_Token*  token = axis_tokens + n;
+      FT_Byte*   name;
+      FT_Int     len;
+
+      /* skip first slash, if any */
+      if (token->start[0] == '/')
+        token->start++;
+
+      len = token->limit - token->start;
+      if ( len <= 0 )
+      {
+        error = T1_Err_Invalid_File_Format;
+        goto Exit;
+      }
+
+      if ( ALLOC( blend->axis_names[n], len + 1 ) )
+        goto Exit;
+
+      name = (FT_Byte*)blend->axis_names[n];
+      MEM_Copy( name, token->start, len );
+      name[len] = 0;
+    }
+
+  Exit:
+    loader->parser.root.error = error;
+  }
+
+
+  static
+  void  parse_blend_design_positions( T1_Face     face,
+                                      Z1_Loader*  loader )
+  {
+    T1_Token    design_tokens[ T1_MAX_MM_DESIGNS ];
+    FT_Int      num_designs;
+    FT_Int      num_axis;
+    Z1_Parser*  parser = &loader->parser;
+
+    FT_Error    error = 0;
+    T1_Blend*   blend;
+
+
+    /* get the array of design tokens - compute number of designs */
+    Z1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs );
+    if ( num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS )
+    {
+      FT_ERROR(( "parse_blend_design_positions:" ));
+      FT_ERROR(( " incorrect number of designs: %d\n",
+                 num_designs ));
+      error = T1_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    {
+      FT_Byte*  old_cursor = parser->root.cursor;
+      FT_Byte*  old_limit  = parser->root.limit;
+      FT_UInt   n;
+
+
+      blend    = face->blend;
+      num_axis = 0;  /* make compiler happy */
+
+      for ( n = 0; n < (FT_UInt)num_designs; n++ )
+      {
+        T1_Token   axis_tokens[ T1_MAX_MM_DESIGNS ];
+        T1_Token*  token;
+        FT_Int     axis, n_axis;
+
+
+        /* read axis/coordinates tokens */
+        token = design_tokens + n;
+        parser->root.cursor = token->start - 1;
+        parser->root.limit  = token->limit + 1;
+        Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
+
+        if ( n == 0 )
+        {
+          num_axis = n_axis;
+          error = t1_allocate_blend( face, num_designs, num_axis );
+          if ( error )
+            goto Exit;
+          blend = face->blend;
+        }
+        else if ( n_axis != num_axis )
+        {
+          FT_ERROR(( "parse_blend_design_positions: incorrect table\n" ));
+          error = T1_Err_Invalid_File_Format;
+          goto Exit;
+        }
+
+        /* now, read each axis token into the design position */
+        for ( axis = 0; axis < n_axis; axis++ )
+        {
+          T1_Token*  token2 = axis_tokens + axis;
+
+
+          parser->root.cursor = token2->start;
+          parser->root.limit  = token2->limit;
+          blend->design_pos[n][axis] = Z1_ToFixed( parser, 0 );
+        }
+      }
+
+      loader->parser.root.cursor = old_cursor;
+      loader->parser.root.limit  = old_limit;
+    }
+
+  Exit:
+    loader->parser.root.error = error;
+  }
+
+
+  static
+  void  parse_blend_design_map( T1_Face     face,
+                                Z1_Loader*  loader )
+  {
+    FT_Error    error  = 0;
+    Z1_Parser*  parser = &loader->parser;
+    T1_Blend*   blend;
+    T1_Token    axis_tokens[ T1_MAX_MM_AXIS ];
+    FT_Int      n, num_axis;
+    FT_Byte*    old_cursor;
+    FT_Byte*    old_limit;
+    FT_Memory   memory = face->root.memory;
+
+
+    Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis );
+    if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
+    {
+      FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n",
+                 num_axis ));
+      error = T1_Err_Invalid_File_Format;
+      goto Exit;
+    }
+    old_cursor = parser->root.cursor;
+    old_limit  = parser->root.limit;
+
+    error = t1_allocate_blend( face, 0, num_axis );
+    if ( error )
+      goto Exit;
+    blend = face->blend;
+
+    /* now, read each axis design map */
+    for ( n = 0; n < num_axis; n++ )
+    {
+      T1_DesignMap* map = blend->design_map + n;
+      T1_Token*     token;
+      FT_Int        p, num_points;
+
+
+      token = axis_tokens + n;
+      parser->root.cursor = token->start;
+      parser->root.limit  = token->limit;
+
+      /* count the number of map points */
+      {
+        FT_Byte*  ptr   = token->start;
+        FT_Byte*  limit = token->limit;
+
+
+        num_points = 0;
+        for ( ; ptr < limit; ptr++ )
+          if ( ptr[0] == '[' )
+            num_points++;
+      }
+      if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
+      {
+        FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
+        error = T1_Err_Invalid_File_Format;
+        goto Exit;
+      }
+
+      /* allocate design map data */
+      if ( ALLOC_ARRAY( map->design_points, num_points * 2, FT_Fixed ) )
+        goto Exit;
+      map->blend_points = map->design_points + num_points;
+      map->num_points   = (FT_Byte)num_points;
+
+      for ( p = 0; p < num_points; p++ )
+      {
+        map->design_points[p] = Z1_ToInt( parser );
+        map->blend_points [p] = Z1_ToFixed( parser, 0 );
+      }
+    }
+
+    parser->root.cursor = old_cursor;
+    parser->root.limit  = old_limit;
+
+  Exit:
+    parser->root.error = error;
+  }
+
+
+  static
+  void  parse_weight_vector( T1_Face     face,
+                             Z1_Loader*  loader )
+  {
+    FT_Error    error  = 0;
+    Z1_Parser*  parser = &loader->parser;
+    T1_Blend*   blend  = face->blend;
+    T1_Token    master;
+    FT_UInt     n;
+    FT_Byte*    old_cursor;
+    FT_Byte*    old_limit;
+
+
+    if ( !blend || blend->num_designs == 0 )
+    {
+      FT_ERROR(( "parse_weight_vector: too early!\n" ));
+      error = T1_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    Z1_ToToken( parser, &master );
+    if ( master.type != t1_token_array )
+    {
+      FT_ERROR(( "parse_weight_vector: incorrect format!\n" ));
+      error = T1_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    old_cursor = parser->root.cursor;
+    old_limit  = parser->root.limit;
+
+    parser->root.cursor = master.start;
+    parser->root.limit  = master.limit;
+
+    for ( n = 0; n < blend->num_designs; n++ )
+    {
+      blend->default_weight_vector[n] =
+      blend->weight_vector[n]         = Z1_ToFixed( parser, 0 );
+    }
+
+    parser->root.cursor = old_cursor;
+    parser->root.limit  = old_limit;
+
+  Exit:
+    parser->root.error = error;
+  }
+
+
+  /* the keyword `/shareddict' appears in some multiple master fonts   */
+  /* with a lot of Postscript garbage behind it (that's completely out */
+  /* of spec!); we detect it and terminate the parsing                 */
+  /*                                                                   */
+  static
+  void  parse_shared_dict( T1_Face     face,
+                           Z1_Loader*  loader )
+  {
+    Z1_Parser*  parser = &loader->parser;
+
+    FT_UNUSED( face );
+
+
+    parser->root.cursor = parser->root.limit;
+    parser->root.error  = 0;
+  }
+
+#endif /* Z1_CONFIG_OPTION_NO_MM_SUPPORT */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                      TYPE 1 SYMBOL PARSING                    *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* First of all, define the token field static variables.  This is a set */
+  /* of T1_Field variables used later.                                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  static
+  FT_Error  t1_load_keyword( T1_Face     face,
+                             Z1_Loader*  loader,
+                             T1_Field*   field )
+  {
+    FT_Error   error;
+    void*      dummy_object;
+    void**     objects;
+    FT_UInt    max_objects;
+    T1_Blend*  blend = face->blend;
+
+
+    /* if the keyword has a dedicated callback, call it */
+    if ( field->type == t1_field_callback )
+    {
+      field->reader( (FT_Face)face, loader );
+      error = loader->parser.root.error;
+      goto Exit;
+    }
+
+    /* now, the keyword is either a simple field, or a table of fields; */
+    /* we are now going to take care of it                              */
+    switch ( field->location )
+    {
+    case t1_field_font_info:
+      dummy_object = &face->type1.font_info;
+      objects      = &dummy_object;
+      max_objects  = 0;
+
+      if ( blend )
+      {
+        objects     = (void**)blend->font_infos;
+        max_objects = blend->num_designs;
+      }
+      break;
+
+    case t1_field_private:
+      dummy_object = &face->type1.private_dict;
+      objects      = &dummy_object;
+      max_objects  = 0;
+
+      if ( blend )
+      {
+        objects     = (void**)blend->privates;
+        max_objects = blend->num_designs;
+      }
+      break;
+
+    default:
+      dummy_object = &face->type1;
+      objects      = &dummy_object;
+      max_objects  = 0;
+    }
+
+    if ( field->type == t1_field_integer_array ||
+         field->type == t1_field_fixed_array   )
+      error = Z1_Load_Field_Table( &loader->parser, field,
+                                   objects, max_objects, 0 );
+    else
+      error = Z1_Load_Field( &loader->parser, field,
+                             objects, max_objects, 0 );
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  int  is_space( FT_Byte  c )
+  {
+    return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
+  }
+
+
+  static
+  int  is_alpha( FT_Byte  c )
+  {
+    return ( isalnum( c ) || c == '.' || c == '_' );
+  }
+
+
+
+  static
+  int  read_binary_data( Z1_Parser*  parser,
+                         FT_Int*     size,
+                         FT_Byte**   base )
+  {
+    FT_Byte*  cur;
+    FT_Byte*  limit = parser->root.limit;
+
+
+    /* the binary data has the following format */
+    /*                                          */
+    /* `size' [white*] RD white ....... ND      */
+    /*                                          */
+
+    Z1_Skip_Spaces( parser );
+    cur = parser->root.cursor;
+
+    if ( cur < limit && (FT_Byte)( *cur - '0' ) < 10 )
+    {
+      *size = Z1_ToInt( parser );
+
+      Z1_Skip_Spaces( parser );
+      Z1_Skip_Alpha ( parser );  /* `RD' or `-|' or something else */
+
+      /* there is only one whitespace char after the */
+      /* `RD' or `-|' token                          */
+      *base = parser->root.cursor + 1;
+
+      parser->root.cursor += *size + 1;
+      return 1;
+    }
+
+    FT_ERROR(( "read_binary_data: invalid size field\n" ));
+    parser->root.error = T1_Err_Invalid_File_Format;
+    return 0;
+  }
+
+
+  /* we will now define the routines used to handle */
+  /* the `/Encoding', `/Subrs', and `/CharStrings'  */
+  /* dictionaries                                   */
+
+  static
+  void  parse_font_name( T1_Face     face,
+                         Z1_Loader*  loader )
+  {
+    Z1_Parser*  parser = &loader->parser;
+    FT_Error    error;
+    FT_Memory   memory = parser->root.memory;
+    FT_Int      len;
+    FT_Byte*    cur;
+    FT_Byte*    cur2;
+    FT_Byte*    limit;
+
+
+    Z1_Skip_Spaces( parser );
+
+    cur   = parser->root.cursor;
+    limit = parser->root.limit;
+
+    if ( cur >= limit - 1 || *cur != '/' )
+      return;
+
+    cur++;
+    cur2 = cur;
+    while ( cur2 < limit && is_alpha( *cur2 ) )
+      cur2++;
+
+    len = cur2 - cur;
+    if ( len > 0 )
+    {
+      if ( ALLOC( face->type1.font_name, len + 1 ) )
+      {
+        parser->root.error = error;
+        return;
+      }
+
+      MEM_Copy( face->type1.font_name, cur, len );
+      face->type1.font_name[len] = '\0';
+    }
+    parser->root.cursor = cur2;
+  }
+
+
+  static
+  void  parse_font_bbox( T1_Face     face,
+                         Z1_Loader*  loader )
+  {
+    Z1_Parser*  parser = &loader->parser;
+    FT_Short    temp[4];
+    FT_BBox*    bbox   = &face->type1.font_bbox;
+
+
+    (void)Z1_ToCoordArray( parser, 4, temp );
+    bbox->xMin = temp[0];
+    bbox->yMin = temp[1];
+    bbox->xMax = temp[2];
+    bbox->yMax = temp[3];
+  }
+
+
+  static
+  void  parse_font_matrix( T1_Face     face,
+                           Z1_Loader*  loader )
+  {
+    Z1_Parser*  parser = &loader->parser;
+    FT_Matrix*  matrix = &face->type1.font_matrix;
+    FT_Vector*  offset = &face->type1.font_offset;
+    FT_Fixed    temp[6];
+
+
+    if ( matrix->xx || matrix->yx )
+      /*  with synthetic fonts, it's possible we get here twice  */
+      return;
+
+    (void)Z1_ToFixedArray( parser, 6, temp, 3 );
+
+    /* we need to scale the values by 1.0/temp[3] */
+    if ( temp[3] != 0x10000L )
+    {
+      temp[0] = FT_DivFix( temp[0], temp[3] );
+      temp[1] = FT_DivFix( temp[1], temp[3] );
+      temp[2] = FT_DivFix( temp[2], temp[3] );
+      temp[4] = FT_DivFix( temp[4], temp[3] );
+      temp[5] = FT_DivFix( temp[5], temp[3] );
+      temp[3] = 0x10000L;
+    }
+
+    matrix->xx = temp[0];
+    matrix->yx = temp[1];
+    matrix->xy = temp[2];
+    matrix->yy = temp[3];
+    
+    /* note that the offsets must be expressed in integer font units */
+    offset->x  = temp[4] >> 16;
+    offset->y  = temp[5] >> 16;
+  }
+
+
+  static
+  void  parse_encoding( T1_Face     face,
+                        Z1_Loader*  loader )
+  {
+    Z1_Parser*  parser = &loader->parser;
+    FT_Byte*    cur   = parser->root.cursor;
+    FT_Byte*    limit = parser->root.limit;
+    
+    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
+
+
+    /* skip whitespace */
+    while ( is_space( *cur ) )
+    {
+      cur++;
+      if ( cur >= limit )
+      {
+        FT_ERROR(( "parse_encoding: out of bounds!\n" ));
+        parser->root.error = T1_Err_Invalid_File_Format;
+        return;
+      }
+    }
+
+    /* if we have a number, then the encoding is an array, */
+    /* and we must load it now                             */
+    if ( (FT_Byte)( *cur - '0' ) < 10 )
+    {
+      T1_Encoding*  encode     = &face->type1.encoding;
+      FT_Int        count, n;
+      PS_Table*     char_table = &loader->encoding_table;
+      FT_Memory     memory     = parser->root.memory;
+      FT_Error      error;
+
+
+      /* read the number of entries in the encoding, should be 256 */
+      count = Z1_ToInt( parser );
+      if ( parser->root.error )
+        return;
+
+      /* we use a Z1_Table to store our charnames */
+      encode->num_chars = count;
+      if ( ALLOC_ARRAY( encode->char_index, count, FT_Short   ) ||
+           ALLOC_ARRAY( encode->char_name,  count, FT_String* ) ||
+           ( error = psaux->ps_table_funcs->init(
+                       char_table, count, memory ) ) != 0       )
+      {
+        parser->root.error = error;
+        return;
+      }
+
+      /* We need to `zero' out encoding_table.elements          */
+      for ( n = 0; n < count; n++ )
+      {
+        char*  notdef = ".notdef";       
+
+
+        Z1_Add_Table( char_table, n, notdef, 8 );
+      }
+
+      /* Now, we will need to read a record of the form         */
+      /* ... charcode /charname ... for each entry in our table */
+      /*                                                        */
+      /* We simply look for a number followed by an immediate   */
+      /* name.  Note that this ignores correctly the sequence   */
+      /* that is often seen in type1 fonts:                     */
+      /*                                                        */
+      /*   0 1 255 { 1 index exch /.notdef put } for dup        */
+      /*                                                        */
+      /* used to clean the encoding array before anything else. */
+      /*                                                        */
+      /* We stop when we encounter a `def'.                     */
+
+      cur   = parser->root.cursor;
+      limit = parser->root.limit;
+      n     = 0;
+
+      for ( ; cur < limit; )
+      {
+        FT_Byte  c;
+
+
+        c = *cur;
+
+        /* we stop when we encounter a `def' */
+        if ( c == 'd' && cur + 3 < limit )
+        {
+          if ( cur[1] == 'e' &&
+               cur[2] == 'f' &&
+               is_space(cur[-1]) &&
+               is_space(cur[3]) )
+          {
+            FT_TRACE6(( "encoding end\n" ));
+            break;
+          }
+        }
+
+        /* otherwise, we must find a number before anything else */
+        if ( (FT_Byte)( c - '0' ) < 10 )
+        {
+          FT_Int  charcode;
+
+
+          parser->root.cursor = cur;
+          charcode = Z1_ToInt( parser );
+          cur = parser->root.cursor;
+
+          /* skip whitespace */
+          while ( cur < limit && is_space( *cur ) )
+            cur++;
+
+          if ( cur < limit && *cur == '/' )
+          {
+            /* bingo, we have an immediate name -- it must be a */
+            /* character name                                   */
+            FT_Byte*  cur2 = cur + 1;
+            FT_Int    len;
+
+
+            while ( cur2 < limit && is_alpha( *cur2 ) )
+              cur2++;
+
+            len = cur2 - cur - 1;
+
+            parser->root.error = Z1_Add_Table( char_table, charcode,
+                                          cur + 1, len + 1 );
+            char_table->elements[charcode][len] = '\0';
+            if ( parser->root.error )
+              return;
+
+            cur = cur2;
+          }
+        }
+        else
+          cur++;
+      }
+
+      face->type1.encoding_type = t1_encoding_array;
+      parser->root.cursor       = cur;
+    }
+    /* Otherwise, we should have either `StandardEncoding' or */
+    /* `ExpertEncoding'                                       */
+    else
+    {
+      if ( cur + 17 < limit &&
+           strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
+        face->type1.encoding_type = t1_encoding_standard;
+
+      else if ( cur + 15 < limit &&
+                strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
+        face->type1.encoding_type = t1_encoding_expert;
+
+      else
+      {
+        FT_ERROR(( "parse_encoding: invalid token!\n" ));
+        parser->root.error = T1_Err_Invalid_File_Format;
+      }
+    }
+  }
+
+
+  static
+  void  parse_subrs( T1_Face     face,
+                     Z1_Loader*  loader )
+  {
+    Z1_Parser*  parser = &loader->parser;
+    PS_Table*   table  = &loader->subrs;
+    FT_Memory   memory = parser->root.memory;
+    FT_Error    error;
+    FT_Int      n;
+
+    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
+
+    
+    loader->num_subrs = Z1_ToInt( parser );
+    if ( parser->root.error )
+      return;
+
+    /* position the parser right before the `dup' of the first subr */
+    Z1_Skip_Spaces( parser );
+    Z1_Skip_Alpha( parser );      /* `array' */
+    Z1_Skip_Spaces( parser );
+
+    /* initialize subrs array */
+    error = psaux->ps_table_funcs->init( table, loader->num_subrs, memory );
+    if ( error )
+      goto Fail;
+
+    /* the format is simple:                                 */
+    /*                                                       */
+    /*   `index' + binary data                               */
+    /*                                                       */
+
+    for ( n = 0; n < loader->num_subrs; n++ )
+    {
+      FT_Int    index, size;
+      FT_Byte*  base;
+
+
+      /* If the next token isn't `dup', we are also done.  This */
+      /* happens when there are `holes' in the Subrs array.     */
+      if ( strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 )
+        break;
+
+      index = Z1_ToInt( parser );
+      
+      if ( !read_binary_data( parser, &size, &base ) )
+        return;
+
+      /* The binary string is followed by one token, e.g. `NP' */
+      /* (bound to `noaccess put') or by two separate tokens:  */
+      /* `noaccess' & `put'.  We position the parser right     */
+      /* before the next `dup', if any.                        */
+      Z1_Skip_Spaces( parser );
+      Z1_Skip_Alpha( parser );    /* `NP' or `I' or `noaccess' */
+      Z1_Skip_Spaces( parser );
+
+      if ( strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 )
+      {
+        Z1_Skip_Alpha( parser );  /* skip `put' */
+        Z1_Skip_Spaces( parser );
+      }
+
+      /* some fonts use a value of -1 for lenIV to indicate that */
+      /* the charstrings are unencoded                           */
+      /*                                                         */
+      /* thanks to Tom Kacvinsky for pointing this out           */
+      /*                                                         */
+      if ( face->type1.private_dict.lenIV >= 0 )
+      {
+        Z1_Decrypt( base, size, 4330 );
+        size -= face->type1.private_dict.lenIV;
+        base += face->type1.private_dict.lenIV;
+      }
+
+      error = Z1_Add_Table( table, index, base, size );
+      if ( error )
+        goto Fail;
+    }
+    return;
+
+  Fail:
+    parser->root.error = error;
+  }
+
+
+  static
+  void  parse_charstrings( T1_Face     face,
+                           Z1_Loader*  loader )
+  {
+    Z1_Parser*  parser     = &loader->parser;
+    PS_Table*   code_table = &loader->charstrings;
+    PS_Table*   name_table = &loader->glyph_names;
+    FT_Memory   memory     = parser->root.memory;
+    FT_Error    error;
+
+    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
+
+    FT_Byte*    cur;
+    FT_Byte*    limit = parser->root.limit;
+    FT_Int      n;
+    FT_UInt     notdef_index = 0;
+    FT_Byte     notdef_found = 0;
+
+
+    if ( loader->num_glyphs )
+      /*  with synthetic fonts, it's possible we get here twice  */
+      return;
+
+    loader->num_glyphs = Z1_ToInt( parser );
+    if ( parser->root.error )
+      return;
+
+    /* initialize tables, adding space for `swap' at table end   */
+    error = psaux->ps_table_funcs->init( code_table,
+                                         loader->num_glyphs + 1,
+                                         memory );
+    if ( error )
+      goto Fail;
+
+    error = psaux->ps_table_funcs->init( name_table,
+                                         loader->num_glyphs + 1,
+                                         memory );
+    if ( error )
+      goto Fail;
+
+    n = 0;
+    for (;;)
+    {
+      FT_Int    size;
+      FT_Byte*  base;
+
+
+      /* the format is simple:                    */
+      /*   `/glyphname' + binary data             */
+      /*                                          */
+      /* note that we stop when we find a `def'   */
+      /*                                          */
+      Z1_Skip_Spaces( parser );
+
+      cur = parser->root.cursor;
+      if ( cur >= limit )
+        break;
+
+      /* we stop when we find a `def' or `end' keyword */
+      if ( *cur   == 'd'   &&
+           cur + 3 < limit &&
+           cur[1] == 'e'   &&
+           cur[2] == 'f'   )
+        break;
+
+      if ( *cur   == 'e'   &&
+           cur + 3 < limit &&
+           cur[1] == 'n'   &&
+           cur[2] == 'd'   )
+        break;
+
+      if ( *cur != '/' )
+        Z1_Skip_Alpha( parser );
+      else
+      {
+        FT_Byte*  cur2 = cur + 1;
+        FT_Int    len;
+
+
+        while ( cur2 < limit && is_alpha( *cur2 ) )
+          cur2++;
+        len = cur2 - cur - 1;
+
+        error = Z1_Add_Table( name_table, n, cur + 1, len + 1 );
+        if ( error )
+          goto Fail;
+
+        /* add a trailing zero to the name table */
+        name_table->elements[n][len] = '\0';
+
+        /* record index of /.notdef              */
+        if ( strcmp( (const char*)".notdef",
+                     (const char*)(name_table->elements[n]) ) == 0 )
+        {
+          notdef_index = n;
+          notdef_found = 1;
+        }
+
+        parser->root.cursor = cur2;
+        if ( !read_binary_data( parser, &size, &base ) )
+          return;
+
+        if ( face->type1.private_dict.lenIV >= 0 )
+        {
+          Z1_Decrypt( base, size, 4330 );
+          size -= face->type1.private_dict.lenIV;
+          base += face->type1.private_dict.lenIV;
+        }
+
+        error = Z1_Add_Table( code_table, n, base, size );
+        if ( error )
+          goto Fail;
+
+        n++;
+        if ( n >= loader->num_glyphs )
+          break;
+      }
+    }
+
+    loader->num_glyphs = n;
+
+    /* if /.notdef is found but does not occupy index 0, do our magic.      */
+    if ( strcmp( (const char*)".notdef",
+                 (const char*)name_table->elements[0] ) &&
+         notdef_found                                      )
+    {
+
+      /* Swap glyph in index 0 with /.notdef glyph.  First, add index 0     */
+      /* name/code to end of table. Then place notdef_index name/code into  */
+      /* index 0.  Then take end of table name/code and place it into index */
+      /* notdef_index.                                                      */
+
+      error = Z1_Add_Table( name_table, n, 
+                            name_table->elements[0],
+                            name_table->lengths [0] );
+      if ( error )
+        goto Fail;
+      error = Z1_Add_Table( code_table, n,
+                            code_table->elements[0],
+                            code_table->lengths [0] );
+      if ( error )
+        goto Fail;
+
+      error = Z1_Add_Table( name_table, 0,
+                            name_table->elements[notdef_index],
+                            name_table->lengths [notdef_index] );
+      if ( error )
+        goto Fail;
+
+      error = Z1_Add_Table( code_table, 0,
+                            code_table->elements[notdef_index],
+                            code_table->lengths [notdef_index] );
+      if ( error )
+        goto Fail;
+
+      error = Z1_Add_Table( name_table, notdef_index,
+                            name_table->elements[n],
+                            name_table->lengths [n] );
+      if ( error )
+        goto Fail;
+
+      error = Z1_Add_Table( code_table, notdef_index,
+                            code_table->elements[n],
+                            code_table->lengths [n] );
+      if ( error )
+        goto Fail;
+
+    }
+    else if ( !notdef_found )
+    {
+
+      /* notdef_index is already 0, or /.notdef is undefined in  */
+      /* charstrings dictionary. Worry about /.notdef undefined. */
+      /* we take index 0 and add it to the end of the table(s)   */
+      /* and add our own /.notdef glyph to index 0.              */
+      
+      /* 0 333 hsbw endchar                                      */
+      FT_Byte  notdef_glyph[] = {0x8B, 0xF7, 0xE1, 0x0D, 0x0E};
+      char*    notdef_name    = ".notdef";
+
+
+      error = Z1_Add_Table( name_table, n,
+                            name_table->elements[0],
+                            name_table->lengths [0] );
+      if ( error )
+        goto Fail;
+
+      error = Z1_Add_Table( code_table, n,
+                            code_table->elements[0],
+                            code_table->lengths [0] );
+      if ( error )
+        goto Fail;
+
+      error = Z1_Add_Table( name_table, 0, notdef_name, 8 );
+      if ( error )
+        goto Fail;
+
+      error = Z1_Add_Table( code_table, 0, notdef_glyph, 5 );
+
+      if ( error )
+        goto Fail;
+
+      /* we added a glyph. */
+      loader->num_glyphs = n + 1;
+
+    }
+
+    return;
+
+  Fail:
+    parser->root.error = error;
+  }
+
+
+  static
+  const T1_Field  t1_keywords[] =
+  {
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1tokens.h"
+
+#else
+
+#include <type1z/z1tokens.h>
+
+#endif
+
+    /* now add the special functions... */
+    T1_FIELD_CALLBACK( "FontName", parse_font_name )
+    T1_FIELD_CALLBACK( "FontBBox", parse_font_bbox )
+    T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix )
+    T1_FIELD_CALLBACK( "Encoding", parse_encoding )
+    T1_FIELD_CALLBACK( "Subrs", parse_subrs )
+    T1_FIELD_CALLBACK( "CharStrings", parse_charstrings )
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+    T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions )
+    T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map )
+    T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types )
+    T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector )
+    T1_FIELD_CALLBACK( "shareddict", parse_shared_dict )
+#endif
+
+    { 0, t1_field_cid_info, t1_field_none, 0, 0, 0, 0, 0 }
+  };
+
+
+  static
+  FT_Error  parse_dict( T1_Face     face,
+                        Z1_Loader*  loader,
+                        FT_Byte*    base,
+                        FT_Long     size )
+  {
+    Z1_Parser*  parser = &loader->parser;
+
+
+    parser->root.cursor = base;
+    parser->root.limit  = base + size;
+    parser->root.error  = 0;
+
+    {
+      FT_Byte*  cur   = base;
+      FT_Byte*  limit = cur + size;
+
+
+      for ( ; cur < limit; cur++ )
+      {
+        /* look for `FontDirectory', which causes problems on some fonts */
+        if ( *cur == 'F' && cur + 25 < limit                 &&
+             strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
+        {
+          FT_Byte*  cur2;
+
+
+          /* skip the `FontDirectory' keyword */
+          cur += 13;
+          cur2 = cur;
+
+          /* lookup the `known' keyword */
+          while ( cur < limit && *cur != 'k'        &&
+                  strncmp( (char*)cur, "known", 5 ) )
+            cur++;
+
+          if ( cur < limit )
+          {
+            T1_Token  token;
+
+
+            /* skip the `known' keyword and the token following it */
+            cur += 5;
+            loader->parser.root.cursor = cur;
+            Z1_ToToken( &loader->parser, &token );
+
+            /* if the last token was an array, skip it! */
+            if ( token.type == t1_token_array )
+              cur2 = parser->root.cursor;
+          }
+          cur = cur2;
+        }
+        /* 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 )
+          {
+            if ( !loader->fontdata )
+            {
+              if ( strncmp( (char*)cur, "FontInfo", 8 ) == 0 )
+                loader->fontdata = 1;
+            }
+            else
+            {
+              /* now, compare the immediate name to the keyword table */
+              T1_Field*  keyword = (T1_Field*)t1_keywords;
+
+
+              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->root.cursor = cur2;
+                    Z1_Skip_Spaces( parser );
+                    parser->root.error = t1_load_keyword( face,
+                                                          loader,
+                                                          keyword );
+                    if ( parser->root.error )
+                      return parser->root.error;
+
+                    cur = parser->root.cursor;
+                    break;
+                  }
+                }
+                keyword++;
+              }
+            }
+          }
+        }
+      }
+    }
+    return parser->root.error;
+  }
+
+
+  static
+  void  t1_init_loader( Z1_Loader*  loader,
+                        T1_Face     face )
+  {
+    FT_UNUSED( face );
+
+    MEM_Set( loader, 0, sizeof ( *loader ) );
+    loader->num_glyphs = 0;
+    loader->num_chars  = 0;
+
+    /* initialize the tables -- simply set their `init' field to 0 */
+    loader->encoding_table.init = 0;
+    loader->charstrings.init    = 0;
+    loader->glyph_names.init    = 0;
+    loader->subrs.init          = 0;
+    loader->fontdata            = 0;
+  }
+
+
+  static
+  void  t1_done_loader( Z1_Loader*  loader )
+  {
+    Z1_Parser*  parser = &loader->parser;
+
+
+    /* finalize tables */
+    Z1_Release_Table( &loader->encoding_table );
+    Z1_Release_Table( &loader->charstrings );
+    Z1_Release_Table( &loader->glyph_names );
+    Z1_Release_Table( &loader->subrs );
+
+    /* finalize parser */
+    Z1_Done_Parser( parser );
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  Z1_Open_Face( T1_Face  face )
+  {
+    Z1_Loader   loader;
+    Z1_Parser*  parser;
+    T1_Font*    type1 = &face->type1;
+    FT_Error    error;
+    
+    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
+
+
+    t1_init_loader( &loader, face );
+
+    /* default lenIV */
+    type1->private_dict.lenIV = 4;
+
+    parser = &loader.parser;
+    error = Z1_New_Parser( parser,
+                           face->root.stream,
+                           face->root.memory,
+                           psaux );
+    if ( error )
+      goto Exit;
+
+    error = parse_dict( face, &loader, parser->base_dict, parser->base_len );
+    if ( error )
+      goto Exit;
+
+    error = Z1_Get_Private_Dict( parser );
+    if ( error )
+      goto Exit;
+
+    error = parse_dict( face, &loader, parser->private_dict,
+                        parser->private_len );
+    if ( error )
+      goto Exit;
+
+    /* now, propagate the subrs, charstrings, and glyphnames tables */
+    /* to the Type1 data                                            */
+    type1->num_glyphs = loader.num_glyphs;
+
+    if ( !loader.subrs.init )
+    {
+      FT_ERROR(( "Z1_Open_Face: no subrs array in face!\n" ));
+      error = T1_Err_Invalid_File_Format;
+    }
+
+    if ( !loader.charstrings.init )
+    {
+      FT_ERROR(( "Z1_Open_Face: no charstrings array in face!\n" ));
+      error = T1_Err_Invalid_File_Format;
+    }
+
+    loader.subrs.init  = 0;
+    type1->num_subrs   = loader.num_subrs;
+    type1->subrs_block = loader.subrs.block;
+    type1->subrs       = loader.subrs.elements;
+    type1->subrs_len   = loader.subrs.lengths;
+
+    loader.charstrings.init  = 0;
+    type1->charstrings_block = loader.charstrings.block;
+    type1->charstrings       = loader.charstrings.elements;
+    type1->charstrings_len   = loader.charstrings.lengths;
+
+    /* we copy the glyph names `block' and `elements' fields; */
+    /* the `lengths' field must be released later             */
+    type1->glyph_names_block    = loader.glyph_names.block;
+    type1->glyph_names          = (FT_String**)loader.glyph_names.elements;
+    loader.glyph_names.block    = 0;
+    loader.glyph_names.elements = 0;
+
+    /* we must now build type1.encoding when we have a custom */
+    /* array..                                                */
+    if ( type1->encoding_type == t1_encoding_array )
+    {
+      FT_Int    charcode, index, min_char, max_char;
+      FT_Byte*  char_name;
+      FT_Byte*  glyph_name;
+
+
+      /* OK, we do the following: for each element in the encoding  */
+      /* table, look up the index of the glyph having the same name */
+      /* the index is then stored in type1.encoding.char_index, and */
+      /* a the name to type1.encoding.char_name                     */
+
+      min_char = +32000;
+      max_char = -32000;
+
+      charcode = 0;
+      for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
+      {
+        type1->encoding.char_index[charcode] = 0;
+        type1->encoding.char_name [charcode] = (char *)".notdef";
+
+        char_name = loader.encoding_table.elements[charcode];
+        if ( char_name )
+          for ( index = 0; index < type1->num_glyphs; index++ )
+          {
+            glyph_name = (FT_Byte*)type1->glyph_names[index];
+            if ( strcmp( (const char*)char_name,
+                         (const char*)glyph_name ) == 0 )
+            {
+              type1->encoding.char_index[charcode] = index;
+              type1->encoding.char_name [charcode] = (char*)glyph_name;
+
+              /* Change min/max encoded char only if glyph name is */
+              /* not /.notdef                                      */
+              if ( strcmp( (const char*)".notdef",
+                           (const char*)glyph_name ) != 0 )
+              {
+                if (charcode < min_char) min_char = charcode;
+                if (charcode > max_char) max_char = charcode;
+              }
+              break;
+            }
+          }
+      }
+      type1->encoding.code_first = min_char;
+      type1->encoding.code_last  = max_char;
+      type1->encoding.num_chars  = loader.num_chars;
+   }
+
+  Exit:
+    t1_done_loader( &loader );
+    return error;
+  }
+
+
+/* END */
--- /dev/null
+++ b/src/type1/z1load.h
@@ -1,0 +1,93 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1load.h                                                               */
+/*                                                                         */
+/*    Experimental Type 1 font loader (specification).                     */
+/*                                                                         */
+/*  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 Z1LOAD_H
+#define Z1LOAD_H
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/psaux.h>
+#include <freetype/ftmm.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1parse.h"
+
+#else
+
+#include <type1z/z1parse.h>
+
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+  typedef struct  Z1_Loader_
+  {
+    Z1_Parser  parser;          /* parser used to read the stream */
+
+    FT_Int     num_chars;       /* number of characters in encoding */
+    PS_Table   encoding_table;  /* PS_Table used to store the       */
+                                /* encoding character names         */
+
+    FT_Int     num_glyphs;
+    PS_Table   glyph_names;
+    PS_Table   charstrings;
+
+    FT_Int     num_subrs;
+    PS_Table   subrs;
+    FT_Bool    fontdata;
+
+  } Z1_Loader;
+
+
+  LOCAL_DEF
+  FT_Error  Z1_Open_Face( T1_Face  face );
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+
+  LOCAL_DEF
+  FT_Error  Z1_Get_Multi_Master( T1_Face           face,
+                                 FT_Multi_Master*  master );
+
+  LOCAL_DEF
+  FT_Error  Z1_Set_MM_Blend( T1_Face    face,
+                             FT_UInt    num_coords,
+                             FT_Fixed*  coords );
+
+  LOCAL_DEF
+  FT_Error  Z1_Set_MM_Design( T1_Face   face,
+                              FT_UInt   num_coords,
+                              FT_Long*  coords );
+
+  LOCAL_DEF
+  void  Z1_Done_Blend( T1_Face  face );
+
+#endif /* !Z1_CONFIG_OPTION_NO_MM_SUPPORT */
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* Z1LOAD_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1/z1objs.c
@@ -1,0 +1,406 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1objs.c                                                               */
+/*                                                                         */
+/*    Experimental Type 1 objects manager (body).                          */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1gload.h"
+#include "z1load.h"
+#include "z1afm.h"
+
+#else
+
+#include <type1z/z1gload.h>
+#include <type1z/z1load.h>
+#include <type1z/z1afm.h>
+
+#endif
+
+
+#include <freetype/internal/psnames.h>
+#include <freetype/internal/psaux.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_z1objs
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                            FACE  FUNCTIONS                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Z1_Done_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The face object destructor.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A typeless pointer to the face object to destroy.          */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  Z1_Done_Face( T1_Face  face )
+  {
+    FT_Memory  memory;
+    T1_Font*   type1 = &face->type1;
+
+
+    if ( face )
+    {
+      memory = face->root.memory;
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+      /* release multiple masters information */
+      Z1_Done_Blend( face );
+      face->blend = 0;
+#endif
+
+      /* release font info strings */
+      {
+        T1_FontInfo*  info = &type1->font_info;
+
+
+        FREE( info->version );
+        FREE( info->notice );
+        FREE( info->full_name );
+        FREE( info->family_name );
+        FREE( info->weight );
+      }
+
+      /* release top dictionary */
+      FREE( type1->charstrings_len );
+      FREE( type1->charstrings );
+      FREE( type1->glyph_names );
+
+      FREE( type1->subrs );
+      FREE( type1->subrs_len );
+
+      FREE( type1->subrs_block );
+      FREE( type1->charstrings_block );
+      FREE( type1->glyph_names_block );
+
+      FREE( type1->encoding.char_index );
+      FREE( type1->font_name );
+
+#ifndef Z1_CONFIG_OPTION_NO_AFM
+      /* release afm data if present */
+      if ( face->afm_data )
+        Z1_Done_AFM( memory, (Z1_AFM*)face->afm_data );
+#endif
+
+      /* release unicode map, if any */
+      FREE( face->unicode_map.maps );
+      face->unicode_map.num_maps = 0;
+
+      face->root.family_name = 0;
+      face->root.style_name  = 0;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Z1_Init_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The face object constructor.                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream     ::  input stream where to load font data.               */
+  /*                                                                       */
+  /*    face_index :: The index of the font face in the resource.          */
+  /*                                                                       */
+  /*    num_params :: Number of additional generic parameters.  Ignored.   */
+  /*                                                                       */
+  /*    params     :: Additional generic parameters.  Ignored.             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face       :: The face record to build.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  Z1_Init_Face( FT_Stream      stream,
+                          T1_Face        face,
+                          FT_Int         face_index,
+                          FT_Int         num_params,
+                          FT_Parameter*  params )
+  {
+    FT_Error            error;
+    PSNames_Interface*  psnames;
+    PSAux_Interface*    psaux;
+
+    FT_UNUSED( num_params );
+    FT_UNUSED( params );
+    FT_UNUSED( face_index );
+    FT_UNUSED( stream );
+
+
+    face->root.num_faces = 1;
+
+    psnames = (PSNames_Interface*)face->psnames;
+    if ( !psnames )
+    {
+      psnames = (PSNames_Interface*)
+                FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psnames" );
+
+      face->psnames = psnames;
+    }
+
+    psaux = (PSAux_Interface*)face->psaux;
+    if ( !psaux )
+    {
+      psaux = (PSAux_Interface*)
+              FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psaux" );
+              
+      face->psaux = psaux;
+    }
+
+    /* open the tokenizer, this will also check the font format */
+    error = Z1_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(( "Z1_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->type1.num_glyphs;
+      root->num_charmaps = 1;
+
+      root->face_index = face_index;
+      root->face_flags = FT_FACE_FLAG_SCALABLE;
+
+      root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
+
+      root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
+
+      if ( face->type1.font_info.is_fixed_pitch )
+        root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+      if ( face->blend )
+        root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
+
+      /* XXX: TODO -- add kerning with .afm support */
+
+      /* get style name -- be careful, some broken fonts only */
+      /* have a `/FontName' dictionary entry!                 */
+      root->family_name = face->type1.font_info.family_name;
+      if ( root->family_name )
+      {
+        char*  full   = face->type1.font_info.full_name;
+        char*  family = root->family_name;
+
+
+        while ( *family && *full == *family )
+        {
+          family++;
+          full++;
+        }
+
+        root->style_name = ( *full == ' ' ? full + 1
+                                          : (char *)"Regular" );
+      }
+      else
+      {
+        /* do we have a `/FontName'? */
+        if ( face->type1.font_name )
+        {
+          root->family_name = face->type1.font_name;
+          root->style_name  = (char *)"Regular";
+        }
+      }
+
+      /* no embedded bitmap support */
+      root->num_fixed_sizes = 0;
+      root->available_sizes = 0;
+
+      root->bbox         = face->type1.font_bbox;
+      root->units_per_EM = 1000;
+      root->ascender     = (FT_Short)face->type1.font_bbox.yMax;
+      root->descender    = (FT_Short)face->type1.font_bbox.yMin;
+      root->height       = ( ( root->ascender + root->descender ) * 12 ) / 10;
+
+      /* 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 = Z1_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;
+
+      root->underline_position  = face->type1.font_info.underline_position;
+      root->underline_thickness = face->type1.font_info.underline_thickness;
+
+      root->max_points   = 0;
+      root->max_contours = 0;
+    }
+
+    /* charmap support -- synthetize unicode charmap if possible */
+    {
+      FT_Face     root    = &face->root;
+      FT_CharMap  charmap = face->charmaprecs;
+
+
+      /* synthesize a Unicode charmap if there is support in the `PSNames' */
+      /* module                                                            */
+      if ( 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 = FT_Err_Ok;
+        }
+      }
+
+      /* now, support either the standard, expert, or custom encoding */
+      charmap->face        = (FT_Face)face;
+      charmap->platform_id = 7;  /* a new platform id for Adobe fonts? */
+
+      switch ( face->type1.encoding_type )
+      {
+      case t1_encoding_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];
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Z1_Init_Driver                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given Type 1 driver object.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target driver object.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  Z1_Init_Driver( Z1_Driver  driver )
+  {
+    FT_UNUSED( driver );
+
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Z1_Done_Driver                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given Type 1 driver.                                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver  :: A handle to the target Type 1 driver.                   */
+  /*                                                                       */
+  LOCAL_DEF
+  void  Z1_Done_Driver( Z1_Driver  driver )
+  {
+    FT_UNUSED( driver );
+  }
+
+
+/* END */
--- /dev/null
+++ b/src/type1/z1objs.h
@@ -1,0 +1,161 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1objs.h                                                               */
+/*                                                                         */
+/*    Experimental Type 1 objects manager (specification).                 */
+/*                                                                         */
+/*  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 Z1OBJS_H
+#define Z1OBJS_H
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/config/ftconfig.h>
+#include <freetype/internal/t1errors.h>
+#include <freetype/internal/t1types.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+  /* The following structures must be defined by the hinter */
+  typedef struct Z1_Size_Hints_   Z1_Size_Hints;
+  typedef struct Z1_Glyph_Hints_  Z1_Glyph_Hints;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    Z1_Driver                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 driver object.                                */
+  /*                                                                       */
+  typedef struct Z1_DriverRec_   *Z1_Driver;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    Z1_Size                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 size object.                                  */
+  /*                                                                       */
+  typedef struct Z1_SizeRec_*  Z1_Size;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    Z1_GlyphSlot                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 glyph slot object.                            */
+  /*                                                                       */
+  typedef struct Z1_GlyphSlotRec_*  Z1_GlyphSlot;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    Z1_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 Z1_CharMapRec_*   Z1_CharMap;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                  HERE BEGINS THE TYPE1 SPECIFIC STUFF                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    Z1_SizeRec                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Type 1 size record.                                                */
+  /*                                                                       */
+  typedef struct  Z1_SizeRec_
+  {
+    FT_SizeRec      root;
+    FT_Bool         valid;
+    Z1_Size_Hints*  hints;  /* defined in the hinter. This allows */
+                            /* us to experiment with different    */
+                            /* hinting schemes without having to  */
+                            /* change `z1objs' each time.         */
+  } Z1_SizeRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    Z1_GlyphSlotRec                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Type 1 glyph slot record.                                          */
+  /*                                                                       */
+  typedef struct  Z1_GlyphSlotRec_
+  {
+    FT_GlyphSlotRec  root;
+
+    FT_Bool          hint;
+    FT_Bool          scaled;
+
+    FT_Int           max_points;
+    FT_Int           max_contours;
+
+    FT_Fixed         x_scale;
+    FT_Fixed         y_scale;
+
+    Z1_Glyph_Hints*  hints;  /* defined in the hinter */
+
+  } Z1_GlyphSlotRec;
+
+
+  LOCAL_DEF
+  FT_Error  Z1_Init_Face( FT_Stream      stream,
+                          T1_Face        face,
+                          FT_Int         face_index,
+                          FT_Int         num_params,
+                          FT_Parameter*  params );
+
+  LOCAL_DEF
+  void  Z1_Done_Face( T1_Face  face );
+
+  LOCAL_DEF
+  FT_Error  Z1_Init_Driver( Z1_Driver  driver );
+
+  LOCAL_DEF
+  void  Z1_Done_Driver( Z1_Driver  driver );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* Z1OBJS_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1/z1parse.c
@@ -1,0 +1,487 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1parse.c                                                              */
+/*                                                                         */
+/*    Experimental Type 1 parser (body).                                   */
+/*                                                                         */
+/*  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 Type 1 parser is in charge of the following:                      */
+  /*                                                                       */
+  /*  - provide an implementation of a growing sequence of objects called  */
+  /*    a `Z1_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 `z1load.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 <freetype/internal/t1errors.h>
+#include <freetype/internal/psaux.h>
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1parse.h"
+
+#else
+
+#include <type1z/z1parse.h>
+
+#endif
+
+
+#include <string.h>     /* for strncmp() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_z1parse
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                   INPUT STREAM PARSER                         *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#define IS_Z1_WHITESPACE( c )  ( (c) == ' '  || (c) == '\t' )
+#define IS_Z1_LINESPACE( c )   ( (c) == '\r' || (c) == '\n' )
+
+#define IS_Z1_SPACE( c )  ( IS_Z1_WHITESPACE( c ) || IS_Z1_LINESPACE( c ) )
+
+
+  typedef struct  PFB_Tag_
+  {
+    FT_UShort  tag;
+    FT_Long    size;
+    
+  } PFB_Tag;
+
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  PFB_Tag
+
+
+  static
+  const FT_Frame_Field  pfb_tag_fields[] =
+  {
+    FT_FRAME_START( 6 ),
+      FT_FRAME_USHORT ( tag ),
+      FT_FRAME_LONG_LE( size ),
+    FT_FRAME_END
+  };
+
+
+  static
+  FT_Error  read_pfb_tag( FT_Stream   stream,
+                          FT_UShort*  tag,
+                          FT_Long*    size )
+  {
+    FT_Error  error;
+    PFB_Tag   head;
+
+
+    *tag  = 0;
+    *size = 0;
+    if ( !READ_Fields( pfb_tag_fields, &head ) )
+    {
+      if ( head.tag == 0x8001 || head.tag == 0x8002 )
+      {
+        *tag  = head.tag;
+        *size = head.size;
+      }
+    }
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  Z1_New_Parser( Z1_Parser*        parser,
+                           FT_Stream         stream,
+                           FT_Memory         memory,
+                           PSAux_Interface*  psaux )
+  {
+    FT_Error   error;
+    FT_UShort  tag;
+    FT_Long    size;
+
+
+    psaux->t1_parser_funcs->init( &parser->root,0, 0, memory );
+
+    parser->stream       = stream;
+    parser->base_len     = 0;
+    parser->base_dict    = 0;
+    parser->private_len  = 0;
+    parser->private_dict = 0;
+    parser->in_pfb       = 0;
+    parser->in_memory    = 0;
+    parser->single_block = 0;
+
+    /******************************************************************/
+    /*                                                                */
+    /* Here a short summary of what is going on:                      */
+    /*                                                                */
+    /*   When creating a new Type 1 parser, we try to locate and load */
+    /*   the base dictionary if this is possible (i.e. for PFB        */
+    /*   files).  Otherwise, we load the whole font into memory.      */
+    /*                                                                */
+    /*   When `loading' the base dictionary, we only setup pointers   */
+    /*   in the case of a memory-based stream.  Otherwise, we         */
+    /*   allocate and load the base dictionary in it.                 */
+    /*                                                                */
+    /*   parser->in_pfb is set if we are in a binary (".pfb") font.   */
+    /*   parser->in_memory is set if we have a memory stream.         */
+    /*                                                                */
+
+    /* try to compute the size of the base dictionary;   */
+    /* look for a Postscript binary file tag, i.e 0x8001 */
+    if ( FILE_Seek( 0L ) )
+      goto Exit;
+
+    error = read_pfb_tag( stream, &tag, &size );
+    if ( error )
+      goto Exit;
+
+    if ( tag != 0x8001 )
+    {
+      /* assume that this is a PFA file for now; an error will */
+      /* be produced later when more things are checked        */
+      if ( FILE_Seek( 0L ) )
+        goto Exit;
+      size = stream->size;
+    }
+    else
+      parser->in_pfb = 1;
+
+    /* now, try to load `size' bytes of the `base' dictionary we */
+    /* found previously                                          */
+
+    /* if it is a memory-based resource, set up pointers */
+    if ( !stream->read )
+    {
+      parser->base_dict = (FT_Byte*)stream->base + stream->pos;
+      parser->base_len  = size;
+      parser->in_memory = 1;
+
+      /* check that the `size' field is valid */
+      if ( FILE_Skip( size ) )
+        goto Exit;
+    }
+    else
+    {
+      /* read segment in memory */
+      if ( ALLOC( parser->base_dict, size )     ||
+           FILE_Read( parser->base_dict, size ) )
+        goto Exit;
+      parser->base_len = size;
+    }
+
+    /* Now check font format; we must see `%!PS-AdobeFont-1' */
+    /* or `%!FontType'                                       */
+    {
+      if ( size <= 16                                    ||
+           ( strncmp( (const char*)parser->base_dict,
+                      "%!PS-AdobeFont-1", 16 )        &&
+             strncmp( (const char*)parser->base_dict,
+                      "%!FontType", 10 )              )  )
+      {
+        FT_TRACE2(( "[not a Type1 font]\n" ));
+        error = FT_Err_Unknown_File_Format;
+      }
+      else
+      {
+        parser->root.base   = parser->base_dict;
+        parser->root.cursor = parser->base_dict;
+        parser->root.limit  = parser->root.cursor + parser->base_len;
+      }
+    }
+
+  Exit:
+    if ( error && !parser->in_memory )
+      FREE( parser->base_dict );
+
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  void  Z1_Done_Parser( Z1_Parser*  parser )
+  {
+    FT_Memory   memory = parser->root.memory;
+
+
+    /* always free the private dictionary */
+    FREE( parser->private_dict );
+
+    /* free the base dictionary only when we have a disk stream */
+    if ( !parser->in_memory )
+      FREE( parser->base_dict );
+      
+    parser->root.funcs.done( &parser->root );
+  }
+
+
+  /* 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;
+  }
+
+
+  LOCAL_FUNC
+  void  Z1_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--;
+    }
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  Z1_Get_Private_Dict( Z1_Parser*  parser )
+  {
+    FT_Stream  stream = parser->stream;
+    FT_Memory  memory = parser->root.memory;
+    FT_Error   error  = 0;
+    FT_Long    size;
+
+
+    if ( parser->in_pfb )
+    {
+      /* in the case of the PFB format, the private dictionary can be  */
+      /* made of several segments.  We thus first read the number of   */
+      /* segments to compute the total size of the private dictionary  */
+      /* then re-read them into memory.                                */
+      FT_Long    start_pos = FILE_Pos();
+      FT_UShort  tag;
+
+
+      parser->private_len = 0;
+      for (;;)
+      {
+        error = read_pfb_tag( stream, &tag, &size );
+        if ( error )
+          goto Fail;
+
+        if ( tag != 0x8002 )
+          break;
+
+        parser->private_len += size;
+
+        if ( FILE_Skip( size ) )
+          goto Fail;
+      }
+
+      /* Check that we have a private dictionary there */
+      /* and allocate private dictionary buffer        */
+      if ( parser->private_len == 0 )
+      {
+        FT_ERROR(( "Z1_Get_Private_Dict:" ));
+        FT_ERROR(( " invalid private dictionary section\n" ));
+        error = T1_Err_Invalid_File_Format;
+        goto Fail;
+      }
+
+      if ( FILE_Seek( start_pos )                             ||
+           ALLOC( parser->private_dict, parser->private_len ) )
+        goto Fail;
+
+      parser->private_len = 0;
+      for (;;)
+      {
+        error = read_pfb_tag( stream, &tag, &size );
+        if ( error || tag != 0x8002 )
+        {
+          error = FT_Err_Ok;
+          break;
+        }
+
+        if ( FILE_Read( parser->private_dict + parser->private_len, size ) )
+          goto Fail;
+
+        parser->private_len += size;
+      }
+    }
+    else
+    {
+      /* we have already `loaded' the whole PFA font file into memory; */
+      /* if this is a memory resource, allocate a new block to hold    */
+      /* the private dict. Otherwise, simply overwrite into the base   */
+      /* dictionary block in the heap.                                 */
+
+      /* first of all, look at the `eexec' keyword */
+      FT_Byte*  cur   = parser->base_dict;
+      FT_Byte*  limit = cur + parser->base_len;
+      FT_Byte   c;
+
+
+      for (;;)
+      {
+        c = cur[0];
+        if ( c == 'e' && cur + 9 < limit )  /* 9 = 5 letters for `eexec' + */
+                                            /* newline + 4 chars           */
+        {
+          if ( cur[1] == 'e' && cur[2] == 'x' &&
+               cur[3] == 'e' && cur[4] == 'c' )
+          {
+            cur += 6; /* we skip the newling after the `eexec' */
+
+            /* XXX: Some fonts use DOS-linefeeds, i.e. \r\n; we need to */
+            /*      skip the extra \n if we find it                     */
+            if ( cur[0] == '\n' )
+              cur++;
+
+            break;
+          }
+        }
+        cur++;
+        if ( cur >= limit )
+        {
+          FT_ERROR(( "Z1_Get_Private_Dict:" ));
+          FT_ERROR(( " could not find `eexec' keyword\n" ));
+          error = T1_Err_Invalid_File_Format;
+          goto Exit;
+        }
+      }
+
+      /* now determine where to write the _encrypted_ binary private  */
+      /* dictionary.  We overwrite the base dictionary for disk-based */
+      /* resources and allocate a new block otherwise                 */
+
+      size = parser->base_len - ( cur - parser->base_dict);
+
+      if ( parser->in_memory )
+      {
+        /* note that we allocate one more byte to put a terminating `0' */
+        if ( ALLOC( parser->private_dict, size + 1 ) )
+          goto Fail;
+        parser->private_len = size;
+      }
+      else
+      {
+        parser->single_block = 1;
+        parser->private_dict = parser->base_dict;
+        parser->private_len  = size;
+        parser->base_dict    = 0;
+        parser->base_len     = 0;
+      }
+
+      /* now determine whether the private dictionary is encoded in binary */
+      /* or hexadecimal ASCII format -- decode it accordingly              */
+
+      /* we need to access the next 4 bytes (after the final \r following */
+      /* the `eexec' keyword); if they all are hexadecimal digits, then   */
+      /* we have a case of ASCII storage                                  */
+
+      if ( ( hexa_value( cur[0] ) | hexa_value( cur[1] ) |
+             hexa_value( cur[2] ) | hexa_value( cur[3] ) ) < 0 )
+
+        /* binary encoding -- `simply' copy the private dict */
+        MEM_Copy( parser->private_dict, cur, size );
+
+      else
+      {
+        /* ASCII hexadecimal encoding */
+
+        FT_Byte*  write;
+        FT_Int    count;
+
+
+        write = parser->private_dict;
+        count = 0;
+
+        for ( ;cur < limit; cur++ )
+        {
+          int  hex1;
+
+
+          /* check for newline */
+          if ( cur[0] == '\r' || cur[0] == '\n' )
+            continue;
+
+          /* exit if we have a non-hexadecimal digit that isn't a newline */
+          hex1 = hexa_value( cur[0] );
+          if ( hex1 < 0 || cur + 1 >= limit )
+            break;
+
+          /* otherwise, store byte */
+          *write++ = ( hex1 << 4 ) | hexa_value( cur[1] );
+          count++;
+          cur++;
+        }
+
+        /* put a safeguard */
+        parser->private_len = write - parser->private_dict;
+        *write++ = 0;
+      }
+    }
+
+    /* we now decrypt the encoded binary private dictionary */
+    Z1_Decrypt( parser->private_dict, parser->private_len, 55665 );
+    parser->root.base = parser->private_dict;
+    parser->root.cursor = parser->private_dict;
+    parser->root.limit  = parser->root.cursor + parser->private_len;
+
+  Fail:
+  Exit:
+    return error;
+  }
+
+
+/* END */
--- /dev/null
+++ b/src/type1/z1parse.h
@@ -1,0 +1,140 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1parse.h                                                              */
+/*                                                                         */
+/*    Experimental Type 1 parser (specification).                          */
+/*                                                                         */
+/*  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 Z1PARSE_H
+#define Z1PARSE_H
+
+#include <freetype/internal/t1types.h>
+#include <freetype/internal/ftstream.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    Z1_Parser                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A Z1_Parser is an object used to parse a Type 1 fonts very         */
+  /*    quickly.                                                           */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    root         :: The root parser.                                   */
+  /*                                                                       */
+  /*    stream       :: The current input stream.                          */
+  /*                                                                       */
+  /*    base_dict    :: A pointer to the top-level dictionary.             */
+  /*                                                                       */
+  /*    base_len     :: The length in bytes of the top dictionary.         */
+  /*                                                                       */
+  /*    private_dict :: A pointer to the private dictionary.               */
+  /*                                                                       */
+  /*    private_len  :: The length in bytes of the private dictionary.     */
+  /*                                                                       */
+  /*    in_pfb       :: A boolean.  Indicates that we are handling a PFB   */
+  /*                    file.                                              */
+  /*                                                                       */
+  /*    in_memory    :: A boolean.  Indicates a memory-based stream.       */
+  /*                                                                       */
+  /*    single_block :: A boolean.  Indicates that the private dictionary  */
+  /*                    is stored in lieu of the base dictionary.          */
+  /*                                                                       */
+  typedef struct  Z1_Parser_
+  {
+    T1_Parser  root;
+    FT_Stream  stream;
+
+    FT_Byte*   base_dict;
+    FT_Int     base_len;
+
+    FT_Byte*   private_dict;
+    FT_Int     private_len;
+
+    FT_Byte    in_pfb;
+    FT_Byte    in_memory;
+    FT_Byte    single_block;
+
+  } Z1_Parser;
+
+
+#define Z1_Add_Table( p, i, o, l )  (p)->funcs.add( (p), i, o, l )
+#define Z1_Done_Table( p )          \
+          do                        \
+          {                         \
+            if ( (p)->funcs.done )  \
+              (p)->funcs.done( p ); \
+          } while ( 0 )
+#define Z1_Release_Table( p )          \
+          do                           \
+          {                            \
+            if ( (p)->funcs.release )  \
+              (p)->funcs.release( p ); \
+          } while ( 0 )
+
+
+#define Z1_Skip_Spaces( p )  (p)->root.funcs.skip_spaces( &(p)->root )
+#define Z1_Skip_Alpha( p )   (p)->root.funcs.skip_alpha ( &(p)->root )
+
+#define Z1_ToInt( p )       (p)->root.funcs.to_int( &(p)->root )
+#define Z1_ToFixed( p, t )  (p)->root.funcs.to_fixed( &(p)->root, t )
+
+#define Z1_ToCoordArray( p, m, c )    \
+          (p)->root.funcs.to_coord_array( &(p)->root, m, c )
+#define Z1_ToFixedArray( p, m, f, t ) \
+          (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
+#define Z1_ToToken( p, t )            \
+          (p)->root.funcs.to_token( &(p)->root, t )
+#define Z1_ToTokenArray( p, t, m, c ) \
+          (p)->root.funcs.to_token_array( &(p)->root, t, m, c )
+
+#define Z1_Load_Field( p, f, o, m, pf )       \
+          (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )
+#define Z1_Load_Field_Table( p, f, o, m, pf ) \
+          (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )
+
+
+  LOCAL_DEF
+  FT_Error  Z1_New_Parser( Z1_Parser*        parser,
+                           FT_Stream         stream,
+                           FT_Memory         memory,
+                           PSAux_Interface*  psaux );
+
+  LOCAL_DEF
+  FT_Error  Z1_Get_Private_Dict( Z1_Parser*  parser );
+
+  LOCAL_DEF
+  void  Z1_Decrypt( FT_Byte*   buffer,
+                    FT_Int     length,
+                    FT_UShort  seed );
+
+  LOCAL_DEF
+  void  Z1_Done_Parser( Z1_Parser*  parser );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* Z1PARSE_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1/z1tokens.h
@@ -1,0 +1,73 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1tokens.h                                                             */
+/*                                                                         */
+/*    Experimental Type 1 tokenizer (specification).                       */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  T1_FontInfo
+#undef  T1CODE
+#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_NUM   ( "ItalicAngle", italic_angle )
+  T1_FIELD_BOOL  ( "isFixedPitch", is_fixed_pitch )
+  T1_FIELD_NUM   ( "UnderlinePosition", underline_position )
+  T1_FIELD_NUM   ( "UnderlineThickness", underline_thickness )
+
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  T1_Private
+#undef  T1CODE
+#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 )
+
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  T1_Font
+#undef  T1CODE
+#define T1CODE        t1_field_font_dict
+
+  T1_FIELD_NUM( "PaintType", paint_type )
+  T1_FIELD_NUM( "FontType", font_type )
+  T1_FIELD_NUM( "StrokeWidth", stroke_width )
+
+
+/* END */
--- a/src/type1z/Readme.txt
+++ /dev/null
@@ -1,10 +1,0 @@
-This directory contains an experimental Type 1 driver that will ultimately
-replace the "official" one in "src/type1".
-
-This driver doesn't provide a mini Postscript interpreter, but uses
-pattern matching in order to load data from fonts. It works better and
-faster than the official driver, but will replace it only when we finish
-the auto-hinting module..
-
-You don't need to compile it to support Type 1 fonts, the driver should
-co-exist peacefully with the rest of the engine however..
--- a/src/type1z/module.mk
+++ /dev/null
@@ -1,22 +1,0 @@
-#
-# FreeType 2 Type1z module definition
-#
-
-
-# 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.
-
-
-make_module_list: add_type1_driver
-
-add_type1_driver:
-	$(OPEN_DRIVER)t1_driver_class$(CLOSE_DRIVER)
-	$(ECHO_DRIVER)type1     $(ECHO_DRIVER_DESC)Postscript font files with extension *.pfa or *.pfb$(ECHO_DRIVER_DONE)
-
-# EOF
--- a/src/type1z/rules.mk
+++ /dev/null
@@ -1,72 +1,0 @@
-#
-# FreeType 2 Type1z 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.
-
-
-# Type1z driver directory
-#
-T1Z_DIR  := $(SRC_)type1z
-T1Z_DIR_ := $(T1Z_DIR)$(SEP)
-
-
-# compilation flags for the driver
-#
-T1Z_COMPILE := $(FT_COMPILE)
-
-
-# Type1 driver sources (i.e., C files)
-#
-T1Z_DRV_SRC := $(T1Z_DIR_)z1parse.c  \
-               $(T1Z_DIR_)z1load.c   \
-               $(T1Z_DIR_)z1driver.c \
-               $(T1Z_DIR_)z1afm.c    \
-               $(T1Z_DIR_)z1gload.c  \
-               $(T1Z_DIR_)z1objs.c
-
-# Type1 driver headers
-#
-T1Z_DRV_H := $(T1Z_DRV_SRC:%.c=%.h) \
-             $(T1Z_DIR_)z1tokens.h
-
-
-# Type1z driver object(s)
-#
-#   T1Z_DRV_OBJ_M is used during `multi' builds
-#   T1Z_DRV_OBJ_S is used during `single' builds
-#
-T1Z_DRV_OBJ_M := $(T1Z_DRV_SRC:$(T1Z_DIR_)%.c=$(OBJ_)%.$O)
-T1Z_DRV_OBJ_S := $(OBJ_)type1z.$O
-
-# Type1z driver source file for single build
-#
-T1Z_DRV_SRC_S := $(T1Z_DIR_)type1z.c
-
-
-# Type1z driver - single object
-#
-$(T1Z_DRV_OBJ_S): $(T1Z_DRV_SRC_S) $(T1Z_DRV_SRC) $(FREETYPE_H) $(T1Z_DRV_H)
-	$(T1Z_COMPILE) $T$@ $(T1Z_DRV_SRC_S)
-
-
-# Type1z driver - multiple objects
-#
-$(OBJ_)%.$O: $(T1Z_DIR_)%.c $(FREETYPE_H) $(T1Z_DRV_H)
-	$(T1Z_COMPILE) $T$@ $<
-
-
-# update main driver object lists
-#
-DRV_OBJS_S += $(T1Z_DRV_OBJ_S)
-DRV_OBJS_M += $(T1Z_DRV_OBJ_M)
-
-# EOF
--- a/src/type1z/type1z.c
+++ /dev/null
@@ -1,49 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  type1z.c                                                               */
-/*                                                                         */
-/*    FreeType experimental Type 1 driver component (body only).           */
-/*                                                                         */
-/*  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.                                        */
-/*                                                                         */
-/***************************************************************************/
-
-
-#define FT_MAKE_OPTION_SINGLE_OBJECT
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1parse.c"
-#include "z1load.c"
-#include "z1objs.c"
-#include "z1driver.c"
-#include "z1gload.c"
-
-#ifndef Z1_CONFIG_OPTION_NO_AFM
-#include "z1afm.c"
-#endif
-
-#else /* FT_FLAT_COMPILE */
-
-#include <type1z/z1parse.c>
-#include <type1z/z1load.c>
-#include <type1z/z1objs.c>
-#include <type1z/z1driver.c>
-#include <type1z/z1gload.c>
-
-#ifndef Z1_CONFIG_OPTION_NO_AFM
-#include <type1z/z1afm.c>
-#endif
-
-#endif /* FT_FLAT_COMPILE */
-
-
-/* END */
--- a/src/type1z/z1afm.c
+++ /dev/null
@@ -1,293 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  z1afm.c                                                                */
-/*                                                                         */
-/*    AFM support for Type 1 fonts (body).                                 */
-/*                                                                         */
-/*  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.                                        */
-/*                                                                         */
-/***************************************************************************/
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1afm.h"
-
-#else
-
-#include <type1z/z1afm.h>
-
-#endif
-
-
-#include <freetype/internal/ftstream.h>
-#include <freetype/internal/t1types.h>
-
-#include <stdlib.h>  /* for qsort()   */
-#include <string.h>  /* for strcmp()  */
-#include <ctype.h>   /* for isalnum() */
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
-  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
-  /* messages during execution.                                            */
-  /*                                                                       */
-#undef  FT_COMPONENT
-#define FT_COMPONENT  trace_z1afm
-
-
-  LOCAL_FUNC
-  void  Z1_Done_AFM( FT_Memory  memory,
-                     Z1_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 )  ( isalnum( c ) || \
-                            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 && !isdigit( *p ) )
-    {
-      sign = 1;
-      if ( *p == '-' )
-        sign = -1;
-
-      p++;
-    }
-
-    while ( p < limit && isdigit( *p ) )
-    {
-      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 */
-  LOCAL_FUNC_X
-  int  compare_kern_pairs( const void*  a,
-                           const void*  b )
-  {
-    Z1_Kern_Pair*  pair1 = (Z1_Kern_Pair*)a;
-    Z1_Kern_Pair*  pair2 = (Z1_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  Z1_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;
-    Z1_Kern_Pair*  pair;
-    T1_Font*       type1 = &((T1_Face)t1_face)->type1;
-    Z1_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, Z1_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 ( Z1_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  Z1_Get_Kerning( Z1_AFM*     afm,
-                        FT_UInt     glyph1,
-                        FT_UInt     glyph2,
-                        FT_Vector*  kerning )
-  {
-    Z1_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;
-  }
-
-
-/* END */
--- a/src/type1z/z1afm.h
+++ /dev/null
@@ -1,79 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  z1afm.h                                                                */
-/*                                                                         */
-/*    AFM support for Type 1 fonts (specification).                        */
-/*                                                                         */
-/*  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 Z1AFM_H
-#define Z1AFM_H
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1objs.h"
-
-#else
-
-#include <type1z/z1objs.h>
-
-#endif
-
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-
-  typedef struct  Z1_Kern_Pair_
-  {
-    FT_UInt    glyph1;
-    FT_UInt    glyph2;
-    FT_Vector  kerning;
-
-  } Z1_Kern_Pair;
-
-
-  typedef struct  Z1_AFM_
-  {
-    FT_Int         num_pairs;
-    Z1_Kern_Pair*  kern_pairs;
-
-  } Z1_AFM;
-
-
-  LOCAL_DEF
-  FT_Error  Z1_Read_AFM( FT_Face    face,
-                         FT_Stream  stream );
-
-  LOCAL_DEF
-  void  Z1_Done_AFM( FT_Memory  memory,
-                     Z1_AFM*    afm );
-
-  LOCAL_DEF
-  void  Z1_Get_Kerning( Z1_AFM*     afm,
-                        FT_UInt     glyph1,
-                        FT_UInt     glyph2,
-                        FT_Vector*  kerning );
-
-
-#ifdef __cplusplus
-  }
-#endif
-
-
-#endif /* Z1AFM_H */
-
-
-/* END */
--- a/src/type1z/z1driver.c
+++ /dev/null
@@ -1,340 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  z1driver.c                                                             */
-/*                                                                         */
-/*    Experimental Type 1 driver interface (body).                         */
-/*                                                                         */
-/*  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.                                        */
-/*                                                                         */
-/***************************************************************************/
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1driver.h"
-#include "z1gload.h"
-#include "z1load.h"
-#include "z1afm.h"
-
-#else
-
-#include <type1z/z1driver.h>
-#include <type1z/z1gload.h>
-#include <type1z/z1load.h>
-#include <type1z/z1afm.h>
-
-#endif
-
-
-#include <freetype/internal/ftdebug.h>
-#include <freetype/internal/ftstream.h>
-#include <freetype/internal/psnames.h>
-
-#include <string.h>     /* for strcmp() */
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
-  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
-  /* messages during execution.                                            */
-  /*                                                                       */
-#undef  FT_COMPONENT
-#define FT_COMPONENT  trace_z1driver
-
-
-  static
-  FT_Error  get_z1_glyph_name( T1_Face     face,
-                               FT_UInt     glyph_index,
-                               FT_Pointer  buffer,
-                               FT_UInt     buffer_max )
-  {
-    FT_String*  gname;
-    
-
-    gname = face->type1.glyph_names[glyph_index];
-
-    if ( buffer_max > 0 )
-    {
-      FT_UInt  len = strlen( gname );
-      
-
-      if (len >= buffer_max)
-        len = buffer_max - 1;
-        
-      MEM_Copy( buffer, gname, len );
-      ((FT_Byte*)buffer)[len] = 0;
-    }
-
-    return T1_Err_Ok;
-  }                                  
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <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
-  FT_Module_Interface  Get_Interface( FT_Driver         driver,
-                                      const FT_String*  interface )
-  {
-    FT_UNUSED( driver );
-    FT_UNUSED( interface );
-
-    if ( strcmp( (const char*)interface, "glyph_name" ) == 0 )
-      return (FT_Module_Interface)get_z1_glyph_name;
-
-#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
-    if ( strcmp( (const char*)interface, "get_mm" ) == 0 )
-      return (FT_Module_Interface)Z1_Get_Multi_Master;
-
-    if ( strcmp( (const char*)interface, "set_mm_design") == 0 )
-      return (FT_Module_Interface)Z1_Set_MM_Design;
-
-    if ( strcmp( (const char*)interface, "set_mm_blend") == 0 )
-      return (FT_Module_Interface)Z1_Set_MM_Blend;
-#endif
-    return 0;
-  }
-
-
-#ifndef Z1_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,
-                         FT_Vector*  kerning )
-  {
-    Z1_AFM*  afm;
-
-
-    kerning->x = 0;
-    kerning->y = 0;
-
-    afm = (Z1_AFM*)face->afm_data;
-    if ( afm )
-      Z1_Get_Kerning( afm, left_glyph, right_glyph, kerning );
-
-    return T1_Err_Ok;
-  }
-
-
-#endif /* T1_CONFIG_OPTION_NO_AFM */
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <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 if 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;
-  }
-
-
-  FT_CPLUSPLUS( const FT_Driver_Class )  t1_driver_class =
-  {
-    {
-      ft_module_font_driver | ft_module_driver_scalable,
-      sizeof( FT_DriverRec ),
-
-      "type1",
-      0x10000L,
-      0x20000L,
-
-      0,   /* format interface */
-
-      (FT_Module_Constructor)Z1_Init_Driver,
-      (FT_Module_Destructor) Z1_Done_Driver,
-      (FT_Module_Requester)  Get_Interface,
-    },
-
-    sizeof( T1_FaceRec ),
-    sizeof( Z1_SizeRec ),
-    sizeof( Z1_GlyphSlotRec ),
-
-    (FTDriver_initFace)     Z1_Init_Face,
-    (FTDriver_doneFace)     Z1_Done_Face,
-    (FTDriver_initSize)     0,
-    (FTDriver_doneSize)     0,
-    (FTDriver_initGlyphSlot)0,
-    (FTDriver_doneGlyphSlot)0,
-
-    (FTDriver_setCharSizes) 0,
-    (FTDriver_setPixelSizes)0,
-    (FTDriver_loadGlyph)    Z1_Load_Glyph,
-    (FTDriver_getCharIndex) Get_Char_Index,
-
-#ifdef Z1_CONFIG_OPTION_NO_AFM
-    (FTDriver_getKerning)   0,
-    (FTDriver_attachFile)   0,
-#else
-    (FTDriver_getKerning)   Get_Kerning,
-    (FTDriver_attachFile)   Z1_Read_AFM,
-#endif
-    (FTDriver_getAdvances)  0
-  };
-
-
-#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
-
-  EXPORT_FUNC( const FT_Driver_Class* )  getDriverClass( void )
-  {
-    return &t1z_driver_class;
-  }
-
-#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
-
-
-/* END */
--- a/src/type1z/z1driver.h
+++ /dev/null
@@ -1,39 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  z1driver.h                                                             */
-/*                                                                         */
-/*    High-level experimental Type 1 driver interface (specification).     */
-/*                                                                         */
-/*  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 Z1DRIVER_H
-#define Z1DRIVER_H
-
-#include <freetype/internal/ftdriver.h>
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-
-  FT_EXPORT_VAR( const  FT_Driver_Class )  t1_driver_class;
-
-#ifdef __cplusplus
-  }
-#endif
-
-
-#endif /* Z1DRIVER_H */
-
-
-/* END */
--- a/src/type1z/z1gload.c
+++ /dev/null
@@ -1,309 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  z1gload.c                                                              */
-/*                                                                         */
-/*    Experimental Type 1 Glyph Loader (body).                             */
-/*                                                                         */
-/*  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.                                        */
-/*                                                                         */
-/***************************************************************************/
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1gload.h"
-
-#else
-
-#include <type1z/z1gload.h>
-
-#endif
-
-
-#include <freetype/internal/ftdebug.h>
-#include <freetype/internal/ftstream.h>
-#include <freetype/ftoutln.h>
-#include <freetype/internal/psaux.h>
-
-
-#include <string.h>     /* for strcmp() */
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
-  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
-  /* messages during execution.                                            */
-  /*                                                                       */
-#undef  FT_COMPONENT
-#define FT_COMPONENT  trace_z1gload
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-  /**********                                                      *********/
-  /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
-  /**********                                                      *********/
-  /**********    The following code is in charge of computing      *********/
-  /**********    the maximum advance width of the font.  It        *********/
-  /**********    quickly processes each glyph charstring to        *********/
-  /**********    extract the value from either a `sbw' or `seac'   *********/
-  /**********    operator.                                         *********/
-  /**********                                                      *********/
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-
-
-  LOCAL_FUNC_X
-  FT_Error  Z1_Parse_Glyph( T1_Decoder*  decoder,
-                            FT_UInt      glyph_index )
-  {
-    T1_Face   face  = (T1_Face)decoder->builder.face;
-    T1_Font*  type1 = &face->type1;
-
-
-    decoder->font_matrix = type1->font_matrix;
-    decoder->font_offset = type1->font_offset;
-
-    return decoder->funcs.parse_charstrings(
-                      decoder,
-                      type1->charstrings    [glyph_index],
-                      type1->charstrings_len[glyph_index] );
-  }
-
-
-  LOCAL_FUNC
-  FT_Error  Z1_Compute_Max_Advance( T1_Face  face,
-                                    FT_Int*  max_advance )
-  {
-    FT_Error          error;
-    T1_Decoder        decoder;
-    FT_Int            glyph_index;
-    T1_Font*          type1 = &face->type1;
-    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
-
-
-    *max_advance = 0;
-
-    /* initialize load decoder */
-    error = psaux->t1_decoder_funcs->init( &decoder,
-                                           (FT_Face)face,
-                                           0, /* size       */
-                                           0, /* glyph slot */
-                                           (FT_Byte**)type1->glyph_names,
-                                           face->blend,
-                                           Z1_Parse_Glyph );
-    if ( error )
-      return error;
-      
-    decoder.builder.metrics_only = 1;
-    decoder.builder.load_points  = 0;
-
-    decoder.num_subrs = type1->num_subrs;
-    decoder.subrs     = type1->subrs;
-    decoder.subrs_len = type1->subrs_len;
-
-    /* for each glyph, parse the glyph charstring and extract */
-    /* the advance width                                      */
-    for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
-    {
-      /* now get load the unscaled outline */
-      error = Z1_Parse_Glyph( &decoder, glyph_index );
-      /* ignore the error if one occured - skip to next glyph */
-    }
-
-    *max_advance = decoder.builder.advance.x;
-    return FT_Err_Ok;
-  }
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-  /**********                                                      *********/
-  /**********               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.       *********/
-  /**********                                                      *********/
-  /**********      The Type 1 hinter is located in `t1hint.c'      *********/
-  /**********                                                      *********/
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-
-
-  LOCAL_FUNC
-  FT_Error  Z1_Load_Glyph( Z1_GlyphSlot  glyph,
-                           Z1_Size       size,
-                           FT_Int        glyph_index,
-                           FT_Int        load_flags )
-  {
-    FT_Error                error;
-    T1_Decoder              decoder;
-    T1_Face                 face = (T1_Face)glyph->root.face;
-    FT_Bool                 hinting;
-    T1_Font*                type1         = &face->type1;
-    PSAux_Interface*        psaux         = (PSAux_Interface*)face->psaux;
-    const T1_Decoder_Funcs* decoder_funcs = psaux->t1_decoder_funcs;
-
-    FT_Matrix               font_matrix;
-    FT_Vector               font_offset;
-
-    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_outline;
-
-    error = decoder_funcs->init( &decoder,
-                                 (FT_Face)face,
-                                 (FT_Size)size,
-                                 (FT_GlyphSlot)glyph,
-                                 (FT_Byte**)type1->glyph_names,
-                                 face->blend,
-                                 Z1_Parse_Glyph );
-    if ( error )
-      goto Exit;
-                      
-    decoder.builder.no_recurse = ( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
-
-    decoder.num_subrs = type1->num_subrs;
-    decoder.subrs     = type1->subrs;
-    decoder.subrs_len = type1->subrs_len;
-   
-
-    /* now load the unscaled outline */
-    error = Z1_Parse_Glyph( &decoder, glyph_index );
-    if ( error )
-      goto Exit;
-
-    font_matrix = decoder.font_matrix;
-    font_offset = decoder.font_offset;
-
-    /* save new glyph tables */
-    decoder_funcs->done( &decoder );
-
-    /* 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 )
-    {
-      glyph->root.outline.flags &= ft_outline_owner;
-      glyph->root.outline.flags |= ft_outline_reverse_fill;
-      
-      /* for composite glyphs, return only left side bearing and */
-      /* 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;
-        glyph->root.linearHoriAdvance = decoder.builder.advance.x;
-
-        /* make up vertical metrics */
-        metrics->vertBearingX = 0;
-        metrics->vertBearingY = 0;
-        metrics->vertAdvance  = 0;
-
-        glyph->root.linearVertAdvance = 0;
-
-        glyph->root.format = ft_glyph_format_outline;
-
-        if ( size && size->root.metrics.y_ppem < 24 )
-          glyph->root.outline.flags |= ft_outline_high_precision;
-
-        /* apply the font matrix */
-        FT_Outline_Transform( &glyph->root.outline, &font_matrix );
-
-        FT_Outline_Translate( &glyph->root.outline,
-                              font_offset.x,
-                              font_offset.y );
-
-#if 0
-
-        glyph->root.outline.second_pass    = TRUE;
-        glyph->root.outline.high_precision = size->root.metrics.y_ppem < 24;
-        glyph->root.outline.dropout_mode   = 2;
-
-#endif /* 0 */
-
-        if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
-        {
-          /* scale the outline and the metrics */
-          FT_Int       n;
-          FT_Outline*  cur = decoder.builder.base;
-          FT_Vector*   vec = cur->points;
-          FT_Fixed     x_scale = glyph->x_scale;
-          FT_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->vertAdvance  = FT_MulFix( metrics->vertAdvance,  y_scale );
-
-          metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
-          metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
-        }
-
-        /* 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;
-      }
-    }
-
-  Exit:
-    return error;
-  }
-
-
-/* END */
--- a/src/type1z/z1gload.h
+++ /dev/null
@@ -1,58 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  z1gload.h                                                              */
-/*                                                                         */
-/*    Experimental Type 1 Glyph Loader (specification).                    */
-/*                                                                         */
-/*  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 Z1GLOAD_H
-#define Z1GLOAD_H
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1objs.h"
-
-#else
-
-#include <type1z/z1objs.h>
-
-#endif
-
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-
-  LOCAL_DEF
-  FT_Error  Z1_Compute_Max_Advance( T1_Face  face,
-                                    FT_Int*  max_advance );
-
-  LOCAL_DEF
-  FT_Error  Z1_Load_Glyph( Z1_GlyphSlot  glyph,
-                           Z1_Size       size,
-                           FT_Int        glyph_index,
-                           FT_Int        load_flags );
-
-
-#ifdef __cplusplus
-  }
-#endif
-
-
-#endif /* Z1GLOAD_H */
-
-
-/* END */
--- a/src/type1z/z1load.c
+++ /dev/null
@@ -1,1702 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  z1load.c                                                               */
-/*                                                                         */
-/*    Experimental Type 1 font loader (body).                              */
-/*                                                                         */
-/*  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 by 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; 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 PARSE_XXX.                                               */
-  /*                                                                       */
-  /* This file is included twice here; the first time to generate parsing  */
-  /* callback functions, the second to generate a table of keywords (with  */
-  /* pointers to the associated callback).                                 */
-  /*                                                                       */
-  /* The function `parse_dict' simply scans *linearly* a given dictionary  */
-  /* (either the top-level or private one) and calls the appropriate       */
-  /* callback when it encounters an immediate keyword.                     */
-  /*                                                                       */
-  /* 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 <freetype/internal/t1errors.h>
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1load.h"
-
-#else
-
-#include <type1z/z1load.h>
-
-#endif
-
-
-#include <string.h>     /* for strncmp(), strcmp() */
-#include <ctype.h>      /* for isalnum()           */
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
-  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
-  /* messages during execution.                                            */
-  /*                                                                       */
-#undef  FT_COMPONENT
-#define FT_COMPONENT  trace_z1load
-
-
-#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****                    MULTIPLE MASTERS SUPPORT                   *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-  static
-  FT_Error  t1_allocate_blend( T1_Face  face,
-                               FT_UInt  num_designs,
-                               FT_UInt  num_axis )
-  {
-    T1_Blend*  blend;
-    FT_Memory  memory = face->root.memory;
-    FT_Error   error  = 0;
-
-
-    blend = face->blend;
-    if ( !blend )
-    {
-      if ( ALLOC( blend, sizeof ( *blend ) ) )
-        goto Exit;
-
-      face->blend = blend;
-    }
-
-    /* allocate design data if needed */
-    if ( num_designs > 0 )
-    {
-      if ( blend->num_designs == 0 )
-      {
-        FT_UInt  nn;
-        
-
-        /* allocate the blend `private' and `font_info' dictionaries */
-        if ( ALLOC_ARRAY( blend->font_infos[1], num_designs, T1_FontInfo )  ||
-             ALLOC_ARRAY( blend->privates[1], num_designs, T1_Private )     ||
-             ALLOC_ARRAY( blend->weight_vector, num_designs * 2, FT_Fixed ) )
-          goto Exit;
-
-        blend->default_weight_vector = blend->weight_vector + num_designs;
-
-        blend->font_infos[0] = &face->type1.font_info;
-        blend->privates  [0] = &face->type1.private_dict;
-        
-        for ( nn = 2; nn <= num_designs; nn++ )
-        {
-          blend->privates[nn]   = blend->privates  [nn - 1] + 1;
-          blend->font_infos[nn] = blend->font_infos[nn - 1] + 1;
-        }
-        
-        blend->num_designs   = num_designs;
-      }
-      else if ( blend->num_designs != num_designs )
-        goto Fail;
-    }
-
-    /* allocate axis data if needed */
-    if ( num_axis > 0 )
-    {
-      if ( blend->num_axis != 0 && blend->num_axis != num_axis )
-        goto Fail;
-
-      blend->num_axis = num_axis;
-    }
-
-    /* allocate the blend design pos table if needed */
-    num_designs = blend->num_designs;
-    num_axis    = blend->num_axis;
-    if ( num_designs && num_axis && blend->design_pos[0] == 0 )
-    {
-      FT_UInt  n;
-
-
-      if ( ALLOC_ARRAY( blend->design_pos[0],
-                        num_designs * num_axis, FT_Fixed ) )
-        goto Exit;
-
-      for ( n = 1; n < num_designs; n++ )
-        blend->design_pos[n] = blend->design_pos[0] + num_axis * n;
-    }
-
-  Exit:
-    return error;
-
-  Fail:
-    error = -1;
-    goto Exit;
-  }
-
-
-  LOCAL_FUNC
-  FT_Error  Z1_Get_Multi_Master( T1_Face           face,
-                                 FT_Multi_Master*  master )
-  {
-    T1_Blend*  blend = face->blend;
-    FT_UInt    n;
-    FT_Error   error;
-
-
-    error = T1_Err_Invalid_Argument;
-
-    if ( blend )
-    {
-      master->num_axis    = blend->num_axis;
-      master->num_designs = blend->num_designs;
-
-      for ( n = 0; n < blend->num_axis; n++ )
-      {
-        FT_MM_Axis*    axis = master->axis + n;
-        T1_DesignMap*  map = blend->design_map + n;
-
-
-        axis->name    = blend->axis_names[n];
-        axis->minimum = map->design_points[0];
-        axis->maximum = map->design_points[map->num_points - 1];
-      }
-      error = 0;
-    }
-    return error;
-  }
-
-
-  LOCAL_FUNC
-  FT_Error  Z1_Set_MM_Blend( T1_Face    face,
-                             FT_UInt    num_coords,
-                             FT_Fixed*  coords )
-  {
-    T1_Blend*  blend = face->blend;
-    FT_Error   error;
-    FT_UInt    n, m;
-
-
-    error = T1_Err_Invalid_Argument;
-
-    if ( blend && blend->num_axis == num_coords )
-    {
-      /* recompute the weight vector from the blend coordinates */
-      error = FT_Err_Ok;
-
-      for ( n = 0; n < blend->num_designs; n++ )
-      {
-        FT_Fixed  result = 0x10000L;  /* 1.0 fixed */
-
-
-        for ( m = 0; m < blend->num_axis; m++ )
-        {
-          FT_Fixed  factor;
-
-
-          /* get current blend axis position */
-          factor = coords[m];
-          if ( factor < 0 )        factor = 0;
-          if ( factor > 0x10000L ) factor = 0x10000L;
-
-          if ( ( n & ( 1 << m ) ) == 0 )
-            factor = 0x10000L - factor;
-
-          result = FT_MulFix( result, factor );
-        }
-        blend->weight_vector[n] = result;
-      }
-
-      error = FT_Err_Ok;
-    }
-    return error;
-  }
-
-
-  LOCAL_FUNC
-  FT_Error  Z1_Set_MM_Design( T1_Face   face,
-                              FT_UInt   num_coords,
-                              FT_Long*  coords )
-  {
-    T1_Blend*  blend = face->blend;
-    FT_Error   error;
-    FT_UInt    n, p;
-
-
-    error = T1_Err_Invalid_Argument;
-    if ( blend && blend->num_axis == num_coords )
-    {
-      /* compute the blend coordinates through the blend design map */
-      FT_Fixed  final_blends[T1_MAX_MM_DESIGNS];
-
-
-      for ( n = 0; n < blend->num_axis; n++ )
-      {
-        FT_Long        design  = coords[n];
-        FT_Fixed       the_blend;
-        T1_DesignMap*  map     = blend->design_map + n;
-        FT_Fixed*      designs = map->design_points;
-        FT_Fixed*      blends  = map->blend_points;
-        FT_Int         before  = -1, after = -1;
-
-        for ( p = 0; p < map->num_points; p++ )
-        {
-          FT_Fixed  p_design = designs[p];
-
-
-          /* exact match ? */
-          if ( design == p_design )
-          {
-            the_blend = blends[p];
-            goto Found;
-          }
-
-          if ( design < p_design )
-          {
-            after = p;
-            break;
-          }
-
-          before = p;
-        }
-
-        /* now, interpolate if needed */
-        if ( before < 0 )
-          the_blend = blends[0];
-
-        else if ( after < 0 )
-          the_blend = blends[map->num_points - 1];
-
-        else
-          the_blend = FT_MulDiv( design         - designs[before],
-                                 blends [after] - blends [before],
-                                 designs[after] - designs[before] );
-
-      Found:
-        final_blends[n] = the_blend;
-      }
-
-      error = Z1_Set_MM_Blend( face, num_coords, final_blends );
-    }
-
-    return error;
-  }
-
-
-  LOCAL_FUNC
-  void  Z1_Done_Blend( T1_Face  face )
-  {
-    FT_Memory  memory = face->root.memory;
-    T1_Blend*  blend  = face->blend;
-
-
-    if ( blend )
-    {
-      FT_UInt  num_designs = blend->num_designs;
-      FT_UInt  num_axis    = blend->num_axis;
-      FT_UInt  n;
-
-
-      /* release design pos table */
-      FREE( blend->design_pos[0] );
-      for ( n = 1; n < num_designs; n++ )
-        blend->design_pos[n] = 0;
-
-      /* release blend `private' and `font info' dictionaries */
-      FREE( blend->privates[1] );
-      FREE( blend->font_infos[1] );
-
-      for ( n = 0; n < num_designs; n++ )
-      {
-        blend->privates  [n] = 0;
-        blend->font_infos[n] = 0;
-      }
-
-      /* release weight vectors */
-      FREE( blend->weight_vector );
-      blend->default_weight_vector = 0;
-
-      /* release axis names */
-      for ( n = 0; n < num_axis; n++ )
-        FREE( blend->axis_names[n] );
-
-      /* release design map */
-      for ( n = 0; n < num_axis; n++ )
-      {
-        T1_DesignMap*  dmap = blend->design_map + n;
-
-
-        FREE( dmap->design_points );
-        dmap->num_points = 0;
-      }
-
-      FREE( face->blend );
-    }
-  }
-
-
-  static
-  void  parse_blend_axis_types( T1_Face     face,
-                                Z1_Loader*  loader )
-  {
-    T1_Token   axis_tokens[ T1_MAX_MM_AXIS ];
-    FT_Int     n, num_axis;
-    FT_Error   error = 0;
-    T1_Blend*  blend;
-    FT_Memory  memory;
-
-
-    /* take an array of objects */
-    Z1_ToTokenArray( &loader->parser, axis_tokens,
-                     T1_MAX_MM_AXIS, &num_axis );
-    if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
-    {
-      FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n",
-                 num_axis ));
-      error = T1_Err_Invalid_File_Format;
-      goto Exit;
-    }
-
-    /* allocate blend if necessary */
-    error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
-    if ( error )
-      goto Exit;
-
-    blend  = face->blend;
-    memory = face->root.memory;
-
-    /* each token is an immediate containing the name of the axis */
-    for ( n = 0; n < num_axis; n++ )
-    {
-      T1_Token*  token = axis_tokens + n;
-      FT_Byte*   name;
-      FT_Int     len;
-
-      /* skip first slash, if any */
-      if (token->start[0] == '/')
-        token->start++;
-
-      len = token->limit - token->start;
-      if ( len <= 0 )
-      {
-        error = T1_Err_Invalid_File_Format;
-        goto Exit;
-      }
-
-      if ( ALLOC( blend->axis_names[n], len + 1 ) )
-        goto Exit;
-
-      name = (FT_Byte*)blend->axis_names[n];
-      MEM_Copy( name, token->start, len );
-      name[len] = 0;
-    }
-
-  Exit:
-    loader->parser.root.error = error;
-  }
-
-
-  static
-  void  parse_blend_design_positions( T1_Face     face,
-                                      Z1_Loader*  loader )
-  {
-    T1_Token    design_tokens[ T1_MAX_MM_DESIGNS ];
-    FT_Int      num_designs;
-    FT_Int      num_axis;
-    Z1_Parser*  parser = &loader->parser;
-
-    FT_Error    error = 0;
-    T1_Blend*   blend;
-
-
-    /* get the array of design tokens - compute number of designs */
-    Z1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs );
-    if ( num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS )
-    {
-      FT_ERROR(( "parse_blend_design_positions:" ));
-      FT_ERROR(( " incorrect number of designs: %d\n",
-                 num_designs ));
-      error = T1_Err_Invalid_File_Format;
-      goto Exit;
-    }
-
-    {
-      FT_Byte*  old_cursor = parser->root.cursor;
-      FT_Byte*  old_limit  = parser->root.limit;
-      FT_UInt   n;
-
-
-      blend    = face->blend;
-      num_axis = 0;  /* make compiler happy */
-
-      for ( n = 0; n < (FT_UInt)num_designs; n++ )
-      {
-        T1_Token   axis_tokens[ T1_MAX_MM_DESIGNS ];
-        T1_Token*  token;
-        FT_Int     axis, n_axis;
-
-
-        /* read axis/coordinates tokens */
-        token = design_tokens + n;
-        parser->root.cursor = token->start - 1;
-        parser->root.limit  = token->limit + 1;
-        Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
-
-        if ( n == 0 )
-        {
-          num_axis = n_axis;
-          error = t1_allocate_blend( face, num_designs, num_axis );
-          if ( error )
-            goto Exit;
-          blend = face->blend;
-        }
-        else if ( n_axis != num_axis )
-        {
-          FT_ERROR(( "parse_blend_design_positions: incorrect table\n" ));
-          error = T1_Err_Invalid_File_Format;
-          goto Exit;
-        }
-
-        /* now, read each axis token into the design position */
-        for ( axis = 0; axis < n_axis; axis++ )
-        {
-          T1_Token*  token2 = axis_tokens + axis;
-
-
-          parser->root.cursor = token2->start;
-          parser->root.limit  = token2->limit;
-          blend->design_pos[n][axis] = Z1_ToFixed( parser, 0 );
-        }
-      }
-
-      loader->parser.root.cursor = old_cursor;
-      loader->parser.root.limit  = old_limit;
-    }
-
-  Exit:
-    loader->parser.root.error = error;
-  }
-
-
-  static
-  void  parse_blend_design_map( T1_Face     face,
-                                Z1_Loader*  loader )
-  {
-    FT_Error    error  = 0;
-    Z1_Parser*  parser = &loader->parser;
-    T1_Blend*   blend;
-    T1_Token    axis_tokens[ T1_MAX_MM_AXIS ];
-    FT_Int      n, num_axis;
-    FT_Byte*    old_cursor;
-    FT_Byte*    old_limit;
-    FT_Memory   memory = face->root.memory;
-
-
-    Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis );
-    if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
-    {
-      FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n",
-                 num_axis ));
-      error = T1_Err_Invalid_File_Format;
-      goto Exit;
-    }
-    old_cursor = parser->root.cursor;
-    old_limit  = parser->root.limit;
-
-    error = t1_allocate_blend( face, 0, num_axis );
-    if ( error )
-      goto Exit;
-    blend = face->blend;
-
-    /* now, read each axis design map */
-    for ( n = 0; n < num_axis; n++ )
-    {
-      T1_DesignMap* map = blend->design_map + n;
-      T1_Token*     token;
-      FT_Int        p, num_points;
-
-
-      token = axis_tokens + n;
-      parser->root.cursor = token->start;
-      parser->root.limit  = token->limit;
-
-      /* count the number of map points */
-      {
-        FT_Byte*  ptr   = token->start;
-        FT_Byte*  limit = token->limit;
-
-
-        num_points = 0;
-        for ( ; ptr < limit; ptr++ )
-          if ( ptr[0] == '[' )
-            num_points++;
-      }
-      if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
-      {
-        FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
-        error = T1_Err_Invalid_File_Format;
-        goto Exit;
-      }
-
-      /* allocate design map data */
-      if ( ALLOC_ARRAY( map->design_points, num_points * 2, FT_Fixed ) )
-        goto Exit;
-      map->blend_points = map->design_points + num_points;
-      map->num_points   = (FT_Byte)num_points;
-
-      for ( p = 0; p < num_points; p++ )
-      {
-        map->design_points[p] = Z1_ToInt( parser );
-        map->blend_points [p] = Z1_ToFixed( parser, 0 );
-      }
-    }
-
-    parser->root.cursor = old_cursor;
-    parser->root.limit  = old_limit;
-
-  Exit:
-    parser->root.error = error;
-  }
-
-
-  static
-  void  parse_weight_vector( T1_Face     face,
-                             Z1_Loader*  loader )
-  {
-    FT_Error    error  = 0;
-    Z1_Parser*  parser = &loader->parser;
-    T1_Blend*   blend  = face->blend;
-    T1_Token    master;
-    FT_UInt     n;
-    FT_Byte*    old_cursor;
-    FT_Byte*    old_limit;
-
-
-    if ( !blend || blend->num_designs == 0 )
-    {
-      FT_ERROR(( "parse_weight_vector: too early!\n" ));
-      error = T1_Err_Invalid_File_Format;
-      goto Exit;
-    }
-
-    Z1_ToToken( parser, &master );
-    if ( master.type != t1_token_array )
-    {
-      FT_ERROR(( "parse_weight_vector: incorrect format!\n" ));
-      error = T1_Err_Invalid_File_Format;
-      goto Exit;
-    }
-
-    old_cursor = parser->root.cursor;
-    old_limit  = parser->root.limit;
-
-    parser->root.cursor = master.start;
-    parser->root.limit  = master.limit;
-
-    for ( n = 0; n < blend->num_designs; n++ )
-    {
-      blend->default_weight_vector[n] =
-      blend->weight_vector[n]         = Z1_ToFixed( parser, 0 );
-    }
-
-    parser->root.cursor = old_cursor;
-    parser->root.limit  = old_limit;
-
-  Exit:
-    parser->root.error = error;
-  }
-
-
-  /* the keyword `/shareddict' appears in some multiple master fonts   */
-  /* with a lot of Postscript garbage behind it (that's completely out */
-  /* of spec!); we detect it and terminate the parsing                 */
-  /*                                                                   */
-  static
-  void  parse_shared_dict( T1_Face     face,
-                           Z1_Loader*  loader )
-  {
-    Z1_Parser*  parser = &loader->parser;
-
-    FT_UNUSED( face );
-
-
-    parser->root.cursor = parser->root.limit;
-    parser->root.error  = 0;
-  }
-
-#endif /* Z1_CONFIG_OPTION_NO_MM_SUPPORT */
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****                      TYPE 1 SYMBOL PARSING                    *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* First of all, define the token field static variables.  This is a set */
-  /* of T1_Field variables used later.                                     */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  static
-  FT_Error  t1_load_keyword( T1_Face     face,
-                             Z1_Loader*  loader,
-                             T1_Field*   field )
-  {
-    FT_Error   error;
-    void*      dummy_object;
-    void**     objects;
-    FT_UInt    max_objects;
-    T1_Blend*  blend = face->blend;
-
-
-    /* if the keyword has a dedicated callback, call it */
-    if ( field->type == t1_field_callback )
-    {
-      field->reader( (FT_Face)face, loader );
-      error = loader->parser.root.error;
-      goto Exit;
-    }
-
-    /* now, the keyword is either a simple field, or a table of fields; */
-    /* we are now going to take care of it                              */
-    switch ( field->location )
-    {
-    case t1_field_font_info:
-      dummy_object = &face->type1.font_info;
-      objects      = &dummy_object;
-      max_objects  = 0;
-
-      if ( blend )
-      {
-        objects     = (void**)blend->font_infos;
-        max_objects = blend->num_designs;
-      }
-      break;
-
-    case t1_field_private:
-      dummy_object = &face->type1.private_dict;
-      objects      = &dummy_object;
-      max_objects  = 0;
-
-      if ( blend )
-      {
-        objects     = (void**)blend->privates;
-        max_objects = blend->num_designs;
-      }
-      break;
-
-    default:
-      dummy_object = &face->type1;
-      objects      = &dummy_object;
-      max_objects  = 0;
-    }
-
-    if ( field->type == t1_field_integer_array ||
-         field->type == t1_field_fixed_array   )
-      error = Z1_Load_Field_Table( &loader->parser, field,
-                                   objects, max_objects, 0 );
-    else
-      error = Z1_Load_Field( &loader->parser, field,
-                             objects, max_objects, 0 );
-
-  Exit:
-    return error;
-  }
-
-
-  static
-  int  is_space( FT_Byte  c )
-  {
-    return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
-  }
-
-
-  static
-  int  is_alpha( FT_Byte  c )
-  {
-    return ( isalnum( c ) || c == '.' || c == '_' );
-  }
-
-
-
-  static
-  int  read_binary_data( Z1_Parser*  parser,
-                         FT_Int*     size,
-                         FT_Byte**   base )
-  {
-    FT_Byte*  cur;
-    FT_Byte*  limit = parser->root.limit;
-
-
-    /* the binary data has the following format */
-    /*                                          */
-    /* `size' [white*] RD white ....... ND      */
-    /*                                          */
-
-    Z1_Skip_Spaces( parser );
-    cur = parser->root.cursor;
-
-    if ( cur < limit && (FT_Byte)( *cur - '0' ) < 10 )
-    {
-      *size = Z1_ToInt( parser );
-
-      Z1_Skip_Spaces( parser );
-      Z1_Skip_Alpha ( parser );  /* `RD' or `-|' or something else */
-
-      /* there is only one whitespace char after the */
-      /* `RD' or `-|' token                          */
-      *base = parser->root.cursor + 1;
-
-      parser->root.cursor += *size + 1;
-      return 1;
-    }
-
-    FT_ERROR(( "read_binary_data: invalid size field\n" ));
-    parser->root.error = T1_Err_Invalid_File_Format;
-    return 0;
-  }
-
-
-  /* we will now define the routines used to handle */
-  /* the `/Encoding', `/Subrs', and `/CharStrings'  */
-  /* dictionaries                                   */
-
-  static
-  void  parse_font_name( T1_Face     face,
-                         Z1_Loader*  loader )
-  {
-    Z1_Parser*  parser = &loader->parser;
-    FT_Error    error;
-    FT_Memory   memory = parser->root.memory;
-    FT_Int      len;
-    FT_Byte*    cur;
-    FT_Byte*    cur2;
-    FT_Byte*    limit;
-
-
-    Z1_Skip_Spaces( parser );
-
-    cur   = parser->root.cursor;
-    limit = parser->root.limit;
-
-    if ( cur >= limit - 1 || *cur != '/' )
-      return;
-
-    cur++;
-    cur2 = cur;
-    while ( cur2 < limit && is_alpha( *cur2 ) )
-      cur2++;
-
-    len = cur2 - cur;
-    if ( len > 0 )
-    {
-      if ( ALLOC( face->type1.font_name, len + 1 ) )
-      {
-        parser->root.error = error;
-        return;
-      }
-
-      MEM_Copy( face->type1.font_name, cur, len );
-      face->type1.font_name[len] = '\0';
-    }
-    parser->root.cursor = cur2;
-  }
-
-
-  static
-  void  parse_font_bbox( T1_Face     face,
-                         Z1_Loader*  loader )
-  {
-    Z1_Parser*  parser = &loader->parser;
-    FT_Short    temp[4];
-    FT_BBox*    bbox   = &face->type1.font_bbox;
-
-
-    (void)Z1_ToCoordArray( parser, 4, temp );
-    bbox->xMin = temp[0];
-    bbox->yMin = temp[1];
-    bbox->xMax = temp[2];
-    bbox->yMax = temp[3];
-  }
-
-
-  static
-  void  parse_font_matrix( T1_Face     face,
-                           Z1_Loader*  loader )
-  {
-    Z1_Parser*  parser = &loader->parser;
-    FT_Matrix*  matrix = &face->type1.font_matrix;
-    FT_Vector*  offset = &face->type1.font_offset;
-    FT_Fixed    temp[6];
-
-
-    if ( matrix->xx || matrix->yx )
-      /*  with synthetic fonts, it's possible we get here twice  */
-      return;
-
-    (void)Z1_ToFixedArray( parser, 6, temp, 3 );
-
-    /* we need to scale the values by 1.0/temp[3] */
-    if ( temp[3] != 0x10000L )
-    {
-      temp[0] = FT_DivFix( temp[0], temp[3] );
-      temp[1] = FT_DivFix( temp[1], temp[3] );
-      temp[2] = FT_DivFix( temp[2], temp[3] );
-      temp[4] = FT_DivFix( temp[4], temp[3] );
-      temp[5] = FT_DivFix( temp[5], temp[3] );
-      temp[3] = 0x10000L;
-    }
-
-    matrix->xx = temp[0];
-    matrix->yx = temp[1];
-    matrix->xy = temp[2];
-    matrix->yy = temp[3];
-    
-    /* note that the offsets must be expressed in integer font units */
-    offset->x  = temp[4] >> 16;
-    offset->y  = temp[5] >> 16;
-  }
-
-
-  static
-  void  parse_encoding( T1_Face     face,
-                        Z1_Loader*  loader )
-  {
-    Z1_Parser*  parser = &loader->parser;
-    FT_Byte*    cur   = parser->root.cursor;
-    FT_Byte*    limit = parser->root.limit;
-    
-    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
-
-
-    /* skip whitespace */
-    while ( is_space( *cur ) )
-    {
-      cur++;
-      if ( cur >= limit )
-      {
-        FT_ERROR(( "parse_encoding: out of bounds!\n" ));
-        parser->root.error = T1_Err_Invalid_File_Format;
-        return;
-      }
-    }
-
-    /* if we have a number, then the encoding is an array, */
-    /* and we must load it now                             */
-    if ( (FT_Byte)( *cur - '0' ) < 10 )
-    {
-      T1_Encoding*  encode     = &face->type1.encoding;
-      FT_Int        count, n;
-      PS_Table*     char_table = &loader->encoding_table;
-      FT_Memory     memory     = parser->root.memory;
-      FT_Error      error;
-
-
-      /* read the number of entries in the encoding, should be 256 */
-      count = Z1_ToInt( parser );
-      if ( parser->root.error )
-        return;
-
-      /* we use a Z1_Table to store our charnames */
-      encode->num_chars = count;
-      if ( ALLOC_ARRAY( encode->char_index, count, FT_Short   ) ||
-           ALLOC_ARRAY( encode->char_name,  count, FT_String* ) ||
-           ( error = psaux->ps_table_funcs->init(
-                       char_table, count, memory ) ) != 0       )
-      {
-        parser->root.error = error;
-        return;
-      }
-
-      /* We need to `zero' out encoding_table.elements          */
-      for ( n = 0; n < count; n++ )
-      {
-        char*  notdef = ".notdef";       
-
-
-        Z1_Add_Table( char_table, n, notdef, 8 );
-      }
-
-      /* Now, we will need to read a record of the form         */
-      /* ... charcode /charname ... for each entry in our table */
-      /*                                                        */
-      /* We simply look for a number followed by an immediate   */
-      /* name.  Note that this ignores correctly the sequence   */
-      /* that is often seen in type1 fonts:                     */
-      /*                                                        */
-      /*   0 1 255 { 1 index exch /.notdef put } for dup        */
-      /*                                                        */
-      /* used to clean the encoding array before anything else. */
-      /*                                                        */
-      /* We stop when we encounter a `def'.                     */
-
-      cur   = parser->root.cursor;
-      limit = parser->root.limit;
-      n     = 0;
-
-      for ( ; cur < limit; )
-      {
-        FT_Byte  c;
-
-
-        c = *cur;
-
-        /* we stop when we encounter a `def' */
-        if ( c == 'd' && cur + 3 < limit )
-        {
-          if ( cur[1] == 'e' &&
-               cur[2] == 'f' &&
-               is_space(cur[-1]) &&
-               is_space(cur[3]) )
-          {
-            FT_TRACE6(( "encoding end\n" ));
-            break;
-          }
-        }
-
-        /* otherwise, we must find a number before anything else */
-        if ( (FT_Byte)( c - '0' ) < 10 )
-        {
-          FT_Int  charcode;
-
-
-          parser->root.cursor = cur;
-          charcode = Z1_ToInt( parser );
-          cur = parser->root.cursor;
-
-          /* skip whitespace */
-          while ( cur < limit && is_space( *cur ) )
-            cur++;
-
-          if ( cur < limit && *cur == '/' )
-          {
-            /* bingo, we have an immediate name -- it must be a */
-            /* character name                                   */
-            FT_Byte*  cur2 = cur + 1;
-            FT_Int    len;
-
-
-            while ( cur2 < limit && is_alpha( *cur2 ) )
-              cur2++;
-
-            len = cur2 - cur - 1;
-
-            parser->root.error = Z1_Add_Table( char_table, charcode,
-                                          cur + 1, len + 1 );
-            char_table->elements[charcode][len] = '\0';
-            if ( parser->root.error )
-              return;
-
-            cur = cur2;
-          }
-        }
-        else
-          cur++;
-      }
-
-      face->type1.encoding_type = t1_encoding_array;
-      parser->root.cursor       = cur;
-    }
-    /* Otherwise, we should have either `StandardEncoding' or */
-    /* `ExpertEncoding'                                       */
-    else
-    {
-      if ( cur + 17 < limit &&
-           strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
-        face->type1.encoding_type = t1_encoding_standard;
-
-      else if ( cur + 15 < limit &&
-                strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
-        face->type1.encoding_type = t1_encoding_expert;
-
-      else
-      {
-        FT_ERROR(( "parse_encoding: invalid token!\n" ));
-        parser->root.error = T1_Err_Invalid_File_Format;
-      }
-    }
-  }
-
-
-  static
-  void  parse_subrs( T1_Face     face,
-                     Z1_Loader*  loader )
-  {
-    Z1_Parser*  parser = &loader->parser;
-    PS_Table*   table  = &loader->subrs;
-    FT_Memory   memory = parser->root.memory;
-    FT_Error    error;
-    FT_Int      n;
-
-    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
-
-    
-    loader->num_subrs = Z1_ToInt( parser );
-    if ( parser->root.error )
-      return;
-
-    /* position the parser right before the `dup' of the first subr */
-    Z1_Skip_Spaces( parser );
-    Z1_Skip_Alpha( parser );      /* `array' */
-    Z1_Skip_Spaces( parser );
-
-    /* initialize subrs array */
-    error = psaux->ps_table_funcs->init( table, loader->num_subrs, memory );
-    if ( error )
-      goto Fail;
-
-    /* the format is simple:                                 */
-    /*                                                       */
-    /*   `index' + binary data                               */
-    /*                                                       */
-
-    for ( n = 0; n < loader->num_subrs; n++ )
-    {
-      FT_Int    index, size;
-      FT_Byte*  base;
-
-
-      /* If the next token isn't `dup', we are also done.  This */
-      /* happens when there are `holes' in the Subrs array.     */
-      if ( strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 )
-        break;
-
-      index = Z1_ToInt( parser );
-      
-      if ( !read_binary_data( parser, &size, &base ) )
-        return;
-
-      /* The binary string is followed by one token, e.g. `NP' */
-      /* (bound to `noaccess put') or by two separate tokens:  */
-      /* `noaccess' & `put'.  We position the parser right     */
-      /* before the next `dup', if any.                        */
-      Z1_Skip_Spaces( parser );
-      Z1_Skip_Alpha( parser );    /* `NP' or `I' or `noaccess' */
-      Z1_Skip_Spaces( parser );
-
-      if ( strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 )
-      {
-        Z1_Skip_Alpha( parser );  /* skip `put' */
-        Z1_Skip_Spaces( parser );
-      }
-
-      /* some fonts use a value of -1 for lenIV to indicate that */
-      /* the charstrings are unencoded                           */
-      /*                                                         */
-      /* thanks to Tom Kacvinsky for pointing this out           */
-      /*                                                         */
-      if ( face->type1.private_dict.lenIV >= 0 )
-      {
-        Z1_Decrypt( base, size, 4330 );
-        size -= face->type1.private_dict.lenIV;
-        base += face->type1.private_dict.lenIV;
-      }
-
-      error = Z1_Add_Table( table, index, base, size );
-      if ( error )
-        goto Fail;
-    }
-    return;
-
-  Fail:
-    parser->root.error = error;
-  }
-
-
-  static
-  void  parse_charstrings( T1_Face     face,
-                           Z1_Loader*  loader )
-  {
-    Z1_Parser*  parser     = &loader->parser;
-    PS_Table*   code_table = &loader->charstrings;
-    PS_Table*   name_table = &loader->glyph_names;
-    FT_Memory   memory     = parser->root.memory;
-    FT_Error    error;
-
-    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
-
-    FT_Byte*    cur;
-    FT_Byte*    limit = parser->root.limit;
-    FT_Int      n;
-    FT_UInt     notdef_index = 0;
-    FT_Byte     notdef_found = 0;
-
-
-    if ( loader->num_glyphs )
-      /*  with synthetic fonts, it's possible we get here twice  */
-      return;
-
-    loader->num_glyphs = Z1_ToInt( parser );
-    if ( parser->root.error )
-      return;
-
-    /* initialize tables, adding space for `swap' at table end   */
-    error = psaux->ps_table_funcs->init( code_table,
-                                         loader->num_glyphs + 1,
-                                         memory );
-    if ( error )
-      goto Fail;
-
-    error = psaux->ps_table_funcs->init( name_table,
-                                         loader->num_glyphs + 1,
-                                         memory );
-    if ( error )
-      goto Fail;
-
-    n = 0;
-    for (;;)
-    {
-      FT_Int    size;
-      FT_Byte*  base;
-
-
-      /* the format is simple:                    */
-      /*   `/glyphname' + binary data             */
-      /*                                          */
-      /* note that we stop when we find a `def'   */
-      /*                                          */
-      Z1_Skip_Spaces( parser );
-
-      cur = parser->root.cursor;
-      if ( cur >= limit )
-        break;
-
-      /* we stop when we find a `def' or `end' keyword */
-      if ( *cur   == 'd'   &&
-           cur + 3 < limit &&
-           cur[1] == 'e'   &&
-           cur[2] == 'f'   )
-        break;
-
-      if ( *cur   == 'e'   &&
-           cur + 3 < limit &&
-           cur[1] == 'n'   &&
-           cur[2] == 'd'   )
-        break;
-
-      if ( *cur != '/' )
-        Z1_Skip_Alpha( parser );
-      else
-      {
-        FT_Byte*  cur2 = cur + 1;
-        FT_Int    len;
-
-
-        while ( cur2 < limit && is_alpha( *cur2 ) )
-          cur2++;
-        len = cur2 - cur - 1;
-
-        error = Z1_Add_Table( name_table, n, cur + 1, len + 1 );
-        if ( error )
-          goto Fail;
-
-        /* add a trailing zero to the name table */
-        name_table->elements[n][len] = '\0';
-
-        /* record index of /.notdef              */
-        if ( strcmp( (const char*)".notdef",
-                     (const char*)(name_table->elements[n]) ) == 0 )
-        {
-          notdef_index = n;
-          notdef_found = 1;
-        }
-
-        parser->root.cursor = cur2;
-        if ( !read_binary_data( parser, &size, &base ) )
-          return;
-
-        if ( face->type1.private_dict.lenIV >= 0 )
-        {
-          Z1_Decrypt( base, size, 4330 );
-          size -= face->type1.private_dict.lenIV;
-          base += face->type1.private_dict.lenIV;
-        }
-
-        error = Z1_Add_Table( code_table, n, base, size );
-        if ( error )
-          goto Fail;
-
-        n++;
-        if ( n >= loader->num_glyphs )
-          break;
-      }
-    }
-
-    loader->num_glyphs = n;
-
-    /* if /.notdef is found but does not occupy index 0, do our magic.      */
-    if ( strcmp( (const char*)".notdef",
-                 (const char*)name_table->elements[0] ) &&
-         notdef_found                                      )
-    {
-
-      /* Swap glyph in index 0 with /.notdef glyph.  First, add index 0     */
-      /* name/code to end of table. Then place notdef_index name/code into  */
-      /* index 0.  Then take end of table name/code and place it into index */
-      /* notdef_index.                                                      */
-
-      error = Z1_Add_Table( name_table, n, 
-                            name_table->elements[0],
-                            name_table->lengths [0] );
-      if ( error )
-        goto Fail;
-      error = Z1_Add_Table( code_table, n,
-                            code_table->elements[0],
-                            code_table->lengths [0] );
-      if ( error )
-        goto Fail;
-
-      error = Z1_Add_Table( name_table, 0,
-                            name_table->elements[notdef_index],
-                            name_table->lengths [notdef_index] );
-      if ( error )
-        goto Fail;
-
-      error = Z1_Add_Table( code_table, 0,
-                            code_table->elements[notdef_index],
-                            code_table->lengths [notdef_index] );
-      if ( error )
-        goto Fail;
-
-      error = Z1_Add_Table( name_table, notdef_index,
-                            name_table->elements[n],
-                            name_table->lengths [n] );
-      if ( error )
-        goto Fail;
-
-      error = Z1_Add_Table( code_table, notdef_index,
-                            code_table->elements[n],
-                            code_table->lengths [n] );
-      if ( error )
-        goto Fail;
-
-    }
-    else if ( !notdef_found )
-    {
-
-      /* notdef_index is already 0, or /.notdef is undefined in  */
-      /* charstrings dictionary. Worry about /.notdef undefined. */
-      /* we take index 0 and add it to the end of the table(s)   */
-      /* and add our own /.notdef glyph to index 0.              */
-      
-      /* 0 333 hsbw endchar                                      */
-      FT_Byte  notdef_glyph[] = {0x8B, 0xF7, 0xE1, 0x0D, 0x0E};
-      char*    notdef_name    = ".notdef";
-
-
-      error = Z1_Add_Table( name_table, n,
-                            name_table->elements[0],
-                            name_table->lengths [0] );
-      if ( error )
-        goto Fail;
-
-      error = Z1_Add_Table( code_table, n,
-                            code_table->elements[0],
-                            code_table->lengths [0] );
-      if ( error )
-        goto Fail;
-
-      error = Z1_Add_Table( name_table, 0, notdef_name, 8 );
-      if ( error )
-        goto Fail;
-
-      error = Z1_Add_Table( code_table, 0, notdef_glyph, 5 );
-
-      if ( error )
-        goto Fail;
-
-      /* we added a glyph. */
-      loader->num_glyphs = n + 1;
-
-    }
-
-    return;
-
-  Fail:
-    parser->root.error = error;
-  }
-
-
-  static
-  const T1_Field  t1_keywords[] =
-  {
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1tokens.h"
-
-#else
-
-#include <type1z/z1tokens.h>
-
-#endif
-
-    /* now add the special functions... */
-    T1_FIELD_CALLBACK( "FontName", parse_font_name )
-    T1_FIELD_CALLBACK( "FontBBox", parse_font_bbox )
-    T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix )
-    T1_FIELD_CALLBACK( "Encoding", parse_encoding )
-    T1_FIELD_CALLBACK( "Subrs", parse_subrs )
-    T1_FIELD_CALLBACK( "CharStrings", parse_charstrings )
-
-#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
-    T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions )
-    T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map )
-    T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types )
-    T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector )
-    T1_FIELD_CALLBACK( "shareddict", parse_shared_dict )
-#endif
-
-    { 0, t1_field_cid_info, t1_field_none, 0, 0, 0, 0, 0 }
-  };
-
-
-  static
-  FT_Error  parse_dict( T1_Face     face,
-                        Z1_Loader*  loader,
-                        FT_Byte*    base,
-                        FT_Long     size )
-  {
-    Z1_Parser*  parser = &loader->parser;
-
-
-    parser->root.cursor = base;
-    parser->root.limit  = base + size;
-    parser->root.error  = 0;
-
-    {
-      FT_Byte*  cur   = base;
-      FT_Byte*  limit = cur + size;
-
-
-      for ( ; cur < limit; cur++ )
-      {
-        /* look for `FontDirectory', which causes problems on some fonts */
-        if ( *cur == 'F' && cur + 25 < limit                 &&
-             strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
-        {
-          FT_Byte*  cur2;
-
-
-          /* skip the `FontDirectory' keyword */
-          cur += 13;
-          cur2 = cur;
-
-          /* lookup the `known' keyword */
-          while ( cur < limit && *cur != 'k'        &&
-                  strncmp( (char*)cur, "known", 5 ) )
-            cur++;
-
-          if ( cur < limit )
-          {
-            T1_Token  token;
-
-
-            /* skip the `known' keyword and the token following it */
-            cur += 5;
-            loader->parser.root.cursor = cur;
-            Z1_ToToken( &loader->parser, &token );
-
-            /* if the last token was an array, skip it! */
-            if ( token.type == t1_token_array )
-              cur2 = parser->root.cursor;
-          }
-          cur = cur2;
-        }
-        /* 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 )
-          {
-            if ( !loader->fontdata )
-            {
-              if ( strncmp( (char*)cur, "FontInfo", 8 ) == 0 )
-                loader->fontdata = 1;
-            }
-            else
-            {
-              /* now, compare the immediate name to the keyword table */
-              T1_Field*  keyword = (T1_Field*)t1_keywords;
-
-
-              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->root.cursor = cur2;
-                    Z1_Skip_Spaces( parser );
-                    parser->root.error = t1_load_keyword( face,
-                                                          loader,
-                                                          keyword );
-                    if ( parser->root.error )
-                      return parser->root.error;
-
-                    cur = parser->root.cursor;
-                    break;
-                  }
-                }
-                keyword++;
-              }
-            }
-          }
-        }
-      }
-    }
-    return parser->root.error;
-  }
-
-
-  static
-  void  t1_init_loader( Z1_Loader*  loader,
-                        T1_Face     face )
-  {
-    FT_UNUSED( face );
-
-    MEM_Set( loader, 0, sizeof ( *loader ) );
-    loader->num_glyphs = 0;
-    loader->num_chars  = 0;
-
-    /* initialize the tables -- simply set their `init' field to 0 */
-    loader->encoding_table.init = 0;
-    loader->charstrings.init    = 0;
-    loader->glyph_names.init    = 0;
-    loader->subrs.init          = 0;
-    loader->fontdata            = 0;
-  }
-
-
-  static
-  void  t1_done_loader( Z1_Loader*  loader )
-  {
-    Z1_Parser*  parser = &loader->parser;
-
-
-    /* finalize tables */
-    Z1_Release_Table( &loader->encoding_table );
-    Z1_Release_Table( &loader->charstrings );
-    Z1_Release_Table( &loader->glyph_names );
-    Z1_Release_Table( &loader->subrs );
-
-    /* finalize parser */
-    Z1_Done_Parser( parser );
-  }
-
-
-  LOCAL_FUNC
-  FT_Error  Z1_Open_Face( T1_Face  face )
-  {
-    Z1_Loader   loader;
-    Z1_Parser*  parser;
-    T1_Font*    type1 = &face->type1;
-    FT_Error    error;
-    
-    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
-
-
-    t1_init_loader( &loader, face );
-
-    /* default lenIV */
-    type1->private_dict.lenIV = 4;
-
-    parser = &loader.parser;
-    error = Z1_New_Parser( parser,
-                           face->root.stream,
-                           face->root.memory,
-                           psaux );
-    if ( error )
-      goto Exit;
-
-    error = parse_dict( face, &loader, parser->base_dict, parser->base_len );
-    if ( error )
-      goto Exit;
-
-    error = Z1_Get_Private_Dict( parser );
-    if ( error )
-      goto Exit;
-
-    error = parse_dict( face, &loader, parser->private_dict,
-                        parser->private_len );
-    if ( error )
-      goto Exit;
-
-    /* now, propagate the subrs, charstrings, and glyphnames tables */
-    /* to the Type1 data                                            */
-    type1->num_glyphs = loader.num_glyphs;
-
-    if ( !loader.subrs.init )
-    {
-      FT_ERROR(( "Z1_Open_Face: no subrs array in face!\n" ));
-      error = T1_Err_Invalid_File_Format;
-    }
-
-    if ( !loader.charstrings.init )
-    {
-      FT_ERROR(( "Z1_Open_Face: no charstrings array in face!\n" ));
-      error = T1_Err_Invalid_File_Format;
-    }
-
-    loader.subrs.init  = 0;
-    type1->num_subrs   = loader.num_subrs;
-    type1->subrs_block = loader.subrs.block;
-    type1->subrs       = loader.subrs.elements;
-    type1->subrs_len   = loader.subrs.lengths;
-
-    loader.charstrings.init  = 0;
-    type1->charstrings_block = loader.charstrings.block;
-    type1->charstrings       = loader.charstrings.elements;
-    type1->charstrings_len   = loader.charstrings.lengths;
-
-    /* we copy the glyph names `block' and `elements' fields; */
-    /* the `lengths' field must be released later             */
-    type1->glyph_names_block    = loader.glyph_names.block;
-    type1->glyph_names          = (FT_String**)loader.glyph_names.elements;
-    loader.glyph_names.block    = 0;
-    loader.glyph_names.elements = 0;
-
-    /* we must now build type1.encoding when we have a custom */
-    /* array..                                                */
-    if ( type1->encoding_type == t1_encoding_array )
-    {
-      FT_Int    charcode, index, min_char, max_char;
-      FT_Byte*  char_name;
-      FT_Byte*  glyph_name;
-
-
-      /* OK, we do the following: for each element in the encoding  */
-      /* table, look up the index of the glyph having the same name */
-      /* the index is then stored in type1.encoding.char_index, and */
-      /* a the name to type1.encoding.char_name                     */
-
-      min_char = +32000;
-      max_char = -32000;
-
-      charcode = 0;
-      for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
-      {
-        type1->encoding.char_index[charcode] = 0;
-        type1->encoding.char_name [charcode] = (char *)".notdef";
-
-        char_name = loader.encoding_table.elements[charcode];
-        if ( char_name )
-          for ( index = 0; index < type1->num_glyphs; index++ )
-          {
-            glyph_name = (FT_Byte*)type1->glyph_names[index];
-            if ( strcmp( (const char*)char_name,
-                         (const char*)glyph_name ) == 0 )
-            {
-              type1->encoding.char_index[charcode] = index;
-              type1->encoding.char_name [charcode] = (char*)glyph_name;
-
-              /* Change min/max encoded char only if glyph name is */
-              /* not /.notdef                                      */
-              if ( strcmp( (const char*)".notdef",
-                           (const char*)glyph_name ) != 0 )
-              {
-                if (charcode < min_char) min_char = charcode;
-                if (charcode > max_char) max_char = charcode;
-              }
-              break;
-            }
-          }
-      }
-      type1->encoding.code_first = min_char;
-      type1->encoding.code_last  = max_char;
-      type1->encoding.num_chars  = loader.num_chars;
-   }
-
-  Exit:
-    t1_done_loader( &loader );
-    return error;
-  }
-
-
-/* END */
--- a/src/type1z/z1load.h
+++ /dev/null
@@ -1,93 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  z1load.h                                                               */
-/*                                                                         */
-/*    Experimental Type 1 font loader (specification).                     */
-/*                                                                         */
-/*  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 Z1LOAD_H
-#define Z1LOAD_H
-
-#include <freetype/internal/ftstream.h>
-#include <freetype/internal/psaux.h>
-#include <freetype/ftmm.h>
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1parse.h"
-
-#else
-
-#include <type1z/z1parse.h>
-
-#endif
-
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-  typedef struct  Z1_Loader_
-  {
-    Z1_Parser  parser;          /* parser used to read the stream */
-
-    FT_Int     num_chars;       /* number of characters in encoding */
-    PS_Table   encoding_table;  /* PS_Table used to store the       */
-                                /* encoding character names         */
-
-    FT_Int     num_glyphs;
-    PS_Table   glyph_names;
-    PS_Table   charstrings;
-
-    FT_Int     num_subrs;
-    PS_Table   subrs;
-    FT_Bool    fontdata;
-
-  } Z1_Loader;
-
-
-  LOCAL_DEF
-  FT_Error  Z1_Open_Face( T1_Face  face );
-
-#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
-
-  LOCAL_DEF
-  FT_Error  Z1_Get_Multi_Master( T1_Face           face,
-                                 FT_Multi_Master*  master );
-
-  LOCAL_DEF
-  FT_Error  Z1_Set_MM_Blend( T1_Face    face,
-                             FT_UInt    num_coords,
-                             FT_Fixed*  coords );
-
-  LOCAL_DEF
-  FT_Error  Z1_Set_MM_Design( T1_Face   face,
-                              FT_UInt   num_coords,
-                              FT_Long*  coords );
-
-  LOCAL_DEF
-  void  Z1_Done_Blend( T1_Face  face );
-
-#endif /* !Z1_CONFIG_OPTION_NO_MM_SUPPORT */
-
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif /* Z1LOAD_H */
-
-
-/* END */
--- a/src/type1z/z1objs.c
+++ /dev/null
@@ -1,406 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  z1objs.c                                                               */
-/*                                                                         */
-/*    Experimental Type 1 objects manager (body).                          */
-/*                                                                         */
-/*  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.                                        */
-/*                                                                         */
-/***************************************************************************/
-
-
-#include <freetype/internal/ftdebug.h>
-#include <freetype/internal/ftstream.h>
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1gload.h"
-#include "z1load.h"
-#include "z1afm.h"
-
-#else
-
-#include <type1z/z1gload.h>
-#include <type1z/z1load.h>
-#include <type1z/z1afm.h>
-
-#endif
-
-
-#include <freetype/internal/psnames.h>
-#include <freetype/internal/psaux.h>
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
-  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
-  /* messages during execution.                                            */
-  /*                                                                       */
-#undef  FT_COMPONENT
-#define FT_COMPONENT  trace_z1objs
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /*                            FACE  FUNCTIONS                            */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Z1_Done_Face                                                       */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    The face object destructor.                                        */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    face :: A typeless pointer to the face object to destroy.          */
-  /*                                                                       */
-  LOCAL_FUNC
-  void  Z1_Done_Face( T1_Face  face )
-  {
-    FT_Memory  memory;
-    T1_Font*   type1 = &face->type1;
-
-
-    if ( face )
-    {
-      memory = face->root.memory;
-
-#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
-      /* release multiple masters information */
-      Z1_Done_Blend( face );
-      face->blend = 0;
-#endif
-
-      /* release font info strings */
-      {
-        T1_FontInfo*  info = &type1->font_info;
-
-
-        FREE( info->version );
-        FREE( info->notice );
-        FREE( info->full_name );
-        FREE( info->family_name );
-        FREE( info->weight );
-      }
-
-      /* release top dictionary */
-      FREE( type1->charstrings_len );
-      FREE( type1->charstrings );
-      FREE( type1->glyph_names );
-
-      FREE( type1->subrs );
-      FREE( type1->subrs_len );
-
-      FREE( type1->subrs_block );
-      FREE( type1->charstrings_block );
-      FREE( type1->glyph_names_block );
-
-      FREE( type1->encoding.char_index );
-      FREE( type1->font_name );
-
-#ifndef Z1_CONFIG_OPTION_NO_AFM
-      /* release afm data if present */
-      if ( face->afm_data )
-        Z1_Done_AFM( memory, (Z1_AFM*)face->afm_data );
-#endif
-
-      /* release unicode map, if any */
-      FREE( face->unicode_map.maps );
-      face->unicode_map.num_maps = 0;
-
-      face->root.family_name = 0;
-      face->root.style_name  = 0;
-    }
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Z1_Init_Face                                                       */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    The face object constructor.                                       */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    stream     ::  input stream where to load font data.               */
-  /*                                                                       */
-  /*    face_index :: The index of the font face in the resource.          */
-  /*                                                                       */
-  /*    num_params :: Number of additional generic parameters.  Ignored.   */
-  /*                                                                       */
-  /*    params     :: Additional generic parameters.  Ignored.             */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    face       :: The face record to build.                            */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  LOCAL_FUNC
-  FT_Error  Z1_Init_Face( FT_Stream      stream,
-                          T1_Face        face,
-                          FT_Int         face_index,
-                          FT_Int         num_params,
-                          FT_Parameter*  params )
-  {
-    FT_Error            error;
-    PSNames_Interface*  psnames;
-    PSAux_Interface*    psaux;
-
-    FT_UNUSED( num_params );
-    FT_UNUSED( params );
-    FT_UNUSED( face_index );
-    FT_UNUSED( stream );
-
-
-    face->root.num_faces = 1;
-
-    psnames = (PSNames_Interface*)face->psnames;
-    if ( !psnames )
-    {
-      psnames = (PSNames_Interface*)
-                FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psnames" );
-
-      face->psnames = psnames;
-    }
-
-    psaux = (PSAux_Interface*)face->psaux;
-    if ( !psaux )
-    {
-      psaux = (PSAux_Interface*)
-              FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psaux" );
-              
-      face->psaux = psaux;
-    }
-
-    /* open the tokenizer, this will also check the font format */
-    error = Z1_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(( "Z1_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->type1.num_glyphs;
-      root->num_charmaps = 1;
-
-      root->face_index = face_index;
-      root->face_flags = FT_FACE_FLAG_SCALABLE;
-
-      root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
-
-      root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
-
-      if ( face->type1.font_info.is_fixed_pitch )
-        root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
-
-      if ( face->blend )
-        root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
-
-      /* XXX: TODO -- add kerning with .afm support */
-
-      /* get style name -- be careful, some broken fonts only */
-      /* have a `/FontName' dictionary entry!                 */
-      root->family_name = face->type1.font_info.family_name;
-      if ( root->family_name )
-      {
-        char*  full   = face->type1.font_info.full_name;
-        char*  family = root->family_name;
-
-
-        while ( *family && *full == *family )
-        {
-          family++;
-          full++;
-        }
-
-        root->style_name = ( *full == ' ' ? full + 1
-                                          : (char *)"Regular" );
-      }
-      else
-      {
-        /* do we have a `/FontName'? */
-        if ( face->type1.font_name )
-        {
-          root->family_name = face->type1.font_name;
-          root->style_name  = (char *)"Regular";
-        }
-      }
-
-      /* no embedded bitmap support */
-      root->num_fixed_sizes = 0;
-      root->available_sizes = 0;
-
-      root->bbox         = face->type1.font_bbox;
-      root->units_per_EM = 1000;
-      root->ascender     = (FT_Short)face->type1.font_bbox.yMax;
-      root->descender    = (FT_Short)face->type1.font_bbox.yMin;
-      root->height       = ( ( root->ascender + root->descender ) * 12 ) / 10;
-
-      /* 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 = Z1_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;
-
-      root->underline_position  = face->type1.font_info.underline_position;
-      root->underline_thickness = face->type1.font_info.underline_thickness;
-
-      root->max_points   = 0;
-      root->max_contours = 0;
-    }
-
-    /* charmap support -- synthetize unicode charmap if possible */
-    {
-      FT_Face     root    = &face->root;
-      FT_CharMap  charmap = face->charmaprecs;
-
-
-      /* synthesize a Unicode charmap if there is support in the `PSNames' */
-      /* module                                                            */
-      if ( 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 = FT_Err_Ok;
-        }
-      }
-
-      /* now, support either the standard, expert, or custom encoding */
-      charmap->face        = (FT_Face)face;
-      charmap->platform_id = 7;  /* a new platform id for Adobe fonts? */
-
-      switch ( face->type1.encoding_type )
-      {
-      case t1_encoding_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];
-    }
-
-  Exit:
-    return error;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Z1_Init_Driver                                                     */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Initializes a given Type 1 driver object.                          */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    driver :: A handle to the target driver object.                    */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  LOCAL_FUNC
-  FT_Error  Z1_Init_Driver( Z1_Driver  driver )
-  {
-    FT_UNUSED( driver );
-
-    return T1_Err_Ok;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Z1_Done_Driver                                                     */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Finalizes a given Type 1 driver.                                   */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    driver  :: A handle to the target Type 1 driver.                   */
-  /*                                                                       */
-  LOCAL_DEF
-  void  Z1_Done_Driver( Z1_Driver  driver )
-  {
-    FT_UNUSED( driver );
-  }
-
-
-/* END */
--- a/src/type1z/z1objs.h
+++ /dev/null
@@ -1,161 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  z1objs.h                                                               */
-/*                                                                         */
-/*    Experimental Type 1 objects manager (specification).                 */
-/*                                                                         */
-/*  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 Z1OBJS_H
-#define Z1OBJS_H
-
-#include <freetype/internal/ftobjs.h>
-#include <freetype/config/ftconfig.h>
-#include <freetype/internal/t1errors.h>
-#include <freetype/internal/t1types.h>
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-  /* The following structures must be defined by the hinter */
-  typedef struct Z1_Size_Hints_   Z1_Size_Hints;
-  typedef struct Z1_Glyph_Hints_  Z1_Glyph_Hints;
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Type>                                                                */
-  /*    Z1_Driver                                                          */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A handle to a Type 1 driver object.                                */
-  /*                                                                       */
-  typedef struct Z1_DriverRec_   *Z1_Driver;
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Type>                                                                */
-  /*    Z1_Size                                                            */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A handle to a Type 1 size object.                                  */
-  /*                                                                       */
-  typedef struct Z1_SizeRec_*  Z1_Size;
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Type>                                                                */
-  /*    Z1_GlyphSlot                                                       */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A handle to a Type 1 glyph slot object.                            */
-  /*                                                                       */
-  typedef struct Z1_GlyphSlotRec_*  Z1_GlyphSlot;
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Type>                                                                */
-  /*    Z1_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 Z1_CharMapRec_*   Z1_CharMap;
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /*                  HERE BEGINS THE TYPE1 SPECIFIC STUFF                 */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Type>                                                                */
-  /*    Z1_SizeRec                                                         */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Type 1 size record.                                                */
-  /*                                                                       */
-  typedef struct  Z1_SizeRec_
-  {
-    FT_SizeRec      root;
-    FT_Bool         valid;
-    Z1_Size_Hints*  hints;  /* defined in the hinter. This allows */
-                            /* us to experiment with different    */
-                            /* hinting schemes without having to  */
-                            /* change `z1objs' each time.         */
-  } Z1_SizeRec;
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Type>                                                                */
-  /*    Z1_GlyphSlotRec                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Type 1 glyph slot record.                                          */
-  /*                                                                       */
-  typedef struct  Z1_GlyphSlotRec_
-  {
-    FT_GlyphSlotRec  root;
-
-    FT_Bool          hint;
-    FT_Bool          scaled;
-
-    FT_Int           max_points;
-    FT_Int           max_contours;
-
-    FT_Fixed         x_scale;
-    FT_Fixed         y_scale;
-
-    Z1_Glyph_Hints*  hints;  /* defined in the hinter */
-
-  } Z1_GlyphSlotRec;
-
-
-  LOCAL_DEF
-  FT_Error  Z1_Init_Face( FT_Stream      stream,
-                          T1_Face        face,
-                          FT_Int         face_index,
-                          FT_Int         num_params,
-                          FT_Parameter*  params );
-
-  LOCAL_DEF
-  void  Z1_Done_Face( T1_Face  face );
-
-  LOCAL_DEF
-  FT_Error  Z1_Init_Driver( Z1_Driver  driver );
-
-  LOCAL_DEF
-  void  Z1_Done_Driver( Z1_Driver  driver );
-
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif /* Z1OBJS_H */
-
-
-/* END */
--- a/src/type1z/z1parse.c
+++ /dev/null
@@ -1,487 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  z1parse.c                                                              */
-/*                                                                         */
-/*    Experimental Type 1 parser (body).                                   */
-/*                                                                         */
-/*  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 Type 1 parser is in charge of the following:                      */
-  /*                                                                       */
-  /*  - provide an implementation of a growing sequence of objects called  */
-  /*    a `Z1_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 `z1load.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 <freetype/internal/t1errors.h>
-#include <freetype/internal/psaux.h>
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1parse.h"
-
-#else
-
-#include <type1z/z1parse.h>
-
-#endif
-
-
-#include <string.h>     /* for strncmp() */
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
-  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
-  /* messages during execution.                                            */
-  /*                                                                       */
-#undef  FT_COMPONENT
-#define FT_COMPONENT  trace_z1parse
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****                   INPUT STREAM PARSER                         *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-
-
-#define IS_Z1_WHITESPACE( c )  ( (c) == ' '  || (c) == '\t' )
-#define IS_Z1_LINESPACE( c )   ( (c) == '\r' || (c) == '\n' )
-
-#define IS_Z1_SPACE( c )  ( IS_Z1_WHITESPACE( c ) || IS_Z1_LINESPACE( c ) )
-
-
-  typedef struct  PFB_Tag_
-  {
-    FT_UShort  tag;
-    FT_Long    size;
-    
-  } PFB_Tag;
-
-
-#undef  FT_STRUCTURE
-#define FT_STRUCTURE  PFB_Tag
-
-
-  static
-  const FT_Frame_Field  pfb_tag_fields[] =
-  {
-    FT_FRAME_START( 6 ),
-      FT_FRAME_USHORT ( tag ),
-      FT_FRAME_LONG_LE( size ),
-    FT_FRAME_END
-  };
-
-
-  static
-  FT_Error  read_pfb_tag( FT_Stream   stream,
-                          FT_UShort*  tag,
-                          FT_Long*    size )
-  {
-    FT_Error  error;
-    PFB_Tag   head;
-
-
-    *tag  = 0;
-    *size = 0;
-    if ( !READ_Fields( pfb_tag_fields, &head ) )
-    {
-      if ( head.tag == 0x8001 || head.tag == 0x8002 )
-      {
-        *tag  = head.tag;
-        *size = head.size;
-      }
-    }
-    return error;
-  }
-
-
-  LOCAL_FUNC
-  FT_Error  Z1_New_Parser( Z1_Parser*        parser,
-                           FT_Stream         stream,
-                           FT_Memory         memory,
-                           PSAux_Interface*  psaux )
-  {
-    FT_Error   error;
-    FT_UShort  tag;
-    FT_Long    size;
-
-
-    psaux->t1_parser_funcs->init( &parser->root,0, 0, memory );
-
-    parser->stream       = stream;
-    parser->base_len     = 0;
-    parser->base_dict    = 0;
-    parser->private_len  = 0;
-    parser->private_dict = 0;
-    parser->in_pfb       = 0;
-    parser->in_memory    = 0;
-    parser->single_block = 0;
-
-    /******************************************************************/
-    /*                                                                */
-    /* Here a short summary of what is going on:                      */
-    /*                                                                */
-    /*   When creating a new Type 1 parser, we try to locate and load */
-    /*   the base dictionary if this is possible (i.e. for PFB        */
-    /*   files).  Otherwise, we load the whole font into memory.      */
-    /*                                                                */
-    /*   When `loading' the base dictionary, we only setup pointers   */
-    /*   in the case of a memory-based stream.  Otherwise, we         */
-    /*   allocate and load the base dictionary in it.                 */
-    /*                                                                */
-    /*   parser->in_pfb is set if we are in a binary (".pfb") font.   */
-    /*   parser->in_memory is set if we have a memory stream.         */
-    /*                                                                */
-
-    /* try to compute the size of the base dictionary;   */
-    /* look for a Postscript binary file tag, i.e 0x8001 */
-    if ( FILE_Seek( 0L ) )
-      goto Exit;
-
-    error = read_pfb_tag( stream, &tag, &size );
-    if ( error )
-      goto Exit;
-
-    if ( tag != 0x8001 )
-    {
-      /* assume that this is a PFA file for now; an error will */
-      /* be produced later when more things are checked        */
-      if ( FILE_Seek( 0L ) )
-        goto Exit;
-      size = stream->size;
-    }
-    else
-      parser->in_pfb = 1;
-
-    /* now, try to load `size' bytes of the `base' dictionary we */
-    /* found previously                                          */
-
-    /* if it is a memory-based resource, set up pointers */
-    if ( !stream->read )
-    {
-      parser->base_dict = (FT_Byte*)stream->base + stream->pos;
-      parser->base_len  = size;
-      parser->in_memory = 1;
-
-      /* check that the `size' field is valid */
-      if ( FILE_Skip( size ) )
-        goto Exit;
-    }
-    else
-    {
-      /* read segment in memory */
-      if ( ALLOC( parser->base_dict, size )     ||
-           FILE_Read( parser->base_dict, size ) )
-        goto Exit;
-      parser->base_len = size;
-    }
-
-    /* Now check font format; we must see `%!PS-AdobeFont-1' */
-    /* or `%!FontType'                                       */
-    {
-      if ( size <= 16                                    ||
-           ( strncmp( (const char*)parser->base_dict,
-                      "%!PS-AdobeFont-1", 16 )        &&
-             strncmp( (const char*)parser->base_dict,
-                      "%!FontType", 10 )              )  )
-      {
-        FT_TRACE2(( "[not a Type1 font]\n" ));
-        error = FT_Err_Unknown_File_Format;
-      }
-      else
-      {
-        parser->root.base   = parser->base_dict;
-        parser->root.cursor = parser->base_dict;
-        parser->root.limit  = parser->root.cursor + parser->base_len;
-      }
-    }
-
-  Exit:
-    if ( error && !parser->in_memory )
-      FREE( parser->base_dict );
-
-    return error;
-  }
-
-
-  LOCAL_FUNC
-  void  Z1_Done_Parser( Z1_Parser*  parser )
-  {
-    FT_Memory   memory = parser->root.memory;
-
-
-    /* always free the private dictionary */
-    FREE( parser->private_dict );
-
-    /* free the base dictionary only when we have a disk stream */
-    if ( !parser->in_memory )
-      FREE( parser->base_dict );
-      
-    parser->root.funcs.done( &parser->root );
-  }
-
-
-  /* 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;
-  }
-
-
-  LOCAL_FUNC
-  void  Z1_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--;
-    }
-  }
-
-
-  LOCAL_FUNC
-  FT_Error  Z1_Get_Private_Dict( Z1_Parser*  parser )
-  {
-    FT_Stream  stream = parser->stream;
-    FT_Memory  memory = parser->root.memory;
-    FT_Error   error  = 0;
-    FT_Long    size;
-
-
-    if ( parser->in_pfb )
-    {
-      /* in the case of the PFB format, the private dictionary can be  */
-      /* made of several segments.  We thus first read the number of   */
-      /* segments to compute the total size of the private dictionary  */
-      /* then re-read them into memory.                                */
-      FT_Long    start_pos = FILE_Pos();
-      FT_UShort  tag;
-
-
-      parser->private_len = 0;
-      for (;;)
-      {
-        error = read_pfb_tag( stream, &tag, &size );
-        if ( error )
-          goto Fail;
-
-        if ( tag != 0x8002 )
-          break;
-
-        parser->private_len += size;
-
-        if ( FILE_Skip( size ) )
-          goto Fail;
-      }
-
-      /* Check that we have a private dictionary there */
-      /* and allocate private dictionary buffer        */
-      if ( parser->private_len == 0 )
-      {
-        FT_ERROR(( "Z1_Get_Private_Dict:" ));
-        FT_ERROR(( " invalid private dictionary section\n" ));
-        error = T1_Err_Invalid_File_Format;
-        goto Fail;
-      }
-
-      if ( FILE_Seek( start_pos )                             ||
-           ALLOC( parser->private_dict, parser->private_len ) )
-        goto Fail;
-
-      parser->private_len = 0;
-      for (;;)
-      {
-        error = read_pfb_tag( stream, &tag, &size );
-        if ( error || tag != 0x8002 )
-        {
-          error = FT_Err_Ok;
-          break;
-        }
-
-        if ( FILE_Read( parser->private_dict + parser->private_len, size ) )
-          goto Fail;
-
-        parser->private_len += size;
-      }
-    }
-    else
-    {
-      /* we have already `loaded' the whole PFA font file into memory; */
-      /* if this is a memory resource, allocate a new block to hold    */
-      /* the private dict. Otherwise, simply overwrite into the base   */
-      /* dictionary block in the heap.                                 */
-
-      /* first of all, look at the `eexec' keyword */
-      FT_Byte*  cur   = parser->base_dict;
-      FT_Byte*  limit = cur + parser->base_len;
-      FT_Byte   c;
-
-
-      for (;;)
-      {
-        c = cur[0];
-        if ( c == 'e' && cur + 9 < limit )  /* 9 = 5 letters for `eexec' + */
-                                            /* newline + 4 chars           */
-        {
-          if ( cur[1] == 'e' && cur[2] == 'x' &&
-               cur[3] == 'e' && cur[4] == 'c' )
-          {
-            cur += 6; /* we skip the newling after the `eexec' */
-
-            /* XXX: Some fonts use DOS-linefeeds, i.e. \r\n; we need to */
-            /*      skip the extra \n if we find it                     */
-            if ( cur[0] == '\n' )
-              cur++;
-
-            break;
-          }
-        }
-        cur++;
-        if ( cur >= limit )
-        {
-          FT_ERROR(( "Z1_Get_Private_Dict:" ));
-          FT_ERROR(( " could not find `eexec' keyword\n" ));
-          error = T1_Err_Invalid_File_Format;
-          goto Exit;
-        }
-      }
-
-      /* now determine where to write the _encrypted_ binary private  */
-      /* dictionary.  We overwrite the base dictionary for disk-based */
-      /* resources and allocate a new block otherwise                 */
-
-      size = parser->base_len - ( cur - parser->base_dict);
-
-      if ( parser->in_memory )
-      {
-        /* note that we allocate one more byte to put a terminating `0' */
-        if ( ALLOC( parser->private_dict, size + 1 ) )
-          goto Fail;
-        parser->private_len = size;
-      }
-      else
-      {
-        parser->single_block = 1;
-        parser->private_dict = parser->base_dict;
-        parser->private_len  = size;
-        parser->base_dict    = 0;
-        parser->base_len     = 0;
-      }
-
-      /* now determine whether the private dictionary is encoded in binary */
-      /* or hexadecimal ASCII format -- decode it accordingly              */
-
-      /* we need to access the next 4 bytes (after the final \r following */
-      /* the `eexec' keyword); if they all are hexadecimal digits, then   */
-      /* we have a case of ASCII storage                                  */
-
-      if ( ( hexa_value( cur[0] ) | hexa_value( cur[1] ) |
-             hexa_value( cur[2] ) | hexa_value( cur[3] ) ) < 0 )
-
-        /* binary encoding -- `simply' copy the private dict */
-        MEM_Copy( parser->private_dict, cur, size );
-
-      else
-      {
-        /* ASCII hexadecimal encoding */
-
-        FT_Byte*  write;
-        FT_Int    count;
-
-
-        write = parser->private_dict;
-        count = 0;
-
-        for ( ;cur < limit; cur++ )
-        {
-          int  hex1;
-
-
-          /* check for newline */
-          if ( cur[0] == '\r' || cur[0] == '\n' )
-            continue;
-
-          /* exit if we have a non-hexadecimal digit that isn't a newline */
-          hex1 = hexa_value( cur[0] );
-          if ( hex1 < 0 || cur + 1 >= limit )
-            break;
-
-          /* otherwise, store byte */
-          *write++ = ( hex1 << 4 ) | hexa_value( cur[1] );
-          count++;
-          cur++;
-        }
-
-        /* put a safeguard */
-        parser->private_len = write - parser->private_dict;
-        *write++ = 0;
-      }
-    }
-
-    /* we now decrypt the encoded binary private dictionary */
-    Z1_Decrypt( parser->private_dict, parser->private_len, 55665 );
-    parser->root.base = parser->private_dict;
-    parser->root.cursor = parser->private_dict;
-    parser->root.limit  = parser->root.cursor + parser->private_len;
-
-  Fail:
-  Exit:
-    return error;
-  }
-
-
-/* END */
--- a/src/type1z/z1parse.h
+++ /dev/null
@@ -1,140 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  z1parse.h                                                              */
-/*                                                                         */
-/*    Experimental Type 1 parser (specification).                          */
-/*                                                                         */
-/*  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 Z1PARSE_H
-#define Z1PARSE_H
-
-#include <freetype/internal/t1types.h>
-#include <freetype/internal/ftstream.h>
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Struct>                                                              */
-  /*    Z1_Parser                                                          */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A Z1_Parser is an object used to parse a Type 1 fonts very         */
-  /*    quickly.                                                           */
-  /*                                                                       */
-  /* <Fields>                                                              */
-  /*    root         :: The root parser.                                   */
-  /*                                                                       */
-  /*    stream       :: The current input stream.                          */
-  /*                                                                       */
-  /*    base_dict    :: A pointer to the top-level dictionary.             */
-  /*                                                                       */
-  /*    base_len     :: The length in bytes of the top dictionary.         */
-  /*                                                                       */
-  /*    private_dict :: A pointer to the private dictionary.               */
-  /*                                                                       */
-  /*    private_len  :: The length in bytes of the private dictionary.     */
-  /*                                                                       */
-  /*    in_pfb       :: A boolean.  Indicates that we are handling a PFB   */
-  /*                    file.                                              */
-  /*                                                                       */
-  /*    in_memory    :: A boolean.  Indicates a memory-based stream.       */
-  /*                                                                       */
-  /*    single_block :: A boolean.  Indicates that the private dictionary  */
-  /*                    is stored in lieu of the base dictionary.          */
-  /*                                                                       */
-  typedef struct  Z1_Parser_
-  {
-    T1_Parser  root;
-    FT_Stream  stream;
-
-    FT_Byte*   base_dict;
-    FT_Int     base_len;
-
-    FT_Byte*   private_dict;
-    FT_Int     private_len;
-
-    FT_Byte    in_pfb;
-    FT_Byte    in_memory;
-    FT_Byte    single_block;
-
-  } Z1_Parser;
-
-
-#define Z1_Add_Table( p, i, o, l )  (p)->funcs.add( (p), i, o, l )
-#define Z1_Done_Table( p )          \
-          do                        \
-          {                         \
-            if ( (p)->funcs.done )  \
-              (p)->funcs.done( p ); \
-          } while ( 0 )
-#define Z1_Release_Table( p )          \
-          do                           \
-          {                            \
-            if ( (p)->funcs.release )  \
-              (p)->funcs.release( p ); \
-          } while ( 0 )
-
-
-#define Z1_Skip_Spaces( p )  (p)->root.funcs.skip_spaces( &(p)->root )
-#define Z1_Skip_Alpha( p )   (p)->root.funcs.skip_alpha ( &(p)->root )
-
-#define Z1_ToInt( p )       (p)->root.funcs.to_int( &(p)->root )
-#define Z1_ToFixed( p, t )  (p)->root.funcs.to_fixed( &(p)->root, t )
-
-#define Z1_ToCoordArray( p, m, c )    \
-          (p)->root.funcs.to_coord_array( &(p)->root, m, c )
-#define Z1_ToFixedArray( p, m, f, t ) \
-          (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
-#define Z1_ToToken( p, t )            \
-          (p)->root.funcs.to_token( &(p)->root, t )
-#define Z1_ToTokenArray( p, t, m, c ) \
-          (p)->root.funcs.to_token_array( &(p)->root, t, m, c )
-
-#define Z1_Load_Field( p, f, o, m, pf )       \
-          (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )
-#define Z1_Load_Field_Table( p, f, o, m, pf ) \
-          (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )
-
-
-  LOCAL_DEF
-  FT_Error  Z1_New_Parser( Z1_Parser*        parser,
-                           FT_Stream         stream,
-                           FT_Memory         memory,
-                           PSAux_Interface*  psaux );
-
-  LOCAL_DEF
-  FT_Error  Z1_Get_Private_Dict( Z1_Parser*  parser );
-
-  LOCAL_DEF
-  void  Z1_Decrypt( FT_Byte*   buffer,
-                    FT_Int     length,
-                    FT_UShort  seed );
-
-  LOCAL_DEF
-  void  Z1_Done_Parser( Z1_Parser*  parser );
-
-
-#ifdef __cplusplus
-  }
-#endif
-
-
-#endif /* Z1PARSE_H */
-
-
-/* END */
--- a/src/type1z/z1tokens.h
+++ /dev/null
@@ -1,73 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  z1tokens.h                                                             */
-/*                                                                         */
-/*    Experimental Type 1 tokenizer (specification).                       */
-/*                                                                         */
-/*  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.                                        */
-/*                                                                         */
-/***************************************************************************/
-
-
-#undef  FT_STRUCTURE
-#define FT_STRUCTURE  T1_FontInfo
-#undef  T1CODE
-#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_NUM   ( "ItalicAngle", italic_angle )
-  T1_FIELD_BOOL  ( "isFixedPitch", is_fixed_pitch )
-  T1_FIELD_NUM   ( "UnderlinePosition", underline_position )
-  T1_FIELD_NUM   ( "UnderlineThickness", underline_thickness )
-
-
-#undef  FT_STRUCTURE
-#define FT_STRUCTURE  T1_Private
-#undef  T1CODE
-#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 )
-
-
-#undef  FT_STRUCTURE
-#define FT_STRUCTURE  T1_Font
-#undef  T1CODE
-#define T1CODE        t1_field_font_dict
-
-  T1_FIELD_NUM( "PaintType", paint_type )
-  T1_FIELD_NUM( "FontType", font_type )
-  T1_FIELD_NUM( "StrokeWidth", stroke_width )
-
-
-/* END */