* include/freetype/config/ftoption.h,
        include/freetype/config/ftstdlib.h,
        include/freetype/internal/tttypes.h,
        src/sfnt/Jamfile, src/sfnt/rules.mk, src/sfnt/sfdriver.c,
        src/sfnt/ttbdf.h, src/sfnt/ttbdf.c, src/sfnt/sfobjs.c:

        Added support for an embedded 'BDF ' table within SFNT-based
        bitmap font files. This is used to store atoms & properties from
        the original BDF fonts that were used to generate the font file.

        the feature is controled by TT_CONFIG_OPTION_BDF within 'ftoption.h'
        and is used to implement FT_Get_BDF_Property for these font files.

        At the moment, this is still experimental, the BDF table format isn't
        cast into stone yet.
diff --git a/ChangeLog b/ChangeLog
index 8fe21a1..747f487 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -12,6 +12,8 @@
         same location than other generated objects (i.e. within the 'objs'
         directory of the current dir)
 
+        * src/sfnt/
+
 2005-12-07  Werner Lemberg  <wl@gnu.org>
 
 	* src/sfnt/sfobjc.c (sfnt_init_face): Move tag check to...
diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h
index 42579ad..fcd142e 100644
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -101,9 +101,7 @@
   /*                                                                       */
   /*   FreeType now handles font files that have been compressed with the  */
   /*   'compress' program.  This is mostly used to parse many of the PCF   */
-  /*   files that come with various X11 distributions.  The implementation */
-  /*   uses NetBSD's `zopen' to partially uncompress the file on the fly   */
-  /*   (see src/lzw/ftgzip.c).                                             */
+  /*   files that come with various X11 distributions.                     */
   /*                                                                       */
   /*   Define this macro if you want to enable this `feature'.             */
   /*                                                                       */
@@ -494,6 +492,13 @@
 
 
   /*************************************************************************/
+  /*                                                                       */
+  /* Define TT_CONFIG_OPTION_BDF if upi want to include support for        */
+  /* an embedded 'BDF' table within SFNT-based bitmap formats.             */
+  /*                                                                       */
+#define TT_CONFIG_OPTION_BDF
+
+  /*************************************************************************/
   /*************************************************************************/
   /****                                                                 ****/
   /****      T Y P E 1   D R I V E R    C O N F I G U R A T I O N       ****/
@@ -547,6 +552,7 @@
   /*                                                                       */
 #undef T1_CONFIG_OPTION_NO_MM_SUPPORT
 
+
  /* */
 
 /*
diff --git a/include/freetype/config/ftstdlib.h b/include/freetype/config/ftstdlib.h
index 4b9b398..2839e15 100644
--- a/include/freetype/config/ftstdlib.h
+++ b/include/freetype/config/ftstdlib.h
@@ -92,6 +92,7 @@
 #define ft_memcpy   memcpy
 #define ft_memmove  memmove
 #define ft_memset   memset
+#define ft_memchr   memchr
 #define ft_strcat   strcat
 #define ft_strcmp   strcmp
 #define ft_strcpy   strcpy
diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h
index 7f8335f..368ab68 100644
--- a/include/freetype/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -843,6 +843,68 @@
   typedef struct GX_BlendRec_  *GX_Blend;
 #endif
 
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /***       EMBEDDED BDF PROPERTIES TABLE SUPPORT                       ***/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+/* these types are used to support a 'BDF' table that isn't part of the
+ * official TrueType specification. It is mainly used in SFNT-based bitmap
+ * fonts that were generated from a set of BDF fonts
+ *
+ * the format of the table is the following:
+ *
+ *   USHORT   version      'BDF' table version number, should be 0x0001
+ *   USHORT   strikeCount  number of strikes (bitmap sizes) in this table
+ *   ULONG    stringTable  offset (froms start of BDF table) to string table
+ *
+ * followed by an array of 'strikeCount' descriptors that look like:
+ *
+ *   USHORT   ppem         vertical pixels per EM for this strike
+ *   USHORT   numItems     number of items for this strike (properties and
+ *                         atoms), max is 255
+ *
+ * this array is followed by 'strikeCount' value sets. Each "value set"
+ * is an array of 'numItems' items that look like the following:
+ *
+ *   ULONG    item_name     offset in string table to item name
+ *   USHORT   item_type     0 => string (e.g. COMMENT)
+ *                          1 => atom   (e.g. FONT or even SIZE)
+ *                          2 => int32
+ *                          3 => uint32
+ *                       0x10 => flag for properties, ored with above values
+ *
+ *   ULONG    item_value    for strings => offset in string table without
+ *                                         the corresponding double quotes
+ *
+ *                              atoms   => offset in string table
+ *
+ *                              integers => direct value
+ *
+ * all strings in the string table are 8-bit, zero-terminated
+ */
+
+#ifdef TT_CONFIG_OPTION_BDF
+
+  typedef struct TT_BDFRec_
+  {
+    FT_Byte*       table;
+    FT_Byte*       table_end;
+    FT_Byte*       strings;
+    FT_UInt32      strings_size;
+    FT_UInt        num_strikes;
+    FT_Bool        loaded;
+
+  } TT_BDFRec, *TT_BDF;
+
+#endif /* TT_CONFIG_OPTION_BDF */
 
   /*************************************************************************/
   /*************************************************************************/
