shithub: freetype+ttf2subf

Download patch

ref: 2dfb5aca285baf50eed6c0a9520069614a2e5cf5
parent: d42c68e85593db7dc925c5cc6f831a1f94e9a48a
author: David Turner <[email protected]>
date: Thu Jan 27 09:02:04 EST 2000

added a new experimental Type 1 driver. This version sports several
improvements compared to "src/type1". Briefly :

  - the postscript-like interpreter is now gone. We now perform
    pattern-matching to load our font content. The resultant code
    is much faster, smaller, and easier to maintain.

    For a more detailed description, see the comments at the start
    of "src/type1z/t1objs.c"

  - the glyph loader will be greatly simplified really soon, and the
    clumsy hinter will be ditched in favor of a more general auto-hinting
    module (when we get one).

    The goal is to strip down the Type1 driver to about 15-20 Kb.

This is still an experimental version. It is added to the repository
for archiving. You should not try to use it for now (it won't work
because some crucial parts are _knowingly_ ignored for now !).

Note that the "old" type1 driver will probably move to the "demos/src"
directory, in order to show how one can replace one given font driver
at runtime (and to provide the functionality of the "t1dump" program).

git/fs: mount .git/fs: mount/attach disallowed
--- /dev/null
+++ b/src/type1z/module.mk
@@ -1,0 +1,6 @@
+make_module_list: add_type1z_driver
+
+add_type1z_driver:
+	$(OPEN_DRIVER)t1z_driver_interface$(CLOSE_DRIVER)
+	$(ECHO_DRIVER)type1z    $(ECHO_DRIVER_DESC) Postscript font files with extension *.pfa or *.pfb $(ECHO_DRIVER_DONE)
+
--- /dev/null
+++ b/src/type1z/rules.mk
@@ -1,0 +1,168 @@
+#****************************************************************************
+#*                                                                          *
+#*  Type1z driver Makefile                                                  *
+#*                                                                          *
+#*  Copyright 1996-1999 by                                                  *
+#*  David Turner, Robert Wilhelm, and Werner Lemberg.                       *
+#*                                                                          *
+#*  This file is part of the FreeType project, and may only be used         *
+#*  modified and distributed under the terms of the FreeType project        *
+#*  license, LICENSE.TXT.  By continuing to use, modify, or distribute      *
+#*  this file you indicate that you have read the license and               *
+#*  understand and accept it fully.                                         *
+#*                                                                          *
+#*  The "Type1z" driver is an experimental replacement for the current      *
+#*  Type 1 driver. It features a very different loading mechanism that      *
+#*  is much faster than the one used by the "normal" driver, and also       *
+#*  deals nicely with nearly broken Type 1 font files.. It is also          *
+#*  much smaller..                                                          *
+#*                                                                          *
+#*  Note that it may become a permanent replacement of the current          *
+#*  "src/type1" driver in the future..                                      *
+#*                                                                          *
+#****************************************************************************
+
+
+#****************************************************************************
+#*                                                                          *
+#*  IMPORTANT NOTE: This Makefile is intended for GNU Make!                 *
+#*                  If you provide Makefiles for other make utilities,      *
+#*                  please place them in `freetype/lib/arch/<system>'.      *
+#*                                                                          *
+#*                                                                          *
+#*  This file is to be included by the FreeType Makefile.lib, located in    *
+#*  the `freetype/lib' directory.  Here is the list of the variables that   *
+#*  must be defined to use it:                                              *
+#*                                                                          *
+#*                                                                          *
+#*     BASE_DIR:    The location of the base layer's directory.  This is    *
+#*                  usually `freetype/lib/base'.                            *
+#*                                                                          *
+#*     ARCH_DIR:    The location of the architecture-dependent directory.   *
+#*                  This is usually `freetype/lib/arch/<system>'.           *
+#*                                                                          *
+#*     DRIVERS_DIR: The location of the font driver sub-dirs, usually       *
+#*                  `freetype/lib/drivers'.                                 *
+#*                                                                          *
+#*     OBJ_DIR:     The location where the compiled object(s) file will be  *
+#*                  placed.                                                 *
+#*                                                                          *
+#*     BASE_H:      A list of pathnames to the base layer's header files on *
+#*                  which the driver depends.                               *
+#*                                                                          *
+#*     FT_CFLAGS:   A set of flags used for compilation of object files.    *
+#*                  This contains at least the include paths of the arch    *
+#*                  and base directories + optimization + warnings + ANSI   *
+#*                  compliance.                                             *
+#*                                                                          *
+#*     FT_IFLAG:    The flag used to specify an include path on the         *
+#*                  compiler command line.  For example, with GCC, this is  *
+#*                  `-I', while some other compilers use `/i=' or `-J',     *
+#*                  etc.                                                    *
+#*                                                                          *
+#*     FT_OBJ:      The suffix of an object file for the platform; can be   *
+#*                  `o', `obj', `coff', `tco', etc. depending on the        *
+#*                  platform.                                               *
+#*                                                                          *
+#*                                                                          *
+#*  It also updates the following variables defined and used in the main    *
+#*  Makefile:                                                               *
+#*                                                                          *
+#*     DRV_OBJ_S:            The list of driver object files in             *
+#*                           single-object mode.                            *
+#*                                                                          *
+#*     DRV_OBJ_M:            The list of driver object files in             *
+#*                           multiple-objects mode.                         *
+#*                                                                          *
+#*     FTINIT_DRIVER_PATHS:  The list of include paths used to compile the  *
+#*                           `ftinit' component which registers all font    *
+#*                            drivers in the FT_Init_FreeType() function.   *
+#*                                                                          *
+#*     FTINIT_DRIVER_H:      The list of header dependencies used to        *
+#*                           compile the `ftinit' component.                *
+#*                                                                          *
+#*     FTINIT_DRIVER_MACROS: The list of macros to be defined when          *
+#*                           compiling the `ftinit' component.              *
+#*                                                                          *
+#*  `Single-object compilation' means that each font driver is compiled     *
+#*  into a single object file.  This is useful to get rid of all            *
+#*  driver-specific entries.                                                *
+#*                                                                          *
+#****************************************************************************
+
+
+# Type1z driver directory
+#
+T1Z_DIR  := $(SRC_)type1z
+T1Z_DIR_ := $(T1Z_DIR)$(SEP)
+
+
+# additional include flags used when compiling the driver
+#
+T1Z_INCLUDE := $(SHARED) $(T1Z_DIR)
+T1Z_COMPILE := $(FT_COMPILE) $(T1Z_INCLUDE:%=$I%)
+
+
+# Type1 driver sources (i.e., C files)
+#
+T1Z_DRV_SRC := $(T1Z_DIR_)t1parse.c   \
+              $(T1Z_DIR_)t1load.c
+#              $(T1Z_DIR_)t1parse.c   \
+#              $(T1Z_DIR_)t1tokens.c  \
+#              $(T1Z_DIR_)t1driver.c  \
+#	          $(T1Z_DIR_)t1encode.c  \
+#              $(T1Z_DIR_)t1hinter.c  \
+#              $(T1Z_DIR_)t1gload.c
+
+
+# Type1 driver headers
+#
+T1Z_DRV_H := $(T1Z_DIR_)t1errors.h    \
+            $(T1Z_DIR_)t1config.h    \
+            $(T1SHARED_H)           \
+            $(T1Z_DRV_SRC:%.c=%.h)
+
+
+# driver object(s)
+#
+#   T1Z_DRV_OBJ_M is used during `debug' builds
+#   T1Z_DRV_OBJ_S is used during `release' builds
+#
+T1Z_DRV_OBJ_M := $(T1Z_DRV_SRC:$(T1Z_DIR_)%.c=$(OBJ_)%.$O) \
+                $(T1SHARED:$(T1SHARED_DIR_)%.c=$(OBJ_)%.$O)
+T1Z_DRV_OBJ_S := $(OBJ_)type1z.$O
+
+
+
+# driver root source file(s)
+#
+T1Z_DRV_SRC_M := $(T1Z_DRV_SRC) $(T1SHARED_SRC)
+T1Z_DRV_SRC_S := $(T1Z_DIR_)type1z.c
+
+
+# driver - single object
+#
+#  the driver is recompiled if any of the header or source files is changed
+#
+$(T1Z_DRV_OBJ_S): $(BASE_H) $(T1Z_DRV_H) $(T1Z_DRV_SRC) $(T1Z_DRV_SRC_S)
+	$(T1Z_COMPILE) $T$@ $(T1Z_DRV_SRC_S)
+
+
+
+# driver - multiple objects
+#
+#   All objects are recompiled if any of the header files is changed
+#
+$(OBJ_)t1%.$O: $(T1Z_DIR_)t1%.c $(BASE_H) $(T1Z_DRV_H)
+	$(T1Z_COMPILE) $T$@ $<
+
+$(OBJ_)t1%.$O: $(T1SHARED_DIR_)t1%.c $(BASE_H) $(T1SHARED_H)
+	$(T1Z_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(T1Z_DRV_OBJ_S)
+DRV_OBJS_M += $(T1Z_DRV_OBJ_M)
+
+# END
--- /dev/null
+++ b/src/type1z/t1config.h
@@ -1,0 +1,45 @@
+/*******************************************************************
+ *
+ *  t1config.h
+ *
+ *    Type 1 driver configuration file
+ *
+ *  Copyright 1996-1998 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ *  This file is part of the FreeType project, and may only be used,
+ *  modified, and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT.  By continuing to use, modify, or distribute 
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ ******************************************************************/
+
+#ifndef T1CONFIG_H
+#define T1CONFIG_H
+
+/* T1_MAX_STACK_DEPTH is the maximal depth of the token stack used */
+/* by the Type 1 parser (see t1load.c). A minimum of 16 is required */
+/*                                                                 */
+#define T1_MAX_STACK_DEPTH  16
+
+/* T1_MAX_DICT_DEPTH is the maximal depth of nest dictionaries and */
+/* arrays in the Type 1 stream (see t1load.c). A minimum of 4 is   */
+/* required                                                        */
+#define T1_MAX_DICT_DEPTH   5
+
+/* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine */
+/* calls during glyph loading                                          */
+#define T1_MAX_SUBRS_CALLS   8
+
+
+/* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity */
+#define T1_MAX_CHARSTRINGS_OPERANDS  32
+
+
+/* Define T1_CONFIG_OPTION_DISABLE_HINTER if you want to generate  */
+/* a driver with no hinter. This can be useful to debug the parser */
+/*                                                                 */
+#undef  T1_CONFIG_OPTION_DISABLE_HINTER
+
+#endif /* T1CONFIG_H */
--- /dev/null
+++ b/src/type1z/t1driver.c
@@ -1,0 +1,271 @@
+/*******************************************************************
+ *
+ *  t1driver.c
+ *
+ *    High-level Type1 driver interface for FreeType 2.0
+ *
+ *  Copyright 1996-1998 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ *  This file is part of the FreeType project, and may only be used,
+ *  modified, and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT.  By continuing to use, modify, or distribute 
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ ******************************************************************/
+
+#include <t1driver.h>
+#include <t1gload.h>
+
+#include <ftdebug.h>
+#include <ftstream.h>
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1driver
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Interface                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Each driver can provide one or more extensions to the base         */
+  /*    FreeType API.  These can be used to access format specific         */
+  /*    features (e.g., all TrueType/OpenType resources share a common     */
+  /*    file structure and common tables which can be accessed through the */
+  /*    `sfnt' interface), or more simply generic ones (e.g., the          */
+  /*    `postscript names' interface which can be used to retrieve the     */
+  /*     PostScript name of a given glyph index).                          */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    driver    :: A handle to a driver object.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    interface :: A string designing the interface.  Examples are       */
+  /*                 `sfnt', `post_names', `charmaps', etc.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A typeless pointer to the extension's interface (normally a table  */
+  /*    of function pointers).  Returns NULL if the requested extension    */
+  /*    isn't available (i.e., wasn't compiled in the driver at build      */
+  /*    time).                                                             */
+  /*                                                                       */
+  static
+  void*  Get_Interface( FT_Driver*        driver,
+                        const FT_String*  interface )
+  {
+    UNUSED(driver);
+    UNUSED(interface);
+    return 0;
+  }
+
+
+  /******************************************************************/
+  /*                                                                */
+  /* <Function> Set_Char_Sizes                                      */
+  /*                                                                */
+  /* <Description>                                                  */
+  /*    A driver method used to reset a size's character sizes      */
+  /*    (horizontal and vertical) expressed in fractional points.   */
+  /*                                                                */
+  /* <Input>                                                        */
+  /*    size        :: handle to target size object                 */
+  /*    char_width  :: character width expressed in 26.6 points     */
+  /*    char_height :: character height expressed in 26.6 points    */
+  /*                                                                */
+  /* <Return>                                                       */
+  /*    FreeType error code. 0 means success                        */
+  /*                                                                */
+  static
+  T1_Error  Set_Char_Sizes( T1_Size      size,
+                            T1_F26Dot6   char_width,
+                            T1_F26Dot6   char_height,
+                            T1_UInt      horz_resolution,
+                            T1_UInt      vert_resolution )
+  {
+    UNUSED(char_width);
+    UNUSED(horz_resolution);
+    UNUSED(vert_resolution);
+
+    size->valid = FALSE;
+    return T1_Reset_Size( size );
+  }
+
+
+  /******************************************************************/
+  /*                                                                */
+  /* <Function> Set_Pixel_Sizes                                     */
+  /*                                                                */
+  /* <Description>                                                  */
+  /*    A driver method used to reset a size's character sizes      */
+  /*    (horizontal and vertical) expressed in integer pixels.      */
+  /*                                                                */
+  /* <Input>                                                        */
+  /*    size         :: handle to target size object                */
+  /*                                                                */
+  /*    pixel_width  :: character width expressed in 26.6 points    */
+  /*                                                                */
+  /*    pixel_height :: character height expressed in 26.6 points   */
+  /*                                                                */
+  /*    char_size    :: the corresponding character size in points  */
+  /*                    This value is only sent to the TrueType     */
+  /*                    bytecode interpreter, even though 99% of    */
+  /*                    glyph programs will simply ignore it. A     */
+  /*                    safe value there is the maximum of the      */
+  /*                    pixel width and height (multiplied by       */
+  /*                    64 to make it a 26.6 fixed float !)         */
+  /* <Return>                                                       */
+  /*    FreeType error code. 0 means success                        */
+  /*                                                                */
+  static
+  T1_Error  Set_Pixel_Sizes( T1_Size     size,
+                             T1_Int      pixel_width,
+                             T1_Int      pixel_height )
+  {
+    UNUSED(pixel_width);
+    UNUSED(pixel_height);
+
+    size->valid = FALSE; 
+    return T1_Reset_Size(size);
+  }
+
+
+  /******************************************************************/
+  /*                                                                */
+  /* <Struct> FT_DriverInterface                                    */
+  /*                                                                */
+  /* <Description>                                                  */
+  /*    A structure used to hold a font driver's basic interface    */
+  /*    used by the high-level parts of FreeType (or other apps)    */
+  /*                                                                */
+  /*    Most scalable drivers provide a specialized interface to    */
+  /*    access format-specific features. It can be retrieved with   */
+  /*    a call to the "get_format_interface", and should be defined */
+  /*    in each font driver header (e.g. ttdriver.h, t1driver.h,..) */
+  /*                                                                */
+  /*    All fields are function pointers ..                         */
+  /*                                                                */
+  /*                                                                */
+  /* <Fields>                                                       */
+  /*                                                                */
+  /*    new_engine ::                                               */
+  /*        used to create and initialise a new driver object       */
+  /*                                                                */
+  /*    done_engine ::                                              */
+  /*        used to finalise and destroy a given driver object      */
+  /*                                                                */
+  /*    get_format_interface ::                                     */
+  /*        return a typeless pointer to the format-specific        */
+  /*        driver interface.                                       */
+  /*                                                                */
+  /*    new_face ::                                                 */
+  /*        create a new face object from a resource                */
+  /*                                                                */
+  /*    done_face ::                                                */
+  /*        discards a face object, as well as all child objects    */
+  /*        ( sizes, charmaps, glyph slots )                        */
+  /*                                                                */
+  /*    get_face_properties ::                                      */
+  /*        return generic face properties                          */
+  /*                                                                */
+  /*    get_kerning ::                                              */
+  /*        return the kerning vector corresponding to a pair       */
+  /*        of glyphs, expressed in unscaled font units.            */
+  /*                                                                */
+  /*    new_size ::                                                 */
+  /*        create and initialise a new scalable size object.       */
+  /*                                                                */
+  /*    new_fixed_size ::                                           */
+  /*        create and initialise a new fixed-size object.          */
+  /*                                                                */
+  /*    done_size ::                                                */
+  /*        finalize a given face size object.                      */
+  /*                                                                */
+  /*    set_size_resolutions ::                                     */
+  /*        reset a scalable size object's output resolutions       */
+  /*                                                                */
+  /*    set_size_char_sizes ::                                      */
+  /*        reset a scalable size object's character size           */
+  /*                                                                */
+  /*    set_pixel_sizes ::                                          */
+  /*        reset a face size object's pixel dimensions. Applies    */
+  /*        to both scalable and fixed faces.                       */
+  /*                                                                */
+  /*    new_glyph_slot ::                                           */
+  /*        create and initialise a new glyph slot                  */
+  /*                                                                */
+  /*    done_glyph_slot ::                                          */
+  /*        discard a given glyph slot                              */
+  /*                                                                */
+  /*    load_glyph ::                                               */
+  /*        load a given glyph into a given slot                    */
+  /*                                                                */
+  /*    get_glyph_metrics ::                                        */
+  /*        return a loaded glyph's metrics.                        */
+  /*                                                                */
+
+  EXPORT_FUNC
+  const  FT_DriverInterface  t1_driver_interface =
+  {
+    sizeof( FT_DriverRec ),
+    sizeof( T1_FaceRec ),
+    sizeof( T1_SizeRec ),
+    sizeof( T1_GlyphSlotRec ),
+    
+    "type1",
+    100,  /* driver version == 1.0          */
+    200,  /* requires FreeType 2.0 or above */
+
+    0,   /* format interface */
+
+    (FTDriver_initDriver)           T1_Init_Driver,
+    (FTDriver_doneDriver)           T1_Done_Driver,
+    (FTDriver_getInterface)         Get_Interface,
+
+    (FTDriver_initFace)             T1_Init_Face,
+    (FTDriver_doneFace)             T1_Done_Face,
+    (FTDriver_getKerning)           0,
+
+    (FTDriver_initSize)             T1_Init_Size,
+    (FTDriver_doneSize)             T1_Done_Size,
+    (FTDriver_setCharSizes)         Set_Char_Sizes,
+    (FTDriver_setPixelSizes)        Set_Pixel_Sizes,
+
+    (FTDriver_initGlyphSlot)        T1_Init_GlyphSlot,
+    (FTDriver_doneGlyphSlot)        T1_Done_GlyphSlot,
+    (FTDriver_loadGlyph)            T1_Load_Glyph,
+
+    (FTDriver_getCharIndex)         0,
+  };
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    getDriverInterface                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used when compiling the font driver as a          */
+  /*    shared library (`.DLL' or `.so').  It will be used by the          */
+  /*    high-level library of FreeType to retrieve the address of the      */
+  /*    driver's generic interface.                                        */
+  /*                                                                       */
+  /*    It shouldn't be implemented in a static build, as each driver must */
+  /*    have the same function as an exported entry point.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The address of the TrueType's driver generic interface.  The       */
+  /*    format-specific interface can then be retrieved through the method */
+  /*    interface->get_format_interface.                                   */
+  /*                                                                       */
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+  EXPORT_FUNC
+  FT_DriverInterface*  getDriverInterface( void )
+  {
+    return &t1_driver_interface;
+  }
+
+#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
--- /dev/null
+++ b/src/type1z/t1driver.h
@@ -1,0 +1,28 @@
+/*******************************************************************
+ *
+ *  t1driver.h
+ *
+ *    High-level Type1 driver interface for FreeType 2.0
+ *
+ *  Copyright 1996-1998 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ *  This file is part of the FreeType project, and may only be used,
+ *  modified, and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT.  By continuing to use, modify, or distribute 
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ ******************************************************************/
+
+#ifndef T1DRIVER_H
+#define T1DRIVER_H
+
+#include <t1objs.h>
+#include <t1errors.h>
+
+  EXPORT_DEF
+  const  FT_DriverInterface  t1_driver_interface;
+
+#endif /* T1DRIVER_H */
+
--- /dev/null
+++ b/src/type1z/t1encode.c
@@ -1,0 +1,332 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1encode.c                                                             */
+/*                                                                         */
+/*    Type 1 standard encoding tables definitions (body).                  */
+/*                                                                         */
+/*  Copyright 1996-1999 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used        */
+/*  modified and distributed under the terms of the FreeType project       */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*                                                                         */
+/*  This file is included by both the Type1 and Type2 driver.              */
+/*  It should never be compiled directly.                                  */
+/*                                                                         */
+/***************************************************************************/
+
+#include <ftobjs.h>
+#include <t1types.h>
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  t1_standard_strings:                                                 */
+  /*                                                                       */
+  /*     This array contains the Adobe Standard Glyph Names ordered by     */
+  /*     SID.  It was taken from the CFF specification.                    */
+  /*                                                                       */
+  LOCAL_FUNC
+  const T1_String*  t1_standard_strings[] =
+  {
+  /*   0 */
+    ".notdef", "space", "exclam", "quotedbl", "numbersign",
+    "dollar", "percent", "ampersand", "quoteright", "parenleft",
+  /*  10 */
+    "parenright", "asterisk", "plus", "comma", "hyphen",
+    "period", "slash", "zero", "one", "two",
+  /*  20 */
+    "three", "four", "five", "six", "seven",
+    "height", "nine", "colon", "semicolon", "less",
+  /*  30 */
+    "equal", "greater", "question", "at", "A",
+    "B", "C", "D", "E", "F",
+  /*  40 */
+    "G", "H", "I", "J", "K",
+    "L", "M", "N", "O", "P",
+  /*  50 */
+    "Q", "R", "S", "T", "U",
+    "V", "W", "X", "Y", "Z",
+  /*  60 */
+    "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
+    "quoteleft", "a", "b", "c", "d",
+  /*  70 */
+    "e", "f", "g", "h", "i",
+    "j", "k", "l", "m", "n",
+  /*  80 */
+    "o", "p", "q", "r", "s",
+    "t", "u", "v", "w", "x",
+  /*  90 */
+    "y", "z", "braceleft", "bar", "braceright",
+    "asciitilde", "exclamdown", "cent", "sterling", "fraction",
+  /* 100 */
+    "yen", "florin", "section", "currency", "quotesingle",
+    "quotedblleft", "quillemotleft", "guilsinglleft", "guilsinglright", "fi",
+  /* 110 */
+    "fl", "endash", "dagger", "daggerdbl", "periodcenter",
+    "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright",
+  /* 120 */
+    "quillemotright", "ellipsis", "perthousand", "questiondown", "grave",
+    "acute", "circumflex", "tilde", "macron", "breve",
+  /* 130 */
+    "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut",
+    "ogonek", "caron", "emdash", "AE", "ordfeminine",
+  /* 140 */
+    "Lslash", "Oslash", "OE", "ordmasculine", "ae",
+   "dotlessi", "Islash", "oslash", "oe", "germandbls",
+  /* 150 */
+    "onesuperior", "logicalnot", "mu", "trademark", "Eth",
+    "onehalf", "plusminus", "Thorn", "onequarter", "divide",
+  /* 160 */
+    "brokenbar", "degree", "thorn", "threequarters", "twosuperior",
+    "regitered", "minus", "eth", "multiply", "threesuperior",
+  /* 170 */
+    "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave",
+    "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex",
+  /* 180 */
+    "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis",
+    "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis",
+  /* 190 */
+    "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex",
+    "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron",
+  /* 200 */
+    "aacute", "acircumflex", "adieresis", "agrave", "aring",
+    "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis",
+  /* 210 */
+    "egrave", "iacute", "icircumflex", "idieresis", "igrave",
+    "ntilde", "oacute", "ocircumflex", "odieresis", "ograve",
+  /* 220 */
+    "otilde", "scaron", "uacute", "ucircumflex", "udieresis",
+    "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall",
+  /* 230 */
+    "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall",
+      "Acutesmall",
+    "parenleftsuperior", "parenrightsuperior", "twodotenleader",
+      "onedotenleader", "zerooldstyle",
+  /* 240 */
+    "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle",
+      "fiveoldstyle",
+    "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle",
+      "commasuperior",
+  /* 250 */
+    "threequartersemdash", "periodsuperior", "questionsmall", "asuperior",
+      "bsuperior",
+    "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior",
+  /* 260 */
+    "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior",
+    "tsuperior", "ff", "ffi", "ffl", "parenleftinferior",
+  /* 270 */
+    "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall",
+      "Asmall",
+    "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall",
+  /* 280 */
+    "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall",
+    "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall",
+  /* 290 */
+    "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall",
+    "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall",
+  /* 300 */
+    "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall",
+    "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall",
+      "Dieresissmall",
+  /* 310 */
+    "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash",
+    "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall",
+      "questiondownsmall",
+  /* 320 */
+    "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird",
+    "twothirds", "zerosuperior", "foursuperior", "fivesuperior",
+      "sixsuperior",
+  /* 330 */
+    "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior",
+      "oneinferior",
+    "twoinferior", "threeinferior", "fourinferior", "fiveinferior",
+      "sixinferior",
+  /* 340 */
+    "seveninferior", "eightinferior", "nineinferior", "centinferior",
+      "dollarinferior",
+    "periodinferior", "commainferior", "Agravesmall", "Aacutesmall",
+      "Acircumflexsmall",
+  /* 350 */
+    "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall",
+    "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall",
+      "Igravesmall",
+  /* 360 */
+    "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall",
+      "Ntildesmall",
+    "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall",
+      "Odieresissmall",
+  /* 370 */
+    "OEsmall", "Oslashsmall", "Ugravesmall", "Uacautesmall",
+      "Ucircumflexsmall",
+    "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall",
+      "001.000",
+  /* 380 */
+    "001.001", "001.002", "001.003", "Black", "Bold",
+    "Book", "Light", "Medium", "Regular", "Roman",
+  /* 390 */
+    "Semibold"
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  t1_standard_encoding:                                                */
+  /*                                                                       */
+  /*     A simple table used to encode the Adobe StandardEncoding.  The    */
+  /*     table values are the SID of the standard glyphs; the table index  */
+  /*     is the character code for the encoding.                           */
+  /*                                                                       */
+  /*     Example:                                                          */
+  /*                                                                       */
+  /*       t1_standard_encoding[33] == 2                                   */
+  /*                                                                       */
+  /*     which means that the glyph name for character code 32 is          */
+  /*                                                                       */
+  /*       t1_standard_strings[2] == "exclam"                              */
+  /*                                                                       */
+  /*     (this correspond to the exclamation mark `!').                    */
+  /*                                                                       */
+  LOCAL_FUNC
+  T1_Short  t1_standard_encoding[256] =
+  {
+  /*   0 */ 
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   1,   2,   3,   4,   5,   6,   7,   8,
+      9,  10,  11,  12,  13,  14,  15,  16,  17,  18,
+  /*  50 */
+     19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
+     29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
+     39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
+     49,  50,  51,  52,  53,  54,  55,  56,  57,  58,
+     59,  60,  61,  62,  63,  64,  65,  66,  67,  68,
+  /* 100 */
+     69,  70,  71,  72,  73,  74,  75,  76,  77,  78,
+     79,  80,  81,  82,  83,  84,  85,  86,  87,  88,
+     89,  90,  91,  92,  93,  94,  95,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  /* 150 */
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,  96,  97,  98,  99, 100, 101, 102, 103, 104,
+    105, 106, 107, 108, 109, 110,   0, 111, 112, 113,
+    114,   0, 115, 116, 117, 118, 119, 120, 121, 122,
+      0, 123,   0, 124, 125, 126, 127, 128, 129, 130,
+  /* 200 */
+    131,   0, 132, 133,   0, 134, 135, 136, 137,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0, 138,   0, 139,   0,   0,
+      0,   0, 140, 141, 142, 143,   0,   0,   0,   0,
+      0, 144,   0,   0,   0, 145,   0,   0, 146, 147,
+  /* 250 */
+    148, 149,   0,   0,   0,   0
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  t1_expert_encoding:                                                  */
+  /*                                                                       */
+  /*     A simple table used to encode the Adobe ExpertEncoding.  The      */
+  /*     table values are the SID of the standard glyphs; the table index  */
+  /*     is the character code for the encoding.                           */
+  /*                                                                       */
+  /*     Example:                                                          */
+  /*                                                                       */
+  /*       t1_expert_encoding[33] == 229                                   */
+  /*                                                                       */
+  /*     which means that the glyph name for character code 32 is          */
+  /*                                                                       */
+  /*       t1_standard_strings[229] == "exclamsmall"                       */
+  /*                                                                       */
+  LOCAL_FUNC
+  T1_Short  t1_expert_encoding[256] =
+  {
+  /*   0 */
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   1, 229, 230,   0, 231, 232, 233, 234,
+    235, 236, 237, 238,  13,  14,  15,  99, 239, 240,
+  /*  50 */
+    241, 242, 243, 244, 245, 246, 247, 248,  27,  28,
+    249, 250, 251, 252,   0, 253, 254, 255, 256, 257,
+      0,   0,   0, 258,   0,   0, 259, 260, 261, 262,
+      0,   0, 263, 264, 265,   0, 266, 109, 110, 267,
+    268, 269,   0, 270, 271, 272, 273, 274, 275, 276,
+  /* 100 */
+    277, 278, 279, 280, 281, 282, 283, 284, 285, 286,
+    287, 288, 289, 290, 291, 292, 293, 294, 295, 296,
+    297, 298, 299, 300, 301, 302, 303,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  /* 150 */
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0, 304, 305, 306,   0,   0, 307, 308, 309, 310,
+    311,   0, 312,   0,   0, 312,   0,   0, 314, 315,
+      0,   0, 316, 317, 318,   0,   0,   0, 158, 155,
+    163, 319, 320, 321, 322, 323, 324, 325,   0,   0,
+  /* 200 */
+    326, 150, 164, 169, 327, 328, 329, 330, 331, 332,
+    333, 334, 335, 336, 337, 338, 339, 340, 341, 342,
+    343, 344, 345, 346, 347, 348, 349, 350, 351, 352,
+    353, 354, 355, 356, 357, 358, 359, 360, 361, 362,
+    363, 364, 365, 366, 367, 368, 369, 370, 371, 372,
+  /* 250 */
+    373, 374, 375, 376, 377, 378
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  t1_expert_subset_encoding:                                           */
+  /*                                                                       */
+  /*     A simple table used to encode the Adobe ExpertEncoding subset     */
+  /*     defined in the CFF specification.  It will probably evolve into   */
+  /*     another form sooner or later, as we deal with charsets            */
+  /*     differently than with encodings.                                  */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Short  t1_expert_subset_encoding[256] =
+  {
+  /*   0 */
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   1,   0,   0,   0, 231, 232,   0,   0,
+    235, 236, 237, 238,  13,  14,  15,  99, 239, 240,
+  /*  50 */
+    241, 242, 243, 244, 245, 246, 247, 248,  27,  28,
+    249, 250, 251, 252,   0, 253, 254, 255, 256, 257,
+      0,   0,   0, 258,   0,   0, 259, 260, 261, 262,
+      0,   0, 263, 264, 265,   0, 266, 109, 110, 267,
+    268, 269,   0, 270,   0, 272,   0,   0,   0,   0,
+  /* 100 */
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0, 300, 301, 302, 303,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  /* 150 */
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0, 304, 305,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0, 314, 315,
+      0,   0,   0,   0,   0,   0,   0,   0, 158, 155,
+    163,   0, 320, 321, 322, 323, 324, 325,   0,   0,
+  /* 200 */
+    326, 150, 164, 169, 327, 328, 329, 330, 331, 332,
+    333, 334, 335, 336, 337, 338, 339, 340, 341, 342,
+    343, 344, 345, 346,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  /* 250 */
+      0,   0,   0,   0,   0,   0
+  };
+
+
+/* END */
--- /dev/null
+++ b/src/type1z/t1encode.h
@@ -1,0 +1,98 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1encode.h                                                             */
+/*                                                                         */
+/*    Type 1 standard encoding tables definitions (specification).         */
+/*                                                                         */
+/*  Copyright 1996-1999 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used        */
+/*  modified and distributed under the terms of the FreeType project       */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*                                                                         */
+/*  This file is included by both the Type1 and Type2 driver.              */
+/*  It should never be compiled directly.                                  */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef T1ENCODE_H
+#define T1ENCODE_H
+
+#include <t1types.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  t1_standard_strings:                                                 */
+  /*                                                                       */
+  /*     This array contains the Adobe Standard Glyph Names ordered by     */
+  /*     SID.  It was taken from the CFF specification.                    */
+  /*                                                                       */
+  LOCAL_DEF
+  const T1_String*  t1_standard_strings[];
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  t1_standard_encoding:                                                */
+  /*                                                                       */
+  /*     A simple table used to encode the Adobe StandardEncoding.  The    */
+  /*     table values are the SID of the standard glyphs; the table index  */
+  /*     is the character code for the encoding.                           */
+  /*                                                                       */
+  /*     Example:                                                          */
+  /*                                                                       */
+  /*       t1_standard_encoding[33] == 2                                   */
+  /*                                                                       */
+  /*     which means that the glyph name for character code 33 is          */
+  /*                                                                       */
+  /*       t1_standard_strings[2] == "exclam"                              */
+  /*                                                                       */
+  /*     (this correspond to the exclamation mark `!').                    */
+  /*                                                                       */
+  LOCAL_DEF
+  T1_Short  t1_standard_encoding[256];
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  t1_expert_encoding:                                                  */
+  /*                                                                       */
+  /*     A simple table used to encode the Adobe ExpertEncoding.  The      */
+  /*     table values are the SID of the standard glyphs; the table index  */
+  /*     is the character code for the encoding.                           */
+  /*                                                                       */
+  /*     Example:                                                          */
+  /*                                                                       */
+  /*       t1_expert_encoding[33] == 229                                   */
+  /*                                                                       */
+  /*     which means that the glyph name for character code 33 is          */
+  /*                                                                       */
+  /*       t1_standard_strings[229] == "exclamsmall"                       */
+  /*                                                                       */
+  LOCAL_DEF
+  T1_Short  t1_expert_encoding[256];
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  t1_expert_subset_encoding:                                           */
+  /*                                                                       */
+  /*     A simple table used to encode the Adobe ExpertEncoding subset     */
+  /*     defined in the CFF specification.  It will probably evolve into   */
+  /*     another form sooner or later, as we deal with charsets            */
+  /*     differently than with encodings.                                  */
+  /*                                                                       */
+  LOCAL_DEF
+  T1_Short  t1_expert_subset_encoding[256];
+
+
+#endif /* T1ENCODE_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1z/t1errors.h
@@ -1,0 +1,75 @@
+/*******************************************************************
+ *
+ *  t1errors.h
+ *
+ *    Type1 Error ID definitions
+ *
+ *  Copyright 1996-1998 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ *  This file is part of the FreeType project, and may only be used
+ *  modified and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ ******************************************************************/
+
+#ifndef T1ERRORS_H
+#define T1ERRORS_H
+
+#include <fterrors.h>
+
+  /************************ error codes declaration **************/
+
+  /* The error codes are grouped in 'classes' used to indicate the */
+  /* 'level' at which the error happened.                          */
+  /* The class is given by an error code's high byte.              */
+
+
+/* ------------- Success is always 0 -------- */
+
+#define  T1_Err_Ok                       FT_Err_Ok
+
+/* ----------- high level API errors -------- */
+  
+#define  T1_Err_Invalid_File_Format      FT_Err_Invalid_File_Format
+#define  T1_Err_Invalid_Argument         FT_Err_Invalid_Argument
+#define  T1_Err_Invalid_Driver_Handle    FT_Err_Invalid_Driver_Handle
+#define  T1_Err_Invalid_Face_Handle      FT_Err_Invalid_Face_Handle
+#define  T1_Err_Invalid_Size_Handle      FT_Err_Invalid_Size_Handle
+#define  T1_Err_Invalid_Glyph_Handle     FT_Err_Invalid_Slot_Handle
+#define  T1_Err_Invalid_CharMap_Handle   FT_Err_Invalid_CharMap_Handle
+#define  T1_Err_Invalid_Glyph_Index      FT_Err_Invalid_Glyph_Index
+
+#define  T1_Err_Unimplemented_Feature    FT_Err_Unimplemented_Feature
+#define  T1_Err_Unavailable_Outline      FT_Err_Unavailable_Outline
+#define  T1_Err_Unavailable_Bitmap       FT_Err_Unavailable_Bitmap
+#define  T1_Err_Unavailable_Pixmap       FT_Err_Unavailable_Pixmap
+#define  T1_Err_File_Is_Not_Collection   FT_Err_File_Is_Not_Collection
+
+#define  T1_Err_Invalid_Engine           FT_Err_Invalid_Driver_Handle
+
+/* ------------- internal errors ------------ */
+  
+#define  T1_Err_Out_Of_Memory            FT_Err_Out_Of_Memory
+#define  T1_Err_Unlisted_Object          FT_Err_Unlisted_Object
+
+/* ------------ general glyph outline errors ------ */
+
+#define  T1_Err_Too_Many_Points          FT_Err_Too_Many_Points
+#define  T1_Err_Too_Many_Contours        FT_Err_Too_Many_Contours
+#define  T1_Err_Too_Many_Hints           FT_Err_Too_Many_Hints
+#define  T1_Err_Invalid_Composite        FT_Err_Invalid_Composite
+#define  T1_Err_Too_Many_Edges           FT_Err_Too_Many_Edges
+#define  T1_Err_Too_Many_Strokes         FT_Err_Too_Many_Strokes
+
+
+#define  T1_Err_Syntax_Error             FT_Err_Invalid_File_Format
+#define  T1_Err_Stack_Underflow          FT_Err_Invalid_File_Format
+#define  T1_Err_Stack_Overflow           FT_Err_Invalid_File_Format
+
+#endif /* TDERRORS_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1z/t1gload.c
@@ -1,0 +1,1582 @@
+/*******************************************************************
+ *
+ *  t1gload.c                                                   1.0
+ *
+ *    Type1 Glyph Loader.
+ *
+ *  Copyright 1996-1999 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ *  This file is part of the FreeType project, and may only be used
+ *  modified and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ ******************************************************************/
+
+#include <t1gload.h>
+#include <ftdebug.h>
+#include <t1encode.h>
+#include <ftstream.h>
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+#include <t1hinter.h>
+#endif
+
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********                                                   *********/
+  /**********                                                   *********/
+  /**********           GENERIC CHARSTRINGS PARSING             *********/
+  /**********                                                   *********/
+  /**********                                                   *********/
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********************************************************************/
+
+/*********************************************************************
+ *
+ * <Function>
+ *    T1_Init_Builder
+ *
+ * <Description>
+ *    Initialise a given glyph builder.
+ *
+ * <Input>
+ *    builder :: glyph builder to initialise
+ *    face    :: current face object
+ *    size    :: current size object
+ *    glyph   :: current glyph object
+ *    funcs   :: glyph builder functions (or "methods").
+ *
+ *********************************************************************/
+
+  EXPORT_FUNC
+  void  T1_Init_Builder( T1_Builder*             builder,
+                         T1_Face                 face,
+                         T1_Size                 size,
+                         T1_GlyphSlot            glyph,
+                         const T1_Builder_Funcs* funcs )
+  {
+    builder->funcs       = *funcs;
+    builder->path_begun  = 0;
+    builder->load_points = 1;
+
+    builder->face   = face;
+    builder->size   = size;
+    builder->glyph  = glyph;
+    builder->memory = face->root.memory;
+
+    if (glyph)
+    {
+      builder->base         = glyph->root.outline;
+      builder->max_points   = glyph->max_points;
+      builder->max_contours = glyph->max_contours;
+    }
+
+    if (size)
+    {
+      builder->scale_x = size->root.metrics.x_scale;
+      builder->scale_y = size->root.metrics.y_scale;
+    }
+
+    builder->pos_x = 0;
+    builder->pos_y = 0;
+
+    builder->left_bearing.x = 0;
+    builder->left_bearing.y = 0;
+    builder->advance.x      = 0;
+    builder->advance.y      = 0;
+
+    builder->base.n_points   = 0;
+    builder->base.n_contours = 0;
+    builder->current         = builder->base;
+
+    builder->pass       = 0;
+    builder->hint_point = 0;
+  }
+
+
+/*********************************************************************
+ *
+ * <Function>
+ *    T1_Done_Builder
+ *
+ * <Description>
+ *    Finalise a given glyph builder. Its content can still be
+ *    used after the call, but the function saves important information
+ *    within the corresponding glyph slot.
+ *
+ * <Input>
+ *    builder :: glyph builder to initialise
+ *
+ *********************************************************************/
+
+  EXPORT_FUNC
+  void T1_Done_Builder( T1_Builder*  builder )
+  {
+    T1_GlyphSlot  glyph = builder->glyph;
+
+    if (glyph)
+    {
+      glyph->root.outline = builder->base;
+      glyph->max_points   = builder->max_points;
+      glyph->max_contours = builder->max_contours;
+    }
+  }
+
+
+
+/*********************************************************************
+ *
+ * <Function>
+ *    T1_Init_Decoder
+ *
+ * <Description>
+ *    Initialise a given Type 1 decoder for parsing
+ *
+ * <Input>
+ *    decoder :: Type 1 decoder to initialise
+ *    funcs   :: hinter functions interface
+ *
+ *********************************************************************/
+
+  EXPORT_FUNC
+  void  T1_Init_Decoder( T1_Decoder*             decoder,
+                         const T1_Hinter_Funcs*  funcs )
+  {
+    decoder->hinter = *funcs;    /* copy hinter interface */
+    decoder->top    = 0;
+    decoder->zone   = 0;
+
+    decoder->flex_state       = 0;
+    decoder->num_flex_vectors = 0;
+
+    /* Clear loader */
+    MEM_Set( &decoder->builder, 0, sizeof(decoder->builder) );
+  }
+
+
+/*********************************************************************
+ *
+ * <Function>
+ *    lookup_glyph_by_stdcharcode
+ *
+ * <Description>
+ *    Lookup a given glyph by its StandardEncoding charcode. Used
+ *    to implement the SEAC Type 1 operator.
+ *
+ * <Input>
+ *    face     :: current face object         
+ *    charcode :: charcode to look for
+ *
+ * <Return>
+ *    glyph index in font face. Returns -1 if the corresponding
+ *    glyph wasn't found.
+ *
+ *********************************************************************/
+
+  static
+  T1_Int    lookup_glyph_by_stdcharcode( T1_Face  face,
+                                         T1_Int   charcode )
+  {
+    T1_Int            n;
+    const T1_String*  glyph_name;
+    
+    /* check range of standard char code */
+    if (charcode < 0 || charcode > 255)
+      return -1;
+      
+    glyph_name = t1_standard_strings[t1_standard_encoding[charcode]];
+    
+    for ( n = 0; n < face->type1.num_glyphs; n++ )
+    {
+      T1_String*  name = (T1_String*)face->type1.glyph_names[n];
+      
+      if ( name && strcmp(name,glyph_name) == 0 )
+        return n;
+    }
+
+    return -1;
+  }
+
+
+/*********************************************************************
+ *
+ * <Function>
+ *    t1operator_seac
+ *
+ * <Description>
+ *    Implements the "seac" Type 1 operator for a Type 1 decoder
+ *
+ * <Input>
+ *    decoder  :: current Type 1 decoder
+ *    asb      :: accent's side bearing
+ *    adx      :: horizontal position of accent
+ *    ady      :: vertical position of accent
+ *    bchar    :: base character's StandardEncoding charcode
+ *    achar    :: accent character's StandardEncoding charcode
+ *
+ * <Return>
+ *    Error code. 0 means success.                               
+ *
+ *********************************************************************/
+
+  static
+  T1_Error  t1operator_seac( T1_Decoder*  decoder,
+                             T1_Pos       asb,
+                             T1_Pos       adx,
+                             T1_Pos       ady,
+                             T1_Int       bchar,
+                             T1_Int       achar )
+  {
+    T1_Error     error;
+    T1_Face      face = decoder->builder.face;
+    T1_Int       bchar_index, achar_index, n_base_points;
+    FT_Outline*  cur  = &decoder->builder.current;
+    FT_Outline*  base = &decoder->builder.base;
+    T1_Vector    left_bearing, advance;
+    T1_Font*     type1 = &face->type1;
+    
+    bchar_index = lookup_glyph_by_stdcharcode( face, bchar );
+    achar_index = lookup_glyph_by_stdcharcode( face, achar );
+    
+    if (bchar_index < 0 || achar_index < 0)
+    {
+      FT_ERROR(( "T1.Parse_Seac : invalid seac character code arguments\n" ));
+      return T1_Err_Syntax_Error;
+    }
+
+    /* First load "bchar" in builder */
+    /* now load the unscaled outline */
+    cur->n_points   = 0;
+    cur->n_contours = 0;
+    cur->points     = base->points   + base->n_points;
+    cur->flags      = base->flags    + base->n_points;
+    cur->contours   = base->contours + base->n_contours;
+
+    error = T1_Parse_CharStrings( decoder,
+                                  type1->charstrings    [bchar_index],
+                                  type1->charstrings_len[bchar_index],
+                                  type1->num_subrs,
+                                  type1->subrs,
+                                  type1->subrs_len );
+    if (error) return error;
+
+    n_base_points   = cur->n_points;
+
+    /* save the left bearing and width of the base character */
+    /* as they will be erase by the next load..              */
+    left_bearing = decoder->builder.left_bearing;
+    advance      = decoder->builder.advance;
+
+    decoder->builder.left_bearing.x = 0;
+    decoder->builder.left_bearing.y = 0;    
+
+    /* Now load "achar" on top of */
+    /* the base outline           */
+    /*                            */ 
+    cur->n_points   = 0;
+    cur->n_contours = 0;
+    cur->points     = base->points   + base->n_points;
+    cur->flags      = base->flags    + base->n_points;
+    cur->contours   = base->contours + base->n_contours;
+
+    error = T1_Parse_CharStrings( decoder,
+                                  type1->charstrings    [achar_index],
+                                  type1->charstrings_len[achar_index],
+                                  type1->num_subrs,
+                                  type1->subrs,
+                                  type1->subrs_len );
+    if (error) return error;
+
+    /* adjust contours in accented character outline */
+    {
+      T1_Int  n;
+
+      for ( n = 0; n < cur->n_contours; n++ )
+        cur->contours[n] += n_base_points;
+    }
+
+    /* restore the left side bearing and   */
+    /* advance width of the base character */
+    decoder->builder.left_bearing = left_bearing;
+    decoder->builder.advance      = advance;
+
+    /* Finally, move the accent */
+    FT_Translate_Outline( cur, adx - asb, ady );
+    
+    (void)asb;           /* ignore this parameter */
+    return T1_Err_Ok;
+  }
+
+/*********************************************************************
+ *
+ * <Function>
+ *    t1operator_flex
+ *
+ * <Description>
+ *    Implements the "flex" Type 1 operator for a Type 1 decoder
+ *
+ * <Input>
+ *    decoder   :: current Type 1 decoder
+ *    threshold :: threshold
+ *    end_x     :: position of final flex point
+ *    end_y     :: position of final flex point
+ *
+ * <Return>
+ *    Error code. 0 means success.                               
+ *
+ *********************************************************************/
+
+  static
+  T1_Error  t1operator_flex( T1_Decoder*  decoder,
+                             T1_Pos       threshold,
+                             T1_Pos       end_x,
+                             T1_Pos       end_y )
+  {
+    T1_Vector    vec;
+    T1_Vector*   flex  = decoder->flex_vectors;
+    T1_Int       n;
+
+    /* we don't even try to test the threshold in the non-hinting  */
+    /* builder, even if the flex operator is said to be a path      */
+    /* construction statement in the specification. This is better */
+    /* left to the hinter..                                        */
+
+    flex = decoder->flex_vectors;
+    vec  = *flex++;
+
+    for ( n = 0; n < 6; n++ )
+    {
+      flex->x += vec.x;
+      flex->y += vec.y;
+
+      vec = *flex++;
+    }
+
+
+    (void)threshold;
+    (void)end_x;
+    (void)end_y;
+
+    flex  = decoder->flex_vectors;
+
+    return  decoder->builder.funcs.rcurve_to( &decoder->builder,
+                                              flex[0].x, flex[0].y,
+                                              flex[1].x, flex[1].y,
+                                              flex[2].x, flex[2].y ) ||
+
+            decoder->builder.funcs.rcurve_to( &decoder->builder,
+                                              flex[3].x, flex[3].y,
+                                              flex[4].x, flex[4].y,
+                                              flex[5].x, flex[5].y );
+  }
+
+
+/*********************************************************************
+ *
+ * <Function>
+ *    T1_Parse_CharStrings
+ *
+ * <Description>
+ *    Parses a given Type 1 charstrings program
+ *
+ * <Input>
+ *    decoder          :: current Type 1 decoder
+ *    charstring_base  :: base of the charstring stream
+ *    charstring_len   :: length in bytes of the charstring stream
+ *    num_subrs        :: number of sub-routines
+ *    subrs_base       :: array of sub-routines addresses
+ *    subrs_len        :: array of sub-routines lengths
+ *
+ * <Return>
+ *    Error code. 0 means success.                               
+ *
+ *********************************************************************/
+
+  EXPORT_FUNC
+  T1_Error   T1_Parse_CharStrings( T1_Decoder*  decoder,
+                                   T1_Byte*     charstring_base,
+                                   T1_Int       charstring_len,
+                                   T1_Int       num_subrs,
+                                   T1_Byte**    subrs_base,
+                                   T1_Int*      subrs_len )
+  {
+    T1_Error            error;
+    T1_Decoder_Zone*    zone;
+    T1_Byte*            ip;
+    T1_Byte*            limit;
+    T1_Builder*         builder = &decoder->builder;
+    T1_Builder_Funcs*   builds  = &builder->funcs;
+    T1_Hinter_Funcs*    hints   = &decoder->hinter;
+
+    static const T1_Int  args_count[ op_max ] = 
+    {
+      0, /* none */
+      0, /* endchar */
+      2, /* hsbw */
+      5, /* seac */
+      4, /* sbw */
+      0, /* closepath */
+      1, /* hlineto */
+      1, /* hmoveto */
+      4, /* hvcurveto */
+      2, /* rlineto */
+      2, /* rmoveto */
+      6, /* rrcurveto */
+      4, /* vhcurveto */
+      1, /* vlineto */
+      1, /* vmoveto */
+      0, /* dotsection */
+      2, /* hstem */
+      6, /* hstem3 */
+      2, /* vstem */
+      6, /* vstem3 */
+      2, /* div */
+     -1, /* callothersubr */
+      1, /* callsubr */
+      0, /* pop */
+      0, /* return */
+      2  /* setcurrentpoint */
+    };
+
+    /* First of all, initialise the decoder */
+    decoder->top  = decoder->stack;
+    decoder->zone = decoder->zones;
+    zone          = decoder->zones;
+
+    builder->path_begun  = 0;
+
+    zone->base           = charstring_base;
+    limit = zone->limit  = charstring_base + charstring_len;
+    ip    = zone->cursor = zone->base;
+
+    error = T1_Err_Ok;
+
+    /* now, execute loop */
+    while ( ip < limit )
+    {
+      T1_Int*      top      = decoder->top;
+      T1_Operator  op       = op_none;
+      T1_Long      value    = 0;
+
+      /* First of all, decompress operator or value */
+      switch (*ip++)
+      {
+        case 1:  op = op_hstem;     break;
+
+        case 3:  op = op_vstem;     break;
+        case 4:  op = op_vmoveto;   break;
+        case 5:  op = op_rlineto;   break;
+        case 6:  op = op_hlineto;   break;
+        case 7:  op = op_vlineto;   break;
+        case 8:  op = op_rrcurveto; break;
+        case 9:  op = op_closepath; break;
+        case 10: op = op_callsubr;  break;
+        case 11: op = op_return;    break;
+
+        case 13: op = op_hsbw;      break;
+        case 14: op = op_endchar;   break;
+
+        case 21: op = op_rmoveto;   break;
+        case 22: op = op_hmoveto;   break;
+
+        case 30: op = op_vhcurveto; break;
+        case 31: op = op_hvcurveto; break;
+
+        case 12:
+          {
+            if (ip > limit)
+            {
+              FT_ERROR(( "T1.Parse_CharStrings : invalid escape (12+EOF)\n" ));
+              goto Syntax_Error;
+            }
+
+            switch (*ip++)
+            {
+              case 0:  op = op_dotsection;      break;
+              case 1:  op = op_vstem3;          break;
+              case 2:  op = op_hstem3;          break;
+              case 6:  op = op_seac;            break;
+              case 7:  op = op_sbw;             break;
+              case 12: op = op_div;             break;
+              case 16: op = op_callothersubr;   break;
+              case 17: op = op_pop;             break;
+              case 33: op = op_setcurrentpoint; break;
+
+              default:
+                FT_ERROR(( "T1.Parse_CharStrings : invalid escape (12+%d)\n",
+                         ip[-1] ));
+                goto Syntax_Error;
+            }
+          }
+          break;
+
+        case 255:    /* four bytes integer */
+          {
+            if (ip+4 > limit)
+            {
+              FT_ERROR(( "T1.Parse_CharStrings : unexpected EOF in integer\n" ));
+              goto Syntax_Error;
+            }
+
+            value = ((long)ip[0] << 24) |
+                    ((long)ip[1] << 16) |
+                    ((long)ip[2] << 8)  |
+                           ip[3];
+            ip += 4;
+          }
+          break;
+
+        default:
+          if (ip[-1] >= 32)
+          {
+            if (ip[-1] < 247)
+              value = (long)ip[-1] - 139;
+            else
+            {
+              if (++ip > limit)
+              {
+                FT_ERROR(( "T1.Parse_CharStrings : unexpected EOF in integer\n" ));
+                goto Syntax_Error;
+              }
+
+              if (ip[-2] < 251)
+                value =  ((long)(ip[-2]-247) << 8) + ip[-1] + 108;
+              else
+                value = -((((long)ip[-2]-251) << 8) + ip[-1] + 108 );
+            }
+          }
+          else
+          {
+            FT_ERROR(( "T1.Parse_CharStrings : invalid byte (%d)\n",
+                     ip[-1] ));
+            goto Syntax_Error;
+          }
+      }
+
+      /* push value if needed */
+      if ( op == op_none )
+      {
+        if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
+        {
+          FT_ERROR(( "T1.Parse_CharStrings : Stack overflow !!\n" ));
+          goto Syntax_Error;
+        }
+
+        *top++       = value;
+        decoder->top = top;
+      }
+
+      else if ( op == op_callothersubr ) /* check arguments differently */
+      {
+        if ( top - decoder->stack < 2)
+          goto Stack_Underflow;
+
+        top -= 2;
+
+        switch (top[1])
+        {
+          case 1:   /* start flex feature ----------------------------- */
+            {
+              if (top[0] != 0) goto Unexpected_OtherSubr;
+
+              decoder->flex_state        = 1;
+              decoder->num_flex_vectors  = 0;
+              decoder->flex_vectors[0].x = 0;
+              decoder->flex_vectors[0].y = 0;
+            }
+            break;
+
+
+          case 2:   /* add flex vector ------------------------------- */
+            {
+              T1_Int      index;
+              T1_Vector*  flex;
+
+              if (top[0] != 0) goto Unexpected_OtherSubr;
+
+              top -= 2;
+              if (top < decoder->stack) goto Stack_Underflow;
+
+              index = decoder->num_flex_vectors++;
+              if (index >= 7)
+              {
+                FT_ERROR(( "T1.Parse_CharStrings: too many flex vectors !\n" ));
+                goto Syntax_Error;
+              }
+
+              flex = decoder->flex_vectors + index;
+              flex->x += top[0];
+              flex->y += top[1];
+
+            }
+            break;
+
+
+          case 0:   /* end flex feature ------------------------------ */
+            {
+              if ( decoder->flex_state       == 0 ||
+                   decoder->num_flex_vectors != 7 )
+              {
+                FT_ERROR(( "T1.Parse_CharStrings: unexpected flex end\n" ));
+                goto Syntax_Error;
+              }
+
+              if (top[0] != 3) goto Unexpected_OtherSubr;
+
+              top -= 3;
+              if (top < decoder->stack) goto Stack_Underflow;
+
+              /* now consume the remaining "pop pop setcurrentpoint" */
+              if ( ip+6 > limit ||
+                   ip[0] != 12  || ip[1] != 17 ||   /* pop */
+                   ip[2] != 12  || ip[3] != 17 ||   /* pop */
+                   ip[4] != 12  || ip[5] != 33 )    /* setcurrentpoint */
+              {
+                FT_ERROR(( "T1.Parse_CharStrings: invalid flex charstring\n" ));
+                goto Syntax_Error;
+              }
+
+              decoder->flex_state = 0;
+              decoder->top        = top;
+
+              error = t1operator_flex( decoder, top[0], top[1], top[2] );
+            }
+            break;
+
+
+          case 3:  /* change hints ------------------------------------ */
+            {
+              if (top[0] != 1) goto Unexpected_OtherSubr;
+
+              /* eat the following "pop" */
+              if (ip+2 > limit)
+              {
+                FT_ERROR(( "T1.Parse_CharStrings: invalid escape (12+%d)\n",
+                         ip[-1] ));
+                goto Syntax_Error;
+              }
+
+              if (ip[0] != 12 || ip[1] != 17)
+              {
+                FT_ERROR(( "T1.Parse_CharStrings: 'pop' expected, found (%d %d)\n",
+                         ip[0], ip[1] ));
+                goto Syntax_Error;
+              }
+
+              ip    += 2;
+              error  = hints->change_hints(builder);
+            }
+            break;
+
+
+          default:
+            /* invalid OtherSubrs call */
+          Unexpected_OtherSubr:
+            FT_ERROR(( "T1.Parse_CharStrings: unexpected OtherSubrs [%d %d]\n",
+                     top[0], top[1] ));
+            goto Syntax_Error;
+        }
+        decoder->top = top;
+      }
+      else
+      {
+        T1_Int  num_args = args_count[op];
+
+        if ( top - decoder->stack < num_args )
+          goto Stack_Underflow;
+
+        top -= num_args;
+
+        switch (op)
+        {
+          case op_endchar:
+            error = builds->end_char( builder );
+            break;
+
+          case op_hsbw:
+            error = builds->set_bearing_point( builder, top[0], 0,
+                                                        top[1], 0 );
+            break;
+
+          case op_seac:
+            /* return immediately after the processing */
+            return t1operator_seac( decoder, top[0], top[1],
+                                             top[2], top[3], top[4] );
+
+          case op_sbw:
+            error = builds->set_bearing_point( builder, top[0], top[1],
+                                                        top[2], top[3] );
+            break;
+
+          case op_closepath:
+            error = builds->close_path( builder );
+            break;
+
+          case op_hlineto:
+            error = builds->rline_to( builder, top[0], 0 );
+            break;
+
+          case op_hmoveto:
+            error = builds->rmove_to( builder, top[0], 0 );
+            break;
+
+          case op_hvcurveto:
+            error = builds->rcurve_to( builder, top[0], 0,
+                                                top[1], top[2],
+                                                0,      top[3] );
+            break;
+
+          case op_rlineto:
+            error = builds->rline_to( builder, top[0], top[1] );
+            break;
+
+          case op_rmoveto:
+            /* ignore operator when in flex mode */
+            if (decoder->flex_state == 0)
+              error = builds->rmove_to( builder, top[0], top[1] );
+            else
+              top += 2;
+            break;
+
+          case op_rrcurveto:
+            {
+              error = builds->rcurve_to( builder, top[0], top[1],
+                                                  top[2], top[3],
+                                                  top[4], top[5] );
+            }
+            break;
+
+          case op_vhcurveto:
+            error = builds->rcurve_to( builder,      0, top[0],
+                                                top[1], top[2],
+                                                top[3],      0 );
+            break;
+
+          case op_vlineto:
+            error = builds->rline_to( builder, 0, top[0] );
+            break;
+
+          case op_vmoveto:
+            error = builds->rmove_to( builder, 0, top[0] );
+            break;
+
+          case op_dotsection:
+            error = hints->dot_section( builder );
+            break;
+
+          case op_hstem:
+            error = hints->stem( builder, top[0], top[1], 0 );
+            break;
+
+          case op_hstem3:
+            error = hints->stem3( builder, top[0], top[1], top[2],
+                                           top[3], top[4], top[5], 0 );
+            break;
+
+          case op_vstem:
+            error = hints->stem( builder, top[0], top[1], 1 );
+            break;
+
+          case op_vstem3:
+            error = hints->stem3( builder, top[0], top[1], top[2],
+                                           top[3], top[4], top[5], 1 );
+            break;
+
+          case op_div:
+            if (top[1])
+              *top++ = top[0] / top[1];
+            else
+            {
+              FT_ERROR(( "T1.Parse_CHarStrings : division by 0\n" ));
+              goto Syntax_Error;
+            }
+            break;
+
+          case op_callsubr:
+            {
+              T1_Int  index = top[0];
+
+              if ( index < 0 || index >= num_subrs )
+              {
+                FT_ERROR(( "T1.Parse_CharStrings : invalid subrs index\n" ));
+                goto Syntax_Error;
+              }
+
+              if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
+              {
+                FT_ERROR(( "T1.Parse_CharStrings : too many nested subrs\n" ));
+                goto Syntax_Error;
+              }
+
+              zone->cursor = ip;  /* save current instruction pointer */
+
+              zone++;
+              zone->base    = subrs_base[index];
+              zone->limit   = zone->base + subrs_len[index];
+              zone->cursor  = zone->base;
+
+              if (!zone->base)
+              {
+                FT_ERROR(( "T1.Parse_CharStrings : invoking empty subrs !!\n" ));
+                goto Syntax_Error;
+              }
+
+              decoder->zone = zone;
+              ip            = zone->base;
+              limit         = zone->limit;
+            }
+            break;
+
+          case op_pop:
+            FT_ERROR(( "T1.Parse_CharStrings : unexpected POP\n" ));
+            goto Syntax_Error;
+
+
+          case op_return:
+            if ( zone <= decoder->zones )
+            {
+              FT_ERROR(( "T1.Parse_CharStrings : unexpected return\n" ));
+              goto Syntax_Error;
+            }
+
+            zone--;
+            ip            = zone->cursor;
+            limit         = zone->limit;
+            decoder->zone = zone;
+            break;
+
+          case op_setcurrentpoint:
+            FT_ERROR(( "T1.Parse_CharStrings : unexpected SETCURRENTPOINT\n" ));
+            goto Syntax_Error;
+            break;
+
+          default:
+            FT_ERROR(( "T1.Parse_CharStrings : unhandled opcode %d\n", op ));
+            goto Syntax_Error;
+        }
+
+        decoder->top = top;
+      }
+    }
+
+    return error;
+
+  Syntax_Error:
+    return T1_Err_Syntax_Error;
+
+  Stack_Underflow:
+    return T1_Err_Stack_Underflow;
+  }
+
+
+
+/*************************************************************************/
+/*                                                                       */
+/* <Function> T1_Add_Points                                              */
+/*                                                                       */
+/* <Description>                                                         */
+/*    Checks that there is enough room in the current load glyph outline */
+/*    to accept "num_points" additional outline points. If not, this     */
+/*    function grows the load outline's arrays accordingly..             */
+/*                                                                       */
+/* <Input>                                                               */
+/*    builder    :: pointer to glyph builder object                      */
+/*    num_points :: number of points that will be added later            */
+/*                                                                       */
+/* <Return>                                                              */
+/*    Type1 error code. 0 means success                                  */
+/*                                                                       */
+/* <Note>                                                                */
+/*    This function does NOT update the points count in the glyph builder*/
+/*    This must be done by the caller itself, after this function is     */
+/*    invoked..                                                          */
+/*                                                                       */
+  LOCAL_FUNC
+  T1_Error  T1_Add_Points( T1_Builder*  builder,
+                           T1_Int       num_points )
+  {
+    T1_Int    new_points;
+
+    new_points = builder->base.n_points +
+                 builder->current.n_points +
+                 num_points;
+
+    if ( new_points > builder->max_points )
+    {
+      FT_Memory  memory    = builder->memory;
+      T1_Error   error;
+      T1_Int     increment = builder->current.points - builder->base.points;
+      T1_Int     current   = builder->max_points;
+
+      while ( builder->max_points < new_points )
+        builder->max_points += 16;
+
+      if ( REALLOC_ARRAY( builder->base.points,
+                          current, builder->max_points, T1_Vector )  ||
+  
+           REALLOC_ARRAY( builder->base.flags,
+                          current, builder->max_points, T1_Byte )    )
+        return error;
+    
+      builder->current.points = builder->base.points + increment;
+      builder->current.flags  = builder->base.flags  + increment;
+    }
+
+    return T1_Err_Ok;
+  }
+
+/*************************************************************************/
+/*                                                                       */
+/* <Function> T1_Add_Contours                                            */
+/*                                                                       */
+/* <Description>                                                         */
+/*    Checks that there is enough room in the current load glyph outline */
+/*    to accept "num_contours" additional contours. If not, this func    */
+/*    the load outline's arrays accordingly..                            */
+/*                                                                       */
+/* <Input>                                                               */
+/*    builder       :: pointer to glyph builder object                   */
+/*    num_contours :: number of contours that will be added later        */
+/*                                                                       */
+/* <Return>                                                              */
+/*    Type1 error code. 0 means success                                  */
+/*                                                                       */
+/* <Note>                                                                */
+/*    This function does NOT update the contours count in the load glyph */
+/*    This must be done by the caller itself, after this function is     */
+/*    invoked..                                                          */
+/*                                                                       */
+  LOCAL_FUNC
+  T1_Error  T1_Add_Contours( T1_Builder*  builder,
+                             T1_Int       num_contours )
+  {
+    T1_Int    new_contours;
+
+    new_contours = builder->base.n_contours +
+                   builder->current.n_contours +
+                   num_contours;
+
+    if ( new_contours > builder->max_contours && builder->load_points )
+    {
+      T1_Error  error;
+      FT_Memory memory = builder->memory;
+      T1_Int    increment = builder->current.contours - builder->base.contours;
+      T1_Int    current   = builder->max_contours;
+
+      while ( builder->max_contours < new_contours )
+        builder->max_contours += 4;
+
+      if ( REALLOC_ARRAY( builder->base.contours,
+                          current, builder->max_contours, T1_Short ) )
+        return error;
+  
+      builder->current.contours = builder->base.contours + increment;
+    }
+
+    return T1_Err_Ok;
+  }
+
+
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********                                                   *********/
+  /**********                                                   *********/
+  /**********           COMPUTE THE MAXIMUM ADVANCE WIDTH       *********/
+  /**********                                                   *********/
+  /**********   The following code is in charge of computing    *********/
+  /**********   the maximum advance width of the font. It       *********/
+  /**********   quickly process each glyph charstring to        *********/
+  /**********   extract the value from either a "sbw" or "seac" *********/
+  /**********   operator.                                       *********/
+  /**********                                                   *********/
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********************************************************************/
+
+
+
+  static
+  T1_Error  maxadv_sbw( T1_Decoder*  decoder,
+                        T1_Pos       sbx,
+                        T1_Pos       sby,
+                        T1_Pos       wx,
+                        T1_Pos       wy )
+  {
+    if (wx > decoder->builder.advance.x)
+      decoder->builder.advance.x = wx;
+
+    (void)sbx;
+    (void)sby;
+    (void)wy;
+    return -1;    /* return an error code to exit the Type 1 parser */
+                  /* immediately.                                   */
+  }
+
+
+  static
+  T1_Int  maxadv_error( void )
+  {
+    /* we should never reach this code, unless with a buggy font */
+    return -2;
+  }
+
+  /* the maxadv_gbuilder_interface is used when computing the maximum  */
+  /* advance width of all glyphs in a given font. We only process the */
+  /* 'sbw' operator here, and return an error for all others..        */
+
+  /* Note that "seac" is processed by the T1_Decoder                  */
+  static
+  const T1_Builder_Funcs  maxadv_builder_interface =
+  {
+    (T1_Builder_EndChar)     maxadv_error,
+    (T1_Builder_Sbw)         maxadv_sbw,
+    (T1_Builder_ClosePath)   maxadv_error,
+    (T1_Builder_RLineTo)     maxadv_error,
+    (T1_Builder_RMoveTo)     maxadv_error,
+    (T1_Builder_RCurveTo)    maxadv_error
+  };
+
+
+  /* the maxadv_interface is used when computing the maximum advance */
+  /* with of the set of glyphs in a given font file. We only process */
+  /* the "seac" operator and return immediately..                    */
+  static
+  const T1_Hinter_Funcs  maxadv_hinter_interface =
+  {
+    (T1_Hinter_DotSection)   maxadv_error,
+    (T1_Hinter_ChangeHints)  maxadv_error,
+    (T1_Hinter_Stem)         maxadv_error,
+    (T1_Hinter_Stem3)        maxadv_error,
+  };
+
+
+
+  LOCAL_FUNC
+  T1_Error  T1_Compute_Max_Advance( T1_Face  face,
+                                    T1_Int  *max_advance )
+  {
+    T1_Error    error;
+    T1_Decoder  decoder;
+    T1_Int      glyph_index;
+    T1_Font*    type1 = &face->type1;
+
+    *max_advance = 0;
+
+    /* Initialise load decoder */
+    T1_Init_Decoder( &decoder, &maxadv_hinter_interface );
+
+    T1_Init_Builder( &decoder.builder, face, 0, 0,
+                     &maxadv_builder_interface );
+
+    /* 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 = T1_Parse_CharStrings( &decoder,
+                                    type1->charstrings    [glyph_index],
+                                    type1->charstrings_len[glyph_index],
+                                    type1->num_subrs,
+                                    type1->subrs,
+                                    type1->subrs_len );
+      /* ignore the error if one occured - skip to next glyph */
+      (void)error;
+    }
+
+    *max_advance = decoder.builder.advance.x;
+    return T1_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"    *********/
+  /**********                                                   *********/
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********************************************************************/
+
+
+
+  static
+  T1_Error  close_open_path( T1_Builder*  builder )
+  {
+    T1_Error     error;
+    FT_Outline*  cur = &builder->current;
+    T1_Int       num_points;
+    T1_Int       first_point;
+      
+    /* Some fonts, like Hershey, are made of "open paths" which are    */
+    /* now managed directly by FreeType. In this case, it is necessary */
+    /* to close the path by duplicating its points in reverse order,   */
+    /* which is precisely the purpose of this function                 */
+
+    /* first compute the number of points to duplicate..           */
+    if (cur->n_contours > 1)
+      first_point = cur->contours[ cur->n_contours-2 ]+1;
+    else
+      first_point = 0;
+        
+    num_points = cur->n_points - first_point - 2;
+    if ( num_points > 0 )
+    {
+      T1_Vector*  source_point;
+      char*       source_flags;
+      T1_Vector*  point;
+      char*       flags;
+              
+      error = T1_Add_Points( builder, num_points );
+      if (error) return error;
+
+      point = cur->points + cur->n_points;
+      flags = cur->flags  + cur->n_points;
+        
+      source_point   = point - 2;
+      source_flags   = flags - 2;
+
+      cur->n_points += num_points;
+
+      if ( builder->load_points )  
+        do
+        {
+          *point++ = *source_point--;
+          *flags++ = *source_flags--;
+          num_points--;
+        }
+        while (num_points > 0);
+    }
+
+    builder->path_begun = 0;
+    return T1_Err_Ok;
+  }
+
+
+  static
+  T1_Error  gload_closepath( T1_Builder*  builder )
+  {
+    FT_Outline*  cur = &builder->current;
+
+    /* save current contour, if any */
+    if ( cur->n_contours > 0 )
+      cur->contours[cur->n_contours-1] = cur->n_points-1;
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+    /* hint latest points if needed - this is not strictly required      */
+    /* there, but it helps for debugging, and doesn't affect performance */
+    if ( builder->pass == 1 )
+      T1_Hint_Points( builder );
+#endif
+
+    builder->path_begun = 0;
+    return T1_Err_Ok;
+  }
+
+
+
+  static
+  T1_Error  gload_endchar( T1_Builder*  builder )
+  {
+    FT_Outline*  cur = &builder->current;
+    T1_Error     error;
+
+    /* close path if needed */
+    if (builder->path_begun)
+    {
+      error = close_open_path( builder );
+      if (error) return error;
+    }
+
+    error = gload_closepath( builder );  
+
+    builder->base.n_points   += cur->n_points;
+    builder->base.n_contours += cur->n_contours;
+
+    return error;
+  }
+
+
+
+  static
+  T1_Error  gload_sbw( T1_Builder*  builder,
+                       T1_Pos       sbx,
+                       T1_Pos       sby,
+                       T1_Pos       wx,
+                       T1_Pos       wy )
+  {
+    builder->left_bearing.x += sbx;
+    builder->left_bearing.y += sby;
+    builder->advance.x       = wx;
+    builder->advance.y       = wy;
+
+    builder->last.x = sbx;
+    builder->last.y = sby;
+    return 0;
+  }
+
+
+
+
+  static
+  T1_Error  gload_rlineto( T1_Builder*  builder,
+                           T1_Pos       dx,
+                           T1_Pos       dy )
+  {
+    T1_Error     error;
+    FT_Outline*  cur = &builder->current;
+    T1_Vector    vec;
+
+    /* grow buffer if necessary */
+    error = T1_Add_Points  ( builder, 1 );
+    if (error) return error;
+
+    if ( builder->load_points )
+    {
+      /* save point */
+      vec.x = builder->last.x + dx;
+      vec.y = builder->last.y + dy;
+
+      cur->points[cur->n_points] = vec;
+      cur->flags [cur->n_points] = FT_Curve_Tag_On;
+
+      builder->last = vec;
+    }
+    cur->n_points++;
+
+    builder->path_begun  = 1;
+    return T1_Err_Ok;
+  }
+
+
+  static
+  T1_Error  gload_rmoveto( T1_Builder*  builder,
+                           T1_Pos       dx,
+                           T1_Pos       dy )
+  {
+    T1_Error     error;
+    FT_Outline*  cur = &builder->current;
+    T1_Vector    vec;
+
+    /* in the case where "path_begun" is set, we have a rmoveto    */
+    /* after some normal path definition. When the face's paint    */
+    /* type is set to 1, this means that we have an "open path",   */
+    /* also called a 'stroke'. The FreeType raster doesn't support */
+    /* opened path, so we'll close it explicitely there..          */
+    if ( builder->path_begun && builder->face->type1.paint_type == 1 )
+    {
+      if ( builder->face->type1.paint_type == 1 )
+      {
+        error = close_open_path( builder );
+        if (error) return error;
+      }
+    }
+    
+    /* grow buffer if necessary */
+    error = T1_Add_Contours( builder, 1 ) ||
+            T1_Add_Points  ( builder, 1 );
+    if (error) return error;
+
+    /* save current contour, if any */
+    if ( cur->n_contours > 0 )
+      cur->contours[cur->n_contours-1] = cur->n_points-1;
+
+    if ( builder->load_points )
+    {
+      /* save point */
+      vec.x = builder->last.x + dx;
+      vec.y = builder->last.y + dy;
+      cur->points[cur->n_points] = vec;
+      cur->flags [cur->n_points] = FT_Curve_Tag_On;
+
+      builder->last = vec;
+    }
+
+    cur->n_contours++;
+    cur->n_points++;
+
+    return T1_Err_Ok;
+  }
+
+
+  static
+  T1_Error  gload_rrcurveto( T1_Builder*  builder,
+                             T1_Pos       dx1,
+                             T1_Pos       dy1,
+                             T1_Pos       dx2,
+                             T1_Pos       dy2,
+                             T1_Pos       dx3,
+                             T1_Pos       dy3 )
+  {
+    T1_Error     error;
+    FT_Outline*  cur = &builder->current;
+    T1_Vector    vec;
+    T1_Vector*   points;
+    char*        flags;
+
+    /* grow buffer if necessary */
+    error = T1_Add_Points  ( builder, 3 );
+    if (error) return error;
+
+    if ( builder->load_points )
+    {
+      /* save point */
+      points = cur->points + cur->n_points;
+      flags  = cur->flags  + cur->n_points;
+
+      vec.x = builder->last.x + dx1;
+      vec.y = builder->last.y + dy1;
+      points[0] = vec;  flags[0] = FT_Curve_Tag_Cubic;
+
+      vec.x += dx2;
+      vec.y += dy2;
+      points[1] = vec;  flags[1] = FT_Curve_Tag_Cubic;
+
+      vec.x += dx3;
+      vec.y += dy3;
+      points[2] = vec;  flags[2] = FT_Curve_Tag_On;
+
+      builder->last = vec;
+    }
+    
+    cur->n_points      += 3;
+    builder->path_begun = 1;
+    return T1_Err_Ok;
+  }
+
+
+
+
+  static
+  T1_Error  gload_ignore( void )
+  {
+    return 0;
+  }
+
+
+  static
+  const T1_Builder_Funcs  gload_builder_interface =
+  {
+    gload_endchar,
+    gload_sbw,
+    gload_closepath,
+    gload_rlineto,
+    gload_rmoveto,
+    gload_rrcurveto
+  };
+
+
+  static
+  const T1_Builder_Funcs  gload_builder_interface_null =
+  {
+    (T1_Builder_EndChar)    gload_ignore,
+    (T1_Builder_Sbw)        gload_sbw,      /* record left bearing */
+    (T1_Builder_ClosePath)  gload_ignore,
+    (T1_Builder_RLineTo)    gload_ignore,
+    (T1_Builder_RMoveTo)    gload_ignore,
+    (T1_Builder_RCurveTo)   gload_ignore
+  };
+
+
+  static
+  const T1_Hinter_Funcs   gload_hinter_interface =
+  {
+    (T1_Hinter_DotSection)   gload_ignore,   /* dotsection         */
+    (T1_Hinter_ChangeHints)  gload_ignore,   /* changehints        */
+    (T1_Hinter_Stem)         gload_ignore,   /* hstem & vstem      */
+    (T1_Hinter_Stem3)        gload_ignore,   /* hstem3 & vestem3   */
+  };
+
+
+
+
+  LOCAL_FUNC
+  T1_Error  T1_Load_Glyph( T1_GlyphSlot  glyph,
+                           T1_Size       size,
+                           T1_Int        glyph_index,
+                           T1_Int        load_flags )
+  {
+    T1_Error        error;
+    T1_Decoder      decoder;
+    T1_Face         face = (T1_Face)glyph->root.face;
+    T1_Bool         hinting;
+    T1_Font*        type1 = &face->type1;
+
+    glyph->x_scale = size->root.metrics.x_scale;
+    glyph->y_scale = size->root.metrics.y_scale;
+
+    glyph->root.outline.n_points   = 0;
+    glyph->root.outline.n_contours = 0;
+
+    hinting = ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
+              ( load_flags & FT_LOAD_NO_HINTING ) == 0;
+
+    glyph->root.format = ft_glyph_format_none;
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+    /*****************************************************************/
+    /*                                                               */
+    /*  Hinter overview :                                            */
+    /*                                                               */
+    /*    This is a two-pass hinter. On the first pass, the hints    */
+    /*    are all recorded by the hinter, and no point is loaded     */
+    /*    in the outline.                                            */
+    /*                                                               */
+    /*    When the first pass is finished, all stems hints are       */
+    /*    grid-fitted at once.                                       */
+    /*                                                               */
+    /*    Then, a second pass is performed to load the outline       */
+    /*    points as well as hint/scale them correctly.               */
+    /*                                                               */
+
+    if ( hinting )
+    {
+      /* Pass 1 - don't record points, simply stem hints */
+      T1_Init_Decoder( &decoder, &t1_hinter_funcs );
+      T1_Init_Builder( &decoder.builder, face, size, glyph,
+                       &gload_builder_interface_null );
+
+      glyph->hints->hori_stems.num_stems = 0;
+      glyph->hints->vert_stems.num_stems = 0;
+
+      error = T1_Parse_CharStrings( &decoder,
+                                    type1->charstrings    [glyph_index],
+                                    type1->charstrings_len[glyph_index],
+                                    type1->num_subrs,
+                                    type1->subrs,
+                                    type1->subrs_len );
+
+      /* All right, pass 1 is finished, now grid-fit all stem hints */
+      T1_Hint_Stems( &decoder.builder );
+
+      /* Pass 2 - record and scale/hint the points */
+      T1_Init_Decoder( &decoder, &t1_hinter_funcs );
+      T1_Init_Builder( &decoder.builder, face, size, glyph,
+                       &gload_builder_interface );
+
+      decoder.builder.pass = 1;
+
+      error = T1_Parse_CharStrings( &decoder,
+                                    type1->charstrings    [glyph_index],
+                                    type1->charstrings_len[glyph_index],
+                                    type1->num_subrs,
+                                    type1->subrs,
+                                    type1->subrs_len );
+
+      /* save new glyph tables */
+      T1_Done_Builder( &decoder.builder );
+    }
+    else
+#endif
+    {
+      T1_Init_Decoder( &decoder, &gload_hinter_interface );
+
+      T1_Init_Builder( &decoder.builder, face, size, glyph,
+                       &gload_builder_interface );
+  
+      /* now load the unscaled outline */
+      error = T1_Parse_CharStrings( &decoder,
+                                    type1->charstrings    [glyph_index],
+                                    type1->charstrings_len[glyph_index],
+                                    type1->num_subrs,
+                                    type1->subrs,
+                                    type1->subrs_len );
+  
+      /* save new glyph tables */
+      T1_Done_Builder( &decoder.builder );
+    }
+
+
+    /* Now, set the metrics.. - this is rather simple, as : */
+    /* the left side bearing is the xMin, and the top side  */
+    /* bearing the yMax..                                   */
+    if (!error)
+    {
+      FT_BBox           cbox;
+      FT_Glyph_Metrics* metrics = &glyph->root.metrics;
+
+      FT_Get_Outline_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;
+
+      /* copy the _unscaled_ advance width */
+      metrics->horiAdvance  = decoder.builder.advance.x;
+
+      /* make up vertical metrics */
+      metrics->vertBearingX = 0;
+      metrics->vertBearingY = 0;
+      metrics->vertAdvance  = 0;
+
+      glyph->root.format = ft_glyph_format_outline;
+
+      glyph->root.outline.second_pass    = TRUE;
+      glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 );
+      glyph->root.outline.dropout_mode   = 2;
+
+      if ( hinting )
+      {
+        /* adjust the advance width                  */
+        /* XXX : TODO : consider stem hints grid-fit */
+        metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,
+                                           glyph->x_scale );
+      }
+      else if ( (load_flags & FT_LOAD_NO_SCALE) == 0 )
+      {
+        /* scale the outline and the metrics */
+        T1_Int       n;
+        FT_Outline*  cur = &decoder.builder.base;
+        T1_Vector*   vec = cur->points;
+        T1_Fixed     x_scale = glyph->x_scale;
+        T1_Fixed     y_scale = glyph->y_scale;
+
+        /* First of all, scale the points */
+        for ( n = cur->n_points; n > 0; n--, vec++ )
+        {
+          vec->x = FT_MulFix( vec->x, x_scale );
+          vec->y = FT_MulFix( vec->y, y_scale );
+        }
+
+        /* Then scale the metrics */
+        metrics->width  = FT_MulFix( metrics->width,  x_scale );
+        metrics->height = FT_MulFix( metrics->height, y_scale );
+
+        metrics->horiBearingX = FT_MulFix( metrics->horiBearingX, x_scale );
+        metrics->horiBearingY = FT_MulFix( metrics->horiBearingY, y_scale );
+        metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
+
+        metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+        metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+        metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  x_scale );
+
+      }
+    }
+
+    return error;
+  }
+
--- /dev/null
+++ b/src/type1z/t1gload.h
@@ -1,0 +1,436 @@
+/*******************************************************************
+ *
+ *  t1gload.h                                                   1.0
+ *
+ *    Type1 Glyph Loader.
+ *
+ *  Copyright 1996-1998 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ *  This file is part of the FreeType project, and may only be used
+ *  modified and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ *
+ *  The Type 1 glyph loader uses three distinct objects to build
+ *  scaled and hinted outlines from a charstrings program. These are :
+ *
+ *  - a glyph builder, T1_Builder, used to store the built outline
+ *
+ *  - a glyph hinter, T1_Hinter, used to record and apply the stem
+ *    hints
+ *
+ *  - a charstrings interpreter, T1_Decoder, used to parse the
+ *    Type 1 charstrings stream, manage a stack and call the builder
+ *    and/or hinter depending on the opcodes.
+ *
+ *  Ideally, a Type 2 glyph loader would only need to have its own
+ *  T2_Decoder object (assuming the hinter is able to manage all
+ *  kinds of hints).
+ *
+ ******************************************************************/
+
+#ifndef T1GLOAD_H
+#define T1GLOAD_H
+
+#include <t1objs.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+/*************************************************************************/
+/*                                                                       */
+/* <Structure> T1_Builder_Funcs                                          */
+/*                                                                       */
+/* <Description>                                                         */
+/*     a structure used to store the address of various functions        */
+/*     used by a glyph builder to implement the outline's "path          */
+/*     construction".                                                    */
+/*                                                                       */
+/*                                                                       */
+  typedef struct T1_Builder_  T1_Builder;
+
+  typedef T1_Error  (*T1_Builder_EndChar)( T1_Builder*  loader );
+
+  typedef T1_Error  (*T1_Builder_Sbw)    ( T1_Builder*  loader,
+                                           T1_Pos       sbx,
+                                           T1_Pos       sby,
+                                           T1_Pos       wx,
+                                           T1_Pos       wy );
+
+  typedef T1_Error  (*T1_Builder_ClosePath)( T1_Builder*  loader );
+
+  typedef T1_Error  (*T1_Builder_RLineTo)( T1_Builder*  loader,
+                                           T1_Pos       dx,
+                                           T1_Pos       dy );
+
+  typedef T1_Error  (*T1_Builder_RMoveTo)( T1_Builder*  loader,
+                                           T1_Pos       dx,
+                                           T1_Pos       dy );
+
+  typedef T1_Error  (*T1_Builder_RCurveTo)( T1_Builder*  loader,
+                                            T1_Pos       dx1,
+                                            T1_Pos       dy1,
+                                            T1_Pos       dx2,
+                                            T1_Pos       dy2,
+                                            T1_Pos       dx3,
+                                            T1_Pos       dy3 );
+
+  typedef struct T1_Builder_Funcs_
+  {
+    T1_Builder_EndChar    end_char;
+    T1_Builder_Sbw        set_bearing_point;
+    T1_Builder_ClosePath  close_path;
+    T1_Builder_RLineTo    rline_to;
+    T1_Builder_RMoveTo    rmove_to;
+    T1_Builder_RCurveTo   rcurve_to;
+
+  } T1_Builder_Funcs;
+
+
+
+/*************************************************************************/
+/*                                                                       */
+/* <Structure> T1_Builder                                                */
+/*                                                                       */
+/* <Description>                                                         */
+/*     a structure used during glyph loading to store its outline.       */
+/*                                                                       */
+/* <Fields>                                                              */
+/*    system :: current system object                                    */
+/*    face   :: current face object                                      */
+/*    size   :: current size object                                      */
+/*    glyph  :: current glyph slot                                       */
+/*                                                                       */
+/*    current :: current glyph outline                                   */
+/*    base    :: base glyph outline                                      */
+/*                                                                       */
+/*    max_points   :: maximum points in builder outline                  */
+/*    max_contours :: maximum contours in builder outline                */
+/*                                                                       */
+/*    last     :: last point position                                    */
+/*                                                                       */
+/*    scale_x  :: horizontal scale ( FUnits to sub-pixels )              */
+/*    scale_y  :: vertical scale   ( FUnits to sub-pixels )              */
+/*    pos_x    :: horizontal translation (composite glyphs)              */
+/*    pos_y    :: vertical translation   (composite glyph)               */
+/*                                                                       */
+/*    left_bearing  :: left side bearing point                           */
+/*    advance       :: horizontal advance vector                         */
+/*                                                                       */
+/*    path_begun    :: flag, indicates that a new path has begun         */
+/*    load_points   :: flag, if not set, no points are loaded            */
+/*                                                                       */
+/*    pass     :: pass number for multi-pass hinters                     */
+/*                                                                       */
+/*    funcs    :: table of builder functions used to perform             */
+/*                the outline's path construction                        */
+/*                                                                       */
+/*    hint_point :: index of next point to hint..                        */
+/*                                                                       */
+/*                                                                       */
+/*                                                                       */
+/*                                                                       */
+
+  struct T1_Builder_
+  {
+    FT_Memory     memory;
+    T1_Face       face;
+    T1_Size       size;
+    T1_GlyphSlot  glyph;
+
+    FT_Outline    current;       /* the current glyph outline   */
+    FT_Outline    base;          /* the composite glyph outline */
+
+    T1_Int        max_points;    /* capacity of base outline in points   */
+    T1_Int        max_contours;  /* capacity of base outline in contours */
+
+    T1_Vector     last;
+
+    T1_Fixed      scale_x;
+    T1_Fixed      scale_y;
+
+    T1_Pos        pos_x;
+    T1_Pos        pos_y;
+
+    T1_Vector     left_bearing;
+    T1_Vector     advance;
+
+    T1_BBox       bbox;          /* bounding box */
+    T1_Bool       path_begun;
+    T1_Bool       load_points;
+
+    T1_Int        pass;
+    T1_Int        hint_point;
+
+    /* path construction function interface */
+    T1_Builder_Funcs  funcs;
+  };
+
+
+/*************************************************************************/
+/*                                                                       */
+/* <Structure> T1_Hinter_Funcs                                           */
+/*                                                                       */
+/* <Description>                                                         */
+/*     a structure used to store the address of various functions        */
+/*     used by a Type 1 hinter to perform outline hinting.               */
+/*                                                                       */
+ 
+  typedef T1_Error  (*T1_Hinter_ChangeHints)( T1_Builder*  builder );
+
+  typedef T1_Error  (*T1_Hinter_DotSection)( T1_Builder*  builder );
+
+  typedef T1_Error  (*T1_Hinter_Stem)( T1_Builder*  builder,
+                                       T1_Pos       pos,
+                                       T1_Pos       width,
+                                       T1_Bool      vertical );
+
+
+  typedef T1_Error  (*T1_Hinter_Stem3)( T1_Builder*  builder,
+                                        T1_Pos       pos0,
+                                        T1_Pos       width0,
+                                        T1_Pos       pos1,
+                                        T1_Pos       width1,
+                                        T1_Pos       pos2,
+                                        T1_Pos       width2,
+                                        T1_Bool      vertical );
+
+  typedef struct T1_Hinter_Func_
+  {
+    T1_Hinter_ChangeHints     change_hints;
+    T1_Hinter_DotSection      dot_section;
+    T1_Hinter_Stem            stem;
+    T1_Hinter_Stem3           stem3;
+
+  } T1_Hinter_Funcs;
+
+
+
+  typedef enum T1_Operator_
+  {
+    op_none = 0,
+    op_endchar,
+    op_hsbw,
+    op_seac,
+    op_sbw,
+    op_closepath,
+    op_hlineto,
+    op_hmoveto,
+    op_hvcurveto,
+    op_rlineto,
+    op_rmoveto,
+    op_rrcurveto,
+    op_vhcurveto,
+    op_vlineto,
+    op_vmoveto,
+    op_dotsection,
+    op_hstem,
+    op_hstem3,
+    op_vstem,
+    op_vstem3,
+    op_div,
+    op_callothersubr,
+    op_callsubr,
+    op_pop,
+    op_return,
+    op_setcurrentpoint,
+
+    op_max    /* never remove this one */
+
+  } T1_Operator;
+
+
+
+
+  /* execution context charstring zone */
+  typedef struct T1_Decoder_Zone_
+  {
+    T1_Byte*  base;
+    T1_Byte*  limit;
+    T1_Byte*  cursor;
+
+  } T1_Decoder_Zone;
+
+
+  typedef struct T1_Decoder_
+  {
+    T1_Builder         builder;
+    T1_Hinter_Funcs    hinter;
+
+    T1_Int             stack[ T1_MAX_CHARSTRINGS_OPERANDS ];
+    T1_Int*            top;
+
+    T1_Decoder_Zone    zones[ T1_MAX_SUBRS_CALLS+1 ];
+    T1_Decoder_Zone*   zone;
+
+    T1_Int             flex_state;
+    T1_Int             num_flex_vectors;
+    T1_Vector          flex_vectors[7];
+
+  } T1_Decoder;
+
+
+
+/*********************************************************************
+ *
+ * <Function>
+ *    T1_Init_Builder
+ *
+ * <Description>
+ *    Initialise a given glyph builder.
+ *
+ * <Input>
+ *    builder :: glyph builder to initialise
+ *    face    :: current face object
+ *    size    :: current size object
+ *    glyph   :: current glyph object
+ *    funcs   :: glyph builder functions (or "methods").
+ *
+ * <Note>
+ *    This function is exported for now because it is used by the
+ *    "t1dump" utility. Later, it will be accessed through a
+ *    format-specific extension
+ *
+ *********************************************************************/
+
+  EXPORT_DEF
+  void  T1_Init_Builder( T1_Builder*             builder,
+                         T1_Face                 face,
+                         T1_Size                 size,
+                         T1_GlyphSlot            glyph,
+                         const T1_Builder_Funcs* funcs );
+
+/*********************************************************************
+ *
+ * <Function>
+ *    T1_Done_Builder
+ *
+ * <Description>
+ *    Finalise a given glyph builder. Its content can still be
+ *    used after the call, but the function saves important information
+ *    within the corresponding glyph slot.
+ *
+ * <Input>
+ *    builder :: glyph builder to initialise
+ *
+ * <Note>
+ *    This function is exported for now because it is used by the
+ *    "t1dump" utility. Later, it will be accessed through a
+ *    format-specific extension
+ *
+ *********************************************************************/
+
+  EXPORT_DEF
+  void T1_Done_Builder( T1_Builder*  builder );
+
+
+/*********************************************************************
+ *
+ * <Function>
+ *    T1_Init_Decoder
+ *
+ * <Description>
+ *    Initialise a given Type 1 decoder for parsing
+ *
+ * <Input>
+ *    decoder :: Type 1 decoder to initialise
+ *    funcs   :: hinter functions interface
+ *
+ * <Note>
+ *    This function is exported for now because it is used by the
+ *    "t1dump" utility. Later, it will be accessed through a
+ *    format-specific extension
+ *
+ *********************************************************************/
+
+  EXPORT_DEF
+  void  T1_Init_Decoder( T1_Decoder*             decoder,
+                         const T1_Hinter_Funcs*  funcs );
+
+
+
+  /* Compute the maximum advance width of a font through quick parsing */
+  LOCAL_DEF
+  T1_Error  T1_Compute_Max_Advance( T1_Face  face,
+                                    T1_Int  *max_advance );
+
+
+  /* This function is exported, because it is used by the T1Dump utility */
+  EXPORT_DEF
+  T1_Error   T1_Parse_CharStrings( T1_Decoder*  decoder,
+                                   T1_Byte*     charstring_base,
+                                   T1_Int       charstring_len,
+                                   T1_Int       num_subrs,
+                                   T1_Byte**    subrs_base,
+                                   T1_Int*      subrs_len );
+
+
+
+/*************************************************************************/
+/*                                                                       */
+/* <Function> T1_Add_Points                                              */
+/*                                                                       */
+/* <Description>                                                         */
+/*    Checks that there is enough room in the current load glyph outline */
+/*    to accept "num_points" additional outline points. If not, this     */
+/*    function grows the load outline's arrays accordingly..             */
+/*                                                                       */
+/* <Input>                                                               */
+/*    builder    :: pointer to glyph builder object                      */
+/*    num_points :: number of points that will be added later            */
+/*                                                                       */
+/* <Return>                                                              */
+/*    Type1 error code. 0 means success                                  */
+/*                                                                       */
+/* <Note>                                                                */
+/*    This function does NOT update the points count in the glyph loader */
+/*    This must be done by the caller itself, after this function is     */
+/*    invoked..                                                          */
+/*                                                                       */
+  LOCAL_DEF
+  T1_Error  T1_Add_Points( T1_Builder*  builder,
+                           T1_Int       num_points );
+
+/*************************************************************************/
+/*                                                                       */
+/* <Function> T1_Add_Contours                                            */
+/*                                                                       */
+/* <Description>                                                         */
+/*    Checks that there is enough room in the current load glyph outline */
+/*    to accept "num_contours" additional contours. If not, this func    */
+/*    the load outline's arrays accordingly..                            */
+/*                                                                       */
+/* <Input>                                                               */
+/*    builder      :: pointer to glyph builder object                    */
+/*    num_contours :: number of contours that will be added later        */
+/*                                                                       */
+/* <Return>                                                              */
+/*    Type1 error code. 0 means success                                  */
+/*                                                                       */
+/* <Note>                                                                */
+/*    This function does NOT update the contours count in the load glyph */
+/*    This must be done by the caller itself, after this function is     */
+/*    invoked..                                                          */
+/*                                                                       */
+  LOCAL_DEF
+  T1_Error  T1_Add_Contours( T1_Builder*  builder,
+                             T1_Int       num_contours );
+
+
+  LOCAL_DEF
+  T1_Error  T1_Load_Glyph( T1_GlyphSlot  glyph,
+                           T1_Size       size,
+                           T1_Int        glyph_index,
+                           T1_Int        load_flags );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* T1GLOAD_H */
--- /dev/null
+++ b/src/type1z/t1hinter.c
@@ -1,0 +1,1269 @@
+/*******************************************************************
+ *
+ *  t1hinter.c                                                 1.2
+ *
+ *    Type1 hinter.         
+ *
+ *  Copyright 1996-1999 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ *  This file is part of the FreeType project, and may only be used
+ *  modified and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ *
+ *  The Hinter is in charge of fitting th scaled outline to the
+ *  pixel grid in order to considerably improve the quality of
+ *  the Type 1 font driver's output..
+ *
+ ******************************************************************/
+
+#include <ftdebug.h>
+#include <t1objs.h>
+#include <t1hinter.h>
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1hint    /* for debugging/tracing */
+
+
+#undef  ONE_PIXEL
+#define ONE_PIXEL  64
+
+#undef  ROUND
+#define ROUND(x)   (( x + ONE_PIXEL/2 ) & -ONE_PIXEL)
+
+#undef  SCALE
+#define SCALE(val)   FT_MulFix( val, scale )
+
+/* various constants used to describe the alignment of a horizontal */
+/* stem with regards to the blue zones                              */
+#define T1_ALIGN_NONE    0
+#define T1_ALIGN_BOTTOM  1
+#define T1_ALIGN_TOP     2
+#define T1_ALIGN_BOTH    3
+
+
+/************************************************************************
+ *
+ * <Function>
+ *    t1_set_blue_zones
+ *
+ * <Description>
+ *    Set a size object's blue zones during reset. This will compute
+ *    the "snap" zone corresponding to each blue zone.
+ *
+ * <Input>
+ *    size  :: handle to target size object
+ *
+ * <Return>
+ *    Error code. 0 means success
+ *
+ * <Note>
+ *    This functions does the following :
+ *
+ *      1. It extracts the bottom and top blue zones from the
+ *         face object.
+ *
+ *      2. Each zone is then grown by  BlueFuzz, overlapping 
+ *         is eliminated by adjusting the zone edges appropriately
+ *
+ *      3. For each zone, we keep its original font units position, its
+ *         original scaled position, as well as its grown/adjusted
+ *         edges.
+ *
+ ************************************************************************/
+
+      /* ultra simple bubble sort (not a lot of elements, mostly */
+      /* pre-sorted, no need for quicksort)                      */
+      static
+      void  t1_sort_blues( T1_Int*  blues,
+                           T1_Int   count )
+      {
+        T1_Int  i, swap;
+        T1_Int* cur;
+    
+        for ( i = 2; i < count; i += 2 )
+        {
+          cur = blues + i;
+          do
+          {
+            if ( cur[-1] < cur[0] )
+              break;
+    
+            swap = cur[-2]; cur[-2] = cur[0]; cur[0] = swap;
+            swap = cur[-1]; cur[-1] = cur[1]; cur[1] = swap;
+            cur -= 2;
+          }
+          while ( cur > blues );
+        }
+      }
+
+
+  static
+  T1_Error  t1_set_blue_zones( T1_Size  size )
+  {
+    T1_Face          face = (T1_Face)size->root.face;
+    T1_Font*         priv = &face->type1;
+    T1_Int           n;
+    T1_Int           blues[24];
+    T1_Int           num_bottom;
+    T1_Int           num_top;
+    T1_Int           num_blues;
+    T1_Size_Hints*   hints = size->hints;
+    T1_Snap_Zone*    zone;
+    T1_Pos           pix, orus;
+    T1_Pos           min, max, threshold;
+    T1_Fixed         scale;
+    T1_Bool          is_bottom;
+
+    /**********************************************************************/
+    /*                                                                    */
+    /*  COPY BOTTOM AND TOP BLUE ZONES IN LOCAL ARRAYS                    */
+    /*                                                                    */
+    /*                                                                    */
+
+    /* First of all, check the sizes of the /BlueValues and /OtherBlues */
+    /* tables. They all must contain an even number of arguments        */
+    if ( priv->num_other_blues & 1 ||
+         priv->num_blues       & 1 )
+    {
+      FT_ERROR(( "T1.Copy_Blues : odd number of blue values\n" ));
+      return T1_Err_Syntax_Error;
+    }
+
+    /* copy the bottom blue zones from /OtherBlues           */
+    num_top    = 0;
+    num_bottom = priv->num_other_blues;
+
+    for ( n = 0; n < num_bottom; n ++ )
+      blues[n] = priv->other_blues[n];
+
+    /* Add the first blue zone in /BlueValues to the table */
+    num_top = priv->num_blues - 2;
+    if ( num_top >= 0 )
+    {
+      blues[ num_bottom ] = priv->blue_values[0];
+      blues[num_bottom+1] = priv->blue_values[1];
+
+      num_bottom += 2;
+    }
+
+    /* sort the bottom blue zones */
+    t1_sort_blues( blues, num_bottom );
+
+    hints->num_bottom_zones = num_bottom >> 1;
+
+    /* now copy the /BlueValues to the top of the blues array */
+    if ( num_top > 0 )
+    {
+      for ( n = 0; n < num_top; n++ )
+        blues[ num_bottom+n ] = priv->blue_values[n+2];
+
+      /* sort the top blue zones */
+      t1_sort_blues( blues + num_bottom, num_top );
+    }
+    else
+      num_top = 0;
+
+    num_blues             = num_top + num_bottom;
+    hints->num_blue_zones = ( num_blues ) >> 1;
+
+    /**********************************************************************/
+    /*                                                                    */
+    /*    BUILD BLUE SNAP ZONES FROM THE LOCAL BLUES ARRAYS               */
+    /*                                                                    */
+    /*                                                                    */
+
+    scale     = size->root.metrics.y_scale;
+    zone      = hints->blue_zones;
+    threshold = ONE_PIXEL/4;   /* 0.25 pixels */
+
+    for ( n = 0; n < num_blues; n += 2, zone ++ )
+    {
+      is_bottom = ( n < num_bottom ? 1 : 0 );
+
+      orus = blues[n+is_bottom];  /* get alignement coordinate */
+      pix  = SCALE( orus );       /* scale it                  */
+
+      min  = SCALE( blues[ n ] - priv->blue_fuzz );
+      max  = SCALE( blues[n+1] + priv->blue_fuzz );
+
+      if ( min > pix - threshold ) min = pix - threshold;
+      if ( max < pix + threshold ) max = pix + threshold;
+
+      zone->orus = orus;
+      zone->pix  = pix;
+      zone->min  = min;
+      zone->max  = max;
+    }
+
+    /* adjust edges in case of overlap */
+    zone = hints->blue_zones;
+    for ( n = 0; n < num_blues-2; n += 2, zone ++ )
+    {
+      if ( n != num_bottom-2         &&
+           zone[0].max > zone[1].min )
+      {
+        zone[0].max = zone[1].min = (zone[0].pix+zone[1].pix)/2;
+      }
+    }
+
+    
+    /* Compare the current pixel size with the BlueScale value */
+    /* to know wether to supress overshoots..                  */
+    
+    hints->supress_overshoots = 
+      ( size->root.metrics.y_ppem < FT_MulFix(1000,priv->blue_scale) );
+
+    /* Now print the new blue values in tracing mode */
+#ifdef FT_DEBUG_LEVEL_TRACE
+    
+    FT_TRACE2(( "Blue Zones for size object at $%08lx :\n", (long)size ));
+    FT_TRACE2(( "   orus    pix    min   max\n" ));
+    FT_TRACE2(( "-------------------------------\n" ));
+    
+    zone = hints->blue_zones;
+    for ( n = 0; n < hints->num_blue_zones; n++ )
+    {
+      FT_TRACE2(( "    %3d   %.2f   %.2f  %.2f\n",
+                zone->orus, 
+                zone->pix/64.0,
+                zone->min/64.0, 
+                zone->max/64.0 ));
+      zone++;
+    }
+    FT_TRACE2(( "\nOver shoots are %s\n\n",
+              hints->supress_overshoots ? "supressed" : "active" ));
+
+#endif /* DEBUG_LEVEL_TRACE */
+                               
+    return T1_Err_Ok;
+  }
+
+
+
+/************************************************************************
+ *
+ * <Function>
+ *    t1_set_snap_zones
+ *
+ * <Description>
+ *    This function set a size object's stem snap zones.
+ *
+ * <Input>
+ *    size :: handle to target size object
+ *
+ * <Return>
+ *    Error code. 0 means success
+ *
+ * <Note>
+ *    This function performs the following :
+ *
+ *      1. It reads and scales the stem snap widths from the parent face
+ *     
+ *      2. A "snap zone" is computed for each snap width, by "growing"
+ *         it with a threshold of a 1/2 pixel. Overlapping is avoided
+ *         through proper edge adjustment.
+ *
+ *      3. Each width whose zone contain the scaled standard set width
+ *         is removed from the table
+ *
+ *      4. Finally, the standard set width is scaled, and its correponding
+ *         "snap zone" is inserted into the sorted snap zones table
+ *
+ ************************************************************************/
+
+  static
+  T1_Error  t1_set_snap_zones( T1_Size  size )
+  {
+    T1_Int         n, direction, n_zones, num_zones;
+    T1_Snap_Zone*  zone;
+    T1_Snap_Zone*  base_zone;
+    T1_Short*      orgs;
+    T1_Pos         standard_width;
+    T1_Fixed       scale;
+
+    T1_Face          face = (T1_Face)size->root.face;
+    T1_Font*         priv = &face->type1;
+    T1_Size_Hints*  hints = size->hints;
+
+    /* start with horizontal snap zones */
+    direction      = 0;
+    standard_width = priv->standard_width;
+    n_zones        = priv->num_snap_widths;
+    base_zone      = hints->snap_widths;
+    orgs           = priv->stem_snap_widths;
+    scale          = size->root.metrics.x_scale;
+    
+    while (direction < 2)
+    {
+      /*****************************************************************/
+      /*                                                               */
+      /*  Read and scale stem snap widths table from the physical      */
+      /*  font record.                                                 */
+      /*                                                               */
+      T1_Pos  prev, orus, pix, min, max, threshold;
+      
+      threshold = ONE_PIXEL/4;
+      zone      = base_zone;
+
+      if ( n_zones > 0 )
+      {
+        orus = *orgs++;
+        pix  = SCALE( orus );
+        min  = pix-threshold;
+        max  = pix+threshold;
+
+        zone->orus = orus;
+        zone->pix  = pix;
+        zone->min  = min;
+        prev       = pix;
+
+        for ( n = 1; n < n_zones; n++ )
+        {
+          orus = *orgs++;
+          pix  = SCALE( orus );
+
+          if ( pix-prev < 2*threshold )
+          {
+            min = max = (pix+prev)/2;
+          }
+          else
+            min = pix-threshold;
+
+          zone->max = max;
+          zone++;
+          zone->orus = orus;
+          zone->pix  = pix;
+          zone->min  = min;
+
+          max  = pix+threshold;
+          prev = pix;
+        }
+        zone->max = max;
+      }
+
+      /* print the scaled stem snap values in tracing modes */
+#ifdef FT_DEBUG_LEVEL_TRACE
+      
+      FT_TRACE2(( "Set_Snap_Zones : first %s pass\n", 
+                direction ? "vertical" : "horizontal" ));
+                
+      FT_TRACE2(( "Scaled original stem snap zones :\n" ));
+      FT_TRACE2(( "   orus   pix   min   max\n" ));
+      FT_TRACE2(( "-----------------------------\n" ));
+      
+      zone = base_zone;
+      for ( n = 0; n < n_zones; n++, zone++ )
+        FT_TRACE2(( "  %3d  %.2f  %.2f  %.2f\n",
+                  zone->orus,
+                  zone->pix/64.0,
+                  zone->min/64.0,
+                  zone->max/64.0 ));
+      FT_TRACE2(( "\n" ));
+      
+      FT_TRACE2(( "Standard width = %d\n", standard_width ));
+#endif
+
+      /*****************************************************************/
+      /*                                                               */
+      /*  Now, each snap width which is in the range of the standard   */
+      /*  set width will be removed from the list..                    */
+      /*                                                               */
+
+      if ( standard_width > 0 )
+      {
+        T1_Snap_Zone*  parent;
+        T1_Pos         std_pix, std_min, std_max;
+
+        std_pix = SCALE( standard_width );        
+
+        std_min = std_pix-threshold;
+        std_max = std_pix+threshold;
+
+        num_zones = 0;
+        zone      = base_zone;
+        parent    = base_zone;
+
+        for ( n = 0; n < n_zones; n++ )
+        {
+          if ( zone->pix >= std_min && zone->pix <= std_max )
+          {
+            /* this zone must be removed from the list */
+            if ( std_min > zone->min ) std_min = zone->min;
+            if ( std_max < zone->max ) std_max = zone->max;
+          }
+          else
+          {
+            *parent++ = *zone;
+            num_zones++;
+          }
+          zone++;
+        }
+        
+        /**********************************************/
+        /*  Now, insert the standard width zone       */
+        
+        zone = base_zone+num_zones;
+        while ( zone > base_zone && zone[-1].pix > std_max )
+        {
+          zone[0] = zone[-1];
+          zone --;
+        }
+        
+        /* check border zones */
+        if ( zone > base_zone && zone[-1].max > std_min )
+          zone[-1].max = std_min;
+          
+        if ( zone < base_zone+num_zones && zone[1].min < std_max )
+          zone[1].min = std_max;
+        
+        zone->orus = standard_width;
+        zone->pix  = std_pix;
+        zone->min  = std_min;
+        zone->max  = std_max;
+        
+        num_zones++;
+      }
+      else
+        num_zones = n_zones;
+
+      /* save total number of stem snaps now */
+      if (direction) hints->num_snap_heights = num_zones;
+                else hints->num_snap_widths  = num_zones;
+
+      /* print the scaled stem snap values in tracing modes */
+#ifdef FT_DEBUG_LEVEL_TRACE
+      
+      FT_TRACE2(( "Set_Snap_Zones : second %s pass\n", 
+                direction ? "vertical" : "horizontal" ));
+                
+      FT_TRACE2(( "Scaled clipped stem snap zones :\n" ));
+      FT_TRACE2(( "   orus   pix   min   max\n" ));
+      FT_TRACE2(( "-----------------------------\n" ));
+      
+      zone = base_zone;
+      for ( n = 0; n < num_zones; n++, zone++ )
+        FT_TRACE2(( "  %3d  %.2f  %.2f  %.2f\n",
+                  zone->orus,
+                  zone->pix/64.0,
+                  zone->min/64.0,
+                  zone->max/64.0 ));
+      FT_TRACE2(( "\n" ));
+      
+      FT_TRACE2(( "Standard width = %d\n", standard_width ));
+#endif
+     
+      /* continue with vertical snap zone */
+      direction++;
+      standard_width = priv->standard_height;
+      n_zones        = priv->num_snap_heights;
+      base_zone      = hints->snap_heights;
+      orgs           = priv->stem_snap_heights;
+      scale          = size->root.metrics.y_scale;
+    }
+
+    return T1_Err_Ok;
+  }
+  
+
+/************************************************************************
+ *
+ * <Function>
+ *    T1_New_Size_Hinter
+ *
+ * <Description>
+ *    Allocates a new hinter structure for a given size object
+ *
+ * <Input>
+ *    size :: handle to target size object
+ *
+ * <Return>
+ *    Error code. 0 means success
+ *
+ ************************************************************************/
+
+  LOCAL_FUNC
+  T1_Error  T1_New_Size_Hinter( T1_Size  size )
+  {
+    FT_Memory  memory = size->root.face->memory;
+    
+    return MEM_Alloc( size->hints, sizeof(*size->hints) );
+  }
+
+
+/************************************************************************
+ *
+ * <Function>
+ *    T1_Done_Size_Hinter
+ *
+ * <Description>
+ *    Releases a given size object's hinter structure
+ *
+ * <Input>
+ *    size :: handle to target size object
+ *
+ ************************************************************************/
+
+  LOCAL_FUNC
+  void      T1_Done_Size_Hinter( T1_Size  size )
+  {
+    FT_Memory  memory = size->root.face->memory;
+
+    FREE( size->hints );
+  }
+
+
+
+/************************************************************************
+ *
+ * <Function>
+ *    T1_Reset_Size_Hinter
+ *
+ * <Description>
+ *    Recomputes hinting information when a given size object has
+ *    changed its resolutions/char sizes/pixel sizes
+ *
+ * <Input>
+ *    size :: handle to size object
+ *
+ * <Return>
+ *    Error code. 0 means success
+ *
+ ************************************************************************/
+
+  LOCAL_FUNC
+  T1_Error  T1_Reset_Size_Hinter( T1_Size  size )
+  {
+    return t1_set_blue_zones(size) || t1_set_snap_zones(size);
+  }
+
+
+
+/************************************************************************
+ *
+ * <Function>
+ *    T1_New_Glyph_Hinter
+ *
+ * <Description>
+ *    Allocates a new hinter structure for a given glyph slot
+ *
+ * <Input>
+ *    glyph :: handle to target glyph slot
+ *
+ * <Return>
+ *    Error code. 0 means success
+ *
+ ************************************************************************/
+
+  LOCAL_FUNC
+  T1_Error  T1_New_Glyph_Hinter( T1_GlyphSlot  glyph )
+  {
+    FT_Memory  memory = glyph->root.face->memory;
+    
+    return MEM_Alloc( glyph->hints, sizeof(*glyph->hints) );
+  }
+
+
+/************************************************************************
+ *
+ * <Function>
+ *    T1_Done_Glyph_Hinter
+ *
+ * <Description>
+ *    Releases a given glyph slot's hinter structure
+ *
+ * <Input>
+ *    glyph :: handle to glyph slot
+ *
+ ************************************************************************/
+
+  LOCAL_FUNC
+  void  T1_Done_Glyph_Hinter( T1_GlyphSlot  glyph )
+  {
+    FT_Memory  memory = glyph->root.face->memory;
+
+    FREE( glyph->hints );
+  }
+
+
+
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********                                                   *********/
+  /**********                                                   *********/
+  /**********              HINTED GLYPH LOADER                  *********/
+  /**********                                                   *********/
+  /**********   The following code is in charge of the first    *********/
+  /**********   and second pass when loading a single outline   *********/
+  /**********                                                   *********/
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********************************************************************/
+
+  static
+  T1_Error   t1_hinter_ignore( void )
+  {
+    /* do nothing, used for "dotsection" which is unsupported for now */
+    return 0;
+  }
+
+  static
+  T1_Error   t1_hinter_stem( T1_Builder*  builder,
+                             T1_Pos       pos,
+                             T1_Int       width,
+                             T1_Bool      vertical )
+  {
+    T1_Stem_Table*   stem_table;
+    T1_Stem_Hint*    stems;
+    T1_Stem_Hint*    cur_stem;
+    T1_Int           min, max, n, num_stems;
+    T1_Bool          new_stem;
+    T1_Glyph_Hints*  hinter = builder->glyph->hints;
+
+    /* select the appropriate stem array */
+    stem_table = vertical ? &hinter->vert_stems : &hinter->hori_stems;
+    stems      = stem_table->stems;
+    num_stems  = stem_table->num_stems;
+
+    /* Compute minimum and maximum orus for the stem */
+    min = pos + ( vertical
+                ? builder->left_bearing.x
+                : builder->left_bearing.y );
+
+    if ( width >= 0 )
+      max = min + width;
+    else
+    {
+      /* a negative width indicates a ghost stem */
+      if ( width == -21 )
+        min += width;
+
+      max = min;
+    }
+
+    /* now scan the array. If we find a stem with the same borders */
+    /* simply activate it..                                        */
+    cur_stem = stems;
+    new_stem = 1;
+
+    for ( n = 0; n < num_stems; n++, cur_stem++ )
+    {
+      if ( cur_stem->min_edge.orus == min &&
+           cur_stem->max_edge.orus == max )
+      {
+        /* This stem is already in the table, simply activate it */
+        if ( (cur_stem->hint_flags & T1_HINT_FLAG_ACTIVE) == 0)
+        {
+          cur_stem->hint_flags  |= T1_HINT_FLAG_ACTIVE;
+          stem_table->num_active ++;
+        }
+        new_stem = 0;
+        break;
+      }
+    }
+
+    /* add a new stem to the array when necessary */
+    if (new_stem)
+    {
+      if (cur_stem >= stems + T1_HINTER_MAX_EDGES)
+      {
+        FT_ERROR(( "T1.Hinter : too many stems in glyph charstring\n" ));
+        return T1_Err_Syntax_Error;
+      }
+
+      /* on the first pass, we record the stem, otherwise, this is */
+      /* a bug in the glyph loader !!                              */
+      if ( builder->pass == 0 )
+      {
+        cur_stem->min_edge.orus = min;
+        cur_stem->max_edge.orus = max;
+        cur_stem->hint_flags    = T1_HINT_FLAG_ACTIVE;
+
+        stem_table->num_stems++;
+        stem_table->num_active++;
+      }
+      else
+      {
+        FT_ERROR(( "T1.Hinter : fatal glyph loader bug - pass2-stem\n" ));
+        return T1_Err_Syntax_Error;
+      }
+    }
+
+    return T1_Err_Ok;
+  }
+
+
+  static
+  T1_Error   t1_hinter_stem3( T1_Builder*  builder,
+                              T1_Pos       pos0,
+                              T1_Int       width0,
+                              T1_Pos       pos1,
+                              T1_Int       width1,
+                              T1_Pos       pos2,
+                              T1_Int       width2,
+                              T1_Bool      vertical )
+  {
+    /* For now, don't be elitist and simply call "stem" 3 times */
+    return t1_hinter_stem( builder, pos0, width0, vertical ) ||
+           t1_hinter_stem( builder, pos1, width1, vertical ) ||
+           t1_hinter_stem( builder, pos2, width2, vertical );
+  }
+
+
+  static
+  T1_Error  t1_hinter_changehints( T1_Builder*  builder )
+  {
+    T1_Int           dimension;
+    T1_Stem_Table*   stem_table;
+    T1_Glyph_Hints*  hinter = builder->glyph->hints;
+
+    /* if we're in the second pass of glyph hinting, we must    */
+    /* call the function T1_Hint_Points on the builder in order */
+    /* to force the fit the latest points to the pixel grid     */
+    if ( builder->pass == 1 )
+      T1_Hint_Points( builder );
+
+    /* Simply de-activate all hints in all arrays */
+    stem_table = &hinter->hori_stems;
+
+    for ( dimension = 2; dimension > 0; dimension-- )
+    {
+      T1_Stem_Hint*  cur   = stem_table->stems;
+      T1_Stem_Hint*  limit = cur + stem_table->num_stems;
+
+      for ( ; cur < limit; cur++ )
+        cur->hint_flags &= ~T1_HINT_FLAG_ACTIVE;
+
+      stem_table->num_active = 0;
+      stem_table = &hinter->vert_stems;
+    }
+
+    return T1_Err_Ok;
+  }
+
+
+  LOCAL_FUNC
+  const T1_Hinter_Funcs  t1_hinter_funcs =
+  {
+    (T1_Hinter_ChangeHints)  t1_hinter_changehints,
+    (T1_Hinter_DotSection)   t1_hinter_ignore,
+    (T1_Hinter_Stem)         t1_hinter_stem,
+    (T1_Hinter_Stem3)        t1_hinter_stem3
+  };
+
+
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********                                                   *********/
+  /**********                                                   *********/
+  /**********              STEM HINTS MANAGEMENT                *********/
+  /**********                                                   *********/
+  /**********   The following code is in charge of computing    *********/
+  /**********   the placement of each scaled stem hint..        *********/
+  /**********                                                   *********/
+  /**********************************************************************/
+  /**********************************************************************/
+  /**********************************************************************/
+
+/************************************************************************
+ *
+ * <Function>
+ *    t1_sort_hints
+ *
+ * <Description>
+ *    Sort the list of active stems in increasing order, through
+ *    the "sort" indexing table
+ *
+ * <Input>
+ *    table  :: a stem hints table
+ *
+ ************************************************************************/
+
+  static
+  void  t1_sort_hints( T1_Stem_Table*  table )
+  {
+    T1_Int         num_stems   = table->num_stems;
+    T1_Int         num_active  = 0;
+    T1_Int*        sort        = table->sort;
+    T1_Stem_Hint*  stems       = table->stems;
+    T1_Int         n;
+
+    /* record active stems in sort table */
+    for ( n = 0; n < num_stems; n++ )
+    {
+      if ( stems[n].hint_flags & T1_HINT_FLAG_ACTIVE )
+        sort[num_active++] = n;
+    }
+
+    /* now sort the indices. There are usually very few stems, */
+    /* and they are pre-sorted in 90% cases, so we choose a    */
+    /* simple bubble sort (quicksort would be slower)..        */
+    for ( n = 1; n < num_active; n++ )
+    {
+      T1_Int        p   = n-1;
+      T1_Stem_Hint* cur = stems + sort[n];
+
+      do
+      {
+        T1_Int         swap;
+        T1_Stem_Hint*  prev = stems + sort[p];
+
+        /* note that by definition, the active stems cannot overlap    */
+        /* so we simply compare their "min" to sort them..             */
+        /* (we could compare their max, this wouldn't change anything) */
+        if ( prev->min_edge.orus <= cur->min_edge.orus )
+          break;
+
+        /* swap elements */
+        swap      = sort[ p ];
+        sort[ p ] = sort[p+1];
+        sort[p+1] = swap;
+        p--;
+      }
+      while ( p >= 0 );
+    }
+
+    table->num_active = num_active;
+  }
+
+
+/************************************************************************
+ *
+ * <Function>
+ *    t1_hint_horizontal_stems
+ *
+ * <Description>
+ *    Compute the location of each scaled horizontal stem hint.
+ *    This takes care of the blue zones and the horizontal stem
+ *    snap table
+ *
+ * <Input>
+ *    table     :: the horizontal stem hints table
+ *    hints     :: the current size's hint structure
+ *    blueShift :: the value of the /BlueShift as taken from the
+ *                 face object.                               
+ *    scale     :: the 16.16 scale used to convert outline
+ *                 units to 26.6 pixels
+ *
+ * <Note>
+ *    For now, all stems are hinted independently from each other.
+ *    It might be necessary, for better performance, to introduce
+ *    the notion of "controlled" hints describing things like
+ *    counter-stems, stem3 as well as overlapping stems control.
+ *
+ ************************************************************************/
+
+  static
+  void  t1_hint_horizontal_stems( T1_Stem_Table*  table,
+                                  T1_Size_Hints*  hints,
+                                  T1_Pos          blueShift,
+                                  T1_Fixed        scale )
+  {
+    T1_Stem_Hint*  stem      = table->stems;
+    T1_Stem_Hint*  limit     = stem + table->num_stems;
+
+    /* first of all, scale the blueShift */
+    blueShift = SCALE(blueShift);
+
+    /* then scan the horizontal stem table */
+    for ( ; stem < limit; stem++ )
+    {
+      T1_Pos  bottom_orus = stem->min_edge.orus;
+      T1_Pos  top_orus    = stem->max_edge.orus;
+
+      T1_Pos  top_pix     = SCALE( top_orus );
+      T1_Pos  bottom_pix  = SCALE( bottom_orus );
+      T1_Pos  width_pix   = top_pix - bottom_pix;
+
+      T1_Pos  bottom      = bottom_pix;
+      T1_Pos  top         = top_pix;
+      T1_Int  align       = T1_ALIGN_NONE;
+
+      /******************************************************************/
+      /* Snap pixel width if in stem snap range                         */
+      {
+        T1_Snap_Zone*  zone       = hints->snap_heights;
+        T1_Snap_Zone*  zone_limit = zone + hints->num_snap_heights;
+
+        for ( ; zone < zone_limit; zone++ )
+        {
+          if ( width_pix < zone->min )
+            break;
+
+          if ( width_pix <= zone->max )
+          {
+            width_pix = zone->pix;
+            break;
+          }
+        }
+      }
+
+      /******************************************************************/
+      /* round width - minimum 1 pixel if this isn't a ghost stem       */
+      if ( width_pix > 0 )
+        width_pix = ( width_pix < ONE_PIXEL ? ONE_PIXEL : ROUND(width_pix) );
+
+
+      /******************************************************************/
+      /* Now check for bottom blue zones alignement                     */
+      {
+        T1_Int         num_blues  = hints->num_bottom_zones;
+        T1_Snap_Zone*  blue       = hints->blue_zones;
+        T1_Snap_Zone*  blue_limit = blue + num_blues;
+
+        for ( ; blue < blue_limit; blue++ )
+        {
+          if ( bottom_pix < blue->min )
+            break;
+
+          if ( bottom_pix <= blue->max )
+          {
+            align  = T1_ALIGN_BOTTOM;
+            bottom = ROUND( blue->pix );
+
+            /* implements blue shift */
+            if (!hints->supress_overshoots)
+            {
+              T1_Pos  delta = blue->pix - bottom_pix;
+              
+              delta   = ( delta < blueShift ? 0 : ROUND( delta ) );
+              bottom -= delta;
+            }
+          }
+        }
+      }
+
+
+      /******************************************************************/
+      /* Check for top blue zones alignement */
+      {
+        T1_Int         num_blues  = hints->num_blue_zones - 
+                                    hints->num_bottom_zones;
+
+        T1_Snap_Zone*  blue       = hints->blue_zones +
+                                    hints->num_bottom_zones;
+
+        T1_Snap_Zone*  blue_limit = blue + num_blues;
+
+        for ( ; blue < blue_limit; blue++ )
+        {
+          if ( top_pix < blue->min )
+            break;
+
+          if ( top_pix <= blue->max )
+          {
+            align  |= T1_ALIGN_TOP;
+            top     = ROUND( blue->pix );
+
+            /* implements blue shift */
+            if (!hints->supress_overshoots)
+            {
+              T1_Pos  delta = top - blue->pix;
+              
+              delta  = ( delta < blueShift ? 0 : ROUND( delta ) );
+              top   += delta;
+            }
+          }
+        }
+      }
+
+
+      /******************************************************************/
+      /* compute the hinted stem position, according to its alignment   */
+      switch (align)
+      {
+        case T1_ALIGN_BOTTOM:  /* bottom zone alignement */
+          bottom_pix = bottom;
+          top_pix    = bottom + width_pix;
+          break;
+          
+        case T1_ALIGN_TOP:  /* top zone alignement */
+          top_pix    = top;
+          bottom_pix = top - width_pix;
+          
+          break;
+          
+        case T1_ALIGN_BOTH:  /* bottom+top zone alignement */
+          bottom_pix = bottom;
+          top_pix    = top;
+          break;
+          
+        default:  /* no alignement */
+
+          /* XXXX : TODO : Add management of controlled stems */        
+          bottom = ( SCALE(bottom_orus+top_orus) - width_pix )/2;
+        
+          bottom_pix = ROUND(bottom);
+          top_pix    = bottom_pix + width_pix;
+      }
+      
+      stem->min_edge.pix = bottom_pix;
+      stem->max_edge.pix = top_pix;
+    }
+  }
+
+
+
+
+/************************************************************************
+ *
+ * <Function>
+ *    t1_hint_vertical_stems
+ *
+ * <Description>
+ *    Compute the location of each scaled vertical stem hint.
+ *    This takes care of the vertical stem snap table
+ *
+ * <Input>
+ *    table     :: the vertical stem hints table
+ *    hints     :: the current size's hint structure
+ *    scale     :: the 16.16 scale used to convert outline
+ *                 units to 26.6 pixels
+ *
+ * <Note>
+ *    For now, all stems are hinted independently from each other.
+ *    It might be necessary, for better performance, to introduce
+ *    the notion of "controlled" hints describing things like
+ *    counter-stems, stem3 as well as overlapping stems control.
+ *
+ ************************************************************************/
+
+  /* compute the location of each scaled vertical stem hint. */
+  /* Take care of blue zones and stem snap table             */
+  static
+  void  t1_hint_vertical_stems( T1_Stem_Table*  table,
+                                T1_Size_Hints*  hints,
+                                T1_Fixed        scale )
+  {
+    T1_Stem_Hint*  stem  = table->stems;
+    T1_Stem_Hint*  limit = stem + table->num_stems;
+
+    for ( ; stem < limit; stem++ )
+    {
+      T1_Pos  stem_left  = stem->min_edge.orus;
+      T1_Pos  stem_right = stem->max_edge.orus;
+      T1_Pos  width_pix, left;
+
+      width_pix = SCALE( stem_right - stem_left );
+
+      /* Snap pixel width if in stem snap range */
+      {
+        T1_Snap_Zone*  zone       = hints->snap_widths;
+        T1_Snap_Zone*  zone_limit = zone + hints->num_snap_widths;
+
+        for ( ; zone < zone_limit; zone++ )
+        {
+          if ( width_pix < zone->min )
+            break;
+
+          if ( width_pix <= zone->max )
+          {
+            width_pix = zone->pix;
+            break;
+          }
+        }
+      }
+   
+      /* round width - minimum 1 pixel if this isn't a ghost stem */
+      if ( width_pix > 0 )
+        width_pix = ( width_pix < ONE_PIXEL ? ONE_PIXEL :
+                                              ROUND( width_pix ) );
+
+      /* now place the snapped and rounded stem   */
+
+      /* XXXX : TODO : implement controlled stems for the overlapping */
+      /*               cases..                                        */
+
+      left = ( SCALE(stem_left+stem_right) - width_pix )/2;
+
+      stem->min_edge.pix = ROUND(left);
+      stem->max_edge.pix = stem->min_edge.pix + width_pix;
+    }
+  }
+
+
+
+
+/************************************************************************
+ *
+ * <Function>
+ *    t1_hint_point
+ *
+ * <Description>
+ *    Grid-fit a coordinate with regards to a given stem hints table
+ *
+ * <Input>
+ *    table  :: the source stem hints table
+ *    coord  :: original coordinate, expressed in font units
+ *    scale  :: the 16.16 scale used to convert font units into
+ *              26.6 pixels
+ *
+ * <Return>
+ *    the hinted/scaled value in 26.6 pixels
+ *
+ * <Note>
+ *    For now, all stems are hinted independently from each other.
+ *    It might be necessary, for better performance, to introduce
+ *    the notion of "controlled" hints describing things like
+ *    counter-stems, stem3 as well as overlapping stems control.
+ *
+ ************************************************************************/
+
+  static
+  T1_Pos  t1_hint_point( T1_Stem_Table*  table,
+                         T1_Pos          coord,
+                         T1_Fixed        scale )
+  {
+    T1_Int         num_active = table->num_active;
+    T1_Int         n;
+    T1_Stem_Hint*  prev = 0;
+    T1_Stem_Hint*  cur  = 0;
+    T1_Edge*       min;
+    T1_Edge*       max;
+    T1_Pos         delta;
+
+    /* only hint when there is at least one stem defined */
+    if (num_active <= 0)
+      return SCALE(coord);
+
+    /* scan the stem table to determine placement of coordinate */
+    /* relative to the list of sorted and stems                 */
+    for ( n = 0; n < num_active; n++, prev = cur )
+    {
+      cur = table->stems + table->sort[n];
+
+      /* is it on the left of the current edge ? */
+      delta = cur->min_edge.orus - coord;
+      if ( delta == 0 ) return cur->min_edge.pix;
+
+      if (delta > 0)
+      {
+        /* if this is the left of the first edge, simply shift */
+        if (!prev) return cur->min_edge.pix - SCALE(delta);
+
+        /* otherwise, interpolate between the maximum of the */
+        /* previous stem, and the minimum of the current one */
+        min = &prev->max_edge;
+        max = &cur->min_edge;
+        goto Interpolate;
+      }
+
+      /* is it within the current edge ? */
+      delta = cur->max_edge.orus - coord;
+      if ( delta == 0 ) return cur->max_edge.pix;
+
+      if (delta > 0)
+      {
+        /* interpolate within the stem */
+        min = &cur->min_edge;
+        max = &cur->max_edge;
+        goto Interpolate;
+      }
+    }
+
+    /* apparently, this coordinate is on the right of the last stem */
+    delta = coord - cur->max_edge.orus;
+    return cur->max_edge.pix + SCALE(delta);
+
+  Interpolate:
+    return min->pix +
+            FT_MulDiv( coord     - min->orus,
+                       max->pix  - min->pix,
+                       max->orus - min->orus );
+  }
+
+
+
+
+
+
+#if 1
+
+/************************************************************************
+ *
+ * <Function>
+ *   T1_Hint_Points
+ *
+ * <Description>
+ *   this function grid-fits several points in a given Type 1 builder
+ *   at once. 
+ *
+ * <Input>
+ *   builder  :: handle to target Type 1 builder
+ *   first    :: first point to hint in builder's current outline
+ *   last     :: last point to hint in builder's current outline
+ *
+ ************************************************************************/
+
+  LOCAL_FUNC
+  void  T1_Hint_Points( T1_Builder*  builder )
+  {
+    T1_Int    first   = builder->hint_point;
+    T1_Int    last    = builder->current.n_points-1;
+
+    T1_Size   size    = builder->size;
+    T1_Fixed  scale_x = size->root.metrics.x_scale;
+    T1_Fixed  scale_y = size->root.metrics.y_scale;
+
+    T1_Glyph_Hints*  hints      = builder->glyph->hints;
+    T1_Stem_Table*   hori_stems = &hints->hori_stems;
+    T1_Stem_Table*   vert_stems = &hints->vert_stems;
+
+    T1_Vector*  cur   = builder->current.points + first;
+    T1_Vector*  limit = cur + last - first + 1;
+
+    /* first of all, sort the active stem hints */
+    t1_sort_hints( hori_stems );
+    t1_sort_hints( vert_stems );
+
+    for ( ; cur < limit; cur++ )
+    {
+      cur->x = t1_hint_point( vert_stems, cur->x, scale_x );
+      cur->y = t1_hint_point( hori_stems, cur->y, scale_y );
+    }
+
+    builder->hint_point = builder->current.n_points;
+  }
+
+
+/************************************************************************
+ *
+ * <Function>
+ *    T1_Hint_Stems
+ *
+ * <Description>
+ *    This function is used to compute the location of each stem hint
+ *    between the first and second passes of the glyph loader on the
+ *    charstring.
+ *
+ * <Input>
+ *    builder :: handle to target builder
+ *
+ ************************************************************************/
+
+  LOCAL_FUNC
+  void  T1_Hint_Stems( T1_Builder*  builder )
+  {
+    T1_Glyph_Hints*  hints = builder->glyph->hints;
+    T1_Font*         priv  = &builder->face->type1;
+
+    T1_Size   size    = builder->size;
+    T1_Fixed  scale_x = size->root.metrics.x_scale;
+    T1_Fixed  scale_y = size->root.metrics.y_scale;
+
+    t1_hint_horizontal_stems( &hints->hori_stems,
+                              builder->size->hints,
+                              priv->blue_shift,
+                              scale_y );
+
+    t1_hint_vertical_stems( &hints->vert_stems,
+                            builder->size->hints,
+                            scale_x );
+  }
+
+#endif
--- /dev/null
+++ b/src/type1z/t1hinter.h
@@ -1,0 +1,380 @@
+/*******************************************************************
+ *
+ *  t1hinter.h                                                 1.2
+ *
+ *    Type1 hinter.         
+ *
+ *  Copyright 1996-1999 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ *  This file is part of the FreeType project, and may only be used
+ *  modified and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ *
+ *  The Hinter is in charge of fitting th scaled outline to the
+ *  pixel grid in order to considerably improve the quality of
+ *  the Type 1 font driver's output..
+ *
+ ******************************************************************/
+
+#ifndef T1HINTER_H
+#define T1HINTER_H
+
+#include <t1objs.h>
+#include <t1gload.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+/************************************************************************
+ *
+ * <Struct>
+ *   T1_Snap_Zone
+ *
+ * <Description>
+ *   A "snap zone" is used to model either a blue zone or a stem width
+ *   at a given character size. It is made of a minimum and maximum
+ *   edge, defined in 26.6 pixels, as well as one "original" and
+ *   "scaled" position.
+ *
+ *   the position corresponds to the stem width (for stem snap zones)
+ *   or to the blue position (for blue zones)
+ *
+ * <Fields>
+ *   orus  :: original position in font units
+ *   pix   :: current position in sub-pixel units
+ *   min   :: minimum boundary in sub-pixel units
+ *   max   :: maximim boundary in sub-pixel units
+ *
+ ************************************************************************/
+
+  typedef struct T1_Snap_Zone_
+  {
+    T1_Pos  orus;
+    T1_Pos  pix; 
+    T1_Pos  min; 
+    T1_Pos  max;  
+  
+  } T1_Snap_Zone;
+
+
+/************************************************************************
+ *
+ * <Struct>
+ *   T1_Edge
+ *
+ * <Description>
+ *   A very simply structure used to model an stem edge
+ *
+ * <Fields>
+ *   orus  :: original edge position in font units
+ *   pix   :: scaled edge position in sub-pixel units
+ *
+ ************************************************************************/
+
+  typedef struct T1_Edge_
+  {
+    T1_Pos  orus;
+    T1_Pos  pix;  
+  
+  } T1_Edge;
+
+
+/************************************************************************
+ *
+ * <Struct>
+ *    T1_Stem_Hint
+ *
+ * <Description>
+ *    A simple structure used to model a stem hint
+ *
+ * <Fields>
+ *    min_edge   :: the hint's minimum edge
+ *    max_edge   :: the hint's maximum edge
+ *    hint_flags :: some flags describing the stem properties
+ *
+ * <Note>
+ *    the min and max edges of a ghost stem have the same position,
+ *    even if they're coded in a weird way in the charstrings
+ *
+ ************************************************************************/
+
+  typedef struct T1_Stem_Hint_
+  {
+    T1_Edge  min_edge;
+    T1_Edge  max_edge;
+    T1_Int   hint_flags;
+
+  } T1_Stem_Hint;
+
+
+#define T1_HINT_FLAG_ACTIVE      1    /* indicates an active stem */
+#define T1_HINT_FLAG_MIN_BORDER  2    /* unused for now..         */
+#define T1_HINT_FLAG_MAX_BORDER  4    /* unused for now..         */
+
+
+/* hinter's configuration constants */
+#define T1_HINTER_MAX_BLUES    24    /* maximum number of blue zones      */
+#define T1_HINTER_MAX_SNAPS    16    /* maximum number of stem snap zones */
+#define T1_HINTER_MAX_EDGES    64    /* maximum number of stem hints      */
+
+
+/************************************************************************
+ *
+ * <Struct>
+ *   T1_Size_Hints
+ *
+ * <Description>
+ *   A structure used to model the hinting information related to
+ *   a size object
+ *
+ * <Fields>
+ *   supress_overshoots :: a boolean flag to tell when overshoot
+ *                         supression should occur.
+ *
+ *   num_blue_zones     :: the total number of blue zones (top+bottom)
+ *   num_bottom_zones   :: the number of bottom zones
+ *
+ *   blue_zones         :: the blue zones table. bottom zones are
+ *                         stored first in the table, followed by
+ *                         all top zones
+ *
+ *   num_stem_snapH     :: number of horizontal stem snap zones
+ *   stem_snapH         :: horizontal stem snap zones
+ *
+ *   num_stem_snapV     :: number of vertical stem snap zones
+ *   stem_snapV         :: vertical stem snap zones
+ *
+ ************************************************************************/
+
+  struct T1_Size_Hints_
+  {
+    T1_Bool       supress_overshoots;
+
+    T1_Int        num_blue_zones;
+    T1_Int        num_bottom_zones;
+    T1_Snap_Zone  blue_zones[ T1_HINTER_MAX_BLUES ];
+
+    T1_Int        num_snap_widths;
+    T1_Snap_Zone  snap_widths[ T1_HINTER_MAX_SNAPS ];
+
+    T1_Int        num_snap_heights;
+    T1_Snap_Zone  snap_heights[ T1_HINTER_MAX_SNAPS ];
+  };
+
+
+
+/************************************************************************
+ *
+ * <Struct>
+ *    T1_Stem_Table
+ *
+ * <Description>
+ *    A simple structure used to model a set of stem hints in a
+ *    single direction during the loading of a given glyph outline.
+ *    Not all stem hints are active at a time. Moreover, stems must
+ *    be sorted regularly
+ *
+ * <Fields>
+ *    num_stems   :: total number of stems in table
+ *    num_active  :: number of active stems in table
+ *
+ *    stems       :: the table of all stems
+ *    sort        :: a table of indices into the stems table, used
+ *                   to keep a sorted list of the active stems
+ *
+ ************************************************************************/
+
+  typedef struct T1_Stem_Table_
+  {
+    T1_Int        num_stems;
+    T1_Int        num_active;
+
+    T1_Stem_Hint  stems[ T1_HINTER_MAX_EDGES ];
+    T1_Int        sort [ T1_HINTER_MAX_EDGES ];
+
+  } T1_Stem_Table;
+
+
+
+/************************************************************************
+ *
+ * <Struct>
+ *   T1_Glyph_Hints
+ *
+ * <Description>
+ *   A structure used to model the stem hints of a given glyph outline
+ *   during glyph loading. 
+ *
+ * <Fields>
+ *   hori_stems  :: horizontal stem hints table
+ *   vert_stems  :: vertical stem hints table
+ *
+ ************************************************************************/
+
+  struct T1_Glyph_Hints_
+  {
+    T1_Stem_Table  hori_stems;
+    T1_Stem_Table  vert_stems;
+  };
+
+
+
+/************************************************************************
+ *
+ * <Data>
+ *    t1_hinter_funcs
+ *
+ * <Description>
+ *    A table containing the address of various functions used during
+ *    the loading of an hinted scaled outline
+ *
+ ************************************************************************/
+
+  LOCAL_DEF
+  const T1_Hinter_Funcs  t1_hinter_funcs;
+
+
+/************************************************************************
+ *
+ * <Function>
+ *    T1_New_Size_Hinter
+ *
+ * <Description>
+ *    Allocates a new hinter structure for a given size object
+ *
+ * <Input>
+ *    size :: handle to target size object
+ *
+ * <Return>
+ *    Error code. 0 means success
+ *
+ ************************************************************************/
+
+  LOCAL_DEF
+  T1_Error  T1_New_Size_Hinter( T1_Size  size );
+
+
+/************************************************************************
+ *
+ * <Function>
+ *    T1_Done_Size_Hinter
+ *
+ * <Description>
+ *    Releases a given size object's hinter structure
+ *
+ * <Input>
+ *    size :: handle to target size object
+ *
+ ************************************************************************/
+
+  LOCAL_DEF
+  void      T1_Done_Size_Hinter( T1_Size  size );
+
+
+/************************************************************************
+ *
+ * <Function>
+ *    T1_Reset_Size_Hinter
+ *
+ * <Description>
+ *    Recomputes hinting information when a given size object has
+ *    changed its resolutions/char sizes/pixel sizes
+ *
+ * <Input>
+ *    size :: handle to size object
+ *
+ * <Return>
+ *    Error code. 0 means success
+ *
+ ************************************************************************/
+
+  LOCAL_DEF
+  T1_Error  T1_Reset_Size_Hinter( T1_Size  size );
+
+
+/************************************************************************
+ *
+ * <Function>
+ *    T1_New_Glyph_Hinter
+ *
+ * <Description>
+ *    Allocates a new hinter structure for a given glyph slot
+ *
+ * <Input>
+ *    glyph :: handle to target glyph slot
+ *
+ * <Return>
+ *    Error code. 0 means success
+ *
+ ************************************************************************/
+
+  LOCAL_DEF
+  T1_Error  T1_New_Glyph_Hinter( T1_GlyphSlot  glyph );
+
+
+/************************************************************************
+ *
+ * <Function>
+ *    T1_Done_Glyph_Hinter
+ *
+ * <Description>
+ *    Releases a given glyph slot's hinter structure
+ *
+ * <Input>
+ *    glyph :: handle to glyph slot
+ *
+ ************************************************************************/
+
+  LOCAL_DEF
+  void      T1_Done_Glyph_Hinter( T1_GlyphSlot  glyph );
+
+
+
+
+/************************************************************************
+ *
+ * <Function>
+ *   T1_Hint_Points
+ *
+ * <Description>
+ *   this function grid-fits several points in a given Type 1 builder
+ *   at once. 
+ *
+ * <Input>
+ *   builder  :: handle to target Type 1 builder
+ *
+ ************************************************************************/
+
+  LOCAL_DEF
+  void  T1_Hint_Points( T1_Builder*  builder );
+
+
+/************************************************************************
+ *
+ * <Function>
+ *    T1_Hint_Stems
+ *
+ * <Description>
+ *    This function is used to compute the location of each stem hint
+ *    between the first and second passes of the glyph loader on the
+ *    charstring.
+ *
+ * <Input>
+ *    builder :: handle to target builder
+ *
+ ************************************************************************/
+
+  LOCAL_DEF
+  void  T1_Hint_Stems( T1_Builder*  builder );
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* T1HINTER_H */
--- /dev/null
+++ b/src/type1z/t1load.c
@@ -1,0 +1,741 @@
+/*******************************************************************
+ *
+ *  t1load.h                                                    2.0
+ *
+ *    Type1 Loader.                          
+ *
+ *  Copyright 1996-2000 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ *  This file is part of the FreeType project, and may only be used
+ *  modified and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ *
+ *  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 and they are
+ *  handled with a special pattern-matching routine.
+ *
+ *  All other common cases are handled very simply. The matching
+ *  rules are defined in the file "t1tokens.h" through the use
+ *  of several macros calls PARSE_XXXX
+ *
+ *  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 <ftdebug.h>
+
+#include <t1types.h>
+#include <t1errors.h>
+#include <t1encode.h>
+#include <t1config.h>
+#include <t1load.h>
+
+#include <stdio.h>
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1load
+
+  typedef  void  (*T1_Parse_Func)( T1_Face   face, T1_Loader*  loader );
+
+  typedef  struct T1_KeyWord_  
+  {
+    const char*    name;
+    T1_Parse_Func  parsing;
+  
+  } T1_KeyWord;
+
+  /* some handy macros used to easily define parsing callback functions */
+  /* each callback is in charge of loading a value and storing it in a  */
+  /* given field of the Type 1 face..                                   */
+ 
+#define PARSE_(x)  static void parse_##x##( T1_Face  face, T1_Loader* loader )
+
+#define PARSE_STRING(s,x)   PARSE_(x)                               \
+        {                                                           \
+          FACE.##x = T1_ToString(&loader->parser);                  \
+          FT_TRACE2(( "type1.parse_##x##: \"%s\"\n", FACE.##x ));   \
+        }
+           
+#define PARSE_INT(s,x)   PARSE_(x)                                  \
+        {                                                           \
+          FACE.##x = T1_ToInt(&loader->parser);                     \
+          FT_TRACE2(( "type1.parse_##x##: \"%d\"\n", FACE.##x ));   \
+        }
+           
+#define PARSE_BOOL(s,x)   PARSE_(x)                                 \
+        {                                                           \
+          FACE.##x = T1_ToBool(&loader->parser);                    \
+          FT_TRACE2(( "type1.parse_##x##: \"%s\"\n",                \
+                       FACE.##x ? "true" : "false" ));              \
+        }
+ 
+#define PARSE_FIXED(s,x)   PARSE_(x)                                        \
+        {                                                                   \
+          FACE.##x = T1_ToFixed(&loader->parser,3);                         \
+          FT_TRACE2(( "type1.parse_##x##: \"%f\"\n", FACE.##x/65536.0 ));   \
+        }
+ 
+#define PARSE_COORDS(s,c,m,x)   PARSE_(x)                                         \
+        {                                                                         \
+          FACE.##c = T1_ToCoordArray(&loader->parser, m, (T1_Short*)FACE.##x );   \
+          FT_TRACE2(( "type1.parse_##x##\n" ));                                   \
+        }
+           
+#define PARSE_FIXEDS(s,c,m,x)   PARSE_(x)                                           \
+        {                                                                           \
+          FACE.##c = T1_ToFixedArray(&loader->parser, m, (T1_Fixed*)FACE.##x, 3 );  \
+          FT_TRACE2(( "type1.parse_##x##\n" ));                                     \
+        }
+
+
+#define PARSE_COORDS2(s,m,x)   PARSE_(x)                                     \
+        {                                                                    \
+          (void)T1_ToCoordArray( &loader->parser, m, (T1_Short*)&FACE.##x );  \
+          FT_TRACE2(( "type1.parse_##x##\n" ));                              \
+        }
+
+#define PARSE_FIXEDS2(s,m,x)   PARSE_(x)                                           \
+        {                                                                           \
+          (void)T1_ToFixedArray(&loader->parser, m, (T1_Fixed*)&FACE.##x, 3 );  \
+          FT_TRACE2(( "type1.parse_##x##\n" ));                                     \
+        }
+
+
+/* define all parsing callbacks */
+#include <t1tokens.h>
+
+
+  static
+  int  is_space( char c )
+  {
+    return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
+  }
+
+  static
+  int  is_alpha( char c )
+  {
+    return ( (c >= 'A' && c <= 'Z') ||
+             (c >= 'a' && c <= 'z') ||
+             (c >= '0' && c <= '9') ||
+             (c == '.')             ||
+             (c == '_') );
+  }
+
+  static
+  void  skip_whitespace( T1_Parser* parser )
+  {
+    T1_Byte*  cur = parser->cursor;
+    
+    while ( cur < parser->limit && is_space(*cur) )
+      cur++;
+      
+    parser->cursor = cur;
+  }
+  
+  static
+  void skip_blackspace( T1_Parser* parser )
+  {
+    T1_Byte*  cur = parser->cursor;
+    
+    while ( cur < parser->limit && !is_space(*cur) )
+      cur++;
+      
+    parser->cursor = cur;
+  }
+  
+  static
+  int   read_binary_data( T1_Parser*  parser, T1_Int *size, T1_Byte* *base )
+  {
+    T1_Byte*  cur;
+    T1_Byte*  limit = parser->limit;
+    
+    /* the binary data has the following format */
+    /*                                          */
+    /* "size" [white*] RD white ....... ND      */
+    /*                                          */
+    
+    skip_whitespace(parser);
+    cur = parser->cursor;
+    
+    if ( cur < limit && (T1_Byte)(*cur-'0') < 10 )
+    {
+      *size = T1_ToInt(parser);
+      
+      skip_whitespace(parser);
+      skip_blackspace(parser);  /* "RD" or "-|" or something else */
+      
+      /* there is only one whitespace char after the */
+      /* "RD" or "-|" token                          */
+      *base = parser->cursor + 1;
+      
+      parser->cursor += *size+1;
+      return 1;
+    }
+
+    FT_ERROR(( "type1.read_binary_data: invalid size field\n" ));
+    parser->error = FT_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, T1_Loader*  loader )
+  {
+    T1_Parser*  parser = &loader->parser;
+    FT_Error    error;
+    FT_Memory   memory = parser->memory;
+    T1_Int      len;
+    T1_Byte*    cur;
+    T1_Byte*    cur2;
+    T1_Byte*    limit;
+    
+    skip_whitespace(parser);
+    cur   = parser->cursor;
+    limit = parser->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->error = error;
+        return;
+      }
+      
+      MEM_Copy( face->type1.font_name, cur, len );
+      face->type1.font_name[len] = '\0';
+    }
+    parser->cursor = cur2;
+  }
+
+  static
+  void  parse_font_bbox( T1_Face  face, T1_Loader*  loader )
+  {
+    T1_Parser*  parser = &loader->parser;
+    T1_Short    temp[4];
+    T1_BBox*    bbox = &face->type1.font_bbox;
+    
+    (void)T1_ToCoordArray( parser, 4, temp );
+    bbox->xMin = temp[0];
+    bbox->yMin = temp[1];
+    bbox->xMax = temp[2];
+    bbox->yMax = temp[3];
+  }
+
+  static
+  void  parse_encoding( T1_Face  face, T1_Loader*  loader )
+  {
+    T1_Parser*  parser = &loader->parser;
+    T1_Byte*    cur   = parser->cursor;
+    T1_Byte*    limit = parser->limit;
+    
+    /* skip whitespace */
+    while (is_space(*cur))
+    {
+      cur++;
+      if (cur >= limit)
+      {
+        FT_ERROR(( "type1.parse_encoding: out of bounds !!\n" ));
+        parser->error = FT_Err_Invalid_File_Format;
+        return;
+      }
+    }
+    
+    /* if we have a number, then the encoding is an array, */
+    /* and we must load it now                             */
+    if ((T1_Byte)(*cur - '0') < 10)
+    {
+      T1_Encoding*  encode     = &face->type1.encoding;
+      T1_Int        count, n;
+      T1_Table*     char_table = &loader->encoding_table;
+      FT_Memory     memory     = parser->memory;
+      FT_Error      error;
+      
+      /* read the number of entries in the encoding, should be 256 */
+      count = T1_ToInt( parser );
+      if (parser->error) return;
+
+      /* we use a T1_Table to store our charnames */
+      encode->num_chars = count;
+      if ( ALLOC_ARRAY( encode->char_index, count, T1_Short   ) ||
+           ALLOC_ARRAY( encode->char_name,  count, T1_String* ) ||
+           (error = T1_New_Table( char_table, count, memory )) != 0     )
+      {
+        parser->error = error;
+        return;
+      }
+      
+      /* 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->cursor;
+      limit = parser->limit;
+      n     = 0;
+
+      for ( ; cur < limit; )
+      {
+        T1_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[3]) )
+            break;
+        }
+        
+        /* otherwise, we must find a number before anything else */
+        if ( (T1_Byte)(c-'0') < 10 )
+        {
+          T1_Int  charcode;
+          
+          parser->cursor = cur;
+          charcode = T1_ToInt(parser);
+          cur = parser->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;
+            T1_Int    len;
+            
+            while (cur2 < limit && is_alpha(*cur2)) cur2++;
+            len = cur2-cur-1;
+            parser->error = T1_Add_Table( char_table, charcode, cur+1, len+1 );
+            char_table->elements[charcode][len] = '\0';
+            if (parser->error) return;
+            
+            cur = cur2;
+          }
+        }
+        else
+          cur++;
+      }
+      
+      face->type1.encoding_type = t1_encoding_array;
+    }
+    /* Otherwise, we should have either "StandardEncoding" or */
+    /* "ExpertEncoding"                                       */
+    else
+    {
+      if ( cur+17 < limit && strncmp( cur, "StandardEncoding", 16 ) == 0 )
+        face->type1.encoding_type = t1_encoding_standard;
+        
+      else if (cur+15 < limit && strncmp( cur, "ExpertEncoding", 14 ) == 0 )
+        face->type1.encoding_type = t1_encoding_expert;
+
+      else
+      {
+        FT_ERROR(( "type1.parse_encoding: invalid token !!\n" ));
+        parser->error = FT_Err_Invalid_File_Format;
+      }      
+    }
+  }
+
+
+  static
+  void  parse_subrs( T1_Face  face, T1_Loader*  loader )
+  {
+    T1_Parser*  parser = &loader->parser;
+    T1_Table*   table  = &loader->subrs;
+    FT_Memory   memory = parser->memory;
+    FT_Error    error;
+    T1_Int      n;
+    
+    loader->num_subrs = T1_ToInt( parser );    
+    if (parser->error) return;
+    
+    /* initialise subrs array */
+    error = T1_New_Table( table, loader->num_subrs, memory );
+    if (error) goto Fail;
+
+    /* the format is simple :                                */
+    /*                                                       */
+    /*   "index" + binary data                               */
+    /*                                                       */
+    
+    for ( n = 0; n < loader->num_subrs; n++ )
+    {
+      T1_Int    index, size;
+      T1_Byte*  base;
+      
+      index = T1_ToInt(parser);
+      if (!read_binary_data(parser,&size,&base)) return;
+      
+      error = T1_Add_Table( table, index, base, size );
+      if (error) goto Fail;
+    }
+    return;
+
+  Fail:
+    parser->error = error;
+  }
+
+
+
+
+  static
+  void  parse_charstrings( T1_Face  face, T1_Loader*  loader )
+  {
+    T1_Parser*  parser     = &loader->parser;
+    T1_Table*   code_table = &loader->charstrings;
+    T1_Table*   name_table = &loader->glyph_names;
+    FT_Memory   memory     = parser->memory;
+    FT_Error    error;
+
+    T1_Byte*    cur;
+    T1_Byte*    limit = parser->limit;
+    T1_Int      n;
+    
+    loader->num_glyphs = T1_ToInt( parser );    
+    if (parser->error) return;
+    
+    /* initialise tables */
+    error = T1_New_Table( code_table, loader->num_glyphs, memory ) ||
+            T1_New_Table( name_table, loader->num_glyphs, memory );
+    if (error) goto Fail;
+    
+    n = 0;
+    for ( ;; )
+    {
+      T1_Int    size;
+      T1_Byte*  base;
+      
+      /* the format is simple :                   */
+      /*   "/glyphname" + binary data             */
+      /*                                          */
+      /* note that we stop when we find a "def"   */
+      /*                                          */
+      skip_whitespace(parser);
+      cur = parser->cursor;
+      if (cur >= limit) break;
+
+      /* we stop when we find a "def" */
+      if (*cur    == 'd' && 
+           cur+3 < limit &&
+           cur[1] == 'e' &&
+           cur[2] == 'f' )
+        break;
+
+      if (*cur != '/')
+        skip_blackspace(parser);
+      else
+      {
+        T1_Byte*  cur2 = cur+1;
+        T1_Int    len;
+        
+        while (cur2 < limit && is_alpha(*cur2)) cur2++;
+        len = cur2-cur-1;
+        error = T1_Add_Table( name_table, n, cur+1, len+1 );
+        if (error) goto Fail;
+       
+        /* add a trailing zero to the name table */
+        name_table->elements[n][len] = '\0';
+       
+        parser->cursor = cur2; 
+        if (!read_binary_data(parser,&size,&base)) return;
+      
+        error = T1_Add_Table( code_table, n, base, size );
+        if (error) goto Fail;
+        
+        n++;
+        if (n >= loader->num_glyphs)
+          break;
+      }
+    }
+    return;
+    
+  Fail:
+    parser->error = error;
+  }
+
+
+#undef PARSE_STRING
+#undef PARSE_INT
+#undef PARSE_BOOL
+#undef PARSE_FIXED
+#undef PARSE_COORDS
+#undef PARSE_FIXEDS
+#undef PARSE_COORDS2
+#undef PARSE_FIXEDS2
+
+#undef PARSE_
+#define PARSE_(s,x)   { s, parse_##x },
+
+#define PARSE_STRING(s,x)      PARSE_(s,x)
+#define PARSE_INT(s,x)         PARSE_(s,x)
+#define PARSE_BOOL(s,x)        PARSE_(s,x)
+#define PARSE_FIXED(s,x)       PARSE_(s,x)
+#define PARSE_COORDS(s,c,m,x)  PARSE_(s,x)
+#define PARSE_FIXEDS(s,c,m,x)  PARSE_(s,x)
+#define PARSE_COORDS2(s,m,x)   PARSE_(s,x)
+#define PARSE_FIXEDS2(s,m,x)   PARSE_(s,x)
+
+  static
+  const T1_KeyWord  t1_keywords[] =
+  {
+#include <t1tokens.h>
+    /* now add the special functions... */
+    { "FontName",    parse_font_name   },
+    { "FontBBox",    parse_font_bbox   },
+    { "Encoding",    parse_encoding    },
+    { "Subrs",       parse_subrs       },
+    { "CharStrings", parse_charstrings },
+    { 0, 0 }
+  };
+
+
+  static
+  T1_Error  parse_dict( T1_Face     face,
+                        T1_Loader*  loader,
+                        T1_Byte*    base,
+                        T1_Int      size )
+  {
+    T1_Parser*  parser = &loader->parser;
+    
+    parser->cursor = base;
+    parser->limit  = base + size;
+    parser->error  = 0;
+    
+    {
+      T1_Byte*  cur   = base;
+      T1_Byte*  limit = cur + size;
+      
+      for ( ;cur < limit; cur++ )
+      {
+        /* look for immediates */
+        if (*cur == '/' && cur+2 < limit)
+        {
+          T1_Byte* cur2;
+          T1_Int   len;
+          
+          cur  ++;
+          cur2 = cur;
+          while (cur2 < limit && is_alpha(*cur2)) cur2++;
+          len  = cur2-cur;
+          
+          if (len > 0)
+          {
+            /* now, compare the immediate name to the keyword table */
+            T1_KeyWord*  keyword = (T1_KeyWord*)t1_keywords;
+            
+            for (;;)
+            {
+              T1_Byte*  name;
+              
+              name = (T1_Byte*)keyword->name;
+              if (!name) break;
+
+              if (cur[0] == name[0] && len == strlen(name) )
+              {
+                T1_Int  n;
+                for ( n = 1; n < len; n++ )
+                  if (cur[n] != name[n])
+                    break;
+                    
+                if (n >= len)
+                {
+                  /* we found it - run the parsing callback !! */
+                  parser->cursor = cur2;
+                  skip_whitespace( parser );
+                  keyword->parsing( face, loader );
+                  if (parser->error)
+                    return parser->error;
+
+                  cur = parser->cursor;
+                }
+              }
+              keyword++;
+            }
+          }
+        }
+      }
+    }
+    return parser->error;
+  }
+
+  static
+  void t1_init_loader( T1_Loader* loader, T1_Face  face )
+  {
+    loader->num_glyphs = 0;
+    loader->num_chars  = 0;
+    
+    loader->encoding_table.init = 0;
+    loader->charstrings.init    = 0;
+    loader->glyph_names.init    = 0;
+    loader->subrs.init          = 0;
+  }
+  
+  static
+  void t1_done_loader( T1_Loader* loader )
+  {
+    T1_Parser*  parser = &loader->parser;
+    
+    /* finalize tables */
+    T1_Release_Table( &loader->encoding_table );
+    T1_Release_Table( &loader->charstrings );
+    T1_Release_Table( &loader->glyph_names );
+    T1_Release_Table( &loader->subrs );
+    
+    /* finalize parser */
+    T1_Done_Parser( parser );
+  }
+
+  LOCAL_FUNC
+  T1_Error  T1_Open_Face( T1_Face  face )
+  {
+    T1_Loader  loader;
+    T1_Parser* parser;
+    T1_Font*   type1 = &face->type1;
+    FT_Error   error;
+
+    t1_init_loader( &loader, face );
+
+    /* default lenIV */
+    type1->lenIV = 4;
+    
+    parser = &loader.parser;
+    error = T1_New_Parser( parser, face->root.stream, face->root.memory );
+    if (error) goto Exit;
+
+    error = parse_dict( face, &loader, parser->base_dict, parser->base_len );
+    if (error) goto Exit;
+    
+    error = T1_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;
+    
+    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 */
+    /* but the "lengths" field must be released later..      */
+    type1->glyph_names_block    = loader.glyph_names.block;
+    type1->glyph_names          = (T1_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 )
+    {
+      T1_Int    charcode, index, min_char, max_char;
+      T1_Byte*  char_name;
+      T1_Byte*  glyph_name;
+
+      /* OK, we do the following : for each element in the encoding */
+      /* table, lookup 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.num_elems; charcode++ )
+      {
+        type1->encoding.char_index[charcode] = 0;
+        type1->encoding.char_name [charcode] = ".notdef";
+        
+        char_name = loader.encoding_table.elements[charcode];
+        if (char_name)
+          for ( index = 0; index < type1->num_glyphs; index++ )
+          {
+            glyph_name = type1->glyph_names[index];
+            if ( strcmp( char_name, glyph_name ) == 0 )
+            {
+              type1->encoding.char_index[charcode] = index;
+              type1->encoding.char_name [charcode] = glyph_name;
+              
+              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;
+  } 
--- /dev/null
+++ b/src/type1z/t1load.h
@@ -1,0 +1,56 @@
+/*******************************************************************
+ *
+ *  t1load.h                                                    2.0
+ *
+ *    Type1 Loader.                          
+ *
+ *  Copyright 1996-2000 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ *  This file is part of the FreeType project, and may only be used
+ *  modified and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ ******************************************************************/
+
+#ifndef T1LOAD_H
+#define T1LOAD_H
+
+#include <ftstream.h>
+#include <t1parse.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+  typedef struct T1_Loader_
+  {
+    T1_Parser        parser;          /* parser used to read the stream */
+
+    T1_Int           num_chars;       /* number of characters in encoding */
+    T1_Table         encoding_table;  /* T1_Table used to store the       */
+                                /* encoding character names         */
+                           
+    T1_Int           num_glyphs;     
+    T1_Table         glyph_names;
+    T1_Table         charstrings;
+        
+    T1_Int           num_subrs;
+    T1_Table         subrs;
+    
+  } T1_Loader;
+
+  LOCAL_DEF
+  T1_Error  T1_Open_Face( T1_Face  face );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* T1LOAD_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1z/t1objs.c
@@ -1,0 +1,404 @@
+/*******************************************************************
+ *
+ *  t1objs.c                                                     1.0
+ *
+ *    Type1 Objects manager.        
+ *
+ *  Copyright 1996-1998 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ *  This file is part of the FreeType project, and may only be used
+ *  modified and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ ******************************************************************/
+
+#include <ftdebug.h>
+#include <ftstream.h>
+
+#include <t1gload.h>
+#include <t1load.h>
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+#include <t1hinter.h>
+#endif
+
+/* Required by tracing mode */
+#undef   FT_COMPONENT
+#define  FT_COMPONENT  trace_t1objs
+
+/*******************************************************************
+ *                                                                 *
+ *                         SIZE  FUNCTIONS                         *
+ *                                                                 *
+ *                                                                 *
+ *******************************************************************/
+
+/*******************************************************************
+ *
+ * <Function>  T1_Done_Size
+ *
+ * <Description>
+ *    The TrueDoc instance object destructor. Used to discard
+ *    a given instance object..
+ *
+ * <Input>
+ *    instance   :: handle to the target instance object
+ *
+ * <Return>
+ *    TrueDoc error code. 0 means success
+ *
+ ******************************************************************/
+
+  LOCAL_FUNC
+  void  T1_Done_Size( T1_Size  size )
+  {
+    if (size)
+    {
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+      T1_Done_Size_Hinter( size );
+#endif
+      size->valid = 0;
+    }
+  }
+
+
+/*******************************************************************
+ *
+ *  <Function> T1_Init_Size
+ *
+ *  <Description>
+ *     The instance object constructor
+ *
+ *  <Input>
+ *     instance  : handle to new instance object
+ *     face      : pointer to parent face object
+ *
+ *  <Return>
+ *     TrueDoc error code. 0 means success.
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  T1_Error  T1_Init_Size( T1_Size  size )
+  {
+    T1_Error    error;
+      
+    size->valid = 0;
+    
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+    error = T1_New_Size_Hinter( size );
+    return error;
+#else
+    (void)error;
+    return T1_Err_Ok;
+#endif
+  }
+
+
+/*******************************************************************
+ *
+ *  <Function> T1_Reset_Size
+ *
+ *  <Description>
+ *     Resets an instance to a new pointsize/transform.
+ *     This function is in charge of resetting the blue zones,
+ *     As well as the stem snap tables for a given size..
+ *
+ *  <Input>
+ *     instance   the instance object to destroy
+ *
+ *  <Output>
+ *     Error code.
+ *
+ ******************************************************************/
+ 
+  LOCAL_FUNC
+  T1_Error  T1_Reset_Size( T1_Size  size )
+  {
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+    return T1_Reset_Size_Hinter( size );
+#else
+    (void)size;
+    return 0;
+#endif
+  }
+
+
+/*******************************************************************
+ *                                                                 *
+ *                         FACE  FUNCTIONS                         *
+ *                                                                 *
+ *                                                                 *
+ *******************************************************************/
+
+/*******************************************************************
+ *
+ *  <Function> T1_Done_Face
+ *
+ *  <Description>
+ *     The face object destructor.
+ *
+ *  <Input>
+ *     face  :: typeless pointer to the face object to destroy
+ *
+ *  <Return>
+ *     Error code.                       
+ *
+ ******************************************************************/
+
+  LOCAL_FUNC
+  void  T1_Done_Face( T1_Face  face )
+  {
+    FT_Memory  memory;
+
+    if (face)
+    {
+      memory = face->root.memory;
+      /* XXXX : TO DO */
+    }
+  }
+
+/*******************************************************************
+ *
+ *  <Function>  T1_Init_Face
+ *
+ *  <Description>
+ *     The face object constructor.
+ *
+ *  <Input>
+ *     face  ::  face record to build
+ *     Input ::  input stream where to load font data
+ *
+ *  <Return>
+ *     Error code.
+ *
+ ******************************************************************/
+
+  LOCAL_FUNC
+  T1_Error  T1_Init_Face( FT_Stream  stream,
+                          FT_Int     face_index,
+                          T1_Face    face )
+  {
+    T1_Error      error;
+
+    (void)face_index;
+    (void)face;
+
+    face->root.num_faces = 1;
+
+    /* open the tokenizer, this will also check the font format */
+    error = T1_Open_Face( face );
+    if (error) goto Exit;
+
+    /* if we just wanted to check the format, leave successfully now */
+    if (face_index < 0)
+      goto Exit;
+
+    /* check the face index */
+    if ( face_index != 0 )
+    {
+      FT_ERROR(( "T1.Init_Face : invalid face index\n" ));
+      error = T1_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    /* Now, load the font program into the face object */
+    {
+      /* Init the face object fields */
+      /* Now set up root face fields */
+      {
+        FT_Face  root = (FT_Face)&face->root;
+        
+        root->num_glyphs   = face->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;
+                              
+        if ( face->type1.is_fixed_pitch )
+          root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+        /* XXX : TO DO - add kerning with .afm support */
+
+        /* get style name - be careful, some broken fonts only */
+        /* have a /FontName dictionary entry .. !!             */
+        root->family_name = face->type1.family_name;
+        if (root->family_name)
+        {
+          char*  full   = face->type1.full_name;
+          char*  family = root->family_name;
+          
+          while ( *family && *full == *family )
+          {
+            family++;
+            full++;
+          }
+          
+          root->style_name = ( *full == ' ' ? full+1 : "Regular" );
+        }
+        else
+        {
+          /* do we have a /FontName ?? */
+          if (face->type1.font_name)
+          {
+            root->family_name = face->type1.font_name;
+            root->style_name  = "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     =  (T1_Short)face->type1.font_bbox.yMax;
+        root->descender    = -(T1_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.standard_width;
+
+        /* compute max advance width for proportional fonts */
+        if (!face->type1.is_fixed_pitch)
+        {
+          T1_Int  max_advance;
+
+          error = T1_Compute_Max_Advance( face, &max_advance );
+
+          /* in case of error, keep the standard width */
+          if (!error)
+            root->max_advance_width = max_advance;
+          else
+            error = 0;   /* clear error */
+        }
+
+        root->max_advance_height = root->height;
+        
+        root->underline_position  = face->type1.underline_position;
+        root->underline_thickness = face->type1.underline_thickness;
+  
+        root->max_points   = 0;
+        root->max_contours = 0;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+/*******************************************************************
+ *
+ *  Function    :  Glyph_Destroy
+ *
+ *  Description :  The glyph object destructor.
+ *
+ *  Input  :  _glyph  typeless pointer to the glyph record to destroy
+ *
+ *  Output :  Error code.                       
+ *
+ ******************************************************************/
+
+  LOCAL_FUNC
+  void  T1_Done_GlyphSlot( T1_GlyphSlot  glyph )
+  {
+    FT_Memory  memory  = glyph->root.face->memory;
+    FT_Library library = glyph->root.face->driver->library;
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+    T1_Done_Glyph_Hinter( glyph );
+#endif
+	/* the bitmaps are created on demand */
+	FREE( glyph->root.bitmap.buffer );
+    FT_Done_Outline( library, &glyph->root.outline );
+    return;
+  }
+
+
+/*******************************************************************
+ *
+ *  Function    :  Glyph_Create
+ *
+ *  Description :  The glyph object constructor.
+ *
+ *  Input  :  glyph   glyph record to build.
+ *            face    the glyph's parent face.              
+ *
+ *  Output :  Error code.
+ *
+ ******************************************************************/
+
+  LOCAL_FUNC
+  T1_Error  T1_Init_GlyphSlot( T1_GlyphSlot  glyph )
+  {
+    FT_Library  library = glyph->root.face->driver->library;
+    T1_Error    error;
+
+    glyph->max_points         = 0;
+    glyph->max_contours       = 0;
+    glyph->root.bitmap.buffer = 0;
+
+    error = FT_New_Outline( library, 0, 0, &glyph->root.outline );
+    if (error) return error;
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+    error = T1_New_Glyph_Hinter( glyph );
+    if (error)
+      FT_Done_Outline( library, &glyph->root.outline );
+#endif
+
+    return error;
+  }
+
+
+/*******************************************************************
+ *
+ *  <Function>  T1_Init_Driver
+ *
+ *  <Description>
+ *     Initialise a given Type 1 driver object
+ *
+ *  <Input>
+ *     driver ::  handle to target driver object
+ *
+ *  <Return>
+ *     Error code.
+ *
+ ******************************************************************/
+
+  LOCAL_FUNC
+  T1_Error  T1_Init_Driver( T1_Driver  driver )
+  {
+    (void)driver;
+    return T1_Err_Ok;
+  }
+
+
+
+/*******************************************************************
+ *
+ *  <Function> T1_Done_Driver
+ *
+ *  <Description>
+ *     finalise a given Type 1 driver
+ *
+ *  <Input>
+ *     driver  :: handle to target Type 1 driver
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  void  T1_Done_Driver( T1_Driver  driver )
+  {
+    (void)driver;
+  }
+
+
+/* END */
--- /dev/null
+++ b/src/type1z/t1objs.h
@@ -1,0 +1,302 @@
+/*******************************************************************
+ *
+ *  t1objs.h                                                    1.0
+ *
+ *    Type1 objects definition.         
+ *
+ *  Copyright 1996-1999 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ *  This file is part of the FreeType project, and may only be used
+ *  modified and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ ******************************************************************/
+
+#ifndef T1OBJS_H
+#define T1OBJS_H
+
+#include <ftobjs.h>
+#include <t1config.h>
+#include <t1errors.h>
+#include <t1types.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+  /* The following structures must be defined by the hinter */
+  typedef struct T1_Size_Hints_   T1_Size_Hints;
+  typedef struct T1_Glyph_Hints_  T1_Glyph_Hints;
+
+  /***********************************************************************/
+  /*                                                                     */
+  /* <Type> T1_Driver                                                    */
+  /*                                                                     */
+  /* <Description>                                                       */
+  /*    A handle to a Type 1 driver object.                              */
+  /*                                                                     */
+  typedef struct T1_DriverRec_   *T1_Driver;
+
+
+  /***********************************************************************/
+  /*                                                                     */
+  /* <Type> T1_Size                                                      */
+  /*                                                                     */
+  /* <Description>                                                       */
+  /*    A handle to a Type 1 size object.                                */
+  /*                                                                     */
+  typedef struct T1_SizeRec_*  T1_Size;
+
+
+  /***********************************************************************/
+  /*                                                                     */
+  /* <Type> T1_GlyphSlot                                                 */
+  /*                                                                     */
+  /* <Description>                                                       */
+  /*    A handle to a Type 1 glyph slot object.                          */
+  /*                                                                     */
+  typedef struct T1_GlyphSlotRec_*  T1_GlyphSlot;
+
+
+  /***********************************************************************/
+  /*                                                                     */
+  /* <Type> T1_CharMap                                                   */
+  /*                                                                     */
+  /* <Description>                                                       */
+  /*    A handle to a Type 1 character mapping object.                   */
+  /*                                                                     */
+  /* <Note>                                                              */
+  /*    The Type 1 format doesn't use a charmap but an encoding table.   */
+  /*    The driver is responsible for making up charmap objects          */
+  /*    corresponding to these tables..                                  */
+  /*                                                                     */
+  typedef struct T1_CharMapRec_*   T1_CharMap;
+
+
+
+ /**************************************************************************/
+ /*                                                                        */
+ /*    NOW BEGINS THE TYPE1 SPECIFIC STUFF ..............................  */
+ /*                                                                        */
+ /**************************************************************************/
+ 
+
+  /***************************************************/
+  /*                                                 */
+  /*  T1_Size :                                      */
+  /*                                                 */
+  /*    Type 1 size record..                         */
+  /*                                                 */
+  
+  typedef struct T1_SizeRec_
+  {
+    FT_SizeRec      root;
+    T1_Bool         valid;
+    T1_Size_Hints*  hints;  /* defined in the hinter. This allows */
+                            /* us to experiment with different    */
+                            /* hinting schemes without having to  */
+                            /* change 't1objs' each time..        */
+  } T1_SizeRec;
+
+
+
+  /***************************************************/
+  /*                                                 */
+  /*  T1_GlyphSlot :                                 */
+  /*                                                 */
+  /*    TrueDoc glyph record..                       */
+  /*                                                 */
+  
+  typedef struct T1_GlyphSlotRec_
+  {
+    FT_GlyphSlotRec  root;
+
+    T1_Bool          hint;
+    T1_Bool          scaled;
+    
+    T1_Int           max_points;
+    T1_Int           max_contours;
+
+    FT_Fixed         x_scale;
+    FT_Fixed         y_scale;
+
+    T1_Glyph_Hints*  hints;  /* defined in the hinter */
+
+  } T1_GlyphSlotRec;
+
+
+/*******************************************************************
+ *
+ *  <Function>  T1_Init_Face
+ *
+ *  <Description>
+ *     Initialise a given Type 1 face object
+ *
+ *  <Input>
+ *     face_index :: index of font face in resource
+ *     resource   :: source font resource
+ *     face       ::  face record to build
+ *
+ *  <Return>
+ *     Error code.
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  T1_Error  T1_Init_Face( FT_Stream    stream,
+                          FT_Int       face_index,
+                          T1_Face      face );
+
+
+
+/*******************************************************************
+ *
+ *  <Function> T1_Done_Face
+ *
+ *  <Description>
+ *     Finalise a given face object
+ *
+ *  <Input>
+ *     face  :: handle  to the face object to destroy
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  void  T1_Done_Face( T1_Face  face );
+
+
+
+/*******************************************************************
+ *
+ *  <Function> T1_Init_Size
+ *
+ *  <Description>
+ *     Initialise a new Type 1 size object
+ *
+ *  <Input>
+ *     size  :: handle to size object
+ *
+ *  <Return>
+ *     Type 1 error code. 0 means success.
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  T1_Error  T1_Init_Size( T1_Size  size );
+
+
+
+/*******************************************************************
+ *
+ * <Function>  T1_Done_Size
+ *
+ * <Description>
+ *    The Type 1 size object finaliser.
+ *
+ * <Input>
+ *    size   :: handle to the target size object.
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  void  T1_Done_Size( T1_Size  size );
+
+
+/*******************************************************************
+ *
+ * <Function>  T1_Reset_Size
+ *
+ * <Description>
+ *    Reset a Type 1 size when resolutions and character dimensions
+ *    have been changed..
+ *
+ * <Input>
+ *    size   :: handle to the target size object.
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  T1_Error  T1_Reset_Size( T1_Size  size );
+
+
+
+/*******************************************************************
+ *
+ *  <Function> T1_Init_GlyphSlot
+ *
+ *  <Description> The TrueType glyph slot initialiser
+ *
+ *  <Input>  glyph ::  glyph record to build.
+ *
+ *  <Output> Error code.
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  T1_Error  T1_Init_GlyphSlot( T1_GlyphSlot  slot );
+
+
+
+/*******************************************************************
+ *
+ *  <Function> T1_Done_GlyphSlot
+ *
+ *  <Description> The Type 1 glyph slot finaliser
+ *
+ *  <Input>  glyph  :: handle to glyph slot object
+ *
+ *  <Output>  Error code.                       
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  void  T1_Done_GlyphSlot( T1_GlyphSlot  slot );
+
+
+
+/*******************************************************************
+ *
+ *  <Function>  T1_Init_Driver
+ *
+ *  <Description>
+ *     Initialise a given Type 1 driver object
+ *
+ *  <Input>
+ *     driver ::  handle to target driver object
+ *
+ *  <Return>
+ *     Error code.
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  T1_Error  T1_Init_Driver( T1_Driver  driver );
+
+
+
+/*******************************************************************
+ *
+ *  <Function> T1_Done_Driver
+ *
+ *  <Description>
+ *     finalise a given Type 1 driver
+ *
+ *  <Input>
+ *     driver  :: handle to target Type 1 driver
+ *
+ ******************************************************************/
+
+  LOCAL_DEF
+  void  T1_Done_Driver( T1_Driver  driver );
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* T1OBJS_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1z/t1parse.c
@@ -1,0 +1,901 @@
+/*******************************************************************
+ *
+ *  t1parse.c                                                   2.0
+ *
+ *    Type1 parser.
+ *
+ *  Copyright 1996-1998 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ *  This file is part of the FreeType project, and may only be used
+ *  modified and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ *  The Type 1 parser is in charge of the following:
+ *
+ *   - provide an implementation of a growing sequence of
+ *     objects called a T1_Table (used to build various tables
+ *     needed by the loader).
+ *
+ *   - opening .pfb and .pfa files to extract their top-level
+ *     and private dictionaries
+ *
+ *   - read numbers, arrays & strings from any dictionary
+ *
+ *  See "t1load.c" to see how data is loaded from the font file
+ *
+ ******************************************************************/
+ 
+#include <ftdebug.h>
+#include <ftcalc.h>
+#include <ftobjs.h>
+#include <ftstream.h>
+#include <t1errors.h>
+#include <t1parse.h>
+
+#undef FT_COMPONENT
+#define FT_COMPONENT  trace_t1load
+
+/*************************************************************************/
+/*                                                                       */
+/* <Function> T1_New_Table                                               */
+/*                                                                       */
+/* <Description>                                                         */
+/*    Initialise a T1_Table.                                             */
+/*                                                                       */
+/* <Input>                                                               */
+/*    table  :: address of target table                                  */
+/*    count  :: table size = maximum number of elements                  */
+/*    memory :: memory object to use for all subsequent reallocations    */
+/*                                                                       */
+/* <Return>                                                              */
+/*    Error code. 0 means success                                        */
+/*                                                                       */
+
+  LOCAL_FUNC
+  T1_Error  T1_New_Table( T1_Table*  table,
+                          T1_Int     count,
+                          FT_Memory  memory )
+  {
+	 T1_Error  error;
+
+	 table->memory = memory;
+	 if ( ALLOC_ARRAY( table->elements, count, T1_Byte*  ) ||
+          ALLOC_ARRAY( table->lengths, count, T1_Byte* ) )
+       goto Exit;
+
+	table->max_elems = count;
+    table->init      = 0xdeadbeef;
+	table->num_elems = 0;
+	table->block     = 0;
+	table->capacity  = 0;
+	table->cursor    = 0;
+
+  Exit:
+    if (error) FREE(table->elements);
+      
+	return error;
+  }
+
+
+
+/*************************************************************************/
+/*                                                                       */
+/* <Function> T1_Add_Table                                               */
+/*                                                                       */
+/* <Description>                                                         */
+/*    Adds an object to a T1_Table, possibly growing its memory block    */
+/*                                                                       */
+/* <Input>                                                               */
+/*    table  :: target table                                             */
+/*    index  :: index of object in table                                 */
+/*    object :: address of object to copy in memory                      */
+/*    length :: length in bytes of source object                         */
+/*                                                                       */
+/* <Return>                                                              */
+/*    Error code. 0 means success. An error is returned when a           */
+/*    realloc failed..                                                   */
+/*                                                                       */
+
+
+      static void  shift_elements( T1_Table*  table, T1_Byte*  old_base )
+      {
+        T1_Long    delta  = table->block - old_base;
+        T1_Byte**  offset = table->elements;
+        T1_Byte**  limit  = offset + table->max_elems;
+    
+        if (delta)
+          for ( ; offset < limit; offset++ )
+          {
+            if (offset[0])
+              offset[0] += delta;
+          }
+      }
+  
+      static
+      T1_Error  reallocate_t1_table( T1_Table*  table,
+                                     T1_Int     new_size )
+      {
+        FT_Memory  memory   = table->memory;
+        T1_Byte*   old_base = table->block;
+        T1_Error   error;
+  
+        /* realloc the base block */
+        if ( REALLOC( table->block, table->capacity, new_size ) )
+          return error;
+  
+        table->capacity = new_size;
+  
+        /* shift all offsets when needed */
+        if (old_base)
+          shift_elements( table, old_base );
+  
+        return T1_Err_Ok;
+      }
+
+
+
+  LOCAL_FUNC
+  T1_Error  T1_Add_Table( T1_Table*  table,
+                          T1_Int     index,
+                          void*      object,
+                          T1_Int     length )
+  {
+	if (index < 0 || index > table->max_elems)
+    {
+	  FT_ERROR(( "T1.Add_Table: invalid index\n" ));
+	  return T1_Err_Syntax_Error;
+    }
+
+    /* grow the base block if needed */
+    if ( table->cursor + length > table->capacity )
+    {
+      T1_Error  error;
+      T1_Int    new_size = table->capacity;
+
+      while ( new_size < table->cursor+length )
+        new_size += 1024;
+
+      error = reallocate_t1_table( table, new_size );
+      if (error) return error;
+    }
+
+    /* add the object to the base block and adjust offset */
+    table->elements[ index ] = table->block + table->cursor;
+    table->lengths [ index ] = length;
+    MEM_Copy( table->block + table->cursor, object, length );
+
+    table->cursor += length;
+    return T1_Err_Ok;
+  }
+
+
+/*************************************************************************/
+/*                                                                       */
+/* <Function> T1_Done_Table                                              */
+/*                                                                       */
+/* <Description>                                                         */
+/*    Finalise a T1_Table. (realloc it to its current cursor).           */
+/*                                                                       */
+/* <Input>                                                               */
+/*    table :: target table                                              */
+/*                                                                       */
+/* <Note>                                                                */
+/*    This function does NOT release the heap's memory block. It is up   */
+/*    to the caller to clean it, or reference it in its own structures.  */
+/*                                                                       */
+  LOCAL_FUNC
+  void  T1_Done_Table( T1_Table*  table )
+  {
+    FT_Memory  memory = table->memory;
+    T1_Error   error;
+    T1_Byte*   old_base;
+
+    /* should never fail, as rec.cursor <= rec.size */
+    old_base = table->block;
+    if (!old_base)
+      return;
+    
+    (void)REALLOC( table->block, table->capacity, table->cursor );
+    table->capacity = table->cursor;
+    
+    if (old_base != table->block)
+      shift_elements( table, old_base );
+  }
+
+
+  LOCAL_FUNC
+  void  T1_Release_Table( T1_Table*  table )
+  {
+    FT_Memory  memory = table->memory;
+    
+    if (table->init == 0xdeadbeef)
+    {
+      FREE( table->block );
+      FREE( table->elements );
+      FREE( table->lengths );
+      table->init = 0;
+    }
+  }
+
+  static
+  T1_Long  t1_toint( T1_Byte* *cursor,
+                     T1_Byte*  limit )
+  {
+    T1_Long  result = 0;
+    T1_Byte* cur    = *cursor;
+    T1_Byte  c, d;
+    
+    for (; cur < limit; cur++)
+    {
+      c = *cur;
+      d = (T1_Byte)(c - '0');
+      if (d < 10) break;
+      
+      if ( c=='-' )
+      {
+        cur++;
+        break;
+      }
+    }
+    
+    if (cur < limit)
+    {
+      do
+      {
+        d = (T1_Byte)(cur[0] - '0');
+        if (d >= 10)
+          break;
+          
+        result = result*10 + d;
+        cur++;
+        
+      } while (cur < limit);
+      
+      if (c == '-')
+        result = -result;
+    }
+    
+    *cursor = cur;
+    return result;
+  }
+
+
+  static
+  T1_Long  t1_tofixed( T1_Byte* *cursor,
+                       T1_Byte*  limit,
+                       T1_Long   power_ten )
+  {
+    T1_Byte* cur    = *cursor;
+    T1_Long  num, divider, result;
+    T1_Int   sign   = 0;
+    T1_Byte  d;
+    
+    if (cur >= limit) return 0;
+    
+    /* first of all, read the integer part */
+    result  = t1_toint( &cur, limit ) << 16;
+    num     = 0;
+    divider = 1;
+    
+    if (result < 0)
+    {
+      sign   = 1;
+      result = -result;
+    }
+    if (cur >= limit) goto Exit;
+    
+    /* read decimal part, if any */
+    if (*cur == '.' && cur+1 < limit)
+    {
+      cur++;
+      
+      for (;;)
+      {
+        d = (T1_Byte)(*cur - '0');
+        if (d >= 10) break;
+
+        if (divider < 10000000L)
+        {
+          num      = num*10 + d;
+          divider *= 10;
+        }
+        cur++;
+        if (cur >= limit) break;
+      }
+    }
+    
+    /* read exponent, if any */
+    if ( cur+1 < limit && (*cur == 'e' || *cur == 'E'))
+    {
+      cur++;
+      power_ten += t1_toint( &cur, limit );
+    }
+    
+  Exit:
+    /* raise to power of ten if needed */
+    while (power_ten > 0)
+    {
+      result = result*10;
+      num    = num*10;
+      power_ten--;
+    }
+    
+    while (power_ten < 0)
+    {
+      result  = result/10;
+      divider = divider*10;
+      power_ten++;
+    }
+
+    if (num)
+      result += FT_DivFix( num, divider );
+
+    if (sign)
+      result = -result;
+      
+    *cursor = cur;
+    return result;
+  }
+
+
+  static
+  T1_Int  t1_tocoordarray( T1_Byte*  *cursor,
+                           T1_Byte*   limit,
+                           T1_Int     max_coords,
+                           T1_Short*  coords )
+  {
+    T1_Byte*  cur   = *cursor;
+    T1_Int    count = 0;
+    T1_Byte   c, ender;
+    
+    if (cur >= limit) goto Exit;
+    
+    /* check for the beginning of an array. If not, only one number will be read */
+    c     = *cur;
+    ender = 0;
+    
+    if (c == '[')
+      ender = ']';
+      
+    if (c == '{')
+      ender = '}';
+      
+    if (ender)
+      cur++;
+
+    /* now, read the coordinates */
+    for ( ; cur < limit; cur++ )
+    {
+      c = *cur;
+      if (count >= max_coords || c == ender)
+        break;
+      
+      coords[count] = (T1_Short)(t1_tofixed(&cur,limit,0) >> 16);
+      count++;
+      
+      if (!ender)
+        break;
+    }
+    
+  Exit:
+    *cursor = cur;
+    return count;
+  }
+
+
+
+  static
+  T1_Int  t1_tofixedarray( T1_Byte*  *cursor,
+                           T1_Byte*   limit, 
+                           T1_Int     max_values,
+                           T1_Fixed*  values,
+                           T1_Int     power_ten )
+  {
+    T1_Byte*  cur   = *cursor;
+    T1_Int    count = 0;
+    T1_Byte   c, ender;
+    
+    if (cur >= limit) goto Exit;
+    
+    /* check for the beginning of an array. If not, only one number will be read */
+    c     = *cur;
+    ender = 0;
+    
+    if (c == '[')
+      ender = ']';
+      
+    if (c == '{')
+      ender = '}';
+      
+    if (ender)
+      cur++;
+
+    /* now, read the values */
+    for ( ; cur < limit; cur++ )
+    {
+      c = *cur;
+      if (count >= max_values || c == ender)
+        break;
+      
+      values[count] = t1_tofixed(&cur,limit,power_ten);
+      count++;
+      
+      if (!ender)
+        break;
+    }
+    
+  Exit:
+    *cursor = cur;
+    return count;
+  }
+
+
+  static
+  T1_String*  t1_tostring( T1_Byte* *cursor, T1_Byte* limit, FT_Memory memory )
+  {
+    T1_Byte*    cur = *cursor;
+    T1_Int      len = 0;
+    T1_Int      count;
+    T1_String*  result;
+    FT_Error    error;
+
+    /* first of all, skip everything until we encounter a string */
+    while ( cur < limit && *cur != '(' ) cur++;
+    cur++;
+    if (cur >= limit) return 0;
+    
+    *cursor = cur;
+    count   = 0;
+    
+    /* then, count its length */
+    for ( ; cur < limit; cur++ )
+    {
+      if (*cur == '(')
+        count++;
+        
+      else if (*cur == ')')
+      {
+        count--;
+        if (count < 0)
+          break;
+      }
+    }
+
+    len = cur - *cursor;    
+    if (cur >= limit || ALLOC(result,len+1)) return 0;
+    
+    /* now copy the string */
+    MEM_Copy( result, *cursor, len );
+    result[len] = '\0';
+
+    return result;    
+  }
+
+  static
+  int  t1_tobool( T1_Byte* *cursor, T1_Byte* limit )
+  {
+    T1_Byte*  cur    = *cursor;
+    T1_Bool   result = 0;
+    
+    /* return 1 if we find a "true", 0 otherwise */
+    if ( cur+3 < limit &&
+         cur[0] == 't' &&
+         cur[1] == 'r' &&
+         cur[2] == 'u' &&
+         cur[3] == 'e' )
+    {
+      result = 1;
+      cur   += 5;
+    }
+    else if ( cur+4 < limit &&
+              cur[0] == 'f' &&
+              cur[1] == 'a' &&
+              cur[2] == 'l' &&
+              cur[3] == 's' &&
+              cur[4] == 'e' )
+    {
+      result = 0;
+      cur   += 6;
+    }
+    *cursor = cur;
+    return result;
+  }
+
+
+  LOCAL_FUNC
+  T1_Long  T1_ToInt  ( T1_Parser*  parser )
+  {
+    return t1_toint( &parser->cursor, parser->limit );
+  }
+
+
+  LOCAL_FUNC
+  T1_Long  T1_ToFixed( T1_Parser*  parser, T1_Int power_ten )
+  {
+    return t1_tofixed( &parser->cursor, parser->limit, power_ten );
+  }
+
+
+  LOCAL_FUNC
+  T1_Int  T1_ToCoordArray( T1_Parser* parser,
+                           T1_Int     max_coords,
+                           T1_Short*  coords )
+  {
+    return t1_tocoordarray( &parser->cursor, parser->limit, max_coords, coords );
+  }
+
+
+  LOCAL_FUNC
+  T1_Int  T1_ToFixedArray( T1_Parser* parser,
+                           T1_Int     max_values,
+                           T1_Fixed*  values,
+                           T1_Int     power_ten )
+  {
+    return t1_tofixedarray( &parser->cursor, parser->limit, max_values, values, power_ten );
+  }
+
+
+  LOCAL_FUNC
+  T1_String*  T1_ToString( T1_Parser* parser )
+  {
+    return t1_tostring( &parser->cursor, parser->limit, parser->memory );
+  }
+
+
+  LOCAL_FUNC
+  T1_Bool   T1_ToBool( T1_Parser* parser )
+  {
+    return t1_tobool( &parser->cursor, parser->limit );
+  }
+
+  static
+  FT_Error  read_pfb_tag( FT_Stream  stream, T1_UShort *tag, T1_Long*  size )
+  {
+    FT_Error  error;
+    
+    if (READ_UShort(*tag)) goto Exit;
+    if (*tag == 0x8001 || *tag == 0x8002)
+    {
+      FT_Long  asize;
+      
+      if (READ_ULong(asize)) goto Exit;
+      
+      /* swap between big and little endianness */
+      *size  = ((asize & 0xFF000000) >> 24) |
+               ((asize & 0x00FF0000) >> 8 ) |
+               ((asize & 0x0000FF00) << 8 ) |
+               ((asize & 0x000000FF) << 24);
+    }
+    
+  Exit:
+    return error;
+  }
+
+
+
+  LOCAL_FUNC
+  T1_Error  T1_New_Parser( T1_Parser*  parser,
+                           FT_Stream   stream,
+                           FT_Memory   memory )
+  {
+    FT_Error  error;
+    T1_UShort tag;
+    T1_Long   size;
+  
+    parser->stream       = stream;
+    parser->memory       = memory;
+    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;
+    
+    parser->cursor       = 0;
+    parser->limit        = 0;
+    
+    /******************************************************************/
+    /*                                                                */
+    /* Here's a short summary of what is going on :                   */
+    /*                                                                */
+    /*   When creating a new Type 1 parser, we try to locate and      */
+    /*   load the base dictionary when this is possible (i.e. for     */
+    /*   .pfb files). Otherwise, we load the whole font in 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 dict in it.                                */
+    /*                                                                */
+    /*   parser->in_pfb is set when we are in a binary (".pfb") font  */
+    /*   parser->in_memory is set when 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        */
+      (void)FILE_Seek(0L);
+      size = stream->size;
+    }
+    else
+      parser->in_pfb = 1;
+
+   /* now, try to load the "size" bytes of the "base" dictionary we */
+   /* found previously                                              */
+
+   /* if it's a memory-based resource, set up pointers */
+   if ( !stream->read )
+   {
+     parser->base_dict = (T1_Byte*)stream->base + stream->pos;
+     parser->base_len  = size;
+     parser->in_memory = 1;
+
+     /* check that the "size" field is valid */
+     if ( FILE_Skip(size) ) goto Exit;
+   }
+   else
+   {
+     /* read segment in memory */
+     if ( ALLOC( parser->base_dict, size )     ||
+          FILE_Read( parser->base_dict, size ) )
+       goto Exit;
+   }
+
+   /* Now check font format, we must see a '%!PS-AdobeFont-1' */
+   /* or a '%!FontType'                                       */
+   {
+     if ( size <= 16 ||
+          ( strncmp( (const char*)parser->base_dict, "%!PS-AdobeFont-1", 16 ) &&
+            strncmp( (const char*)parser->base_dict, "%!FontType", 10 )       ) )
+     {
+       FT_TRACE2(( "Not a Type1 font\n" ));
+       error = T1_Err_Invalid_File_Format;
+     }
+     else
+     {
+       parser->cursor = parser->base_dict;
+       parser->limit  = parser->cursor + parser->base_len;
+     }
+   }
+
+  Exit:
+    if (error && !parser->in_memory)
+      FREE( parser->base_dict );
+
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  void  T1_Done_Parser( T1_Parser*  parser )
+  {
+    FT_Memory   memory = parser->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 );
+  }
+
+
+ /* 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  T1_Decrypt( T1_Byte*   buffer,
+                    T1_Int     length,
+                    T1_UShort  seed )
+  {
+    while ( length > 0 )
+    {
+      T1_Byte  plain;
+
+      plain     = (*buffer ^ (seed >> 8));
+      seed      = (*buffer+seed)*52845+22719;
+      *buffer++ = plain;
+      length--;
+    }
+  }
+
+
+  LOCAL_FUNC
+  T1_Error  T1_Get_Private_Dict( T1_Parser*  parser )
+  {
+    FT_Stream  stream = parser->stream;
+    FT_Memory  memory = parser->memory;
+    FT_Error   error  = 0;
+    T1_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..                               */
+      T1_Long    start_pos    = FILE_Pos();
+      T1_UShort  tag;
+      T1_Long    size;
+
+      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(( "T1.Open_Private: 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 = 0; 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 in memory */
+      /* if this is a memory resource, allocate a new block to hold */
+      /* the private dict. Otherwise, simply overwrite into the     */
+      /* base dict 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" */
+            break;
+          }
+        }
+        cur++;
+        if (cur >= limit)
+        {
+          FT_ERROR(("T1.Open_Private: could not find 'eexec' keyword\n"));
+          error = FT_Err_Invalid_File_Format;
+          goto Exit;
+        }
+      }
+      
+      /* now determine wether 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 wether the private dictionary is encoded in binary */
+      /* or hexadecimal ASCII format..                                    */
+      /* and 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.. This blows goats !!.. */
+       
+        T1_Byte*  write;
+        T1_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 */
+    T1_Decrypt( parser->private_dict, parser->private_len, 55665 );
+    parser->cursor = parser->private_dict;
+    parser->limit  = parser->cursor + parser->private_len;
+
+  Fail:
+  Exit:
+    return error;
+  }
+  
--- /dev/null
+++ b/src/type1z/t1parse.h
@@ -1,0 +1,206 @@
+/*******************************************************************
+ *
+ *  t1parse.h                                                   2.0
+ *
+ *    Type1 parser.
+ *
+ *  Copyright 1996-1998 by
+ *  David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ *  This file is part of the FreeType project, and may only be used
+ *  modified and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ *  The Type 1 parser is in charge of the following:
+ *
+ *   - provide an implementation of a growing sequence of
+ *     objects called a T1_Table (used to build various tables
+ *     needed by the loader).
+ *
+ *   - opening .pfb and .pfa files to extract their top-level
+ *     and private dictionaries
+ *
+ *   - read numbers, arrays & strings from any dictionary
+ *
+ *  See "t1load.c" to see how data is loaded from the font file
+ *
+ ******************************************************************/
+
+#ifndef T1PARSE_H
+#define T1PARSE_H
+
+#include <t1types.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*************************************************************************
+ *
+ * <Struct> T1_Table
+ *
+ * <Description>
+ *    A T1_Table is a simple object used to store an array of objects
+ *    in a single memory block.
+ *
+ * <Fields>
+ *    block     :: address in memory of the growheap's block. This
+ *                 can change between two object adds, due to the use
+ *                 of 'realloc'.
+ *
+ *    cursor    :: current top of the grow heap within its block
+ *
+ *    capacity  :: current size of the heap block. Increments by 1 Kb
+ *
+ *    init      :: boolean. set when the table has been initialized
+ *                 (the table user should set this field)
+ *
+ *    max_elems :: maximum number of elements in table
+ *    num_elems :: current number of elements in table
+ *
+ *    elements  :: table of element addresses within the block
+ *    lengths   :: table of element sizes within the block
+ *
+ *    memory    :: memory object used for memory operations (alloc/realloc)
+ */
+
+  typedef struct T1_Table_
+  {
+    T1_Byte*   block;          /* current memory block           */
+    T1_Int     cursor;         /* current cursor in memory block */
+    T1_Int     capacity;       /* current size of memory block   */
+    T1_Long    init;
+
+    T1_Int     max_elems;
+    T1_Int     num_elems;
+    T1_Byte**  elements;       /* addresses of table elements */
+    T1_Int*    lengths;        /* lengths of table elements   */
+
+    FT_Memory  memory;
+
+  } T1_Table;
+
+
+/*************************************************************************
+ *
+ * <Struct> T1_Parser
+ *
+ * <Description>
+ *    A T1_Parser is an object used to parse a Type 1 fonts very
+ *    quickly.
+ *
+ * <Fields>
+ *    stream        :: current input stream
+ *    memory        :: current memory object
+ *
+ *    base_dict     :: pointer to top-level dictionary
+ *    base_len      :: length in bytes of top dict
+ *
+ *    private_dict  :: pointer to private dictionary
+ *    private_len   :: length in bytes of private dict
+ *
+ *    in_pfb        :: boolean. Indicates that we're in a .pfb file
+ *    in_memory     :: boolean. Indicates a memory-based stream
+ *    single_block  :: boolean. Indicates that the private dict
+ *                     is stored in lieu of the base dict
+ *
+ *    cursor        :: current parser cursor
+ *    limit         :: current parser limit (first byte after current
+ *                     dictionary).
+ *
+ *    error         :: current parsing error
+ */
+  typedef struct T1_Parser_
+  {
+    FT_Stream  stream;
+    FT_Memory  memory;
+    
+    T1_Byte*   base_dict;
+    T1_Int     base_len;
+    
+    T1_Byte*   private_dict;
+    T1_Int     private_len;
+    
+    T1_Byte    in_pfb;
+    T1_Byte    in_memory;
+    T1_Byte    single_block;
+
+    T1_Byte*   cursor;
+    T1_Byte*   limit;
+    T1_Error   error;
+    
+  } T1_Parser;
+
+
+  LOCAL_DEF
+  T1_Error  T1_New_Table( T1_Table*  table,
+                          T1_Int     count,
+                          FT_Memory  memory );
+
+
+  LOCAL_DEF
+  T1_Error  T1_Add_Table( T1_Table*  table,
+                          T1_Int     index,
+                          void*      object,
+                          T1_Int     length );
+
+
+  LOCAL_DEF
+  void  T1_Done_Table( T1_Table*  table );
+
+  LOCAL_DEF
+  void  T1_Release_Table( T1_Table*  table );
+
+  LOCAL_DEF
+  T1_Long  T1_ToInt  ( T1_Parser*  parser );
+
+  LOCAL_DEF
+  T1_Long  T1_ToFixed( T1_Parser*  parser, T1_Int  power_ten );
+
+  LOCAL_DEF
+  T1_Int  T1_ToCoordArray( T1_Parser* parser,
+                           T1_Int     max_coords,
+                           T1_Short*  coords );
+
+  LOCAL_DEF
+  T1_Int  T1_ToFixedArray( T1_Parser* parser,
+                           T1_Int     max_values,
+                           T1_Fixed*  values,
+                           T1_Int     power_ten );
+
+  LOCAL_DEF
+  T1_String*  T1_ToString( T1_Parser* parser );
+
+
+  LOCAL_DEF
+  T1_Bool   T1_ToBool( T1_Parser* parser );
+
+
+  LOCAL_DEF
+  T1_Int  T1_ToImmediate( T1_Parser*  parser );
+
+
+  LOCAL_DEF
+  T1_Error  T1_New_Parser( T1_Parser*  parser,
+                           FT_Stream   stream,
+                           FT_Memory   memory );
+
+  LOCAL_DEF
+  T1_Error  T1_Get_Private_Dict( T1_Parser*  parser );
+
+  LOCAL_DEF
+  void  T1_Decrypt( T1_Byte*   buffer,
+                    T1_Int     length,
+                    T1_UShort  seed );
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* T1PARSE_H */
+
+
+/* END */
+
--- /dev/null
+++ b/src/type1z/t1tokens.h
@@ -1,0 +1,73 @@
+/*******************************************************************
+ *
+ *  t1tokens.h
+ *
+ *  Type 1 tokens definition
+ *
+ *  Copyright 2000 David Turner, Robert Wilhelm and Werner Lemberg.
+ *
+ *  This file is part of the FreeType project, and may only be used
+ *  modified and distributed under the terms of the FreeType project
+ *  license, LICENSE.TXT. By continuing to use, modify or distribute
+ *  this file you indicate that you have read the license and
+ *  understand and accept it fully.
+ *
+ *  This file only contains macros that are expanded when compiling
+ *  the "t1load.c" source file.
+ *
+ ******************************************************************/
+
+#undef  FACE
+#define FACE  (face->type1)
+
+ /* define the font info dictionary parsing callbacks */
+
+  PARSE_STRING("version",version)
+  PARSE_STRING("Notice",notice)
+  PARSE_STRING("FullName",full_name)
+  PARSE_STRING("FamilyName",family_name)
+  PARSE_STRING("Weight",weight)
+  
+  PARSE_INT("ItalicAngle",italic_angle)
+  PARSE_BOOL("isFixedPitch",is_fixed_pitch)
+  PARSE_INT("UnderlinePosition",underline_position)
+  PARSE_INT("UnderlineThickness",underline_thickness)
+
+ /* define the private dict parsing callbacks */ 
+ 
+   PARSE_INT("UniqueID",unique_id)
+   PARSE_INT("lenIV",lenIV)
+   
+   PARSE_COORDS( "BlueValues", num_blues,       14, blue_values)
+   PARSE_COORDS( "OtherBlues", num_other_blues, 10, other_blues)
+   
+   PARSE_COORDS( "FamilyBlues", num_family_blues,       14, family_blues)
+   PARSE_COORDS( "FamilyOtherBlues", num_family_other_blues, 10, family_other_blues)
+ 
+   PARSE_FIXED( "BlueScale", blue_scale)
+   PARSE_INT( "BlueShift", blue_shift)
+   
+   PARSE_INT( "BlueFuzz", blue_fuzz)
+
+   PARSE_COORDS2( "StdHW", 1, standard_width  )
+   PARSE_COORDS2( "StdVW", 1, standard_height )
+   
+   PARSE_COORDS( "StemSnapH", num_snap_widths,  12, stem_snap_widths )
+   PARSE_COORDS( "StemSnapV", num_snap_heights, 12, stem_snap_heights )
+   
+   PARSE_INT( "LanguageGroup", language_group )
+   PARSE_INT( "password", password )
+   PARSE_COORDS2( "MinFeature", 2, min_feature )
+
+ /* define the top-level dictionary parsing callbacks */
+ 
+/* PARSE_STRING( "FontName", font_name ) -- handled by special routine */
+   PARSE_INT( "PaintType", paint_type )
+   PARSE_INT( "FontType", font_type )
+   PARSE_FIXEDS2( "FontMatrix", 4, font_matrix )
+/*  PARSE_COORDS2( "FontBBox", 4, font_bbox ) -- handled by special func */
+   PARSE_INT( "StrokeWidth", stroke_width )
+
+#undef FACE
+
+
--- /dev/null
+++ b/src/type1z/type1z.c
@@ -1,0 +1,41 @@
+/***************************************************************************/
+/*                                                                         */
+/*  type1.c                                                                */
+/*                                                                         */
+/*  FreeType Type 1 driver component                                       */
+/*                                                                         */
+/*  Copyright 1996-1998 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used        */
+/*  modified and distributed under the terms of the FreeType project       */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*                                                                         */
+/*  This file is used to compile the FreeType Type 1  font driver.         */
+/*  It relies on all components included in the "base" layer (see          */
+/*  the file "ftbase.c"). Source code is located in "freetype/ttlib"       */
+/*  and contains :                                                         */
+/*                                                                         */
+/*     - a driver interface                                                */
+/*     - an object manager                                                 */
+/*     - a table loader                                                    */
+/*     - a glyph loader                                                    */
+/*     - a glyph hinter                                                    */
+/*                                                                         */
+/***************************************************************************/
+
+
+
+#include <t1parse.c>
+#include <t1load.c>
+#include <t1objs.c>
+#include <t1driver.c>
+/*
+#include <t1hinter.c>
+#include <t1gload.c>
+#include <t1encode.c>
+*/
+