Extract width parsing from Type 1 parser.

Duplicate the fast advance width calculations from the old parser. This
is to facilitate adding options for compiling out the old parser.

* src/psaux/t1decode.{c,h} (t1_decoder_parse_metrics): New function.
* include/freetype/internal/psaux.h (T1_Decoder_Funcs): New entry
`parse_metrics'.
* src/psaux/psauxmod.c: Set the new entry.

* src/type1/t1gload.c (T1_Parse_Glyph_And_Get_Char_String),
src/cid/cidgload.c (cid_load_glyph): Separate
conditional for selecting engine.
This commit is contained in:
Ewald Hew 2017-10-12 18:13:08 +08:00
parent 8768536c89
commit 78df3c27b6
7 changed files with 313 additions and 0 deletions

View File

@ -1,3 +1,19 @@
2017-10-12 Ewald Hew <ewaldhew@gmail.com>
Extract width parsing from Type 1 parser.
Duplicate the fast advance width calculations from the old parser.
This is to facilitate adding options for compiling out the old parser.
* src/psaux/t1decode.{c,h} (t1_decoder_parse_metrics): New function.
* include/freetype/internal/psaux.h (T1_Decoder_Funcs): New entry
`parse_metrics'.
* src/psaux/psauxmod.c: Set the new entry.
* src/type1/t1gload.c (T1_Parse_Glyph_And_Get_Char_String),
src/cid/cidgload.c (cid_load_glyph): Separate
conditional for selecting engine.
2017-10-09 Werner Lemberg <wl@gnu.org>
* src/base/ftoutln.c (FT_Outline_Translate): Fix integer overflow.

View File

@ -879,6 +879,11 @@ FT_BEGIN_HEADER
FT_Byte* base,
FT_UInt len );
FT_Error
(*parse_metrics)( T1_Decoder decoder,
FT_Byte* base,
FT_UInt len );
FT_Error
(*parse_charstrings)( PS_Decoder* decoder,
FT_Byte* charstring_base,

View File

@ -183,6 +183,11 @@
decoder,
charstring + cs_offset,
glyph_length - cs_offset );
else if ( decoder->builder.metrics_only )
error = psaux->t1_decoder_funcs->parse_metrics(
decoder,
charstring + cs_offset,
glyph_length - cs_offset );
else
{
PS_Decoder psdecoder;

View File

@ -90,6 +90,7 @@
t1_decoder_init, /* init */
t1_decoder_done, /* done */
t1_decoder_parse_charstrings, /* parse_charstrings_old */
t1_decoder_parse_metrics, /* parse_metrics */
cf2_decoder_parse_charstrings /* parse_charstrings */
};

View File