@@ -1342,6 +1404,10 @@
     GX_Blend              blend;
 #endif
 
+#ifdef TT_CONFIG_OPTION_BDF
+    TT_BDFRec        bdf;
+#endif /* TT_CONFIG_OPTION_BDF */
+
     /***********************************************************************/
     /*                                                                     */
     /* Other tables or fields. This is used by derivative formats like     */
diff --git a/include/freetype/tttags.h b/include/freetype/tttags.h
index a289db3..e10244c 100644
--- a/include/freetype/tttags.h
+++ b/include/freetype/tttags.h
@@ -36,6 +36,7 @@
 #define TTAG_avar  FT_MAKE_TAG( 'a', 'v', 'a', 'r' )
 #define TTAG_BASE  FT_MAKE_TAG( 'B', 'A', 'S', 'E' )
 #define TTAG_bdat  FT_MAKE_TAG( 'b', 'd', 'a', 't' )
+#define TTAG_BDF   FT_MAKE_TAG( 'B', 'D', 'F', ' ' )
 #define TTAG_bhed  FT_MAKE_TAG( 'b', 'h', 'e', 'd' )
 #define TTAG_bloc  FT_MAKE_TAG( 'b', 'l', 'o', 'c' )
 #define TTAG_bsln  FT_MAKE_TAG( 'b', 's', 'l', 'n' )
diff --git a/src/sfnt/Jamfile b/src/sfnt/Jamfile
index 8fe191f..6b8a401 100644
--- a/src/sfnt/Jamfile
+++ b/src/sfnt/Jamfile
@@ -16,7 +16,7 @@
 
   if $(FT2_MULTI)
   {
-    _sources = sfobjs sfdriver ttcmap ttpost ttload ttsbit ttkern ;
+    _sources = sfobjs sfdriver ttcmap ttpost ttload ttsbit ttkern ttbdf ;
   }
   else
   {
diff --git a/src/sfnt/rules.mk b/src/sfnt/rules.mk
index e15681b..6fa3f55 100644
--- a/src/sfnt/rules.mk
+++ b/src/sfnt/rules.mk
@@ -30,6 +30,7 @@
                 $(SFNT_DIR)/ttsbit.c   \
                 $(SFNT_DIR)/ttpost.c   \
                 $(SFNT_DIR)/ttkern.c   \
+                $(SFNT_DIR)/ttbdf.c    \
                 $(SFNT_DIR)/sfobjs.c   \
                 $(SFNT_DIR)/sfdriver.c
 
diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c
index 96dd1da..c7fc713 100644
--- a/src/sfnt/sfdriver.c
+++ b/src/sfnt/sfdriver.c
@@ -34,6 +34,11 @@
 #include "ttpost.h"
 #endif
 
+#ifdef TT_CONFIG_OPTION_BDF
+#include "ttbdf.h"
+#include FT_SERVICE_BDF_H
+#endif
+
 #include "ttcmap.h"
 #include "ttkern.h"
 
@@ -293,6 +298,51 @@
     (TT_CMap_Info_GetFunc)tt_get_cmap_info
   };
 
