shithub: freetype+ttf2subf

Download patch

ref: 609e28c3be484792936271dacefe9b48c378e7eb
parent: f123ab6e5f1f7c912ac2102547ab2178305d8c1d
author: David Turner <[email protected]>
date: Fri Apr 19 11:13:47 EDT 2002

* src/type1/t1gload.h, src/type1/t1gload.c: fixed incorrect
          parameter sign-ness in callback function

        * include/freetype/config/ftmodule.h,
          include/freetype/internal/fttrace.h,
          src/Jamfile, src/pfr/*:

          adding a PFR font driver to the FreeType sources. Not that it
          doesn't support embedded bitmaps or kerning tables for now..


        * include/freetype/internal/ftmemory.h: adding the FT_MEM_ZERO
          and FT_ZERO macros

        * include/freetype/internal/ftstream.h: adding the FT_NEXT_OFF3,
          FT_NEXT_UOFF3, FT_NEXT_OFF3_LE and FT_NEXT_UOFF3_LE to parse
          in-memory 24-bit integers.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2002-04-19  David Turner  <[email protected]>
+
+        * src/type1/t1gload.h, src/type1/t1gload.c: fixed incorrect
+          parameter sign-ness in callback function
+
+        * include/freetype/config/ftmodule.h,
+          include/freetype/internal/fttrace.h,
+          src/Jamfile, src/pfr/*:
+        
+          adding a PFR font driver to the FreeType sources. Not that it
+          doesn't support embedded bitmaps or kerning tables for now..
+
+
+        * include/freetype/internal/ftmemory.h: adding the FT_MEM_ZERO
+          and FT_ZERO macros
+
+        * include/freetype/internal/ftstream.h: adding the FT_NEXT_OFF3,
+          FT_NEXT_UOFF3, FT_NEXT_OFF3_LE and FT_NEXT_UOFF3_LE to parse
+          in-memory 24-bit integers.
+
+
 2002-04-18  David Turner  <[email protected]>
 
 	* src/base/ftobjs.c, builds/win32/ftdebug.c,
--- a/include/freetype/config/ftmodule.h
+++ b/include/freetype/config/ftmodule.h
@@ -10,5 +10,6 @@
 FT_USE_MODULE(ft_smooth_renderer_class)
 FT_USE_MODULE(tt_driver_class)
 FT_USE_MODULE(t1_driver_class)
+FT_USE_MODULE(pfr_driver_class)
 FT_USE_MODULE(winfnt_driver_class)
 
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -375,7 +375,7 @@
   /* By undefining this, you will only compile the code necessary to load  */
   /* TrueType glyphs without hinting.                                      */
   /*                                                                       */
-#undef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#undef  TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
 
   /*************************************************************************/
--- a/include/freetype/internal/ftmemory.h
+++ b/include/freetype/internal/ftmemory.h
@@ -178,6 +178,9 @@
 
 #define FT_MEM_MOVE( dest, source, count )  ft_memmove( dest, source, count )
 
+#define FT_MEM_ZERO( dest, count )     FT_MEM_SET( dest, 0, count )
+
+#define FT_ZERO(p)    FT_MEM_ZERO( p, sizeof(*(p)) )
 
   /*************************************************************************/
   /*                                                                       */
--- a/include/freetype/internal/ftstream.h
+++ b/include/freetype/internal/ftstream.h
@@ -120,6 +120,8 @@
 #define FT_FRAME_ULONG( f )      FT_FRAME_FIELD( ft_frame_ulong_be, f )
 #define FT_FRAME_SHORT( f )      FT_FRAME_FIELD( ft_frame_short_be, f )
 #define FT_FRAME_USHORT( f )     FT_FRAME_FIELD( ft_frame_ushort_be, f )
+#define FT_FRAME_OFF3( f )       FT_FRAME_FIELD( ft_frame_off3_be, f )
+#define FT_FRAME_UOFF3( f )      FT_FRAME_FIELD( ft_frame_uoff3_be, f )
 #define FT_FRAME_BYTE( f )       FT_FRAME_FIELD( ft_frame_byte, f )
 #define FT_FRAME_CHAR( f )       FT_FRAME_FIELD( ft_frame_schar, f )
 
@@ -127,6 +129,8 @@
 #define FT_FRAME_ULONG_LE( f )   FT_FRAME_FIELD( ft_frame_ulong_le, f )
 #define FT_FRAME_SHORT_LE( f )   FT_FRAME_FIELD( ft_frame_short_le, f )
 #define FT_FRAME_USHORT_LE( f )  FT_FRAME_FIELD( ft_frame_ushort_le, f )
+#define FT_FRAME_OFF3_LE( f )    FT_FRAME_FIELD( ft_frame_off3_le, f )
+#define FT_FRAME_UOFF3_LE( f )   FT_FRAME_FIELD( ft_frame_uoff3_le, f )
 
 #define FT_FRAME_SKIP_LONG       { ft_frame_long_be, 0, 0 }
 #define FT_FRAME_SKIP_SHORT      { ft_frame_short_be, 0, 0 }
--- a/include/freetype/internal/fttrace.h
+++ b/include/freetype/internal/fttrace.h
@@ -92,5 +92,7 @@
 FT_TRACE_DEF( pcfdriver )
 FT_TRACE_DEF( pcfread )
 
+/* PFR fonts component */
+FT_TRACE_DEF( pfr )
 
 /* END */
--- a/src/Jamfile
+++ b/src/Jamfile
@@ -21,6 +21,7 @@
 SubInclude  FT2_TOP src cff ;
 SubInclude  FT2_TOP src cid ;
 SubInclude  FT2_TOP src pcf ;
+SubInclude  FT2_TOP src pfr ;
 SubInclude  FT2_TOP src psaux ;
 SubInclude  FT2_TOP src psnames ;
 SubInclude  FT2_TOP src raster ;
