fixed divide by zero bug
added CFF/OpenType driver source (not working for now)
diff --git a/CHANGES b/CHANGES
index e7ffb23..5c1b7ae 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,14 @@
 LATEST_CHANGES
 
+  - fixed potential "divide by zero" bugs in ftcalc.c.. my god..
+
+  - added source code for the OpenType/CFF driver (still incomplete though..)
+
+  - modified the SFNT driver slightly to perform more robust header
+    checks in TT_Load_SFNT_Header. This prevents certain font files
+    (e.g. some Type 1 Multiple Masters) from being incorrectly "recognized"
+    as TrueType font files..
+
   - moved a lot of stuff from the TrueType driver to the SFNT module,
     this allows greater code re-use between font drivers (e.g. TrueType,
     OpenType, Compact-TrueType, etc..)
diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c
index ddc6946..90d58e1 100644
--- a/src/base/ftcalc.c
+++ b/src/base/ftcalc.c
@@ -132,13 +132,13 @@
   {
     FT_Int s;
 
-
     s = 1;
     if ( a < 0 ) { a = -a; s = -s; }
     if ( b < 0 ) { b = -b; s = -s; }
     if ( c < 0 ) { c = -c; s = -s; }
 
-    return s * ( ( (FT_Int64)a * b + ( c >> 1 ) ) / c );
+    return s * ( c > 0 ? ( ( (FT_Int64)a * b + ( c >> 1 ) ) / c )
+                       : 0x7FFFFFFF );
   }
 
 
@@ -344,21 +344,22 @@
     s ^= b; b = ABS( b );
     s ^= c; c = ABS( c );
 
-    if ( a <= 46340 && b <= 46340 && c <= 176095L )
+    if ( a <= 46340 && b <= 46340 && c <= 176095L && c > 0)
     {
-      a = ( a*b + (c >> 1) ) / c;
+      a = a*b + (c >> 1) ) / c;
     }
-    else
+    else if (c > 0)
     {
       FT_Int64  temp, temp2;
 
-
       FT_MulTo64( a, b, &temp );
       temp2.hi = (FT_Int32)(c >> 31);
       temp2.lo = (FT_Word32)(c / 2);
       FT_Add64( &temp, &temp2, &temp );
       a = FT_Div64by32( &temp, c );
     }
+    else
+      a = 0x7FFFFFFF;
 
     return ( s < 0 ) ? -a : a;
   }
@@ -614,7 +615,6 @@
     FT_Int32   s;
     FT_Word32  q, r, i, lo;
 