+#ifdef TT_CONFIG_OPTION_BDF
+
+  static FT_Error
+  sfnt_get_charset_id( TT_Face       face,
+                       const char*  *acharset_encoding,
+                       const char*  *acharset_registry )
+  {
+    BDF_PropertyRec   encoding, registry;
+    FT_Error          error;
+
+   /* XXX: I don't know if this is correct, since tt_face_find_bdf_prop
+    *      will only return something correct if we have previously
+    *      selected a size that is listed in the BDF table.
+    *      should we change the BDF table format to include single
+    *      offsets for "CHARSET_REGISTRY" and "CHARSET_ENCODING" ?
+    */
+    error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", &registry );
+    if ( !error )
+    {
+      error = tt_face_find_bdf_prop( face, "CHARSET_ENCODING", &encoding );
+      if ( !error )
+      {
+        if ( registry.type == BDF_PROPERTY_TYPE_ATOM &&
+             encoding.type == BDF_PROPERTY_TYPE_ATOM )
+        {
+          *acharset_encoding = encoding.u.atom;
+          *acharset_registry = registry.u.atom;
+        }
+        else
+          error = FT_Err_Invalid_Argument;
+      }
+    }
+
+    return error;
+  }
+
+
+  static const FT_Service_BDFRec  sfnt_service_bdf =
+  {
+    (FT_BDF_GetCharsetIdFunc) sfnt_get_charset_id,
+    (FT_BDF_GetPropertyFunc)  tt_face_find_bdf_prop,
+  };
+
+#endif /* TT_CONFIG_OPTION_BDF */
+
 
  /*
   *  SERVICE LIST
@@ -306,6 +356,9 @@
 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
     { FT_SERVICE_ID_GLYPH_DICT,           &sfnt_service_glyph_dict },
 #endif
+#ifdef TT_CONFIG_OPTION_BDF
+    { FT_SERVICE_ID_BDF,                  &sfnt_service_bdf },
+#endif
     { FT_SERVICE_ID_TT_CMAP,              &tt_service_get_cmap_info },
 
     { NULL, NULL }
diff --git a/src/sfnt/sfnt.c b/src/sfnt/sfnt.c
index 798f923..a7b14a7 100644
--- a/src/sfnt/sfnt.c
+++ b/src/sfnt/sfnt.c
@@ -33,5 +33,8 @@
 #include "ttpost.c"
 #endif
 
+#ifdef TT_CONFIG_OPTION_BDF
+#include "ttbdf.c"
+#endif
 
 /* END */
diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c
index 991705d..ba3194a 100644
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -27,6 +27,9 @@
 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
 #include "sferrors.h"
 
+#ifdef TT_CONFIG_OPTION_BDF
+#include "ttbdf.h"
+#endif
 
   /*************************************************************************/
   /*                                                                       */
@@ -752,6 +755,11 @@
         sfnt->free_sbits( face );
     }
 
+#ifdef TT_CONFIG_OPTION_BDF
+    /* freeing the embedded BDF properties */
+    tt_face_free_bdf_props( face );
+#endif
+
     /* freeing the kerning table */
     tt_face_done_kern( face );
 
diff --git a/src/sfnt/ttbdf.c b/src/sfnt/ttbdf.c
new file mode 100644
index 0000000..0e679c6
--- /dev/null
+++ b/src/sfnt/ttbdf.c
@@ -0,0 +1,237 @@
+/***************************************************************************/

+/*                                                                         */

