summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEwald Hew <ewaldhew@gmail.com>2017-10-12 18:13:08 +0800
committerEwald Hew <ewaldhew@gmail.com>2017-10-12 18:32:50 +0800
commit78df3c27b651e3de068437ac35ee2214849badb9 (patch)
tree2c8df4abbef62c434d8d10f53ba079a57e998802 /src
parent8768536c89d6bb3e747bc69a7c2c1e58d2ed4aa9 (diff)
downloadfreetype2-78df3c27b651e3de068437ac35ee2214849badb9.tar.gz
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.
Diffstat (limited to 'src')
-rw-r--r--src/cid/cidgload.c5
-rw-r--r--src/psaux/psauxmod.c1
-rw-r--r--src/psaux/t1decode.c277
-rw-r--r--src/psaux/t1decode.h4
-rw-r--r--src/type1/t1gload.c5
5 files changed, 292 insertions, 0 deletions
diff --git a/src/cid/cidgload.c b/src/cid/cidgload.c
index 8541cca5a..82be44008 100644
--- a/src/cid/cidgload.c
+++ b/src/cid/cidgload.c
@@ -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;
diff --git a/src/psaux/psauxmod.c b/src/psaux/psauxmod.c
index b539b1ac1..16e887dec 100644
--- a/src/psaux/psauxmod.c
+++ b/src/psaux/psauxmod.c
@@ -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 */
};
diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c
index e68b76dac..61d246269 100644
--- a/src/psaux/t1decode.c
+++ b/src/psaux/t1decode.c
@@ -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 )
diff --git a/src/psaux/t1decode.h b/src/psaux/t1decode.h
index 1ca7e013d..420d120ff 100644
--- a/src/psaux/t1decode.h
+++ b/src/psaux/t1decode.h
@@ -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,
diff --git a/src/type1/t1gload.c b/src/type1/t1gload.c
index 30ca186fc..53f89b230 100644
--- a/src/type1/t1gload.c
+++ b/src/type1/t1gload.c
@@ -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;