@ -1628,6 +1628,283 @@
return FT_THROW( Stack_Underflow );
}
/*************************************************************************/
/* */
/* <Function> */
/* t1_decoder_parse_metrics */
/* */
/* <Description> */
/* Parses a given Type 1 charstrings program to extract width */
/* */
/* <Input> */
/* decoder :: The current Type 1 decoder. */
/* */
/* charstring_base :: The base address of the charstring stream. */
/* */
/* charstring_len :: The length in bytes of the charstring stream. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
t1_decoder_parse_metrics( T1_Decoder decoder,
FT_Byte* charstring_base,
FT_UInt charstring_len )
{
T1_Decoder_Zone zone;
FT_Byte* ip;
FT_Byte* limit;
T1_Builder builder = &decoder->builder;
#ifdef FT_DEBUG_LEVEL_TRACE
FT_Bool bol = TRUE;
#endif
/* First of all, initialize the decoder */
decoder->top = decoder->stack;
decoder->zone = decoder->zones;
zone = decoder->zones;
builder->parse_state = T1_Parse_Start;
FT_TRACE4(( "\n"
"Start charstring: get width\n" ));
zone->base = charstring_base;
limit = zone->limit = charstring_base + charstring_len;
ip = zone->cursor = zone->base;
/* now, execute loop */
while ( ip < limit )
{
FT_Long* top = decoder->top;
T1_Operator op = op_none;
FT_Int32 value = 0;
#ifdef FT_DEBUG_LEVEL_TRACE
if ( bol )
{
FT_TRACE5(( " (%d)", decoder->top - decoder->stack ));
bol = FALSE;
}
#endif
/*********************************************************************/
/* */
/* Decode operator or operand */
/* */
/* */
/* first of all, decompress operator or value */
switch ( *ip++ )
{
case 1:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 14:
case 15:
case 21:
case 22:
case 30:
case 31:
goto No_Width;
case 13:
op = op_hsbw;
break;
case 12:
if ( ip >= limit )
{
FT_ERROR(( "t1_decoder_parse_metrics:"
" invalid escape (12+EOF)\n" ));
goto Syntax_Error;
}
switch ( *ip++ )
{
case 7:
op = op_sbw;
break;
default:
goto No_Width;
}
break;
case 255: /* four bytes integer */
if ( ip + 4 > limit )
{
FT_ERROR(( "t1_decoder_parse_metrics:"
" unexpected EOF in integer\n" ));
goto Syntax_Error;
}
value = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) |
( (FT_UInt32)ip[1] << 16 ) |
( (FT_UInt32)ip[2] << 8 ) |
(FT_UInt32)ip[3] );
ip += 4;
/* According to the specification, values > 32000 or < -32000 must */
/* be followed by a `div' operator to make the result be in the */
/* range [-32000;32000]. We expect that the second argument of */
/* `div' is not a large number. Additionally, we don't handle */
/* stuff like `<large1> <large2> <num> div <num> div' or */
/* <large1> <large2> <num> div div'. This is probably not allowed */
/* anyway. */
if ( value > 32000 || value < -32000 )
{
FT_ERROR(( "t1_decoder_parse_metrics:"
" large integer found for width\n" ));
goto Syntax_Error;
}
else
{
value = (FT_Int32)( (FT_UInt32)value << 16 );
}
break;
default:
if ( ip[-1] >= 32 )
{
if ( ip[-1] < 247 )
value = (FT_Int32)ip[-1] - 139;
else
{
if ( ++ip > limit )
{
FT_ERROR(( "t1_decoder_parse_metrics:"
" unexpected EOF in integer\n" ));
goto Syntax_Error;
}
if ( ip[-2] < 251 )
value = ( ( ip[-2] - 247 ) * 256 ) + ip[-1] + 108;
else
value = -( ( ( ip[-2] - 251 ) * 256 ) + ip[-1] + 108 );
}
value = (FT_Int32)( (FT_UInt32)value << 16 );
}
else
{
FT_ERROR(( "t1_decoder_parse_metrics:"
" invalid byte (%d)\n", ip[-1] ));
goto Syntax_Error;
}
}
/*********************************************************************/
/* */
/* Push value on stack, or process operator */
/* */
/* */
if ( op == op_none )
{
if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
{
FT_ERROR(( "t1_decoder_parse_metrics: stack overflow\n" ));
goto Syntax_Error;
}
#ifdef FT_DEBUG_LEVEL_TRACE
FT_TRACE4(( " %d", value / 65536 ));
#endif
*top++ = value;
decoder->top = top;
}
else /* general operator */
{
FT_Int num_args = t1_args_count[op];
FT_ASSERT( num_args >= 0 );
if ( top - decoder->stack < num_args )
goto Stack_Underflow;
#ifdef FT_DEBUG_LEVEL_TRACE
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 ));
#endif /* FT_DEBUG_LEVEL_TRACE */
top -= num_args;
switch ( op )
{
case op_hsbw:
FT_TRACE4(( " hsbw" ));
builder->parse_state = T1_Parse_Have_Width;
builder->left_bearing.x = ADD_LONG( builder->left_bearing.x,
top[0] );
builder->advance.x = top[1];
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 */
return FT_Err_Ok;
case op_sbw:
FT_TRACE4(( " sbw" ));
builder->parse_state = T1_Parse_Have_Width;
builder->left_bearing.x = ADD_LONG( builder->left_bearing.x,
top[0] );
builder->left_bearing.y = ADD_LONG( builder->left_bearing.y,
top[1] );
builder->advance.x = top[2];
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 */
return FT_Err_Ok;
default:
FT_ERROR(( "t1_decoder_parse_metrics:"
" unhandled opcode %d\n", op ));
goto Syntax_Error;
}
} /* general operator processing */
} /* while ip < limit */
FT_TRACE4(( "..end..\n\n" ));
No_Width:
FT_ERROR(( "t1_decoder_parse_metrics:"
" no width, found op %d instead\n",
ip[-1] ));
Syntax_Error:
return FT_THROW( Syntax_Error );
Stack_Underflow:
return FT_THROW( Stack_Underflow );
}
/* parse a single Type 1 glyph */
FT_LOCAL_DEF( FT_Error )

View File

@ -43,6 +43,10 @@ FT_BEGIN_HEADER
t1_decoder_parse_charstrings( T1_Decoder decoder,
FT_Byte* base,
FT_UInt len );
FT_LOCAL( FT_Error )
t1_decoder_parse_metrics( T1_Decoder decoder,
FT_Byte* charstring_base,
FT_UInt charstring_len );
FT_LOCAL( FT_Error )
t1_decoder_init( T1_Decoder decoder,

View File

@ -90,6 +90,11 @@
decoder,
(FT_Byte*)char_string->pointer,
(FT_UInt)char_string->length );
else if ( decoder->builder.metrics_only )
error = decoder_funcs->parse_metrics(
decoder,
(FT_Byte*)char_string->pointer,
(FT_UInt)char_string->length );
else
{
CFF_SubFontRec subfont;