+/*  ttbdf.c                                                                */

+/*                                                                         */

+/*    TrueType and OpenType embedded BDF properties (body).                */

+/*                                                                         */

+/*  Copyright 2005 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 <ft2build.h>

+#include FT_INTERNAL_DEBUG_H

+#include FT_INTERNAL_STREAM_H

+#include FT_TRUETYPE_TAGS_H

+#include "ttbdf.h"

+

+#include "sferrors.h"

+

+#ifdef TT_CONFIG_OPTION_BDF

+

+  /*************************************************************************/

+  /*                                                                       */

+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */

+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */

+  /* messages during execution.                                            */

+  /*                                                                       */

+#undef  FT_COMPONENT

+#define FT_COMPONENT  trace_ttbdf

+

+FT_LOCAL_DEF( void )

+tt_face_free_bdf_props( TT_Face  face )

+{

+  TT_BDF   bdf = &face->bdf;

+

+  if ( bdf->loaded )

+  {

+    FT_Stream  stream = FT_FACE(face)->stream;

+

+    if ( bdf->table != NULL )

+      FT_FRAME_RELEASE( bdf->table );

+

+    bdf->table_end    = NULL;

+    bdf->strings      = NULL;

+    bdf->strings_size = 0;

+  }

+}

+

+

+static FT_Error

+tt_face_load_bdf_props( TT_Face    face,

+                        FT_Stream  stream )

+{

+  TT_BDF    bdf = &face->bdf;

+  FT_ULong  length;

+  FT_Error  error;

+

+  FT_ZERO( bdf );

+

+  error = tt_face_goto_table( face, TTAG_BDF, stream, &length );

+  if ( error                                  ||

+       length < 8                             ||

+       FT_FRAME_EXTRACT( length, bdf->table ) )

+  {

+    error = FT_Err_Invalid_Table;

+    goto Exit;

+  }

+

+  bdf->table_end = bdf->table + length;

+

+  {

+    FT_Byte*  p           = bdf->table;

+    FT_UInt   version     = FT_NEXT_USHORT(p);

+    FT_UInt   num_strikes = FT_NEXT_USHORT(p);

+    FT_UInt32 strings     = FT_NEXT_ULONG(p);

+

+    if ( version != 0x0001           ||

+         strings < 8                 ||

+         (strings-8)/4 < num_strikes ||

+         strings+1 > length          )

+    {

+    BadTable:

+      FT_FRAME_RELEASE( bdf->table );

+      FT_ZERO( bdf );

+      error = FT_Err_Invalid_Table;

+      goto Exit;

+    }

+

+    bdf->num_strikes  = num_strikes;

+    bdf->strings      = bdf->table + strings;

+    bdf->strings_size = length - strings;

+  }

+

+ /* check the strike descriptors

+  */

+  {

+    FT_UInt   count  = bdf->num_strikes;

+    FT_Byte*  p      = bdf->table + 8;

+    FT_Byte*  strike = p + count*4;

+

+    for ( ; count > 0; count-- )

+    {

+      FT_UInt  num_items = FT_PEEK_USHORT(p+2);

+

+     /* we don't need to check the value sets themselves, since this

+      * is done later

+      */

+      strike += 10*num_items;

+

+      p += 4;

+    }

+

+    if ( strike > bdf->strings )

+      goto BadTable;

+  }

+

+  bdf->loaded = 1;

+

+Exit:

+  return error;

+}

+

+

+FT_LOCAL_DEF( FT_Error )

+tt_face_find_bdf_prop( TT_Face           face,

+                       const char*       property_name,

+                       BDF_PropertyRec  *aprop )

