ref: 89a2a4b531cec490761ac971c7a222d2bcec441f
parent: 8def3c897f3dc31797796220c443fffd625e55dc
author: David Turner <[email protected]>
date: Wed Dec 14 15:38:15 EST 2005
* 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.
--- 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 <[email protected]>
* src/sfnt/sfobjc.c (sfnt_init_face): Move tag check to...
--- 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,7 +492,14 @@
/*************************************************************************/
+ /* */
+ /* 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 ****/
/**** ****/
@@ -546,6 +551,7 @@
/* driver. */
/* */
#undef T1_CONFIG_OPTION_NO_MM_SUPPORT
+
/* */
--- 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
--- a/include/freetype/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -843,7 +843,69 @@
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 */
+
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
@@ -1341,6 +1403,10 @@
FT_Bool doblend;
GX_Blend blend;
#endif
+
+#ifdef TT_CONFIG_OPTION_BDF
+ TT_BDFRec bdf;
+#endif /* TT_CONFIG_OPTION_BDF */
/***********************************************************************/
/* */
--- 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' )
--- 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
{
--- 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
--- 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,7 +298,52 @@
(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", ®istry );
+ 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
*
@@ -305,6 +355,9 @@
{ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name },
#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 },
--- 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 */
--- 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
/*************************************************************************/
/* */
@@ -751,6 +754,11 @@
if ( sfnt->free_sbits )
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 );
--- /dev/null
+++ b/src/sfnt/ttbdf.c
@@ -1,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 */
--- /dev/null
+++ b/src/sfnt/ttbdf.h
@@ -1,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 */