From bbc445e165c4bfa7571523cfbe8f164aaf02ea57 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sat, 11 Jan 2025 23:11:07 -0500 Subject: [PATCH] [bdf] Speed up bitmap parsing. A dedicated parser of bitmap data with minimal error checking and no string comparisons helps to improve performance. * src/bdf/bdflib.c (bdf_parse_bitmap_): New dedicated bitmap parser. (bdf_parse_glyphs_): Pass to `bdf_parse_bitmap_` on BITMAP. --- docs/CHANGES | 7 ++- src/bdf/bdflib.c | 136 +++++++++++++++++++++++------------------------ 2 files changed, 72 insertions(+), 71 deletions(-) diff --git a/docs/CHANGES b/docs/CHANGES index 3b5d0d5ef..bf454f46e 100644 --- a/docs/CHANGES +++ b/docs/CHANGES @@ -5,10 +5,15 @@ CHANGES BETWEEN 2.13.3 and 2.13.4 (2025-Mmm-DD) - Bitmap-only TrueType fonts now ignore FT_LOAD_NO_BITMAP flag and proceed loading bitmaps instead of giving an error. This behavior is documented and implemented for other bitmap-only fonts. The - flag has always meant to suppress the bitmap strikes in favor of + flag was always meant to suppress the bitmap strikes in favor of outlines, not to ban them completely. + III. MISCELLANEOUS + + - The BDF driver now loads fonts noticeably faster. + + ====================================================================== CHANGES BETWEEN 2.13.2 and 2.13.3 (2024-Aug-11) diff --git a/src/bdf/bdflib.c b/src/bdf/bdflib.c index 6f5509823..d145080c1 100644 --- a/src/bdf/bdflib.c +++ b/src/bdf/bdflib.c @@ -268,6 +268,7 @@ char* glyph_name; long glyph_enc; + bdf_glyph_t* glyph; bdf_font_t* font; bdf_options_t* opts; @@ -940,9 +941,6 @@ BDF_BBX_ | \ BDF_BITMAP_ ) -#define BDF_GLYPH_WIDTH_CHECK_ 0x40000000UL -#define BDF_GLYPH_HEIGHT_CHECK_ 0x80000000UL - static FT_Error bdf_add_comment_( bdf_font_t* font, @@ -1280,7 +1278,67 @@ } - /* Actually parse the glyph info and bitmaps. */ + /* Line function prototype. */ + static FT_Error + bdf_parse_glyphs_( char* line, + unsigned long linelen, + unsigned long lineno, + void* call_data, + void* client_data ); + + + /* Aggressively parse the glyph bitmaps. */ + static FT_Error + bdf_parse_bitmap_( char* line, + unsigned long linelen, + unsigned long lineno, + void* call_data, + void* client_data ) + { + bdf_line_func_t_* next = (bdf_line_func_t_ *)call_data; + bdf_parse_t_* p = (bdf_parse_t_ *) client_data; + bdf_glyph_t* glyph = p->glyph; + + unsigned char* bp; + unsigned long i, nibbles; + int x; + + FT_UNUSED( lineno ); /* only used in debug mode */ + + + nibbles = glyph->bpr << 1; + bp = glyph->bitmap + p->row * glyph->bpr; + + if ( nibbles > linelen ) + { + FT_TRACE2(( "bdf_parse_bitmap_: " ACMSG16, glyph->encoding )); + nibbles = linelen; + } + + for ( i = 0; i < nibbles; i++ ) + { + /* char to hex without checks */ + x = line[i]; + x += ( x & 0x40 ) * 9 >> 6; /* for [A-Fa-f] */ + x &= 0x0F; + + if ( i & 1 ) + *bp++ |= x; + else + *bp = x << 4; + } + + p->row++; + + /* When done, go back to parsing glyphs */ + if ( p->row >= (unsigned long)glyph->bbx.height ) + *next = bdf_parse_glyphs_; + + return FT_Err_Ok; + } + + + /* Actually parse the glyph info. */ static FT_Error bdf_parse_glyphs_( char* line, unsigned long linelen, @@ -1296,10 +1354,8 @@ FT_Memory memory = font->memory; FT_Error error = FT_Err_Ok; - int c, mask_index; char* s; - unsigned char* bp; - unsigned long i, slen, nibbles; + unsigned long slen; FT_UNUSED( lineno ); /* only used in debug mode */ @@ -1528,10 +1584,6 @@ } } - /* Clear the flags that might be added when width and height are */ - /* checked for consistency. */ - p->flags &= ~( BDF_GLYPH_WIDTH_CHECK_ | BDF_GLYPH_HEIGHT_CHECK_ ); - p->flags |= BDF_ENCODING_; goto Exit; @@ -1546,64 +1598,6 @@ else glyph = font->glyphs + ( font->glyphs_used - 1 ); - /* Check whether a bitmap is being constructed. */ - if ( p->flags & BDF_BITMAP_ ) - { - /* If there are more rows than are specified in the glyph metrics, */ - /* ignore the remaining lines. */ - if ( p->row >= (unsigned long)glyph->bbx.height ) - { - if ( !( p->flags & BDF_GLYPH_HEIGHT_CHECK_ ) ) - { - FT_TRACE2(( "bdf_parse_glyphs_: " ACMSG13, glyph->encoding )); - p->flags |= BDF_GLYPH_HEIGHT_CHECK_; - } - - goto Exit; - } - - /* Only collect the number of nibbles indicated by the glyph */ - /* metrics. If there are more columns, they are simply ignored. */ - nibbles = glyph->bpr << 1; - bp = glyph->bitmap + p->row * glyph->bpr; - - for ( i = 0; i < nibbles; i++ ) - { - c = line[i]; - if ( !sbitset( hdigits, c ) ) - break; - *bp = (FT_Byte)( ( *bp << 4 ) + a2i[c] ); - if ( i + 1 < nibbles && ( i & 1 ) ) - *++bp = 0; - } - - /* If any line has not enough columns, */ - /* indicate they have been padded with zero bits. */ - if ( i < nibbles && - !( p->flags & BDF_GLYPH_WIDTH_CHECK_ ) ) - { - FT_TRACE2(( "bdf_parse_glyphs_: " ACMSG16, glyph->encoding )); - p->flags |= BDF_GLYPH_WIDTH_CHECK_; - } - - /* Remove possible garbage at the right. */ - mask_index = ( glyph->bbx.width * p->font->bpp ) & 7; - if ( glyph->bbx.width ) - *bp &= nibble_mask[mask_index]; - - /* If any line has extra columns, indicate they have been removed. */ - if ( i == nibbles && - sbitset( hdigits, line[nibbles] ) && - !( p->flags & BDF_GLYPH_WIDTH_CHECK_ ) ) - { - FT_TRACE2(( "bdf_parse_glyphs_: " ACMSG14, glyph->encoding )); - p->flags |= BDF_GLYPH_WIDTH_CHECK_; - } - - p->row++; - goto Exit; - } - /* Expect the SWIDTH (scalable width) field next. */ if ( _bdf_strncmp( line, "SWIDTH", 6 ) == 0 ) { @@ -1727,11 +1721,13 @@ else glyph->bytes = (unsigned short)bitmap_size; - if ( FT_ALLOC( glyph->bitmap, glyph->bytes ) ) + if ( !bitmap_size || FT_ALLOC( glyph->bitmap, glyph->bytes ) ) goto Exit; + p->glyph = glyph; p->row = 0; p->flags |= BDF_BITMAP_; + *next = bdf_parse_bitmap_; goto Exit; }