From 1ee02cd0419021c3d4950af2619da39c6e9c47f0 Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 21 Dec 2009 15:22:51 +0000 Subject: Updated to freetype-2.3.11 --- freetype/src/psaux/t1decode.c | 339 +++++++++++++++++++++++++++--------------- 1 file changed, 221 insertions(+), 118 deletions(-) (limited to 'freetype/src/psaux/t1decode.c') diff --git a/freetype/src/psaux/t1decode.c b/freetype/src/psaux/t1decode.c index bda2324d7..b3245a678 100644 --- a/freetype/src/psaux/t1decode.c +++ b/freetype/src/psaux/t1decode.c @@ -17,6 +17,7 @@ #include +#include FT_INTERNAL_CALC_H #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_POSTSCRIPT_HINTS_H #include FT_OUTLINE_H @@ -144,7 +145,8 @@ FT_String* name = (FT_String*)decoder->glyph_names[n]; - if ( name && name[0] == glyph_name[0] && + if ( name && + name[0] == glyph_name[0] && ft_strcmp( name, glyph_name ) == 0 ) return n; } @@ -193,6 +195,16 @@ #endif FT_Vector left_bearing, advance; +#ifdef FT_CONFIG_OPTION_INCREMENTAL + T1_Face face = (T1_Face)decoder->builder.face; +#endif + + + if ( decoder->seac ) + { + FT_ERROR(( "t1operator_seac: invalid nested seac\n" )); + return PSaux_Err_Syntax_Error; + } /* seac weirdness */ adx += decoder->builder.left_bearing.x; @@ -201,18 +213,29 @@ /* include an encoding. How can we deal with these? */ if ( decoder->glyph_names == 0 ) { - FT_ERROR(( "t1operator_seac:" )); - FT_ERROR(( " glyph names table not available in this font!\n" )); + FT_ERROR(( "t1operator_seac:" + " glyph names table not available in this font\n" )); return PSaux_Err_Syntax_Error; } - bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar ); - achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar ); +#ifdef FT_CONFIG_OPTION_INCREMENTAL + if ( face->root.internal->incremental_interface ) + { + /* the caller must handle the font encoding also */ + bchar_index = bchar; + achar_index = achar; + } + else +#endif + { + bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar ); + achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar ); + } if ( bchar_index < 0 || achar_index < 0 ) { - FT_ERROR(( "t1operator_seac:" )); - FT_ERROR(( " invalid seac character code arguments\n" )); + FT_ERROR(( "t1operator_seac:" + " invalid seac character code arguments\n" )); return PSaux_Err_Syntax_Error; } @@ -243,8 +266,8 @@ /* subglyph 1 = accent character */ subg->index = achar_index; subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; - subg->arg1 = (FT_Int)( adx - asb ); - subg->arg2 = (FT_Int)ady; + subg->arg1 = (FT_Int)FIXED_TO_INT( adx - asb ); + subg->arg2 = (FT_Int)FIXED_TO_INT( ady ); /* set up remaining glyph fields */ glyph->num_subglyphs = 2; @@ -260,7 +283,10 @@ FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */ + /* the seac operator must not be nested */ + decoder->seac = TRUE; error = t1_decoder_parse_glyph( decoder, bchar_index ); + decoder->seac = FALSE; if ( error ) goto Exit; @@ -278,7 +304,11 @@ /* Now load `achar' on top of */ /* the base outline */ + + /* the seac operator must not be nested */ + decoder->seac = TRUE; error = t1_decoder_parse_glyph( decoder, achar_index ); + decoder->seac = FALSE; if ( error ) goto Exit; @@ -327,9 +357,15 @@ FT_Pos x, y, orig_x, orig_y; FT_Int known_othersubr_result_cnt = 0; FT_Int unknown_othersubr_result_cnt = 0; + FT_Bool large_int; + FT_Fixed seed; T1_Hints_Funcs hinter; +#ifdef FT_DEBUG_LEVEL_TRACE + FT_Bool bol = TRUE; +#endif + /* we don't want to touch the source code -- use macro trick */ #define start_point t1_builder_start_point @@ -339,6 +375,16 @@ #define add_contour t1_builder_add_contour #define close_contour t1_builder_close_contour + + /* compute random seed from stack address of parameter */ + seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed ^ + (FT_PtrDist)(char*)&decoder ^ + (FT_PtrDist)(char*)&charstring_base ) & + FT_ULONG_MAX ) ; + seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL; + if ( seed == 0 ) + seed = 0x7384; + /* First of all, initialize the decoder */ decoder->top = decoder->stack; decoder->zone = decoder->zones; @@ -351,14 +397,15 @@ /* a font that reads BuildCharArray without setting */ /* its values first is buggy, but ... */ FT_ASSERT( ( decoder->len_buildchar == 0 ) == - ( decoder->buildchar == NULL ) ); + ( decoder->buildchar == NULL ) ); if ( decoder->len_buildchar > 0 ) ft_memset( &decoder->buildchar[0], 0, sizeof( decoder->buildchar[0] ) * decoder->len_buildchar ); - FT_TRACE4(( "\nStart charstring\n" )); + FT_TRACE4(( "\n" + "Start charstring\n" )); zone->base = charstring_base; limit = zone->limit = charstring_base + charstring_len; @@ -373,18 +420,26 @@ if ( hinter ) hinter->open( hinter->hints ); + large_int = FALSE; + /* now, execute loop */ while ( ip < limit ) { FT_Long* top = decoder->top; T1_Operator op = op_none; - FT_Long value = 0; + FT_Int32 value = 0; FT_ASSERT( known_othersubr_result_cnt == 0 || unknown_othersubr_result_cnt == 0 ); - FT_TRACE5(( " (%d)", decoder->top - decoder->stack )); +#ifdef FT_DEBUG_LEVEL_TRACE + if ( bol ) + { + FT_TRACE5(( " (%d)", decoder->top - decoder->stack )); + bol = FALSE; + } +#endif /*********************************************************************/ /* */ @@ -455,8 +510,8 @@ case 12: if ( ip > limit ) { - FT_ERROR(( "t1_decoder_parse_charstrings: " - "invalid escape (12+EOF)\n" )); + FT_ERROR(( "t1_decoder_parse_charstrings:" + " invalid escape (12+EOF)\n" )); goto Syntax_Error; } @@ -491,8 +546,8 @@ break; default: - FT_ERROR(( "t1_decoder_parse_charstrings: " - "invalid escape (12+%d)\n", + FT_ERROR(( "t1_decoder_parse_charstrings:" + " invalid escape (12+%d)\n", ip[-1] )); goto Syntax_Error; } @@ -501,42 +556,69 @@ case 255: /* four bytes integer */ if ( ip + 4 > limit ) { - FT_ERROR(( "t1_decoder_parse_charstrings: " - "unexpected EOF in integer\n" )); + FT_ERROR(( "t1_decoder_parse_charstrings:" + " unexpected EOF in integer\n" )); goto Syntax_Error; } - value = (FT_Int32)( ((FT_Long)ip[0] << 24) | - ((FT_Long)ip[1] << 16) | - ((FT_Long)ip[2] << 8 ) | - ip[3] ); + value = (FT_Int32)( ( (FT_Long)ip[0] << 24 ) | + ( (FT_Long)ip[1] << 16 ) | + ( (FT_Long)ip[2] << 8 ) | + 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 ` div div' or */ + /* div div'. This is probably not allowed */ + /* anyway. */ + if ( value > 32000 || value < -32000 ) + { + if ( large_int ) + { + FT_ERROR(( "t1_decoder_parse_charstrings:" + " no `div' after large integer\n" )); + } + else + large_int = TRUE; + } + else + { + if ( !large_int ) + value <<= 16; + } + break; default: if ( ip[-1] >= 32 ) { if ( ip[-1] < 247 ) - value = (FT_Long)ip[-1] - 139; + value = (FT_Int32)ip[-1] - 139; else { if ( ++ip > limit ) { - FT_ERROR(( "t1_decoder_parse_charstrings: " )); - FT_ERROR(( "unexpected EOF in integer\n" )); + FT_ERROR(( "t1_decoder_parse_charstrings:" + " unexpected EOF in integer\n" )); goto Syntax_Error; } if ( ip[-2] < 251 ) - value = ( ( (FT_Long)ip[-2] - 247 ) << 8 ) + ip[-1] + 108; + value = ( ( (FT_Int32)ip[-2] - 247 ) << 8 ) + ip[-1] + 108; else - value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 ); + value = -( ( ( (FT_Int32)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 ); } + + if ( !large_int ) + value <<= 16; } else { - FT_ERROR(( "t1_decoder_parse_charstrings: " - "invalid byte (%d)\n", ip[-1] )); + FT_ERROR(( "t1_decoder_parse_charstrings:" + " invalid byte (%d)\n", ip[-1] )); goto Syntax_Error; } } @@ -558,6 +640,14 @@ } } + if ( large_int && !( op == op_none || op == op_div ) ) + { + FT_ERROR(( "t1_decoder_parse_charstrings:" + " no `div' after large integer\n" )); + + large_int = FALSE; + } + /*********************************************************************/ /* */ /* Push value on stack, or process operator */ @@ -567,11 +657,16 @@ { if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS ) { - FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow!\n" )); + FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow\n" )); goto Syntax_Error; } - FT_TRACE4(( " %ld", value )); +#ifdef FT_DEBUG_LEVEL_TRACE + if ( large_int ) + FT_TRACE4(( " %ld", value )); + else + FT_TRACE4(( " %ld", (FT_Int32)( value >> 16 ) )); +#endif *top++ = value; decoder->top = top; @@ -582,15 +677,18 @@ FT_Int arg_cnt; - FT_TRACE4(( " callothersubr" )); +#ifdef FT_DEBUG_LEVEL_TRACE + FT_TRACE4(( " callothersubr\n" )); + bol = TRUE; +#endif if ( top - decoder->stack < 2 ) goto Stack_Underflow; top -= 2; - subr_no = (FT_Int)top[1]; - arg_cnt = (FT_Int)top[0]; + subr_no = (FT_Int)( top[1] >> 16 ); + arg_cnt = (FT_Int)( top[0] >> 16 ); /***********************************************************/ /* */ @@ -667,8 +765,8 @@ if ( decoder->flex_state == 0 || decoder->num_flex_vectors != 7 ) { - FT_ERROR(( "t1_decoder_parse_charstrings: " - "unexpected flex end\n" )); + FT_ERROR(( "t1_decoder_parse_charstrings:" + " unexpected flex end\n" )); goto Syntax_Error; } @@ -684,7 +782,6 @@ if ( hinter ) hinter->reset( hinter->hints, builder->current->n_points ); - break; case 12: @@ -707,16 +804,16 @@ if ( !blend ) { - FT_ERROR(( "t1_decoder_parse_charstrings: " )); - FT_ERROR(( "unexpected multiple masters operator!\n" )); + FT_ERROR(( "t1_decoder_parse_charstrings:" + " unexpected multiple masters operator\n" )); goto Syntax_Error; } num_points = (FT_UInt)subr_no - 13 + ( subr_no == 18 ); if ( arg_cnt != (FT_Int)( num_points * blend->num_designs ) ) { - FT_ERROR(( "t1_decoder_parse_charstrings: " )); - FT_ERROR(( "incorrect number of mm arguments\n" )); + FT_ERROR(( "t1_decoder_parse_charstrings:" + " incorrect number of multiple masters arguments\n" )); goto Syntax_Error; } @@ -752,12 +849,6 @@ break; } -#ifdef CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS - - /* We cannot yet enable these since currently */ - /* our T1 stack stores integers which lack the */ - /* precision to express the values */ - case 19: /* 1 19 callothersubr */ /* => replace elements starting from index cvi( ) */ @@ -770,10 +861,10 @@ if ( arg_cnt != 1 || blend == NULL ) goto Unexpected_OtherSubr; - idx = top[0]; + idx = (FT_Int)( top[0] >> 16 ); - if ( idx < 0 || - idx + blend->num_designs > decoder->face->len_buildchar ) + if ( idx < 0 || + idx + blend->num_designs > decoder->len_buildchar ) goto Unexpected_OtherSubr; ft_memcpy( &decoder->buildchar[idx], @@ -811,7 +902,7 @@ if ( arg_cnt != 2 ) goto Unexpected_OtherSubr; - top[0] *= top[1]; /* XXX (over|under)flow */ + top[0] = FT_MulFix( top[0], top[1] ); known_othersubr_result_cnt = 1; break; @@ -822,24 +913,23 @@ if ( arg_cnt != 2 || top[1] == 0 ) goto Unexpected_OtherSubr; - top[0] /= top[1]; /* XXX (over|under)flow */ + top[0] = FT_DivFix( top[0], top[1] ); known_othersubr_result_cnt = 1; break; -#endif /* CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS */ - case 24: - /* 2 24 callothersubr */ - /* => set BuildCharArray[cvi( )] = */ + /* 2 24 callothersubr */ + /* ==> set BuildCharArray[cvi( )] = */ { FT_Int idx; PS_Blend blend = decoder->blend; + if ( arg_cnt != 2 || blend == NULL ) goto Unexpected_OtherSubr; - idx = top[1]; + idx = (FT_Int)( top[1] >> 16 ); if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) goto Unexpected_OtherSubr; @@ -849,17 +939,18 @@ break; case 25: - /* 1 25 callothersubr pop */ - /* => push BuildCharArray[cvi( idx )] */ - /* onto T1 stack */ + /* 1 25 callothersubr pop */ + /* ==> push BuildCharArray[cvi( idx )] */ + /* onto T1 stack */ { FT_Int idx; PS_Blend blend = decoder->blend; + if ( arg_cnt != 1 || blend == NULL ) goto Unexpected_OtherSubr; - idx = top[0]; + idx = (FT_Int)( top[0] >> 16 ); if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) goto Unexpected_OtherSubr; @@ -875,13 +966,13 @@ /* mark ==> set BuildCharArray[cvi( )] = , */ /* leave mark on T1 stack */ /* ==> set BuildCharArray[cvi( )] = */ - XXX who has left his mark on the (PostScript) stack ?; + XXX which routine has left its mark on the (PostScript) stack?; break; #endif case 27: /* 4 27 callothersubr pop */ - /* ==> push onto T1 stack if <= , */ + /* ==> push onto T1 stack if <= , */ /* otherwise push */ if ( arg_cnt != 4 ) goto Unexpected_OtherSubr; @@ -892,28 +983,40 @@ known_othersubr_result_cnt = 1; break; -#ifdef CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS case 28: /* 0 28 callothersubr pop */ /* => push random value from interval [0, 1) onto stack */ if ( arg_cnt != 0 ) goto Unexpected_OtherSubr; - top[0] = FT_rand(); + { + FT_Fixed Rand; + + + Rand = seed; + if ( Rand >= 0x8000L ) + Rand++; + + top[0] = Rand; + + seed = FT_MulFix( seed, 0x10000L - seed ); + if ( seed == 0 ) + seed += 0x2873; + } + known_othersubr_result_cnt = 1; break; -#endif default: - FT_ERROR(( "t1_decoder_parse_charstrings: " - "unknown othersubr [%d %d], wish me luck!\n", + FT_ERROR(( "t1_decoder_parse_charstrings:" + " unknown othersubr [%d %d], wish me luck\n", arg_cnt, subr_no )); unknown_othersubr_result_cnt = arg_cnt; break; Unexpected_OtherSubr: - FT_ERROR(( "t1_decoder_parse_charstrings: " - "invalid othersubr [%d %d]!\n", arg_cnt, subr_no )); + FT_ERROR(( "t1_decoder_parse_charstrings:" + " invalid othersubr [%d %d]\n", arg_cnt, subr_no )); goto Syntax_Error; } @@ -950,9 +1053,9 @@ default: if ( top - decoder->stack != num_args ) - FT_TRACE0(( "t1_decoder_parse_charstrings: " - "too much operands on the stack " - "(seen %d, expected %d)\n", + FT_TRACE0(( "t1_decoder_parse_charstrings:" + " too much operands on the stack" + " (seen %d, expected %d)\n", top - decoder->stack, num_args )); break; } @@ -964,28 +1067,26 @@ switch ( op ) { case op_endchar: - FT_TRACE4(( " endchar" )); + FT_TRACE4(( " endchar\n" )); close_contour( builder ); /* close hints recording session */ if ( hinter ) { - if (hinter->close( hinter->hints, builder->current->n_points )) + if ( hinter->close( hinter->hints, builder->current->n_points ) ) goto Syntax_Error; /* apply hints to the loaded glyph outline now */ hinter->apply( hinter->hints, builder->current, - (PSH_Globals) builder->hints_globals, + (PSH_Globals)builder->hints_globals, decoder->hint_mode ); } /* add current outline to the glyph slot */ FT_GlyphLoader_Add( builder->loader ); - FT_TRACE4(( "\n" )); - /* the compiler should optimize away this empty loop but ... */ #ifdef FT_DEBUG_LEVEL_TRACE @@ -1019,8 +1120,8 @@ builder->advance.x = top[1]; builder->advance.y = 0; - orig_x = builder->last.x = x = builder->pos_x + top[0]; - orig_y = builder->last.y = y = builder->pos_y; + orig_x = x = builder->pos_x + top[0]; + orig_y = y = builder->pos_y; FT_UNUSED( orig_y ); @@ -1033,9 +1134,12 @@ break; case op_seac: - /* return immediately after the processing */ - return t1operator_seac( decoder, top[0], top[1], top[2], - (FT_Int)top[3], (FT_Int)top[4] ); + return t1operator_seac( decoder, + top[0], + top[1], + top[2], + (FT_Int)( top[3] >> 16 ), + (FT_Int)( top[4] >> 16 ) ); case op_sbw: FT_TRACE4(( " sbw" )); @@ -1047,8 +1151,8 @@ builder->advance.x = top[2]; builder->advance.y = top[3]; - builder->last.x = x = builder->pos_x + top[0]; - builder->last.y = y = builder->pos_y + top[1]; + x = builder->pos_x + top[0]; + y = 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 */ @@ -1134,7 +1238,7 @@ break; case op_rrcurveto: - FT_TRACE4(( " rcurveto" )); + FT_TRACE4(( " rrcurveto" )); if ( start_point( builder, x, y ) || check_points( builder, 3 ) ) @@ -1193,16 +1297,13 @@ case op_div: FT_TRACE4(( " div" )); - if ( top[1] ) - { - *top = top[0] / top[1]; - ++top; - } - else - { - FT_ERROR(( "t1_decoder_parse_charstrings: division by 0\n" )); - goto Syntax_Error; - } + /* if `large_int' is set, we divide unscaled numbers; */ + /* otherwise, we divide numbers in 16.16 format -- */ + /* in both cases, it is the same operation */ + *top = FT_DivFix( top[0], top[1] ); + ++top; + + large_int = FALSE; break; case op_callsubr: @@ -1212,18 +1313,18 @@ FT_TRACE4(( " callsubr" )); - idx = (FT_Int)top[0]; + idx = (FT_Int)( top[0] >> 16 ); if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs ) { - FT_ERROR(( "t1_decoder_parse_charstrings: " - "invalid subrs index\n" )); + FT_ERROR(( "t1_decoder_parse_charstrings:" + " invalid subrs index\n" )); goto Syntax_Error; } if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) { - FT_ERROR(( "t1_decoder_parse_charstrings: " - "too many nested subrs\n" )); + FT_ERROR(( "t1_decoder_parse_charstrings:" + " too many nested subrs\n" )); goto Syntax_Error; } @@ -1250,8 +1351,8 @@ if ( !zone->base ) { - FT_ERROR(( "t1_decoder_parse_charstrings: " - "invoking empty subrs!\n" )); + FT_ERROR(( "t1_decoder_parse_charstrings:" + " invoking empty subrs\n" )); goto Syntax_Error; } @@ -1273,8 +1374,8 @@ if ( unknown_othersubr_result_cnt == 0 ) { - FT_ERROR(( "t1_decoder_parse_charstrings: " - "no more operands for othersubr!\n" )); + FT_ERROR(( "t1_decoder_parse_charstrings:" + " no more operands for othersubr\n" )); goto Syntax_Error; } @@ -1287,7 +1388,8 @@ if ( zone <= decoder->zones ) { - FT_ERROR(( "t1_decoder_parse_charstrings: unexpected return\n" )); + FT_ERROR(( "t1_decoder_parse_charstrings:" + " unexpected return\n" )); goto Syntax_Error; } @@ -1311,7 +1413,6 @@ /* top[0] += builder->left_bearing.y; */ hinter->stem( hinter->hints, 1, top ); } - break; case op_hstem3: @@ -1320,19 +1421,17 @@ /* record horizontal counter-controlled hints */ if ( hinter ) hinter->stem3( hinter->hints, 1, top ); - break; case op_vstem: FT_TRACE4(( " vstem" )); - /* record vertical hint */ + /* record vertical hint */ if ( hinter ) { top[0] += orig_x; hinter->stem( hinter->hints, 0, top ); } - break; case op_vstem3: @@ -1362,9 +1461,8 @@ /* known_othersubr_result_cnt != 0 is already handled above */ if ( decoder->flex_state != 1 ) { - FT_ERROR(( "t1_decoder_parse_charstrings: " )); - FT_ERROR(( "unexpected `setcurrentpoint'\n" )); - + FT_ERROR(( "t1_decoder_parse_charstrings:" + " unexpected `setcurrentpoint'\n" )); goto Syntax_Error; } else @@ -1377,8 +1475,8 @@ break; default: - FT_ERROR(( "t1_decoder_parse_charstrings: " - "unhandled opcode %d\n", op )); + FT_ERROR(( "t1_decoder_parse_charstrings:" + " unhandled opcode %d\n", op )); goto Syntax_Error; } @@ -1389,6 +1487,11 @@ decoder->top = top; +#ifdef FT_DEBUG_LEVEL_TRACE + FT_TRACE4(( "\n" )); + bol = TRUE; +#endif + } /* general operator processing */ } /* while ip < limit */ @@ -1437,8 +1540,8 @@ FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); if ( !psnames ) { - FT_ERROR(( "t1_decoder_init: " )); - FT_ERROR(( "the `psnames' module is not available\n" )); + FT_ERROR(( "t1_decoder_init:" + " the `psnames' module is not available\n" )); return PSaux_Err_Unimplemented_Feature; } -- cgit v1.2.3