-
     s  = x->hi;
     if ( s < 0 )
     {
@@ -626,7 +626,9 @@
     /* Shortcut */
     if ( x->hi == 0 )
     {
-      q = x->lo / y;
+      if (y > 0) q = x->lo / y;
+            else q = 0x7FFFFFFF;
+
       return ( s < 0 ) ? -(FT_Int32)q : (FT_Int32)q;
     }
 
diff --git a/src/cff/cff.c b/src/cff/cff.c
new file mode 100644
index 0000000..b2581e9
--- /dev/null
+++ b/src/cff/cff.c
@@ -0,0 +1,49 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cff.c                                                                  */
+/*                                                                         */
+/*    FreeType OpenType driver component (body only).                      */
+/*                                                                         */
+/*  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 used to compile the FreeType TrueType font driver.  It  */
+  /*  relies on all components included in the `base' layer (see the file  */
+  /*  `ftbase.c').  The source code is located in `freetype/ttlib' and     */
+  /*  contains:                                                            */
+  /*                                                                       */
+  /*  - a driver interface                                                 */
+  /*  - an object manager                                                  */
+  /*  - a table loader                                                     */
+  /*  - a glyph loader                                                     */
+  /*  - a glyph hinter/bytecode interpreter                                */
+  /*  - a charmap processor                                                */
+  /*  - an extension manager (only used for some tools)                    */
+  /*                                                                       */
+  /*  Note that the engine extensions found in `freetype/ttlib/extend' are */
+  /*  reserved to specific tools and/or font servers; they're not part of  */
+  /*  the `core' TrueType driver, even though they are separately linkable */
+  /*  to it.                                                               */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <t2driver.c>    /* driver interface     */
+#include <t2parse.c>     /* token parser         */
+#include <t2load.c>      /* tables loader        */
+#include <t2objs.c>      /* object management    */
+
+/* END */
diff --git a/src/cff/module.mk b/src/cff/module.mk
new file mode 100644
index 0000000..1e8b925
--- /dev/null
+++ b/src/cff/module.mk
@@ -0,0 +1,7 @@
+make_module_list: add_cff_driver
+
+add_cff_driver:
+	$(OPEN_DRIVER)cff_driver_interface$(CLOSE_DRIVER)
+	$(ECHO_DRIVER)cff       $(ECHO_DRIVER_DESC)OpenType fonts with extension *.otf$(ECHO_DRIVER_DONE)
+
+# EOF
diff --git a/src/cff/rules.mk b/src/cff/rules.mk
new file mode 100644
index 0000000..39e658d
--- /dev/null
+++ b/src/cff/rules.mk
@@ -0,0 +1,112 @@
+#
+# FreeType 2 OpenType/CFF driver configuration rules
+#
+
+
+# Copyright 1996-2000 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used modified
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT.  By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+# Include the rules defined for the SFNT driver, which is heavily used
+# by the TrueType one.
+#
+include $(SRC_)sfnt/rules.mk
+
+
+# OpenType driver directory
+#
+T2_DIR  := $(SRC_)cff
+T2_DIR_ := $(T2_DIR)$(SEP)
+
+
+# location of all extensions to the driver, if any
+#
+T2_EXT_DIR  := $(T2_DIR_)extend
+T2_EXT_DIR_ := $(T2_EXT_DIR)$(SEP)
+
+# additional include flags used when compiling the driver
+#
+T2_INCLUDE := $(SFNT_INCLUDE) $(T2_DIR) $(T2_EXT_DIR)
+
+
+# compilation flags for the driver
+#
+T2_CFLAGS  := $(T2_INCLUDE:%=$I%)
+T2_COMPILE := $(FT_COMPILE) $(T2_CFLAGS)
+
+
+# driver sources (i.e., C files)
+#
+T2_DRV_SRC := $(T2_DIR_)t2objs.c   \
+              $(T2_DIR_)t2load.c   \
+              $(T2_DIR_)t2gload.c  \
+              $(T2_DIR_)t2parse.c  \
+              $(T2_DIR_)t2driver.c
+
+# driver headers
+#
+T2_DRV_H := $(SFNT_H)             \
+            $(T2_DRV_SRC:%.c=%.h)
+
+
+# default extensions headers
+#
+T2_EXT_H := $(T2_EXT_SRC:.c=.h)
+
+
+# driver object(s)
+#
+#   T2_DRV_OBJ_M is used during `debug' builds
+#   T2_DRV_OBJ_S is used during `release' builds
+#
+T2_DRV_OBJ_M := $(T2_DRV_SRC:$(T2_DIR_)%.c=$(OBJ_)%.$O)
+T2_DRV_OBJ_S := $(OBJ_)cff.$O
+
+
+# default extensions objects
+#
+T2_EXT_OBJ := $(T2_EXT_SRC:$(T2_EXT_DIR_)%.c=$(OBJ_)%.$O)
+
+
+# driver source file(s)
+#
+T2_DRV_SRC_M := $(T2_DRV_SRC) $(SFNT_SRC)
+T2_DRV_SRC_S := $(T2_DIR_)cff.c
+
+
+# driver - single object
+#
+#  the driver is recompiled if any of the header or source files is changed
+#  as well as any of the shared source files found in `shared/sfnt'
+#
+$(T2_DRV_OBJ_S): $(BASE_H) $(T2_DRV_H) $(T2_DRV_SRC) $(T2_DRV_SRC_S)
+	$(T2_COMPILE) $T$@ $(T2_DRV_SRC_S)
+
+
+
+# driver - multiple objects
+#
+#   All objects are recompiled if any of the header files is changed
+#
+$(OBJ_)t2%.$O: $(T2_DIR_)t2%.c $(BASE_H) $(T2_DRV_H)
+	$(T2_COMPILE) $T$@ $<
+
+$(OBJ_)t2x%.$O: $(T2_EXT_DIR_)t2x%.c $(BASE_H) $(SFNT_H) $(T2_EXT_H)
+	$(T2_COMPILE) $T$@ $<
+
+$(OBJ_)t2%.$O: $(SFNT_DIR_)t2%.c $(BASE_H) $(SFNT_H)
+	$(T2_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(T2_DRV_OBJ_S)
+DRV_OBJS_M += $(T2_DRV_OBJ_M)
+
+# EOF
diff --git a/src/cff/t2driver.c b/src/cff/t2driver.c
new file mode 100644
index 0000000..cac43ca
--- /dev/null
+++ b/src/cff/t2driver.c
@@ -0,0 +1,444 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2driver.c                                                             */
+/*                                                                         */
+/*    OpenType font driver implementation (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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/sfnt.h>
+#include <freetype/ttnameid.h>
+
+#include <t2driver.h>
+#include <t2gload.h>
+
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttdriver
+
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                          F A C E S                              ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+#undef  PAIR_TAG
+#define PAIR_TAG( left, right )  ( ((TT_ULong)left << 16) | (TT_ULong)right )
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Kerning                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to return the kerning vector between two      */
+  /*    glyphs of the same face.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to the source face object.                 */
+  /*                                                                       */
+  /*    left_glyph  :: The index of the left glyph in the kern pair.       */
+  /*                                                                       */
+  /*    right_glyph :: The index of the right glyph in the kern pair.      */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    kerning     :: The kerning vector.  This is in font units for      */
+  /*                   scalable formats, and in pixels for fixed-sizes     */
+  /*                   formats.                                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only horizontal layouts (left-to-right & right-to-left) are        */
+  /*    supported by this function.  Other layouts, or more sophisticated  */
+  /*    kernings are out of scope of this method (the basic driver         */
+  /*    interface is meant to be simple).                                  */
+  /*                                                                       */
+  /*    They can be implemented by format-specific interfaces.             */
+  /*                                                                       */
+  static
+  TT_Error  Get_Kerning( TT_Face     face,
+                         TT_UInt     left_glyph,
+                         TT_UInt     right_glyph,
+                         TT_Vector*  kerning )
+  {
+    TT_Kern_0_Pair*  pair;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    kerning->x = 0;
+    kerning->y = 0;
+
+    if ( face->kern_pairs )
+    {
+      /* there are some kerning pairs in this font file! */
+      TT_ULong  search_tag = PAIR_TAG( left_glyph, right_glyph );
+      TT_Long   left, right;
+
+
+      left  = 0;
+      right = face->num_kern_pairs - 1;
+
+      while ( left <= right )
+      {
+        TT_Int    middle   = left + ((right-left) >> 1);
+        TT_ULong  cur_pair;
+
+
+        pair     = face->kern_pairs + middle;
+        cur_pair = PAIR_TAG( pair->left, pair->right );
+
+        if ( cur_pair == search_tag )
+          goto Found;
+
+        if ( cur_pair < search_tag )
+          left = middle+1;
+        else
+          right = middle-1;
+      }
+    }
+
+  Exit:
+    return FT_Err_Ok;
+
+  Found:
+    kerning->x = pair->value;
+    goto Exit;
+  }
+
+
+#undef PAIR_TAG
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                           S I Z E S                             ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Set_Char_Sizes                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to reset a size's character sizes (horizontal */
+  /*    and vertical) expressed in fractional points.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    char_width  :: The character width expressed in 26.6 fractional    */
+  /*                   points.                                             */
+  /*    char_height :: The character height expressed in 26.6 fractional   */
+  /*                   points.                                             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size        :: A handle to the target size object.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  TT_Error  Set_Char_Sizes( T2_Size     size,
+                            FT_F26Dot6  char_width,
+                            FT_F26Dot6  char_height,
+                            FT_UInt     horz_resolution,
+                            FT_UInt     vert_resolution )
+  {
+    FT_Size_Metrics*  metrics = &size->metrics;
+    T2_Face           face    = (T2_Face)size->face;
+    FT_Long           dim_x, dim_y;
+
+    /* This bit flag, when set, indicates that the pixel size must be */
+    /* truncated to an integer. Nearly all TrueType fonts have this   */
+    /* bit set, as hinting won't work really well otherwise.          */
+    /*                                                                */
+    /* However, for those rare fonts who do not set it, we override   */
+    /* the default computations performed by the base layer. I really */
+    /* don't know if this is useful, but hey, that's the spec :-)     */
+    /*                                                                */
+    if ( (face->header.Flags & 8) == 0 )
+    {
+      /* Compute pixel sizes in 26.6 units */
+      dim_x = (char_width * horz_resolution) / 72;
+      dim_y = (char_height * vert_resolution) / 72;
+
+      metrics->x_scale = FT_DivFix( dim_x, face->root.units_per_EM );
+      metrics->y_scale = FT_DivFix( dim_y, face->root.units_per_EM );
+
+      metrics->x_ppem    = (TT_UShort)(dim_x >> 6);
+      metrics->y_ppem    = (TT_UShort)(dim_y >> 6);
+    }
+
+    return T2_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>                                                               */
+  /*    pixel_width  :: The character width expressed in integer pixels.   */
+  /*                                                                       */
+  /*    pixel_height :: The character height expressed in integer pixels.  */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size         :: A handle to the target size object.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code. 0 means success                               */
+  /*                                                                       */
+  static
+  FT_Error  Set_Pixel_Sizes( T2_Size  size,
+                             FT_UInt  pixel_width,
+                             FT_UInt  pixel_height )
+  {
+    UNUSED(pixel_width);
+    UNUSED(pixel_height);
+
+    return T2_Reset_Size( size );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Load_Glyph                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to load a glyph within a given glyph slot.    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    slot        :: A handle to the target slot object where the glyph  */
+  /*                   will be loaded.                                     */
+  /*                                                                       */
+  /*    size        :: A handle to the source face size at which the glyph */
+  /*                   must be scaled/loaded/etc.                          */
+  /*                                                                       */
+  /*    glyph_index :: The index of the glyph in the font file.            */
+  /*                                                                       */
+  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
+  /*                   FTLOAD_??? constants can be used to control the     */
+  /*                   glyph loading process (e.g., whether the outline    */
+  /*                   should be scaled, whether to load bitmaps or not,   */
+  /*                   whether to hint the outline, etc).                  */
+  /* <Output>                                                              */
+  /*    result      :: A set of bit flags indicating the type of data that */
+  /*                   was loaded in the glyph slot (outline, bitmap,      */
+  /*                   pixmap, etc).                                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Load_Glyph( T2_GlyphSlot  slot,
+                        T2_Size       size,
+                        FT_UShort     glyph_index,
+                        FT_UInt       load_flags )
+  {
+    FT_Error  error;
+
+
+    if ( !slot )
+      return FT_Err_Invalid_Handle;
+
+    /* check that we want a scaled outline or bitmap */
+    if ( !size )
+      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+    if ( load_flags & FT_LOAD_NO_SCALE )
+      size = NULL;
+
+    /* reset the size object if necessary */
+    if ( size )
+    {
+      /* these two object must have the same parent */
+      if ( size->face != slot->face )
+        return FT_Err_Invalid_Face_Handle;
+    }
+
+    /* now load the glyph outline if necessary */
+#if 1 /* XXXX: TODO */
+    error = FT_Err_Unimplemented_Feature;
+#else    
+    error = T2_Load_Glyph( size, slot, glyph_index, load_flags );
+#endif
+    /* force drop-out mode to 2 - irrelevant now */
+    /* slot->outline.dropout_mode = 2; */
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****             C H A R A C T E R   M A P P I N G S                 ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Char_Index                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Uses a charmap to return a given character code's glyph index.     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charmap  :: A handle to the source charmap object.                 */
+  /*    charcode :: The character code.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index.  0 means `undefined character code'.                  */
+  /*                                                                       */
+  static
+  FT_UInt  Get_Char_Index( TT_CharMap  charmap,
+                           FT_Long     charcode )
+  {
+    FT_Error       error;
+    T2_Face        face;
+    TT_CMapTable*  cmap;
+
+    cmap = &charmap->cmap;
+    face = (T2_Face)charmap->root.face;
+
+    /* Load table if needed */
+    if ( !cmap->loaded )
+    {
+      SFNT_Interface*  sfnt = (SFNT_Interface*)face->sfnt;
+
+      error = sfnt->load_charmap( face, cmap, face->root.stream );
+      if (error) return error;
+
+      cmap->loaded = TRUE;
+    }
+
+    return (cmap->get_index ? cmap->get_index( cmap, charcode ) : 0 );
+  }
+
+
+  static
+  FTDriver_Interface  t2_get_interface( T2_Driver  driver, const char* interface )
+  {
+    FT_Driver        sfntd = FT_Get_Driver( driver->root.library, "sfnt" );
+    SFNT_Interface*  sfnt;
+    
+    /* only return the default interface from the SFNT module */
+    if (sfntd)
+    {
+      sfnt = (SFNT_Interface*)(sfntd->interface.format_interface);
+      if (sfnt)
+        return sfnt->get_interface( (FT_Driver)driver, interface );
+    }
+    return 0;
+  }
+
+
+  /* The FT_DriverInterface structure is defined in ftdriver.h. */
+
+  const FT_DriverInterface  cff_driver_interface =
+  {
+    sizeof ( T2_DriverRec ),
+    sizeof ( TT_FaceRec ),
+    sizeof ( FT_SizeRec ),
+    sizeof ( FT_GlyphSlotRec ),
+
+    "cff",           /* driver name                           */
+    100,             /* driver version == 1.0                 */
+    200,             /* driver requires FreeType 2.0 or above */
+
+    (void*)0,
+
+    (FTDriver_initDriver)        T2_Init_Driver,
+    (FTDriver_doneDriver)        T2_Done_Driver,
+    (FTDriver_getInterface)      t2_get_interface,
+
+    (FTDriver_initFace)          T2_Init_Face,
+    (FTDriver_doneFace)          T2_Done_Face,
+    (FTDriver_getKerning)        Get_Kerning,
+
+    (FTDriver_initSize)          T2_Init_Size,
+    (FTDriver_doneSize)          T2_Done_Size,
+    (FTDriver_setCharSizes)      Set_Char_Sizes,
+    (FTDriver_setPixelSizes)     Set_Pixel_Sizes,
+
+    (FTDriver_initGlyphSlot)     T2_Init_GlyphSlot,
+    (FTDriver_doneGlyphSlot)     T2_Done_GlyphSlot,
+    (FTDriver_loadGlyph)         Load_Glyph,
+
+    (FTDriver_getCharIndex)      Get_Char_Index,
+  };
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    getDriverInterface                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used when compiling the TrueType driver as a      */
+  /*    shared library (`.DLL' or `.so').  It will be used by the          */
+  /*    high-level library of FreeType to retrieve the address of the      */
+  /*    driver's generic interface.                                        */
+  /*                                                                       */
+  /*    It shouldn't be implemented in a static build, as each driver must */
+  /*    have the same function as an exported entry point.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    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 &cff_driver_interface;
+  }
+
+#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
diff --git a/src/cff/t2driver.h b/src/cff/t2driver.h
new file mode 100644
index 0000000..129096e
--- /dev/null
+++ b/src/cff/t2driver.h
@@ -0,0 +1,34 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2driver.h                                                             */
+/*                                                                         */
+/*    High-level OpenType driver interface (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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef T2DRIVER_H
+#define T2DRIVER_H
+
+#include <freetype/internal/ftdriver.h>
+#include <freetype/ttnameid.h>
+#include <t2objs.h>
+#include <t2errors.h>
+
+
+  FT_EXPORT_VAR(const FT_DriverInterface)  cff_driver_interface;
+
+
+#endif /* T2DRIVER_H */
+
+
+/* END */
diff --git a/src/cff/t2errors.h b/src/cff/t2errors.h
new file mode 100644
index 0000000..ab3d4e4
--- /dev/null
+++ b/src/cff/t2errors.h
@@ -0,0 +1,126 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2errors.h                                                             */
+/*                                                                         */
+/*    OpenType error ID definitions (specification only).                  */
+/*                                                                         */
+/*  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 T2ERRORS_H
+#define T2ERRORS_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  T2_Err_Ok                       FT_Err_Ok
+
+  /* High level API errors. */
+
+#define  T2_Err_Invalid_File_Format      FT_Err_Invalid_File_Format
+#define  T2_Err_Invalid_Argument         FT_Err_Invalid_Argument
+#define  T2_Err_Invalid_Driver_Handle    FT_Err_Invalid_Driver_Handle
+#define  T2_Err_Invalid_Face_Handle      FT_Err_Invalid_Face_Handle
+#define  T2_Err_Invalid_Instance_Handle  FT_Err_Invalid_Size_Handle
+#define  T2_Err_Invalid_Glyph_Handle     FT_Err_Invalid_Slot_Handle
+#define  T2_Err_Invalid_CharMap_Handle   FT_Err_Invalid_CharMap_Handle
+#define  T2_Err_Invalid_Glyph_Index      FT_Err_Invalid_Glyph_Index
+
+#define  T2_Err_Unimplemented_Feature    FT_Err_Unimplemented_Feature
+#define  T2_Err_Unavailable_Outline      FT_Err_Unavailable_Outline
+#define  T2_Err_Unavailable_Bitmap       FT_Err_Unavailable_Bitmap
+#define  T2_Err_Unavailable_Pixmap       FT_Err_Unavailable_Pixmap
+#define  T2_Err_File_Is_Not_Collection   FT_Err_File_Is_Not_Collection
+
+#define  T2_Err_Invalid_Engine           FT_Err_Invalid_Driver_Handle
+
+  /* Internal errors. */
+
+#define  T2_Err_Out_Of_Memory            FT_Err_Out_Of_Memory
+#define  T2_Err_Unlisted_Object          FT_Err_Unlisted_Object
+
+  /* General glyph outline errors. */
+
+#define  T2_Err_Too_Many_Points          FT_Err_Too_Many_Points
+#define  T2_Err_Too_Many_Contours        FT_Err_Too_Many_Contours
+#define  T2_Err_Too_Many_Ins             FT_Err_Too_Many_Hints
+#define  T2_Err_Invalid_Composite        FT_Err_Invalid_Composite
+
+  /* Bytecode interpreter error codes. */
+
+  /* These error codes are produced by the TrueType */
+  /* bytecode interpreter.  They usually indicate a */
+  /* broken font file, a broken glyph within a font */
+  /* file, or a bug in the interpreter!             */
+
+#define T2_Err_Invalid_Opcode           0x400
+#define T2_Err_Too_Few_Arguments        0x401
+#define T2_Err_Stack_Overflow           0x402
+#define T2_Err_Code_Overflow            0x403
+#define T2_Err_Bad_Argument             0x404
+#define T2_Err_Divide_By_Zero           0x405
+#define T2_Err_Storage_Overflow         0x406
+#define T2_Err_Cvt_Overflow             0x407
+#define T2_Err_Invalid_Reference        0x408
+#define T2_Err_Invalid_Distance         0x409
+#define T2_Err_Interpolate_Twilight     0x40A
+#define T2_Err_Debug_OpCode             0x40B
+#define T2_Err_ENDF_In_Exec_Stream      0x40C
+#define T2_Err_Out_Of_CodeRanges        0x40D
+#define T2_Err_Nested_DEFS              0x40E
+#define T2_Err_Invalid_CodeRange        0x40F
+#define T2_Err_Invalid_Displacement     0x410
+#define T2_Err_Execution_Too_Long       0x411
+
+#define T2_Err_Too_Many_Instruction_Defs  0x412
+#define T2_Err_Too_Many_Function_Defs     0x412
+
+  /* Other TrueType specific error codes. */
+
+#define T2_Err_Table_Missing            0x420
+#define T2_Err_Too_Many_Extensions      0x421
+#define T2_Err_Extensions_Unsupported   0x422
+#define T2_Err_Invalid_Extension_Id     0x423
+
+#define T2_Err_No_Vertical_Data         0x424
+
+#define T2_Err_Max_Profile_Missing      0x430
+#define T2_Err_Header_Table_Missing     0x431
+#define T2_Err_Horiz_Header_Missing     0x432
+#define T2_Err_Locations_Missing        0x433
+#define T2_Err_Name_Table_Missing       0x434
+#define T2_Err_CMap_Table_Missing       0x435
+#define T2_Err_Hmtx_Table_Missing       0x436
+#define T2_Err_OS2_Table_Missing        0x437
+#define T2_Err_Post_Table_Missing       0x438
+
+#define T2_Err_Invalid_Horiz_Metrics    0x440
+#define T2_Err_Invalid_CharMap_Format   0x441
+#define T2_Err_Invalid_PPem             0x442
+#define T2_Err_Invalid_Vert_Metrics     0x443
+
+#define T2_Err_Could_Not_Find_Context   0x450
+
+#endif /* FTERRID_H */
+
+
+/* END */
diff --git a/src/cff/t2gload.c b/src/cff/t2gload.c
new file mode 100644
index 0000000..a5caa75
--- /dev/null
+++ b/src/cff/t2gload.c
@@ -0,0 +1,1177 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2gload.c                                                              */
+/*                                                                         */
+/*    OpenType Glyph Loader (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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/sfnt.h>
+#include <freetype/tttags.h>
+
+
+#include <t2gload.h>
+
+  /* required for the tracing mode */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttgload
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Composite font flags.                                                 */
+  /*                                                                       */
+#define ARGS_ARE_WORDS       0x001
+#define ARGS_ARE_XY_VALUES   0x002
+#define ROUND_XY_TO_GRID     0x004
+#define WE_HAVE_A_SCALE      0x008
+/* reserved                  0x010 */
+#define MORE_COMPONENTS      0x020
+#define WE_HAVE_AN_XY_SCALE  0x040
+#define WE_HAVE_A_2X2        0x080
+#define WE_HAVE_INSTR        0x100
+#define USE_MY_METRICS       0x200
+
+
+
+  /*************************************************************************/
+  /*    Returns the horizontal or vertical metrics in font units for a     */
+  /*    given glyph.  The metrics are the left side bearing (resp. top     */
+  /*    side bearing) and advance width (resp. advance height).            */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  T2_Get_Metrics( TT_HoriHeader*  header,
+                        FT_UInt       index,
+                        FT_Short*       bearing,
+                        FT_UShort*      advance )
+  {
+    TT_LongMetrics*  longs_m;
+    TT_UShort        k = header->number_Of_HMetrics;
+
+
+    if ( index < k )
+    {
+      longs_m  = (TT_LongMetrics*)header->long_metrics + index;
+      *bearing = longs_m->bearing;
+      *advance = longs_m->advance;
+    }
+    else
+    {
+      *bearing = ((TT_ShortMetrics*)header->short_metrics)[index - k];
+      *advance = ((TT_LongMetrics*)header->long_metrics)[k - 1].advance;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*    Returns the horizontal metrics in font units for a given glyph.    */
+  /*    If `check' is true, take care of monospaced fonts by returning the */
+  /*    advance width maximum.                                             */
+  /*                                                                       */
+  static
+  void Get_HMetrics( T2_Face     face,
+                     FT_UInt     index,
+                     FT_Bool     check,
+                     FT_Short*   lsb,
+                     FT_UShort*  aw )
+  {
+    T2_Get_Metrics( &face->horizontal, index, lsb, aw );
+
+    if ( check && face->postscript.isFixedPitch )
+      *aw = face->horizontal.advance_Width_Max;
+  }
+
+
+  /*************************************************************************/
+  /*    Returns the advance width table for a given pixel size if it is    */
+  /*    found in the font's `hdmx' table (if any).                         */
+  /*                                                                       */
+  static
+  FT_Byte*  Get_Advance_Widths( T2_Face    face,
+                                FT_UShort  ppem )
+  {
+    FT_UShort  n;
+
+    for ( n = 0; n < face->hdmx.num_records; n++ )
+      if ( face->hdmx.records[n].ppem == ppem )
+        return face->hdmx.records[n].widths;
+
+    return NULL;
+  }
+
+
+#define cur_to_org( n, zone )  \
+          MEM_Copy( (zone)->org, (zone)->cur, n * sizeof ( TT_Vector ) )
+
+#define org_to_cur( n, zone )  \
+          MEM_Copy( (zone)->cur, (zone)->org, n * sizeof ( TT_Vector ) )
+
+
+  /*************************************************************************/
+  /*    Translates an array of coordinates.                                */
+  /*                                                                       */
+  static
+  void  translate_array( FT_UInt     n,
+                         FT_Vector*  coords,
+                         FT_Pos      delta_x,
+                         FT_Pos      delta_y )
+  {
+    FT_UInt  k;
+
+    if ( delta_x )
+      for ( k = 0; k < n; k++ )
+        coords[k].x += delta_x;
+
+    if ( delta_y )
+      for ( k = 0; k < n; k++ )
+        coords[k].y += delta_y;
+  }
+
+
+
+  /*************************************************************************/
+  /*    Mounts one glyph zone on top of another.  This is needed to        */
+  /*    assemble composite glyphs.                                         */
+  /*                                                                       */
+  static
+  void  mount_zone( FT_GlyphZone*  source,
+                    FT_GlyphZone*  target )
+  {
+    FT_UInt  np;
+    FT_Int   nc;
+
+    np = source->n_points;
+    nc = source->n_contours;
+
+    target->org   = source->org + np;
+    target->cur   = source->cur + np;
+    target->tags = source->tags + np;
+
+    target->contours = source->contours + nc;
+
+    target->n_points   = 0;
+    target->n_contours = 0;
+  }
+
+
+#undef  IS_HINTED
+#define IS_HINTED(flags)  ((flags & FT_LOAD_NO_HINTING) == 0)
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Load_Simple_Glyph                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads a simple (i.e, non-composite) glyph.  This function is used  */
+  /*    for the `Load_Simple' state of TT_Load_Glyph().  All composite     */
+  /*    glyphs elements will be loaded with routine.                       */
+  /*                                                                       */
+  static
+  FT_Error  Load_Simple( T2_Loader*       load,
+                         FT_UInt          byte_count,
+                         FT_Int           n_contours,
+                         FT_Bool          debug )
+  {
+    FT_Error       error;
+    FT_Stream      stream = load->stream;
+    FT_GlyphZone*  zone   = &load->zone;
+    T2_Face        face = load->face;
+
+    FT_UShort      n_ins;
+    FT_Int         n, n_points;
+
+    /*********************************************************************/
+    /* simple check                                                      */
+
+    if ( n_contours > load->left_contours )
+    {
+      FT_TRACE0(( "ERROR: Glyph index %ld has %d contours > left %d\n",
+                   load->glyph_index,
+                   n_contours,
+                   load->left_contours ));
+      return TT_Err_Too_Many_Contours;
+    }
+
+    /* preparing the execution context */
+    mount_zone( &load->base, zone );
+
+    /*********************************************************************/
+    /* reading the contours endpoints                                    */
+
+    if ( ACCESS_Frame( byte_count ) )
+      return error;
+
+    for ( n = 0; n < n_contours; n++ )
+      zone->contours[n] = GET_UShort();
+
+    n_points = 0;
+    if ( n_contours > 0 )
+      n_points = zone->contours[n_contours - 1] + 1;
+
+
+    /*********************************************************************/
+    /* reading the bytecode instructions                                 */
+
+    n_ins = GET_UShort();
+    load->face->root.glyph->control_len = n_ins;
+
+    if ( n_points > load->left_points )
+    {
+      FT_TRACE0(( "ERROR: Too many points in glyph %ld\n", load->glyph_index ));
+      error = TT_Err_Too_Many_Points;
+      goto Fail;
+    }
+
+    FT_TRACE4(( "Instructions size : %d\n", n_ins ));
+
+    if ( n_ins > face->max_profile.maxSizeOfInstructions )
+    {
+      FT_TRACE0(( "ERROR: Too many instructions!\n" ));
+      error = TT_Err_Too_Many_Ins;
+      goto Fail;
+    }
+
+    if (stream->cursor + n_ins > stream->limit)
+    {
+      FT_TRACE0(( "ERROR: Instruction count mismatch!\n" ));
+      error = TT_Err_Too_Many_Ins;
+      goto Fail;
+    }
+
+    stream->cursor += n_ins;
+
+    /*********************************************************************/
+    /* reading the point tags                                           */
+
+    {
+      FT_Byte*  flag  = load->zone.tags;
+      FT_Byte*  limit = flag + n_points;
+      FT_Byte   c, count;
+
+      for (; flag < limit; flag++)
+      {
+        *flag = c = GET_Byte();
+        if ( c & 8 )
+        {
+          for ( count = GET_Byte(); count > 0; count-- )
+            *++flag = c;
+        }
+      }
+    }
+
+    /*********************************************************************/
+    /* reading the X coordinates                                         */
+
+    {
+      FT_Vector*  vec   = zone->org;
+      FT_Vector*  limit = vec + n_points;
+      FT_Byte*    flag  = zone->tags;
+      FT_Pos      x     = 0;
+
+      for ( ; vec < limit; vec++, flag++ )
+      {
+        FT_Pos  y = 0;
+
+        if ( *flag & 2 )
+        {
+          y = GET_Byte();
+          if ((*flag & 16) == 0) y = -y;
+        }
+        else if ((*flag & 16) == 0)
+          y = GET_Short();
+
+        x     += y;
+        vec->x = x;
+      }
+    }
+
+    /*********************************************************************/
+    /* reading the Y coordinates                                         */
+
+    {
+      FT_Vector*  vec   = zone->org;
+      FT_Vector*  limit = vec + n_points;
+      FT_Byte*    flag  = zone->tags;
+      FT_Pos      x     = 0;
+
+      for ( ; vec < limit; vec++, flag++ )
+      {
+        FT_Pos  y = 0;
+
+        if ( *flag & 4 )
+        {
+          y = GET_Byte();
+          if ((*flag & 32) == 0) y = -y;
+        }
+        else if ((*flag & 32) == 0)
+          y = GET_Short();
+
+        x     += y;
+        vec->y = x;
+      }
+    }
+
+    FORGET_Frame();
+
+    /*********************************************************************/
+    /* Add shadow points                                                  */
+
+    /* Now add the two shadow points at n and n + 1.    */
+    /* We need the left side bearing and advance width. */
+
+    {
+      FT_Vector*  pp1;
+      FT_Vector*  pp2;
+
+      /* pp1 = xMin - lsb */
+      pp1    = zone->org + n_points;
+      pp1->x = load->bbox.xMin - load->left_bearing;
+      pp1->y = 0;
+
+      /* pp2 = pp1 + aw */
+      pp2    = pp1 + 1;
+      pp2->x = pp1->x + load->advance;
+      pp2->y = 0;
+
+      /* clear the touch tags */
+      for ( n = 0; n < n_points; n++ )
+        zone->tags[n] &= FT_Curve_Tag_On;
+
+      zone->tags[n_points    ] = 0;
+      zone->tags[n_points + 1] = 0;
+    }
+    /* Note that we return two more points that are not */
+    /* part of the glyph outline.                       */
+
+    zone->n_points   = n_points;
+    zone->n_contours = n_contours;
+    n_points        += 2;
+
+    /*******************************************/
+    /* now eventually scale and hint the glyph */
+
+    if (load->load_flags & FT_LOAD_NO_SCALE)
+    {
+      /* no scaling, just copy the orig arrays into the cur ones */
+      org_to_cur( n_points, zone );
+    }
+    else
+    {
+      FT_Vector*  vec = zone->org;
+      FT_Vector*  limit = vec + n_points;
+      FT_Fixed    x_scale = load->size->root.metrics.x_scale;
+      FT_Fixed    y_scale = load->size->root.metrics.y_scale;
+
+      /* first scale the glyph points */
+      for (; vec < limit; vec++)
+      {
+        vec->x = FT_MulFix( vec->x, x_scale );
+        vec->y = FT_MulFix( vec->y, y_scale );
+      }
+
+      /* if hinting, round pp1, and shift the glyph accordingly */
+      if ( !IS_HINTED(load->load_flags) )
+      {
+        org_to_cur( n_points, zone );
+      }
+      else
+      {
+        FT_Pos  x = zone->org[n_points-2].x;
+        x = ((x + 32) & -64) - x;
+        translate_array( n_points, zone->org, x, 0 );
+
+        org_to_cur( n_points, zone );
+
+        zone->cur[n_points-1].x = (zone->cur[n_points-1].x + 32) & -64;
+
+      }
+    }
+
+    /* save glyph phantom points */
+    if ( !load->preserve_pps )
+    {
+      load->pp1 = zone->cur[n_points - 2];
+      load->pp2 = zone->cur[n_points - 1];
+    }
+
+    return FT_Err_Ok;
+
+  Fail:
+    FORGET_Frame();
+    return error;
+  }
+
+
+
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    load_opentype_glyph                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads a given truetype glyph. Handles composites and uses a        */
+  /*    T2_Loader object..                                                 */
+  /*                                                                       */
+  static
+  FT_Error  load_opentype_glyph( T2_Loader*  loader,
+                                 FT_UInt     glyph_index )
+  {
+    FT_Stream    stream = loader->stream;
+    FT_Error     error;
+    T2_Face      face   = loader->face;
+    FT_ULong     offset;
+    FT_Int       num_subglyphs = 0, contours_count;
+    FT_UInt      index, num_points, num_contours, count;
+    FT_Fixed     x_scale, y_scale;
+    FT_ULong     ins_offset;
+
+    /* check glyph index */
+    index = glyph_index;
+    if ( index >= (TT_UInt)face->root.num_glyphs )
+    {
+      error = TT_Err_Invalid_Glyph_Index;
+      goto Fail;
+    }
+
+    loader->glyph_index = glyph_index;
+    num_contours = 0;
+    num_points   = 0;
+    ins_offset   = 0;
+
+    x_scale = 0x10000;
+    y_scale = 0x10000;
+    if ( (loader->load_flags & FT_LOAD_NO_SCALE)==0 )
+    {
+      x_scale = loader->size->root.metrics.x_scale;
+      y_scale = loader->size->root.metrics.y_scale;
+    }
+
+    /* get horizontal metrics */
+    {
+      FT_Short   left_bearing;
+      FT_UShort  advance_width;
+
+      Get_HMetrics( face, index,
+                    (FT_Bool)!(loader->load_flags &
+                                 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH),
+                    &left_bearing,
+                    &advance_width );
+
+      loader->left_bearing = left_bearing;
+      loader->advance      = advance_width;
+    }
+
+    /* load glyph header */
+    offset = face->glyph_locations[index];
+    count  = 0;
+    if (index < (TT_UInt)face->num_locations-1)
+       count = face->glyph_locations[index+1] - offset;
+
+
+    if (count == 0)
+    {
+      /* as described by Frederic Loyer, these are spaces, and */
+      /* not the unknown glyph.                                */
+      loader->bbox.xMin = 0;
+      loader->bbox.xMax = 0;
+      loader->bbox.yMin = 0;
+      loader->bbox.yMax = 0;
+
+      loader->pp1.x = 0;
+      loader->pp2.x = loader->advance;
+
+      if ( (loader->load_flags & FT_LOAD_NO_SCALE)==0 )
+        loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+
+      goto Load_End;
+    }
+
+    offset = loader->glyf_offset + offset;
+
+    /* read first glyph header */
+    if ( FILE_Seek( offset ) || ACCESS_Frame( 10L ) )
+      goto Fail;
+
+    contours_count = GET_Short();
+
+    loader->bbox.xMin = GET_Short();
+    loader->bbox.yMin = GET_Short();
+    loader->bbox.xMax = GET_Short();
+    loader->bbox.yMax = GET_Short();
+
+    FORGET_Frame();
+
+    FT_TRACE6(( "Glyph %ld\n", index ));
+    FT_TRACE6(( " # of contours : %d\n", num_contours ));
+    FT_TRACE6(( " xMin: %4d  xMax: %4d\n", loader->bbox.xMin,
+                                           loader->bbox.xMax ));
+    FT_TRACE6(( " yMin: %4d  yMax: %4d\n", loader->bbox.yMin,
+                                           loader->bbox.yMax ));
+    FT_TRACE6(( "-" ));
+
+    count -= 10;
+
+    if ( contours_count > loader->left_contours )
+    {
+      FT_TRACE0(( "ERROR: Too many contours for glyph %ld\n", index ));
+      error = TT_Err_Too_Many_Contours;
+      goto Fail;
+    }
+
+    loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
+    loader->pp1.y = 0;
+    loader->pp2.x = loader->pp1.x + loader->advance;
+    loader->pp2.y = 0;
+
+    if ((loader->load_flags & FT_LOAD_NO_SCALE)==0)
+    {
+      loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
+      loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+    }
+
+    /*************************************************************************/
+    /*************************************************************************/
+    /*************************************************************************/
+
+    /**********************************************************************/
+    /* if it is a simple glyph, load it                                   */
+    if (contours_count >= 0)
+    {
+      FT_UInt  num_base_points;
+
+      error = Load_Simple( loader, count, contours_count, 0 );
+      if ( error ) goto Fail;
+
+      /* Note: We could have put the simple loader source there */
+      /*       but the code is fat enough already :-)           */
+      num_points   = loader->zone.n_points;
+      num_contours = loader->zone.n_contours;
+
+      num_base_points = loader->base.n_points;
+      {
+        FT_UInt  k;
+        for ( k = 0; k < num_contours; k++ )
+          loader->zone.contours[k] += num_base_points;
+      }
+
+      loader->base.n_points   += num_points;
+      loader->base.n_contours += num_contours;
+
+      loader->zone.n_points    = 0;
+      loader->zone.n_contours  = 0;
+
+      loader->left_points   -= num_points;
+      loader->left_contours -= num_contours;
+    }
+    /*************************************************************************/
+    /*************************************************************************/
+    /*************************************************************************/
+
+    /************************************************************************/
+    else /* otherwise, load a composite !!                                  */
+    {
+      /* for each subglyph, read composite header */
+	  T2_GlyphSlot  glyph    = loader->glyph;
+      FT_SubGlyph*  subglyph = glyph->subglyphs + glyph->num_subglyphs;
+
+      if (ACCESS_Frame(count)) goto Fail;
+
+      num_subglyphs = 0;
+      do
+      {
+        TT_Fixed  xx, xy, yy, yx;
+		FT_UInt   total_subglyphs;
+
+        /* grow the 'glyph->subglyphs' table if necessary */
+		total_subglyphs = glyph->num_subglyphs + num_subglyphs;
+		if ( total_subglyphs >= glyph->max_subglyphs )
+		{
+		  FT_UInt    new_max = glyph->max_subglyphs;
+		  FT_Memory  memory = loader->face->root.memory;
+
+          while (new_max <= total_subglyphs)
+		    new_max += 4;
+			
+		  if ( REALLOC_ARRAY( glyph->subglyphs, glyph->max_subglyphs,
+		                      new_max, FT_SubGlyph ) )
+            goto Fail;							  
+			
+		  glyph->max_subglyphs = new_max;
+		  subglyph = glyph->subglyphs + glyph->num_subglyphs + num_subglyphs;
+		}
+
+        subglyph->arg1 = subglyph->arg2 = 0;
+
+        subglyph->flags = GET_UShort();
+        subglyph->index = GET_UShort();
+
+        /* read arguments */
+        if (subglyph->flags & ARGS_ARE_WORDS)
+        {
+          subglyph->arg1 = GET_Short();
+          subglyph->arg2 = GET_Short();
+        }
+        else
+        {
+          subglyph->arg1 = GET_Char();
+          subglyph->arg2 = GET_Char();
+        }
+
+        /* read transform */
+        xx = yy = 0x10000;
+        xy = yx = 0;
+
+        if (subglyph->flags & WE_HAVE_A_SCALE)
+        {
+          xx = (TT_Fixed)GET_Short() << 2;
+          yy = xx;
+        }
+        else if (subglyph->flags & WE_HAVE_AN_XY_SCALE)
+        {
+          xx = (TT_Fixed)GET_Short() << 2;
+          yy = (TT_Fixed)GET_Short() << 2;
+        }
+        else if (subglyph->flags & WE_HAVE_A_2X2)
+        {
+          xx = (TT_Fixed)GET_Short() << 2;
+          xy = (TT_Fixed)GET_Short() << 2;
+          yx = (TT_Fixed)GET_Short() << 2;
+          yy = (TT_Fixed)GET_Short() << 2;
+        }
+
+        subglyph->transform.xx = xx;
+        subglyph->transform.xy = xy;
+        subglyph->transform.yx = yx;
+        subglyph->transform.yy = yy;
+
+        subglyph++;
+        num_subglyphs++;
+      }
+      while (subglyph[-1].flags & MORE_COMPONENTS);
+
+      FORGET_Frame();
+
+      /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
+      /* "as is" in the glyph slot (the client application will be     */
+      /* responsible for interpreting this data..)                     */
+      if ( loader->load_flags & FT_LOAD_NO_RECURSE )
+      {
+        /* set up remaining glyph fields */
+        glyph->num_subglyphs += num_subglyphs;
+        glyph->format         = ft_glyph_format_composite;
+        goto Load_End;
+      }
+
+
+    /*************************************************************************/
+    /*************************************************************************/
+    /*************************************************************************/
+
+      /*********************************************************************/
+      /* Now, read each subglyph independently..                           */
+      {
+        FT_Int  n, num_base_points, num_new_points;
+
+        subglyph = glyph->subglyphs + glyph->num_subglyphs;
+		glyph->num_subglyphs += num_subglyphs;
+		
+        for ( n = 0; n < num_subglyphs; n++, subglyph++ )
+        {
+          FT_Vector  pp1, pp2;
+          FT_Pos     x, y;
+
+          pp1 = loader->pp1;
+          pp2 = loader->pp2;
+
+          num_base_points = loader->base.n_points;
+
+          error = load_truetype_glyph( loader, subglyph->index );
+		  if (error) goto Fail;
+
+          if ( subglyph->flags & USE_MY_METRICS )
+          {
+            pp1 = loader->pp1;
+            pp2 = loader->pp2;
+          }
+          else
+          {
+            loader->pp1 = pp1;
+            loader->pp2 = pp2;
+          }
+
+          num_points   = loader->base.n_points;
+          num_contours = loader->base.n_contours;
+
+          num_new_points = num_points - num_base_points;
+
+          /********************************************************/
+          /* now perform the transform required for this subglyph */
+
+          if ( subglyph->flags & ( WE_HAVE_A_SCALE     |
+                                   WE_HAVE_AN_XY_SCALE |
+                                   WE_HAVE_A_2X2       ) )
+          {
+            FT_Vector*  cur = loader->zone.cur;
+            FT_Vector*  org = loader->zone.org;
+            FT_Vector*  limit = cur + num_new_points;
+
+            for ( ; cur < limit; cur++, org++ )
+            {
+              TT_Pos  nx, ny;
+
+              nx = FT_MulFix( cur->x, subglyph->transform.xx ) +
+                   FT_MulFix( cur->y, subglyph->transform.yx );
+
+              ny = FT_MulFix( cur->x, subglyph->transform.xy ) +
+                   FT_MulFix( cur->y, subglyph->transform.yy );
+
+              cur->x = nx;
+              cur->y = ny;
+
+              nx = FT_MulFix( org->x, subglyph->transform.xx ) +
+                   FT_MulFix( org->y, subglyph->transform.yx );
+
+              ny = FT_MulFix( org->x, subglyph->transform.xy ) +
+                   FT_MulFix( org->y, subglyph->transform.yy );
+
+              org->x = nx;
+              org->y = ny;
+            }
+          }
+
+          /* apply offset */
+
+          if ( !(subglyph->flags & ARGS_ARE_XY_VALUES) )
+          {
+            FT_Int   k = subglyph->arg1;
+            FT_UInt  l = subglyph->arg2;
+
+            if ( k >= num_base_points ||
+                 l >= (TT_UInt)num_new_points  )
+            {
+              error = TT_Err_Invalid_Composite;
+              goto Fail;
+            }
+
+            l += num_base_points;
+
+            x = loader->base.cur[k].x - loader->base.cur[l].x;
+            y = loader->base.cur[k].y - loader->base.cur[l].y;
+          }
+          else
+          {
+            x = subglyph->arg1;
+            y = subglyph->arg2;
+
+            if (!(loader->load_flags & FT_LOAD_NO_SCALE))
+            {
+              x = FT_MulFix( x, x_scale );
+              y = FT_MulFix( y, y_scale );
+
+              if ( subglyph->flags & ROUND_XY_TO_GRID )
+	          {
+	            x = (x + 32) & -64;
+	            y = (y + 32) & -64;
+	          }
+            }
+          }
+
+          translate_array( num_new_points, loader->zone.cur, x, y );
+          cur_to_org( num_new_points, &loader->zone );
+        }
+
+    /*************************************************************************/
+    /*************************************************************************/
+    /*************************************************************************/
+
+        /* we have finished loading all sub-glyphs, now, look for */
+        /* instructions for this composite !!                     */
+
+      }
+	  /* end of composite loading */
+    }
+
+    /*************************************************************************/
+    /*************************************************************************/
+    /*************************************************************************/
+    /*************************************************************************/
+
+  Load_End:
+    error = FT_Err_Ok;
+
+  Fail:
+    return error;
+  }
+
+
+
+
+
+  static
+  void  compute_glyph_metrics( T2_Loader*    loader,
+                               FT_UInt       glyph_index )
+  {
+    FT_UInt       num_points   = loader->base.n_points;
+    FT_UInt       num_contours = loader->base.n_contours;
+    FT_BBox       bbox;
+    T2_Face       face = loader->face;
+    FT_Fixed      x_scale, y_scale;
+    T2_GlyphSlot  glyph = loader->glyph;
+    T2_Size       size = loader->size;
+
+    /* when a simple glyph was loaded, the value of        */
+    /* "base.n_points" and "base.n_contours" is 0, we must */
+    /* take those in the "zone" instead..                  */
+    if ( num_points == 0 && num_contours == 0 )
+    {
+      num_points   = loader->zone.n_points;
+      num_contours = loader->zone.n_contours;
+    }
+
+    x_scale = 0x10000;
+    y_scale = 0x10000;
+    if ( (loader->load_flags & FT_LOAD_NO_SCALE) == 0)
+    {
+      x_scale = size->root.metrics.x_scale;
+      y_scale = size->root.metrics.y_scale;
+    }
+
+    if ( glyph->format != ft_glyph_format_composite )
+    {
+      FT_UInt  u;
+      for ( u = 0; u < num_points + 2; u++ )
+      {
+        glyph->outline.points[u] = loader->base.cur[u];
+        glyph->outline.tags [u] = loader->base.tags[u];
+      }
+
+      for ( u = 0; u < num_contours; u++ )
+        glyph->outline.contours[u] = loader->base.contours[u];
+
+      /* glyph->outline.second_pass = TRUE; */
+      glyph->outline.flags      &= ~ft_outline_single_pass;
+      glyph->outline.n_points    = num_points;
+      glyph->outline.n_contours  = num_contours;
+
+      /* translate array so that (0,0) is the glyph's origin */
+      translate_array( (TT_UShort)(num_points + 2),
+                       glyph->outline.points,
+                       -loader->pp1.x,
+                       0 );
+
+      FT_Outline_Get_CBox( &glyph->outline, &bbox );
+
+      if ( IS_HINTED(loader->load_flags) )
+      {
+        /* grid-fit the bounding box */
+        bbox.xMin &= -64;
+        bbox.yMin &= -64;
+        bbox.xMax  = (bbox.xMax + 63) & -64;
+        bbox.yMax  = (bbox.yMax + 63) & -64;
+      }
+    }
+    else
+      bbox = loader->bbox;
+
+    /* get the device-independent scaled horizontal metrics */
+    /* take care of fixed-pitch fonts...                    */
+    {
+      FT_Pos  left_bearing;
+      FT_Pos  advance;
+
+      left_bearing = loader->left_bearing;
+      advance      = loader->advance;
+
+     /* the flag FT_LOAD_NO_ADVANCE_CHECK was introduced to       */
+     /* correctly support DynaLab fonts, who have an incorrect    */
+     /* "advance_Width_Max" field !! It is used, to my knowledge  */
+     /* exclusively in the X-TrueType font server..               */
+     /*                                                           */
+      if ( face->postscript.isFixedPitch                        &&
+           (loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH) == 0 )
+        advance = face->horizontal.advance_Width_Max;
+
+      if ( !(loader->load_flags & FT_LOAD_NO_SCALE) )
+      {
+        left_bearing = FT_MulFix( left_bearing, x_scale );
+        advance      = FT_MulFix( advance, x_scale );
+      }
+
+      glyph->metrics2.horiBearingX = left_bearing;
+      glyph->metrics2.horiAdvance  = advance;
+    }
+
+    glyph->metrics.horiBearingX = bbox.xMin;
+    glyph->metrics.horiBearingY = bbox.yMax;
+    glyph->metrics.horiAdvance  = loader->pp2.x - loader->pp1.x;
+
+    /* Now take care of vertical metrics.  In the case where there is    */
+    /* no vertical information within the font (relatively common), make */
+    /* up some metrics by `hand'...                                      */
+
+    {
+      FT_Short   top_bearing;    /* vertical top side bearing (EM units) */
+      FT_UShort  advance_height; /* vertical advance height   (EM units) */
+
+      FT_Pos  left;     /* scaled vertical left side bearing         */
+      FT_Pos  Top;      /* scaled original vertical top side bearing */
+      FT_Pos  top;      /* scaled vertical top side bearing          */
+      FT_Pos  advance;  /* scaled vertical advance height            */
+
+
+      /* Get the unscaled `tsb' and `ah' */
+      if ( face->vertical_info                   &&
+           face->vertical.number_Of_VMetrics > 0 )
+      {
+        /* Don't assume that both the vertical header and vertical */
+        /* metrics are present in the same font :-)                */
+
+        T2_Get_Metrics( (TT_HoriHeader*)&face->vertical,
+                        glyph_index,
+                        &top_bearing,
+                        &advance_height );
+      }
+      else
+      {
+        /* Make up the distances from the horizontal header..     */
+
+        /* NOTE: The OS/2 values are the only `portable' ones,    */
+        /*       which is why we use them, when there is an       */
+        /*       OS/2 table in the font. Otherwise, we use the    */
+        /*       values defined in the horizontal header..        */
+        /*                                                        */
+        /* NOTE2: The sTypoDescender is negative, which is why    */
+        /*        we compute the baseline-to-baseline distance    */
+        /*        here with:                                      */
+        /*             ascender - descender + linegap             */
+        /*                                                        */
+        if ( face->os2.version != 0xFFFF )
+        {
+          top_bearing    = face->os2.sTypoLineGap / 2;
+          advance_height = (TT_UShort)(face->os2.sTypoAscender -
+                                       face->os2.sTypoDescender +
+                                       face->os2.sTypoLineGap);
+        }
+        else
+        {
+          top_bearing    = face->horizontal.Line_Gap / 2;
+          advance_height = (TT_UShort)(face->horizontal.Ascender  +
+                                       face->horizontal.Descender +
+                                       face->horizontal.Line_Gap);
+        }
+      }
+
+      /* We must adjust the top_bearing value from the bounding box given
+         in the glyph header to te bounding box calculated with
+         TT_Get_Outline_BBox()                                            */
+
+      /* scale the metrics */
+      if ( !(loader->load_flags & FT_LOAD_NO_SCALE) )
+      {
+        Top     = FT_MulFix( top_bearing, y_scale );
+        top     = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale )
+                    - bbox.yMax;
+        advance = FT_MulFix( advance_height, y_scale );
+      }
+      else
+      {
+        Top     = top_bearing;
+        top     = top_bearing + loader->bbox.yMax - bbox.yMax;
+        advance = advance_height;
+      }
+
+      glyph->metrics2.vertBearingY = Top;
+      glyph->metrics2.vertAdvance  = advance;
+
+      /* XXX: for now, we have no better algorithm for the lsb, but it    */
+      /*      should work fine.                                           */
+      /*                                                                  */
+      left = ( bbox.xMin - bbox.xMax ) / 2;
+
+      /* grid-fit them if necessary */
+      if ( IS_HINTED(loader->load_flags) )
+      {
+        left   &= -64;
+        top     = (top + 63) & -64;
+        advance = (advance + 32) & -64;
+      }
+
+      glyph->metrics.vertBearingX = left;
+      glyph->metrics.vertBearingY = top;
+      glyph->metrics.vertAdvance  = advance;
+    }
+
+    /* Adjust advance width to the value contained in the hdmx table. */
+    if ( !face->postscript.isFixedPitch && size &&
+         IS_HINTED(loader->load_flags) )
+    {
+      FT_Byte* widths = Get_Advance_Widths( face,
+                                   size->root.metrics.x_ppem );
+      if ( widths )
+        glyph->metrics.horiAdvance = widths[glyph_index] << 6;
+    }
+
+    /* set glyph dimensions */
+    glyph->metrics.width  = bbox.xMax - bbox.xMin;
+    glyph->metrics.height = bbox.yMax - bbox.yMin;
+  }
+
+
+
+
+
+
+
+
+
+
+
+
+  LOCAL_FUNC
+  FT_Error  TT_Load_Glyph( T2_Size       size,
+                           T2_GlyphSlot  glyph,
+                           FT_UShort     glyph_index,
+                           FT_UInt       load_flags )
+  {
+    SFNT_Interface*  sfnt;
+    T2_Face          face;
+    FT_Stream        stream;
+    FT_Memory        memory;
+    FT_Error         error;
+    T2_Loader        loader;
+    FT_GlyphZone*    zone;
+
+    face   = (TT_Face)glyph->face;
+    sfnt   = (SFNT_Interface*)face->sfnt;
+    stream = face->root.stream;
+    memory = face->root.memory;
+    error  = 0;
+
+    if ( !size || (load_flags & FT_LOAD_NO_SCALE)  ||
+                  (load_flags & FT_LOAD_NO_RECURSE ))
+    {
+      size        = NULL;
+      load_flags |= FT_LOAD_NO_SCALE   |
+                    FT_LOAD_NO_HINTING |
+                    FT_LOAD_NO_BITMAP;
+    }
+
+    glyph->num_subglyphs = 0;
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+    /*********************************************************************/
+    /* Try to load embedded bitmap if any                                */
+    if ( size && (load_flags & FT_LOAD_NO_BITMAP) == 0 && sfnt->load_sbits )
+    {
+      TT_SBit_Metrics  metrics;
+
+      error = sfnt->load_sbit_image( face,
+                                     size->root.metrics.x_ppem,
+                                     size->root.metrics.y_ppem,
+                                     glyph_index,
+                                     load_flags,
+                                     stream,
+                                     &glyph->bitmap,
+                                     &metrics );
+      if ( !error )
+      {
+        glyph->outline.n_points   = 0;
+        glyph->outline.n_contours = 0;
+
+        glyph->metrics.width  = (FT_Pos)metrics.width  << 6;
+        glyph->metrics.height = (FT_Pos)metrics.height << 6;
+
+        glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
+        glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
+        glyph->metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
+
+        glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
+        glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
+        glyph->metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
+
+        glyph->format = ft_glyph_format_bitmap;
+        return error;
+      }
+    }
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+    if ( load_flags & FT_LOAD_NO_OUTLINE )
+      return ( error ? error : TT_Err_Unavailable_Bitmap );
+
+   /* seek to the beginning of the glyph table. For Type 43 fonts       */
+   /* the table might be accessed from a Postscript stream or something */
+   /* else...                                                           */
+    error = face->goto_table( face, TTAG_glyf, stream, 0 );
+    if (error)
+    {
+      FT_ERROR(( "TT.GLoad: could not access glyph table\n" ));
+      goto Exit;
+    }
+
+    MEM_Set( &loader, 0, sizeof(loader) );
+
+    /* update the glyph zone bounds */
+    zone   = &((TT_Driver)face->root.driver)->zone;
+    error  = FT_Update_GlyphZone( zone,
+                                  face->root.max_points,
+                                  face->root.max_contours );
+    if (error)
+    {
+      FT_ERROR(( "TT.GLoad: could not update loader glyph zone\n" ));
+      goto Exit;
+    }
+    loader.base = *zone;
+
+    loader.zone.n_points   = 0;
+    loader.zone.n_contours = 0;
+
+    /* clear all outline flags, except the "owner" one */
+    glyph->outline.flags &= ft_outline_owner;
+
+    if (size && size->root.metrics.y_ppem < 24 )
+      glyph->outline.flags |= ft_outline_high_precision;
+
+    /************************************************************************/
+    /* let's initialise the rest of our loader now                          */
+    loader.left_points   = face->root.max_points;
+    loader.left_contours = face->root.max_contours;
+    loader.load_flags    = load_flags;
+
+    loader.face   = face;
+    loader.size   = size;
+    loader.glyph  = glyph;
+    loader.stream = stream;
+
+    loader.glyf_offset = FILE_Pos();
+
+    /* Main loading loop */
+    glyph->format        = ft_glyph_format_outline;
+	glyph->num_subglyphs = 0;
+    error = load_truetype_glyph( &loader, glyph_index );
+    if (!error)
+      compute_glyph_metrics( &loader, glyph_index );
+
+  Exit:
+    return error;
+  }
+
+
+
+/* END */
diff --git a/src/cff/t2gload.h b/src/cff/t2gload.h
new file mode 100644
index 0000000..012b7ac
--- /dev/null
+++ b/src/cff/t2gload.h
@@ -0,0 +1,140 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2gload.h                                                              */
+/*                                                                         */
+/*    OpenType Glyph Loader (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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef T2GLOAD_H
+#define T2GLOAD_H
+
+#include <t2objs.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+  typedef struct T2_Loader_
+  {
+    T2_Face         face;
+    T2_Size         size;
+    T2_GlyphSlot    glyph;
+
+    FT_ULong        load_flags;
+    FT_UInt         glyph_index;
+
+    FT_Stream       stream;
+    FT_Int          byte_len;
+    FT_Int          left_points;
+    FT_Int          left_contours;
+
+    FT_BBox         bbox;
+    FT_Int          left_bearing;
+    FT_Int          advance;
+    FT_Bool         preserve_pps;
+    FT_Vector       pp1;
+    FT_Vector       pp2;
+
+    FT_ULong        glyf_offset;
+
+    /* the zone where we load our glyphs */
+    FT_GlyphZone    base;
+    FT_GlyphZone    zone;
+
+  } T2_Loader;
+
+
+#if 0
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T2_Get_Metrics                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns the horizontal or vertical metrics in font units for a     */
+  /*    given glyph.  The metrics are the left side bearing (resp. top     */
+  /*    side bearing) and advance width (resp. advance height).            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    header  :: A pointer to either the horizontal or vertical metrics  */
+  /*               structure.                                              */
+  /*                                                                       */
+  /*    index   :: The glyph index.                                        */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    bearing :: The bearing, either left side or top side.              */
+  /*                                                                       */
+  /*    advance :: The advance width resp. advance height.                 */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function will much probably move to another component in the  */
+  /*    near future, but I haven't decided which yet.                      */
+  /*                                                                       */
+  LOCAL_DEF
+  void  T2_Get_Metrics( TT_HoriHeader*  header,
+                        FT_UInt         index,
+                        FT_Short*       bearing,
+                        FT_UShort*      advance );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T2_Load_Glyph                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to load a single glyph within a given glyph slot,  */
+  /*    for a given size.                                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph       :: A handle to a target slot object where the glyph    */
+  /*                   will be loaded.                                     */
+  /*                                                                       */
+  /*    size        :: A handle to the source face size at which the glyph */
+  /*                   must be scaled/loaded.                              */
+  /*                                                                       */
+  /*    glyph_index :: The index of the glyph in the font file.            */
+  /*                                                                       */
+  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
+  /*                   FT_LOAD_XXX constants can be used to control the    */
+  /*                   glyph loading process (e.g., whether the outline    */
+  /*                   should be scaled, whether to load bitmaps or not,   */
+  /*                   whether to hint the outline, etc).                  */
+  /* <Output>                                                              */
+  /*    result      :: A set of bit flags indicating the type of data that */
+  /*                   was loaded in the glyph slot (outline or bitmap,    */
+  /*                   etc).                                               */
+  /*                                                                       */
+  /*                   You can set this field to 0 if you don't want this  */
+  /*                   information.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_DEF
+  FT_Error  T2_Load_Glyph( T2_Size       size,
+                           T2_GlyphSlot  glyph,
+                           FT_UShort     glyph_index,
+                           FT_UInt       load_flags );
+#endif
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* T2GLOAD_H */
+
+
+/* END */
diff --git a/src/cff/t2load.c b/src/cff/t2load.c
new file mode 100644
index 0000000..b33aae5
--- /dev/null
+++ b/src/cff/t2load.c
@@ -0,0 +1,292 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2load.h                                                               */
+/*                                                                         */
+/*    TrueType glyph data/program tables loader (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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftstream.h>
+
+#include <freetype/fterrors.h>
+#include <freetype/tttags.h>
+#include <t2load.h>
+#include <t2parse.h>
+#include <t2errors.h>
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttload
+
+ /* read a CFF offset from memory */
+  LOCAL_FUNC
+  FT_ULong  T2_Get_Offset( FT_Byte*  p,
+                           FT_Byte   off_size )
+  {
+    FT_ULong  result;
+    for ( result = 0; off_size > 0; off_size-- )
+      result = (result <<= 8) | *p++;
+    return result;
+  }
+
+
+#if 0
+ /* read a CFF offset from a stream */
+  LOCAL_FUNC
+  FT_ULong  T2_Read_Offset( FT_Byte    off_size,
+                            FT_Stream  stream )
+  {
+    FT_Byte   bytes[4];
+    FT_Byte*  p;
+    FT_ULong  result;
+
+    if (off_size > 4)
+      off_size = 4;
+
+    /* first of all, read or access the bytes - this should really go     */
+    /* in "src/base/ftstream.c", but there are great chances that it will */
+    /* never be used elsewhere, so..                                      */
+    if (stream->read)
+    {
+      p = bytes;
+      if ( stream->read( stream, stream->pos, (char*)bytes, off_size ) != off_size )
+        goto Fail;
+    }
+    else
+    {
+      p = (FT_Byte*)stream->base + stream->pos;
+      if (p+off_size-1 >= (FT_Byte*)stream->limit)
+        goto Fail;
+    }
+
+    result = 0;
+    while (off_size > 0)
+    {
+      result = (result <<= 8) | *p++;
+      off_size--;
+    }
+    stream->pos += off_size;
+    return result;
+
+  Fail:
+    FT_ERROR(( "T2_Read_Offset:" ));
+    FT_ERROR(( " invalid i/o, pos = 0x%lx, size = 0x%lx",
+               stream->pos, stream->size ));
+    return 0;
+  }
+#endif
+
+ /* return the memory address of a CFF index's element, when the index */
+ /* is already loaded in memory..                                      */
+
+  LOCAL_FUNC
+  FT_Error  T2_Access_Element( CFF_Index*   cff_index,
+                               FT_UInt      element,
+                               FT_Byte*    *pbytes,
+                               FT_ULong    *pbyte_len )
+  {
+    FT_Error  error;
+
+    if (cff_index && cff_index->bytes && element < (FT_UInt)cff_index->count)
+    {
+      FT_ULong  off1, off2;
+      FT_Byte   offsize = cff_index->off_size;
+      FT_Byte*  p       = cff_index->bytes + 3 + element*offsize;
+      FT_Byte*  limit   = cff_index->bytes + cff_index->data_offset;
+
+      /* read element offset */
+      off1 = T2_Get_Offset(p,offsize);
+
+      /* a value of 0 indicates no object !! */
+      if (off1)
+      {
+        /* compute offset of next element - skip empty elements */
+        do
+        {
+          p   += offsize;
+          off2 = T2_Get_Offset(p,offsize);
+        }
+        while (off2 == 0 && p < limit);
+
+        if (p >= limit)
+          off1 = 0;
+      }
+
+      *pbytes    = 0;
+      *pbyte_len = 0;
+      if (off1)
+      {
+        *pbytes    = cff_index->bytes + cff_index->data_offset + off1 - 1;
+        *pbyte_len = off2 - off1;
+      }
+      error = 0;
+    }
+    else
+      error = FT_Err_Invalid_Argument;
+
+    return error;
+  }
+
+
+  LOCAL_FUNC
+
+  LOCAL_FUNC
+  FT_Error  T2_Read_CFF_Index( CFF_Index*  index,
+                               FT_Stream   stream )
+  {
+    FT_Error  error;
+    FT_ULong  data_size;
+
+    MEM_Set( index, 0, sizeof(*index) );
+    index->file_offset = FILE_Pos();
+    if ( !READ_UShort( index->count ) &&
+         index->count > 0             )
+    {
+      FT_Byte*  p;
+      FT_Byte   offsize;
+
+      /* there is at least one element, read the offset size            */
+      /* then access the offset table to compute the index's total size */
+      if ( READ_Byte( offsize ) )
+        goto Exit;
+
+      index->off_size    = offsize;
+      index->data_offset = ((FT_Long)index->count + 1)*offsize;
+
+      if (ACCESS_Frame( index->data_offset ))
+        goto Exit;
+
+      /* now read element offset limit */
+      p         = (FT_Byte*)stream->cursor + index->data_offset - offsize;
+      data_size = T2_Get_Offset( p, offsize );
+
+      FORGET_Frame();
+
+      index->data_offset += 3;
+      index->total_size   = index->data_offset + data_size;
+
+      /* skip the data */
+      (void)FILE_Skip( data_size );
+    }
+  Exit:
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  T2_Load_CFF_Index( CFF_Index*  index,
+                               FT_Stream   stream )
+  {
+    FT_Error   error;
+
+    /* we begin by reading the index's data */
+    error = T2_Read_CFF_Index( index, stream );
+    if (!error && index->total_size > 0)
+    {
+      /* OK, read it from the file */
+      if ( FILE_Seek( index->file_offset )                  ||
+           EXTRACT_Frame( index->total_size, index->bytes ) )
+        goto Exit;
+
+      /* done !! */
+    }
+  Exit:
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  void  T2_Done_CFF_Index( CFF_Index*  index,
+                           FT_Stream   stream )
+  {
+    if (index->bytes)
+      RELEASE_Frame( index->bytes );
+
+    MEM_Set( index, 0, sizeof(*index) );
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  T2_Load_CFF_Font( FT_Stream   stream,
+                              CFF_Font*   font )
+  {
+    static const FT_Frame_Field  cff_header_fields[] = {
+                     FT_FRAME_START(4),
+                       FT_FRAME_BYTE( CFF_Font,  version_major ),
+                       FT_FRAME_BYTE( CFF_Font,  version_minor ),
+                       FT_FRAME_BYTE( CFF_Font,  header_size   ),
+                       FT_FRAME_BYTE( CFF_Font,  absolute_offsize ),
+                     FT_FRAME_END };
+
+    FT_Error  error;
+
+    MEM_Set( font, 0, sizeof(*font) );
+    font->stream = stream;
+    font->memory = stream->memory;
+
+    /* read CFF font header */
+    if ( READ_Fields( cff_header_fields, font ) )
+      goto Exit;
+
+    /* check format */
+    if ( font->version_major   != 1 ||
+         font->header_size      < 4 ||
+         font->absolute_offsize > 4 )
+    {
+      FT_ERROR(( "incorrect CFF font header !!\n" ));
+      error = FT_Err_Unknown_File_Format;
+      goto Exit;
+    }
+
+    /* skip the rest of the header */
+    (void)FILE_Skip( font->header_size - 4 );
+
+    /* read the name, top dict, strong and global subrs index */
+    error = T2_Load_CFF_Index( &font->name_index, stream )     ||
+            T2_Load_CFF_Index( &font->top_dict_index, stream ) ||
+            T2_Read_CFF_Index( &font->string_index, stream )   ||
+            T2_Load_CFF_Index( &font->global_subrs_index, stream );
+    if (error) goto Exit;
+
+    /* well, we don't really forget the "disable" fonts.. */
+    font->num_faces = font->name_index.count;
+
+  Exit:
+    return error;
+  }
+
+  LOCAL_FUNC
+  void  T2_Done_CFF_Font( CFF_Font*  font )
+  {
+    FT_Stream  stream = font->stream;
+
+    T2_Done_CFF_Index( &font->global_subrs_index, stream );
+    T2_Done_CFF_Index( &font->string_index, stream );
+    T2_Done_CFF_Index( &font->top_dict_index, stream );
+    T2_Done_CFF_Index( &font->name_index, stream );
+  }
+
+
+
+ /***********************************************************************/
+ /***********************************************************************/
+ /***********************************************************************/
+ /*****                                                             *****/
+ /*****      TYPE 2 TABLES DECODING..                               *****/
+ /*****                                                             *****/
+ /***********************************************************************/
+ /***********************************************************************/
+ /***********************************************************************/
+
+/* END */
diff --git a/src/cff/t2load.h b/src/cff/t2load.h
new file mode 100644
index 0000000..720f05f
--- /dev/null
+++ b/src/cff/t2load.h
@@ -0,0 +1,36 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2load.h                                                               */
+/*                                                                         */
+/*    OpenType glyph data/program tables loader (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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef T2LOAD_H
+#define T2LOAD_H
+
+#include <freetype/internal/t2types.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* T2LOAD_H */
+
+
+/* END */
diff --git a/src/cff/t2objs.c b/src/cff/t2objs.c
new file mode 100644
index 0000000..10fc38e
--- /dev/null
+++ b/src/cff/t2objs.c
@@ -0,0 +1,333 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttobjs.c                                                               */
+/*                                                                         */
+/*    Objects manager (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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/ttnameid.h>
+#include <freetype/tttags.h>
+
+#include <freetype/internal/sfnt.h>
+#include <freetype/internal/psnames.h>
+#include <t2objs.h>
+
+#include <t2load.h>
+#include <t2errors.h>
+
+/* required by tracing mode */
+#undef   FT_COMPONENT
+#define  FT_COMPONENT  trace_ttobjs
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                       GLYPH ZONE FUNCTIONS                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T2_Init_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given TrueType face object.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    resource   :: The source font resource.                            */
+  /*    face_index :: The index of the font face in the resource.          */
+  /*    face       :: The newly built face object.                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    TrueType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_DEF
+  FT_Error  T2_Init_Face( FT_Stream      stream,
+                          T2_Face        face,
+                          FT_Int         face_index,
+                          FT_Int         num_params,
+                          FT_Parameter*  params )
+  {
+    TT_Error           error;
+    FT_Driver          sfnt_driver;
+    SFNT_Interface*    sfnt;
+
+    sfnt_driver = FT_Get_Driver( face->root.driver->library, "sfnt" );
+    if (!sfnt_driver) goto Bad_Format;
+
+    sfnt = (SFNT_Interface*)(sfnt_driver->interface.format_interface);
+    if (!sfnt) goto Bad_Format;
+
+    /* create input stream from resource */
+    if ( FILE_Seek(0) )
+      goto Exit;
+
+    /* check that we have a valid TrueType file */
+    error = sfnt->init_face( stream, face, face_index, num_params, params );
+    if (error) goto Exit;
+
+    /* We must also be able to accept Mac/GX fonts, as well as OT ones */
+    if ( face->format_tag != 0x4f54544f )     /* OpenType/CFF font */
+    {
+      FT_TRACE2(( "[not a valid OpenType/CFF font]" ));
+      goto Bad_Format;
+    }
+
+    /* If we're performing a simple font format check, exit immediately */
+    if ( face_index < 0 )
+      return FT_Err_Ok;
+
+    /* Load font directory */
+    error = sfnt->load_face( stream, face, face_index, num_params, params );
+    if ( error ) goto Exit;
+
+  Exit:
+    return error;
+  Bad_Format:    
+    error = FT_Err_Unknown_File_Format;
+    goto Exit;
+  }
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T2_Done_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given face object.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A pointer to the face object to destroy.                   */
+  /*                                                                       */
+  LOCAL_DEF
+  void  T2_Done_Face( T2_Face  face )
+  {
+#if 0  
+    FT_Memory  memory = face->root.memory;
+    FT_Stream  stream = face->root.stream;
+#endif
+    SFNT_Interface*  sfnt = face->sfnt;
+
+    if (sfnt)
+      sfnt->done_face(face);
+
+    /* XXXXX: TO DO */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                           SIZE  FUNCTIONS                             */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T2_Init_Size                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a new OpenType size object.                            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size :: A handle to the size object.                               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    TrueType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_DEF
+  FT_Error  T2_Init_Size( T2_Size  size )
+  {
+    UNUSED(size);
+    return 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T2_Done_Size                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The OpenType size object finalizer.                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    size :: A handle to the target size object.                        */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  T2_Done_Size( T2_Size  size )
+  {
+    UNUSED(size);
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T2_Reset_Size                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Resets a OpenType size when resolutions and character dimensions   */
+  /*    have been changed.                                                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    size :: A handle to the target size object.                        */
+  /*                                                                       */
+  LOCAL_DEF
+  FT_Error  T2_Reset_Size( T2_Size  size )
+  {
+    T2_Face           face    = (T2_Face)size->face;
+    FT_Size_Metrics*  metrics = &size->metrics;
+    FT_Error          error   = FT_Err_Ok;
+
+    if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 )
+      return FT_Err_Invalid_Argument;
+
+    /* Compute root ascender, descender, test height, and max_advance */
+    metrics->ascender = ( FT_MulFix( face->root.ascender,
+                                     metrics->y_scale ) + 32 ) & -64;
+
+    metrics->descender = ( FT_MulFix( face->root.descender,
+                                      metrics->y_scale ) + 32 ) & -64;
+
+    metrics->height = ( FT_MulFix( face->root.height,
+                                   metrics->y_scale ) + 32 ) & -64;
+
+    metrics->max_advance = ( FT_MulFix( face->root.max_advance_width,
+                                        metrics->x_scale ) + 32 ) & -64;
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T2_Init_GlyphSlot                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The OpenType glyph slot initializer.                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    slot :: The glyph record to build.                                 */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    TrueType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  T2_Init_GlyphSlot( T2_GlyphSlot  slot )
+  {
+    /* allocate the outline space */
+    FT_Face     face    = slot->face;
+    FT_Library  library = face->driver->library;
+
+    FT_TRACE4(( "TT.Init_GlyphSlot: Creating outline maxp = %d, maxc = %d\n",
+                face->max_points, face->max_contours ));
+
+    return FT_Outline_New( library,
+                           face->max_points + 2,
+                           face->max_contours,
+                           &slot->outline );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Done_GlyphSlot                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The OpenType glyph slot finalizer.                                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    slot :: A handle to the glyph slot object.                         */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  T2_Done_GlyphSlot( T2_GlyphSlot  slot )
+  {
+    FT_Library  library = slot->face->driver->library;
+    FT_Memory   memory  = library->memory;
+
+    if (slot->flags & ft_glyph_own_bitmap)
+      FREE( slot->bitmap.buffer );
+
+    FT_Outline_Done( library, &slot->outline );
+    return;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T2_Init_Driver                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given OpenType driver object.                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target driver object.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    TrueType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  T2_Init_Driver( T2_Driver  driver )
+  {
+    FT_Memory  memory = driver->root.memory;
+    FT_Error   error;
+
+    error = FT_New_GlyphZone( memory, 0, 0, &driver->zone );
+    if (error) return error;
+
+    /* init extension registry if needed */
+#ifdef T2_CONFIG_OPTION_EXTEND_ENGINE
+    return TT_Init_Extensions( driver );
+#else
+    return FT_Err_Ok;
+#endif
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Done_Driver                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given TrueType driver.                                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target TrueType driver.                  */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  T2_Done_Driver( T2_Driver  driver )
+  {
+    /* destroy extensions registry if needed */
+#ifdef T2_CONFIG_OPTION_EXTEND_ENGINE
+    TT_Done_Extensions( driver );
+#endif
+
+    /* remove the loading glyph zone */
+    FT_Done_GlyphZone( &driver->zone );
+  }
+
+
+/* END */
diff --git a/src/cff/t2objs.h b/src/cff/t2objs.h
new file mode 100644
index 0000000..aed60fc
--- /dev/null
+++ b/src/cff/t2objs.h
@@ -0,0 +1,141 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2objs.h                                                               */
+/*                                                                         */
+/*    Objects manager (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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef T2OBJS_H
+#define T2OBJS_H
+
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/t2types.h>
+#include <t2errors.h>
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T2_Driver                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to an OpenType driver object.                             */
+  /*                                                                       */
+  typedef struct T2_DriverRec_*  T2_Driver;
+
+  typedef TT_Face  T2_Face;
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T2_Size                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to an OpenType size object.                               */
+  /*                                                                       */
+  typedef FT_Size  T2_Size;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T2_GlyphSlot                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to an OpenType glyph slot object.                         */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This is a direct typedef of FT_GlyphSlot, as there is nothing      */
+  /*    specific about the OpenType glyph slot.                            */
+  /*                                                                       */
+  typedef FT_GlyphSlot  T2_GlyphSlot;
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Subglyph transformation record.                                       */
+  /*                                                                       */
+  typedef struct  T2_Transform_
+  {
+    FT_Fixed    xx, xy;     /* transformation matrix coefficients */
+    FT_Fixed    yx, yy;
+    FT_F26Dot6  ox, oy;     /* offsets        */
+
+  } T2_Transform;
+
+
+  /***********************************************************************/
+  /*                                                                     */
+  /* TrueType driver class.                                              */
+  /*                                                                     */
+  typedef struct  T2_DriverRec_
+  {
+    FT_DriverRec    root;
+    FT_GlyphZone    zone;     /* glyph loader points zone */
+
+    void*           extension_component;
+
+  } T2_DriverRec;
+
+
+ /*************************************************************************/
+ /*  Face Funcs                                                           */
+
+  LOCAL_DEF FT_Error  T2_Init_Face( FT_Stream      stream,
+                                    T2_Face        face,
+                                    TT_Int         face_index,
+                                    TT_Int         num_params,
+                                    FT_Parameter*  params );
+
+  LOCAL_DEF void      T2_Done_Face( T2_Face  face );
+
+
+ /*************************************************************************/
+ /*  Size funcs                                                           */
+
+  LOCAL_DEF FT_Error  T2_Init_Size ( T2_Size  size );
+  LOCAL_DEF void      T2_Done_Size ( T2_Size  size );
+  LOCAL_DEF FT_Error  T2_Reset_Size( T2_Size  size );
+
+
+ /*************************************************************************/
+ /*  GlyphSlot funcs                                                      */
+
+  LOCAL_DEF FT_Error  T2_Init_GlyphSlot( T2_GlyphSlot  slot );
+  LOCAL_DEF void      T2_Done_GlyphSlot( T2_GlyphSlot  slot );
+
+
+ /*************************************************************************/
+ /*  Driver funcs                                                         */
+
+  LOCAL_DEF  FT_Error  T2_Init_Driver( T2_Driver  driver );
+  LOCAL_DEF  void      T2_Done_Driver( T2_Driver  driver );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* T2OBJS_H */
+
+
+/* END */
diff --git a/src/cff/t2parse.c b/src/cff/t2parse.c
new file mode 100644
index 0000000..7520209
--- /dev/null
+++ b/src/cff/t2parse.c
@@ -0,0 +1,514 @@
+#include <t2parse.h>
+#include <freetype/fterrors.h>
+
+#define T2_Err_Stack_Underflow   FT_Err_Invalid_Argument
+#define T2_Err_Syntax_Error      FT_Err_Invalid_Argument
+
+  enum
+  {
+    t2_kind_none = 0,
+    t2_kind_num,
+    t2_kind_fixed,
+    t2_kind_string,
+    t2_kind_bool,
+    t2_kind_delta,
+    t2_kind_callback,
+    
+    t2_kind_max  /* do not remove */
+  };
+
+
+  /* now generate handlers for the most simple fields */
+  typedef FT_Error  (*T2_Field_Reader)( T2_Parser*  parser );
+
+  typedef struct T2_Field_Handler_
+  {
+    int              kind;
+    int              code;
+    FT_UInt          offset;
+    FT_Byte          size;
+    T2_Field_Reader  reader;
+    FT_UInt          array_max;
+    FT_UInt          count_offset;
+    
+  } T2_Field_Handler;
+
+
+
+
+
+  LOCAL_FUNC
+  void  T2_Parser_Init( T2_Parser*  parser, FT_UInt code, void*  object )
+  {
+    MEM_Set(parser,0,sizeof(*parser));
+    parser->top         = parser->stack;
+    parser->object_code = code;
+    parser->object      = object;
+  }
+
+
+
+
+
+
+
+  /* reads an integer */
+  static
+  FT_Long   parse_t2_integer( FT_Byte* start,
+                              FT_Byte* limit )
+  {
+    FT_Byte* p   = start;
+    FT_Int   v   = *p++;
+    FT_Long  val = 0;
+
+    if (v == 28)
+    {
+      if ( p+2 > limit ) goto Bad;
+      val = ((FT_Long)p[0] << 8) | p[1];
+      p  += 2;
+    }
+    else if (v == 29)
+    {
+      if ( p+4 > limit ) goto Bad;
+      val = ((FT_Long)p[0] << 24) |
+            ((FT_Long)p[1] << 16) |
+            ((FT_Long)p[2] <<  8) | p[3];
+      p += 4;
+    }
+    else if (v < 247)
+    {
+      val = v - 139;
+    }
+    else if (v < 251)
+    {
+      if (p+1 > limit) goto Bad;
+      val = (v-247)*256 + p[0]+108;
+      p  ++;
+    }
+    else
+    {
+      if (p+1 > limit) goto Bad;
+      val = -(v-251)*256 - p[0]-108;
+      p  ++;
+    }
+
+  Exit:
+    return val;
+
+  Bad:
+    val = 0;
+    goto Exit;
+  }
+
+
+  /* reads a real */
+  static
+  FT_Fixed  parse_t2_real( FT_Byte*  start,
+                           FT_Byte*  limit,
+                           FT_Int    power_ten )
+  {
+    FT_Byte*  p    = start;
+    FT_Long   num, divider, result, exp;
+    FT_Int    sign = 0, exp_sign = 0;
+    FT_Byte   nib;
+    FT_Byte   phase;
+
+    result  = 0;
+    num     = 0;
+    divider = 1;
+
+    /* first of all, read the integer part */
+    phase = 4;
+    p--;
+    for (;;)
+    {
+      /* read one nibble at a time */
+      if (phase && ++p >= limit) goto Bad;
+      nib   = (p[0] >> phase) & 0xF;
+      phase = 4-phase;
+
+      if (nib == 0xE)
+        sign = 1;
+      else if (nib > 9)
+        break;
+      else
+        result = result*10 + nib;
+    }
+
+    /* read decimal part, if any */
+    if (nib == 0xa)
+      for (;;)
+      {
+        /* read one nibble at a time */
+        if (!phase && ++p >= limit) goto Bad;
+        phase = 4-phase;
+        nib   = (p[0] >> phase) & 0xF;
+
+        if (nib >= 10)
+          break;
+
+        if (divider < 10000000L)
+        {
+          num      = num*10 + nib;
+          divider *= 10;
+        }
+      }
+
+    /* read exponent, if any */
+    if (nib == 12)
+    {
+      exp_sign = 1;
+      nib      = 11;
+    }
+    if (nib == 11)
+    {
+      exp = 0;
+      for (;;)
+      {
+        /* read one nibble at a time */
+        if (!phase && ++p >= limit) goto Bad;
+        phase = 4-phase;
+        nib   = (p[0] >> phase) & 0xF;
+
+        if (nib >= 10)
+          break;
+
+        exp = exp*10 + nib;
+      }
+      if (exp_sign)
+        exp = -exp;
+
+      power_ten += exp;
+    }
+
+    /* 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;
+
+  Exit:
+    return result;
+
+  Bad:
+    result = 0;
+    goto Exit;
+  }
+
+
+  /* reads a number, either integer or real */
+  static
+  FT_Long  t2_parse_num( FT_Byte** d )
+  {
+    return ( **d == 30 ? (parse_t2_real   ( d[0], d[1], 0 ) >> 16):
+                          parse_t2_integer( d[0], d[1] ) );
+  }
+
+  /* reads a floating point number, either integer or real */
+  static
+  FT_Fixed  t2_parse_fixed( FT_Byte** d )
+  {
+    return ( **d == 30 ? parse_t2_real( d[0], d[1], 0 ) :
+                         parse_t2_integer( d[0], d[1] ) << 16 );
+  }
+
+
+
+  static
+  FT_Error  parse_font_matrix( T2_Parser*  parser )
+  {
+    CFF_Top_Dict*  dict   = (CFF_Top_Dict*)parser->object;
+    FT_Matrix*     matrix = &dict->font_matrix;
+    FT_Byte**      data   = parser->stack;
+    FT_Error       error;
+
+    error = T2_Err_Stack_Underflow;
+    if (parser->top >= parser->stack + 4)
+    {
+      matrix->xx = t2_parse_fixed( data++ );
+      matrix->yx = t2_parse_fixed( data++ );
+      matrix->xy = t2_parse_fixed( data++ );
+      matrix->yy = t2_parse_fixed( data   );
+      error = 0;
+    }
+    return error;
+  }
+
+
+  static
+  FT_Error  parse_font_bbox( T2_Parser*  parser )
+  {
+    CFF_Top_Dict*  dict   = (CFF_Top_Dict*)parser->object;
+    FT_BBox*       bbox   = &dict->font_bbox;
+    FT_Byte**      data   = parser->stack;
+    FT_Error       error;
+
+    error = T2_Err_Stack_Underflow;
+    if (parser->top >= parser->stack + 4)
+    {
+      bbox->xMin = t2_parse_fixed( data++ );
+      bbox->yMin = t2_parse_fixed( data++ );
+      bbox->xMax = t2_parse_fixed( data++ );
+      bbox->yMax = t2_parse_fixed( data   );
+      error = 0;
+    }
+    return error;
+  }
+
+
+  static
+  FT_Error  parse_private_dict( T2_Parser*  parser )
+  {
+    CFF_Top_Dict*  dict   = (CFF_Top_Dict*)parser->object;
+    FT_Byte**      data   = parser->stack;
+    FT_Error       error;
+
+    error = T2_Err_Stack_Underflow;
+    if (parser->top >= parser->stack + 2)
+    {
+      dict->private_offset = t2_parse_num( data++ );
+      dict->private_size   = t2_parse_num( data );
+      error = 0;
+    }
+    return error;
+  }
+
+
+  static
+  FT_Error  parse_cid_ros( T2_Parser*  parser )
+  {
+    CFF_Top_Dict*  dict   = (CFF_Top_Dict*)parser->object;
+    FT_Byte**      data   = parser->stack;
+    FT_Error       error;
+
+    error = T2_Err_Stack_Underflow;
+    if (parser->top >= parser->stack + 3)
+    {
+      dict->cid_registry   = (FT_UInt)t2_parse_num( data++ );
+      dict->cid_ordering   = (FT_UInt)t2_parse_num( data++ );
+      dict->cid_supplement = (FT_ULong)t2_parse_num( data );
+      error = 0;
+    }
+    return error;
+  }
+
+
+
+#define T2_FIELD_NUM(code,name)        T2_FIELD( code, name, t2_kind_num )
+#define T2_FIELD_FIXED(code,name)      T2_FIELD( code, name, t2_kind_fixed )
+#define T2_FIELD_STRING(code,name)     T2_FIELD( code, name, t2_kind_string )
+#define T2_FIELD_BOOL(code,name)       T2_FIELD( code, name, t2_kind_bool )
+#define T2_FIELD_DELTA(code,name,max)  T2_FIELD( code, name, t2_kind_delta )
+
+
+#define T2_REF(s,f)   (((s*)0)->f)
+
+#define T2_FIELD_CALLBACK( code, name ) \
+     { t2_kind_callback, code, 0, 0, parse_ ## name, 0, 0 },
+     
+#undef  T2_FIELD
+#define T2_FIELD( code, name, kind )           \
+    { kind, code | T2CODE,                     \
+      (FT_UInt)(char*)&T2_REF( T2TYPE, name ), \
+      sizeof( T2_REF( T2TYPE, name ) ),        \
+      0 },
+
+#undef T2_FIELD_DELTA
+#define T2_FIELD_DELTA( code, name, max )                     \
+    { t2_kind_delta, code | T2CODE,                           \
+      (FT_UInt)(char*)&T2_REF( T2TYPE, name ),                \
+      sizeof( T2_REF( T2TYPE, name ) ),                       \
+      0,                                                      \
+      max, (FT_UInt)(char*)&T2_REF( T2TYPE, num_ ## name ) },
+
+
+#define T2CODE_TOPDICT  0x1000
+#define T2CODE_PRIVATE  0x2000
+
+  static const T2_Field_Handler  t2_field_handlers[] =
+  {
+    #include <t2tokens.h>
+    { 0, 0, 0, 0, 0, 0, 0 }
+  };
+
+
+  LOCAL_FUNC
+  FT_Error  T2_Parser_Run( T2_Parser*  parser,
+                           FT_Byte*    start,
+                           FT_Byte*    limit )
+  {
+    FT_Byte*  p;
+    FT_Error  error = 0;
+    
+    parser->top    = parser->stack;
+    parser->start  = start;
+    parser->limit  = limit;
+    parser->cursor = start;
+    
+    while (p < limit)
+    {
+      FT_Byte  v = *p;
+      if ( v >= 27 || v != 31 )
+      {
+        /* its a number, we'll push its position on the stack */
+        if (parser->top - parser->stack >= T2_MAX_STACK_DEPTH)
+          goto Stack_Overflow;
+
+        *parser->top ++ = p;
+        
+        /* now, skip it */
+        if (v == 30)
+        {
+          /* skip real number */
+          for (;;)
+          {
+            if (p >= limit) goto Syntax_Error;
+            v = p[0] >> 4;
+            if (v == 15) break;
+            v = p[0] & 0xF;
+            if (v == 15) break;
+            p++;
+          }
+          p++;
+        }
+        else if (v == 28) 
+          p += 2;
+        else if (v == 29)
+          p += 4;
+        else if (v > 246)
+          p += 1;
+      }
+      else
+      {
+        /* this is not a number, hence it's an operator. Compute its code */
+        /* and look for it in our current list..                          */
+        FT_UInt                  code;
+        FT_Int                   num_args = parser->top - parser->stack;
+        const T2_Field_Handler*  field;
+
+        /* first of all, a trivial check */
+        if ( num_args < 1 ) goto Stack_Underflow;
+
+        code = v;
+        if (v == 12)
+        {
+          /* two byte operator */
+          p++;
+          code = 0x100 | p[0];
+        }
+        code = code | parser->object_code;
+        
+        for ( field = t2_field_handlers; field->kind; field++ )
+        {
+          if (field->code == code)
+          {
+            /* we found our field's handler, read it.. */
+            FT_Long  val;
+            FT_Byte* q = (FT_Byte*)parser->object + field->offset;
+            
+            switch (field->kind)
+            {
+              case t2_kind_bool:
+              case t2_kind_string:
+              case t2_kind_num:
+                       val = t2_parse_num( parser->stack );
+                       goto Store_Number;
+                       
+              case t2_kind_fixed:
+                       val = t2_parse_fixed( parser->stack );
+                       
+                 Store_Number:                       
+                       switch (field->size)
+                       {
+                         case 1: *(FT_Byte*) q = (FT_Byte)val; break;
+                         case 2: *(FT_Short*)q = (FT_Short)val; break;
+                         default: *(FT_Long*)q = val;
+                       }
+                       break;
+              
+              
+              case t2_kind_delta:
+                       {
+                         FT_Byte*  qcount = (FT_Byte*)parser->object +
+                                                field->count_offset;
+
+                         FT_Long   val;
+                         FT_Byte** data = parser->stack;
+                                                
+                         if (num_args > field->array_max)
+                           num_args = field->array_max;
+                         
+                         /* store count */
+                         *qcount = (FT_Byte)num_args;
+                         
+                         val = 0;
+                         while (num_args > 0)
+                         {
+                           val += t2_parse_num( data++ );
+                           switch (field->size)
+                           {
+                             case 1: *(FT_Byte*) q = (FT_Byte)val; break;
+                             case 2: *(FT_Short*)q = (FT_Short)val; break;
+                             default: *(FT_Long*)q = val; 
+                           }
+                           q += field->size;
+                           num_args--;
+                         }
+                       }
+                       break;
+              
+              default:  /* callback */
+                  error = field->reader( parser );
+                  if (error) goto Exit;
+            }
+            /* clear stack */
+            parser->top = parser->stack;
+          }
+          goto Found;  /* exit loop */
+        }
+
+        /* this is an unknown operator, or it is unsupported, we will ignore */
+        /* it for now...                                                     */
+        
+      Found:
+        /* clear stack */
+        parser->top = parser->stack;
+      }
+      p++;
+    }
+  Exit:
+    return error;
+    
+  Stack_Overflow:
+    error = FT_Err_Invalid_Argument;
+    goto Exit;
+    
+  Stack_Underflow:
+    error = FT_Err_Invalid_Argument;
+    goto Exit;
+    
+  Syntax_Error:
+    error = FT_Err_Invalid_Argument;
+    goto Exit;
+    
+  }                           
+
+
+
+
+
diff --git a/src/cff/t2parse.h b/src/cff/t2parse.h
new file mode 100644
index 0000000..75aa48e
--- /dev/null
+++ b/src/cff/t2parse.h
@@ -0,0 +1,33 @@
+#ifndef T2PARSE_H
+#define T2PARSE_H
+
+#include <freetype/internal/t2types.h>
+#include <freetype/internal/ftobjs.h>
+
+#define T2_MAX_STACK_DEPTH  96
+
+  typedef struct T2_Parser_
+  {
+    FT_Byte*   start;
+    FT_Byte*   limit;
+    FT_Byte*   cursor;
+    
+    FT_Byte*   stack[ T2_MAX_STACK_DEPTH+1 ];
+    FT_Byte**  top;
+    
+    FT_UInt    object_code;
+    void*      object;
+    
+  } T2_Parser;
+
+
+  LOCAL_DEF
+  void  T2_Parser_Init( T2_Parser*  parser, FT_UInt code, void*  object );
+
+
+  LOCAL_DEF
+  FT_Error  T2_Parser_Run( T2_Parser*  parser,
+                           FT_Byte*    start,
+                           FT_Byte*    limit );
+
+#endif /* T2PARSE_H */
diff --git a/src/cff/t2tokens.h b/src/cff/t2tokens.h
new file mode 100644
index 0000000..878f6c5
--- /dev/null
+++ b/src/cff/t2tokens.h
@@ -0,0 +1,76 @@
+
+#undef  T2TYPE
+#undef  T2CODE
+#define T2TYPE  CFF_Top_Dict
+#define T2CODE  T2CODE_TOPDICT
+
+  T2_FIELD_STRING  ( 0, version )
+  T2_FIELD_STRING  ( 1, notice )
+  T2_FIELD_STRING  ( 0x100, copyright )
+  T2_FIELD_STRING  ( 2, full_name )
+  T2_FIELD_STRING  ( 3, family_name )
+  T2_FIELD_STRING  ( 4, weight )
+  T2_FIELD_BOOL    ( 0x101, is_fixed_pitch )
+  T2_FIELD_FIXED   ( 0x102, italic_angle )
+  T2_FIELD_NUM     ( 0x103, underline_position )
+  T2_FIELD_NUM     ( 0x104, underline_thickness )
+  T2_FIELD_NUM     ( 0x105, paint_type )
+  T2_FIELD_NUM     ( 0x106, charstring_type )
+  T2_FIELD_CALLBACK( 0x107, font_matrix )
+  T2_FIELD_NUM     ( 13, unique_id )
+  T2_FIELD_CALLBACK( 5, font_bbox )
+  T2_FIELD_NUM     ( 0x108, stroke_width )
+  T2_FIELD_NUM     ( 15, charset_offset )
+  T2_FIELD_NUM     ( 16, encoding_offset )
+  T2_FIELD_NUM     ( 17, charstrings_offset )
+  T2_FIELD_CALLBACK( 18, private_dict )
+  T2_FIELD_NUM     ( 0x114, synthetic_base )
+  T2_FIELD_STRING  ( 0x115, postscript )
+  T2_FIELD_STRING  ( 0x116, base_font_name )
+
+#if 0  
+  T2_FIELD_DELTA   ( 0x117, base_font_blend, 16 )
+  T2_FIELD_CALLBACK( 0x118, multiple_master )
+  T2_FIELD_CALLBACK( 0x119, blend_axit_types )
+#endif
+
+  T2_FIELD_CALLBACK( 0x11E, cid_ros )
+  T2_FIELD_NUM     ( 0x11F, cid_font_version )
+  T2_FIELD_NUM     ( 0x120, cid_font_revision )
+  T2_FIELD_NUM     ( 0x121, cid_font_type )
+  T2_FIELD_NUM     ( 0x122, cid_count )
+  T2_FIELD_NUM     ( 0x123, cid_uid_base )
+  T2_FIELD_NUM     ( 0x124, cid_fd_array_offset )
+  T2_FIELD_NUM     ( 0x125, cid_fd_select_offset )
+  T2_FIELD_STRING  ( 0x126, cid_font_name )
+
+#if 0
+  T2_FIELD_NUM     ( 0x127, chameleon )
+#endif
+
+#undef T2TYPE
+#undef T2CODE
+#define T2TYPE  CFF_Private
+#define T2CODE  T2CODE_PRIVATE
+
+  T2_FIELD_DELTA( 6, blue_values, 14 )
+  T2_FIELD_DELTA( 7, other_blues, 10 )
+  T2_FIELD_DELTA( 8, family_blues, 14 )
+  T2_FIELD_DELTA( 9, family_other_blues, 10 )
+  T2_FIELD_FIXED( 0x109, blue_scale )
+  T2_FIELD_NUM  ( 0x10A, blue_shift )
+  T2_FIELD_NUM  ( 0x10B, blue_fuzz )
+  T2_FIELD_NUM  ( 10, standard_width )
+  T2_FIELD_NUM  ( 11, standard_height )
+  T2_FIELD_DELTA( 0x10C, snap_widths, 13 )
+  T2_FIELD_DELTA( 0x10D, snap_heights, 13 )
+  T2_FIELD_BOOL ( 0x10E, force_bold )
+  T2_FIELD_FIXED( 0x10F, force_bold_threshold )
+  T2_FIELD_NUM  ( 0x110, lenIV )
+  T2_FIELD_NUM  ( 0x111, language_group )
+  T2_FIELD_FIXED( 0x112, expansion_factor )
+  T2_FIELD_NUM  ( 0x113, initial_random_seed )
+  T2_FIELD_NUM  ( 19, local_subrs_offset )
+  T2_FIELD_NUM  ( 20, default_width )
+  T2_FIELD_NUM  ( 21, nominal_width )
+