integrated Yamano-Uchi changes to the base source code. However,

I've made a few modifications:

  - there is no new field named "driver" in "FT_SizeRec"

  - the new fields in "TT_SizeRec" are:

       strike_index   :: value 0xFFFF means "no sbit strike selected"
       strike_metrics :: the FT_Size_Metrics structure corresponding to
                         the currently selected strike

  - the code in "ttload.c" has been somewhat cleaned up too

thanks a lot, Y-U !!

- David
This commit is contained in:
David Turner 2000-11-06 23:07:51 +00:00
parent d18440f14d
commit f96594faf0
14 changed files with 326 additions and 152 deletions

View File

@ -877,16 +877,6 @@
/* to scale vertical distances expressed in font */
/* units to fractional (26.6) pixel coordinates. */
/* */
/* x_resolution :: The horizontal device resolution for this size */
/* object, expressed in integer dots per inches */
/* (dpi). As a convention, fixed font formats set */
/* this value to 72. */
/* */
/* y_resolution :: The vertical device resolution for this size */
/* object, expressed in integer dots per inches */
/* (dpi). As a convention, fixed font formats set */
/* this value to 72. */
/* */
/* ascender :: The ascender, expressed in 26.6 fixed point */
/* pixels. Always positive. */
/* */

View File

@ -281,14 +281,18 @@
/* */
typedef
FT_Error (*TT_Load_SBit_Image_Func)( TT_Face face,
FT_Int x_ppem,
FT_Int y_ppem,
FT_ULong strike_index,
FT_UInt glyph_index,
FT_UInt load_flags,
FT_Stream stream,
FT_Bitmap* map,
TT_SBit_Metrics* metrics );
typedef
FT_Error (*TT_Set_SBit_Strike_Func)( TT_Face face,
FT_Int x_ppem,
FT_Int y_ppem,
FT_ULong* astrike_index );
/*************************************************************************/
/* */
@ -473,8 +477,10 @@
TT_Load_Table_Func load_kerning;
TT_Load_Table_Func load_gasp;
TT_Load_Table_Func load_pclt;
TT_Load_Table_Func load_pclt;
TT_Load_Table_Func load_bitmap_header;
TT_Set_SBit_Strike_Func set_sbit_strike;
/* see `ttsbit.h' */
TT_Load_Table_Func load_sbits;
TT_Load_SBit_Image_Func load_sbit_image;

View File