--- /dev/null
+++ b/src/pfr/Jamfile
@@ -1,0 +1,23 @@
+# FreeType 2 src/pfr Jamfile (c) 2002 David Turner
+#
+
+SubDir  FT2_TOP src pfr ;
+
+SubDirHdrs  [ FT2_SubDir  src pfr ] ;
+
+{
+  local  _sources ;
+
+  if $(FT2_MULTI)
+  {
+    _sources = pfrdrivr  pfrgload  pfrload  pfrobjs pfrcmap ;
+  }
+  else
+  {
+    _sources = pfr ;
+  }
+
+  Library  $(FT2_LIB) : $(_sources).c ;
+}
+
+# end of src/pfr Jamfile
--- /dev/null
+++ b/src/pfr/descrip.mms
@@ -1,0 +1,23 @@
+#
+# FreeType 2 PFR driver compilation rules for VMS
+#
+
+
+# Copyright 1996-2002 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT.  By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+CFLAGS=$(COMP_FLAGS)$(DEBUG)/include=([--.include],[--.src.pfr])
+
+OBJS=pfr.obj
+
+all : $(OBJS)
+        library [--.lib]freetype.olb $(OBJS)
+
+# EOF
--- /dev/null
+++ b/src/pfr/module.mk
@@ -1,0 +1,22 @@
+#
+# FreeType 2 PFR module definition
+#
+
+
+# Copyright 1996-2002 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT.  By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+make_module_list: add_pfr_driver
+
+add_pfr_driver:
+	$(OPEN_DRIVER)pfr_driver_class$(CLOSE_DRIVER)
+	$(ECHO_DRIVER)pfr       $(ECHO_DRIVER_DESC)PFR/TrueDoc font files with extension *.pfr$(ECHO_DRIVER_DONE)
+
+# EOF
--- /dev/null
+++ b/src/pfr/pfr.c
@@ -1,0 +1,28 @@
+/***************************************************************************/
+/*                                                                         */
+/*  pfr.c                                                                  */
+/*                                                                         */
+/*    FreeType PFR driver component                                        */
+/*                                                                         */
+/*  Copyright 1996-2002 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+
+#include "pfrload.c"
+#include "pfrgload.c"
+#include "pfrcmap.c"
+#include "pfrobjs.c"
+#include "pfrdrivr.c"
+
+/* END */
--- /dev/null
+++ b/src/pfr/pfrcmap.c
@@ -1,0 +1,129 @@
+#include "pfrcmap.h" 
+#include "pfrobjs.h"
+#include FT_INTERNAL_DEBUG_H
+
+  FT_CALLBACK_DEF( FT_Error )
+  pfr_cmap_init( PFR_CMap  cmap )
+  {
+    PFR_Face  face = (PFR_Face)FT_CMAP_FACE(cmap);
+
+
+    cmap->num_chars = face->phy_font.num_chars;
+    cmap->chars     = face->phy_font.chars;
+    
+    /* just for safety, check that the character entries are correctly */
+    /* sorted in increasing character code order..                     */
+    {
+      FT_UInt  n;
+      
+      for ( n = 1; n < cmap->num_chars; n++ )
+      {
+        if ( cmap->chars[n-1].char_code >= cmap->chars[n].char_code )
+          FT_ASSERT(0);
+      }
+    }
+    
+    return 0;
+  }
+
+
+  FT_CALLBACK_DEF( void )
+  pfr_cmap_done( PFR_CMap  cmap )
+  {
+    cmap->chars     = NULL;
+    cmap->num_chars = 0;
+  }
+
+
+  FT_CALLBACK_DEF( FT_UInt )
+  pfr_cmap_char_index( PFR_CMap   cmap,
+                       FT_UInt32  char_code )
+  {
+    FT_UInt   min = 0;
+    FT_UInt   max = cmap->num_chars;
+    FT_UInt   mid;
+    PFR_Char  gchar;
+
+
+    while ( min < max )
+    {
+      mid   = min + ( max - min ) / 2;
+      gchar = cmap->chars + mid;
+
+      if ( gchar->char_code == char_code )
+        return mid;
+
+      if ( gchar->char_code < char_code )
+        min = mid + 1;
+      else
+        max = mid;
+    }
+    return 0;
+  }
+
+
+  FT_CALLBACK_DEF( FT_UInt )
+  pfr_cmap_char_next( PFR_CMap   cmap,
+                      FT_UInt32 *pchar_code )
+  {
+    FT_UInt    result    = 0;
+    FT_UInt32  char_code = *pchar_code + 1;
+
+
+  Restart:
+    {
+      FT_UInt   min = 0;
+      FT_UInt   max = cmap->num_chars;
+      FT_UInt   mid;
+      PFR_Char  gchar;
+
+
+      while ( min < max )
+      {
+        mid   = min + ( ( max - min ) >> 1 );
+        gchar = cmap->chars + mid;
+
+        if ( gchar->char_code == char_code )
+        {
+          result = mid;
+          if ( result != 0 )
+            goto Exit;
+
+          char_code++;
+          goto Restart;
+        }
+
+        if ( gchar->char_code < char_code )
+          min = mid+1;
+        else
+          max = mid;
+      }
+
+      /* we didn't find it, but we have a pair just above it */
+      char_code = 0;
+
+      if ( min < cmap->num_chars )
+      {
+        gchar  = cmap->chars + min;
+        result = min;
+        if ( result != 0 )
+          char_code = gchar->char_code;
+      }
+    }
+
+  Exit:
+    *pchar_code = char_code;
+    return result;
+  }
+
+
+  FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
+  pfr_cmap_class_rec =
+  {
+    sizeof ( PFR_CMapRec ),
+
+    (FT_CMap_InitFunc)      pfr_cmap_init,
+    (FT_CMap_DoneFunc)      pfr_cmap_done,
+    (FT_CMap_CharIndexFunc) pfr_cmap_char_index,
+    (FT_CMap_CharNextFunc)  pfr_cmap_char_next
+  };
--- /dev/null
+++ b/src/pfr/pfrcmap.h
@@ -1,0 +1,23 @@
+#ifndef __PFR_CMAP_H__
+#define __PFR_CMAP_H__
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include "pfrtypes.h"
+
+FT_BEGIN_HEADER
+
+  typedef struct PFR_CMapRec_
+  {
+    FT_CMapRec  cmap;
+    FT_UInt     num_chars;
+    PFR_Char    chars;
+  
+  } PFR_CMapRec, *PFR_CMap;
+
+
+  FT_CALLBACK_TABLE const FT_CMap_ClassRec    pfr_cmap_class_rec;
+
+FT_END_HEADER
+
+#endif /* __PFR_CMAP_H__ */
--- /dev/null
+++ b/src/pfr/pfrdrivr.c
@@ -1,0 +1,52 @@
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include "pfrdrivr.h"
+#include "pfrobjs.h"
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_Driver_ClassRec  pfr_driver_class =
+  {
+    {
+      ft_module_font_driver      |
+      ft_module_driver_scalable,
+
+      sizeof( FT_DriverRec ),
+
+      "pfr",
+      0x10000L,
+      0x20000L,
+
+      0,   /* format interface */
+
+      (FT_Module_Constructor) NULL,
+      (FT_Module_Destructor)  NULL,
+      (FT_Module_Requester)   NULL
+    },
+
+    sizeof( PFR_FaceRec ),
+    sizeof( PFR_SizeRec ),
+    sizeof( PFR_SlotRec ),
+
+    (FT_Face_InitFunc)         pfr_face_init,
+    (FT_Face_DoneFunc)         pfr_face_done,
+    (FT_Size_InitFunc)         NULL,
+    (FT_Size_DoneFunc)         NULL,
+    (FT_Slot_InitFunc)         pfr_slot_init,
+    (FT_Slot_DoneFunc)         pfr_slot_done,
+
+    (FT_Size_ResetPointsFunc)  NULL,
+    (FT_Size_ResetPixelsFunc)  NULL,
+    (FT_Slot_LoadFunc)         pfr_slot_load,
+    (FT_CharMap_CharIndexFunc) NULL,
+
+    (FT_Face_GetKerningFunc)   0,
+    (FT_Face_AttachFunc)       0,
+    (FT_Face_GetAdvancesFunc)  0,
+
+    (FT_CharMap_CharNextFunc)  NULL
+  };
+
+
+
--- /dev/null
+++ b/src/pfr/pfrdrivr.h
@@ -1,0 +1,38 @@
+/***************************************************************************/
+/*                                                                         */
+/*  pfrdrivr.h                                                             */
+/*                                                                         */
+/*    High-level Type PFR driver interface                                 */
+/*                                                                         */
+/*  Copyright 1996-2002 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __PFR_DRIVER_H__
+#define __PFR_DRIVER_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_EXPORT_VAR( const FT_Driver_ClassRec )  pfr_driver_class;
+
+
+FT_END_HEADER
+
+#endif /* __PFR_DRIVER_H__ */
+
+
+/* END */
--- /dev/null
+++ b/src/pfr/pfrgload.c
@@ -1,0 +1,751 @@
+#include "pfrgload.h"
+#include "pfrload.h"  /* for macro definitions */
+#include FT_INTERNAL_DEBUG_H
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_pfr
+
+ /**************************************************************************/
+ /**************************************************************************/
+ /*****                                                                *****/
+ /*****                      PFR GLYPH BUILDER                         *****/
+ /*****                                                                *****/
+ /**************************************************************************/
+ /**************************************************************************/
+
+
+  FT_LOCAL_DEF( void )
+  pfr_glyph_init( PFR_Glyph       glyph,
+                  FT_GlyphLoader  loader )
+  {
+    FT_ZERO( glyph );
+
+    glyph->loader     = loader;
+    glyph->path_begun = 0;
+
+    FT_GlyphLoader_Rewind( loader );
+  }
+
+
+  FT_LOCAL_DEF( void )
+  pfr_glyph_done( PFR_Glyph  glyph )
+  {
+    FT_Memory  memory = glyph->loader->memory;
+
+    FT_FREE( glyph->x_control );
+    glyph->y_control = NULL;
+
+    glyph->max_xy_control = 0;
+    glyph->num_x_control  = 0;
+    glyph->num_y_control  = 0;
+
+    FT_FREE( glyph->subs );
+
+    glyph->max_subs = 0;
+    glyph->num_subs = 0;
+
+    glyph->loader     = NULL;
+    glyph->path_begun = 0;
+  }
+
+
+ /* close current contour, if any */
+  static void
+  pfr_glyph_close_contour( PFR_Glyph  glyph )
+  {
+    FT_GlyphLoader  loader  = glyph->loader;
+    FT_Outline*     outline = &loader->current.outline;
+    FT_Int          last, first;
+
+    if ( !glyph->path_begun )
+      return;
+
+    /* compute first and last point indices in current glyph outline */
+    last  = outline->n_points - 1;
+    first = 0;
+    if ( outline->n_contours > 0 )
+      first = outline->contours[ outline->n_contours-1 ];
+
+    /* if the last point falls on the same location than the first one */
+    /* we need to delete it                                            */
+    if ( last > first )
+    {
+      FT_Vector*  p1 = outline->points + first;
+      FT_Vector*  p2 = outline->points + last;
+
+      if ( p1->x == p2->x && p1->y == p2->y )
+      {
+        outline->n_points--;
+        last--;
+      }
+    }
+
+    /* don't add empty contours */
+    if ( last >= first )
+      outline->contours[ outline->n_contours++ ] = (short) last;
+
+    glyph->path_begun = 0;
+  }
+
+
+
+ /* reset glyph to start the loading of a new glyph */
+  static void
+  pfr_glyph_start( PFR_Glyph  glyph )
+  {
+    glyph->path_begun = 0;
+  }
+
+
+  static FT_Error
+  pfr_glyph_line_to( PFR_Glyph   glyph,
+                     FT_Vector*  to )
+  {
+    FT_GlyphLoader  loader  = glyph->loader;
+    FT_Outline*     outline = &loader->current.outline;
+    FT_Error        error;
+
+    /* check that we've begun a new path */
+    FT_ASSERT( glyph->path_begun != 0 );
+
+    error = FT_GlyphLoader_CheckPoints( loader, 1, 0 );
+    if ( !error )
+    {
+      FT_UInt  n = outline->n_points;
+
+      outline->points[n] = *to;
+      outline->tags  [n] = FT_Curve_Tag_On;
+
+      outline->n_points++;
+    }
+
+    return error;
+  }
+
+
+  static FT_Error
+  pfr_glyph_curve_to( PFR_Glyph   glyph,
+                      FT_Vector*  control1,
+                      FT_Vector*  control2,
+                      FT_Vector*  to )
+  {
+    FT_GlyphLoader  loader  = glyph->loader;
+    FT_Outline*     outline = &loader->current.outline;
+    FT_Error        error;
+
+    /* check that we've begun a new path */
+    FT_ASSERT( glyph->path_begun != 0 );
+
+    error = FT_GlyphLoader_CheckPoints( loader, 3, 0 );
+    if ( !error )
+    {
+      FT_Vector*  vec = outline->points + outline->n_points;
+      FT_Byte*    tag = (FT_Byte*)outline->tags   + outline->n_points;
+
+      vec[0] = *control1;
+      vec[1] = *control2;
+      vec[2] = *to;
+      tag[0] = FT_Curve_Tag_Cubic;
+      tag[1] = FT_Curve_Tag_Cubic;
+      tag[2] = FT_Curve_Tag_On;
+
+      outline->n_points = (FT_Short)( outline->n_points + 3 );
+    }
+
+    return error;
+  }
+
+
+  static FT_Error
+  pfr_glyph_move_to( PFR_Glyph   glyph,
+                     FT_Vector*  to )
+  {
+    FT_GlyphLoader  loader  = glyph->loader;
+    FT_Error        error;
+
+    /* close current contour if any */
+    pfr_glyph_close_contour( glyph );
+
+    /* indicate that a new contour has started */
+    glyph->path_begun = 1;
+
+    /* check that there is room for a new contour and a new point */
+    error = FT_GlyphLoader_CheckPoints( loader, 1, 1 );
+    if ( !error )
+      /* add new start point */
+      error = pfr_glyph_line_to( glyph, to );
+
+    return error;
+  }
+
+
+
+  static void
+  pfr_glyph_end( PFR_Glyph  glyph )
+  {
+    /* close current contour if any */
+    pfr_glyph_close_contour( glyph );
+
+    /* merge the current glyph into the stack */
+    FT_GlyphLoader_Add( glyph->loader );
+  }
+
+
+ /**************************************************************************/
+ /**************************************************************************/
+ /*****                                                                *****/
+ /*****                      PFR GLYPH LOADER                          *****/
+ /*****                                                                *****/
+ /**************************************************************************/
+ /**************************************************************************/
+
+ /* Load a simple glyph */
+
+  static FT_Error
+  pfr_glyph_load_simple( PFR_Glyph  glyph,
+                         FT_Byte*   p,
+                         FT_Byte*   limit )
+  {
+    FT_Error   error = 0;
+    FT_Memory  memory = glyph->loader->memory;
+    FT_UInt    flags, x_count, y_count, i, count, mask;
+    FT_Int     x;
+
+    PFR_CHECK(1);
+    flags = PFR_NEXT_BYTE(p);
+
+    /* test for composite glyphs */
+    FT_ASSERT( (flags & PFR_GLYPH_IS_COMPOUND) == 0 );
+
+    x_count = 0;
+    y_count = 0;
+
+    if ( flags & PFR_GLYPH_1BYTE_XYCOUNT )
+    {
+      PFR_CHECK(1);
+      count   = PFR_NEXT_BYTE(p);
+      x_count = (count & 15);
+      y_count = (count >> 4);
+    }
+    else
+    {
+      if ( flags & PFR_GLYPH_XCOUNT )
+      {
+        PFR_CHECK(1);
+        x_count = PFR_NEXT_BYTE(p);
+      }
+
+      if ( flags & PFR_GLYPH_YCOUNT )
+      {
+        PFR_CHECK(1);
+        y_count = PFR_NEXT_BYTE(p);
+      }
+    }
+
+    count = x_count + y_count;
+
+    /* re-allocate array when necessary */
+    if ( count > glyph->max_xy_control )
+    {
+      FT_UInt  new_max = (count+7) & -8;
+
+      if ( FT_RENEW_ARRAY( glyph->x_control, glyph->max_xy_control, new_max ) )
+        goto Exit;
+
+      glyph->max_xy_control = new_max;
+    }
+
+    glyph->y_control = glyph->x_control + x_count;
+
+    mask  = 0;
+    x     = 0;
+    for ( i = 0; i < count; i++ )
+    {
+      if ( (i & 7) == 0 )
+      {
+        PFR_CHECK(1);
+        mask = PFR_NEXT_BYTE(p);
+      }
+      
+      if ( mask & 1 )
+      {
+        PFR_CHECK(2);
+        x = PFR_NEXT_SHORT(p);
+      }
+      else
+      {
+        PFR_CHECK(1);
+        x += PFR_NEXT_BYTE(p);
+      }
+      
+      glyph->x_control[i] = x;
+
+      mask >>= 1;
+    }
+
+    /* XXXX: for now we ignore the secondary stroke and edge definitions */
+    /*       since we don't want to support native PFR hinting..         */
+    /*                                                                   */
+    if ( flags & PFR_GLYPH_EXTRA_ITEMS )
+    {
+      error = pfr_extra_items_skip( &p, limit );
+      if (error) goto Exit;
+    }
+
+
+    pfr_glyph_start( glyph );
+
+    /* now load a simple glyph */
+    {
+      FT_Vector   pos[4];
+      FT_Vector*  cur;
+
+      pos[0].x = pos[0].y = 0;
+      pos[3]   = pos[0];
+
+      for (;;)
+      {
+        FT_Int  format, args_format = 0, args_count, n;
+
+        /***************************************************************/
+        /*  read instruction                                           */
+        /*                                                             */
+        PFR_CHECK(1);
+        format = PFR_NEXT_BYTE(p);
+        switch (format >> 4)
+        {
+          case 0:    /* end glyph */
+            FT_TRACE6(( "- end glyph" ));
+            args_count = 0;
+            break;
+
+          case 1:    /* general line operation */
+            FT_TRACE6(( "- general line" ));
+            goto Line1;
+
+          case 4:    /* move to inside contour  */
+            FT_TRACE6(( "- move to inside" ));
+            goto Line1;
+
+          case 5:    /* move to outside contour */
+            FT_TRACE6(( "- move to outside" ));
+          Line1:
+            args_format = format & 15;
+            args_count  = 1;
+            break;
+
+          case 2:    /* horizontal line to */
+            FT_TRACE6(( "- horizontal line to cx.%d", format & 15 ));
+            pos[0].y   = pos[3].y;
+            pos[0].x   = glyph->x_control[ format & 15 ];
+            pos[3]     = pos[0];
+            args_count = 0;
+            break;
+
+          case 3:    /* vertical line to */
+            FT_TRACE6(( "- vertical line to cy.%d", format & 15 ));
+            pos[0].x   = pos[3].x;
+            pos[0].y   = glyph->y_control[ format & 15 ];
+            pos[3] = pos[0];
+            args_count = 0;
+            break;
+
+          case 6:    /* horizontal to vertical curve */
+            FT_TRACE6(( "- hv curve " ));
+            args_format  = 0xB8E;
+            args_count   = 3;
+            break;
+
+          case 7:    /* vertical to horizontal curve */
+            FT_TRACE6(( "- vh curve" ));
+            args_format = 0xE2B;
+            args_count  = 3;
+            break;
+
+          default:   /* general curve to */
+            FT_TRACE6(( "- general curve" ));
+            args_count  = 4;
+            args_format = (format & 15);
+        }
+
+        /***********************************************************/
+        /*  now read arguments                                     */
+        /*                                                         */
+        cur = pos;
+        for ( n = 0; n < args_count; n++ )
+        {
+          FT_Int  index, delta;
+
+          /* read the X argument */
+          switch ( args_format & 3 )
+          {
+            case 0:  /* 8-bit index */
+              PFR_CHECK(1);
+              index  = PFR_NEXT_BYTE(p);
+              cur->x = glyph->x_control[index];
+              FT_TRACE7(( " cx#%d", index ));
+              break;
+
+            case 1:  /* 16-bit value */
+              PFR_CHECK(2);
+              cur->x = PFR_NEXT_SHORT(p);
+              FT_TRACE7(( " x.%d", cur->x ));
+              break;
+
+            case 2:  /* 8-bit delta */
+              PFR_CHECK(1);
+              delta  = PFR_NEXT_INT8(p);
+              cur->x = pos[3].x + delta;
+              FT_TRACE7(( " dx.%d", delta ));
+              break;
+
+            default:
+              FT_TRACE7(( " |" ));
+              cur->x = pos[3].x;
+          }
+
+          /* read the Y argument */
+          switch ( (args_format >> 2) & 3 )
+          {
+            case 0:  /* 8-bit index */
+              PFR_CHECK(1);
+              index  = PFR_NEXT_BYTE(p);
+              cur->y = glyph->y_control[index];
+              FT_TRACE7(( " cy#%d", index ));
+              break;
+
+            case 1:  /* 16-bit absolute value */
+              PFR_CHECK(2);
+              cur->y = PFR_NEXT_SHORT(p);
+              FT_TRACE7(( " y.%d", cur->y ));
+              break;
+
+            case 2:  /* 8-bit delta */
+              PFR_CHECK(1);
+              delta  = PFR_NEXT_INT8(p);
+              cur->y = pos[3].y + delta;
+              FT_TRACE7(( " dy.%d", delta ));
+              break;
+
+            default:
+              FT_TRACE7(( " -" ));
+              cur->y = pos[3].y;
+          }
+
+          /* read the additional format flag for the general curve */
+          if ( n == 0 && args_count == 4 )
+          {
+            PFR_CHECK(1);
+            args_format = PFR_NEXT_BYTE(p);
+            args_count--;
+          }
+          else
+            args_format >>= 4;
+
+          /* save the previous point */
+          pos[3] = cur[0];
+          cur++;
+        }
+
+        FT_TRACE7(( "\n" ));
+
+        /***********************************************************/
+        /*  finally, execute instruction                           */
+        /*                                                         */
+        switch (format >> 4)
+        {
+          case 0:    /* end glyph => EXIT */
+            pfr_glyph_end( glyph );
+            goto Exit;
+
+          case 1:    /* line operations */
+          case 2:
+          case 3:
+            error = pfr_glyph_line_to( glyph, pos );
+            goto Test_Error;
+
+          case 4:    /* move to inside contour  */
+          case 5:    /* move to outside contour */
+            error = pfr_glyph_move_to( glyph, pos );
+            goto Test_Error;
+
+          default:   /* curve operations */
+            error = pfr_glyph_curve_to( glyph, pos, pos+1, pos+2 );
+
+          Test_Error:  /* test error condition */
+            if (error)
+              goto Exit;
+        }
+      } /* for (;;) */
+    }
+
+  Exit:
+    return error;
+
+  Too_Short:
+    error = FT_Err_Invalid_Table;
+    FT_ERROR(( "pfr_glyph_load: invalid glyph data\n" ));
+    goto Exit;
+  }
+
+
+
+ /* load a composite/compound glyph */
+
+  static FT_Error
+  pfr_glyph_load_compound( PFR_Glyph  glyph,
+                           FT_Byte*   p,
+                           FT_Byte*   limit )
+  {
+    FT_Error        error  = 0;
+    FT_GlyphLoader  loader = glyph->loader;
+    FT_Memory       memory = loader->memory;
+    PFR_SubGlyph    subglyph;
+    FT_UInt         flags, i, count, org_count;
+    FT_Int          x_pos, y_pos;
+
+    PFR_CHECK(1);
+    flags = PFR_NEXT_BYTE(p);
+
+    /* test for composite glyphs */
+    FT_ASSERT( (flags & PFR_GLYPH_IS_COMPOUND) != 0 );
+
+    count = flags & 0x3F;
+
+    /* ignore extra items when present */
+    /*                                 */
+    if ( flags & PFR_GLYPH_EXTRA_ITEMS )
+    {
+      error = pfr_extra_items_skip( &p, limit );
+      if (error) goto Exit;
+    }
+
+    /* we can't rely on the FT_GlyphLoader to load sub-glyphs, because   */
+    /* the PFR format is so damn stupid that it uses direct file offsets */
+    /* to point to the sub-glyphs (instead of glyph indices)..           */
+    /*                                                                   */
+    /* for now, we'll load the list of sub-glyphs in a different array   */
+    /* but this will prevent us from using the auto-hinter at its best   */
+    /* quality..                                                         */
+    /*                                                                   */
+    org_count = glyph->num_subs;
+
+    if ( org_count + count > glyph->max_subs )
+    {
+      FT_UInt  new_max = ( org_count + count + 3 ) & -4;
+
+      if ( FT_RENEW_ARRAY( glyph->subs, glyph->max_subs, new_max ) )
+        goto Exit;
+
+      glyph->max_subs = new_max;
+    }
+
+    subglyph = glyph->subs + org_count;
+    x_pos    = 0;
+    y_pos    = 0;
+
+    for ( i = 0; i < count; i++, subglyph++ )
+    {
+      FT_UInt  format;
+
+      PFR_CHECK(1);
+      format = PFR_NEXT_BYTE(p);
+
+      /* read scale when available */
+      subglyph->x_scale = 0x10000L;
+      if ( format & PFR_SUBGLYPH_XSCALE )
+      {
+        PFR_CHECK(2);
+        subglyph->x_scale = PFR_NEXT_SHORT(p) << 4;
+      }
+
+      subglyph->y_scale = 0x10000L;
+      if ( format & PFR_SUBGLYPH_YSCALE )
+      {
+        PFR_CHECK(2);
+        subglyph->y_scale = PFR_NEXT_SHORT(p) << 4;
+      }
+
+      /* read offset */
+      switch ( format & 3 )
+      {
+        case 1:
+          PFR_CHECK(2);
+          x_pos = PFR_NEXT_SHORT(p);
+          break;
+
+        case 2:
+          PFR_CHECK(1);
+          x_pos += PFR_NEXT_INT8(p);
+          break;
+
+        default:
+          ;
+      }
+
+      switch ( (format >> 2) & 3 )
+      {
+        case 1:
+          PFR_CHECK(2);
+          y_pos = PFR_NEXT_SHORT(p);
+          break;
+
+        case 2:
+          PFR_CHECK(1);
+          y_pos += PFR_NEXT_INT8(p);
+          break;
+
+        default:
+          ;
+      }
+      
+      subglyph->x_delta = x_pos;
+      subglyph->y_delta = y_pos;
+
+      /* read glyph position and size now */
+      if ( format & PFR_SUBGLYPH_2BYTE_SIZE )
+      {
+        PFR_CHECK(2);
+        subglyph->gps_size = PFR_NEXT_USHORT(p);
+      }
+      else
+      {
+        PFR_CHECK(1);
+        subglyph->gps_size = PFR_NEXT_BYTE(p);
+      }
+
+      if ( format & PFR_SUBGLYPH_3BYTE_OFFSET )
+      {
+        PFR_CHECK(3);
+        subglyph->gps_offset = PFR_NEXT_LONG(p);
+      }
+      else
+      {
+        PFR_CHECK(2);
+        subglyph->gps_offset = PFR_NEXT_USHORT(p);
+      }
+
+      glyph->num_subs++;
+    }
+
+
+  Exit:
+    return error;
+
+  Too_Short:
+    error = FT_Err_Invalid_Table;
+    FT_ERROR(( "pfr_glyph_load: invalid glyph data\n" ));
+    goto Exit;
+  }
+
+
+
+  static FT_Error
+  pfr_glyph_load_rec( PFR_Glyph       glyph,
+                      FT_Stream       stream,
+                      FT_ULong        gps_offset,
+                      FT_ULong        offset,
+                      FT_ULong        size )
+  {
+    FT_Error  error;
+    FT_Byte*  p;
+    FT_Byte*  limit;
+
+    if ( FT_STREAM_SEEK( gps_offset + offset ) ||
+         FT_FRAME_ENTER( size )                )
+     goto Exit;
+
+    p     = (FT_Byte*) stream->cursor;
+    limit = p + size;
+
+    if ( size > 0 && *p & PFR_GLYPH_IS_COMPOUND )
+    {
+      FT_Int          n, old_count, count;
+      FT_GlyphLoader  loader = glyph->loader;
+      FT_Outline*     base   = &loader->base.outline;
+
+
+      old_count = glyph->num_subs;
+
+      /* this is a compound glyph - load it */
+      error = pfr_glyph_load_compound( glyph, p, limit );
+
+      FT_FRAME_EXIT();
+
+      if ( error ) goto Exit;
+
+      count = glyph->num_subs - old_count;
+
+      /* now, load each individual glyph */
+      for ( n = 0; n < count; n++ )
+      {
+        FT_Int        i, old_points, num_points;
+        PFR_SubGlyph  subglyph;
+
+
+        subglyph   = glyph->subs + old_count + n;
+        old_points = base->n_points;
+
+        error = pfr_glyph_load_rec( glyph, stream, gps_offset,
+                                    subglyph->gps_offset, subglyph->gps_size );
+        if ( error )
+          goto Exit;
+
+        /* note that the 'glyph->subs' might have been re-allocated */
+        subglyph   = glyph->subs + old_count + n;
+        num_points = base->n_points - old_points;
+
+        /* translate and eventually scale the new glyph points */
+        if ( subglyph->x_scale != 0x10000L || subglyph->y_scale != 0x10000L )
+        {
+          FT_Vector*  vec = base->points + old_points;
+
+
+          for ( i = 0; i < num_points; i++, vec++ )
+          {
+            vec->x = FT_MulFix( vec->x, subglyph->x_scale ) + subglyph->x_delta;
+            vec->y = FT_MulFix( vec->y, subglyph->y_scale ) + subglyph->y_delta;
+          }
+        }
+        else
+        {
+          FT_Vector*  vec = loader->base.outline.points + old_points;
+
+
+          for ( i = 0; i < num_points; i++, vec++ )
+          {
+            vec->x += subglyph->x_delta;
+            vec->y += subglyph->y_delta;
+          }
+        }
+
+        /* proceed to next sub-glyph */
+      }
+    }
+    else
+    {
+      /* load a simple glyph */
+      error = pfr_glyph_load_simple( glyph, p, limit );
+
+      FT_FRAME_EXIT();
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  pfr_glyph_load( PFR_Glyph    glyph,
+                  FT_Stream    stream,
+                  FT_ULong     gps_offset,
+                  FT_ULong     offset,
+                  FT_ULong     size )
+  {
+    /* initialize glyph loader */
+    FT_GlyphLoader_Rewind( glyph->loader );
+
+    /* load the glyph, recursively when needed */
+    return pfr_glyph_load_rec( glyph, stream, gps_offset, offset, size );
+  }
+
--- /dev/null
+++ b/src/pfr/pfrgload.h
@@ -1,0 +1,27 @@
+#ifndef __PFR_GLYPH_LOAD_H__
+#define __PFR_GLYPH_LOAD_H__
+
+#include "pfrtypes.h"
+
+FT_BEGIN_HEADER
+
+  FT_LOCAL( void )
+  pfr_glyph_init( PFR_Glyph       glyph,
+                  FT_GlyphLoader  loader );
+
+  FT_LOCAL( void )
+  pfr_glyph_done( PFR_Glyph  glyph );
+
+
+  FT_LOCAL( FT_Error )
+  pfr_glyph_load( PFR_Glyph  glyph,
+                  FT_Stream  stream,
+                  FT_ULong   gps_offset,
+                  FT_ULong   offset,
+                  FT_ULong   size );
+
+
+FT_END_HEADER
+
+
+#endif /* __PFR_GLYPH_LOAD_H__ */
--- /dev/null
+++ b/src/pfr/pfrload.c
@@ -1,0 +1,657 @@
+#include "pfrload.h"
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_pfr
+
+  /***********************************************************************/
+  /***********************************************************************/
+  /*****                                                             *****/
+  /*****                          EXTRA ITEMS                        *****/
+  /*****                                                             *****/
+  /***********************************************************************/
+  /***********************************************************************/
+
+
+  FT_LOCAL_DEF( FT_Error )
+  pfr_extra_items_skip( FT_Byte*  *pp, FT_Byte*  limit )
+  {
+    return pfr_extra_items_parse( pp, limit, NULL, NULL );
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  pfr_extra_items_parse( FT_Byte*       *pp,
+                         FT_Byte*        limit,
+                         PFR_ExtraItem   item_list,
+                         FT_Pointer      item_data )
+  {
+    FT_Error  error = 0;
+    FT_Byte*  p     = *pp;
+    FT_UInt   num_items, item_type, item_size;
+    
+    PFR_CHECK(1);
+    num_items = PFR_NEXT_BYTE(p);
+    for ( ; num_items > 0; num_items-- )
+    {
+      PFR_CHECK(2);
+      item_size = PFR_NEXT_BYTE(p);
+      item_type = PFR_NEXT_BYTE(p);
+      
+      PFR_CHECK(item_size);
+
+      if ( item_list )
+      {      
+        PFR_ExtraItem  extra = item_list;
+        
+        for ( extra = item_list; extra->parser != NULL; extra++ )
+        {
+          if ( extra->type == item_type )
+          {
+            error = extra->parser( p, p + item_size, item_data );
+            if ( error ) goto Exit;
+            
+            break;
+          }
+        }
+      }
+      
+      p += item_size;
+    }
+
+  Exit:
+    *pp = p;
+    return error;
+    
+  Too_Short:
+    FT_ERROR(( "pfr.extra_items.skip: invalid extra items table\n" ));
+    error = FT_Err_Invalid_Table;
+    goto Exit;
+  }
+
+
+
+  /***********************************************************************/
+  /***********************************************************************/
+  /*****                                                             *****/
+  /*****                          PFR HEADER                         *****/
+  /*****                                                             *****/
+  /***********************************************************************/
+  /***********************************************************************/
+
+   static const FT_Frame_Field    pfr_header_fields[] =
+   {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  PFR_HeaderRec
+
+     FT_FRAME_START(58),
+       FT_FRAME_ULONG (signature),
+       FT_FRAME_USHORT(version),
+       FT_FRAME_USHORT(signature2),
+       FT_FRAME_USHORT(header_size),
+
+       FT_FRAME_USHORT(log_dir_size),
+       FT_FRAME_USHORT(log_dir_offset),
+
+       FT_FRAME_USHORT(log_font_max_size),
+       FT_FRAME_UOFF3 (log_font_section_size),
+       FT_FRAME_UOFF3 (log_font_section_offset),
+
+       FT_FRAME_USHORT(phy_font_max_size),
+       FT_FRAME_UOFF3 (phy_font_section_size),
+       FT_FRAME_UOFF3 (phy_font_section_offset),
+
+       FT_FRAME_USHORT(gps_max_size),
+       FT_FRAME_UOFF3 (gps_section_size),
+       FT_FRAME_UOFF3 (gps_section_offset),
+
+       FT_FRAME_BYTE  (max_blue_values),
+       FT_FRAME_BYTE  (max_x_orus),
+       FT_FRAME_BYTE  (max_y_orus),
+
+       FT_FRAME_BYTE  (phy_font_max_size_high),
+       FT_FRAME_BYTE  (color_flags),
+
+       FT_FRAME_UOFF3 (bct_max_size),
+       FT_FRAME_UOFF3 (bct_set_max_size),
+       FT_FRAME_UOFF3 (phy_bct_set_max_size),
+
+       FT_FRAME_USHORT(num_phy_fonts),
+       FT_FRAME_BYTE  (max_vert_stem_snap),
+       FT_FRAME_BYTE  (max_horz_stem_snap),
+       FT_FRAME_USHORT(max_chars),
+     FT_FRAME_END
+   };
+
+
+  FT_LOCAL_DEF( FT_Error )
+  pfr_header_load( PFR_Header  header,
+                   FT_Stream   stream )
+  {
+    FT_Error   error;
+
+    /* read header directly */
+    if ( !FT_STREAM_SEEK( 0 )                                &&
+         !FT_STREAM_READ_FIELDS( pfr_header_fields, header ) )
+    {
+      /* make a few adjustments to the header */
+      header->phy_font_max_size +=
+        (FT_UInt32)header->phy_font_max_size_high << 16;
+    }
+
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  pfr_header_check( PFR_Header  header )
+  {
+    FT_Bool  result = 1;
+
+    /* check signature and header size */
+    if ( header->signature  != 0x50465230 ||   /* "PFR0" */
+         header->version     > 4          ||
+         header->header_size < 58         ||
+         header->signature2 != 0x0d0a     )    /* CR/LF  */
+    {
+      result = 0;
+    }
+    return  result;
+  }
+
+
+  /***********************************************************************/
+  /***********************************************************************/
+  /*****                                                             *****/
+  /*****                    PFR LOGICAL FONTS                        *****/
+  /*****                                                             *****/
+  /***********************************************************************/
+  /***********************************************************************/
+
+
+  FT_LOCAL_DEF( FT_Error )
+  pfr_log_font_count( FT_Stream  stream,
+                      FT_UInt32  section_offset,
+                      FT_UInt   *acount )
+  {
+    FT_Error   error;
+    FT_UInt    count;
+    FT_UInt    result = 0;
+    
+    if ( FT_STREAM_SEEK( section_offset ) || FT_READ_USHORT(count) )
+      goto Exit;
+    
+    result = count;
+    
+  Exit:
+    *acount = result;
+    return error;
+  }                      
+
+
+  FT_LOCAL_DEF( FT_Error )
+  pfr_log_font_load( PFR_LogFont   log_font,
+                     FT_Stream     stream,
+                     FT_UInt       index,
+                     FT_UInt32     section_offset,
+                     FT_Bool       size_increment )
+  {
+    FT_UInt    num_log_fonts;
+    FT_UInt    flags;
+    FT_UInt32  offset;
+    FT_UInt32  size;
+    FT_Error   error;
+
+    if ( FT_STREAM_SEEK( section_offset ) || FT_READ_USHORT(num_log_fonts) )
+      goto Exit;
+
+    if ( index >= num_log_fonts )
+      return FT_Err_Invalid_Argument;
+
+    if ( FT_STREAM_SKIP( index*5 ) ||
+         FT_READ_USHORT(size)      ||
+         FT_READ_UOFF3 (offset)    )
+      goto Exit;
+
+    /* save logical font size and offset */
+    log_font->size   = size;
+    log_font->offset = offset;
+
+    /* now, check the rest of the table before loading it */
+    {
+      FT_Byte*  p;
+      FT_Byte*  limit;
+      FT_UInt   local;
+      
+      if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
+        goto Exit;
+
+      p     = stream->cursor;
+      limit = p + size;
+      
+      PFR_CHECK(13);
+      
+      log_font->matrix[0] = PFR_NEXT_LONG(p);
+      log_font->matrix[1] = PFR_NEXT_LONG(p);
+      log_font->matrix[2] = PFR_NEXT_LONG(p);
+      log_font->matrix[3] = PFR_NEXT_LONG(p);
+      
+      flags = PFR_NEXT_BYTE(p);
+      
+      local = 0;
+      if ( flags & PFR_LOG_STROKE )
+      {
+        local++;
+        if ( flags & PFR_LOG_2BYTE_STROKE )
+          local++;
+          
+        if ( (flags & PFR_LINE_JOIN_MASK) == PFR_LINE_JOIN_MITER )
+          local += 3;
+      }
+      if ( flags & PFR_LOG_BOLD )
+      {
+        local++;
+        if ( flags & PFR_LOG_2BYTE_BOLD )
+          local++;
+      }
+
+      PFR_CHECK(local);
+
+      if ( flags & PFR_LOG_STROKE )
+      {
+        log_font->stroke_thickness = ( flags & PFR_LOG_2BYTE_STROKE )
+                                   ? PFR_NEXT_SHORT(p)
+                                   : PFR_NEXT_BYTE(p);
+  
+        if ( (flags & PFR_LINE_JOIN_MASK) == PFR_LINE_JOIN_MITER )
+          log_font->miter_limit = PFR_NEXT_LONG(p);
+      }
+  
+      if ( flags & PFR_LOG_BOLD )
+      {
+        log_font->bold_thickness = ( flags & PFR_LOG_2BYTE_BOLD )
+                                 ? PFR_NEXT_SHORT(p)
+                                 : PFR_NEXT_BYTE(p);
+      }
+  
+      if ( flags & PFR_LOG_EXTRA_ITEMS )
+      {
+        error = pfr_extra_items_skip( &p, limit );
+        if (error) goto Fail;
+      }
+
+      PFR_CHECK(5);
+      log_font->phys_size   = PFR_NEXT_USHORT(p);
+      log_font->phys_offset = PFR_NEXT_ULONG(p);
+      if ( size_increment )
+      {
+        PFR_CHECK(1);
+        log_font->phys_size += (FT_UInt32)PFR_NEXT_BYTE(p) << 16;
+      }
+    }
+
+  Fail:
+    FT_FRAME_EXIT();
+
+  Exit:
+    return error;
+  
+  Too_Short:
+    FT_ERROR(( "pfr_log_font_load: invalid logical font table\n" ));
+    error = FT_Err_Invalid_Table;
+    goto Fail;
+  }
+
+
+  /***********************************************************************/
+  /***********************************************************************/
+  /*****                                                             *****/
+  /*****                    PFR PHYSICAL FONTS                       *****/
+  /*****                                                             *****/
+  /***********************************************************************/
+  /***********************************************************************/
+
+
+ /* load bitmap strikes lists */
+  FT_CALLBACK_DEF( FT_Error )
+  pfr_extra_item_load_bitmap_info( FT_Byte*     p,
+                                   FT_Byte*     limit,
+                                   PFR_PhyFont  phy_font )
+  {
+    FT_Memory   memory = phy_font->memory;
+    PFR_Strike  strike;
+    FT_UInt     flags0;
+    FT_UInt     n, count, size1;
+    FT_Error    error = 0;
+
+    PFR_CHECK(5);
+
+    p += 3;  /* skip bctSize */
+    flags0 = PFR_NEXT_BYTE(p);
+    count  = PFR_NEXT_BYTE(p);
+
+    /* re-allocate when needed */
+    if ( phy_font->num_strikes + count > phy_font->max_strikes )
+    {
+      FT_UInt  new_max = (phy_font->num_strikes + count + 3) & -4;
+      
+      if ( FT_RENEW_ARRAY( phy_font->strikes, phy_font->num_strikes, new_max ) )
+        goto Exit;
+        
+      phy_font->max_strikes = new_max;
+    }
+
+    size1 = 1 + 1 + 1 + 2 + 2 + 1;
+    if ( flags0 & PFR_STRIKE_2BYTE_XPPM )
+      size1++;
+
+    if ( flags0 & PFR_STRIKE_2BYTE_YPPM )
+      size1++;
+
+    if ( flags0 & PFR_STRIKE_3BYTE_SIZE )
+      size1++;
+
+    if ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
+      size1++;
+
+    if ( flags0 & PFR_STRIKE_2BYTE_COUNT )
+      size1++;
+
+    strike = phy_font->strikes + phy_font->num_strikes;
+
+    PFR_CHECK( count*size1 );
+
+    for ( n = 0; n < count; n++, strike++ )
+    {
+      strike->x_ppm       = ( flags0 & PFR_STRIKE_2BYTE_XPPM )
+                          ? PFR_NEXT_USHORT(p)
+                          : PFR_NEXT_BYTE(p);
+
+      strike->y_ppm       = ( flags0 & PFR_STRIKE_2BYTE_YPPM )
+                          ? PFR_NEXT_USHORT(p)
+                          : PFR_NEXT_BYTE(p);
+
+      strike->flags       = PFR_NEXT_BYTE(p);
+
+      strike->bct_size    = ( flags0 & PFR_STRIKE_3BYTE_SIZE )
+                          ? PFR_NEXT_ULONG(p)
+                          : PFR_NEXT_USHORT(p);
+
+      strike->bct_offset  = ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
+                          ? PFR_NEXT_ULONG(p)
+                          : PFR_NEXT_USHORT(p);
+
+      strike->num_bitmaps = ( flags0 & PFR_STRIKE_2BYTE_COUNT )
+                          ? PFR_NEXT_USHORT(p)
+                          : PFR_NEXT_BYTE(p);
+    }
+
+    phy_font->num_strikes += count;
+    
+  Exit:
+    return error;
+    
+  Too_Short:
+    error = FT_Err_Invalid_Table;
+    FT_ERROR(( "pfr.extra_item_load: invalid bitmap info table\n" ));
+    goto Exit;
+  }                                  
+
+
+ /* load font ID, i.e. name */
+  FT_CALLBACK_DEF( FT_Error )
+  pfr_extra_item_load_font_id( FT_Byte*     p,
+                               FT_Byte*     limit,
+                               PFR_PhyFont  phy_font )
+  {
+    FT_Error   error  = 0;
+    FT_Memory  memory = phy_font->memory;
+    FT_UInt    len    = (FT_UInt)( limit - p );
+    
+    if ( phy_font->font_id != NULL )
+      goto Exit;
+    
+    if ( FT_ALLOC( phy_font->font_id, len+1 ) )
+      goto Exit;
+
+    /* copy font ID name, and terminate it for safety */
+    FT_MEM_COPY( phy_font->font_id, p, len );
+    phy_font->font_id[len] = 0;
+    
+  Exit:
+    return error;
+  }
+
+
+ /* load stem snap tables */
+  FT_CALLBACK_DEF( FT_Error )
+  pfr_extra_item_load_stem_snaps( FT_Byte*     p,
+                                  FT_Byte*     limit,
+                                  PFR_PhyFont  phy_font )
+  {
+    FT_UInt   count, num_vert, num_horz;
+    FT_Int*   snaps;
+    FT_Error  error  = 0;
+    FT_Memory memory = phy_font->memory;
+
+    if ( phy_font->vertical.stem_snaps != NULL )
+      goto Exit;
+    
+    PFR_CHECK(1);
+    count = PFR_NEXT_BYTE(p);
+    
+    num_vert = count & 15;
+    num_horz = count >> 4;
+    count    = num_vert + num_horz;
+    
+    PFR_CHECK( count*2 );
+    
+    if ( FT_NEW_ARRAY( snaps, count ) )
+      goto Exit;
+    
+    phy_font->vertical.stem_snaps = snaps;
+    phy_font->horizontal.stem_snaps = snaps + num_vert;
+    
+    for ( ; count > 0; count--, snaps++ )
+      *snaps = FT_NEXT_SHORT(p);
+    
+  Exit:
+    return error;
+  
+  Too_Short:
+    error = FT_Err_Invalid_Table;
+    FT_ERROR(( "pfr.exta_item_load: invalid stem snaps table\n" ));
+    goto Exit;
+  }                                 
+
+
+  static const PFR_ExtraItemRec   pfr_phy_font_extra_items[] =
+  {
+    { 1, (PFR_ExtraItem_ParseFunc) pfr_extra_item_load_bitmap_info },
+    { 2, (PFR_ExtraItem_ParseFunc) pfr_extra_item_load_font_id },
+    { 3, (PFR_ExtraItem_ParseFunc) pfr_extra_item_load_stem_snaps },
+    { 0, NULL }
+  };
+
+
+
+
+
+  FT_LOCAL_DEF( void )
+  pfr_phy_font_done( PFR_PhyFont  phy_font,
+                     FT_Memory    memory )
+  {
+    if ( phy_font->font_id )
+      FT_FREE( phy_font->font_id );
+
+    FT_FREE( phy_font->vertical.stem_snaps );
+    phy_font->vertical.num_stem_snaps = 0;
+
+    phy_font->horizontal.stem_snaps     = NULL;
+    phy_font->horizontal.num_stem_snaps = 0;
+
+    FT_FREE( phy_font->strikes );
+    phy_font->num_strikes = 0;
+    phy_font->max_strikes = 0;
+  
+    FT_FREE( phy_font->chars );
+    phy_font->num_chars    = 0;
+    phy_font->chars_offset = 0;
+  }
+  
+  
+
+
+
+
+  FT_LOCAL_DEF( FT_Error )
+  pfr_phy_font_load( PFR_PhyFont   phy_font,
+                     FT_Stream     stream,
+                     FT_UInt32     offset,
+                     FT_UInt32     size )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+    FT_UInt    flags, num_aux;
+    FT_Byte*   p;
+    FT_Byte*   limit;
+
+    phy_font->memory = memory;
+    phy_font->offset = offset;
+
+    if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
+      goto Exit;
+
+    p     = stream->cursor;
+    limit = p + size;
+
+    PFR_CHECK( 15 );
+    phy_font->font_ref_number    = PFR_NEXT_USHORT(p);
+    phy_font->outline_resolution = PFR_NEXT_USHORT(p);
+    phy_font->metrics_resolution = PFR_NEXT_USHORT(p);
+    phy_font->bbox.xMin          = PFR_NEXT_SHORT(p);
+    phy_font->bbox.yMin          = PFR_NEXT_SHORT(p);
+    phy_font->bbox.xMax          = PFR_NEXT_SHORT(p);
+    phy_font->bbox.yMax          = PFR_NEXT_SHORT(p);
+    phy_font->flags      = flags = PFR_NEXT_BYTE(p);
+
+    /* get the standard advance for non-proprotional fonts */
+    if ( !(flags & PFR_PHY_PROPORTIONAL) )
+    {
+      PFR_CHECK(2);
+      phy_font->standard_advance = PFR_NEXT_SHORT(p);
+    }
+
+    /* load the extra items when present */
+    if ( flags & PFR_PHY_EXTRA_ITEMS )
+    {
+      error = 
+        pfr_extra_items_parse( &p, limit, pfr_phy_font_extra_items, phy_font );
+        
+      if ( error )
+        goto Fail;
+    }
+    
+    /* skip the aux bytes */
+    PFR_CHECK(3);
+    num_aux = PFR_NEXT_ULONG(p);
+    
+    PFR_CHECK(num_aux);
+    p += num_aux;
+
+    /* read the blue values */
+    {
+      FT_UInt  n, count;
+
+      PFR_CHECK( 1 );
+      phy_font->num_blue_values = count = PFR_NEXT_BYTE(p);
+
+      PFR_CHECK( count*2 );
+      
+      if ( FT_NEW_ARRAY( phy_font->blue_values, count ) )
+        goto Fail;
+
+      for ( n = 0; n < count; n++ )
+        phy_font->blue_values[n] = PFR_NEXT_SHORT(p);
+    }
+
+    PFR_CHECK(8);
+    phy_font->blue_fuzz  = PFR_NEXT_BYTE(p);
+    phy_font->blue_scale = PFR_NEXT_BYTE(p);
+
+    phy_font->vertical.standard   = PFR_NEXT_USHORT(p);
+    phy_font->horizontal.standard = PFR_NEXT_USHORT(p);
+
+    /* read the character descriptors */
+    {
+      FT_UInt  n, count, size;
+
+      phy_font->num_chars    = count = PFR_NEXT_USHORT(p);
+      phy_font->chars_offset = offset + (p - stream->cursor);
+
+      if ( FT_NEW_ARRAY( phy_font->chars, count ) )
+        goto Fail;
+
+      size = 1 + 1 + 2;
+      if ( flags & PFR_PHY_2BYTE_CHARCODE )
+        size += 1;
+      
+      if ( flags & PFR_PHY_PROPORTIONAL )
+        size += 2;
+      
+      if ( flags & PFR_PHY_ASCII_CODE )
+        size += 1;
+        
+      if ( flags & PFR_PHY_2BYTE_GPS_SIZE )
+        size += 1;
+        
+      if ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
+        size += 1;
+      
+      PFR_CHECK( count*size );
+
+      for ( n = 0; n < count; n++ )
+      {
+          PFR_Char  cur = &phy_font->chars[n];
+
+          cur->char_code = ( flags & PFR_PHY_2BYTE_CHARCODE )
+                         ? PFR_NEXT_USHORT(p)
+                         : PFR_NEXT_BYTE(p);
+
+          cur->advance   = ( flags & PFR_PHY_PROPORTIONAL )
+                         ? PFR_NEXT_SHORT(p)
+                         : phy_font->standard_advance;
+
+#if 0
+          cur->ascii     = ( flags & PFR_PHY_ASCII_CODE )
+                         ? PFR_NEXT_BYTE(p)
+                         : 0;
+#else
+          if ( flags & PFR_PHY_ASCII_CODE )
+            p += 1;
+#endif
+          cur->gps_size  = ( flags & PFR_PHY_2BYTE_GPS_SIZE )
+                         ? PFR_NEXT_USHORT(p)
+                         : PFR_NEXT_BYTE(p);
+
+          cur->gps_offset = ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
+                          ? PFR_NEXT_ULONG(p)
+                          : PFR_NEXT_USHORT(p);
+      }
+    }
+
+    /* that's it !! */
+  Fail:
+    FT_FRAME_EXIT();
+
+  Exit:
+    return error;
+  
+  Too_Short:
+    error = FT_Err_Invalid_Table;
+    FT_ERROR(( "pfr_phy_font_load: invalid physical font table\n" ));
+    goto Fail;
+  }
+
+
--- /dev/null
+++ b/src/pfr/pfrload.h
@@ -1,0 +1,89 @@
+#ifndef __PFR_LOAD_H__
+#define __PFR_LOAD_H__
+
+#include "pfrobjs.h"
+#include FT_INTERNAL_STREAM_H
+
+FT_BEGIN_HEADER
+
+#ifdef PFR_CONFIG_NO_CHECKS
+#  define  PFR_CHECK(x)   do { } while (0)
+#else
+#  define  PFR_CHECK(x)   do { if ( p + (x) > limit ) goto Too_Short; } while (0)
+#endif
+
+#define  PFR_NEXT_BYTE(p)    FT_NEXT_BYTE(p)
+#define  PFR_NEXT_INT8(p)    FT_NEXT_CHAR(p)
+#define  PFR_NEXT_SHORT(p)   FT_NEXT_SHORT(p)
+#define  PFR_NEXT_USHORT(p)  FT_NEXT_USHORT(p)
+#define  PFR_NEXT_LONG(p)    FT_NEXT_OFF3(p)
+#define  PFR_NEXT_ULONG(p)   FT_NEXT_UOFF3(p)
+
+ /* handling extra items */
+
+  typedef FT_Error  (*PFR_ExtraItem_ParseFunc)( FT_Byte*    p,
+                                                FT_Byte*    limit,
+                                                FT_Pointer  data );
+  typedef struct PFR_ExtraItemRec_
+  {
+    FT_UInt                  type;
+    PFR_ExtraItem_ParseFunc  parser;
+  
+  } PFR_ExtraItemRec;
+  
+  typedef const struct PFR_ExtraItemRec_*  PFR_ExtraItem;
+ 
+  FT_LOCAL( FT_Error )
+  pfr_extra_items_skip( FT_Byte*  *pp, FT_Byte*  limit );
+
+  FT_LOCAL( FT_Error )
+  pfr_extra_items_parse( FT_Byte*      *pp,
+                         FT_Byte*       limit,
+                         PFR_ExtraItem  item_list,
+                         FT_Pointer     item_data );
+
+
+ /* load a PFR header */
+  FT_LOCAL( FT_Error )
+  pfr_header_load( PFR_Header  header,
+                   FT_Stream   stream );
+
+ /* check a PFR header */
+  FT_LOCAL( FT_Bool )
+  pfr_header_check( PFR_Header  header );
+
+
+
+ /* return number of logical fonts in this file */
+  FT_LOCAL( FT_Error )
+  pfr_log_font_count( FT_Stream    stream,
+                      FT_UInt32    log_section_offset,
+                      FT_UInt     *acount );
+
+
+ /* load a pfr logical font entry */
+  FT_LOCAL( FT_Error )
+  pfr_log_font_load( PFR_LogFont   log_font,
+                     FT_Stream     stream,
+                     FT_UInt       face_index,
+                     FT_UInt32     section_offset,
+                     FT_Bool       size_increment );
+
+
+ /* load a physical font entry */
+  FT_LOCAL( FT_Error )
+  pfr_phy_font_load( PFR_PhyFont   phy_font,
+                     FT_Stream     stream,
+                     FT_UInt32     offset,
+                     FT_UInt32     size );
+
+ /* finalize a physical font */
+  FT_LOCAL( void )
+  pfr_phy_font_done( PFR_PhyFont  phy_font,
+                     FT_Memory    memory );
+
+ /* */
+ 
+FT_END_HEADER
+
+#endif /* __PFR_LOAD_H__ */
--- /dev/null
+++ b/src/pfr/pfrobjs.c
@@ -1,0 +1,280 @@
+#include "pfrobjs.h"
+#include "pfrload.h"
+#include "pfrgload.h"
+#include "pfrcmap.h"
+#include FT_OUTLINE_H
+#include FT_INTERNAL_DEBUG_H
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_pfr
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*****                                                               *****/
+ /*****                     FACE OBJECT METHODS                       *****/
+ /*****                                                               *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+  FT_LOCAL_DEF( void )
+  pfr_face_done( PFR_Face   face )
+  {
+    /* finalize the physical font record */
+    pfr_phy_font_done( &face->phy_font, FT_FACE_MEMORY(face) );
+
+    /* no need to finalize the logical font or the header */
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  pfr_face_init( FT_Stream  stream,
+                 PFR_Face   face,
+                 FT_Int     face_index )
+  {
+    FT_Error  error;
+
+    /* load the header and check it */
+    error = pfr_header_load( &face->header, stream );
+    if ( error ) goto Exit;
+
+    if ( !pfr_header_check( &face->header ) )
+    {
+      FT_TRACE4(( "PFR.Face.Init: not a valid PFR font\n" ));
+      error = FT_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    /* check face index */
+    {
+      FT_UInt  num_faces;
+
+      error = pfr_log_font_count( stream,
+                                  face->header.log_dir_offset,
+                                  &num_faces );
+      if ( error ) goto Exit;
+
+      face->root.num_faces = num_faces;
+    }
+
+    if ( face_index < 0 )
+      goto Exit;
+
+    if ( face_index >= face->root.num_faces )
+    {
+      FT_ERROR(( "PFR.Face.Init: invalid face index\n" ));
+      error = FT_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    /* load the face */
+    error = pfr_log_font_load(
+               &face->log_font, stream, face_index,
+               face->header.log_dir_offset,
+               FT_BOOL( face->header.phy_font_max_size_high != 0 ) );
+    if ( error )
+      goto Exit;
+
+    /* now load the physical font descriptor */
+     error = pfr_phy_font_load( &face->phy_font, stream,
+                                 face->log_font.phys_offset,
+                                 face->log_font.phys_size );
+     if ( error )
+       goto Exit;
+
+     /* now, set-up all root face fields */
+     {
+       FT_Face      root     = FT_FACE(face);
+       PFR_PhyFont  phy_font = &face->phy_font;
+
+       root->face_index = face_index;
+       root->num_glyphs = phy_font->num_chars;
+       root->face_flags = FT_FACE_FLAG_SCALABLE;
+
+       if ( (phy_font->flags & PFR_PHY_PROPORTIONAL) == 0 )
+         root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+       if ( phy_font->flags & PFR_PHY_VERTICAL )
+         root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
+       else
+         root->face_flags |= FT_FACE_FLAG_VERTICAL;
+
+       /* XXXX: kerning and embedded bitmap support isn't there yet */
+
+       root->family_name = phy_font->font_id;
+       root->style_name  = NULL;  /* no style name in font file */
+
+       root->num_fixed_sizes = 0;
+       root->available_sizes = 0;
+
+       root->bbox         = phy_font->bbox;
+       root->units_per_EM = (FT_UShort) phy_font->outline_resolution;
+       root->ascender     = (FT_Short)  phy_font->bbox.yMax;
+       root->descender    = (FT_Short)  phy_font->bbox.yMin;
+       root->height       = (FT_Short)( ((root->ascender - root->descender)*12) / 10 );
+
+       /* now compute maximum advance width */
+       if ( (phy_font->flags & PFR_PHY_PROPORTIONAL) == 0 )
+         root->max_advance_width = (FT_Short) phy_font->standard_advance;
+       else
+       {
+         FT_Int    max = 0;
+         FT_UInt   count = phy_font->num_chars;
+         PFR_Char  gchar = phy_font->chars;
+
+         for ( ; count > 0; count--, gchar++ )
+         {
+           if ( max < gchar->advance )
+             max = gchar->advance;
+         }
+
+         root->max_advance_width = (FT_Short) max;
+       }
+
+       root->max_advance_height = root->height;
+
+       root->underline_position  = (FT_Short)( - root->units_per_EM/10 );
+       root->underline_thickness = (FT_Short)(   root->units_per_EM/30 );
+
+       /* create charmap */
+       {
+         FT_CharMapRec    charmap;
+         
+         charmap.face        = root;
+         charmap.platform_id = 3;
+         charmap.encoding_id = 1;
+         charmap.encoding    = ft_encoding_unicode;
+         
+         FT_CMap_New( &pfr_cmap_class_rec, NULL, &charmap, NULL );
+       }
+     }
+
+  Exit:
+    return error;
+  }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*****                                                               *****/
+ /*****                    SLOT OBJECT METHOD                         *****/
+ /*****                                                               *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+  FT_LOCAL_DEF( FT_Error )
+  pfr_slot_init( PFR_Slot  slot )
+  {
+    FT_GlyphLoader  loader =  slot->root.internal->loader;
+
+    pfr_glyph_init( &slot->glyph, loader );
+
+    return 0;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  pfr_slot_done( PFR_Slot  slot )
+  {
+    pfr_glyph_done( &slot->glyph );
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  pfr_slot_load( PFR_Slot  slot,
+                 PFR_Size  size,
+                 FT_UInt   gindex,
+                 FT_Int    load_flags )
+  {
+    FT_Error     error;
+    PFR_Face     face    = (PFR_Face) slot->root.face;
+    PFR_Char     gchar   = face->phy_font.chars + gindex;
+    FT_Outline*  outline = &slot->root.outline;
+    FT_ULong     gps_offset;
+
+   /* check that the glyph index is correct */
+    FT_ASSERT( gindex < face->phy_font.num_chars );
+
+    slot->root.format   = ft_glyph_format_outline;
+    outline->n_points   = 0;
+    outline->n_contours = 0;
+    gps_offset          = face->header.gps_section_offset;
+
+
+   /* load the glyph outline ( FT_LOAD_NO_RECURSE isn't supported ) */
+    error = pfr_glyph_load( &slot->glyph, face->root.stream,
+                            gps_offset, gchar->gps_offset, gchar->gps_size );
+
+    if (!error)
+    {
+      FT_BBox            cbox;
+      FT_Outline*        outline = &slot->root.outline;
+      FT_Glyph_Metrics*  metrics = &slot->root.metrics;
+      FT_Pos             advance;
+      FT_Int             em_metrics, em_outline;
+      FT_Bool            scaling;
+
+      scaling = FT_BOOL( (load_flags & FT_LOAD_NO_SCALE)  == 0 );
+
+      /* copy outline data */
+      *outline = slot->glyph.loader->base.outline;
+
+      outline->flags &= ~ft_outline_owner;
+      outline->flags |= ft_outline_reverse_fill;
+
+      if ( size && size->root.metrics.y_ppem < 24 )
+        outline->flags |= ft_outline_high_precision;
+
+      /* compute the advance vector */
+      metrics->horiAdvance = 0;
+      metrics->vertAdvance = 0;
+
+      advance    = gchar->advance;
+      em_metrics = face->phy_font.metrics_resolution;
+      em_outline = face->phy_font.outline_resolution;
+
+      if ( em_metrics != em_outline )
+        advance = FT_MulDiv( advance, em_outline, em_metrics );
+
+      if ( face->phy_font.flags & PFR_PHY_VERTICAL )
+        metrics->vertAdvance = gchar->advance;
+      else
+        metrics->horiAdvance = gchar->advance;
+
+      slot->root.linearHoriAdvance = metrics->horiAdvance;
+      slot->root.linearVertAdvance = metrics->vertAdvance;
+
+      /* make-up vertical metrics (?) */
+      metrics->vertBearingX = 0;
+      metrics->vertBearingY = 0;
+
+      /* scale when needed */
+      if ( scaling )
+      {
+        FT_Int      n;
+        FT_Fixed    x_scale = size->root.metrics.x_scale;
+        FT_Fixed    y_scale = size->root.metrics.y_scale;
+        FT_Vector*  vec     = outline->points;
+
+        /* scale outline points */
+        for ( n = 0; n < outline->n_points; n++, vec++ )
+        {
+          vec->x = FT_MulFix( vec->x, x_scale );
+          vec->y = FT_MulFix( vec->y, y_scale );
+        }
+
+        /* scale the advance */
+        metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
+        metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
+      }
+
+      /* compute the rest of the metrics */
+      FT_Outline_Get_CBox( outline, &cbox );
+
+      metrics->width        = cbox.xMax - cbox.xMin;
+      metrics->height       = cbox.yMax - cbox.yMin;
+      metrics->horiBearingX = cbox.xMin;
+      metrics->horiBearingY = cbox.yMax - metrics->height;
+    }
+
+    return error;
+  }
--- /dev/null
+++ b/src/pfr/pfrobjs.h
@@ -1,0 +1,68 @@
+#ifndef __PFR_OBJS_H__
+#define __PFR_OBJS_H__
+
+#include "pfrtypes.h"
+
+FT_BEGIN_HEADER
+
+  typedef struct PFR_FaceRec_*   PFR_Face;
+  
+  typedef struct PFR_SizeRec_*   PFR_Size;
+  
+  typedef struct PFR_SlotRec_*   PFR_Slot;
+
+
+
+  typedef struct PFR_FaceRec_
+  {
+    FT_FaceRec      root;
+    PFR_HeaderRec   header;
+    PFR_LogFontRec  log_font;
+    PFR_PhyFontRec  phy_font;
+
+  } PFR_FaceRec;
+
+
+  typedef struct PFR_SizeRec_
+  {
+    FT_SizeRec   root;
+  
+  } PFR_SizeRec;
+
+
+  typedef struct PFR_SlotRec_
+  {
+    FT_GlyphSlotRec  root;
+    PFR_GlyphRec     glyph;
+    
+  } PFR_SlotRec;
+
+
+  FT_LOCAL( FT_Error )
+  pfr_face_init( FT_Stream  stream,
+                 PFR_Face   face,
+                 FT_Int     face_index );
+
+
+  FT_LOCAL( void )
+  pfr_face_done( PFR_Face  face );
+
+
+  FT_LOCAL( FT_Error )
+  pfr_slot_init( PFR_Slot  slot );
+
+
+  FT_LOCAL( void )
+  pfr_slot_done( PFR_Slot  slot );
+
+
+  FT_LOCAL( FT_Error )
+  pfr_slot_load( PFR_Slot  slot,
+                 PFR_Size  size,
+                 FT_UInt   gindex,
+                 FT_Int    load_flags );
+
+
+FT_END_HEADER
+
+#endif /* __PFR_OBJS_H__ */
--- /dev/null
+++ b/src/pfr/pfrtypes.h
@@ -1,0 +1,289 @@
+#ifndef __PFR_TYPES_H__
+#define __PFR_TYPES_H__
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+
+FT_BEGIN_HEADER
+
+ /************************************************************************/
+
+ /* the PFR Header structure */
+  typedef struct PFR_HeaderRec_
+  {
+    FT_UInt32    signature;
+    FT_UInt      version;
+    FT_UInt      signature2;
+    FT_UInt      header_size;
+
+    FT_UInt      log_dir_size;
+    FT_UInt      log_dir_offset;
+
+    FT_UInt      log_font_max_size;
+    FT_UInt32    log_font_section_size;
+    FT_UInt32    log_font_section_offset;
+
+    FT_UInt32    phy_font_max_size;
+    FT_UInt32    phy_font_section_size;
+    FT_UInt32    phy_font_section_offset;
+
+    FT_UInt      gps_max_size;
+    FT_UInt32    gps_section_size;
+    FT_UInt32    gps_section_offset;
+
+    FT_UInt      max_blue_values;
+    FT_UInt      max_x_orus;
+    FT_UInt      max_y_orus;
+    
+    FT_UInt      phy_font_max_size_high;
+    FT_UInt      color_flags;
+    
+    FT_UInt32    bct_max_size;
+    FT_UInt32    bct_set_max_size;        
+    FT_UInt32    phy_bct_set_max_size;
+    
+    FT_UInt      num_phy_fonts;
+    FT_UInt      max_vert_stem_snap;
+    FT_UInt      max_horz_stem_snap;
+    FT_UInt      max_chars;
+  
+  } PFR_HeaderRec, *PFR_Header;
+
+
+ /* used in 'color_flags' field of the PFR_Header */
+  typedef enum PFR_HeaderFlags_
+  {
+    PFR_FLAG_BLACK_PIXEL   = 1,
+    PFR_FLAG_INVERT_BITMAP = 2
+  
+  } PFR_HeaderFlags;
+
+
+ /************************************************************************/
+
+  typedef struct PFR_LogFontRec_
+  {
+    FT_UInt32  size;
+    FT_UInt32  offset;
+    
+    FT_Int32   matrix[4];
+    FT_UInt    stroke_flags;
+    FT_Int     stroke_thickness;
+    FT_Int     bold_thickness;
+    FT_Int32   miter_limit;
+    
+    FT_UInt32  phys_size;
+    FT_UInt32  phys_offset;
+  
+  } PFR_LogFontRec, *PFR_LogFont;
+
+
+  typedef enum PFR_LogFlags_
+  {
+    PFR_LOG_EXTRA_ITEMS    = 0x40,
+    PFR_LOG_2BYTE_BOLD     = 0x20,
+    PFR_LOG_BOLD           = 0x10,
+    PFR_LOG_2BYTE_STROKE   = 8,
+    PFR_LOG_STROKE         = 4,
+    PFR_LINE_JOIN_MASK     = 3
+    
+  } PFR_LogFlags;
+
+
+  typedef enum PFR_LineJoinFlags_
+  {
+    PFR_LINE_JOIN_MITER = 0,
+    PFR_LINE_JOIN_ROUND = 1,
+    PFR_LINE_JOIN_BEVEL = 2
+    
+  } PFR_LineJoinFlags;
+
+
+ /************************************************************************/
+
+  typedef enum PFR_BitmapFlags_
+  {
+    PFR_BITMAP_3BYTE_OFFSET    = 4,
+    PFR_BITMAP_2BYTE_SIZE      = 2,
+    PFR_BITMAP_2BYTE_CHARCODE  = 1
+  
+  } PFR_BitmapFlags;
+
+
+  typedef struct PFR_BitmapCharRec_
+  {
+    FT_UInt    char_code;
+    FT_UInt    gps_size;
+    FT_UInt32  gps_offset;
+  
+  } PFR_BitmapCharRec, *PFR_BitmapChar;
+
+
+  typedef enum PFR_StrikeFlags_
+  {
+    PFR_STRIKE_2BYTE_COUNT  = 0x10,
+    PFR_STRIKE_3BYTE_OFFSET = 0x08,
+    PFR_STRIKE_3BYTE_SIZE   = 0x04,
+    PFR_STRIKE_2BYTE_YPPM   = 0x02,
+    PFR_STRIKE_2BYTE_XPPM   = 0x01
+
+  } PFR_StrikeFlags;
+
+
+  typedef struct PFR_StrikeRec_
+  {
+    FT_UInt         x_ppm;
+    FT_UInt         y_ppm;
+    FT_UInt         flags;
+    
+    FT_UInt32       gps_size;
+    FT_UInt32       gps_offset;
+    
+    FT_UInt32       bct_size;
+    FT_UInt32       bct_offset;
+    
+    /* optional */
+    FT_UInt         num_bitmaps;
+    PFR_BitmapChar  bitmaps;
+    
+  } PFR_StrikeRec, *PFR_Strike;
+
+
+
+ /************************************************************************/
+
+  typedef struct PFR_CharRec_
+  {
+    FT_UInt   char_code;
+    FT_Int    advance;
+    FT_UInt   gps_size;
+    FT_UInt32 gps_offset;
+  
+  } PFR_CharRec, *PFR_Char;
+
+
+ /************************************************************************/
+
+  typedef struct PFR_DimensionRec_
+  {
+    FT_UInt   standard;
+    FT_UInt   num_stem_snaps;
+    FT_Int*   stem_snaps;
+  
+  } PFR_DimensionRec, *PFR_Dimension;
+
+
+ /************************************************************************/
+
+  typedef struct PFR_PhyFontRec_
+  {
+    FT_Memory          memory;
+    FT_UInt32          offset;
+
+    FT_UInt            font_ref_number;
+    FT_UInt            outline_resolution;
+    FT_UInt            metrics_resolution;
+    FT_BBox            bbox;
+    FT_UInt            flags;
+    FT_UInt            standard_advance;
+    
+    PFR_DimensionRec   horizontal;
+    PFR_DimensionRec   vertical;
+
+    FT_String*         font_id;
+
+    FT_UInt            num_strikes;
+    FT_UInt            max_strikes;
+    PFR_StrikeRec*     strikes;
+    
+    FT_UInt            num_blue_values;
+    FT_Int            *blue_values;
+    FT_UInt            blue_fuzz;
+    FT_UInt            blue_scale;
+    
+    FT_UInt            num_chars;
+    FT_UInt32          chars_offset;
+    PFR_Char           chars;
+  
+  } PFR_PhyFontRec, *PFR_PhyFont;
+
+  typedef enum PFR_PhyFlags_
+  {
+    PFR_PHY_EXTRA_ITEMS      = 0x80,
+    PFR_PHY_3BYTE_GPS_OFFSET = 0x20,
+    PFR_PHY_2BYTE_GPS_SIZE   = 0x10,
+    PFR_PHY_ASCII_CODE       = 0x08,
+    PFR_PHY_PROPORTIONAL     = 0x04,
+    PFR_PHY_2BYTE_CHARCODE   = 0x02,
+    PFR_PHY_VERTICAL         = 0x01
+
+  } PFR_PhyFlags;
+
+ /************************************************************************/
+
+  typedef enum PFR_GlyphFlags_
+  {
+    PFR_GLYPH_IS_COMPOUND   = 0x80,
+    PFR_GLYPH_EXTRA_ITEMS   = 0x08,
+    PFR_GLYPH_1BYTE_XYCOUNT = 0x04,
+    PFR_GLYPH_XCOUNT        = 0x02,
+    PFR_GLYPH_YCOUNT        = 0x01
+    
+  } PFR_GlyphFlags;
+
+ /* controlled coordinate */
+  typedef struct PFR_CoordRec_
+  {
+    FT_UInt  org;
+    FT_UInt  cur;
+  
+  } PFR_CoordRec, *PFR_Coord;
+
+
+  typedef struct PFR_SubGlyphRec_
+  {
+    FT_Fixed   x_scale;
+    FT_Fixed   y_scale;
+    FT_Int     x_delta;
+    FT_Int     y_delta;
+    FT_UInt32  gps_offset;
+    FT_UInt    gps_size;
+  
+  } PFR_SubGlyphRec, *PFR_SubGlyph;
+
+
+  typedef enum PFR_SubgGlyphFlags_
+  {
+    PFR_SUBGLYPH_3BYTE_OFFSET = 0x80,
+    PFR_SUBGLYPH_2BYTE_SIZE   = 0x40,
+    PFR_SUBGLYPH_YSCALE       = 0x20,
+    PFR_SUBGLYPH_XSCALE       = 0x10
+    
+  } PFR_SubGlyphFlags;
+
+
+
+  typedef struct PFR_GlyphRec_
+  {
+    FT_Byte           format;
+    
+    FT_UInt           num_x_control;
+    FT_UInt           num_y_control;
+    FT_UInt           max_xy_control;
+    FT_Pos*           x_control;
+    FT_Pos*           y_control;
+
+
+    FT_UInt           num_subs;
+    FT_UInt           max_subs;
+    PFR_SubGlyphRec*  subs;
+    
+    FT_GlyphLoader    loader;
+    FT_Bool           path_begun;
+    
+  } PFR_GlyphRec, *PFR_Glyph;
+
+
+FT_END_HEADER
+
+#endif /* __PFR_TYPES_H__ */
--- /dev/null
+++ b/src/pfr/rules.mk
@@ -1,0 +1,70 @@
+#
+# FreeType 2 PFR driver configuration rules
+#
+
+
+# Copyright 1996-2002 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT.  By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+# Pfr driver directory
+#
+PFR_DIR  := $(SRC_)pfr
+PFR_DIR_ := $(PFR_DIR)$(SEP)
+
+
+# compilation flags for the driver
+#
+PFR_COMPILE := $(FT_COMPILE) $I$(PFR_DIR)
+
+
+# Pfr driver sources (i.e., C files)
+#
+PFR_DRV_SRC := $(PFR_DIR_)pfrload.c  \
+               $(PFR_DIR_)pfrgload.c \
+               $(PFR_DIR_)pfrcmap.c  \
+               $(PFR_DIR_)pfrdrivr.c \
+               $(PFR_DIR_)pfrobjs.c
+
+# Pfr driver headers
+#
+PFR_DRV_H := $(PFR_DRV_SRC:%.c=%.h)
+
+
+# Pfr driver object(s)
+#
+#   PFR_DRV_OBJ_M is used during `multi' builds
+#   PFR_DRV_OBJ_S is used during `single' builds
+#
+PFR_DRV_OBJ_M := $(PFR_DRV_SRC:$(PFR_DIR_)%.c=$(OBJ_)%.$O)
+PFR_DRV_OBJ_S := $(OBJ_)pfr.$O
+
+# Pfr driver source file for single build
+#
+PFR_DRV_SRC_S := $(PFR_DIR_)pfr.c
+
+
+# Pfr driver - single object
+#
+$(PFR_DRV_OBJ_S): $(PFR_DRV_SRC_S) $(PFR_DRV_SRC) $(FREETYPE_H) $(PFR_DRV_H)
+	$(PFR_COMPILE) $T$@ $(PFR_DRV_SRC_S)
+
+
+# Pfr driver - multiple objects
+#
+$(OBJ_)%.$O: $(PFR_DIR_)%.c $(FREETYPE_H) $(PFR_DRV_H)
+	$(PFR_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(PFR_DRV_OBJ_S)
+DRV_OBJS_M += $(PFR_DRV_OBJ_M)
+
+# EOF
--- a/src/type1/t1gload.c
+++ b/src/type1/t1gload.c
@@ -141,7 +141,7 @@
   FT_LOCAL_DEF( FT_Error )
   T1_Load_Glyph( T1_GlyphSlot  glyph,
                  T1_Size       size,
-                 FT_Int        glyph_index,
+                 FT_UInt       glyph_index,
                  FT_Int        load_flags )
   {
     FT_Error                error;
--- a/src/type1/t1gload.h
+++ b/src/type1/t1gload.h
@@ -34,7 +34,7 @@
   FT_LOCAL( FT_Error )
   T1_Load_Glyph( T1_GlyphSlot  glyph,
                  T1_Size       size,
-                 FT_Int        glyph_index,
+                 FT_UInt       glyph_index,
                  FT_Int        load_flags );