[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[freetype2] ewaldhew-cleaned 14e2d8f 30/36: [psaux] Extend Adobe interpr
From: |
Hew Yih Shiuan Ewald |
Subject: |
[freetype2] ewaldhew-cleaned 14e2d8f 30/36: [psaux] Extend Adobe interpreter. (callothersubr) |
Date: |
Wed, 9 Aug 2017 21:36:12 -0400 (EDT) |
branch: ewaldhew-cleaned
commit 14e2d8ff1b6e01b7375aea84fadc6a110084f879
Author: Ewald Hew <address@hidden>
Commit: Ewald Hew <address@hidden>
[psaux] Extend Adobe interpreter. (callothersubr)
* src/psaux/psintrp.c (cf2_interpT2CharString)
<callothersubr>: Copy code from t1decode.c (t1_decoder_parse_charstrings).
OtherSubr 3 (change hints) should reset the hintmask, so that the new
hints are applied.
Fix function calls and stack access.
---
src/psaux/psintrp.c | 439 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 438 insertions(+), 1 deletion(-)
diff --git a/src/psaux/psintrp.c b/src/psaux/psintrp.c
index 2ae14d1..def5293 100644
--- a/src/psaux/psintrp.c
+++ b/src/psaux/psintrp.c
@@ -1448,8 +1448,445 @@
FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
else
{
+ CF2_Int subr_no;
+ CF2_Int arg_cnt;
+ CF2_UInt count;
+ CF2_UInt opIdx = 0;
+
+ FT_TRACE4(( " callothersubr\n" ));
+
+ subr_no = cf2_stack_popInt( opStack );
+ arg_cnt = cf2_stack_popInt( opStack );
+
+
/***********************************************************/
+ /*
*/
+ /* remove all operands to callothersubr from the stack
*/
+ /*
*/
+ /* for handled othersubrs, where we know the number of
*/
+ /* arguments, we increase the stack by the value of
*/
+ /* known_othersubr_result_cnt
*/
+ /*
*/
+ /* for unhandled othersubrs the following pops adjust the
*/
+ /* stack pointer as necessary
*/
+
+ count = cf2_stack_count( opStack );
+ FT_ASSERT( arg_cnt <= count );
+
+ opIdx += count - arg_cnt;
+
+ known_othersubr_result_cnt = 0;
+ result_cnt = 0;
+
+ /* XXX TODO: The checks to `arg_count == <whatever>'
*/
+ /* might not be correct; an othersubr expects a certain
*/
+ /* number of operands on the PostScript stack (as opposed
*/
+ /* to the T1 stack) but it doesn't have to put them there
*/
+ /* by itself; previous othersubrs might have left the
*/
+ /* operands there if they were not followed by an
*/
+ /* appropriate number of pops
*/
+ /*
*/
+ /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't
*/
+ /* accept a font that contains charstrings like
*/
+ /*
*/
+ /* 100 200 2 20 callothersubr
*/
+ /* 300 1 20 callothersubr pop
*/
+ /*
*/
+ /* Perhaps this is the reason why BuildCharArray exists.
*/
+
+ switch ( subr_no )
+ {
+ case 0: /* end flex feature */
+ if ( arg_cnt != 3 )
+ goto Unexpected_OtherSubr;
+
+ if ( !decoder->flex_state ||
+ decoder->num_flex_vectors != 7 )
+ {
+ FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
+ " unexpected flex end\n" ));
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ /* the two `results' are popped by the following
setcurrentpoint */
+ cf2_stack_pushFixed( opStack, curX );
+ cf2_stack_pushFixed( opStack, curY );
+ known_othersubr_result_cnt = 2;
+ break;
+
+ case 1: /* start flex feature */
+ if ( arg_cnt != 0 )
+ goto Unexpected_OtherSubr;
+
+ if ( ps_builder_start_point( &decoder->builder, curX,
curY ) ||
+ ps_builder_check_points( &decoder->builder, 6 )
)
+ goto exit;
+
+ decoder->flex_state = 1;
+ decoder->num_flex_vectors = 0;
+ break;
+
+ case 2: /* add flex vectors */
+ {
+ FT_Int idx;
+
+
+ if ( arg_cnt != 0 )
+ goto Unexpected_OtherSubr;
+
+ if ( !decoder->flex_state )
+ {
+ FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
+ " missing flex start\n" ));
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ /* note that we should not add a point for index 0; */
+ /* this will move our current position to the flex */
+ /* point without adding any point to the outline */
+ idx = decoder->num_flex_vectors++;
+ if ( idx > 0 && idx < 7 )
+ {
+ /* in malformed fonts it is possible to have other */
+ /* opcodes in the middle of a flex (which don't */
+ /* increase `num_flex_vectors'); we thus have to */
+ /* check whether we can add a point */
+ if ( ps_builder_check_points( &decoder->builder, 1 ) )
+ {
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ ps_builder_add_point( &decoder->builder,
+ curX,
+ curY,
+ (FT_Byte)( idx == 3 || idx == 6
) );
+ }
+ }
+ break;
+
+ case 3: /* change hints */
+ if ( arg_cnt != 1 )
+ goto Unexpected_OtherSubr;
+
+ cf2_arrstack_clear( &vStemHintArray );
+ cf2_arrstack_clear( &hStemHintArray );
+
+ cf2_hintmask_init( &hintMask, error );
+ hintMask.isValid = FALSE;
+ hintMask.isNew = TRUE;
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+ case 12:
+ case 13:
+ /* counter control hints, clear stack */
+ cf2_stack_clear( opStack );
+ break;
+
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18: /* multiple masters */
+ {
+ PS_Blend blend = decoder->blend;
+ FT_UInt num_points, nn, mm;
+ CF2_UInt delta;
+ CF2_UInt values;
+
+
+ if ( !blend )
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings:"
+ " unexpected multiple masters operator\n"
));
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ 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:"
+ " incorrect number of multiple masters
arguments\n" ));
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ /* We want to compute
*/
+ /*
*/
+ /* a0*w0 + a1*w1 + ... + ak*wk
*/
+ /*
*/
+ /* but we only have a0, a1-a0, a2-a0, ..., ak-a0.
*/
+ /*
*/
+ /* However, given that w0 + w1 + ... + wk == 1, we can
*/
+ /* rewrite it easily as
*/
+ /*
*/
+ /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk
*/
+ /*
*/
+ /* where k == num_designs-1.
*/
+ /*
*/
+ /* I guess that's why it's written in this `compact'
*/
+ /* form.
*/
+ /*
*/
+ delta = opIdx + num_points;
+ values = opIdx;
+ for ( nn = 0; nn < num_points; nn++ )
+ {
+ CF2_Fixed tmp = cf2_stack_getReal( opStack, values );
+
+
+ for ( mm = 1; mm < blend->num_designs; mm++ )
+ tmp = ADD_INT32( tmp,
+ FT_MulFix( cf2_stack_getReal(
opStack, delta++ ),
+ blend->weight_vector[mm]
) );
+
+ cf2_stack_setReal( opStack, values++, tmp );
+ }
+ cf2_stack_pop( opStack,
+ arg_cnt - num_points );
+
+ known_othersubr_result_cnt = (FT_Int)num_points;
+ break;
+ }
+
+ case 19:
+ /* <idx> 1 19 callothersubr
*/
+ /* => replace elements starting from index cvi( <idx> )
*/
+ /* of BuildCharArray with WeightVector
*/
+ {
+ FT_Int idx;
+ PS_Blend blend = decoder->blend;
+
+
+ if ( arg_cnt != 1 || !blend )
+ goto Unexpected_OtherSubr;
+
+ idx = cf2_stack_popInt( opStack );
+
+ if ( idx < 0
||
+ (FT_UInt)idx + blend->num_designs >
decoder->len_buildchar )
+ goto Unexpected_OtherSubr;
+
+ ft_memcpy( &decoder->buildchar[idx],
+ blend->weight_vector,
+ blend->num_designs *
+ sizeof ( blend->weight_vector[0] ) );
+ }
+ break;
+
+ case 20:
+ /* <arg1> <arg2> 2 20 callothersubr pop */
+ /* ==> push <arg1> + <arg2> onto T1 stack */
+ {
+ CF2_F16Dot16 summand1;
+ CF2_F16Dot16 summand2;
+
+ if ( arg_cnt != 2 )
+ goto Unexpected_OtherSubr;
+
+ summand2 = cf2_stack_popFixed( opStack );
+ summand1 = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushFixed( opStack,
+ ADD_INT32( summand1,
+ summand2 ) );
+ known_othersubr_result_cnt = 1;
+ }
+ break;
+
+ case 21:
+ /* <arg1> <arg2> 2 21 callothersubr pop */
+ /* ==> push <arg1> - <arg2> onto T1 stack */
+ {
+ CF2_F16Dot16 minuend;
+ CF2_F16Dot16 subtrahend;
+
+ if ( arg_cnt != 2 )
+ goto Unexpected_OtherSubr;
+
+ subtrahend = cf2_stack_popFixed( opStack );
+ minuend = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushFixed( opStack,
+ SUB_INT32( minuend, subtrahend ) );
+ known_othersubr_result_cnt = 1;
+ }
+ break;
+
+ case 22:
+ /* <arg1> <arg2> 2 22 callothersubr pop */
+ /* ==> push <arg1> * <arg2> onto T1 stack */
+ {
+ CF2_F16Dot16 factor1;
+ CF2_F16Dot16 factor2;
+
+ if ( arg_cnt != 2 )
+ goto Unexpected_OtherSubr;
+
+ factor2 = cf2_stack_popFixed( opStack );
+ factor1 = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushFixed( opStack,
+ FT_MulFix( factor1, factor2 ) );
+ known_othersubr_result_cnt = 1;
+ }
+ break;
+
+ case 23:
+ /* <arg1> <arg2> 2 23 callothersubr pop */
+ /* ==> push <arg1> / <arg2> onto T1 stack */
+ {
+ CF2_F16Dot16 dividend;
+ CF2_F16Dot16 divisor;
+
+ if ( arg_cnt != 2 )
+ goto Unexpected_OtherSubr;
+
+ divisor = cf2_stack_popFixed( opStack );
+ dividend = cf2_stack_popFixed( opStack );
+
+ if ( divisor == 0 )
+ goto Unexpected_OtherSubr;
+
+ cf2_stack_pushFixed( opStack,
+ FT_DivFix( dividend, divisor ) );
+ known_othersubr_result_cnt = 1;
+ }
+ break;
+
+ case 24:
+ /* <val> <idx> 2 24 callothersubr */
+ /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
+ {
+ CF2_Int idx;
+ PS_Blend blend = decoder->blend;
+
+
+ if ( arg_cnt != 2 || !blend )
+ goto Unexpected_OtherSubr;
+
+ idx = cf2_stack_popInt( opStack );
+
+ if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
+ goto Unexpected_OtherSubr;
+
+ decoder->buildchar[idx] = cf2_stack_popFixed( opStack );
+ }
+ break;
+
+ case 25:
+ /* <idx> 1 25 callothersubr pop */
+ /* ==> push BuildCharArray[cvi( idx )] */
+ /* onto T1 stack */
+ {
+ CF2_Int idx;
+ PS_Blend blend = decoder->blend;
+
+
+ if ( arg_cnt != 1 || !blend )
+ goto Unexpected_OtherSubr;
+
+ idx = cf2_stack_popInt( opStack );
+
+ if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
+ goto Unexpected_OtherSubr;
+
+ cf2_stack_pushFixed( opStack,
+ decoder->buildchar[idx] );
+ known_othersubr_result_cnt = 1;
+ }
+ break;
+
+#if 0
+ case 26:
+ /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )]
= <val>, */
+ /* leave mark on T1 stack
*/
+ /* <val> <idx> ==> set BuildCharArray[cvi( <idx> )]
= <val> */
+ XXX which routine has left its mark on the (PostScript)
stack?;
+ break;
+#endif
+
+ case 27:
+ /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
+ /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */
+ /* otherwise push <res2> */
+ {
+ CF2_F16Dot16 arg1;
+ CF2_F16Dot16 arg2;
+ CF2_F16Dot16 cond1;
+ CF2_F16Dot16 cond2;
+
+ if ( arg_cnt != 4 )
+ goto Unexpected_OtherSubr;
+
+ cond2 = cf2_stack_popFixed( opStack );
+ cond1 = cf2_stack_popFixed( opStack );
+ arg2 = cf2_stack_popFixed( opStack );
+ arg1 = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushFixed( opStack,
+ cond1 <= cond2 ? arg1 : arg2 );
+ known_othersubr_result_cnt = 1;
+ }
+ break;
+
+ case 28:
+ /* 0 28 callothersubr pop
*/
+ /* => push random value from interval [0, 1) onto stack
*/
+ {
+ CF2_F16Dot16 r;
+
+ if ( arg_cnt != 0 )
+ goto Unexpected_OtherSubr;
+
+ /* only use the lower 16 bits of `random' */
+ /* to generate a number in the range (0;1] */
+ r = (CF2_F16Dot16)
+ ( ( decoder->current_subfont->random & 0xFFFF ) + 1 );
+
+ decoder->current_subfont->random =
+ cff_random( decoder->current_subfont->random );
+
+ cf2_stack_pushFixed( opStack, r );
+ known_othersubr_result_cnt = 1;
+ }
+ break;
+
+ default:
+ if ( arg_cnt >= 0 && subr_no >= 0 )
+ {
+ FT_UInt i;
+
+ FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
+ " unknown othersubr [%d %d], wish me
luck\n",
+ arg_cnt, subr_no ));
+
+ /* Store the unused args for this unhandled OtherSubr
*/
+
+ if ( arg_cnt > PS_STORAGE_SIZE )
+ arg_cnt = PS_STORAGE_SIZE;
+ result_cnt = arg_cnt;
+
+ for ( i = 1; i <= arg_cnt; i++ )
+ {
+ results[result_cnt - i] = cf2_stack_popFixed(
opStack );
+ }
+
+ break;
+ }
+ /* fall through */
+
+ Unexpected_OtherSubr:
+ FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
+ " invalid othersubr [%d %d]\n", arg_cnt,
subr_no ));
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
}
- break;
+ continue; /* do not clear the stack */
case cf2_escPOP:
if ( !font->isT1 )
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [freetype2] ewaldhew-cleaned 14e2d8f 30/36: [psaux] Extend Adobe interpreter. (callothersubr),
Hew Yih Shiuan Ewald <=