ttinterp.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:250k
- /*************************************************************************/
- /* */
- /* CEILING[]: CEILING */
- /* Opcode range: 0x67 */
- /* Stack: f26.6 --> f26.6 */
- /* */
- static void
- Ins_CEILING( INS_ARG )
- {
- DO_CEILING
- }
- /*************************************************************************/
- /* */
- /* RS[]: Read Store */
- /* Opcode range: 0x43 */
- /* Stack: uint32 --> uint32 */
- /* */
- static void
- Ins_RS( INS_ARG )
- {
- DO_RS
- }
- /*************************************************************************/
- /* */
- /* WS[]: Write Store */
- /* Opcode range: 0x42 */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_WS( INS_ARG )
- {
- DO_WS
- }
- /*************************************************************************/
- /* */
- /* WCVTP[]: Write CVT in Pixel units */
- /* Opcode range: 0x44 */
- /* Stack: f26.6 uint32 --> */
- /* */
- static void
- Ins_WCVTP( INS_ARG )
- {
- DO_WCVTP
- }
- /*************************************************************************/
- /* */
- /* WCVTF[]: Write CVT in Funits */
- /* Opcode range: 0x70 */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_WCVTF( INS_ARG )
- {
- DO_WCVTF
- }
- /*************************************************************************/
- /* */
- /* RCVT[]: Read CVT */
- /* Opcode range: 0x45 */
- /* Stack: uint32 --> f26.6 */
- /* */
- static void
- Ins_RCVT( INS_ARG )
- {
- DO_RCVT
- }
- /*************************************************************************/
- /* */
- /* AA[]: Adjust Angle */
- /* Opcode range: 0x7F */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_AA( INS_ARG )
- {
- /* intentionally no longer supported */
- }
- /*************************************************************************/
- /* */
- /* DEBUG[]: DEBUG. Unsupported. */
- /* Opcode range: 0x4F */
- /* Stack: uint32 --> */
- /* */
- /* Note: The original instruction pops a value from the stack. */
- /* */
- static void
- Ins_DEBUG( INS_ARG )
- {
- DO_DEBUG
- }
- /*************************************************************************/
- /* */
- /* ROUND[ab]: ROUND value */
- /* Opcode range: 0x68-0x6B */
- /* Stack: f26.6 --> f26.6 */
- /* */
- static void
- Ins_ROUND( INS_ARG )
- {
- DO_ROUND
- }
- /*************************************************************************/
- /* */
- /* NROUND[ab]: No ROUNDing of value */
- /* Opcode range: 0x6C-0x6F */
- /* Stack: f26.6 --> f26.6 */
- /* */
- static void
- Ins_NROUND( INS_ARG )
- {
- DO_NROUND
- }
- /*************************************************************************/
- /* */
- /* MAX[]: MAXimum */
- /* Opcode range: 0x68 */
- /* Stack: int32? int32? --> int32 */
- /* */
- static void
- Ins_MAX( INS_ARG )
- {
- DO_MAX
- }
- /*************************************************************************/
- /* */
- /* MIN[]: MINimum */
- /* Opcode range: 0x69 */
- /* Stack: int32? int32? --> int32 */
- /* */
- static void
- Ins_MIN( INS_ARG )
- {
- DO_MIN
- }
- #endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
- /*************************************************************************/
- /* */
- /* The following functions are called as is within the switch statement. */
- /* */
- /*************************************************************************/
- /*************************************************************************/
- /* */
- /* MINDEX[]: Move INDEXed element */
- /* Opcode range: 0x26 */
- /* Stack: int32? --> StkElt */
- /* */
- static void
- Ins_MINDEX( INS_ARG )
- {
- FT_Long L, K;
- L = args[0];
- if ( L <= 0 || L > CUR.args )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- K = CUR.stack[CUR.args - L];
- FT_ARRAY_MOVE( &CUR.stack[CUR.args - L ],
- &CUR.stack[CUR.args - L + 1],
- ( L - 1 ) );
- CUR.stack[CUR.args - 1] = K;
- }
- /*************************************************************************/
- /* */
- /* ROLL[]: ROLL top three elements */
- /* Opcode range: 0x8A */
- /* Stack: 3 * StkElt --> 3 * StkElt */
- /* */
- static void
- Ins_ROLL( INS_ARG )
- {
- FT_Long A, B, C;
- FT_UNUSED_EXEC;
- A = args[2];
- B = args[1];
- C = args[0];
- args[2] = C;
- args[1] = A;
- args[0] = B;
- }
- /*************************************************************************/
- /* */
- /* MANAGING THE FLOW OF CONTROL */
- /* */
- /* Instructions appear in the specification's order. */
- /* */
- /*************************************************************************/
- static FT_Bool
- SkipCode( EXEC_OP )
- {
- CUR.IP += CUR.length;
- if ( CUR.IP < CUR.codeSize )
- {
- CUR.opcode = CUR.code[CUR.IP];
- CUR.length = opcode_length[CUR.opcode];
- if ( CUR.length < 0 )
- {
- if ( CUR.IP + 1 > CUR.codeSize )
- goto Fail_Overflow;
- CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
- }
- if ( CUR.IP + CUR.length <= CUR.codeSize )
- return SUCCESS;
- }
- Fail_Overflow:
- CUR.error = TT_Err_Code_Overflow;
- return FAILURE;
- }
- /*************************************************************************/
- /* */
- /* IF[]: IF test */
- /* Opcode range: 0x58 */
- /* Stack: StkElt --> */
- /* */
- static void
- Ins_IF( INS_ARG )
- {
- FT_Int nIfs;
- FT_Bool Out;
- if ( args[0] != 0 )
- return;
- nIfs = 1;
- Out = 0;
- do
- {
- if ( SKIP_Code() == FAILURE )
- return;
- switch ( CUR.opcode )
- {
- case 0x58: /* IF */
- nIfs++;
- break;
- case 0x1B: /* ELSE */
- Out = FT_BOOL( nIfs == 1 );
- break;
- case 0x59: /* EIF */
- nIfs--;
- Out = FT_BOOL( nIfs == 0 );
- break;
- }
- } while ( Out == 0 );
- }
- /*************************************************************************/
- /* */
- /* ELSE[]: ELSE */
- /* Opcode range: 0x1B */
- /* Stack: --> */
- /* */
- static void
- Ins_ELSE( INS_ARG )
- {
- FT_Int nIfs;
- FT_UNUSED_ARG;
- nIfs = 1;
- do
- {
- if ( SKIP_Code() == FAILURE )
- return;
- switch ( CUR.opcode )
- {
- case 0x58: /* IF */
- nIfs++;
- break;
- case 0x59: /* EIF */
- nIfs--;
- break;
- }
- } while ( nIfs != 0 );
- }
- /*************************************************************************/
- /* */
- /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS */
- /* */
- /* Instructions appear in the specification's order. */
- /* */
- /*************************************************************************/
- /*************************************************************************/
- /* */
- /* FDEF[]: Function DEFinition */
- /* Opcode range: 0x2C */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_FDEF( INS_ARG )
- {
- FT_ULong n;
- TT_DefRecord* rec;
- TT_DefRecord* limit;
- /* some font programs are broken enough to redefine functions! */
- /* We will then parse the current table. */
- rec = CUR.FDefs;
- limit = rec + CUR.numFDefs;
- n = args[0];
- for ( ; rec < limit; rec++ )
- {
- if ( rec->opc == n )
- break;
- }
- if ( rec == limit )
- {
- /* check that there is enough room for new functions */
- if ( CUR.numFDefs >= CUR.maxFDefs )
- {
- CUR.error = TT_Err_Too_Many_Function_Defs;
- return;
- }
- CUR.numFDefs++;
- }
- rec->range = CUR.curRange;
- rec->opc = n;
- rec->start = CUR.IP + 1;
- rec->active = TRUE;
- if ( n > CUR.maxFunc )
- CUR.maxFunc = n;
- /* Now skip the whole function definition. */
- /* We don't allow nested IDEFS & FDEFs. */
- while ( SKIP_Code() == SUCCESS )
- {
- switch ( CUR.opcode )
- {
- case 0x89: /* IDEF */
- case 0x2C: /* FDEF */
- CUR.error = TT_Err_Nested_DEFS;
- return;
- case 0x2D: /* ENDF */
- return;
- }
- }
- }
- /*************************************************************************/
- /* */
- /* ENDF[]: END Function definition */
- /* Opcode range: 0x2D */
- /* Stack: --> */
- /* */
- static void
- Ins_ENDF( INS_ARG )
- {
- TT_CallRec* pRec;
- FT_UNUSED_ARG;
- if ( CUR.callTop <= 0 ) /* We encountered an ENDF without a call */
- {
- CUR.error = TT_Err_ENDF_In_Exec_Stream;
- return;
- }
- CUR.callTop--;
- pRec = &CUR.callStack[CUR.callTop];
- pRec->Cur_Count--;
- CUR.step_ins = FALSE;
- if ( pRec->Cur_Count > 0 )
- {
- CUR.callTop++;
- CUR.IP = pRec->Cur_Restart;
- }
- else
- /* Loop through the current function */
- INS_Goto_CodeRange( pRec->Caller_Range,
- pRec->Caller_IP );
- /* Exit the current call frame. */
- /* NOTE: If the last instruction of a program is a */
- /* CALL or LOOPCALL, the return address is */
- /* always out of the code range. This is a */
- /* valid address, and it is why we do not test */
- /* the result of Ins_Goto_CodeRange() here! */
- }
- /*************************************************************************/
- /* */
- /* CALL[]: CALL function */
- /* Opcode range: 0x2B */
- /* Stack: uint32? --> */
- /* */
- static void
- Ins_CALL( INS_ARG )
- {
- FT_ULong F;
- TT_CallRec* pCrec;
- TT_DefRecord* def;
- /* first of all, check the index */
- F = args[0];
- if ( BOUNDS( F, CUR.maxFunc + 1 ) )
- goto Fail;
- /* Except for some old Apple fonts, all functions in a TrueType */
- /* font are defined in increasing order, starting from 0. This */
- /* means that we normally have */
- /* */
- /* CUR.maxFunc+1 == CUR.numFDefs */
- /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */
- /* */
- /* If this isn't true, we need to look up the function table. */
- def = CUR.FDefs + F;
- if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
- {
- /* look up the FDefs table */
- TT_DefRecord* limit;
- def = CUR.FDefs;
- limit = def + CUR.numFDefs;
- while ( def < limit && def->opc != F )
- def++;
- if ( def == limit )
- goto Fail;
- }
- /* check that the function is active */
- if ( !def->active )
- goto Fail;
- /* check the call stack */
- if ( CUR.callTop >= CUR.callSize )
- {
- CUR.error = TT_Err_Stack_Overflow;
- return;
- }
- pCrec = CUR.callStack + CUR.callTop;
- pCrec->Caller_Range = CUR.curRange;
- pCrec->Caller_IP = CUR.IP + 1;
- pCrec->Cur_Count = 1;
- pCrec->Cur_Restart = def->start;
- CUR.callTop++;
- INS_Goto_CodeRange( def->range,
- def->start );
- CUR.step_ins = FALSE;
- return;
- Fail:
- CUR.error = TT_Err_Invalid_Reference;
- }
- /*************************************************************************/
- /* */
- /* LOOPCALL[]: LOOP and CALL function */
- /* Opcode range: 0x2A */
- /* Stack: uint32? Eint16? --> */
- /* */
- static void
- Ins_LOOPCALL( INS_ARG )
- {
- FT_ULong F;
- TT_CallRec* pCrec;
- TT_DefRecord* def;
- /* first of all, check the index */
- F = args[1];
- if ( BOUNDS( F, CUR.maxFunc + 1 ) )
- goto Fail;
- /* Except for some old Apple fonts, all functions in a TrueType */
- /* font are defined in increasing order, starting from 0. This */
- /* means that we normally have */
- /* */
- /* CUR.maxFunc+1 == CUR.numFDefs */
- /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */
- /* */
- /* If this isn't true, we need to look up the function table. */
- def = CUR.FDefs + F;
- if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
- {
- /* look up the FDefs table */
- TT_DefRecord* limit;
- def = CUR.FDefs;
- limit = def + CUR.numFDefs;
- while ( def < limit && def->opc != F )
- def++;
- if ( def == limit )
- goto Fail;
- }
- /* check that the function is active */
- if ( !def->active )
- goto Fail;
- /* check stack */
- if ( CUR.callTop >= CUR.callSize )
- {
- CUR.error = TT_Err_Stack_Overflow;
- return;
- }
- if ( args[0] > 0 )
- {
- pCrec = CUR.callStack + CUR.callTop;
- pCrec->Caller_Range = CUR.curRange;
- pCrec->Caller_IP = CUR.IP + 1;
- pCrec->Cur_Count = (FT_Int)args[0];
- pCrec->Cur_Restart = def->start;
- CUR.callTop++;
- INS_Goto_CodeRange( def->range, def->start );
- CUR.step_ins = FALSE;
- }
- return;
- Fail:
- CUR.error = TT_Err_Invalid_Reference;
- }
- /*************************************************************************/
- /* */
- /* IDEF[]: Instruction DEFinition */
- /* Opcode range: 0x89 */
- /* Stack: Eint8 --> */
- /* */
- static void
- Ins_IDEF( INS_ARG )
- {
- TT_DefRecord* def;
- TT_DefRecord* limit;
- /* First of all, look for the same function in our table */
- def = CUR.IDefs;
- limit = def + CUR.numIDefs;
- for ( ; def < limit; def++ )
- if ( def->opc == (FT_ULong)args[0] )
- break;
- if ( def == limit )
- {
- /* check that there is enough room for a new instruction */
- if ( CUR.numIDefs >= CUR.maxIDefs )
- {
- CUR.error = TT_Err_Too_Many_Instruction_Defs;
- return;
- }
- CUR.numIDefs++;
- }
- def->opc = args[0];
- def->start = CUR.IP+1;
- def->range = CUR.curRange;
- def->active = TRUE;
- if ( (FT_ULong)args[0] > CUR.maxIns )
- CUR.maxIns = args[0];
- /* Now skip the whole function definition. */
- /* We don't allow nested IDEFs & FDEFs. */
- while ( SKIP_Code() == SUCCESS )
- {
- switch ( CUR.opcode )
- {
- case 0x89: /* IDEF */
- case 0x2C: /* FDEF */
- CUR.error = TT_Err_Nested_DEFS;
- return;
- case 0x2D: /* ENDF */
- return;
- }
- }
- }
- /*************************************************************************/
- /* */
- /* PUSHING DATA ONTO THE INTERPRETER STACK */
- /* */
- /* Instructions appear in the specification's order. */
- /* */
- /*************************************************************************/
- /*************************************************************************/
- /* */
- /* NPUSHB[]: PUSH N Bytes */
- /* Opcode range: 0x40 */
- /* Stack: --> uint32... */
- /* */
- static void
- Ins_NPUSHB( INS_ARG )
- {
- FT_UShort L, K;
- L = (FT_UShort)CUR.code[CUR.IP + 1];
- if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
- {
- CUR.error = TT_Err_Stack_Overflow;
- return;
- }
- for ( K = 1; K <= L; K++ )
- args[K - 1] = CUR.code[CUR.IP + K + 1];
- CUR.new_top += L;
- }
- /*************************************************************************/
- /* */
- /* NPUSHW[]: PUSH N Words */
- /* Opcode range: 0x41 */
- /* Stack: --> int32... */
- /* */
- static void
- Ins_NPUSHW( INS_ARG )
- {
- FT_UShort L, K;
- L = (FT_UShort)CUR.code[CUR.IP + 1];
- if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
- {
- CUR.error = TT_Err_Stack_Overflow;
- return;
- }
- CUR.IP += 2;
- for ( K = 0; K < L; K++ )
- args[K] = GET_ShortIns();
- CUR.step_ins = FALSE;
- CUR.new_top += L;
- }
- /*************************************************************************/
- /* */
- /* PUSHB[abc]: PUSH Bytes */
- /* Opcode range: 0xB0-0xB7 */
- /* Stack: --> uint32... */
- /* */
- static void
- Ins_PUSHB( INS_ARG )
- {
- FT_UShort L, K;
- L = (FT_UShort)( CUR.opcode - 0xB0 + 1 );
- if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
- {
- CUR.error = TT_Err_Stack_Overflow;
- return;
- }
- for ( K = 1; K <= L; K++ )
- args[K - 1] = CUR.code[CUR.IP + K];
- }
- /*************************************************************************/
- /* */
- /* PUSHW[abc]: PUSH Words */
- /* Opcode range: 0xB8-0xBF */
- /* Stack: --> int32... */
- /* */
- static void
- Ins_PUSHW( INS_ARG )
- {
- FT_UShort L, K;
- L = (FT_UShort)( CUR.opcode - 0xB8 + 1 );
- if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
- {
- CUR.error = TT_Err_Stack_Overflow;
- return;
- }
- CUR.IP++;
- for ( K = 0; K < L; K++ )
- args[K] = GET_ShortIns();
- CUR.step_ins = FALSE;
- }
- /*************************************************************************/
- /* */
- /* MANAGING THE GRAPHICS STATE */
- /* */
- /* Instructions appear in the specs' order. */
- /* */
- /*************************************************************************/
- /*************************************************************************/
- /* */
- /* GC[a]: Get Coordinate projected onto */
- /* Opcode range: 0x46-0x47 */
- /* Stack: uint32 --> f26.6 */
- /* */
- /* BULLSHIT: Measures from the original glyph must be taken along the */
- /* dual projection vector! */
- /* */
- static void
- Ins_GC( INS_ARG )
- {
- FT_ULong L;
- FT_F26Dot6 R;
- L = (FT_ULong)args[0];
- if ( BOUNDS( L, CUR.zp2.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- else
- R = 0;
- }
- else
- {
- if ( CUR.opcode & 1 )
- R = CUR_fast_dualproj( &CUR.zp2.org[L] );
- else
- R = CUR_fast_project( &CUR.zp2.cur[L] );
- }
- args[0] = R;
- }
- /*************************************************************************/
- /* */
- /* SCFS[]: Set Coordinate From Stack */
- /* Opcode range: 0x48 */
- /* Stack: f26.6 uint32 --> */
- /* */
- /* Formula: */
- /* */
- /* OA := OA + ( value - OA.p )/( f.p ) * f */
- /* */
- static void
- Ins_SCFS( INS_ARG )
- {
- FT_Long K;
- FT_UShort L;
- L = (FT_UShort)args[0];
- if ( BOUNDS( L, CUR.zp2.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- K = CUR_fast_project( &CUR.zp2.cur[L] );
- CUR_Func_move( &CUR.zp2, L, args[1] - K );
- /* not part of the specs, but here for safety */
- if ( CUR.GS.gep2 == 0 )
- CUR.zp2.org[L] = CUR.zp2.cur[L];
- }
- /*************************************************************************/
- /* */
- /* MD[a]: Measure Distance */
- /* Opcode range: 0x49-0x4A */
- /* Stack: uint32 uint32 --> f26.6 */
- /* */
- /* BULLSHIT: Measure taken in the original glyph must be along the dual */
- /* projection vector. */
- /* */
- /* Second BULLSHIT: Flag attributes are inverted! */
- /* 0 => measure distance in original outline */
- /* 1 => measure distance in grid-fitted outline */
- /* */
- /* Third one: `zp0 - zp1', and not `zp2 - zp1! */
- /* */
- static void
- Ins_MD( INS_ARG )
- {
- FT_UShort K, L;
- FT_F26Dot6 D;
- K = (FT_UShort)args[1];
- L = (FT_UShort)args[0];
- if( BOUNDS( L, CUR.zp0.n_points ) ||
- BOUNDS( K, CUR.zp1.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- D = 0;
- }
- else
- {
- if ( CUR.opcode & 1 )
- D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
- else
- D = CUR_Func_dualproj( CUR.zp0.org + L, CUR.zp1.org + K );
- }
- args[0] = D;
- }
- /*************************************************************************/
- /* */
- /* SDPVTL[a]: Set Dual PVector to Line */
- /* Opcode range: 0x86-0x87 */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_SDPVTL( INS_ARG )
- {
- FT_Long A, B, C;
- FT_UShort p1, p2; /* was FT_Int in pas type ERROR */
- p1 = (FT_UShort)args[1];
- p2 = (FT_UShort)args[0];
- if ( BOUNDS( p2, CUR.zp1.n_points ) ||
- BOUNDS( p1, CUR.zp2.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- {
- FT_Vector* v1 = CUR.zp1.org + p2;
- FT_Vector* v2 = CUR.zp2.org + p1;
- A = v1->x - v2->x;
- B = v1->y - v2->y;
- }
- if ( ( CUR.opcode & 1 ) != 0 )
- {
- C = B; /* counter clockwise rotation */
- B = A;
- A = -C;
- }
- NORMalize( A, B, &CUR.GS.dualVector );
- {
- FT_Vector* v1 = CUR.zp1.cur + p2;
- FT_Vector* v2 = CUR.zp2.cur + p1;
- A = v1->x - v2->x;
- B = v1->y - v2->y;
- }
- if ( ( CUR.opcode & 1 ) != 0 )
- {
- C = B; /* counter clockwise rotation */
- B = A;
- A = -C;
- }
- NORMalize( A, B, &CUR.GS.projVector );
- GUESS_VECTOR( freeVector );
- COMPUTE_Funcs();
- }
- /*************************************************************************/
- /* */
- /* SZP0[]: Set Zone Pointer 0 */
- /* Opcode range: 0x13 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SZP0( INS_ARG )
- {
- switch ( (FT_Int)args[0] )
- {
- case 0:
- CUR.zp0 = CUR.twilight;
- break;
- case 1:
- CUR.zp0 = CUR.pts;
- break;
- default:
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- CUR.GS.gep0 = (FT_UShort)args[0];
- }
- /*************************************************************************/
- /* */
- /* SZP1[]: Set Zone Pointer 1 */
- /* Opcode range: 0x14 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SZP1( INS_ARG )
- {
- switch ( (FT_Int)args[0] )
- {
- case 0:
- CUR.zp1 = CUR.twilight;
- break;
- case 1:
- CUR.zp1 = CUR.pts;
- break;
- default:
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- CUR.GS.gep1 = (FT_UShort)args[0];
- }
- /*************************************************************************/
- /* */
- /* SZP2[]: Set Zone Pointer 2 */
- /* Opcode range: 0x15 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SZP2( INS_ARG )
- {
- switch ( (FT_Int)args[0] )
- {
- case 0:
- CUR.zp2 = CUR.twilight;
- break;
- case 1:
- CUR.zp2 = CUR.pts;
- break;
- default:
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- CUR.GS.gep2 = (FT_UShort)args[0];
- }
- /*************************************************************************/
- /* */
- /* SZPS[]: Set Zone PointerS */
- /* Opcode range: 0x16 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SZPS( INS_ARG )
- {
- switch ( (FT_Int)args[0] )
- {
- case 0:
- CUR.zp0 = CUR.twilight;
- break;
- case 1:
- CUR.zp0 = CUR.pts;
- break;
- default:
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- CUR.zp1 = CUR.zp0;
- CUR.zp2 = CUR.zp0;
- CUR.GS.gep0 = (FT_UShort)args[0];
- CUR.GS.gep1 = (FT_UShort)args[0];
- CUR.GS.gep2 = (FT_UShort)args[0];
- }
- /*************************************************************************/
- /* */
- /* INSTCTRL[]: INSTruction ConTRoL */
- /* Opcode range: 0x8e */
- /* Stack: int32 int32 --> */
- /* */
- static void
- Ins_INSTCTRL( INS_ARG )
- {
- FT_Long K, L;
- K = args[1];
- L = args[0];
- if ( K < 1 || K > 2 )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- if ( L != 0 )
- L = K;
- CUR.GS.instruct_control = FT_BOOL(
- ( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );
- }
- /*************************************************************************/
- /* */
- /* SCANCTRL[]: SCAN ConTRoL */
- /* Opcode range: 0x85 */
- /* Stack: uint32? --> */
- /* */
- static void
- Ins_SCANCTRL( INS_ARG )
- {
- FT_Int A;
- /* Get Threshold */
- A = (FT_Int)( args[0] & 0xFF );
- if ( A == 0xFF )
- {
- CUR.GS.scan_control = TRUE;
- return;
- }
- else if ( A == 0 )
- {
- CUR.GS.scan_control = FALSE;
- return;
- }
- A *= 64;
- #if 0
- if ( ( args[0] & 0x100 ) != 0 && CUR.metrics.pointSize <= A )
- CUR.GS.scan_control = TRUE;
- #endif
- if ( ( args[0] & 0x200 ) != 0 && CUR.tt_metrics.rotated )
- CUR.GS.scan_control = TRUE;
- if ( ( args[0] & 0x400 ) != 0 && CUR.tt_metrics.stretched )
- CUR.GS.scan_control = TRUE;
- #if 0
- if ( ( args[0] & 0x800 ) != 0 && CUR.metrics.pointSize > A )
- CUR.GS.scan_control = FALSE;
- #endif
- if ( ( args[0] & 0x1000 ) != 0 && CUR.tt_metrics.rotated )
- CUR.GS.scan_control = FALSE;
- if ( ( args[0] & 0x2000 ) != 0 && CUR.tt_metrics.stretched )
- CUR.GS.scan_control = FALSE;
- }
- /*************************************************************************/
- /* */
- /* SCANTYPE[]: SCAN TYPE */
- /* Opcode range: 0x8D */
- /* Stack: uint32? --> */
- /* */
- static void
- Ins_SCANTYPE( INS_ARG )
- {
- /* for compatibility with future enhancements, */
- /* we must ignore new modes */
- if ( args[0] >= 0 && args[0] <= 5 )
- {
- if ( args[0] == 3 )
- args[0] = 2;
- CUR.GS.scan_type = (FT_Int)args[0];
- }
- }
- /*************************************************************************/
- /* */
- /* MANAGING OUTLINES */
- /* */
- /* Instructions appear in the specification's order. */
- /* */
- /*************************************************************************/
- /*************************************************************************/
- /* */
- /* FLIPPT[]: FLIP PoinT */
- /* Opcode range: 0x80 */
- /* Stack: uint32... --> */
- /* */
- static void
- Ins_FLIPPT( INS_ARG )
- {
- FT_UShort point;
- FT_UNUSED_ARG;
- if ( CUR.top < CUR.GS.loop )
- {
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
- }
- while ( CUR.GS.loop > 0 )
- {
- CUR.args--;
- point = (FT_UShort)CUR.stack[CUR.args];
- if ( BOUNDS( point, CUR.pts.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- }
- else
- CUR.pts.tags[point] ^= FT_CURVE_TAG_ON;
- CUR.GS.loop--;
- }
- CUR.GS.loop = 1;
- CUR.new_top = CUR.args;
- }
- /*************************************************************************/
- /* */
- /* FLIPRGON[]: FLIP RanGe ON */
- /* Opcode range: 0x81 */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_FLIPRGON( INS_ARG )
- {
- FT_UShort I, K, L;
- K = (FT_UShort)args[1];
- L = (FT_UShort)args[0];
- if ( BOUNDS( K, CUR.pts.n_points ) ||
- BOUNDS( L, CUR.pts.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- for ( I = L; I <= K; I++ )
- CUR.pts.tags[I] |= FT_CURVE_TAG_ON;
- }
- /*************************************************************************/
- /* */
- /* FLIPRGOFF: FLIP RanGe OFF */
- /* Opcode range: 0x82 */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_FLIPRGOFF( INS_ARG )
- {
- FT_UShort I, K, L;
- K = (FT_UShort)args[1];
- L = (FT_UShort)args[0];
- if ( BOUNDS( K, CUR.pts.n_points ) ||
- BOUNDS( L, CUR.pts.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- for ( I = L; I <= K; I++ )
- CUR.pts.tags[I] &= ~FT_CURVE_TAG_ON;
- }
- static FT_Bool
- Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6* x,
- FT_F26Dot6* y,
- TT_GlyphZone zone,
- FT_UShort* refp )
- {
- TT_GlyphZoneRec zp;
- FT_UShort p;
- FT_F26Dot6 d;
- if ( CUR.opcode & 1 )
- {
- zp = CUR.zp0;
- p = CUR.GS.rp1;
- }
- else
- {
- zp = CUR.zp1;
- p = CUR.GS.rp2;
- }
- if ( BOUNDS( p, zp.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- *refp = 0;
- return FAILURE;
- }
- *zone = zp;
- *refp = p;
- d = CUR_Func_project( zp.cur + p, zp.org + p );
- #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
- if ( CUR.face->unpatented_hinting )
- {
- if ( CUR.GS.both_x_axis )
- {
- *x = d;
- *y = 0;
- }
- else
- {
- *x = 0;
- *y = d;
- }
- }
- else
- #endif
- {
- *x = TT_MULDIV( d,
- (FT_Long)CUR.GS.freeVector.x * 0x10000L,
- CUR.F_dot_P );
- *y = TT_MULDIV( d,
- (FT_Long)CUR.GS.freeVector.y * 0x10000L,
- CUR.F_dot_P );
- }
- return SUCCESS;
- }
- static void
- Move_Zp2_Point( EXEC_OP_ FT_UShort point,
- FT_F26Dot6 dx,
- FT_F26Dot6 dy,
- FT_Bool touch )
- {
- #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
- if ( CUR.face->unpatented_hinting )
- {
- if ( CUR.GS.both_x_axis )
- {
- CUR.zp2.cur[point].x += dx;
- if ( touch )
- CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
- }
- else
- {
- CUR.zp2.cur[point].y += dy;
- if ( touch )
- CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
- }
- return;
- }
- #endif
- if ( CUR.GS.freeVector.x != 0 )
- {
- CUR.zp2.cur[point].x += dx;
- if ( touch )
- CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
- }
- if ( CUR.GS.freeVector.y != 0 )
- {
- CUR.zp2.cur[point].y += dy;
- if ( touch )
- CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
- }
- }
- /*************************************************************************/
- /* */
- /* SHP[a]: SHift Point by the last point */
- /* Opcode range: 0x32-0x33 */
- /* Stack: uint32... --> */
- /* */
- static void
- Ins_SHP( INS_ARG )
- {
- TT_GlyphZoneRec zp;
- FT_UShort refp;
- FT_F26Dot6 dx,
- dy;
- FT_UShort point;
- FT_UNUSED_ARG;
- if ( CUR.top < CUR.GS.loop )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
- return;
- while ( CUR.GS.loop > 0 )
- {
- CUR.args--;
- point = (FT_UShort)CUR.stack[CUR.args];
- if ( BOUNDS( point, CUR.zp2.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- }
- else
- /* XXX: UNDOCUMENTED! SHP touches the points */
- MOVE_Zp2_Point( point, dx, dy, TRUE );
- CUR.GS.loop--;
- }
- CUR.GS.loop = 1;
- CUR.new_top = CUR.args;
- }
- /*************************************************************************/
- /* */
- /* SHC[a]: SHift Contour */
- /* Opcode range: 0x34-35 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SHC( INS_ARG )
- {
- TT_GlyphZoneRec zp;
- FT_UShort refp;
- FT_F26Dot6 dx,
- dy;
- FT_Short contour;
- FT_UShort first_point, last_point, i;
- contour = (FT_UShort)args[0];
- if ( BOUNDS( contour, CUR.pts.n_contours ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
- return;
- if ( contour == 0 )
- first_point = 0;
- else
- first_point = (FT_UShort)( CUR.pts.contours[contour - 1] + 1 -
- CUR.pts.first_point );
- last_point = (FT_UShort)( CUR.pts.contours[contour] -
- CUR.pts.first_point );
- /* XXX: this is probably wrong... at least it prevents memory */
- /* corruption when zp2 is the twilight zone */
- if ( last_point > CUR.zp2.n_points )
- {
- if ( CUR.zp2.n_points > 0 )
- last_point = (FT_UShort)(CUR.zp2.n_points - 1);
- else
- last_point = 0;
- }
- /* XXX: UNDOCUMENTED! SHC touches the points */
- for ( i = first_point; i <= last_point; i++ )
- {
- if ( zp.cur != CUR.zp2.cur || refp != i )
- MOVE_Zp2_Point( i, dx, dy, TRUE );
- }
- }
- /*************************************************************************/
- /* */
- /* SHZ[a]: SHift Zone */
- /* Opcode range: 0x36-37 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SHZ( INS_ARG )
- {
- TT_GlyphZoneRec zp;
- FT_UShort refp;
- FT_F26Dot6 dx,
- dy;
- FT_UShort last_point, i;
- if ( BOUNDS( args[0], 2 ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
- return;
- /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points. */
- /* Twilight zone has no contours, so use `n_points'. */
- /* Normal zone's `n_points' includes phantoms, so must */
- /* use end of last contour. */
- if ( CUR.GS.gep2 == 0 && CUR.zp2.n_points > 0 )
- last_point = (FT_UShort)( CUR.zp2.n_points - 1 );
- else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 )
- last_point = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] );
- else
- last_point = 0;
- /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
- for ( i = 0; i <= last_point; i++ )
- {
- if ( zp.cur != CUR.zp2.cur || refp != i )
- MOVE_Zp2_Point( i, dx, dy, FALSE );
- }
- }
- /*************************************************************************/
- /* */
- /* SHPIX[]: SHift points by a PIXel amount */
- /* Opcode range: 0x38 */
- /* Stack: f26.6 uint32... --> */
- /* */
- static void
- Ins_SHPIX( INS_ARG )
- {
- FT_F26Dot6 dx, dy;
- FT_UShort point;
- if ( CUR.top < CUR.GS.loop + 1 )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
- if ( CUR.face->unpatented_hinting )
- {
- if ( CUR.GS.both_x_axis )
- {
- dx = TT_MulFix14( args[0], 0x4000 );
- dy = 0;
- }
- else
- {
- dx = 0;
- dy = TT_MulFix14( args[0], 0x4000 );
- }
- }
- else
- #endif
- {
- dx = TT_MulFix14( args[0], CUR.GS.freeVector.x );
- dy = TT_MulFix14( args[0], CUR.GS.freeVector.y );
- }
- while ( CUR.GS.loop > 0 )
- {
- CUR.args--;
- point = (FT_UShort)CUR.stack[CUR.args];
- if ( BOUNDS( point, CUR.zp2.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- }
- else
- MOVE_Zp2_Point( point, dx, dy, TRUE );
- CUR.GS.loop--;
- }
- CUR.GS.loop = 1;
- CUR.new_top = CUR.args;
- }
- /*************************************************************************/
- /* */
- /* MSIRP[a]: Move Stack Indirect Relative Position */
- /* Opcode range: 0x3A-0x3B */
- /* Stack: f26.6 uint32 --> */
- /* */
- static void
- Ins_MSIRP( INS_ARG )
- {
- FT_UShort point;
- FT_F26Dot6 distance;
- point = (FT_UShort)args[0];
- if ( BOUNDS( point, CUR.zp1.n_points ) ||
- BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- /* XXX: UNDOCUMENTED! behaviour */
- if ( CUR.GS.gep1 == 0 ) /* if the point that is to be moved */
- /* is in twilight zone */
- {
- CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
- CUR_Func_move_orig( &CUR.zp1, point, args[1] );
- CUR.zp1.cur[point] = CUR.zp1.org[point];
- }
- distance = CUR_Func_project( CUR.zp1.cur + point,
- CUR.zp0.cur + CUR.GS.rp0 );
- CUR_Func_move( &CUR.zp1, point, args[1] - distance );
- CUR.GS.rp1 = CUR.GS.rp0;
- CUR.GS.rp2 = point;
- if ( ( CUR.opcode & 1 ) != 0 )
- CUR.GS.rp0 = point;
- }
- /*************************************************************************/
- /* */
- /* MDAP[a]: Move Direct Absolute Point */
- /* Opcode range: 0x2E-0x2F */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_MDAP( INS_ARG )
- {
- FT_UShort point;
- FT_F26Dot6 cur_dist,
- distance;
- point = (FT_UShort)args[0];
- if ( BOUNDS( point, CUR.zp0.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- /* XXX: Is there some undocumented feature while in the */
- /* twilight zone? ? */
- if ( ( CUR.opcode & 1 ) != 0 )
- {
- cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
- distance = CUR_Func_round( cur_dist,
- CUR.tt_metrics.compensations[0] ) - cur_dist;
- }
- else
- distance = 0;
- CUR_Func_move( &CUR.zp0, point, distance );
- CUR.GS.rp0 = point;
- CUR.GS.rp1 = point;
- }
- /*************************************************************************/
- /* */
- /* MIAP[a]: Move Indirect Absolute Point */
- /* Opcode range: 0x3E-0x3F */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_MIAP( INS_ARG )
- {
- FT_ULong cvtEntry;
- FT_UShort point;
- FT_F26Dot6 distance,
- org_dist;
- cvtEntry = (FT_ULong)args[1];
- point = (FT_UShort)args[0];
- if ( BOUNDS( point, CUR.zp0.n_points ) ||
- BOUNDS( cvtEntry, CUR.cvtSize ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- /* XXX: UNDOCUMENTED! */
- /* */
- /* The behaviour of an MIAP instruction is quite */
- /* different when used in the twilight zone. */
- /* */
- /* First, no control value cut-in test is performed */
- /* as it would fail anyway. Second, the original */
- /* point, i.e. (org_x,org_y) of zp0.point, is set */
- /* to the absolute, unrounded distance found in */
- /* the CVT. */
- /* */
- /* This is used in the CVT programs of the Microsoft */
- /* fonts Arial, Times, etc., in order to re-adjust */
- /* some key font heights. It allows the use of the */
- /* IP instruction in the twilight zone, which */
- /* otherwise would be `illegal' according to the */
- /* specification. */
- /* */
- /* We implement it with a special sequence for the */
- /* twilight zone. This is a bad hack, but it seems */
- /* to work. */
- distance = CUR_Func_read_cvt( cvtEntry );
- if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */
- {
- CUR.zp0.org[point].x = TT_MulFix14( distance, CUR.GS.freeVector.x );
- CUR.zp0.org[point].y = TT_MulFix14( distance, CUR.GS.freeVector.y ),
- CUR.zp0.cur[point] = CUR.zp0.org[point];
- }
- org_dist = CUR_fast_project( &CUR.zp0.cur[point] );
- if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cutin flag */
- {
- if ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin )
- distance = org_dist;
- distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );
- }
- CUR_Func_move( &CUR.zp0, point, distance - org_dist );
- CUR.GS.rp0 = point;
- CUR.GS.rp1 = point;
- }
- /*************************************************************************/
- /* */
- /* MDRP[abcde]: Move Direct Relative Point */
- /* Opcode range: 0xC0-0xDF */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_MDRP( INS_ARG )
- {
- FT_UShort point;
- FT_F26Dot6 org_dist, distance;
- point = (FT_UShort)args[0];
- if ( BOUNDS( point, CUR.zp1.n_points ) ||
- BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- /* XXX: Is there some undocumented feature while in the */
- /* twilight zone? */
- /* XXX: UNDOCUMENTED: twilight zone special case */
- if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )
- {
- FT_Vector* vec1 = &CUR.zp1.org[point];
- FT_Vector* vec2 = &CUR.zp0.org[CUR.GS.rp0];
- org_dist = CUR_Func_dualproj( vec1, vec2 );
- }
- else
- {
- FT_Vector* vec1 = &CUR.zp1.orus[point];
- FT_Vector* vec2 = &CUR.zp0.orus[CUR.GS.rp0];
- if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
- {
- /* this should be faster */
- org_dist = CUR_Func_dualproj( vec1, vec2 );
- org_dist = TT_MULFIX( org_dist, CUR.metrics.x_scale );
- }
- else
- {
- FT_Vector vec;
- vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
- vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
- org_dist = CUR_fast_dualproj( &vec );
- }
- }
- /* single width cut-in test */
- if ( FT_ABS( org_dist - CUR.GS.single_width_value ) <
- CUR.GS.single_width_cutin )
- {
- if ( org_dist >= 0 )
- org_dist = CUR.GS.single_width_value;
- else
- org_dist = -CUR.GS.single_width_value;
- }
- /* round flag */
- if ( ( CUR.opcode & 4 ) != 0 )
- distance = CUR_Func_round(
- org_dist,
- CUR.tt_metrics.compensations[CUR.opcode & 3] );
- else
- distance = ROUND_None(
- org_dist,
- CUR.tt_metrics.compensations[CUR.opcode & 3] );
- /* minimum distance flag */
- if ( ( CUR.opcode & 8 ) != 0 )
- {
- if ( org_dist >= 0 )
- {
- if ( distance < CUR.GS.minimum_distance )
- distance = CUR.GS.minimum_distance;
- }
- else
- {
- if ( distance > -CUR.GS.minimum_distance )
- distance = -CUR.GS.minimum_distance;
- }
- }
- /* now move the point */
- org_dist = CUR_Func_project( CUR.zp1.cur + point,
- CUR.zp0.cur + CUR.GS.rp0 );
- CUR_Func_move( &CUR.zp1, point, distance - org_dist );
- CUR.GS.rp1 = CUR.GS.rp0;
- CUR.GS.rp2 = point;
- if ( ( CUR.opcode & 16 ) != 0 )
- CUR.GS.rp0 = point;
- }
- /*************************************************************************/
- /* */
- /* MIRP[abcde]: Move Indirect Relative Point */
- /* Opcode range: 0xE0-0xFF */
- /* Stack: int32? uint32 --> */
- /* */
- static void
- Ins_MIRP( INS_ARG )
- {
- FT_UShort point;
- FT_ULong cvtEntry;
- FT_F26Dot6 cvt_dist,
- distance,
- cur_dist,
- org_dist;
- point = (FT_UShort)args[0];
- cvtEntry = (FT_ULong)( args[1] + 1 );
- /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
- if ( BOUNDS( point, CUR.zp1.n_points ) ||
- BOUNDS( cvtEntry, CUR.cvtSize + 1 ) ||
- BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- if ( !cvtEntry )
- cvt_dist = 0;
- else
- cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
- /* single width test */
- if ( FT_ABS( cvt_dist - CUR.GS.single_width_value ) <
- CUR.GS.single_width_cutin )
- {
- if ( cvt_dist >= 0 )
- cvt_dist = CUR.GS.single_width_value;
- else
- cvt_dist = -CUR.GS.single_width_value;
- }
- /* XXX: UNDOCUMENTED! -- twilight zone */
- if ( CUR.GS.gep1 == 0 )
- {
- CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
- TT_MulFix14( cvt_dist, CUR.GS.freeVector.x );
- CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +
- TT_MulFix14( cvt_dist, CUR.GS.freeVector.y );
- CUR.zp1.cur[point] = CUR.zp0.cur[point];
- }
- org_dist = CUR_Func_dualproj( &CUR.zp1.org[point],
- &CUR.zp0.org[CUR.GS.rp0] );
- cur_dist = CUR_Func_project ( &CUR.zp1.cur[point],
- &CUR.zp0.cur[CUR.GS.rp0] );
- /* auto-flip test */
- if ( CUR.GS.auto_flip )
- {
- if ( ( org_dist ^ cvt_dist ) < 0 )
- cvt_dist = -cvt_dist;
- }
- /* control value cutin and round */
- if ( ( CUR.opcode & 4 ) != 0 )
- {
- /* XXX: UNDOCUMENTED! Only perform cut-in test when both points */
- /* refer to the same zone. */
- if ( CUR.GS.gep0 == CUR.GS.gep1 )
- if ( FT_ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )
- cvt_dist = org_dist;
- distance = CUR_Func_round(
- cvt_dist,
- CUR.tt_metrics.compensations[CUR.opcode & 3] );
- }
- else
- distance = ROUND_None(
- cvt_dist,
- CUR.tt_metrics.compensations[CUR.opcode & 3] );
- /* minimum distance test */
- if ( ( CUR.opcode & 8 ) != 0 )
- {
- if ( org_dist >= 0 )
- {
- if ( distance < CUR.GS.minimum_distance )
- distance = CUR.GS.minimum_distance;
- }
- else
- {
- if ( distance > -CUR.GS.minimum_distance )
- distance = -CUR.GS.minimum_distance;
- }
- }
- CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
- CUR.GS.rp1 = CUR.GS.rp0;
- if ( ( CUR.opcode & 16 ) != 0 )
- CUR.GS.rp0 = point;
- /* XXX: UNDOCUMENTED! */
- CUR.GS.rp2 = point;
- }
- /*************************************************************************/
- /* */
- /* ALIGNRP[]: ALIGN Relative Point */
- /* Opcode range: 0x3C */
- /* Stack: uint32 uint32... --> */
- /* */
- static void
- Ins_ALIGNRP( INS_ARG )
- {
- FT_UShort point;
- FT_F26Dot6 distance;
- FT_UNUSED_ARG;
- if ( CUR.top < CUR.GS.loop ||
- BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- while ( CUR.GS.loop > 0 )
- {
- CUR.args--;
- point = (FT_UShort)CUR.stack[CUR.args];
- if ( BOUNDS( point, CUR.zp1.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- }
- else
- {
- distance = CUR_Func_project( CUR.zp1.cur + point,
- CUR.zp0.cur + CUR.GS.rp0 );
- CUR_Func_move( &CUR.zp1, point, -distance );
- }
- CUR.GS.loop--;
- }
- CUR.GS.loop = 1;
- CUR.new_top = CUR.args;
- }
- /*************************************************************************/
- /* */
- /* ISECT[]: moves point to InterSECTion */
- /* Opcode range: 0x0F */
- /* Stack: 5 * uint32 --> */
- /* */
- static void
- Ins_ISECT( INS_ARG )
- {
- FT_UShort point,
- a0, a1,
- b0, b1;
- FT_F26Dot6 discriminant;
- FT_F26Dot6 dx, dy,
- dax, day,
- dbx, dby;
- FT_F26Dot6 val;
- FT_Vector R;
- point = (FT_UShort)args[0];
- a0 = (FT_UShort)args[1];
- a1 = (FT_UShort)args[2];
- b0 = (FT_UShort)args[3];
- b1 = (FT_UShort)args[4];
- if ( BOUNDS( b0, CUR.zp0.n_points ) ||
- BOUNDS( b1, CUR.zp0.n_points ) ||
- BOUNDS( a0, CUR.zp1.n_points ) ||
- BOUNDS( a1, CUR.zp1.n_points ) ||
- BOUNDS( point, CUR.zp2.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
- dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
- dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x;
- day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y;
- dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x;
- dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y;
- CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
- discriminant = TT_MULDIV( dax, -dby, 0x40 ) +
- TT_MULDIV( day, dbx, 0x40 );
- if ( FT_ABS( discriminant ) >= 0x40 )
- {
- val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );
- R.x = TT_MULDIV( val, dax, discriminant );
- R.y = TT_MULDIV( val, day, discriminant );
- CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;
- CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
- }
- else
- {
- /* else, take the middle of the middles of A and B */
- CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x +
- CUR.zp1.cur[a1].x +
- CUR.zp0.cur[b0].x +
- CUR.zp0.cur[b1].x ) / 4;
- CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y +
- CUR.zp1.cur[a1].y +
- CUR.zp0.cur[b0].y +
- CUR.zp0.cur[b1].y ) / 4;
- }
- }
- /*************************************************************************/
- /* */
- /* ALIGNPTS[]: ALIGN PoinTS */
- /* Opcode range: 0x27 */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_ALIGNPTS( INS_ARG )
- {
- FT_UShort p1, p2;
- FT_F26Dot6 distance;
- p1 = (FT_UShort)args[0];
- p2 = (FT_UShort)args[1];
- if ( BOUNDS( args[0], CUR.zp1.n_points ) ||
- BOUNDS( args[1], CUR.zp0.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- distance = CUR_Func_project( CUR.zp0.cur + p2,
- CUR.zp1.cur + p1 ) / 2;
- CUR_Func_move( &CUR.zp1, p1, distance );
- CUR_Func_move( &CUR.zp0, p2, -distance );
- }
- /*************************************************************************/
- /* */
- /* IP[]: Interpolate Point */
- /* Opcode range: 0x39 */
- /* Stack: uint32... --> */
- /* */
- /* SOMETIMES, DUMBER CODE IS BETTER CODE */
- static void
- Ins_IP( INS_ARG )
- {
- FT_F26Dot6 old_range, cur_range;
- FT_Vector* orus_base;
- FT_Vector* cur_base;
- FT_Int twilight;
- FT_UNUSED_ARG;
- if ( CUR.top < CUR.GS.loop )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- /*
- * We need to deal in a special way with the twilight zone.
- * Otherwise, by definition, the value of CUR.twilight.orus[n] is (0,0),
- * for every n.
- */
- twilight = CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 || CUR.GS.gep2 == 0;
- if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- if ( twilight )
- orus_base = &CUR.zp0.org[CUR.GS.rp1];
- else
- orus_base = &CUR.zp0.orus[CUR.GS.rp1];
- cur_base = &CUR.zp0.cur[CUR.GS.rp1];
- /* XXX: There are some glyphs in some braindead but popular */
- /* fonts out there (e.g. [aeu]grave in monotype.ttf) */
- /* calling IP[] with bad values of rp[12]. */
- /* Do something sane when this odd thing happens. */
- if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ||
- BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) )
- {
- old_range = 0;
- cur_range = 0;
- }
- else
- {
- if ( twilight )
- old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2],
- orus_base );
- else
- old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2],
- orus_base );
- cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base );
- }
- for ( ; CUR.GS.loop > 0; --CUR.GS.loop )
- {
- FT_UInt point = (FT_UInt)CUR.stack[--CUR.args];
- FT_F26Dot6 org_dist, cur_dist, new_dist;
- /* check point bounds */
- if ( BOUNDS( point, CUR.zp2.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- continue;
- }
- if ( twilight )
- org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base );
- else
- org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base );
- cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base );
- new_dist = ( old_range != 0 )
- ? TT_MULDIV( org_dist, cur_range, old_range )
- : cur_dist;
- CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
- }
- CUR.GS.loop = 1;
- CUR.new_top = CUR.args;
- }
- /*************************************************************************/
- /* */
- /* UTP[a]: UnTouch Point */
- /* Opcode range: 0x29 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_UTP( INS_ARG )
- {
- FT_UShort point;
- FT_Byte mask;
- point = (FT_UShort)args[0];
- if ( BOUNDS( point, CUR.zp0.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- mask = 0xFF;
- if ( CUR.GS.freeVector.x != 0 )
- mask &= ~FT_CURVE_TAG_TOUCH_X;
- if ( CUR.GS.freeVector.y != 0 )
- mask &= ~FT_CURVE_TAG_TOUCH_Y;
- CUR.zp0.tags[point] &= mask;
- }
- /* Local variables for Ins_IUP: */
- typedef struct
- {
- FT_Vector* orgs; /* original and current coordinate */
- FT_Vector* curs; /* arrays */
- FT_Vector* orus;
- FT_UInt max_points;
- } IUP_WorkerRec, *IUP_Worker;
- static void
- _iup_worker_shift( IUP_Worker worker,
- FT_UInt p1,
- FT_UInt p2,
- FT_UInt p )
- {
- FT_UInt i;
- FT_F26Dot6 dx;
- dx = worker->curs[p].x - worker->orgs[p].x;
- if ( dx != 0 )
- {
- for ( i = p1; i < p; i++ )
- worker->curs[i].x += dx;
- for ( i = p + 1; i <= p2; i++ )
- worker->curs[i].x += dx;
- }
- }
- static void
- _iup_worker_interpolate( IUP_Worker worker,
- FT_UInt p1,
- FT_UInt p2,
- FT_UInt ref1,
- FT_UInt ref2 )
- {
- FT_UInt i;
- FT_F26Dot6 orus1, orus2, org1, org2, delta1, delta2;
- if ( p1 > p2 )
- return;
- if ( BOUNDS( ref1, worker->max_points ) ||
- BOUNDS( ref2, worker->max_points ) )
- return;
- orus1 = worker->orus[ref1].x;
- orus2 = worker->orus[ref2].x;
- if ( orus1 > orus2 )
- {
- FT_F26Dot6 tmp_o;
- FT_UInt tmp_r;
- tmp_o = orus1;
- orus1 = orus2;
- orus2 = tmp_o;
- tmp_r = ref1;
- ref1 = ref2;
- ref2 = tmp_r;
- }
- org1 = worker->orgs[ref1].x;
- org2 = worker->orgs[ref2].x;
- delta1 = worker->curs[ref1].x - org1;
- delta2 = worker->curs[ref2].x - org2;
- if ( orus1 == orus2 )
- {
- /* simple shift of untouched points */
- for ( i = p1; i <= p2; i++ )
- {
- FT_F26Dot6 x = worker->orgs[i].x;
- if ( x <= org1 )
- x += delta1;
- else
- x += delta2;
- worker->curs[i].x = x;
- }
- }
- else
- {
- FT_Fixed scale = 0;
- FT_Bool scale_valid = 0;
- /* interpolation */
- for ( i = p1; i <= p2; i++ )
- {
- FT_F26Dot6 x = worker->orgs[i].x;
- if ( x <= org1 )
- x += delta1;
- else if ( x >= org2 )
- x += delta2;
- else
- {
- if ( !scale_valid )
- {
- scale_valid = 1;
- scale = TT_MULDIV( org2 + delta2 - ( org1 + delta1 ),
- 0x10000, orus2 - orus1 );
- }
- x = ( org1 + delta1 ) +
- TT_MULFIX( worker->orus[i].x - orus1, scale );
- }
- worker->curs[i].x = x;
- }
- }
- }
- /*************************************************************************/
- /* */
- /* IUP[a]: Interpolate Untouched Points */
- /* Opcode range: 0x30-0x31 */
- /* Stack: --> */
- /* */
- static void
- Ins_IUP( INS_ARG )
- {
- IUP_WorkerRec V;
- FT_Byte mask;
- FT_UInt first_point; /* first point of contour */
- FT_UInt end_point; /* end point (last+1) of contour */
- FT_UInt first_touched; /* first touched point in contour */
- FT_UInt cur_touched; /* current touched point in contour */
- FT_UInt point; /* current point */
- FT_Short contour; /* current contour */
- FT_UNUSED_ARG;
- /* ignore empty outlines */
- if ( CUR.pts.n_contours == 0 )
- return;
- if ( CUR.opcode & 1 )
- {
- mask = FT_CURVE_TAG_TOUCH_X;
- V.orgs = CUR.pts.org;
- V.curs = CUR.pts.cur;
- V.orus = CUR.pts.orus;
- }
- else
- {
- mask = FT_CURVE_TAG_TOUCH_Y;
- V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
- V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
- V.orus = (FT_Vector*)( (FT_Pos*)CUR.pts.orus + 1 );
- }
- V.max_points = CUR.pts.n_points;
- contour = 0;
- point = 0;
- do
- {
- end_point = CUR.pts.contours[contour] - CUR.pts.first_point;
- first_point = point;
- while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 )
- point++;
- if ( point <= end_point )
- {
- first_touched = point;
- cur_touched = point;
- point++;
- while ( point <= end_point )
- {
- if ( ( CUR.pts.tags[point] & mask ) != 0 )
- {
- if ( point > 0 )
- _iup_worker_interpolate( &V,
- cur_touched + 1,
- point - 1,
- cur_touched,
- point );
- cur_touched = point;
- }
- point++;
- }
- if ( cur_touched == first_touched )
- _iup_worker_shift( &V, first_point, end_point, cur_touched );
- else
- {
- _iup_worker_interpolate( &V,
- (FT_UShort)( cur_touched + 1 ),
- end_point,
- cur_touched,
- first_touched );
- if ( first_touched > 0 )
- _iup_worker_interpolate( &V,
- first_point,
- first_touched - 1,
- cur_touched,
- first_touched );
- }
- }
- contour++;
- } while ( contour < CUR.pts.n_contours );
- }
- /*************************************************************************/
- /* */
- /* DELTAPn[]: DELTA exceptions P1, P2, P3 */
- /* Opcode range: 0x5D,0x71,0x72 */
- /* Stack: uint32 (2 * uint32)... --> */
- /* */
- static void
- Ins_DELTAP( INS_ARG )
- {
- FT_ULong k, nump;
- FT_UShort A;
- FT_ULong C;
- FT_Long B;
- #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
- /* Delta hinting is covered by US Patent 5159668. */
- if ( CUR.face->unpatented_hinting )
- {
- FT_Long n = args[0] * 2;
- if ( CUR.args < n )
- {
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
- }
- CUR.args -= n;
- CUR.new_top = CUR.args;
- return;
- }
- #endif
- nump = (FT_ULong)args[0]; /* some points theoretically may occur more
- than once, thus UShort isn't enough */
- for ( k = 1; k <= nump; k++ )
- {
- if ( CUR.args < 2 )
- {
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
- }
- CUR.args -= 2;
- A = (FT_UShort)CUR.stack[CUR.args + 1];
- B = CUR.stack[CUR.args];
- /* XXX: Because some popular fonts contain some invalid DeltaP */
- /* instructions, we simply ignore them when the stacked */
- /* point reference is off limit, rather than returning an */
- /* error. As a delta instruction doesn't change a glyph */
- /* in great ways, this shouldn't be a problem. */
- if ( !BOUNDS( A, CUR.zp0.n_points ) )
- {
- C = ( (FT_ULong)B & 0xF0 ) >> 4;
- switch ( CUR.opcode )
- {
- case 0x5D:
- break;
- case 0x71:
- C += 16;
- break;
- case 0x72:
- C += 32;
- break;
- }
- C += CUR.GS.delta_base;
- if ( CURRENT_Ppem() == (FT_Long)C )
- {
- B = ( (FT_ULong)B & 0xF ) - 8;
- if ( B >= 0 )
- B++;
- B = B * 64 / ( 1L << CUR.GS.delta_shift );
- CUR_Func_move( &CUR.zp0, A, B );
- }
- }
- else
- if ( CUR.pedantic_hinting )
- CUR.error = TT_Err_Invalid_Reference;
- }
- CUR.new_top = CUR.args;
- }
- /*************************************************************************/
- /* */
- /* DELTACn[]: DELTA exceptions C1, C2, C3 */
- /* Opcode range: 0x73,0x74,0x75 */
- /* Stack: uint32 (2 * uint32)... --> */
- /* */
- static void
- Ins_DELTAC( INS_ARG )
- {
- FT_ULong nump, k;
- FT_ULong A, C;
- FT_Long B;
- #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
- /* Delta hinting is covered by US Patent 5159668. */
- if ( CUR.face->unpatented_hinting )
- {
- FT_Long n = args[0] * 2;
- if ( CUR.args < n )
- {
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
- }
- CUR.args -= n;
- CUR.new_top = CUR.args;
- return;
- }
- #endif
- nump = (FT_ULong)args[0];
- for ( k = 1; k <= nump; k++ )
- {
- if ( CUR.args < 2 )
- {
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
- }
- CUR.args -= 2;
- A = (FT_ULong)CUR.stack[CUR.args + 1];
- B = CUR.stack[CUR.args];
- if ( BOUNDS( A, CUR.cvtSize ) )
- {
- if ( CUR.pedantic_hinting )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- }
- else
- {
- C = ( (FT_ULong)B & 0xF0 ) >> 4;
- switch ( CUR.opcode )
- {
- case 0x73:
- break;
- case 0x74:
- C += 16;
- break;
- case 0x75:
- C += 32;
- break;
- }
- C += CUR.GS.delta_base;
- if ( CURRENT_Ppem() == (FT_Long)C )
- {
- B = ( (FT_ULong)B & 0xF ) - 8;
- if ( B >= 0 )
- B++;
- B = B * 64 / ( 1L << CUR.GS.delta_shift );
- CUR_Func_move_cvt( A, B );
- }
- }
- }
- CUR.new_top = CUR.args;
- }
- /*************************************************************************/
- /* */
- /* MISC. INSTRUCTIONS */
- /* */
- /*************************************************************************/
- /*************************************************************************/
- /* */
- /* GETINFO[]: GET INFOrmation */
- /* Opcode range: 0x88 */
- /* Stack: uint32 --> uint32 */
- /* */
- static void
- Ins_GETINFO( INS_ARG )
- {
- FT_Long K;
- K = 0;
- /* We return MS rasterizer version 1.7 for the font scaler. */
- if ( ( args[0] & 1 ) != 0 )
- K = 35;
- /* Has the glyph been rotated? */
- if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated )
- K |= 0x80;
- /* Has the glyph been stretched? */
- if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched )
- K |= 1 << 8;
- /* Are we hinting for grayscale? */
- if ( ( args[0] & 32 ) != 0 && CUR.grayscale )
- K |= 1 << 12;
- args[0] = K;
- }
- static void
- Ins_UNKNOWN( INS_ARG )
- {
- TT_DefRecord* def = CUR.IDefs;
- TT_DefRecord* limit = def + CUR.numIDefs;
- FT_UNUSED_ARG;
- for ( ; def < limit; def++ )
- {
- if ( (FT_Byte)def->opc == CUR.opcode && def->active )
- {
- TT_CallRec* call;
- if ( CUR.callTop >= CUR.callSize )
- {
- CUR.error = TT_Err_Stack_Overflow;
- return;
- }
- call = CUR.callStack + CUR.callTop++;
- call->Caller_Range = CUR.curRange;
- call->Caller_IP = CUR.IP+1;
- call->Cur_Count = 1;
- call->Cur_Restart = def->start;
- INS_Goto_CodeRange( def->range, def->start );
- CUR.step_ins = FALSE;
- return;
- }
- }
- CUR.error = TT_Err_Invalid_Opcode;
- }
- #ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
- static
- TInstruction_Function Instruct_Dispatch[256] =
- {
- /* Opcodes are gathered in groups of 16. */
- /* Please keep the spaces as they are. */
- /* SVTCA y */ Ins_SVTCA,
- /* SVTCA x */ Ins_SVTCA,
- /* SPvTCA y */ Ins_SPVTCA,
- /* SPvTCA x */ Ins_SPVTCA,
- /* SFvTCA y */ Ins_SFVTCA,
- /* SFvTCA x */ Ins_SFVTCA,
- /* SPvTL // */ Ins_SPVTL,
- /* SPvTL + */ Ins_SPVTL,
- /* SFvTL // */ Ins_SFVTL,
- /* SFvTL + */ Ins_SFVTL,
- /* SPvFS */ Ins_SPVFS,
- /* SFvFS */ Ins_SFVFS,
- /* GPV */ Ins_GPV,
- /* GFV */ Ins_GFV,
- /* SFvTPv */ Ins_SFVTPV,
- /* ISECT */ Ins_ISECT,
- /* SRP0 */ Ins_SRP0,
- /* SRP1 */ Ins_SRP1,
- /* SRP2 */ Ins_SRP2,
- /* SZP0 */ Ins_SZP0,
- /* SZP1 */ Ins_SZP1,
- /* SZP2 */ Ins_SZP2,
- /* SZPS */ Ins_SZPS,
- /* SLOOP */ Ins_SLOOP,
- /* RTG */ Ins_RTG,
- /* RTHG */ Ins_RTHG,
- /* SMD */ Ins_SMD,
- /* ELSE */ Ins_ELSE,
- /* JMPR */ Ins_JMPR,
- /* SCvTCi */ Ins_SCVTCI,
- /* SSwCi */ Ins_SSWCI,
- /* SSW */ Ins_SSW,
- /* DUP */ Ins_DUP,
- /* POP */ Ins_POP,
- /* CLEAR */ Ins_CLEAR,
- /* SWAP */ Ins_SWAP,
- /* DEPTH */ Ins_DEPTH,
- /* CINDEX */ Ins_CINDEX,
- /* MINDEX */ Ins_MINDEX,
- /* AlignPTS */ Ins_ALIGNPTS,
- /* INS_0x28 */ Ins_UNKNOWN,
- /* UTP */ Ins_UTP,
- /* LOOPCALL */ Ins_LOOPCALL,
- /* CALL */ Ins_CALL,
- /* FDEF */ Ins_FDEF,
- /* ENDF */ Ins_ENDF,
- /* MDAP[0] */ Ins_MDAP,
- /* MDAP[1] */ Ins_MDAP,
- /* IUP[0] */ Ins_IUP,
- /* IUP[1] */ Ins_IUP,
- /* SHP[0] */ Ins_SHP,
- /* SHP[1] */ Ins_SHP,
- /* SHC[0] */ Ins_SHC,
- /* SHC[1] */ Ins_SHC,
- /* SHZ[0] */ Ins_SHZ,
- /* SHZ[1] */ Ins_SHZ,
- /* SHPIX */ Ins_SHPIX,
- /* IP */ Ins_IP,
- /* MSIRP[0] */ Ins_MSIRP,
- /* MSIRP[1] */ Ins_MSIRP,
- /* AlignRP */ Ins_ALIGNRP,
- /* RTDG */ Ins_RTDG,
- /* MIAP[0] */ Ins_MIAP,
- /* MIAP[1] */ Ins_MIAP,
- /* NPushB */ Ins_NPUSHB,
- /* NPushW */ Ins_NPUSHW,
- /* WS */ Ins_WS,
- /* RS */ Ins_RS,
- /* WCvtP */ Ins_WCVTP,
- /* RCvt */ Ins_RCVT,
- /* GC[0] */ Ins_GC,
- /* GC[1] */ Ins_GC,
- /* SCFS */ Ins_SCFS,
- /* MD[0] */ Ins_MD,
- /* MD[1] */ Ins_MD,
- /* MPPEM */ Ins_MPPEM,
- /* MPS */ Ins_MPS,
- /* FlipON */ Ins_FLIPON,
- /* FlipOFF */ Ins_FLIPOFF,
- /* DEBUG */ Ins_DEBUG,
- /* LT */ Ins_LT,
- /* LTEQ */ Ins_LTEQ,
- /* GT */ Ins_GT,
- /* GTEQ */ Ins_GTEQ,
- /* EQ */ Ins_EQ,
- /* NEQ */ Ins_NEQ,
- /* ODD */ Ins_ODD,
- /* EVEN */ Ins_EVEN,
- /* IF */ Ins_IF,
- /* EIF */ Ins_EIF,
- /* AND */ Ins_AND,
- /* OR */ Ins_OR,
- /* NOT */ Ins_NOT,
- /* DeltaP1 */ Ins_DELTAP,
- /* SDB */ Ins_SDB,
- /* SDS */ Ins_SDS,
- /* ADD */ Ins_ADD,
- /* SUB */ Ins_SUB,
- /* DIV */ Ins_DIV,
- /* MUL */ Ins_MUL,
- /* ABS */ Ins_ABS,
- /* NEG */ Ins_NEG,
- /* FLOOR */ Ins_FLOOR,
- /* CEILING */ Ins_CEILING,
- /* ROUND[0] */ Ins_ROUND,
- /* ROUND[1] */ Ins_ROUND,
- /* ROUND[2] */ Ins_ROUND,
- /* ROUND[3] */ Ins_ROUND,
- /* NROUND[0] */ Ins_NROUND,
- /* NROUND[1] */ Ins_NROUND,
- /* NROUND[2] */ Ins_NROUND,
- /* NROUND[3] */ Ins_NROUND,
- /* WCvtF */ Ins_WCVTF,
- /* DeltaP2 */ Ins_DELTAP,
- /* DeltaP3 */ Ins_DELTAP,
- /* DeltaCn[0] */ Ins_DELTAC,
- /* DeltaCn[1] */ Ins_DELTAC,
- /* DeltaCn[2] */ Ins_DELTAC,
- /* SROUND */ Ins_SROUND,
- /* S45Round */ Ins_S45ROUND,
- /* JROT */ Ins_JROT,
- /* JROF */ Ins_JROF,
- /* ROFF */ Ins_ROFF,
- /* INS_0x7B */ Ins_UNKNOWN,
- /* RUTG */ Ins_RUTG,
- /* RDTG */ Ins_RDTG,
- /* SANGW */ Ins_SANGW,
- /* AA */ Ins_AA,
- /* FlipPT */ Ins_FLIPPT,
- /* FlipRgON */ Ins_FLIPRGON,
- /* FlipRgOFF */ Ins_FLIPRGOFF,
- /* INS_0x83 */ Ins_UNKNOWN,
- /* INS_0x84 */ Ins_UNKNOWN,
- /* ScanCTRL */ Ins_SCANCTRL,
- /* SDPVTL[0] */ Ins_SDPVTL,
- /* SDPVTL[1] */ Ins_SDPVTL,
- /* GetINFO */ Ins_GETINFO,
- /* IDEF */ Ins_IDEF,
- /* ROLL */ Ins_ROLL,
- /* MAX */ Ins_MAX,
- /* MIN */ Ins_MIN,
- /* ScanTYPE */ Ins_SCANTYPE,
- /* InstCTRL */ Ins_INSTCTRL,
- /* INS_0x8F */ Ins_UNKNOWN,
- /* INS_0x90 */ Ins_UNKNOWN,
- /* INS_0x91 */ Ins_UNKNOWN,
- /* INS_0x92 */ Ins_UNKNOWN,
- /* INS_0x93 */ Ins_UNKNOWN,
- /* INS_0x94 */ Ins_UNKNOWN,
- /* INS_0x95 */ Ins_UNKNOWN,
- /* INS_0x96 */ Ins_UNKNOWN,
- /* INS_0x97 */ Ins_UNKNOWN,
- /* INS_0x98 */ Ins_UNKNOWN,
- /* INS_0x99 */ Ins_UNKNOWN,
- /* INS_0x9A */ Ins_UNKNOWN,
- /* INS_0x9B */ Ins_UNKNOWN,
- /* INS_0x9C */ Ins_UNKNOWN,
- /* INS_0x9D */ Ins_UNKNOWN,
- /* INS_0x9E */ Ins_UNKNOWN,
- /* INS_0x9F */ Ins_UNKNOWN,
- /* INS_0xA0 */ Ins_UNKNOWN,
- /* INS_0xA1 */ Ins_UNKNOWN,
- /* INS_0xA2 */ Ins_UNKNOWN,
- /* INS_0xA3 */ Ins_UNKNOWN,
- /* INS_0xA4 */ Ins_UNKNOWN,
- /* INS_0xA5 */ Ins_UNKNOWN,
- /* INS_0xA6 */ Ins_UNKNOWN,
- /* INS_0xA7 */ Ins_UNKNOWN,
- /* INS_0xA8 */ Ins_UNKNOWN,
- /* INS_0xA9 */ Ins_UNKNOWN,
- /* INS_0xAA */ Ins_UNKNOWN,
- /* INS_0xAB */ Ins_UNKNOWN,
- /* INS_0xAC */ Ins_UNKNOWN,
- /* INS_0xAD */ Ins_UNKNOWN,
- /* INS_0xAE */ Ins_UNKNOWN,
- /* INS_0xAF */ Ins_UNKNOWN,
- /* PushB[0] */ Ins_PUSHB,
- /* PushB[1] */ Ins_PUSHB,
- /* PushB[2] */ Ins_PUSHB,
- /* PushB[3] */ Ins_PUSHB,
- /* PushB[4] */ Ins_PUSHB,
- /* PushB[5] */ Ins_PUSHB,
- /* PushB[6] */ Ins_PUSHB,
- /* PushB[7] */ Ins_PUSHB,
- /* PushW[0] */ Ins_PUSHW,
- /* PushW[1] */ Ins_PUSHW,
- /* PushW[2] */ Ins_PUSHW,
- /* PushW[3] */ Ins_PUSHW,
- /* PushW[4] */ Ins_PUSHW,
- /* PushW[5] */ Ins_PUSHW,
- /* PushW[6] */ Ins_PUSHW,
- /* PushW[7] */ Ins_PUSHW,
- /* MDRP[00] */ Ins_MDRP,
- /* MDRP[01] */ Ins_MDRP,
- /* MDRP[02] */ Ins_MDRP,
- /* MDRP[03] */ Ins_MDRP,
- /* MDRP[04] */ Ins_MDRP,
- /* MDRP[05] */ Ins_MDRP,
- /* MDRP[06] */ Ins_MDRP,
- /* MDRP[07] */ Ins_MDRP,
- /* MDRP[08] */ Ins_MDRP,
- /* MDRP[09] */ Ins_MDRP,
- /* MDRP[10] */ Ins_MDRP,
- /* MDRP[11] */ Ins_MDRP,
- /* MDRP[12] */ Ins_MDRP,
- /* MDRP[13] */ Ins_MDRP,
- /* MDRP[14] */ Ins_MDRP,
- /* MDRP[15] */ Ins_MDRP,
- /* MDRP[16] */ Ins_MDRP,
- /* MDRP[17] */ Ins_MDRP,
- /* MDRP[18] */ Ins_MDRP,
- /* MDRP[19] */ Ins_MDRP,
- /* MDRP[20] */ Ins_MDRP,
- /* MDRP[21] */ Ins_MDRP,
- /* MDRP[22] */ Ins_MDRP,
- /* MDRP[23] */ Ins_MDRP,
- /* MDRP[24] */ Ins_MDRP,
- /* MDRP[25] */ Ins_MDRP,
- /* MDRP[26] */ Ins_MDRP,
- /* MDRP[27] */ Ins_MDRP,
- /* MDRP[28] */ Ins_MDRP,
- /* MDRP[29] */ Ins_MDRP,
- /* MDRP[30] */ Ins_MDRP,
- /* MDRP[31] */ Ins_MDRP,
- /* MIRP[00] */ Ins_MIRP,
- /* MIRP[01] */ Ins_MIRP,
- /* MIRP[02] */ Ins_MIRP,
- /* MIRP[03] */ Ins_MIRP,
- /* MIRP[04] */ Ins_MIRP,
- /* MIRP[05] */ Ins_MIRP,
- /* MIRP[06] */ Ins_MIRP,
- /* MIRP[07] */ Ins_MIRP,
- /* MIRP[08] */ Ins_MIRP,
- /* MIRP[09] */ Ins_MIRP,
- /* MIRP[10] */ Ins_MIRP,
- /* MIRP[11] */ Ins_MIRP,
- /* MIRP[12] */ Ins_MIRP,
- /* MIRP[13] */ Ins_MIRP,
- /* MIRP[14] */ Ins_MIRP,
- /* MIRP[15] */ Ins_MIRP,
- /* MIRP[16] */ Ins_MIRP,
- /* MIRP[17] */ Ins_MIRP,
- /* MIRP[18] */ Ins_MIRP,
- /* MIRP[19] */ Ins_MIRP,
- /* MIRP[20] */ Ins_MIRP,
- /* MIRP[21] */ Ins_MIRP,
- /* MIRP[22] */ Ins_MIRP,
- /* MIRP[23] */ Ins_MIRP,
- /* MIRP[24] */ Ins_MIRP,
- /* MIRP[25] */ Ins_MIRP,
- /* MIRP[26] */ Ins_MIRP,
- /* MIRP[27] */ Ins_MIRP,
- /* MIRP[28] */ Ins_MIRP,
- /* MIRP[29] */ Ins_MIRP,
- /* MIRP[30] */ Ins_MIRP,
- /* MIRP[31] */ Ins_MIRP
- };
- #endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
- /*************************************************************************/
- /* */
- /* RUN */
- /* */
- /* This function executes a run of opcodes. It will exit in the */
- /* following cases: */
- /* */
- /* - Errors (in which case it returns FALSE). */
- /* */
- /* - Reaching the end of the main code range (returns TRUE). */
- /* Reaching the end of a code range within a function call is an */
- /* error. */
- /* */
- /* - After executing one single opcode, if the flag `Instruction_Trap' */
- /* is set to TRUE (returns TRUE). */
- /* */
- /* On exit with TRUE, test IP < CodeSize to know whether it comes from */
- /* an instruction trap or a normal termination. */
- /* */
- /* */
- /* Note: The documented DEBUG opcode pops a value from the stack. This */
- /* behaviour is unsupported; here a DEBUG opcode is always an */
- /* error. */
- /* */
- /* */
- /* THIS IS THE INTERPRETER'S MAIN LOOP. */
- /* */
- /* Instructions appear in the specification's order. */
- /* */
- /*************************************************************************/
- /* documentation is in ttinterp.h */
- FT_EXPORT_DEF( FT_Error )
- TT_RunIns( TT_ExecContext exc )
- {
- FT_Long ins_counter = 0; /* executed instructions counter */
- #ifdef TT_CONFIG_OPTION_STATIC_RASTER
- cur = *exc;
- #endif
- /* set CVT functions */
- CUR.tt_metrics.ratio = 0;
- if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
- {
- /* non-square pixels, use the stretched routines */
- CUR.func_read_cvt = Read_CVT_Stretched;
- CUR.func_write_cvt = Write_CVT_Stretched;
- CUR.func_move_cvt = Move_CVT_Stretched;
- }
- else
- {
- /* square pixels, use normal routines */
- CUR.func_read_cvt = Read_CVT;
- CUR.func_write_cvt = Write_CVT;
- CUR.func_move_cvt = Move_CVT;
- }
- COMPUTE_Funcs();
- COMPUTE_Round( (FT_Byte)exc->GS.round_state );
- do
- {
- CUR.opcode = CUR.code[CUR.IP];
- if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
- {
- if ( CUR.IP + 1 > CUR.codeSize )
- goto LErrorCodeOverflow_;
- CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
- }
- if ( CUR.IP + CUR.length > CUR.codeSize )
- goto LErrorCodeOverflow_;
- /* First, let's check for empty stack and overflow */
- CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );
- /* `args' is the top of the stack once arguments have been popped. */
- /* One can also interpret it as the index of the last argument. */
- if ( CUR.args < 0 )
- {
- CUR.error = TT_Err_Too_Few_Arguments;
- goto LErrorLabel_;
- }
- CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
- /* `new_top' is the new top of the stack, after the instruction's */
- /* execution. `top' will be set to `new_top' after the `switch' */
- /* statement. */
- if ( CUR.new_top > CUR.stackSize )
- {
- CUR.error = TT_Err_Stack_Overflow;
- goto LErrorLabel_;
- }
- CUR.step_ins = TRUE;
- CUR.error = TT_Err_Ok;
- #ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
- {
- FT_Long* args = CUR.stack + CUR.args;
- FT_Byte opcode = CUR.opcode;
- #undef ARRAY_BOUND_ERROR
- #define ARRAY_BOUND_ERROR goto Set_Invalid_Ref
- switch ( opcode )
- {
- case 0x00: /* SVTCA y */
- case 0x01: /* SVTCA x */
- case 0x02: /* SPvTCA y */
- case 0x03: /* SPvTCA x */
- case 0x04: /* SFvTCA y */
- case 0x05: /* SFvTCA x */
- {
- FT_Short AA, BB;
- AA = (FT_Short)( ( opcode & 1 ) << 14 );
- BB = (FT_Short)( AA ^ 0x4000 );
- if ( opcode < 4 )
- {
- CUR.GS.projVector.x = AA;
- CUR.GS.projVector.y = BB;
- CUR.GS.dualVector.x = AA;
- CUR.GS.dualVector.y = BB;
- }
- else
- {
- GUESS_VECTOR( projVector );
- }
- if ( ( opcode & 2 ) == 0 )
- {
- CUR.GS.freeVector.x = AA;
- CUR.GS.freeVector.y = BB;
- }
- else
- {
- GUESS_VECTOR( freeVector );
- }
- COMPUTE_Funcs();
- }
- break;
- case 0x06: /* SPvTL // */
- case 0x07: /* SPvTL + */
- DO_SPVTL
- break;
- case 0x08: /* SFvTL // */
- case 0x09: /* SFvTL + */
- DO_SFVTL
- break;
- case 0x0A: /* SPvFS */
- DO_SPVFS
- break;
- case 0x0B: /* SFvFS */
- DO_SFVFS
- break;
- case 0x0C: /* GPV */
- DO_GPV
- break;
- case 0x0D: /* GFV */
- DO_GFV
- break;
- case 0x0E: /* SFvTPv */
- DO_SFVTPV
- break;
- case 0x0F: /* ISECT */
- Ins_ISECT( EXEC_ARG_ args );
- break;
- case 0x10: /* SRP0 */
- DO_SRP0
- break;
- case 0x11: /* SRP1 */
- DO_SRP1
- break;
- case 0x12: /* SRP2 */
- DO_SRP2
- break;
- case 0x13: /* SZP0 */
- Ins_SZP0( EXEC_ARG_ args );
- break;
- case 0x14: /* SZP1 */
- Ins_SZP1( EXEC_ARG_ args );
- break;
- case 0x15: /* SZP2 */
- Ins_SZP2( EXEC_ARG_ args );
- break;
- case 0x16: /* SZPS */
- Ins_SZPS( EXEC_ARG_ args );
- break;
- case 0x17: /* SLOOP */
- DO_SLOOP
- break;
- case 0x18: /* RTG */
- DO_RTG
- break;
- case 0x19: /* RTHG */
- DO_RTHG
- break;
- case 0x1A: /* SMD */
- DO_SMD
- break;
- case 0x1B: /* ELSE */
- Ins_ELSE( EXEC_ARG_ args );
- break;
- case 0x1C: /* JMPR */
- DO_JMPR
- break;
- case 0x1D: /* SCVTCI */
- DO_SCVTCI
- break;
- case 0x1E: /* SSWCI */
- DO_SSWCI
- break;
- case 0x1F: /* SSW */
- DO_SSW
- break;
- case 0x20: /* DUP */
- DO_DUP
- break;
- case 0x21: /* POP */
- /* nothing :-) */
- break;
- case 0x22: /* CLEAR */
- DO_CLEAR
- break;
- case 0x23: /* SWAP */
- DO_SWAP
- break;
- case 0x24: /* DEPTH */
- DO_DEPTH
- break;
- case 0x25: /* CINDEX */
- DO_CINDEX
- break;
- case 0x26: /* MINDEX */
- Ins_MINDEX( EXEC_ARG_ args );
- break;
- case 0x27: /* ALIGNPTS */
- Ins_ALIGNPTS( EXEC_ARG_ args );
- break;
- case 0x28: /* ???? */
- Ins_UNKNOWN( EXEC_ARG_ args );
- break;
- case 0x29: /* UTP */
- Ins_UTP( EXEC_ARG_ args );
- break;
- case 0x2A: /* LOOPCALL */
- Ins_LOOPCALL( EXEC_ARG_ args );
- break;
- case 0x2B: /* CALL */
- Ins_CALL( EXEC_ARG_ args );
- break;
- case 0x2C: /* FDEF */
- Ins_FDEF( EXEC_ARG_ args );
- break;
- case 0x2D: /* ENDF */
- Ins_ENDF( EXEC_ARG_ args );
- break;
- case 0x2E: /* MDAP */
- case 0x2F: /* MDAP */
- Ins_MDAP( EXEC_ARG_ args );
- break;
- case 0x30: /* IUP */
- case 0x31: /* IUP */
- Ins_IUP( EXEC_ARG_ args );
- break;
- case 0x32: /* SHP */
- case 0x33: /* SHP */
- Ins_SHP( EXEC_ARG_ args );
- break;
- case 0x34: /* SHC */
- case 0x35: /* SHC */
- Ins_SHC( EXEC_ARG_ args );
- break;
- case 0x36: /* SHZ */
- case 0x37: /* SHZ */
- Ins_SHZ( EXEC_ARG_ args );
- break;
- case 0x38: /* SHPIX */
- Ins_SHPIX( EXEC_ARG_ args );
- break;
- case 0x39: /* IP */
- Ins_IP( EXEC_ARG_ args );
- break;
- case 0x3A: /* MSIRP */
- case 0x3B: /* MSIRP */
- Ins_MSIRP( EXEC_ARG_ args );
- break;
- case 0x3C: /* AlignRP */
- Ins_ALIGNRP( EXEC_ARG_ args );
- break;
- case 0x3D: /* RTDG */
- DO_RTDG
- break;
- case 0x3E: /* MIAP */
- case 0x3F: /* MIAP */
- Ins_MIAP( EXEC_ARG_ args );
- break;
- case 0x40: /* NPUSHB */
- Ins_NPUSHB( EXEC_ARG_ args );
- break;
- case 0x41: /* NPUSHW */
- Ins_NPUSHW( EXEC_ARG_ args );
- break;
- case 0x42: /* WS */
- DO_WS
- break;
- Set_Invalid_Ref:
- CUR.error = TT_Err_Invalid_Reference;
- break;
- case 0x43: /* RS */
- DO_RS
- break;
- case 0x44: /* WCVTP */
- DO_WCVTP
- break;
- case 0x45: /* RCVT */
- DO_RCVT
- break;
- case 0x46: /* GC */
- case 0x47: /* GC */
- Ins_GC( EXEC_ARG_ args );
- break;
- case 0x48: /* SCFS */
- Ins_SCFS( EXEC_ARG_ args );
- break;
- case 0x49: /* MD */
- case 0x4A: /* MD */
- Ins_MD( EXEC_ARG_ args );
- break;
- case 0x4B: /* MPPEM */
- DO_MPPEM
- break;
- case 0x4C: /* MPS */
- DO_MPS
- break;
- case 0x4D: /* FLIPON */
- DO_FLIPON
- break;
- case 0x4E: /* FLIPOFF */
- DO_FLIPOFF
- break;
- case 0x4F: /* DEBUG */
- DO_DEBUG
- break;
- case 0x50: /* LT */
- DO_LT
- break;
- case 0x51: /* LTEQ */
- DO_LTEQ
- break;
- case 0x52: /* GT */
- DO_GT
- break;
- case 0x53: /* GTEQ */
- DO_GTEQ
- break;
- case 0x54: /* EQ */
- DO_EQ
- break;
- case 0x55: /* NEQ */
- DO_NEQ
- break;
- case 0x56: /* ODD */
- DO_ODD
- break;
- case 0x57: /* EVEN */
- DO_EVEN
- break;
- case 0x58: /* IF */
- Ins_IF( EXEC_ARG_ args );
- break;
- case 0x59: /* EIF */
- /* do nothing */
- break;
- case 0x5A: /* AND */
- DO_AND
- break;
- case 0x5B: /* OR */
- DO_OR
- break;
- case 0x5C: /* NOT */
- DO_NOT
- break;
- case 0x5D: /* DELTAP1 */
- Ins_DELTAP( EXEC_ARG_ args );
- break;
- case 0x5E: /* SDB */
- DO_SDB
- break;
- case 0x5F: /* SDS */
- DO_SDS
- break;
- case 0x60: /* ADD */
- DO_ADD
- break;
- case 0x61: /* SUB */
- DO_SUB
- break;
- case 0x62: /* DIV */
- DO_DIV
- break;
- case 0x63: /* MUL */
- DO_MUL
- break;
- case 0x64: /* ABS */
- DO_ABS
- break;
- case 0x65: /* NEG */
- DO_NEG
- break;
- case 0x66: /* FLOOR */
- DO_FLOOR
- break;
- case 0x67: /* CEILING */
- DO_CEILING
- break;
- case 0x68: /* ROUND */
- case 0x69: /* ROUND */
- case 0x6A: /* ROUND */
- case 0x6B: /* ROUND */
- DO_ROUND
- break;
- case 0x6C: /* NROUND */
- case 0x6D: /* NROUND */
- case 0x6E: /* NRRUND */
- case 0x6F: /* NROUND */
- DO_NROUND
- break;
- case 0x70: /* WCVTF */
- DO_WCVTF
- break;
- case 0x71: /* DELTAP2 */
- case 0x72: /* DELTAP3 */
- Ins_DELTAP( EXEC_ARG_ args );
- break;
- case 0x73: /* DELTAC0 */
- case 0x74: /* DELTAC1 */
- case 0x75: /* DELTAC2 */
- Ins_DELTAC( EXEC_ARG_ args );
- break;
- case 0x76: /* SROUND */
- DO_SROUND
- break;
- case 0x77: /* S45Round */
- DO_S45ROUND
- break;
- case 0x78: /* JROT */
- DO_JROT
- break;
- case 0x79: /* JROF */
- DO_JROF
- break;
- case 0x7A: /* ROFF */
- DO_ROFF
- break;
- case 0x7B: /* ???? */
- Ins_UNKNOWN( EXEC_ARG_ args );
- break;
- case 0x7C: /* RUTG */
- DO_RUTG
- break;
- case 0x7D: /* RDTG */
- DO_RDTG
- break;
- case 0x7E: /* SANGW */
- case 0x7F: /* AA */
- /* nothing - obsolete */
- break;
- case 0x80: /* FLIPPT */
- Ins_FLIPPT( EXEC_ARG_ args );
- break;
- case 0x81: /* FLIPRGON */
- Ins_FLIPRGON( EXEC_ARG_ args );
- break;
- case 0x82: /* FLIPRGOFF */
- Ins_FLIPRGOFF( EXEC_ARG_ args );
- break;
- case 0x83: /* UNKNOWN */
- case 0x84: /* UNKNOWN */
- Ins_UNKNOWN( EXEC_ARG_ args );
- break;
- case 0x85: /* SCANCTRL */
- Ins_SCANCTRL( EXEC_ARG_ args );
- break;
- case 0x86: /* SDPVTL */
- case 0x87: /* SDPVTL */
- Ins_SDPVTL( EXEC_ARG_ args );
- break;
- case 0x88: /* GETINFO */
- Ins_GETINFO( EXEC_ARG_ args );
- break;
- case 0x89: /* IDEF */
- Ins_IDEF( EXEC_ARG_ args );
- break;
- case 0x8A: /* ROLL */
- Ins_ROLL( EXEC_ARG_ args );
- break;
- case 0x8B: /* MAX */
- DO_MAX
- break;
- case 0x8C: /* MIN */
- DO_MIN
- break;
- case 0x8D: /* SCANTYPE */
- Ins_SCANTYPE( EXEC_ARG_ args );
- break;
- case 0x8E: /* INSTCTRL */
- Ins_INSTCTRL( EXEC_ARG_ args );
- break;
- case 0x8F:
- Ins_UNKNOWN( EXEC_ARG_ args );
- break;
- default:
- if ( opcode >= 0xE0 )
- Ins_MIRP( EXEC_ARG_ args );
- else if ( opcode >= 0xC0 )
- Ins_MDRP( EXEC_ARG_ args );
- else if ( opcode >= 0xB8 )
- Ins_PUSHW( EXEC_ARG_ args );
- else if ( opcode >= 0xB0 )
- Ins_PUSHB( EXEC_ARG_ args );
- else
- Ins_UNKNOWN( EXEC_ARG_ args );
- }
- }
- #else
- Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );
- #endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
- if ( CUR.error != TT_Err_Ok )
- {
- switch ( CUR.error )
- {
- case TT_Err_Invalid_Opcode: /* looking for redefined instructions */
- {
- TT_DefRecord* def = CUR.IDefs;
- TT_DefRecord* limit = def + CUR.numIDefs;
- for ( ; def < limit; def++ )
- {
- if ( def->active && CUR.opcode == (FT_Byte)def->opc )
- {
- TT_CallRec* callrec;
- if ( CUR.callTop >= CUR.callSize )
- {
- CUR.error = TT_Err_Invalid_Reference;
- goto LErrorLabel_;
- }
- callrec = &CUR.callStack[CUR.callTop];
- callrec->Caller_Range = CUR.curRange;
- callrec->Caller_IP = CUR.IP + 1;
- callrec->Cur_Count = 1;
- callrec->Cur_Restart = def->start;
- if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
- goto LErrorLabel_;
- goto LSuiteLabel_;
- }
- }
- }
- CUR.error = TT_Err_Invalid_Opcode;
- goto LErrorLabel_;
- #if 0
- break; /* Unreachable code warning suppression. */
- /* Leave to remind in case a later change the editor */
- /* to consider break; */
- #endif
- default:
- goto LErrorLabel_;
- #if 0
- break;
- #endif
- }
- }
- CUR.top = CUR.new_top;
- if ( CUR.step_ins )
- CUR.IP += CUR.length;
- /* increment instruction counter and check if we didn't */
- /* run this program for too long (e.g. infinite loops). */
- if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
- return TT_Err_Execution_Too_Long;
- LSuiteLabel_:
- if ( CUR.IP >= CUR.codeSize )
- {
- if ( CUR.callTop > 0 )
- {
- CUR.error = TT_Err_Code_Overflow;
- goto LErrorLabel_;
- }
- else
- goto LNo_Error_;
- }
- } while ( !CUR.instruction_trap );
- LNo_Error_:
- #ifdef TT_CONFIG_OPTION_STATIC_RASTER
- *exc = cur;
- #endif
- return TT_Err_Ok;
- LErrorCodeOverflow_:
- CUR.error = TT_Err_Code_Overflow;
- LErrorLabel_:
- #ifdef TT_CONFIG_OPTION_STATIC_RASTER
- *exc = cur;
- #endif
- return CUR.error;
- }
- #endif /* TT_USE_BYTECODE_INTERPRETER */
- /* END */