@ -492,7 +492,7 @@
/* <Description> */
/* A structure used to hold the big metrics of a given glyph bitmap */
/* in a TrueType or OpenType font. These are usually found in the */
/* `EBDT' (Microsoft) or `bdat' (Apple) table. */
/* `EBDT' (Microsoft) or `bloc' (Apple) table. */
/* */
/* <Fields> */
/* height :: The glyph height in pixels. */
@ -700,7 +700,11 @@
/* */
/* index_ranges :: An array of glyph index ranges. */
/* */
/* color_ref :: Unused. A color reference? */
/* color_ref :: Unused. color_ref is put in for future */
/* enhancements, but these fields are already */
/* in use by other platforms (e.g. Newton). */
/* For details, please see */
/* http://fonts.apple.com/TTRefMan/RM06/Chap6bloc.html */
/* */
/* hori :: The line metrics for horizontal layouts. */
/* */
@ -718,6 +722,8 @@
/* and 8. */
/* */
/* flags :: Is this a vertical or horizontal strike? */
/* For details, please see */
/* http://fonts.apple.com/TTRefMan/RM06/Chap6bloc.html */
/* */
typedef struct TT_SBit_Strike_
{
@ -760,7 +766,6 @@
typedef struct TT_SBit_Component_
{
FT_UShort glyph_code;
FT_Char x_offset;
FT_Char y_offset;

View File

@ -32,6 +32,7 @@
#define TTAG_cvt FT_MAKE_TAG( 'c', 'v', 't', ' ' )
#define TTAG_CFF FT_MAKE_TAG( 'C', 'F', 'F', ' ' )
#define TTAG_DSIG FT_MAKE_TAG( 'D', 'S', 'I', 'G' )
#define TTAG_bhed FT_MAKE_TAG( 'b', 'h', 'e', 'd' )
#define TTAG_bdat FT_MAKE_TAG( 'b', 'd', 'a', 't' )
#define TTAG_bloc FT_MAKE_TAG( 'b', 'l', 'o', 'c' )
#define TTAG_EBDT FT_MAKE_TAG( 'E', 'B', 'D', 'T' )

View File

@ -172,7 +172,11 @@
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
/* see `ttload.h` */
TT_Load_Bitmap_Header,
/* see `ttsbit.h' */
TT_Set_SBit_Strike,
TT_Load_SBit_Strikes,
TT_Load_SBit_Image,
TT_Free_SBit_Strikes,
@ -182,6 +186,8 @@
0,
0,
0,
0,
0,
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */

View File

@ -255,7 +255,9 @@
FT_Parameter* params )
{
FT_Error error;
FT_Bool missing_outline = 0;
FT_Bool has_outline;
FT_Bool is_apple_sbit;
SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt;
FT_UNUSED( face_index );
@ -265,39 +267,63 @@
/* Load tables */
/* If you load SFNT wrapped sbit font files, it will fail if you */
/* want to read the `head', `hhea', and `vhea' tables. */
/* */
if ( LOAD_( header ) )
{
/* we now support two SFNT-based bitmapped font formats. */
/* they are recognized easily as they do not include a "glyf" */
/* table.. */
/* */
/* the first format comes from Apple, and uses a table named */
/* "bhed" instead of "head" to store the font header (using */
/* the same format). it also doesn't include horizontal and */
/* vertical metrics tables (i.e. "hhea" and "vhea" tables) */
/* */
/* the other format comes from Microsoft, and is used with */
/* WinCE / PocketPC. It's standard, except that it doesn't */
/* contain outlines.. */
/* */
/* do we have outlines in there ?? */
has_outline = (TT_LookUp_Table( face, TTAG_glyf ) != 0);
is_apple_sbit = 0;
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
missing_outline = 1;
#else
goto Exit;
/*
* if this font doesn't contain outlines, we'll try to load
* a "bhed" table in it..
*/
if ( !has_outline )
is_apple_sbit = !LOAD_(bitmap_header);
#endif
}
/* load the font header ("head" table) if this isn't an Apple */
/* sbit font file.. */
if ( !is_apple_sbit && LOAD_(header) )
goto Exit;
/* load other tables */
if ( LOAD_( max_profile ) ||
LOAD_( charmaps ) ||
LOAD_( names ) ||
LOAD_( psnames ) )
goto Exit;
if ( /* load the `hhea' & `hmtx' tables at once */
( ( error = sfnt->load_metrics( face, stream, 0 ) ) != TT_Err_Ok ) ||
/* try to load the `vhea' & `vmtx' at once if present */
( ( error = sfnt->load_metrics( face, stream, 1 ) ) != TT_Err_Ok ) ||
LOAD_( os2 ) )
/* do not load the metrics headers and tables if this is an Apple */
/* sbit font file.. */
if ( !is_apple_sbit )
{
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
missing_outline = 1;
#else
goto Exit;
#endif
/* load the "hhea" and "hmtx" tables at once */
error = sfnt->load_metrics( face, stream, 0 );
if (error)
goto Exit;
/* try to load the "vhea" and "vmtx" tables at once */
error = sfnt->load_metrics( face, stream, 1 );
if (error)
goto Exit;
if ( LOAD_(os2) )
goto Exit;
}
/* the optional tables */
@ -307,11 +333,12 @@
/* embedded bitmap support. */
if ( sfnt->load_sbits && LOAD_( sbits ) )
{
if ( !( ( error == TT_Err_Table_Missing ) && /* missing SBit */
( missing_outline == 0 ) ) ) /* find outline */
/* return an error if this font file has no outlines */
if ( error == TT_Err_Table_Missing && has_outline )
error = 0;
else
goto Exit;
}
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
if ( LOAD_( hdmx ) ||
@ -343,7 +370,7 @@
/* */
/* Compute face flags. */
/* */
if ( missing_outline == 0 )
if ( has_outline == TRUE )
flags = FT_FACE_FLAG_SCALABLE; /* scalable outlines */
flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */
@ -374,26 +401,23 @@
/* Compute style flags. */
/* */
flags = 0;
if ( missing_outline == 0 )
if ( has_outline == TRUE && face->os2.version != 0xFFFF )
{
if ( face->os2.version != 0xFFFF )
{
/* we have an OS/2 table; use the `fsSelection' field */
if ( face->os2.fsSelection & 1 )
flags |= FT_STYLE_FLAG_ITALIC;
/* we have an OS/2 table; use the `fsSelection' field */
if ( face->os2.fsSelection & 1 )
flags |= FT_STYLE_FLAG_ITALIC;
if ( face->os2.fsSelection & 32 )
flags |= FT_STYLE_FLAG_BOLD;
}
else
{
/* this is an old Mac font, use the header field */
if ( face->header.Mac_Style & 1 )
flags |= FT_STYLE_FLAG_BOLD;
if ( face->os2.fsSelection & 32 )
flags |= FT_STYLE_FLAG_BOLD;
}
else
{
/* this is an old Mac font, use the header field */
if ( face->header.Mac_Style & 1 )
flags |= FT_STYLE_FLAG_BOLD;
if ( face->header.Mac_Style & 2 )
flags |= FT_STYLE_FLAG_ITALIC;
}
if ( face->header.Mac_Style & 2 )
flags |= FT_STYLE_FLAG_ITALIC;
}
root->style_flags = flags;
@ -437,24 +461,27 @@
if ( face->num_sbit_strikes )
{
root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
#if 0
/* I don't know criteria whether layout is horizontal or vertical */
if ( missing_outline )
if ( has_outline.... )
{
...
root->face_flags |= FT_FACE_FLAG_VERTICAL;
}
#endif
root->num_fixed_sizes = face->num_sbit_strikes;
if ( ALLOC_ARRAY( root->available_sizes,
face->num_sbit_strikes,
FT_Bitmap_Size ) )
return error;
goto Exit;
for ( n = 0 ; n < face->num_sbit_strikes ; n++ )
{
root->available_sizes[n].width =
face->sbit_strikes[n].x_ppem;
root->available_sizes[n].height =
face->sbit_strikes[n].y_ppem;
}
@ -464,15 +491,15 @@
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
{
root->num_fixed_sizes = 0;
root->available_sizes = 0;
root->num_fixed_sizes = 0;
root->available_sizes = 0;
}
/*********************************************************************/
/* */
/* Set up metrics. */
/* */
if ( missing_outline == 0 )
if ( has_outline == TRUE )
{
/* XXX What about if outline header is missing */
/* (e.g. sfnt wrapped outline)? */

View File

@ -458,9 +458,10 @@
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF
FT_Error TT_Load_Header( TT_Face face,
FT_Stream stream )
static
FT_Error TT_Load_Generic_Header( TT_Face face,
FT_Stream stream,
FT_ULong tag )
{
FT_Error error;
TT_Header* header;
@ -496,7 +497,7 @@
FT_TRACE2(( "Load_TT_Header: %08p\n", face ));
error = face->goto_table( face, TTAG_head, stream, 0 );
error = face->goto_table( face, tag, stream, 0 );
if ( error )
{
FT_TRACE0(( "Font Header is missing!\n" ));
@ -516,6 +517,21 @@
return error;
}
FT_LOCAL_DEF
FT_Error TT_Load_Header( TT_Face face,
FT_Stream stream )
{
return TT_Load_Generic_Header( face, stream, TTAG_head );
}
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
FT_LOCAL_DEF
FT_Error TT_Load_Bitmap_Header( TT_Face face,
FT_Stream stream )
{
return TT_Load_Generic_Header( face, stream, TTAG_bhed );
}
#endif
/*************************************************************************/
/* */

View File

@ -120,6 +120,11 @@
FT_Error TT_Load_Gasp( TT_Face face,
FT_Stream stream );
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
FT_LOCAL
FT_Error TT_Load_Bitmap_Header( TT_Face face,
FT_Stream stream );
#endif
#ifdef __cplusplus
}

View File

@ -627,6 +627,32 @@
face->num_sbit_strikes = 0;
}
FT_LOCAL_DEF
FT_Error TT_Set_SBit_Strike( TT_Face face,
FT_Int x_ppem,
FT_Int y_ppem,
FT_ULong* astrike_index )
{
FT_Int i;
if ( x_ppem < 0 || x_ppem > 255 ||
y_ppem < 1 || y_ppem > 255 )
return TT_Err_Invalid_PPem;
for ( i = 0; i < face->num_sbit_strikes; i++ )
{
if ( ( face->sbit_strikes[i].y_ppem == y_ppem ) &&
( ( x_ppem == 0 ) ||
( face->sbit_strikes[i].x_ppem == x_ppem )))
{
*astrike_index = i;
return TT_Err_Ok;
}
}
return TT_Err_Invalid_PPem;
}
/*************************************************************************/
/* */
@ -736,13 +762,12 @@
/* */
/* <Description> */
/* Checks whether an embedded bitmap (an `sbit') exists for a given */
/* glyph, at given x and y ppems. */
/* glyph, at a given strike. */
/* */
/* <Input> */
/* face :: The target face object. */
/* glyph_index :: The glyph index. */
/* x_ppem :: The horizontal resolution in points per EM. */
/* y_ppem :: The vertical resolution in points per EM. */
/* strike_index :: The current strike index. */
/* */
/* <Output> */
/* arange :: The SBit range containing the glyph index. */
@ -756,37 +781,27 @@
static
FT_Error Find_SBit_Image( TT_Face face,
FT_UInt glyph_index,
FT_Int x_ppem,
FT_Int y_ppem,
FT_ULong strike_index,
TT_SBit_Range** arange,
TT_SBit_Strike** astrike,
FT_ULong* aglyph_offset )
{
TT_SBit_Strike* strike = face->sbit_strikes;
TT_SBit_Strike* strike_limit = strike + face->num_sbit_strikes;
FT_Error error;
TT_SBit_Strike* strike;
if ( !strike )
if ( !face->sbit_strikes || ( face->num_sbit_strikes <= (FT_Int)strike_index ) )
goto Fail;
for ( ; strike < strike_limit; strike++ )
{
if ( strike->x_ppem == x_ppem && strike->y_ppem == y_ppem )
{
FT_Error error;
strike = &face->sbit_strikes[strike_index];
error = Find_SBit_Range( glyph_index, strike,
arange, aglyph_offset );
if ( error )
goto Fail;
error = Find_SBit_Range( glyph_index, strike,
arange, aglyph_offset );
if ( error )
goto Fail;
*astrike = strike;
*astrike = strike;
return TT_Err_Ok;
}
}
return TT_Err_Ok;
Fail:
/* no embedded bitmap for this glyph in face */
@ -1353,9 +1368,7 @@
/* <Input> */
/* face :: The target face object. */
/* */
/* x_ppem :: The horizontal resolution in points per EM. */
/* */
/* y_ppem :: The vertical resolution in points per EM. */
/* strike_index :: The current strike index. */
/* */
/* glyph_index :: The current glyph index. */
/* */
@ -1378,8 +1391,7 @@
/* */
FT_LOCAL_DEF
FT_Error TT_Load_SBit_Image( TT_Face face,
FT_Int x_ppem,
FT_Int y_ppem,
FT_ULong strike_index,
FT_UInt glyph_index,
FT_UInt load_flags,
FT_Stream stream,
@ -1395,7 +1407,7 @@
/* Check whether there is a glyph sbit for the current index */
error = Find_SBit_Image( face, glyph_index, x_ppem, y_ppem,
error = Find_SBit_Image( face, glyph_index, strike_index,
&range, &strike, &glyph_offset );
if ( error )
goto Exit;

View File

@ -41,17 +41,24 @@
FT_Stream stream );
FT_LOCAL
void TT_Free_SBit_Strikes( TT_Face face );
void TT_Free_SBit_Strikes( TT_Face face );
FT_LOCAL
FT_Error TT_Set_SBit_Strike( TT_Face face,
FT_Int x_ppem,
FT_Int y_ppem,
FT_ULong *astrike_index );
FT_LOCAL
FT_Error TT_Load_SBit_Image( TT_Face face,
FT_Int x_ppem,
FT_Int y_ppem,
FT_ULong strike_index,
FT_UInt glyph_index,
FT_UInt load_flags,
FT_Stream stream,
FT_Bitmap* map,
TT_SBit_Metrics* metrics );
FT_Bitmap *map,
TT_SBit_Metrics *metrics );
#ifdef __cplusplus

View File

@ -225,6 +225,7 @@
}
size->ttmetrics.valid = FALSE;
size->strike_index = 0xFFFF;
return TT_Reset_Size( size );
}
@ -261,6 +262,7 @@
/* many things have been pre-computed by the base layer */
size->ttmetrics.valid = FALSE;
size->strike_index = 0xFFFF;
return TT_Reset_Size( size );
}

View File

@ -1345,18 +1345,24 @@
glyph->num_subglyphs = 0;
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
/* try to load embedded bitmap if any */
/*
* try to load embedded bitmap if any
*
* XXX: The convention should be emphasized in
* the documents. Because some application
* developpers confuse.
*/
if ( size &&
( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
sfnt->load_sbits )
size->strike_index != 0xFFFF &&
sfnt->load_sbits &&
( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
{
TT_SBit_Metrics metrics;
error = sfnt->load_sbit_image( face,
size->root.metrics.x_ppem,
size->root.metrics.y_ppem,
size->strike_index,
glyph_index,
load_flags,
stream,

View File

@ -453,7 +453,7 @@
size->ttmetrics.valid = FALSE;
return error;
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
#if defined(TT_CONFIG_OPTION_BYTECODE_INTERPRETER) || defined(TT_CONFIG_OPTION_EMBEDDED_BITMAPS)
Fail_Exec:
if ( !size->debug )
@ -535,8 +535,8 @@
/* <Input> */
/* size :: A handle to the target size object. */
/* */
FT_LOCAL
FT_Error TT_Reset_Size( TT_Size size )
static
FT_Error Reset_Outline_Size( TT_Size size )
{
TT_Face face;
FT_Error error = TT_Err_Ok;
@ -575,46 +575,6 @@
}
/* Compute root ascender, descender, test height, and max_advance */
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
if ( ( !( face->root.face_flags & FT_FACE_FLAG_SCALABLE ) &&
( face->root.face_flags & FT_FACE_FLAG_FIXED_SIZES ) ) )
{
FT_Int i;
for ( i = 0; i < face->root.num_fixed_sizes; i++ )
{
if ( ( face->sbit_strikes[i].x_ppem == metrics->x_ppem ) &&
( face->sbit_strikes[i].y_ppem == metrics->y_ppem ) )
{
/*
* XXX: We now set horizontal metrics,
* but this is not valid if we use vertical layout style
*/
metrics->ascender =
face->sbit_strikes[i].hori.ascender * 64;
metrics->descender =
face->sbit_strikes[i].hori.descender * 64;
metrics->height =
( face->sbit_strikes[i].hori.ascender -
face->sbit_strikes[i].hori.descender ) * 64;
/* XXX: Is this correct? */
metrics->max_advance =
( face->sbit_strikes[i].hori.min_origin_SB +
face->sbit_strikes[i].hori.max_width +
face->sbit_strikes[i].hori.min_advance_SB ) * 64;
break;
}
}
if ( i == face->root.num_fixed_sizes )
return TT_Err_Invalid_PPem;
}
else
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
{
metrics->ascender = ( FT_MulFix( face->root.ascender,
metrics->y_scale ) + 32 ) & -64;
@ -628,6 +588,11 @@
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
/* set to "invalid" by default */
size->strike_index = 0xFFFF;
#endif
{
TT_ExecContext exec;
FT_UInt i, j;
@ -708,6 +673,126 @@
return error;
}
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
static
FT_Error Reset_SBit_Size( TT_Size size )
{
TT_Face face;
FT_Error error = TT_Err_Ok;
FT_ULong strike_index;
FT_Size_Metrics* metrics;
FT_Size_Metrics* sbit_metrics;
SFNT_Interface* sfnt;
metrics = &size->root.metrics;
if (size->strike_index != 0xFFFF)
return TT_Err_Ok;
face = (TT_Face)size->root.face;
sfnt = (SFNT_Interface*)face->sfnt;
sbit_metrics = &size->strike_metrics;
error = sfnt->set_sbit_strike(face,
metrics->x_ppem, metrics->y_ppem,
&strike_index);
if (!error)
{
TT_SBit_Strike* strike = face->sbit_strikes + strike_index;
sbit_metrics->x_ppem = metrics->x_ppem;
sbit_metrics->y_ppem = metrics->y_ppem;
#if 0
/*
* sbit_metrics->?_scale
* are not used now.
*/
sbit_metrics->x_scale = 1 << 16;
sbit_metrics->y_scale = 1 << 16;
#endif
sbit_metrics->ascender = strike->hori.ascender << 6;
sbit_metrics->descender = strike->hori.descender << 6;
/* XXX: Is this correct? */
sbit_metrics->height = sbit_metrics->ascender -
sbit_metrics->descender;
/* XXX: Is this correct? */
sbit_metrics->max_advance = ( strike->hori.min_origin_SB +
strike->hori.max_width +
strike->hori.min_advance_SB ) << 6;
size->strike_index = strike_index;
}
else
{
size->strike_index = 0xFFFF;
sbit_metrics->x_ppem = 0;
sbit_metrics->y_ppem = 0;
sbit_metrics->ascender = 0;
sbit_metrics->descender = 0;
sbit_metrics->height = 0;
sbit_metrics->max_advance = 0;
}
return error;
}
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
/*************************************************************************/
/* */
/* <Function> */
/* TT_Reset_Size */
/* */
/* <Description> */
/* Resets a TrueType size when resolutions and character dimensions */
/* have been changed. */
/* */
/* <Input> */
/* size :: A handle to the target size object. */
/* */
FT_LOCAL_DEF
FT_Error TT_Reset_Size( TT_Size size )
{
FT_Face face;
FT_Error error = TT_Err_Ok;
face = size->root.face;
if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
{
if ( !size->ttmetrics.valid )
error = Reset_Outline_Size( size );
if ( error )
return error;
}
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
if ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES )
{
FT_Size_Metrics* sbit_metrics;
if ( size->strike_index == 0xFFFF )
error = Reset_SBit_Size( size );
sbit_metrics = &size->strike_metrics;
if ((!error) && !( face->face_flags & FT_FACE_FLAG_SCALABLE ))
size->root.metrics = *sbit_metrics;
}
#endif
if (face->face_flags & FT_FACE_FLAG_SCALABLE)
return TT_Err_Ok;
else
return error;
}
/*************************************************************************/
/* */

View File

@ -305,6 +305,7 @@
} TT_Size_Metrics;
/*************************************************************************/
/* */
/* TrueType size class. */
@ -315,6 +316,11 @@
TT_Size_Metrics ttmetrics;
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
FT_UInt strike_index; /* 0xFFFF to indicate invalid */
FT_Size_Metrics strike_metrics; /* current strike's metrics */
#endif
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
FT_UInt num_function_defs; /* number of function definitions */