📄 ttinterp.c
字号:
/***************************************************************************/
/* */
/* ttinterp.c */
/* */
/* TrueType bytecode interpreter (body). */
/* */
/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_CALC_H
#include FT_TRIGONOMETRY_H
#include FT_SYSTEM_H
#include "ttinterp.h"
#include "tterrors.h"
#ifdef TT_USE_BYTECODE_INTERPRETER
#define TT_MULFIX FT_MulFix
#define TT_MULDIV FT_MulDiv
#define TT_MULDIV_NO_ROUND FT_MulDiv_No_Round
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_ttinterp
/*************************************************************************/
/* */
/* In order to detect infinite loops in the code, we set up a counter */
/* within the run loop. A single stroke of interpretation is now */
/* limited to a maximal number of opcodes defined below. */
/* */
#define MAX_RUNNABLE_OPCODES 1000000L
/*************************************************************************/
/* */
/* There are two kinds of implementations: */
/* */
/* a. static implementation */
/* */
/* The current execution context is a static variable, which fields */
/* are accessed directly by the interpreter during execution. The */
/* context is named `cur'. */
/* */
/* This version is non-reentrant, of course. */
/* */
/* b. indirect implementation */
/* */
/* The current execution context is passed to _each_ function as its */
/* first argument, and each field is thus accessed indirectly. */
/* */
/* This version is fully re-entrant. */
/* */
/* The idea is that an indirect implementation may be slower to execute */
/* on low-end processors that are used in some systems (like 386s or */
/* even 486s). */
/* */
/* As a consequence, the indirect implementation is now the default, as */
/* its performance costs can be considered negligible in our context. */
/* Note, however, that we kept the same source with macros because: */
/* */
/* - The code is kept very close in design to the Pascal code used for */
/* development. */
/* */
/* - It's much more readable that way! */
/* */
/* - It's still open to experimentation and tuning. */
/* */
/*************************************************************************/
#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER /* indirect implementation */
#define CUR (*exc) /* see ttobjs.h */
/*************************************************************************/
/* */
/* This macro is used whenever `exec' is unused in a function, to avoid */
/* stupid warnings from pedantic compilers. */
/* */
#define FT_UNUSED_EXEC FT_UNUSED( exc )
#else /* static implementation */
#define CUR cur
#define FT_UNUSED_EXEC int __dummy = __dummy
static
TT_ExecContextRec cur; /* static exec. context variable */
/* apparently, we have a _lot_ of direct indexing when accessing */
/* the static `cur', which makes the code bigger (due to all the */
/* four bytes addresses). */
#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
/*************************************************************************/
/* */
/* The instruction argument stack. */
/* */
#define INS_ARG EXEC_OP_ FT_Long* args /* see ttobjs.h for EXEC_OP_ */
/*************************************************************************/
/* */
/* This macro is used whenever `args' is unused in a function, to avoid */
/* stupid warnings from pedantic compilers. */
/* */
#define FT_UNUSED_ARG FT_UNUSED_EXEC; FT_UNUSED( args )
/*************************************************************************/
/* */
/* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to */
/* increase readability of the code. */
/* */
/*************************************************************************/
#define SKIP_Code() \
SkipCode( EXEC_ARG )
#define GET_ShortIns() \
GetShortIns( EXEC_ARG )
#define NORMalize( x, y, v ) \
Normalize( EXEC_ARG_ x, y, v )
#define SET_SuperRound( scale, flags ) \
SetSuperRound( EXEC_ARG_ scale, flags )
#define ROUND_None( d, c ) \
Round_None( EXEC_ARG_ d, c )
#define INS_Goto_CodeRange( range, ip ) \
Ins_Goto_CodeRange( EXEC_ARG_ range, ip )
#define CUR_Func_move( z, p, d ) \
CUR.func_move( EXEC_ARG_ z, p, d )
#define CUR_Func_move_orig( z, p, d ) \
CUR.func_move_orig( EXEC_ARG_ z, p, d )
#define CUR_Func_round( d, c ) \
CUR.func_round( EXEC_ARG_ d, c )
#define CUR_Func_read_cvt( index ) \
CUR.func_read_cvt( EXEC_ARG_ index )
#define CUR_Func_write_cvt( index, val ) \
CUR.func_write_cvt( EXEC_ARG_ index, val )
#define CUR_Func_move_cvt( index, val ) \
CUR.func_move_cvt( EXEC_ARG_ index, val )
#define CURRENT_Ratio() \
Current_Ratio( EXEC_ARG )
#define CURRENT_Ppem() \
Current_Ppem( EXEC_ARG )
#define CUR_Ppem() \
Cur_PPEM( EXEC_ARG )
#define INS_SxVTL( a, b, c, d ) \
Ins_SxVTL( EXEC_ARG_ a, b, c, d )
#define COMPUTE_Funcs() \
Compute_Funcs( EXEC_ARG )
#define COMPUTE_Round( a ) \
Compute_Round( EXEC_ARG_ a )
#define COMPUTE_Point_Displacement( a, b, c, d ) \
Compute_Point_Displacement( EXEC_ARG_ a, b, c, d )
#define MOVE_Zp2_Point( a, b, c, t ) \
Move_Zp2_Point( EXEC_ARG_ a, b, c, t )
#define CUR_Func_project( v1, v2 ) \
CUR.func_project( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
#define CUR_Func_dualproj( v1, v2 ) \
CUR.func_dualproj( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
#define CUR_fast_project( v ) \
CUR.func_project( EXEC_ARG_ (v)->x, (v)->y )
#define CUR_fast_dualproj( v ) \
CUR.func_dualproj( EXEC_ARG_ (v)->x, (v)->y )
/*************************************************************************/
/* */
/* Instruction dispatch function, as used by the interpreter. */
/* */
typedef void (*TInstruction_Function)( INS_ARG );
/*************************************************************************/
/* */
/* A simple bounds-checking macro. */
/* */
#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) )
#undef SUCCESS
#define SUCCESS 0
#undef FAILURE
#define FAILURE 1
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
#define GUESS_VECTOR( V ) \
if ( CUR.face->unpatented_hinting ) \
{ \
CUR.GS.V.x = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0x4000 : 0 ); \
CUR.GS.V.y = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0 : 0x4000 ); \
}
#else
#define GUESS_VECTOR( V )
#endif
/*************************************************************************/
/* */
/* CODERANGE FUNCTIONS */
/* */
/*************************************************************************/
/*************************************************************************/
/* */
/* <Function> */
/* TT_Goto_CodeRange */
/* */
/* <Description> */
/* Switches to a new code range (updates the code related elements in */
/* `exec', and `IP'). */
/* */
/* <Input> */
/* range :: The new execution code range. */
/* */
/* IP :: The new IP in the new code range. */
/* */
/* <InOut> */
/* exec :: The target execution context. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
TT_Goto_CodeRange( TT_ExecContext exec,
FT_Int range,
FT_Long IP )
{
TT_CodeRange* coderange;
FT_ASSERT( range >= 1 && range <= 3 );
coderange = &exec->codeRangeTable[range - 1];
FT_ASSERT( coderange->base != NULL );
/* NOTE: Because the last instruction of a program may be a CALL */
/* which will return to the first byte *after* the code */
/* range, we test for IP <= Size instead of IP < Size. */
/* */
FT_ASSERT( (FT_ULong)IP <= coderange->size );
exec->code = coderange->base;
exec->codeSize = coderange->size;
exec->IP = IP;
exec->curRange = range;
return TT_Err_Ok;
}
/*************************************************************************/
/* */
/* <Function> */
/* TT_Set_CodeRange */
/* */
/* <Description> */
/* Sets a code range. */
/* */
/* <Input> */
/* range :: The code range index. */
/* */
/* base :: The new code base. */
/* */
/* length :: The range size in bytes. */
/* */
/* <InOut> */
/* exec :: The target execution context. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
TT_Set_CodeRange( TT_ExecContext exec,
FT_Int range,
void* base,
FT_Long length )
{
FT_ASSERT( range >= 1 && range <= 3 );
exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
exec->codeRangeTable[range - 1].size = length;
return TT_Err_Ok;
}
/*************************************************************************/
/* */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -