📄 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; } /*************************************************************************/ /* */ /* <Function> */ /* TT_Clear_CodeRange */ /* */ /* <Description> */ /* Clears a code range. */ /* */ /* <Input> */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -