From 5751c184cc1bb010d8007c6485592e75193a5ba7 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Thu, 4 Dec 2025 07:30:06 +0100 Subject: [PATCH] Improve documentation of the 'BDF ' table as used in X11 `.otb` files. Also do some minor code formatting. --- devel/ftoption.h | 8 +++++++- docs/formats.txt | 8 ++++++-- include/freetype/config/ftoption.h | 8 +++++++- include/freetype/ftbdf.h | 12 ++++++++--- src/sfnt/sfdriver.c | 7 +------ src/sfnt/ttbdf.c | 32 +++++++++++++++++------------- 6 files changed, 48 insertions(+), 27 deletions(-) diff --git a/devel/ftoption.h b/devel/ftoption.h index b9820df2b..1d4ad342b 100644 --- a/devel/ftoption.h +++ b/devel/ftoption.h @@ -759,7 +759,13 @@ FT_BEGIN_HEADER /************************************************************************** * * Define `TT_CONFIG_OPTION_BDF` if you want to include support for an - * embedded 'BDF~' table within SFNT-based bitmap formats. + * embedded 'BDF~' table within an SFNT-based `.otb` font file. This table + * is an extension used by X11 to preserve BDF properties after conversion + * to SFNT containers. See + * + * https://fontforge.org/docs/techref/non-standard.html#non-standard-bdf + * + * for more details. */ #define TT_CONFIG_OPTION_BDF diff --git a/docs/formats.txt b/docs/formats.txt index 74ea98bc6..db29a046a 100644 --- a/docs/formats.txt +++ b/docs/formats.txt @@ -86,8 +86,8 @@ which isn't supported yet please send a mail too. SFNT PS CFF SYNTHETIC --- OT spec, 5176.CFF.pdf SFNT PS CFF2 --- cff OT spec 1.8 - SFNT TT SBIT --- sfnt XFree86 (bitmaps only; - with `head' table) + SFNT TT SBIT --- sfnt X11 (bitmaps only; + with `head' table) [8] SFNT TT MACSBIT --- sfnt OT spec (for the Mac; bitmaps only; `bhed' table) SFNT TT --- --- truetype OT spec (`normal' TT font) @@ -204,6 +204,10 @@ which isn't supported yet please send a mail too. versions of FreeType don't not support this format, but FontForge can load it. +[8] Such fonts also contain a 'BDF ' table to hold BDF properties; see + + https://fontforge.org/docs/techref/non-standard.html#non-standard-bdf + ------------------------------------------------------------------------ Copyright (C) 2004-2025 by diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h index 493418689..fadfb9187 100644 --- a/include/freetype/config/ftoption.h +++ b/include/freetype/config/ftoption.h @@ -759,7 +759,13 @@ FT_BEGIN_HEADER /************************************************************************** * * Define `TT_CONFIG_OPTION_BDF` if you want to include support for an - * embedded 'BDF~' table within SFNT-based bitmap formats. + * embedded 'BDF~' table within an SFNT-based `.otb` font file. This table + * is an extension used by X11 to preserve BDF properties after conversion + * to SFNT containers. See + * + * https://fontforge.org/docs/techref/non-standard.html#non-standard-bdf + * + * for more details. */ #define TT_CONFIG_OPTION_BDF diff --git a/include/freetype/ftbdf.h b/include/freetype/ftbdf.h index faad25689..566a78d1b 100644 --- a/include/freetype/ftbdf.h +++ b/include/freetype/ftbdf.h @@ -44,7 +44,8 @@ FT_BEGIN_HEADER * * @description: * This section contains the declaration of functions specific to BDF and - * PCF fonts. + * PCF fonts. They also work for SFNT bitmap fonts that contain a 'BDF~' + * table like X11's `.otb` fonts. * */ @@ -151,7 +152,9 @@ FT_BEGIN_HEADER * FreeType error code. 0~means success. * * @note: - * This function only works with BDF faces, returning an error otherwise. + * This function only works with BDF faces and SFNT fonts that have a + * 'BDF~' table, returning an error otherwise. For the latter, a bitmap + * strike size must be selected first. */ FT_EXPORT( FT_Error ) FT_Get_BDF_Charset_ID( FT_Face face, @@ -165,7 +168,7 @@ FT_BEGIN_HEADER * FT_Get_BDF_Property * * @description: - * Retrieve a BDF property from a BDF or PCF font file. + * Retrieve a BDF property from a BDF or PCF font. * * @input: * face :: @@ -196,6 +199,9 @@ FT_BEGIN_HEADER * * In case of error, `aproperty->type` is always set to * @BDF_PROPERTY_TYPE_NONE. + * + * This also with SFNT fonts that have a 'BDF~' table, after a bitmap + * strike size has been selected. */ FT_EXPORT( FT_Error ) FT_Get_BDF_Property( FT_Face face, diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c index ec78247aa..32291e23e 100644 --- a/src/sfnt/sfdriver.c +++ b/src/sfnt/sfdriver.c @@ -1142,12 +1142,7 @@ FT_Error error; - /* XXX: I don't know whether this is correct, since - * tt_face_find_bdf_prop only returns 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'? - */ + /* We expect that a bitmap strike has been selected. */ error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", ®istry ); if ( !error ) { diff --git a/src/sfnt/ttbdf.c b/src/sfnt/ttbdf.c index 78a33fa30..bd2a94b9d 100644 --- a/src/sfnt/ttbdf.c +++ b/src/sfnt/ttbdf.c @@ -16,6 +16,12 @@ */ + /* + * The 'BDF ' SFNT table is described in the FontForge documentation, see + * + * https://fontforge.org/docs/techref/non-standard.html#non-standard-bdf + */ + #include #include #include @@ -80,21 +86,19 @@ 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_ULong strings = FT_NEXT_ULONG ( p ); - FT_UInt count; - FT_Byte* strike; + FT_Byte* p = bdf->table; + FT_UInt version = FT_NEXT_USHORT( p ); + FT_UInt num_strikes = FT_NEXT_USHORT( p ); + FT_ULong strings = FT_NEXT_ULONG ( p ); + FT_UInt count; + FT_Byte* strike; if ( version != 0x0001 || strings < 8 || ( strings - 8 ) / 4 < num_strikes || strings + 1 > length ) - { goto BadTable; - } bdf->num_strikes = num_strikes; bdf->strings = bdf->table + strings; @@ -104,15 +108,14 @@ p = bdf->table + 8; strike = p + count * 4; - + /* Check table length. */ 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. - */ + + /* We don't check the value sets themselves; */ + /* this is done while accessing a property. */ strike += 10 * num_items; p += 4; @@ -200,6 +203,7 @@ 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 && @@ -212,7 +216,7 @@ case 0x00: /* string */ case 0x01: /* atoms */ /* check that the content is really 0-terminated */ - if ( value < bdf->strings_size && + if ( value < bdf->strings_size && ft_memchr( bdf->strings + value, 0, bdf->strings_size ) ) { aprop->type = BDF_PROPERTY_TYPE_ATOM;