forked from minhngoc25a/freetype2
[psaux] Add Type 1 operations to Adobe CFF interpreter.
The following Type 1 specific ops have been added (copied from t1decode): closepath vstem3 hstem3 seac sbw callothersubr pop setcurrentpoint hsbw The following require a Type 1 mode, because of differences in specification: hstem vstem vmoveto callsubr div rmoveto hmoveto Numbers The subsequent commits will implement these changes and adapt accesses of data and objects to the new interpreter. NOTE: Will not compile in the meantime! * src/psaux/psintrp.c: Add opcodes to enum. Copy relevant code over from t1decode.c (t1_decoder_parse_charstrings).
This commit is contained in:
parent
299fb8893d
commit
3083d228ea
|
@ -205,11 +205,11 @@
|
|||
cf2_cmdHLINETO, /* 6 */
|
||||
cf2_cmdVLINETO, /* 7 */
|
||||
cf2_cmdRRCURVETO, /* 8 */
|
||||
cf2_cmdRESERVED_9, /* 9 */
|
||||
cf2_cmdCLOSEPATH, /* 9 T1 only */
|
||||
cf2_cmdCALLSUBR, /* 10 */
|
||||
cf2_cmdRETURN, /* 11 */
|
||||
cf2_cmdESC, /* 12 */
|
||||
cf2_cmdRESERVED_13, /* 13 */
|
||||
cf2_cmdHSBW, /* 13 T1 only */
|
||||
cf2_cmdENDCHAR, /* 14 */
|
||||
cf2_cmdVSINDEX, /* 15 */
|
||||
cf2_cmdBLEND, /* 16 */
|
||||
|
@ -233,13 +233,13 @@
|
|||
enum
|
||||
{
|
||||
cf2_escDOTSECTION, /* 0 */
|
||||
cf2_escRESERVED_1, /* 1 */
|
||||
cf2_escRESERVED_2, /* 2 */
|
||||
cf2_escVSTEM3, /* 1 T1 only */
|
||||
cf2_escHSTEM3, /* 2 T1 only */
|
||||
cf2_escAND, /* 3 */
|
||||
cf2_escOR, /* 4 */
|
||||
cf2_escNOT, /* 5 */
|
||||
cf2_escRESERVED_6, /* 6 */
|
||||
cf2_escRESERVED_7, /* 7 */
|
||||
cf2_escSEAC, /* 6 T1 only */
|
||||
cf2_escSBW, /* 7 T1 only */
|
||||
cf2_escRESERVED_8, /* 8 */
|
||||
cf2_escABS, /* 9 */
|
||||
cf2_escADD, /* 10 like otherADD */
|
||||
|
@ -248,8 +248,8 @@
|
|||
cf2_escRESERVED_13, /* 13 */
|
||||
cf2_escNEG, /* 14 */
|
||||
cf2_escEQ, /* 15 */
|
||||
cf2_escRESERVED_16, /* 16 */
|
||||
cf2_escRESERVED_17, /* 17 */
|
||||
cf2_escCALLOTHERSUBR,/* 16 T1 only */
|
||||
cf2_escPOP, /* 17 T1 only */
|
||||
cf2_escDROP, /* 18 */
|
||||
cf2_escRESERVED_19, /* 19 */
|
||||
cf2_escPUT, /* 20 like otherPUT */
|
||||
|
@ -265,7 +265,7 @@
|
|||
cf2_escROLL, /* 30 */
|
||||
cf2_escRESERVED_31, /* 31 */
|
||||
cf2_escRESERVED_32, /* 32 */
|
||||
cf2_escRESERVED_33, /* 33 */
|
||||
cf2_escSETCURRENTPT, /* 33 T1 only */
|
||||
cf2_escHFLEX, /* 34 */
|
||||
cf2_escFLEX, /* 35 */
|
||||
cf2_escHFLEX1, /* 36 */
|
||||
|
@ -484,6 +484,12 @@
|
|||
CF2_Fixed scaleY = font->innerTransform.d;
|
||||
CF2_Fixed nominalWidthX = cf2_getNominalWidthX( decoder );
|
||||
|
||||
/* Stuff for Type 1 */
|
||||
FT_Pos orig_x, orig_y;
|
||||
FT_Int known_othersubr_result_cnt = 0;
|
||||
FT_Int unknown_othersubr_result_cnt = 0;
|
||||
FT_Bool large_int;
|
||||
|
||||
/* save this for hinting seac accents */
|
||||
CF2_Fixed hintOriginY = curY;
|
||||
|
||||
|
@ -606,6 +612,12 @@
|
|||
/* main interpreter loop */
|
||||
while ( 1 )
|
||||
{
|
||||
if ( font->isT1 )
|
||||
{
|
||||
FT_ASSERT( known_othersubr_result_cnt == 0 ||
|
||||
unknown_othersubr_result_cnt == 0 );
|
||||
}
|
||||
|
||||
if ( cf2_buf_isEnd( charstring ) )
|
||||
{
|
||||
/* If we've reached the end of the charstring, simulate a */
|
||||
|
@ -627,6 +639,27 @@
|
|||
op1 = cf2_cmdRESERVED_0;
|
||||
}
|
||||
|
||||
if ( font->isT1 )
|
||||
{
|
||||
if ( unknown_othersubr_result_cnt > 0 &&
|
||||
!( op1 == cf2_cmdCALLSUBR ||
|
||||
op1 == cf2_cmdRETURN ||
|
||||
op1 == cf2_escPOP ||
|
||||
op1 >= 32 /* Numbers */ ) )
|
||||
{
|
||||
/* all operands have been transferred by previous pops */
|
||||
unknown_othersubr_result_cnt = 0;
|
||||
}
|
||||
|
||||
if ( large_int && !( op1 >= 32 || op1 == cf2_escDIV ) )
|
||||
{
|
||||
FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
|
||||
" no `div' after large integer\n" ));
|
||||
|
||||
large_int = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for errors once per loop */
|
||||
if ( *error )
|
||||
goto exit;
|
||||
|
@ -642,8 +675,6 @@
|
|||
{
|
||||
case cf2_cmdRESERVED_0:
|
||||
case cf2_cmdRESERVED_2:
|
||||
case cf2_cmdRESERVED_9:
|
||||
case cf2_cmdRESERVED_13:
|
||||
case cf2_cmdRESERVED_17:
|
||||
/* we may get here if we have a prior error */
|
||||
FT_TRACE4(( " unknown op (%d)\n", op1 ));
|
||||
|
@ -777,6 +808,13 @@
|
|||
if ( font->decoder->width_only )
|
||||
goto exit;
|
||||
|
||||
if ( font->isT1 && !decoder->flex_state )
|
||||
{
|
||||
if ( builder->parse_state == T1_Parse_Start )
|
||||
goto Syntax_Error;
|
||||
builder->parse_state = T1_Parse_Have_Moveto;
|
||||
}
|
||||
|
||||
curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) );
|
||||
|
||||
cf2_glyphpath_moveTo( &glyphPath, curX, curY );
|
||||
|
@ -878,6 +916,24 @@
|
|||
}
|
||||
continue; /* no need to clear stack again */
|
||||
|
||||
case cf2_cmdCLOSEPATH:
|
||||
if ( !font->isT1 )
|
||||
{
|
||||
FT_TRACE4(( " unknown op (%d)\n", op1 ));
|
||||
}
|
||||
else
|
||||
{
|
||||
FT_TRACE4(( " closepath" ));
|
||||
|
||||
/* if there is no path, `closepath' is a no-op */
|
||||
if ( builder->parse_state == T1_Parse_Have_Path ||
|
||||
builder->parse_state == T1_Parse_Have_Moveto )
|
||||
t1_builder_close_contour( builder );
|
||||
|
||||
builder->parse_state = T1_Parse_Have_Width;
|
||||
}
|
||||
break;
|
||||
|
||||
case cf2_cmdCALLGSUBR:
|
||||
case cf2_cmdCALLSUBR:
|
||||
{
|
||||
|
@ -903,6 +959,17 @@
|
|||
/* set up the new CFF region and pointer */
|
||||
subrNum = cf2_stack_popInt( opStack );
|
||||
|
||||
if ( font->isT1 && decoder->subrs_hash )
|
||||
{
|
||||
size_t* val = ft_hash_num_lookup( subrNum,
|
||||
decoder->subrs_hash );
|
||||
|
||||
if ( val )
|
||||
subrNum = *val;
|
||||
else
|
||||
subrNum = -1;
|
||||
}
|
||||
|
||||
switch ( op1 )
|
||||
{
|
||||
case cf2_cmdCALLGSUBR:
|
||||
|
@ -1060,20 +1127,13 @@
|
|||
}
|
||||
continue;
|
||||
|
||||
/* these opcodes are reserved in both CFF & CFF2 */
|
||||
case cf2_escRESERVED_1:
|
||||
case cf2_escRESERVED_2:
|
||||
case cf2_escRESERVED_6:
|
||||
case cf2_escRESERVED_7:
|
||||
/* these opcodes are always reserved */
|
||||
case cf2_escRESERVED_8:
|
||||
case cf2_escRESERVED_13:
|
||||
case cf2_escRESERVED_16:
|
||||
case cf2_escRESERVED_17:
|
||||
case cf2_escRESERVED_19:
|
||||
case cf2_escRESERVED_25:
|
||||
case cf2_escRESERVED_31:
|
||||
case cf2_escRESERVED_32:
|
||||
case cf2_escRESERVED_33:
|
||||
FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
|
||||
break;
|
||||
|
||||
|
@ -1083,7 +1143,7 @@
|
|||
FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
|
||||
else
|
||||
{
|
||||
/* second switch for 2-byte operators handles just CFF */
|
||||
/* second switch for 2-byte operators handles CFF and Type 1 */
|
||||
switch ( op2 )
|
||||
{
|
||||
|
||||
|
@ -1093,6 +1153,22 @@
|
|||
|
||||
break;
|
||||
|
||||
case cf2_escVSTEM3:
|
||||
if ( !font->isT1 )
|
||||
FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
|
||||
else
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case cf2_escHSTEM3:
|
||||
if ( !font->isT1 )
|
||||
FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
|
||||
else
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case cf2_escAND:
|
||||
{
|
||||
CF2_F16Dot16 arg1;
|
||||
|
@ -1136,6 +1212,52 @@
|
|||
}
|
||||
continue; /* do not clear the stack */
|
||||
|
||||
case cf2_escSEAC:
|
||||
{
|
||||
if ( !font->isT1 )
|
||||
FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
|
||||
else
|
||||
{
|
||||
return t1operator_seac( decoder,
|
||||
top[0],
|
||||
top[1],
|
||||
top[2],
|
||||
Fix2Int( top[3] ),
|
||||
Fix2Int( top[4] ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case cf2_escSBW:
|
||||
{
|
||||
if ( !font->isT1 )
|
||||
FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
|
||||
else
|
||||
{
|
||||
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];
|
||||
|
||||
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 */
|
||||
/* rest of it; so exit immediately */
|
||||
if ( builder->metrics_only )
|
||||
return FT_Err_Ok;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case cf2_escABS:
|
||||
{
|
||||
CF2_F16Dot16 arg;
|
||||
|
@ -1198,6 +1320,9 @@
|
|||
|
||||
cf2_stack_pushFixed( opStack,
|
||||
FT_DivFix( dividend, divisor ) );
|
||||
|
||||
if ( font->isT1 )
|
||||
large_int = FALSE;
|
||||
}
|
||||
continue; /* do not clear the stack */
|
||||
|
||||
|
@ -1232,6 +1357,40 @@
|
|||
}
|
||||
continue; /* do not clear the stack */
|
||||
|
||||
case cf2_escCALLOTHERSUBR:
|
||||
if ( !font->isT1 )
|
||||
FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
|
||||
else
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case cf2_escPOP:
|
||||
if ( !font->isT1 )
|
||||
FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
|
||||
else
|
||||
{
|
||||
FT_TRACE4(( " pop" ));
|
||||
|
||||
if ( known_othersubr_result_cnt > 0 )
|
||||
{
|
||||
known_othersubr_result_cnt--;
|
||||
/* ignore, we pushed the operands ourselves */
|
||||
break;
|
||||
}
|
||||
|
||||
if ( unknown_othersubr_result_cnt == 0 )
|
||||
{
|
||||
FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
|
||||
" no more operands for othersubr\n" ));
|
||||
goto Syntax_Error;
|
||||
}
|
||||
|
||||
unknown_othersubr_result_cnt--;
|
||||
top++; /* `push' the operand to callothersubr onto the stack */
|
||||
}
|
||||
break;
|
||||
|
||||
case cf2_escDROP:
|
||||
FT_TRACE4(( " drop\n" ));
|
||||
|
||||
|
@ -1433,6 +1592,43 @@
|
|||
}
|
||||
continue; /* do not clear the stack */
|
||||
|
||||
case cf2_escSETCURRENTPT:
|
||||
if ( !font->isT1 )
|
||||
FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
|
||||
else
|
||||
{
|
||||
FT_TRACE4(( " setcurrentpoint" ));
|
||||
|
||||
/* From the T1 specification, section 6.4: */
|
||||
/* */
|
||||
/* The setcurrentpoint command is used only in */
|
||||
/* conjunction with results from OtherSubrs procedures. */
|
||||
|
||||
/* known_othersubr_result_cnt != 0 is already handled */
|
||||
/* above. */
|
||||
|
||||
/* Note, however, that both Ghostscript and Adobe */
|
||||
/* Distiller handle this situation by silently ignoring */
|
||||
/* the inappropriate `setcurrentpoint' instruction. So */
|
||||
/* we do the same. */
|
||||
#if 0
|
||||
|
||||
if ( decoder->flex_state != 1 )
|
||||
{
|
||||
FT_ERROR(( "t1_decoder_parse_charstrings:"
|
||||
" unexpected `setcurrentpoint'\n" ));
|
||||
goto Syntax_Error;
|
||||
}
|
||||
else
|
||||
...
|
||||
#endif
|
||||
|
||||
x = top[0];
|
||||
y = top[1];
|
||||
decoder->flex_state = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
} /* end of 2nd switch checking op2 */
|
||||
}
|
||||
}
|
||||
|
@ -1441,6 +1637,36 @@
|
|||
|
||||
break;
|
||||
|
||||
case cf2_cmdHSBW:
|
||||
if ( !font->isT1 )
|
||||
{
|
||||
FT_TRACE4(( " unknown op (%d)\n", op1 ));
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
|
||||
orig_x = x = ADD_LONG( builder->pos_x, top[0] );
|
||||
orig_y = y = builder->pos_y;
|
||||
|
||||
FT_UNUSED( orig_y );
|
||||
|
||||
/* the `metrics_only' indicates that we only want to compute */
|
||||
/* the glyph's metrics (lsb + advance width), not load the */
|
||||
/* rest of it; so exit immediately */
|
||||
if ( builder->metrics_only )
|
||||
return FT_Err_Ok;
|
||||
}
|
||||
break;
|
||||
|
||||
case cf2_cmdENDCHAR:
|
||||
FT_TRACE4(( " endchar\n" ));
|
||||
|
||||
|
@ -1461,8 +1687,8 @@
|
|||
/* close path if still open */
|
||||
cf2_glyphpath_closeOpenPath( &glyphPath );
|
||||
|
||||
/* disable seac for CFF2 (charstring ending with args on stack) */
|
||||
if ( !font->isCFF2 && cf2_stack_count( opStack ) > 1 )
|
||||
/* disable seac for CFF2 and Type1 (charstring ending with args on stack) */
|
||||
if ( !font->isCFF2 && !font->isT1 && cf2_stack_count( opStack ) > 1 )
|
||||
{
|
||||
/* must be either 4 or 5 -- */
|
||||
/* this is a (deprecated) implied `seac' operator */
|
||||
|
@ -1606,6 +1832,13 @@
|
|||
if ( font->decoder->width_only )
|
||||
goto exit;
|
||||
|
||||
if ( font->isT1 && !decoder->flex_state )
|
||||
{
|
||||
if ( builder->parse_state == T1_Parse_Start )
|
||||
goto Syntax_Error;
|
||||
builder->parse_state = T1_Parse_Have_Moveto;
|
||||
}
|
||||
|
||||
curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) );
|
||||
curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
|
||||
|
||||
|
@ -1626,6 +1859,13 @@
|
|||
if ( font->decoder->width_only )
|
||||
goto exit;
|
||||
|
||||
if ( font->isT1 && !decoder->flex_state )
|
||||
{
|
||||
if ( builder->parse_state == T1_Parse_Start )
|
||||
goto Syntax_Error;
|
||||
builder->parse_state = T1_Parse_Have_Moveto;
|
||||
}
|
||||
|
||||
curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
|
||||
|
||||
cf2_glyphpath_moveTo( &glyphPath, curX, curY );
|
||||
|
|
Loading…
Reference in New Issue