[psaux] Improve `t1_decoder_parse_metrics' (#58646).

* src/psaux/t1decode.c (t1_decoder_parse_metrics): Copy
corresponding code from old engine's `t1_decoder_parse_charstrings'
function to handle `op_callsubr' and `op_return'.
This commit is contained in:
Werner Lemberg 2020-07-06 09:21:03 +02:00
parent b0667d2d36
commit 2eb8f88626
2 changed files with 116 additions and 11 deletions

View File

@ -1,3 +1,11 @@
2020-07-06 Werner Lemberg <wl@gnu.org>
[psaux] Improve `t1_decoder_parse_metrics' (#58646).
* src/psaux/t1decode.c (t1_decoder_parse_metrics): Copy
corresponding code from old engine's `t1_decoder_parse_charstrings'
function to handle `op_callsubr' and `op_return'.
2020-07-05 David Turner <david@freetype.org>
[build] Improve visibility support of library function names.

View File

@ -1237,8 +1237,8 @@
FT_UNUSED( orig_y );
/* the `metrics_only' indicates that we only want to compute */
/* the glyph's metrics (lsb + advance width), not load the */
/* `metrics_only' indicates that we only want to compute the */
/* glyph's metrics (lsb + advance width) without loading the */
/* rest of it; so exit immediately */
if ( builder->metrics_only )
{
@ -1272,8 +1272,8 @@
x = ADD_LONG( builder->pos_x, top[0] );
y = ADD_LONG( builder->pos_y, top[1] );
/* the `metrics_only' indicates that we only want to compute */
/* the glyph's metrics (lsb + advance width), not load the */
/* `metrics_only' indicates that we only want to compute the */
/* glyph's metrics (lsb + advance width) without loading the */
/* rest of it; so exit immediately */
if ( builder->metrics_only )
{
@ -1749,8 +1749,6 @@
case 7:
case 8:
case 9:
case 10:
case 11:
case 14:
case 15:
case 21:
@ -1759,6 +1757,13 @@
case 31:
goto No_Width;
case 10:
op = op_callsubr;
break;
case 11:
op = op_return;
break;
case 13:
op = op_hsbw;
break;
@ -1898,13 +1903,20 @@
#ifdef FT_DEBUG_LEVEL_TRACE
if ( op != op_div )
switch ( op )
{
case op_callsubr:
case op_div:
case op_return:
break;
default:
if ( top - decoder->stack != num_args )
FT_TRACE0(( "t1_decoder_parse_metrics:"
" too much operands on the stack"
" (seen %d, expected %d)\n",
top - decoder->stack, num_args ));
break;
}
#endif /* FT_DEBUG_LEVEL_TRACE */
@ -1925,8 +1937,8 @@
builder->advance.y = 0;
/* we only want to compute the glyph's metrics */
/* (lsb + advance width), not load the rest of */
/* it; so exit immediately */
/* (lsb + advance width) without loading the */
/* rest of it; so exit immediately */
FT_TRACE4(( "\n" ));
return FT_Err_Ok;
@ -1944,8 +1956,8 @@
builder->advance.y = top[3];
/* we only want to compute the glyph's metrics */
/* (lsb + advance width), not load the rest of */
/* it; so exit immediately */
/* (lsb + advance width), without loading the */
/* rest of it; so exit immediately */
FT_TRACE4(( "\n" ));
return FT_Err_Ok;
@ -1961,6 +1973,91 @@
large_int = FALSE;
break;
case op_callsubr:
{
FT_Int idx;
FT_TRACE4(( " callsubr" ));
idx = Fix2Int( top[0] );
if ( decoder->subrs_hash )
{
size_t* val = ft_hash_num_lookup( idx,
decoder->subrs_hash );
if ( val )
idx = *val;
else
idx = -1;
}
if ( idx < 0 || idx >= decoder->num_subrs )
{
FT_ERROR(( "t1_decoder_parse_metrics:"
" invalid subrs index\n" ));
goto Syntax_Error;
}
if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
{
FT_ERROR(( "t1_decoder_parse_metrics:"
" too many nested subrs\n" ));
goto Syntax_Error;
}
zone->cursor = ip; /* save current instruction pointer */
zone++;
/* The Type 1 driver stores subroutines without the seed bytes. */
/* The CID driver stores subroutines with seed bytes. This */
/* case is taken care of when decoder->subrs_len == 0. */
zone->base = decoder->subrs[idx];
if ( decoder->subrs_len )
zone->limit = zone->base + decoder->subrs_len[idx];
else
{
/* We are using subroutines from a CID font. We must adjust */
/* for the seed bytes. */
zone->base += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
zone->limit = decoder->subrs[idx + 1];
}
zone->cursor = zone->base;
if ( !zone->base )
{
FT_ERROR(( "t1_decoder_parse_metrics:"
" invoking empty subrs\n" ));
goto Syntax_Error;
}
decoder->zone = zone;
ip = zone->base;
limit = zone->limit;
break;
}
case op_return:
FT_TRACE4(( " return" ));
if ( zone <= decoder->zones )
{
FT_ERROR(( "t1_decoder_parse_metrics:"
" unexpected return\n" ));
goto Syntax_Error;
}
zone--;
ip = zone->cursor;
limit = zone->limit;
decoder->zone = zone;
break;
default:
FT_ERROR(( "t1_decoder_parse_metrics:"
" unhandled opcode %d\n", op ));