diff --git a/ChangeLog b/ChangeLog index 8fe21a1c0..747f487b8 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 * 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 42579ad83..fcd142eb0 100644 --- a/include/freetype/config/ftoption.h +++ b/include/freetype/config/ftoption.h @@ -101,9 +101,7 @@ FT_BEGIN_HEADER /* */ /* 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'. */ /* */ @@ -493,6 +491,13 @@ FT_BEGIN_HEADER #define TT_CONFIG_OPTION_GX_VAR_SUPPORT + /*************************************************************************/ + /* */ + /* 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 + /*************************************************************************/ /*************************************************************************/ /**** ****/ @@ -547,6 +552,7 @@ FT_BEGIN_HEADER /* */ #undef T1_CONFIG_OPTION_NO_MM_SUPPORT + /* */ /* diff --git a/include/freetype/config/ftstdlib.h b/include/freetype/config/ftstdlib.h index 4b9b398b2..2839e15b4 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 7f8335f82..368ab68f4 100644 --- a/include/freetype/internal/tttypes.h +++ b/include/freetype/internal/tttypes.h @@ -843,6 +843,68 @@ FT_BEGIN_HEADER 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 @@ FT_BEGIN_HEADER 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 a289db3f3..e10244ca7 100644 --- a/include/freetype/tttags.h +++ b/include/freetype/tttags.h @@ -36,6 +36,7 @@ FT_BEGIN_HEADER #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 8fe191fa3..6b8a40182 100644 --- a/src/sfnt/Jamfile +++ b/src/sfnt/Jamfile @@ -16,7 +16,7 @@ SubDir FT2_TOP $(FT2_SRC_DIR) sfnt ; 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 e15681b21..6fa3f5570 100644 --- a/src/sfnt/rules.mk +++ b/src/sfnt/rules.mk @@ -30,6 +30,7 @@ SFNT_DRV_SRC := $(SFNT_DIR)/ttload.c \ $(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 96dd1daf4..c7fc71302 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", ®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 }, diff --git a/src/sfnt/sfnt.c b/src/sfnt/sfnt.c index 798f923fa..a7b14a7a7 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 991705dc8..ba3194a48 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 000000000..0e679c672 --- /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 +#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 000000000..65da1e0d1 --- /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 +#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 */