From 37e193e9357bdccbfb8a4437ddfdc06efd9e140c Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Sun, 6 Nov 2016 12:32:51 +0100 Subject: [PATCH] Introduce a way of quickly retrieving (embedded) bitmap metrics. `FT_Load_Glyph' doesn't generate a bitmap for a non-bitmap glyph until the user calls `FT_Render_Glyph'. However, it always allocates memory for bitmaps and copies or decodes the contents of a bitmap glyph, which can be quite slow for PNG data. * include/freetype/freetype.h (FT_LOAD_BITMAP_METRICS_ONLY): New macro. * src/base/ftobjs.c (FT_Load_Glyph): Unset FT_LOAD_RENDER if FT_LOAD_BITMAP_METRICS_ONLY is used. * src/sfnt/ttsbit.c (tt_sbit_decoder_alloc_bitmap, tt_sbit_decoder_load_bitmap): Add argument to control allocation of the glyph slot. (tt_sbit_decoder_load_image, tt_sbit_decoder_load_compound, tt_face_load_sbit_image): Updated. * src/pcf/pcfdrivr.c (PCF_Glyph_Load): Quickly exit if `FT_LOAD_BITMAP_METRICS_ONLY' is set. * src/pfr/pfrsbit.c, src/pfr/pfrsbit.h (pfr_slot_load_bitmap): Add argument to control allocation of the glyph slot. * src/pfr/pfrobjs (pfr_slot_load): Updated. * src/winfonts/winfnt.c (FNT_Load_Glyph): Ditto. * docs/CHANGES: Updated. --- ChangeLog | 35 ++++++++++++++++++++++++++- docs/CHANGES | 3 +++ include/freetype/freetype.h | 9 +++++++ src/base/ftobjs.c | 3 +++ src/pcf/pcfdrivr.c | 35 +++++++++++++-------------- src/pfr/pfrobjs.c | 6 ++++- src/pfr/pfrsbit.c | 6 ++++- src/pfr/pfrsbit.h | 3 ++- src/sfnt/ttsbit.c | 47 +++++++++++++++++++++++++------------ src/winfonts/winfnt.c | 44 +++++++++++++++++----------------- 10 files changed, 134 insertions(+), 57 deletions(-) diff --git a/ChangeLog b/ChangeLog index 881d23eb8..cbe5a2053 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,37 @@ -2016-10-29 Werner Lemberg +2016-11-06 Seigo Nonaka + Werner Lemberg + + Introduce a way of quickly retrieving (embedded) bitmap metrics. + + `FT_Load_Glyph' doesn't generate a bitmap for a non-bitmap glyph + until the user calls `FT_Render_Glyph'. However, it always + allocates memory for bitmaps and copies or decodes the contents of a + bitmap glyph, which can be quite slow for PNG data. + + * include/freetype/freetype.h (FT_LOAD_BITMAP_METRICS_ONLY): New + macro. + + * src/base/ftobjs.c (FT_Load_Glyph): Unset FT_LOAD_RENDER if + FT_LOAD_BITMAP_METRICS_ONLY is used. + + * src/sfnt/ttsbit.c (tt_sbit_decoder_alloc_bitmap, + tt_sbit_decoder_load_bitmap): Add argument to control allocation of + the glyph slot. + (tt_sbit_decoder_load_image, tt_sbit_decoder_load_compound, + tt_face_load_sbit_image): Updated. + + * src/pcf/pcfdrivr.c (PCF_Glyph_Load): Quickly exit if + `FT_LOAD_BITMAP_METRICS_ONLY' is set. + + * src/pfr/pfrsbit.c, src/pfr/pfrsbit.h (pfr_slot_load_bitmap): Add + argument to control allocation of the glyph slot. + * src/pfr/pfrobjs (pfr_slot_load): Updated. + + * src/winfonts/winfnt.c (FNT_Load_Glyph): Ditto. + + * docs/CHANGES: Updated. + +2016-11-06 Werner Lemberg Synchronize with gnulib (#49448). diff --git a/docs/CHANGES b/docs/CHANGES index 25e27400b..5b50fa23e 100644 --- a/docs/CHANGES +++ b/docs/CHANGES @@ -37,6 +37,9 @@ CHANGES BETWEEN 2.7 and 2.7.1 blend coordinates of the currently selected variation instance has been added to the Multiple Masters interface. + - A new load flag `FT_LOAD_BITMAP_METRICS_ONLY' to retrieve bitmap + information without loading the (embedded) bitmap itself. + ====================================================================== diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h index a81eb7232..49aa6f140 100644 --- a/include/freetype/freetype.h +++ b/include/freetype/freetype.h @@ -2802,6 +2802,14 @@ FT_BEGIN_HEADER * * Currently, this flag is only implemented for TrueType fonts. * + * FT_LOAD_BITMAP_METRICS_ONLY :: + * This flag is used to request loading of the metrics and bitmap + * image information of a (possibly embedded) bitmap glyph without + * allocating or copying the bitmap image data itself. No effect if + * the target glyph is not a bitmap image. + * + * This flag unsets @FT_LOAD_RENDER. + * * FT_LOAD_CROP_BITMAP :: * Ignored. Deprecated. * @@ -2848,6 +2856,7 @@ FT_BEGIN_HEADER /* Bits 16..19 are used by `FT_LOAD_TARGET_' */ #define FT_LOAD_COLOR ( 1L << 20 ) #define FT_LOAD_COMPUTE_METRICS ( 1L << 21 ) +#define FT_LOAD_BITMAP_METRICS_ONLY ( 1L << 22 ) /* */ diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index 9006b598b..060d78e0e 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -641,6 +641,9 @@ load_flags &= ~FT_LOAD_RENDER; } + if ( load_flags & FT_LOAD_BITMAP_METRICS_ONLY ) + load_flags &= ~FT_LOAD_RENDER; + /* * Determine whether we need to auto-hint or not. * The general rules are: diff --git a/src/pcf/pcfdrivr.c b/src/pcf/pcfdrivr.c index a0db8070f..476882ff9 100644 --- a/src/pcf/pcfdrivr.c +++ b/src/pcf/pcfdrivr.c @@ -492,8 +492,6 @@ THE SOFTWARE. PCF_Metric metric; FT_ULong bytes; - FT_UNUSED( load_flags ); - FT_TRACE1(( "PCF_Glyph_Load: glyph index %d\n", glyph_index )); @@ -550,6 +548,24 @@ THE SOFTWARE. return FT_THROW( Invalid_File_Format ); } + slot->format = FT_GLYPH_FORMAT_BITMAP; + slot->bitmap_left = metric->leftSideBearing; + slot->bitmap_top = metric->ascent; + + slot->metrics.horiAdvance = (FT_Pos)( metric->characterWidth * 64 ); + slot->metrics.horiBearingX = (FT_Pos)( metric->leftSideBearing * 64 ); + slot->metrics.horiBearingY = (FT_Pos)( metric->ascent * 64 ); + slot->metrics.width = (FT_Pos)( ( metric->rightSideBearing - + metric->leftSideBearing ) * 64 ); + slot->metrics.height = (FT_Pos)( bitmap->rows * 64 ); + + ft_synthesize_vertical_metrics( &slot->metrics, + ( face->accel.fontAscent + + face->accel.fontDescent ) * 64 ); + + if ( load_flags & FT_LOAD_BITMAP_METRICS_ONLY ) + goto Exit; + /* XXX: to do: are there cases that need repadding the bitmap? */ bytes = (FT_ULong)bitmap->pitch * bitmap->rows; @@ -582,21 +598,6 @@ THE SOFTWARE. } } - slot->format = FT_GLYPH_FORMAT_BITMAP; - slot->bitmap_left = metric->leftSideBearing; - slot->bitmap_top = metric->ascent; - - slot->metrics.horiAdvance = (FT_Pos)( metric->characterWidth * 64 ); - slot->metrics.horiBearingX = (FT_Pos)( metric->leftSideBearing * 64 ); - slot->metrics.horiBearingY = (FT_Pos)( metric->ascent * 64 ); - slot->metrics.width = (FT_Pos)( ( metric->rightSideBearing - - metric->leftSideBearing ) * 64 ); - slot->metrics.height = (FT_Pos)( bitmap->rows * 64 ); - - ft_synthesize_vertical_metrics( &slot->metrics, - ( face->accel.fontAscent + - face->accel.fontDescent ) * 64 ); - Exit: return error; } diff --git a/src/pfr/pfrobjs.c b/src/pfr/pfrobjs.c index 769a3b616..06996d6f3 100644 --- a/src/pfr/pfrobjs.c +++ b/src/pfr/pfrobjs.c @@ -342,7 +342,11 @@ /* try to load an embedded bitmap */ if ( ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) == 0 ) { - error = pfr_slot_load_bitmap( slot, size, gindex ); + error = pfr_slot_load_bitmap( + slot, + size, + gindex, + ( load_flags & FT_LOAD_BITMAP_METRICS_ONLY ) != 0 ); if ( error == 0 ) goto Exit; } diff --git a/src/pfr/pfrsbit.c b/src/pfr/pfrsbit.c index 144f50c0b..f9dbf734b 100644 --- a/src/pfr/pfrsbit.c +++ b/src/pfr/pfrsbit.c @@ -578,7 +578,8 @@ FT_LOCAL( FT_Error ) pfr_slot_load_bitmap( PFR_Slot glyph, PFR_Size size, - FT_UInt glyph_index ) + FT_UInt glyph_index, + FT_Bool metrics_only ) { FT_Error error; PFR_Face face = (PFR_Face) glyph->root.face; @@ -775,6 +776,9 @@ glyph->root.bitmap_left = (FT_Int)xpos; glyph->root.bitmap_top = (FT_Int)( ypos + (FT_Long)ysize ); + if ( metrics_only ) + goto Exit1; + /* Allocate and read bitmap data */ { FT_ULong len = (FT_ULong)glyph->root.bitmap.pitch * ysize; diff --git a/src/pfr/pfrsbit.h b/src/pfr/pfrsbit.h index 94ead28ca..676ad55a9 100644 --- a/src/pfr/pfrsbit.h +++ b/src/pfr/pfrsbit.h @@ -26,7 +26,8 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) pfr_slot_load_bitmap( PFR_Slot glyph, PFR_Size size, - FT_UInt glyph_index ); + FT_UInt glyph_index, + FT_Bool metrics_only ); FT_END_HEADER diff --git a/src/sfnt/ttsbit.c b/src/sfnt/ttsbit.c index b5986aa7c..8d8b9e73c 100644 --- a/src/sfnt/ttsbit.c +++ b/src/sfnt/ttsbit.c @@ -536,7 +536,8 @@ static FT_Error - tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder decoder ) + tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder decoder, + FT_Bool metrics_only ) { FT_Error error = FT_Err_Ok; FT_UInt width, height; @@ -599,6 +600,9 @@ if ( size == 0 ) goto Exit; /* exit successfully! */ + if ( metrics_only ) + goto Exit; /* only metrics are requested */ + error = ft_glyphslot_alloc_bitmap( decoder->face->root.glyph, size ); if ( error ) goto Exit; @@ -665,7 +669,8 @@ FT_UInt glyph_index, FT_Int x_pos, FT_Int y_pos, - FT_UInt recurse_count ); + FT_UInt recurse_count, + FT_Bool metrics_only ); typedef FT_Error (*TT_SBitDecoder_LoadFunc)( TT_SBitDecoder decoder, @@ -995,7 +1000,9 @@ gindex, x_pos + dx, y_pos + dy, - recurse_count + 1 ); + recurse_count + 1, + /* request full bitmap image */ + FALSE ); if ( error ) break; } @@ -1077,7 +1084,8 @@ FT_ULong glyph_size, FT_Int x_pos, FT_Int y_pos, - FT_UInt recurse_count ) + FT_UInt recurse_count, + FT_Bool metrics_only ) { FT_Error error; FT_Stream stream = decoder->stream; @@ -1199,11 +1207,15 @@ if ( !decoder->bitmap_allocated ) { - error = tt_sbit_decoder_alloc_bitmap( decoder ); + error = tt_sbit_decoder_alloc_bitmap( decoder, metrics_only ); + if ( error ) goto Fail; } + if ( metrics_only ) + goto Fail; /* this is not an error */ + error = loader( decoder, p, p_limit, x_pos, y_pos, recurse_count ); } @@ -1220,7 +1232,8 @@ FT_UInt glyph_index, FT_Int x_pos, FT_Int y_pos, - FT_UInt recurse_count ) + FT_UInt recurse_count, + FT_Bool metrics_only ) { FT_Byte* p = decoder->eblc_base + decoder->strike_index_array; FT_Byte* p_limit = decoder->eblc_limit; @@ -1405,7 +1418,8 @@ image_end, x_pos, y_pos, - recurse_count ); + recurse_count, + metrics_only ); Failure: return FT_THROW( Invalid_Table ); @@ -1567,11 +1581,13 @@ error = tt_sbit_decoder_init( decoder, face, strike_index, metrics ); if ( !error ) { - error = tt_sbit_decoder_load_image( decoder, - glyph_index, - 0, - 0, - 0 ); + error = tt_sbit_decoder_load_image( + decoder, + glyph_index, + 0, + 0, + 0, + ( load_flags & FT_LOAD_BITMAP_METRICS_ONLY ) != 0 ); tt_sbit_decoder_done( decoder ); } } @@ -1592,9 +1608,10 @@ } /* Flatten color bitmaps if color was not requested. */ - if ( !error && - !( load_flags & FT_LOAD_COLOR ) && - map->pixel_mode == FT_PIXEL_MODE_BGRA ) + if ( !error && + !( load_flags & FT_LOAD_COLOR ) && + !( load_flags & FT_LOAD_BITMAP_METRICS_ONLY ) && + map->pixel_mode == FT_PIXEL_MODE_BGRA ) { FT_Bitmap new_map; FT_Library library = face->root.glyph->library; diff --git a/src/winfonts/winfnt.c b/src/winfonts/winfnt.c index b412f105d..99cc96617 100644 --- a/src/winfonts/winfnt.c +++ b/src/winfonts/winfnt.c @@ -1000,8 +1000,6 @@ FT_ULong offset; FT_Bool new_format; - FT_UNUSED( load_flags ); - if ( !face ) { @@ -1055,6 +1053,26 @@ goto Exit; } + bitmap->rows = font->header.pixel_height; + bitmap->pixel_mode = FT_PIXEL_MODE_MONO; + + slot->bitmap_left = 0; + slot->bitmap_top = font->header.ascent; + slot->format = FT_GLYPH_FORMAT_BITMAP; + + /* now set up metrics */ + slot->metrics.width = (FT_Pos)( bitmap->width << 6 ); + slot->metrics.height = (FT_Pos)( bitmap->rows << 6 ); + slot->metrics.horiAdvance = (FT_Pos)( bitmap->width << 6 ); + slot->metrics.horiBearingX = 0; + slot->metrics.horiBearingY = slot->bitmap_top << 6; + + ft_synthesize_vertical_metrics( &slot->metrics, + (FT_Pos)( bitmap->rows << 6 ) ); + + if ( load_flags & FT_LOAD_BITMAP_METRICS_ONLY ) + goto Exit; + /* jump to glyph data */ p = font->fnt_frame + /* font->header.bits_offset */ + offset; @@ -1066,10 +1084,7 @@ FT_Byte* write; - bitmap->pitch = (int)pitch; - bitmap->rows = font->header.pixel_height; - bitmap->pixel_mode = FT_PIXEL_MODE_MONO; - + bitmap->pitch = (int)pitch; if ( !pitch || offset + pitch * bitmap->rows > font->header.file_size ) { @@ -1093,23 +1108,10 @@ for ( write = column; p < limit; p++, write += bitmap->pitch ) *write = *p; } + + slot->internal->flags = FT_GLYPH_OWN_BITMAP; } - slot->internal->flags = FT_GLYPH_OWN_BITMAP; - slot->bitmap_left = 0; - slot->bitmap_top = font->header.ascent; - slot->format = FT_GLYPH_FORMAT_BITMAP; - - /* now set up metrics */ - slot->metrics.width = (FT_Pos)( bitmap->width << 6 ); - slot->metrics.height = (FT_Pos)( bitmap->rows << 6 ); - slot->metrics.horiAdvance = (FT_Pos)( bitmap->width << 6 ); - slot->metrics.horiBearingX = 0; - slot->metrics.horiBearingY = slot->bitmap_top << 6; - - ft_synthesize_vertical_metrics( &slot->metrics, - (FT_Pos)( bitmap->rows << 6 ) ); - Exit: return error; }