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.
This commit is contained in:
Werner Lemberg 2016-11-06 12:32:51 +01:00
parent 57f73d1f77
commit 37e193e935
10 changed files with 134 additions and 57 deletions

View File

@ -1,4 +1,37 @@
2016-10-29 Werner Lemberg <wl@gnu.org>
2016-11-06 Seigo Nonaka <nona@google.com>
Werner Lemberg <wl@gnu.org>
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 <wl@gnu.org>
Synchronize with gnulib (#49448).

View File

@ -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.
======================================================================

View File

@ -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 )
/* */

View File

@ -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:

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;
}