+{

+  TT_BDF    bdf   = &face->bdf;

+  FT_Size   size  = FT_FACE(face)->size;

+  FT_Error  error = 0;

+  FT_Byte*  p;

+  FT_UInt   count;

+  FT_Byte*  strike;

+  FT_UInt   property_len;

+

+  aprop->type = BDF_PROPERTY_TYPE_NONE;

+

+  if ( bdf->loaded == 0 )

+  {

+    error = tt_face_load_bdf_props( face, FT_FACE(face)->stream );

+    if ( error )

+      goto Exit;

+  }

+

+  count  = bdf->num_strikes;

+  p      = bdf->table + 8;

+  strike = p + 4*count;

+

+  error = FT_Err_Invalid_Argument;

+

+  if ( size == NULL || property_name == NULL )

+    goto Exit;

+

+  property_len = ft_strlen( property_name );

+  if ( property_len == 0 )

+    goto Exit;

+

+  for ( ; count > 0; count-- )

+  {

+    FT_UInt   _ppem  = FT_NEXT_USHORT(p);

+    FT_UInt   _count = FT_NEXT_USHORT(p);

+

+    if ( _ppem == size->metrics.y_ppem )

+    {

+      count = _count;

+      goto FoundStrike;

+    }

+

+    strike += 10*_count;

+  }

+  goto Exit;

+

+FoundStrike:

+  p = strike;

+  for ( ; count > 0; count-- )

+  {

+    FT_UInt   type = FT_PEEK_USHORT(p+4);

+

+    if ( (type & 0x10) != 0 )

+    {

+      FT_UInt32  name_offset = FT_PEEK_ULONG(p);

+      FT_UInt32  value       = FT_PEEK_ULONG(p+6);

+

+      /* be a bit paranoid for invalid entries here */

+      if ( name_offset < bdf->strings_size                        &&

+           property_len < bdf->strings_size - name_offset         &&

+           ft_strncmp( property_name, (const char*)bdf->strings + name_offset,

+                       bdf->strings_size - name_offset ) == 0     )

+      {

+        switch ( type & 0x0F )

+        {

+          case 0x00:  /* string */

+          case 0x01:  /* atoms */

+            /* check that the content is really 0-terminated */

+            if ( value < bdf->strings_size &&

+                 ft_memchr( bdf->strings + value, 0, bdf->strings_size ) )

+            {

+              aprop->type   = BDF_PROPERTY_TYPE_ATOM;

+              aprop->u.atom = (const char*) bdf->strings + value;

+              error         = 0;

+              goto Exit;

+            }

+            break;

+

+          case 0x02:

+            aprop->type      = BDF_PROPERTY_TYPE_INTEGER;

+            aprop->u.integer = (FT_Int32)value;

+            error            = 0;

+            goto Exit;

+

+          case 0x03:

+            aprop->type       = BDF_PROPERTY_TYPE_CARDINAL;

+            aprop->u.cardinal = value;

+            error             = 0;

+            goto Exit;

+

+          default:

+            ;

+        }

+      }

+    }

+    p += 10;

+  }

+

+Exit:

+  return error;

+}

+

+#endif /* TT_CONFIG_OPTION_BDF */

diff --git a/src/sfnt/ttbdf.h b/src/sfnt/ttbdf.h
new file mode 100644
index 0000000..65da1e0
--- /dev/null
+++ b/src/sfnt/ttbdf.h
@@ -0,0 +1,46 @@
+/***************************************************************************/

+/*                                                                         */

+/*  ttbdf.h                                                                */

+/*                                                                         */

+/*    TrueType and OpenType embedded BDF properties (specification).       */

+/*                                                                         */

+/*  Copyright 2005 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 __TTBDF_H__

+#define __TTBDF_H__

+

+

+#include <ft2build.h>

+#include "ttload.h"

+#include FT_BDF_H

+

+

+FT_BEGIN_HEADER

+

+

+  FT_LOCAL( void )

+  tt_face_free_bdf_props( TT_Face  face );

+

+

+  FT_LOCAL( FT_Error )

+  tt_face_find_bdf_prop( TT_Face           face,

+                         const char*       property_name,

+                         BDF_PropertyRec  *aprop );

+

+

+FT_END_HEADER

+

+#endif /* __TTBDF_H__ */

+

+

+/* END */