diff options
Diffstat (limited to 'Build/source/libs/libttf/ttinterp.c')
-rw-r--r-- | Build/source/libs/libttf/ttinterp.c | 6654 |
1 files changed, 0 insertions, 6654 deletions
diff --git a/Build/source/libs/libttf/ttinterp.c b/Build/source/libs/libttf/ttinterp.c deleted file mode 100644 index 9158feca799..00000000000 --- a/Build/source/libs/libttf/ttinterp.c +++ /dev/null @@ -1,6654 +0,0 @@ -/******************************************************************* - * - * ttinterp.c 3.1 - * - * TrueType bytecode intepreter. - * - * Copyright 1996-1999 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. - * - * - * Changes between 3.1 and 3.0: - * - * - A more relaxed version of the interpreter. It is now able to - * ignore errors like out-of-bound array access and writes in order - * to silently support broken glyphs (even if the results are not - * always pretty). - * - * Note that one can use the flag TTLOAD_PEDANTIC to force - * TrueType-compliant interpretation. - * - * - A big #if used to completely disable the interpreter, which - * is due to the Apple patents issues which emerged recently. - * - ******************************************************************/ - -#include "freetype.h" -#include "tttypes.h" -#include "ttdebug.h" -#include "ttcalc.h" -#include "ttmemory.h" -#include "ttinterp.h" - - -#ifdef TT_CONFIG_OPTION_NO_INTERPRETER - - LOCAL_FUNC - TT_Error RunIns( PExecution_Context exc ) - { - /* do nothing - always successful */ - (void)exc; - return TT_Err_Ok; - } - -#else - - -#ifdef DEBUG_INTERPRETER -#include <memory.h> -#include "ttdebug.h" - -/* Define the `getch()' function. On Unix systems, it is an alias */ -/* for `getchar()', and the debugger front end must ensure that the */ -/* `stdin' file descriptor is not in line-by-line input mode. */ -#ifdef OS2 -#include <conio.h> -#else -#define getch getchar -#endif - -#endif /* DEBUG_INTEPRETER */ - - -/* required by the tracing mode */ -#undef TT_COMPONENT -#define TT_COMPONENT trace_interp - - -/* In order to detect infinite loops in the code, we set-up */ -/* a counter within the run loop. a singly stroke of interpretation */ -/* is now limited to a maximum number of opcodes defined below.. */ -/* */ -#define MAX_RUNNABLE_OPCODES 1000000 - - -/* There are two kinds of implementations there: */ -/* */ -/* 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, however, fully re-entrant. */ -/* */ -/* */ -/* The idea is that an indirect implementation may be */ -/* slower to execute on the low-end processors that are */ -/* used in some systems (like 386s or even 486s). */ -/* */ -/* When the interpreter started, we had no idea of the */ -/* time that glyph hinting (i.e. executing instructions) */ -/* could take in the whole process of rendering a glyph, */ -/* and a 10 to 30% performance penalty on low-end systems */ -/* didn't seem much of a good idea. This question led us */ -/* to provide two distinct builds of the C version from */ -/* a single source, with the use of macros (again). */ -/* */ -/* Now that the engine is working (and working really */ -/* well!), it seems that the greatest time-consuming */ -/* factors are: file i/o, glyph loading, rasterizing and */ -/* _then_ glyph hinting! */ -/* */ -/* Tests performed with two versions of the 'fttimer' */ -/* program seem to indicate that hinting takes less than 5% */ -/* of the rendering process, which is dominated by glyph */ -/* loading and scan-line conversion by an high order of */ -/* magnitude. */ -/* */ -/* 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 one used for development. */ -/* */ -/* - it's much more readable that way! */ -/* */ -/* - it's still open to later experimentation and tuning */ - - - -#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER /* indirect implementation */ - -#define CUR (*exc) /* see ttobjs.h */ - -#else /* static implementation */ - -#define CUR cur - - static TExecution_Context 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 */ - - -#define INS_ARG EXEC_OPS PStorage args /* see ttobjs.h */ - -#define SKIP_Code() SkipCode( EXEC_ARG ) - -#define GET_ShortIns() GetShortIns( EXEC_ARG ) - -#define COMPUTE_Funcs() Compute_Funcs( EXEC_ARG ) - -#define NORMalize( x, y, v ) Normalize( EXEC_ARGS x, y, v ) - -#define SET_SuperRound( scale, flags ) \ - SetSuperRound( EXEC_ARGS scale, flags ) - -#define INS_Goto_CodeRange( range, ip ) \ - Ins_Goto_CodeRange( EXEC_ARGS range, ip ) - -#define CUR_Func_project( x, y ) CUR.func_project( EXEC_ARGS x, y ) -#define CUR_Func_move( z, p, d ) CUR.func_move( EXEC_ARGS z, p, d ) -#define CUR_Func_dualproj( x, y ) CUR.func_dualproj( EXEC_ARGS x, y ) -#define CUR_Func_freeProj( x, y ) CUR.func_freeProj( EXEC_ARGS x, y ) -#define CUR_Func_round( d, c ) CUR.func_round( EXEC_ARGS d, c ) - -#define CUR_Func_read_cvt( index ) \ - CUR.func_read_cvt( EXEC_ARGS index ) - -#define CUR_Func_write_cvt( index, val ) \ - CUR.func_write_cvt( EXEC_ARGS index, val ) - -#define CUR_Func_move_cvt( index, val ) \ - CUR.func_move_cvt( EXEC_ARGS index, val ) - -#define CURRENT_Ratio() Current_Ratio( EXEC_ARG ) -#define CURRENT_Ppem() Current_Ppem( EXEC_ARG ) - -#define CALC_Length() Calc_Length( EXEC_ARG ) - -#define INS_SxVTL( a, b, c, d ) Ins_SxVTL( EXEC_ARGS a, b, c, d ) - -#define COMPUTE_Point_Displacement( a, b, c, d ) \ - Compute_Point_Displacement( EXEC_ARGS a, b, c, d ) - -#define MOVE_Zp2_Point( a, b, c, t ) Move_Zp2_Point( EXEC_ARGS a, b, c, t ) - -#define CUR_Ppem() Cur_PPEM( EXEC_ARG ) - - /* Instruction dispatch function, as used by the interpreter */ - typedef void (*TInstruction_Function)( INS_ARG ); - -#define BOUNDS( x, n ) ( (x) >= (n) ) - - - -/*********************************************************************/ -/* */ -/* Before an opcode is executed, the interpreter verifies that */ -/* there are enough arguments on the stack, with the help of */ -/* the Pop_Push_Count table. */ -/* */ -/* For each opcode, the first column gives the number of arguments */ -/* that are popped from the stack; the second one gives the number */ -/* of those that are pushed in result. */ -/* */ -/* Note that for opcodes with a varying number of parameters, */ -/* either 0 or 1 arg is verified before execution, depending */ -/* on the nature of the instruction: */ -/* */ -/* - if the number of arguments is given by the bytecode */ -/* stream or the loop variable, 0 is chosen. */ -/* */ -/* - if the first argument is a count n that is followed */ -/* by arguments a1..an, then 1 is chosen. */ -/* */ -/*********************************************************************/ - -#undef PACK -#define PACK( x, y ) ((x << 4) | y) - - static const Byte Pop_Push_Count[256] = - { - /* opcodes are gathered in groups of 16 */ - /* please keep the spaces as they are */ - - /* SVTCA y */ PACK( 0, 0 ), - /* SVTCA x */ PACK( 0, 0 ), - /* SPvTCA y */ PACK( 0, 0 ), - /* SPvTCA x */ PACK( 0, 0 ), - /* SFvTCA y */ PACK( 0, 0 ), - /* SFvTCA x */ PACK( 0, 0 ), - /* SPvTL // */ PACK( 2, 0 ), - /* SPvTL + */ PACK( 2, 0 ), - /* SFvTL // */ PACK( 2, 0 ), - /* SFvTL + */ PACK( 2, 0 ), - /* SPvFS */ PACK( 2, 0 ), - /* SFvFS */ PACK( 2, 0 ), - /* GPV */ PACK( 0, 2 ), - /* GFV */ PACK( 0, 2 ), - /* SFvTPv */ PACK( 0, 0 ), - /* ISECT */ PACK( 5, 0 ), - - /* SRP0 */ PACK( 1, 0 ), - /* SRP1 */ PACK( 1, 0 ), - /* SRP2 */ PACK( 1, 0 ), - /* SZP0 */ PACK( 1, 0 ), - /* SZP1 */ PACK( 1, 0 ), - /* SZP2 */ PACK( 1, 0 ), - /* SZPS */ PACK( 1, 0 ), - /* SLOOP */ PACK( 1, 0 ), - /* RTG */ PACK( 0, 0 ), - /* RTHG */ PACK( 0, 0 ), - /* SMD */ PACK( 1, 0 ), - /* ELSE */ PACK( 0, 0 ), - /* JMPR */ PACK( 1, 0 ), - /* SCvTCi */ PACK( 1, 0 ), - /* SSwCi */ PACK( 1, 0 ), - /* SSW */ PACK( 1, 0 ), - - /* DUP */ PACK( 1, 2 ), - /* POP */ PACK( 1, 0 ), - /* CLEAR */ PACK( 0, 0 ), - /* SWAP */ PACK( 2, 2 ), - /* DEPTH */ PACK( 0, 1 ), - /* CINDEX */ PACK( 1, 1 ), - /* MINDEX */ PACK( 1, 0 ), - /* AlignPTS */ PACK( 2, 0 ), - /* INS_$28 */ PACK( 0, 0 ), - /* UTP */ PACK( 1, 0 ), - /* LOOPCALL */ PACK( 2, 0 ), - /* CALL */ PACK( 1, 0 ), - /* FDEF */ PACK( 1, 0 ), - /* ENDF */ PACK( 0, 0 ), - /* MDAP[0] */ PACK( 1, 0 ), - /* MDAP[1] */ PACK( 1, 0 ), - - /* IUP[0] */ PACK( 0, 0 ), - /* IUP[1] */ PACK( 0, 0 ), - /* SHP[0] */ PACK( 0, 0 ), - /* SHP[1] */ PACK( 0, 0 ), - /* SHC[0] */ PACK( 1, 0 ), - /* SHC[1] */ PACK( 1, 0 ), - /* SHZ[0] */ PACK( 1, 0 ), - /* SHZ[1] */ PACK( 1, 0 ), - /* SHPIX */ PACK( 1, 0 ), - /* IP */ PACK( 0, 0 ), - /* MSIRP[0] */ PACK( 2, 0 ), - /* MSIRP[1] */ PACK( 2, 0 ), - /* AlignRP */ PACK( 0, 0 ), - /* RTDG */ PACK( 0, 0 ), - /* MIAP[0] */ PACK( 2, 0 ), - /* MIAP[1] */ PACK( 2, 0 ), - - /* NPushB */ PACK( 0, 0 ), - /* NPushW */ PACK( 0, 0 ), - /* WS */ PACK( 2, 0 ), - /* RS */ PACK( 1, 1 ), - /* WCvtP */ PACK( 2, 0 ), - /* RCvt */ PACK( 1, 1 ), - /* GC[0] */ PACK( 1, 1 ), - /* GC[1] */ PACK( 1, 1 ), - /* SCFS */ PACK( 2, 0 ), - /* MD[0] */ PACK( 2, 1 ), - /* MD[1] */ PACK( 2, 1 ), - /* MPPEM */ PACK( 0, 1 ), - /* MPS */ PACK( 0, 1 ), - /* FlipON */ PACK( 0, 0 ), - /* FlipOFF */ PACK( 0, 0 ), - /* DEBUG */ PACK( 1, 0 ), - - /* LT */ PACK( 2, 1 ), - /* LTEQ */ PACK( 2, 1 ), - /* GT */ PACK( 2, 1 ), - /* GTEQ */ PACK( 2, 1 ), - /* EQ */ PACK( 2, 1 ), - /* NEQ */ PACK( 2, 1 ), - /* ODD */ PACK( 1, 1 ), - /* EVEN */ PACK( 1, 1 ), - /* IF */ PACK( 1, 0 ), - /* EIF */ PACK( 0, 0 ), - /* AND */ PACK( 2, 1 ), - /* OR */ PACK( 2, 1 ), - /* NOT */ PACK( 1, 1 ), - /* DeltaP1 */ PACK( 1, 0 ), - /* SDB */ PACK( 1, 0 ), - /* SDS */ PACK( 1, 0 ), - - /* ADD */ PACK( 2, 1 ), - /* SUB */ PACK( 2, 1 ), - /* DIV */ PACK( 2, 1 ), - /* MUL */ PACK( 2, 1 ), - /* ABS */ PACK( 1, 1 ), - /* NEG */ PACK( 1, 1 ), - /* FLOOR */ PACK( 1, 1 ), - /* CEILING */ PACK( 1, 1 ), - /* ROUND[0] */ PACK( 1, 1 ), - /* ROUND[1] */ PACK( 1, 1 ), - /* ROUND[2] */ PACK( 1, 1 ), - /* ROUND[3] */ PACK( 1, 1 ), - /* NROUND[0] */ PACK( 1, 1 ), - /* NROUND[1] */ PACK( 1, 1 ), - /* NROUND[2] */ PACK( 1, 1 ), - /* NROUND[3] */ PACK( 1, 1 ), - - /* WCvtF */ PACK( 2, 0 ), - /* DeltaP2 */ PACK( 1, 0 ), - /* DeltaP3 */ PACK( 1, 0 ), - /* DeltaCn[0] */ PACK( 1, 0 ), - /* DeltaCn[1] */ PACK( 1, 0 ), - /* DeltaCn[2] */ PACK( 1, 0 ), - /* SROUND */ PACK( 1, 0 ), - /* S45Round */ PACK( 1, 0 ), - /* JROT */ PACK( 2, 0 ), - /* JROF */ PACK( 2, 0 ), - /* ROFF */ PACK( 0, 0 ), - /* INS_$7B */ PACK( 0, 0 ), - /* RUTG */ PACK( 0, 0 ), - /* RDTG */ PACK( 0, 0 ), - /* SANGW */ PACK( 1, 0 ), - /* AA */ PACK( 1, 0 ), - - /* FlipPT */ PACK( 0, 0 ), - /* FlipRgON */ PACK( 2, 0 ), - /* FlipRgOFF */ PACK( 2, 0 ), - /* INS_$83 */ PACK( 0, 0 ), - /* INS_$84 */ PACK( 0, 0 ), - /* ScanCTRL */ PACK( 1, 0 ), - /* SDVPTL[0] */ PACK( 2, 0 ), - /* SDVPTL[1] */ PACK( 2, 0 ), - /* GetINFO */ PACK( 1, 1 ), - /* IDEF */ PACK( 1, 0 ), - /* ROLL */ PACK( 3, 3 ), - /* MAX */ PACK( 2, 1 ), - /* MIN */ PACK( 2, 1 ), - /* ScanTYPE */ PACK( 1, 0 ), - /* InstCTRL */ PACK( 2, 0 ), - /* INS_$8F */ PACK( 0, 0 ), - - /* INS_$90 */ PACK( 0, 0 ), - /* INS_$91 */ PACK( 0, 0 ), - /* INS_$92 */ PACK( 0, 0 ), - /* INS_$93 */ PACK( 0, 0 ), - /* INS_$94 */ PACK( 0, 0 ), - /* INS_$95 */ PACK( 0, 0 ), - /* INS_$96 */ PACK( 0, 0 ), - /* INS_$97 */ PACK( 0, 0 ), - /* INS_$98 */ PACK( 0, 0 ), - /* INS_$99 */ PACK( 0, 0 ), - /* INS_$9A */ PACK( 0, 0 ), - /* INS_$9B */ PACK( 0, 0 ), - /* INS_$9C */ PACK( 0, 0 ), - /* INS_$9D */ PACK( 0, 0 ), - /* INS_$9E */ PACK( 0, 0 ), - /* INS_$9F */ PACK( 0, 0 ), - - /* INS_$A0 */ PACK( 0, 0 ), - /* INS_$A1 */ PACK( 0, 0 ), - /* INS_$A2 */ PACK( 0, 0 ), - /* INS_$A3 */ PACK( 0, 0 ), - /* INS_$A4 */ PACK( 0, 0 ), - /* INS_$A5 */ PACK( 0, 0 ), - /* INS_$A6 */ PACK( 0, 0 ), - /* INS_$A7 */ PACK( 0, 0 ), - /* INS_$A8 */ PACK( 0, 0 ), - /* INS_$A9 */ PACK( 0, 0 ), - /* INS_$AA */ PACK( 0, 0 ), - /* INS_$AB */ PACK( 0, 0 ), - /* INS_$AC */ PACK( 0, 0 ), - /* INS_$AD */ PACK( 0, 0 ), - /* INS_$AE */ PACK( 0, 0 ), - /* INS_$AF */ PACK( 0, 0 ), - - /* PushB[0] */ PACK( 0, 1 ), - /* PushB[1] */ PACK( 0, 2 ), - /* PushB[2] */ PACK( 0, 3 ), - /* PushB[3] */ PACK( 0, 4 ), - /* PushB[4] */ PACK( 0, 5 ), - /* PushB[5] */ PACK( 0, 6 ), - /* PushB[6] */ PACK( 0, 7 ), - /* PushB[7] */ PACK( 0, 8 ), - /* PushW[0] */ PACK( 0, 1 ), - /* PushW[1] */ PACK( 0, 2 ), - /* PushW[2] */ PACK( 0, 3 ), - /* PushW[3] */ PACK( 0, 4 ), - /* PushW[4] */ PACK( 0, 5 ), - /* PushW[5] */ PACK( 0, 6 ), - /* PushW[6] */ PACK( 0, 7 ), - /* PushW[7] */ PACK( 0, 8 ), - - /* MDRP[00] */ PACK( 1, 0 ), - /* MDRP[01] */ PACK( 1, 0 ), - /* MDRP[02] */ PACK( 1, 0 ), - /* MDRP[03] */ PACK( 1, 0 ), - /* MDRP[04] */ PACK( 1, 0 ), - /* MDRP[05] */ PACK( 1, 0 ), - /* MDRP[06] */ PACK( 1, 0 ), - /* MDRP[07] */ PACK( 1, 0 ), - /* MDRP[08] */ PACK( 1, 0 ), - /* MDRP[09] */ PACK( 1, 0 ), - /* MDRP[10] */ PACK( 1, 0 ), - /* MDRP[11] */ PACK( 1, 0 ), - /* MDRP[12] */ PACK( 1, 0 ), - /* MDRP[13] */ PACK( 1, 0 ), - /* MDRP[14] */ PACK( 1, 0 ), - /* MDRP[15] */ PACK( 1, 0 ), - - /* MDRP[16] */ PACK( 1, 0 ), - /* MDRP[17] */ PACK( 1, 0 ), - /* MDRP[18] */ PACK( 1, 0 ), - /* MDRP[19] */ PACK( 1, 0 ), - /* MDRP[20] */ PACK( 1, 0 ), - /* MDRP[21] */ PACK( 1, 0 ), - /* MDRP[22] */ PACK( 1, 0 ), - /* MDRP[23] */ PACK( 1, 0 ), - /* MDRP[24] */ PACK( 1, 0 ), - /* MDRP[25] */ PACK( 1, 0 ), - /* MDRP[26] */ PACK( 1, 0 ), - /* MDRP[27] */ PACK( 1, 0 ), - /* MDRP[28] */ PACK( 1, 0 ), - /* MDRP[29] */ PACK( 1, 0 ), - /* MDRP[30] */ PACK( 1, 0 ), - /* MDRP[31] */ PACK( 1, 0 ), - - /* MIRP[00] */ PACK( 2, 0 ), - /* MIRP[01] */ PACK( 2, 0 ), - /* MIRP[02] */ PACK( 2, 0 ), - /* MIRP[03] */ PACK( 2, 0 ), - /* MIRP[04] */ PACK( 2, 0 ), - /* MIRP[05] */ PACK( 2, 0 ), - /* MIRP[06] */ PACK( 2, 0 ), - /* MIRP[07] */ PACK( 2, 0 ), - /* MIRP[08] */ PACK( 2, 0 ), - /* MIRP[09] */ PACK( 2, 0 ), - /* MIRP[10] */ PACK( 2, 0 ), - /* MIRP[11] */ PACK( 2, 0 ), - /* MIRP[12] */ PACK( 2, 0 ), - /* MIRP[13] */ PACK( 2, 0 ), - /* MIRP[14] */ PACK( 2, 0 ), - /* MIRP[15] */ PACK( 2, 0 ), - - /* MIRP[16] */ PACK( 2, 0 ), - /* MIRP[17] */ PACK( 2, 0 ), - /* MIRP[18] */ PACK( 2, 0 ), - /* MIRP[19] */ PACK( 2, 0 ), - /* MIRP[20] */ PACK( 2, 0 ), - /* MIRP[21] */ PACK( 2, 0 ), - /* MIRP[22] */ PACK( 2, 0 ), - /* MIRP[23] */ PACK( 2, 0 ), - /* MIRP[24] */ PACK( 2, 0 ), - /* MIRP[25] */ PACK( 2, 0 ), - /* MIRP[26] */ PACK( 2, 0 ), - /* MIRP[27] */ PACK( 2, 0 ), - /* MIRP[28] */ PACK( 2, 0 ), - /* MIRP[29] */ PACK( 2, 0 ), - /* MIRP[30] */ PACK( 2, 0 ), - /* MIRP[31] */ PACK( 2, 0 ) - }; - - static const TT_Vector Null_Vector = {0,0}; - -#undef NULL_Vector -#define NULL_Vector (TT_Vector*)&Null_Vector - -/******************************************************************* - * - * Function : Norm - * - * Description : Returns the norm (length) of a vector. - * - * Input : X, Y vector - * - * Output : Returns length in F26dot6. - * - *****************************************************************/ - - static TT_F26Dot6 Norm( TT_F26Dot6 X, TT_F26Dot6 Y ) - { - TT_Int64 T1, T2; - - - MUL_64( X, X, T1 ); - MUL_64( Y, Y, T2 ); - - ADD_64( T1, T2, T1 ); - - return (TT_F26Dot6)SQRT_64( T1 ); - } - - -/******************************************************************* - * - * Function : FUnits_To_Pixels - * - * Description : Scale a distance in FUnits to pixel coordinates. - * - * Input : Distance in FUnits - * - * Output : Distance in 26.6 format. - * - *****************************************************************/ - - static TT_F26Dot6 FUnits_To_Pixels( EXEC_OPS Short distance ) - { - return TT_MulDiv( distance, - CUR.metrics.scale1, - CUR.metrics.scale2 ); - } - - -/******************************************************************* - * - * Function : Current_Ratio - * - * Description : Return the current aspect ratio scaling factor - * depending on the projection vector's state and - * device resolutions. - * - * Input : None - * - * Output : Aspect ratio in 16.16 format, always <= 1.0 . - * - *****************************************************************/ - - static Long Current_Ratio( EXEC_OP ) - { - if ( CUR.metrics.ratio ) - return CUR.metrics.ratio; - - if ( CUR.GS.projVector.y == 0 ) - CUR.metrics.ratio = CUR.metrics.x_ratio; - - else if ( CUR.GS.projVector.x == 0 ) - CUR.metrics.ratio = CUR.metrics.y_ratio; - - else - { - Long x, y; - - - x = TT_MulDiv( CUR.GS.projVector.x, CUR.metrics.x_ratio, 0x4000 ); - y = TT_MulDiv( CUR.GS.projVector.y, CUR.metrics.y_ratio, 0x4000 ); - CUR.metrics.ratio = Norm( x, y ); - } - - return CUR.metrics.ratio; - } - - - static Long Current_Ppem( EXEC_OP ) - { - return TT_MulFix( CUR.metrics.ppem, CURRENT_Ratio() ); - } - - - static TT_F26Dot6 Read_CVT( EXEC_OPS ULong index ) - { - return CUR.cvt[index]; - } - - - static TT_F26Dot6 Read_CVT_Stretched( EXEC_OPS ULong index ) - { - return TT_MulFix( CUR.cvt[index], CURRENT_Ratio() ); - } - - - static void Write_CVT( EXEC_OPS ULong index, TT_F26Dot6 value ) - { - CUR.cvt[index] = value; - } - - static void Write_CVT_Stretched( EXEC_OPS ULong index, TT_F26Dot6 value ) - { - CUR.cvt[index] = TT_MulDiv( value, 0x10000, CURRENT_Ratio() ); - } - - - static void Move_CVT( EXEC_OPS ULong index, TT_F26Dot6 value ) - { - CUR.cvt[index] += value; - } - - static void Move_CVT_Stretched( EXEC_OPS ULong index, TT_F26Dot6 value ) - { - CUR.cvt[index] += TT_MulDiv( value, 0x10000, CURRENT_Ratio() ); - } - - -/****************************************************************** - * - * Function : Calc_Length - * - * Description : Computes the length in bytes of current opcode. - * - *****************************************************************/ - - static Bool Calc_Length( EXEC_OP ) - { - CUR.opcode = CUR.code[CUR.IP]; - - switch ( CUR.opcode ) - { - case 0x40: - if ( CUR.IP + 1 >= CUR.codeSize ) - return FAILURE; - - CUR.length = CUR.code[CUR.IP + 1] + 2; - break; - - case 0x41: - if ( CUR.IP + 1 >= CUR.codeSize ) - return FAILURE; - - CUR.length = CUR.code[CUR.IP + 1] * 2 + 2; - break; - - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - CUR.length = CUR.opcode - 0xB0 + 2; - break; - - case 0xB8: - case 0xB9: - case 0xBA: - case 0xBB: - case 0xBC: - case 0xBD: - case 0xBE: - case 0xBF: - CUR.length = (CUR.opcode - 0xB8) * 2 + 3; - break; - - default: - CUR.length = 1; - break; - } - - /* make sure result is in range */ - - if ( CUR.IP + CUR.length > CUR.codeSize ) - return FAILURE; - - return SUCCESS; - } - - -/******************************************************************* - * - * Function : GetShortIns - * - * Description : Returns a short integer taken from the instruction - * stream at address IP. - * - * Input : None - * - * Output : Short read at Code^[IP..IP+1] - * - * Notes : This one could become a Macro in the C version. - * - *****************************************************************/ - - static Short GetShortIns( EXEC_OP ) - { - /* Reading a byte stream so there is no endianess (DaveP) */ - CUR.IP += 2; - return (Short)((CUR.code[CUR.IP - 2] << 8) + CUR.code[CUR.IP - 1]); - } - - -/******************************************************************* - * - * Function : Ins_Goto_CodeRange - * - * Description : Goes to a certain code range in the instruction - * stream. - * - * - * Input : aRange - * aIP - * - * Output : SUCCESS or FAILURE. - * - *****************************************************************/ - - static Bool Ins_Goto_CodeRange( EXEC_OPS Int aRange, ULong aIP ) - { - TCodeRange* WITH; - - - if ( aRange < 1 || aRange > 3 ) - { - CUR.error = TT_Err_Bad_Argument; - return FAILURE; - } - - WITH = &CUR.codeRangeTable[aRange - 1]; - - if ( WITH->Base == NULL ) /* invalid coderange */ - { - CUR.error = TT_Err_Invalid_CodeRange; - return FAILURE; - } - - /* 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 aIP <= Size, instead of aIP < Size. */ - - if ( aIP > WITH->Size ) - { - CUR.error = TT_Err_Code_Overflow; - return FAILURE; - } - - CUR.code = WITH->Base; - CUR.codeSize = WITH->Size; - CUR.IP = aIP; - CUR.curRange = aRange; - - return SUCCESS; - } - - -/******************************************************************* - * - * Function : Direct_Move - * - * Description : Moves a point by a given distance along the - * freedom vector. The point will be touched. - * - * Input : point index of point to move - * distance distance to apply - * zone affected glyph zone - * - * Output : None - * - *****************************************************************/ - - static void Direct_Move( EXEC_OPS PGlyph_Zone zone, - UShort point, - TT_F26Dot6 distance ) - { - TT_F26Dot6 v; - - - v = CUR.GS.freeVector.x; - - if ( v != 0 ) - { - zone->cur[point].x += TT_MulDiv( distance, - v * 0x10000L, - CUR.F_dot_P ); - - zone->touch[point] |= TT_Flag_Touched_X; - } - - v = CUR.GS.freeVector.y; - - if ( v != 0 ) - { - zone->cur[point].y += TT_MulDiv( distance, - v * 0x10000L, - CUR.F_dot_P ); - - zone->touch[point] |= TT_Flag_Touched_Y; - } - } - - -/******************************************************************/ -/* */ -/* The following versions are used whenever both vectors are both */ -/* along one of the coordinate unit vectors, i.e. in 90% cases. */ -/* */ -/******************************************************************/ - -/******************************************************************* - * Direct_Move_X - * - *******************************************************************/ - - static void Direct_Move_X( EXEC_OPS PGlyph_Zone zone, - UShort point, - TT_F26Dot6 distance ) - { - zone->cur[point].x += distance; - zone->touch[point] |= TT_Flag_Touched_X; - } - - -/******************************************************************* - * Direct_Move_Y - * - *******************************************************************/ - - static void Direct_Move_Y( EXEC_OPS PGlyph_Zone zone, - UShort point, - TT_F26Dot6 distance ) - { - zone->cur[point].y += distance; - zone->touch[point] |= TT_Flag_Touched_Y; - } - - -/******************************************************************* - * - * Function : Round_None - * - * Description : Does not round, but adds engine compensation. - * - * Input : distance : distance to round - * compensation : engine compensation - * - * Output : rounded distance. - * - * NOTE : The spec says very few about the relationship between - * rounding and engine compensation. However, it seems - * from the description of super round that we should - * should add the compensation before rounding. - * - ******************************************************************/ - - static TT_F26Dot6 Round_None( EXEC_OPS TT_F26Dot6 distance, - TT_F26Dot6 compensation ) - { - TT_F26Dot6 val; - - - if ( distance >= 0 ) - { - val = distance + compensation; - if ( val < 0 ) - val = 0; - } - else { - val = distance - compensation; - if ( val > 0 ) - val = 0; - } - - return val; - } - - -/******************************************************************* - * - * Function : Round_To_Grid - * - * Description : Rounds value to grid after adding engine - * compensation - * - * Input : distance : distance to round - * compensation : engine compensation - * - * Output : Rounded distance. - * - *****************************************************************/ - - static TT_F26Dot6 Round_To_Grid( EXEC_OPS TT_F26Dot6 distance, - TT_F26Dot6 compensation ) - { - TT_F26Dot6 val; - - - if ( distance >= 0 ) - { - val = distance + compensation + 32; - if ( val > 0 ) - val &= ~63; - else - val = 0; - } - else - { - val = -( (compensation - distance + 32) & (-64) ); - if ( val > 0 ) - val = 0; - } - - return val; - } - - -/******************************************************************* - * - * Function : Round_To_Half_Grid - * - * Description : Rounds value to half grid after adding engine - * compensation. - * - * Input : distance : distance to round - * compensation : engine compensation - * - * Output : Rounded distance. - * - *****************************************************************/ - - static TT_F26Dot6 Round_To_Half_Grid( EXEC_OPS TT_F26Dot6 distance, - TT_F26Dot6 compensation ) - { - TT_F26Dot6 val; - - - if ( distance >= 0 ) - { - val = ((distance + compensation) & (-64)) + 32; - if ( val < 0 ) - val = 0; - } - else - { - val = -( ((compensation - distance) & (-64)) + 32 ); - if ( val > 0 ) - val = 0; - } - - return val; - } - - -/******************************************************************* - * - * Function : Round_Down_To_Grid - * - * Description : Rounds value down to grid after adding engine - * compensation. - * - * Input : distance : distance to round - * compensation : engine compensation - * - * Output : Rounded distance. - * - *****************************************************************/ - - static TT_F26Dot6 Round_Down_To_Grid( EXEC_OPS TT_F26Dot6 distance, - TT_F26Dot6 compensation ) - { - TT_F26Dot6 val; - - - if ( distance >= 0 ) - { - val = distance + compensation; - if ( val > 0 ) - val &= ~63; - else - val = 0; - } - else - { - val = -( (compensation - distance) & (-64) ); - if ( val > 0 ) - val = 0; - } - - return val; - } - - -/******************************************************************* - * - * Function : Round_Up_To_Grid - * - * Description : Rounds value up to grid after adding engine - * compensation. - * - * Input : distance : distance to round - * compensation : engine compensation - * - * Output : Rounded distance. - * - *****************************************************************/ - - static TT_F26Dot6 Round_Up_To_Grid( EXEC_OPS TT_F26Dot6 distance, - TT_F26Dot6 compensation ) - { - TT_F26Dot6 val; - - - if ( distance >= 0 ) - { - val = distance + compensation + 63; - if ( val > 0 ) - val &= ~63; - else - val = 0; - } - else - { - val = -( (compensation - distance + 63) & (-64) ); - if ( val > 0 ) - val = 0; - } - - return val; - } - - -/******************************************************************* - * - * Function : Round_To_Double_Grid - * - * Description : Rounds value to double grid after adding engine - * compensation. - * - * Input : distance : distance to round - * compensation : engine compensation - * - * Output : Rounded distance. - * - *****************************************************************/ - - static TT_F26Dot6 Round_To_Double_Grid( EXEC_OPS TT_F26Dot6 distance, - TT_F26Dot6 compensation ) - { - TT_F26Dot6 val; - - - if ( distance >= 0 ) - { - val = distance + compensation + 16; - if ( val > 0 ) - val &= ~31; - else - val = 0; - } - else - { - val = -( (compensation - distance + 16) & (-32) ); - if ( val > 0 ) - val = 0; - } - - return val; - } - - -/******************************************************************* - * - * Function : Round_Super - * - * Description : Super-rounds value to grid after adding engine - * compensation. - * - * Input : distance : distance to round - * compensation : engine compensation - * - * Output : Rounded distance. - * - * NOTE : The spec says very few about the relationship between - * rounding and engine compensation. However, it seems - * from the description of super round that we should - * should add the compensation before rounding. - * - *****************************************************************/ - - static TT_F26Dot6 Round_Super( EXEC_OPS TT_F26Dot6 distance, - TT_F26Dot6 compensation ) - { - TT_F26Dot6 val; - - - if ( distance >= 0 ) - { - val = (distance - CUR.phase + CUR.threshold + compensation) & - (-CUR.period); - if ( val < 0 ) - val = 0; - val += CUR.phase; - } - else - { - val = -( (CUR.threshold - CUR.phase - distance + compensation) & - (-CUR.period) ); - if ( val > 0 ) - val = 0; - val -= CUR.phase; - } - - return val; - } - - -/******************************************************************* - * - * Function : Round_Super_45 - * - * Description : Super-rounds value to grid after adding engine - * compensation. - * - * Input : distance : distance to round - * compensation : engine compensation - * - * Output : Rounded distance. - * - * NOTE : There is a separate function for Round_Super_45 as we - * may need a greater precision. - * - *****************************************************************/ - - static TT_F26Dot6 Round_Super_45( EXEC_OPS TT_F26Dot6 distance, - TT_F26Dot6 compensation ) - { - TT_F26Dot6 val; - - - if ( distance >= 0 ) - { - val = ( (distance - CUR.phase + CUR.threshold + compensation) / - CUR.period ) * CUR.period; - if ( val < 0 ) - val = 0; - val += CUR.phase; - } - else - { - val = -( ( (CUR.threshold - CUR.phase - distance + compensation) / - CUR.period ) * CUR.period ); - if ( val > 0 ) - val = 0; - val -= CUR.phase; - } - - return val; - } - - -/******************************************************************* - * Compute_Round - * - *****************************************************************/ - - static void Compute_Round( EXEC_OPS Byte round_mode ) - { - switch ( round_mode ) - { - case TT_Round_Off: - CUR.func_round = (TRound_Function)Round_None; - break; - - case TT_Round_To_Grid: - CUR.func_round = (TRound_Function)Round_To_Grid; - break; - - case TT_Round_Up_To_Grid: - CUR.func_round = (TRound_Function)Round_Up_To_Grid; - break; - - case TT_Round_Down_To_Grid: - CUR.func_round = (TRound_Function)Round_Down_To_Grid; - break; - - case TT_Round_To_Half_Grid: - CUR.func_round = (TRound_Function)Round_To_Half_Grid; - break; - - case TT_Round_To_Double_Grid: - CUR.func_round = (TRound_Function)Round_To_Double_Grid; - break; - - case TT_Round_Super: - CUR.func_round = (TRound_Function)Round_Super; - break; - - case TT_Round_Super_45: - CUR.func_round = (TRound_Function)Round_Super_45; - break; - } - } - - -/******************************************************************* - * - * Function : SetSuperRound - * - * Description : Sets Super Round parameters. - * - * Input : GridPeriod Grid period - * selector SROUND opcode - * - * Output : None. - * - *****************************************************************/ - - static void SetSuperRound( EXEC_OPS TT_F26Dot6 GridPeriod, - Long selector ) - { - switch ( (Int)(selector & 0xC0) ) - { - case 0: - CUR.period = GridPeriod / 2; - break; - - case 0x40: - CUR.period = GridPeriod; - break; - - case 0x80: - CUR.period = GridPeriod * 2; - break; - - /* This opcode is reserved, but... */ - - case 0xC0: - CUR.period = GridPeriod; - break; - } - - switch ( (Int)(selector & 0x30) ) - { - case 0: - CUR.phase = 0; - break; - - case 0x10: - CUR.phase = CUR.period / 4; - break; - - case 0x20: - CUR.phase = CUR.period / 2; - break; - - case 0x30: - CUR.phase = GridPeriod * 3 / 4; - break; - } - - if ( (selector & 0x0F) == 0 ) - CUR.threshold = CUR.period - 1; - else - CUR.threshold = ( (Int)(selector & 0x0F) - 4 ) * CUR.period / 8; - - CUR.period /= 256; - CUR.phase /= 256; - CUR.threshold /= 256; - } - - -/******************************************************************* - * - * Function : Project - * - * Description : Computes the projection of vector given by (v2-v1) - * along the current projection vector. - * - * Input : v1, v2 input vector - * - * Output : Returns distance in F26dot6 format. - * - *****************************************************************/ - - static TT_F26Dot6 Project( EXEC_OPS TT_Vector* v1, - TT_Vector* v2 ) - { - TT_Int64 T1, T2; - - - MUL_64( v1->x - v2->x, CUR.GS.projVector.x, T1 ); - MUL_64( v1->y - v2->y, CUR.GS.projVector.y, T2 ); - - ADD_64( T1, T2, T1 ); - - return (TT_F26Dot6)DIV_64( T1, 0x4000L ); - } - - -/******************************************************************* - * - * Function : Dual_Project - * - * Description : Computes the projection of the vector given by - * (v2-v1) along the current dual vector. - * - * Input : v1, v2 input vector - * - * Output : Returns distance in F26dot6 format. - * - *****************************************************************/ - - static TT_F26Dot6 Dual_Project( EXEC_OPS TT_Vector* v1, - TT_Vector* v2 ) - { - TT_Int64 T1, T2; - - - MUL_64( v1->x - v2->x, CUR.GS.dualVector.x, T1 ); - MUL_64( v1->y - v2->y, CUR.GS.dualVector.y, T2 ); - - ADD_64( T1, T2, T1 ); - - return (TT_F26Dot6)DIV_64( T1, 0x4000L ); - } - - -/******************************************************************* - * - * Function : Free_Project - * - * Description : Computes the projection of the vector given by - * (v2-v1) along the current freedom vector. - * - * Input : v1, v2 input vector - * - * Output : Returns distance in F26dot6 format. - * - *****************************************************************/ - - static TT_F26Dot6 Free_Project( EXEC_OPS TT_Vector* v1, - TT_Vector* v2 ) - { - TT_Int64 T1, T2; - - - MUL_64( v1->x - v2->x, CUR.GS.freeVector.x, T1 ); - MUL_64( v1->y - v2->y, CUR.GS.freeVector.y, T2 ); - - ADD_64( T1, T2, T1 ); - - return (TT_F26Dot6)DIV_64( T1, 0x4000L ); - } - - -/******************************************************************* - * - * Function : Project_x - * - * Input : Vx, Vy input vector - * - * Output : Returns Vx. - * - * Note : Used as a dummy function. - * - *****************************************************************/ - - static TT_F26Dot6 Project_x( EXEC_OPS TT_Vector* v1, - TT_Vector* v2 ) - { - return (v1->x - v2->x); - } - - -/******************************************************************* - * - * Function : Project_y - * - * Input : Vx, Vy input vector - * - * Output : Returns Vy. - * - * Note : Used as a dummy function. - * - *****************************************************************/ - - static TT_F26Dot6 Project_y( EXEC_OPS TT_Vector* v1, - TT_Vector* v2 ) - { - return (v1->y - v2->y); - } - - -/******************************************************************* - * - * Function : Compute_Funcs - * - * Description : Computes the projections and movement function - * pointers according to the current graphics state. - * - * Input : None - * - *****************************************************************/ - - static void Compute_Funcs( EXEC_OP ) - { - if ( CUR.GS.freeVector.x == 0x4000 ) - { - CUR.func_freeProj = (TProject_Function)Project_x; - CUR.F_dot_P = CUR.GS.projVector.x * 0x10000L; - } - else - { - if ( CUR.GS.freeVector.y == 0x4000 ) - { - CUR.func_freeProj = (TProject_Function)Project_y; - CUR.F_dot_P = CUR.GS.projVector.y * 0x10000L; - } - else - { - CUR.func_freeProj = (TProject_Function)Free_Project; - CUR.F_dot_P = (Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 + - (Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4; - } - } - - CUR.cached_metrics = FALSE; - - if ( CUR.GS.projVector.x == 0x4000 ) - CUR.func_project = (TProject_Function)Project_x; - else - { - if ( CUR.GS.projVector.y == 0x4000 ) - CUR.func_project = (TProject_Function)Project_y; - else - CUR.func_project = (TProject_Function)Project; - } - - if ( CUR.GS.dualVector.x == 0x4000 ) - CUR.func_dualproj = (TProject_Function)Project_x; - else - { - if ( CUR.GS.dualVector.y == 0x4000 ) - CUR.func_dualproj = (TProject_Function)Project_y; - else - CUR.func_dualproj = (TProject_Function)Dual_Project; - } - - CUR.func_move = (TMove_Function)Direct_Move; - - if ( CUR.F_dot_P == 0x40000000L ) - { - if ( CUR.GS.freeVector.x == 0x4000 ) - CUR.func_move = (TMove_Function)Direct_Move_X; - else - { - if ( CUR.GS.freeVector.y == 0x4000 ) - CUR.func_move = (TMove_Function)Direct_Move_Y; - } - } - - /* at small sizes, F_dot_P can become too small, resulting */ - /* in overflows and 'spikes' in a number of glyphs like 'w'. */ - - if ( ABS( CUR.F_dot_P ) < 0x4000000L ) - CUR.F_dot_P = 0x40000000L; - - /* Disable cached aspect ratio */ - CUR.metrics.ratio = 0; - } - - -/******************************************************************* - * - * Function : Normalize - * - * Description : Norms a vector - * - * Input : Vx, Vy input vector - * R normed unit vector - * - * Output : Returns FAILURE if a vector parameter is zero. - * - *****************************************************************/ - - static Bool Normalize( EXEC_OPS TT_F26Dot6 Vx, - TT_F26Dot6 Vy, - TT_UnitVector* R ) - { - TT_F26Dot6 W; - Bool S1, S2; - - - if ( ABS( Vx ) < 0x10000L && ABS( Vy ) < 0x10000L ) - { - Vx *= 0x100; - Vy *= 0x100; - - W = Norm( Vx, Vy ); - - if ( W == 0 ) - { - /* XXX : UNDOCUMENTED! It seems that it's possible to try */ - /* to normalize the vector (0,0). Return immediately */ - return SUCCESS; - } - - R->x = (TT_F2Dot14)TT_MulDiv( Vx, 0x4000L, W ); - R->y = (TT_F2Dot14)TT_MulDiv( Vy, 0x4000L, W ); - - return SUCCESS; - } - - W = Norm( Vx, Vy ); - - Vx = TT_MulDiv( Vx, 0x4000L, W ); - Vy = TT_MulDiv( Vy, 0x4000L, W ); - - W = Vx * Vx + Vy * Vy; - - /* Now, we want that Sqrt( W ) = 0x4000 */ - /* Or 0x1000000 <= W < 0x1004000 */ - - if ( Vx < 0 ) - { - Vx = -Vx; - S1 = TRUE; - } - else - S1 = FALSE; - - if ( Vy < 0 ) - { - Vy = -Vy; - S2 = TRUE; - } - else - S2 = FALSE; - - while ( W < 0x1000000L ) - { - /* We need to increase W, by a minimal amount */ - if ( Vx < Vy ) - Vx++; - else - Vy++; - - W = Vx * Vx + Vy * Vy; - } - - while ( W >= 0x1004000L ) - { - /* We need to decrease W, by a minimal amount */ - if ( Vx < Vy ) - Vx--; - else - Vy--; - - W = Vx * Vx + Vy * Vy; - } - - /* Note that in various cases, we can only */ - /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */ - - if ( S1 ) - Vx = -Vx; - - if ( S2 ) - Vy = -Vy; - - R->x = (TT_F2Dot14)Vx; /* Type conversion */ - R->y = (TT_F2Dot14)Vy; /* Type conversion */ - - return SUCCESS; - } - - -/**************************************************************** - * - * Opcodes - * - ****************************************************************/ - - - static Bool Ins_SxVTL( EXEC_OPS UShort aIdx1, - UShort aIdx2, - Int aOpc, - TT_UnitVector* Vec ) - { - Long A, B, C; - TT_Vector* p1; - TT_Vector* p2; - - - if ( BOUNDS( aIdx1, CUR.zp2.n_points ) || - BOUNDS( aIdx2, CUR.zp1.n_points ) ) - { - if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; - return FAILURE; - } - - p1 = CUR.zp1.cur + aIdx2; - p2 = CUR.zp2.cur + aIdx1; - - A = p1->x - p2->x; - B = p1->y - p2->y; - - if ( (aOpc & 1) != 0 ) - { - C = B; /* CounterClockwise rotation */ - B = A; - A = -C; - } - - NORMalize( A, B, Vec ); - return SUCCESS; - } - - -/* When not using the big switch statements, the interpreter uses a */ -/* call table defined later below in this source. Each opcode must */ -/* thus have a corresponding function, even trivial ones. */ -/* */ -/* They're all defined there. */ - -#define DO_SVTCA \ - { \ - Short A, B; \ - \ - \ - A = (Short)(CUR.opcode & 1) << 14; \ - B = A ^ (Short)0x4000; \ - \ - CUR.GS.freeVector.x = A; \ - CUR.GS.projVector.x = A; \ - CUR.GS.dualVector.x = A; \ - \ - CUR.GS.freeVector.y = B; \ - CUR.GS.projVector.y = B; \ - CUR.GS.dualVector.y = B; \ - \ - COMPUTE_Funcs(); \ - } - - -#define DO_SPVTCA \ - { \ - Short A, B; \ - \ - \ - A = (Short)(CUR.opcode & 1) << 14; \ - B = A ^ (Short)0x4000; \ - \ - CUR.GS.projVector.x = A; \ - CUR.GS.dualVector.x = A; \ - \ - CUR.GS.projVector.y = B; \ - CUR.GS.dualVector.y = B; \ - \ - COMPUTE_Funcs(); \ - } - - -#define DO_SFVTCA \ - { \ - Short A, B; \ - \ - \ - A = (Short)(CUR.opcode & 1) << 14; \ - B = A ^ (Short)0x4000; \ - \ - CUR.GS.freeVector.x = A; \ - CUR.GS.freeVector.y = B; \ - \ - COMPUTE_Funcs(); \ - } - - -#define DO_SPVTL \ - if ( INS_SxVTL( (UShort)args[1], \ - (UShort)args[0], \ - CUR.opcode, \ - &CUR.GS.projVector) == SUCCESS ) \ - { \ - CUR.GS.dualVector = CUR.GS.projVector; \ - COMPUTE_Funcs(); \ - } - - -#define DO_SFVTL \ - if ( INS_SxVTL( (UShort)args[1], \ - (UShort)args[0], \ - CUR.opcode, \ - &CUR.GS.freeVector) == SUCCESS ) \ - COMPUTE_Funcs(); - - -#define DO_SFVTPV \ - CUR.GS.freeVector = CUR.GS.projVector; \ - COMPUTE_Funcs(); - - -#define DO_SPVFS \ - { \ - Short S; \ - Long X, Y; \ - \ - \ - /* Only use low 16bits, then sign extend */ \ - S = (Short)args[1]; \ - Y = (Long)S; \ - S = (Short)args[0]; \ - X = (Long)S; \ - \ - NORMalize( X, Y, &CUR.GS.projVector ); \ - \ - CUR.GS.dualVector = CUR.GS.projVector; \ - COMPUTE_Funcs(); \ - } - - -#define DO_SFVFS \ - { \ - Short S; \ - Long X, Y; \ - \ - \ - /* Only use low 16bits, then sign extend */ \ - S = (Short)args[1]; \ - Y = (Long)S; \ - S = (Short)args[0]; \ - X = S; \ - \ - NORMalize( X, Y, &CUR.GS.freeVector ); \ - COMPUTE_Funcs(); \ - } - - -#define DO_GPV \ - args[0] = CUR.GS.projVector.x; \ - args[1] = CUR.GS.projVector.y; - - -#define DO_GFV \ - args[0] = CUR.GS.freeVector.x; \ - args[1] = CUR.GS.freeVector.y; - - -#define DO_SRP0 \ - CUR.GS.rp0 = (UShort)args[0]; - - -#define DO_SRP1 \ - CUR.GS.rp1 = (UShort)args[0]; - - -#define DO_SRP2 \ - CUR.GS.rp2 = (UShort)args[0]; - - -#define DO_RTHG \ - CUR.GS.round_state = TT_Round_To_Half_Grid; \ - CUR.func_round = (TRound_Function)Round_To_Half_Grid; - - -#define DO_RTG \ - CUR.GS.round_state = TT_Round_To_Grid; \ - CUR.func_round = (TRound_Function)Round_To_Grid; - - -#define DO_RTDG \ - CUR.GS.round_state = TT_Round_To_Double_Grid; \ - CUR.func_round = (TRound_Function)Round_To_Double_Grid; - - -#define DO_RUTG \ - CUR.GS.round_state = TT_Round_Up_To_Grid; \ - CUR.func_round = (TRound_Function)Round_Up_To_Grid; - - -#define DO_RDTG \ - CUR.GS.round_state = TT_Round_Down_To_Grid; \ - CUR.func_round = (TRound_Function)Round_Down_To_Grid; - - -#define DO_ROFF \ - CUR.GS.round_state = TT_Round_Off; \ - CUR.func_round = (TRound_Function)Round_None; - - -#define DO_SROUND \ - SET_SuperRound( 0x4000L, args[0] ); \ - CUR.GS.round_state = TT_Round_Super; \ - CUR.func_round = (TRound_Function)Round_Super; - - -#define DO_S45ROUND \ - SET_SuperRound( 0x2D41L, args[0] ); \ - CUR.GS.round_state = TT_Round_Super_45; \ - CUR.func_round = (TRound_Function)Round_Super_45; - - -#define DO_SLOOP \ - if ( args[0] < 0 ) \ - CUR.error = TT_Err_Bad_Argument; \ - else \ - CUR.GS.loop = args[0]; - - -#define DO_SMD \ - CUR.GS.minimum_distance = (TT_F26Dot6)args[0]; - - -#define DO_SCVTCI \ - CUR.GS.control_value_cutin = (TT_F26Dot6)args[0]; - - -#define DO_SSWCI \ - CUR.GS.single_width_cutin = (TT_F26Dot6)args[0]; - - - /* XXX : UNDOCUMENTED! or bug in the Windows engine? */ - /* */ - /* It seems that the value that is read here is */ - /* expressed in 16.16 format, rather than in */ - /* font units.. */ - /* */ -#define DO_SSW \ - CUR.GS.single_width_value = (TT_F26Dot6)(args[0] >> 10); - - -#define DO_FLIPON \ - CUR.GS.auto_flip = TRUE; - - -#define DO_FLIPOFF \ - CUR.GS.auto_flip = FALSE; - - -#define DO_SDB \ - CUR.GS.delta_base = (Short)args[0]; - - -#define DO_SDS \ - CUR.GS.delta_shift = (Short)args[0]; - - -#define DO_MD /* nothing */ - - -#define DO_MPPEM \ - args[0] = CURRENT_Ppem(); - - -#define DO_MPS \ - args[0] = CUR.metrics.pointSize; - - -#define DO_DUP \ - args[1] = args[0]; - - -#define DO_CLEAR \ - CUR.new_top = 0; - - -#define DO_SWAP \ - { \ - Long L; \ - \ - L = args[0]; \ - args[0] = args[1]; \ - args[1] = L; \ - } - - -#define DO_DEPTH \ - args[0] = CUR.top; - - -#define DO_CINDEX \ - { \ - Long L; \ - \ - \ - L = args[0]; \ - \ - if ( L <= 0 || L > CUR.args ) \ - CUR.error = TT_Err_Invalid_Reference; \ - else \ - args[0] = CUR.stack[CUR.args - L]; \ - } - - -#define DO_JROT \ - if ( args[1] != 0 ) \ - { \ - CUR.IP += args[0]; \ - CUR.step_ins = FALSE; \ - } - - -#define DO_JMPR \ - CUR.IP += args[0]; \ - CUR.step_ins = FALSE; - - -#define DO_JROF \ - if ( args[1] == 0 ) \ - { \ - CUR.IP += args[0]; \ - CUR.step_ins = FALSE; \ - } - - -#define DO_LT \ - args[0] = (args[0] < args[1]); - - -#define DO_LTEQ \ - args[0] = (args[0] <= args[1]); - - -#define DO_GT \ - args[0] = (args[0] > args[1]); - - -#define DO_GTEQ \ - args[0] = (args[0] >= args[1]); - - -#define DO_EQ \ - args[0] = (args[0] == args[1]); - - -#define DO_NEQ \ - args[0] = (args[0] != args[1]); - - -#define DO_ODD \ - args[0] = ( (CUR_Func_round( args[0], 0 ) & 127) == 64 ); - - -#define DO_EVEN \ - args[0] = ( (CUR_Func_round( args[0], 0 ) & 127) == 0 ); - - -#define DO_AND \ - args[0] = ( args[0] && args[1] ); - - -#define DO_OR \ - args[0] = ( args[0] || args[1] ); - - -#define DO_NOT \ - args[0] = !args[0]; - - -#define DO_ADD \ - args[0] += args[1]; - - -#define DO_SUB \ - args[0] -= args[1]; - - -#define DO_DIV \ - if ( args[1] == 0 ) \ - CUR.error = TT_Err_Divide_By_Zero; \ - else \ - args[0] = TT_MulDiv( args[0], 64L, args[1] ); - - -#define DO_MUL \ - args[0] = TT_MulDiv( args[0], args[1], 64L ); - - -#define DO_ABS \ - args[0] = ABS( args[0] ); - - -#define DO_NEG \ - args[0] = -args[0]; - - -#define DO_FLOOR \ - args[0] &= -64; - - -#define DO_CEILING \ - args[0] = (args[0] + 63) & (-64); - - -#define DO_RS \ - { \ - ULong I = (ULong)args[0]; \ - if ( BOUNDS( I, CUR.storeSize ) ) \ - { \ - if ( CUR.pedantic_hinting ) \ - { \ - ARRAY_BOUND_ERROR; \ - } \ - else \ - args[0] = 0; \ - } \ - else \ - args[0] = CUR.storage[I]; \ - } - - -#define DO_WS \ - { \ - ULong I = (ULong)args[0]; \ - if ( BOUNDS( I, CUR.storeSize ) ) \ - { \ - if ( CUR.pedantic_hinting ) \ - { \ - ARRAY_BOUND_ERROR; \ - } \ - } \ - else \ - CUR.storage[I] = args[1]; \ - } - - - -#define DO_RCVT \ - { \ - ULong I = (ULong)args[0]; \ - if ( BOUNDS( I, CUR.cvtSize ) ) \ - { \ - if ( CUR.pedantic_hinting ) \ - { \ - ARRAY_BOUND_ERROR; \ - } \ - else \ - args[0] = 0; \ - } \ - else \ - args[0] = CUR_Func_read_cvt(I); \ - } - - -#define DO_WCVTP \ - { \ - ULong I = (ULong)args[0]; \ - if ( BOUNDS( I, CUR.cvtSize ) ) \ - { \ - if ( CUR.pedantic_hinting ) \ - { \ - ARRAY_BOUND_ERROR; \ - } \ - } \ - else \ - CUR_Func_write_cvt( I, args[1] ); \ - } - - -#define DO_WCVTF \ - { \ - ULong I = (ULong)args[0]; \ - if ( BOUNDS( I, CUR.cvtSize ) ) \ - { \ - if ( CUR.pedantic_hinting ) \ - { \ - ARRAY_BOUND_ERROR; \ - } \ - } \ - else \ - CUR.cvt[I] = FUnits_To_Pixels( EXEC_ARGS (Short)args[1] ); \ - } - - -#define DO_DEBUG \ - CUR.error = TT_Err_Debug_OpCode; - - -#define DO_ROUND \ - args[0] = CUR_Func_round( args[0], \ - CUR.metrics.compensations[CUR.opcode-0x68] ); - - -#define DO_NROUND \ - args[0] = Round_None( EXEC_ARGS \ - args[0], \ - CUR.metrics.compensations[CUR.opcode - 0x6C] ); - - -#define DO_MAX \ - if ( args[1] > args[0] ) \ - args[0] = args[1]; - - -#define DO_MIN \ - if ( args[1] < args[0] ) \ - args[0] = args[1]; - - -#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH - - -#undef ARRAY_BOUND_ERROR -#define ARRAY_BOUND_ERROR \ - { \ - CUR.error = TT_Err_Invalid_Reference; \ - return; \ - } - - -/*******************************************/ -/* SVTCA[a] : Set F and P vectors to axis */ -/* CodeRange : $00-$01 */ -/* Stack : --> */ - - static void Ins_SVTCA( INS_ARG ) - { - DO_SVTCA - } - - -/*******************************************/ -/* SPVTCA[a] : Set PVector to Axis */ -/* CodeRange : $02-$03 */ -/* Stack : --> */ - - static void Ins_SPVTCA( INS_ARG ) - { - DO_SPVTCA - } - - -/*******************************************/ -/* SFVTCA[a] : Set FVector to Axis */ -/* CodeRange : $04-$05 */ -/* Stack : --> */ - - static void Ins_SFVTCA( INS_ARG ) - { - DO_SFVTCA - } - -/*******************************************/ -/* SPVTL[a] : Set PVector to Line */ -/* CodeRange : $06-$07 */ -/* Stack : uint32 uint32 --> */ - - static void Ins_SPVTL( INS_ARG ) - { - DO_SPVTL - } - - -/*******************************************/ -/* SFVTL[a] : Set FVector to Line */ -/* CodeRange : $08-$09 */ -/* Stack : uint32 uint32 --> */ - - static void Ins_SFVTL( INS_ARG ) - { - DO_SFVTL - } - - -/*******************************************/ -/* SFVTPV[] : Set FVector to PVector */ -/* CodeRange : $0E */ -/* Stack : --> */ - - static void Ins_SFVTPV( INS_ARG ) - { - DO_SFVTPV - } - - -/*******************************************/ -/* SPVFS[] : Set PVector From Stack */ -/* CodeRange : $0A */ -/* Stack : f2.14 f2.14 --> */ - - static void Ins_SPVFS( INS_ARG ) - { - DO_SPVFS - } - - -/*******************************************/ -/* SFVFS[] : Set FVector From Stack */ -/* CodeRange : $0B */ -/* Stack : f2.14 f2.14 --> */ - - static void Ins_SFVFS( INS_ARG ) - { - DO_SFVFS - } - - -/*******************************************/ -/* GPV[] : Get Projection Vector */ -/* CodeRange : $0C */ -/* Stack : ef2.14 --> ef2.14 */ - - static void Ins_GPV( INS_ARG ) - { - DO_GPV - } - - -/*******************************************/ -/* GFV[] : Get Freedom Vector */ -/* CodeRange : $0D */ -/* Stack : ef2.14 --> ef2.14 */ - - static void Ins_GFV( INS_ARG ) - { - DO_GFV - } - - -/*******************************************/ -/* SRP0[] : Set Reference Point 0 */ -/* CodeRange : $10 */ -/* Stack : uint32 --> */ - - static void Ins_SRP0( INS_ARG ) - { - DO_SRP0 - } - - -/*******************************************/ -/* SRP1[] : Set Reference Point 1 */ -/* CodeRange : $11 */ -/* Stack : uint32 --> */ - - static void Ins_SRP1( INS_ARG ) - { - DO_SRP1 - } - - -/*******************************************/ -/* SRP2[] : Set Reference Point 2 */ -/* CodeRange : $12 */ -/* Stack : uint32 --> */ - - static void Ins_SRP2( INS_ARG ) - { - DO_SRP2 - } - - -/*******************************************/ -/* RTHG[] : Round To Half Grid */ -/* CodeRange : $19 */ -/* Stack : --> */ - - static void Ins_RTHG( INS_ARG ) - { - DO_RTHG - } - - -/*******************************************/ -/* RTG[] : Round To Grid */ -/* CodeRange : $18 */ -/* Stack : --> */ - - static void Ins_RTG( INS_ARG ) - { - DO_RTG - } - - -/*******************************************/ -/* RTDG[] : Round To Double Grid */ -/* CodeRange : $3D */ -/* Stack : --> */ - - static void Ins_RTDG( INS_ARG ) - { - DO_RTDG - } - - -/*******************************************/ -/* RUTG[] : Round Up To Grid */ -/* CodeRange : $7C */ -/* Stack : --> */ - - static void Ins_RUTG( INS_ARG ) - { - DO_RUTG - } - - -/*******************************************/ -/* RDTG[] : Round Down To Grid */ -/* CodeRange : $7D */ -/* Stack : --> */ - - static void Ins_RDTG( INS_ARG ) - { - DO_RDTG - } - - -/*******************************************/ -/* ROFF[] : Round OFF */ -/* CodeRange : $7A */ -/* Stack : --> */ - - static void Ins_ROFF( INS_ARG ) - { - DO_ROFF - } - - -/*******************************************/ -/* SROUND[] : Super ROUND */ -/* CodeRange : $76 */ -/* Stack : Eint8 --> */ - - static void Ins_SROUND( INS_ARG ) - { - DO_SROUND - } - - -/*******************************************/ -/* S45ROUND[]: Super ROUND 45 degrees */ -/* CodeRange : $77 */ -/* Stack : uint32 --> */ - - static void Ins_S45ROUND( INS_ARG ) - { - DO_S45ROUND - } - - -/*******************************************/ -/* SLOOP[] : Set LOOP variable */ -/* CodeRange : $17 */ -/* Stack : int32? --> */ - - static void Ins_SLOOP( INS_ARG ) - { - DO_SLOOP - } - - -/*******************************************/ -/* SMD[] : Set Minimum Distance */ -/* CodeRange : $1A */ -/* Stack : f26.6 --> */ - - static void Ins_SMD( INS_ARG ) - { - DO_SMD - } - - -/**********************************************/ -/* SCVTCI[] : Set Control Value Table Cut In */ -/* CodeRange : $1D */ -/* Stack : f26.6 --> */ - - static void Ins_SCVTCI( INS_ARG ) - { - DO_SCVTCI - } - - -/**********************************************/ -/* SSWCI[] : Set Single Width Cut In */ -/* CodeRange : $1E */ -/* Stack : f26.6 --> */ - - static void Ins_SSWCI( INS_ARG ) - { - DO_SSWCI - } - - -/**********************************************/ -/* SSW[] : Set Single Width */ -/* CodeRange : $1F */ -/* Stack : int32? --> */ - - static void Ins_SSW( INS_ARG ) - { - DO_SSW - } - - -/**********************************************/ -/* FLIPON[] : Set Auto_flip to On */ -/* CodeRange : $4D */ -/* Stack : --> */ - - static void Ins_FLIPON( INS_ARG ) - { - DO_FLIPON - } - - -/**********************************************/ -/* FLIPOFF[] : Set Auto_flip to Off */ -/* CodeRange : $4E */ -/* Stack : --> */ - - static void Ins_FLIPOFF( INS_ARG ) - { - DO_FLIPOFF - } - - -/**********************************************/ -/* SANGW[] : Set Angle Weight */ -/* CodeRange : $7E */ -/* Stack : uint32 --> */ - - static void Ins_SANGW( INS_ARG ) - { - /* instruction not supported anymore */ - } - - -/**********************************************/ -/* SDB[] : Set Delta Base */ -/* CodeRange : $5E */ -/* Stack : uint32 --> */ - - static void Ins_SDB( INS_ARG ) - { - DO_SDB - } - - -/**********************************************/ -/* SDS[] : Set Delta Shift */ -/* CodeRange : $5F */ -/* Stack : uint32 --> */ - - static void Ins_SDS( INS_ARG ) - { - DO_SDS - } - - -/**********************************************/ -/* MPPEM[] : Measure Pixel Per EM */ -/* CodeRange : $4B */ -/* Stack : --> Euint16 */ - - static void Ins_MPPEM( INS_ARG ) - { - DO_MPPEM - } - - -/**********************************************/ -/* MPS[] : Measure PointSize */ -/* CodeRange : $4C */ -/* Stack : --> Euint16 */ - - static void Ins_MPS( INS_ARG ) - { - DO_MPS - } - -/*******************************************/ -/* DUP[] : Duplicate top stack element */ -/* CodeRange : $20 */ -/* Stack : StkElt --> StkElt StkElt */ - - static void Ins_DUP( INS_ARG ) - { - DO_DUP - } - - -/*******************************************/ -/* POP[] : POPs the stack's top elt. */ -/* CodeRange : $21 */ -/* Stack : StkElt --> */ - - static void Ins_POP( INS_ARG ) - { - /* nothing to do */ - } - - -/*******************************************/ -/* CLEAR[] : Clear the entire stack */ -/* CodeRange : $22 */ -/* Stack : StkElt... --> */ - - static void Ins_CLEAR( INS_ARG ) - { - DO_CLEAR - } - - -/*******************************************/ -/* SWAP[] : Swap the top two elements */ -/* CodeRange : $23 */ -/* Stack : 2 * StkElt --> 2 * StkElt */ - - static void Ins_SWAP( INS_ARG ) - { - DO_SWAP - } - - -/*******************************************/ -/* DEPTH[] : return the stack depth */ -/* CodeRange : $24 */ -/* Stack : --> uint32 */ - - static void Ins_DEPTH( INS_ARG ) - { - DO_DEPTH - } - - -/*******************************************/ -/* CINDEX[] : copy indexed element */ -/* CodeRange : $25 */ -/* Stack : int32 --> StkElt */ - - static void Ins_CINDEX( INS_ARG ) - { - DO_CINDEX - } - - -/*******************************************/ -/* EIF[] : End IF */ -/* CodeRange : $59 */ -/* Stack : --> */ - - static void Ins_EIF( INS_ARG ) - { - /* nothing to do */ - } - - -/*******************************************/ -/* JROT[] : Jump Relative On True */ -/* CodeRange : $78 */ -/* Stack : StkElt int32 --> */ - - static void Ins_JROT( INS_ARG ) - { - DO_JROT - } - - -/*******************************************/ -/* JMPR[] : JuMP Relative */ -/* CodeRange : $1C */ -/* Stack : int32 --> */ - - static void Ins_JMPR( INS_ARG ) - { - DO_JMPR - } - - -/*******************************************/ -/* JROF[] : Jump Relative On False */ -/* CodeRange : $79 */ -/* Stack : StkElt int32 --> */ - - static void Ins_JROF( INS_ARG ) - { - DO_JROF - } - - -/*******************************************/ -/* LT[] : Less Than */ -/* CodeRange : $50 */ -/* Stack : int32? int32? --> bool */ - - static void Ins_LT( INS_ARG ) - { - DO_LT - } - - -/*******************************************/ -/* LTEQ[] : Less Than or EQual */ -/* CodeRange : $51 */ -/* Stack : int32? int32? --> bool */ - - static void Ins_LTEQ( INS_ARG ) - { - DO_LTEQ - } - - -/*******************************************/ -/* GT[] : Greater Than */ -/* CodeRange : $52 */ -/* Stack : int32? int32? --> bool */ - - static void Ins_GT( INS_ARG ) - { - DO_GT - } - - -/*******************************************/ -/* GTEQ[] : Greater Than or EQual */ -/* CodeRange : $53 */ -/* Stack : int32? int32? --> bool */ - - static void Ins_GTEQ( INS_ARG ) - { - DO_GTEQ - } - - -/*******************************************/ -/* EQ[] : EQual */ -/* CodeRange : $54 */ -/* Stack : StkElt StkElt --> bool */ - - static void Ins_EQ( INS_ARG ) - { - DO_EQ - } - - -/*******************************************/ -/* NEQ[] : Not EQual */ -/* CodeRange : $55 */ -/* Stack : StkElt StkElt --> bool */ - - static void Ins_NEQ( INS_ARG ) - { - DO_NEQ - } - - -/*******************************************/ -/* ODD[] : Odd */ -/* CodeRange : $56 */ -/* Stack : f26.6 --> bool */ - - static void Ins_ODD( INS_ARG ) - { - DO_ODD - } - - -/*******************************************/ -/* EVEN[] : Even */ -/* CodeRange : $57 */ -/* Stack : f26.6 --> bool */ - - static void Ins_EVEN( INS_ARG ) - { - DO_EVEN - } - - -/*******************************************/ -/* AND[] : logical AND */ -/* CodeRange : $5A */ -/* Stack : uint32 uint32 --> uint32 */ - - static void Ins_AND( INS_ARG ) - { - DO_AND - } - - -/*******************************************/ -/* OR[] : logical OR */ -/* CodeRange : $5B */ -/* Stack : uint32 uint32 --> uint32 */ - - static void Ins_OR( INS_ARG ) - { - DO_OR - } - - -/*******************************************/ -/* NOT[] : logical NOT */ -/* CodeRange : $5C */ -/* Stack : StkElt --> uint32 */ - - static void Ins_NOT( INS_ARG ) - { - DO_NOT - } - - -/*******************************************/ -/* ADD[] : ADD */ -/* CodeRange : $60 */ -/* Stack : f26.6 f26.6 --> f26.6 */ - - static void Ins_ADD( INS_ARG ) - { - DO_ADD - } - - -/*******************************************/ -/* SUB[] : SUBstract */ -/* CodeRange : $61 */ -/* Stack : f26.6 f26.6 --> f26.6 */ - - static void Ins_SUB( INS_ARG ) - { - DO_SUB - } - - -/*******************************************/ -/* DIV[] : DIVide */ -/* CodeRange : $62 */ -/* Stack : f26.6 f26.6 --> f26.6 */ - - static void Ins_DIV( INS_ARG ) - { - DO_DIV - } - - -/*******************************************/ -/* MUL[] : MULtiply */ -/* CodeRange : $63 */ -/* Stack : f26.6 f26.6 --> f26.6 */ - - static void Ins_MUL( INS_ARG ) - { - DO_MUL - } - - -/*******************************************/ -/* ABS[] : ABSolute value */ -/* CodeRange : $64 */ -/* Stack : f26.6 --> f26.6 */ - - static void Ins_ABS( INS_ARG ) - { - DO_ABS - } - - -/*******************************************/ -/* NEG[] : NEGate */ -/* CodeRange : $65 */ -/* Stack : f26.6 --> f26.6 */ - - static void Ins_NEG( INS_ARG ) - { - DO_NEG - } - - -/*******************************************/ -/* FLOOR[] : FLOOR */ -/* CodeRange : $66 */ -/* Stack : f26.6 --> f26.6 */ - - static void Ins_FLOOR( INS_ARG ) - { - DO_FLOOR - } - - -/*******************************************/ -/* CEILING[] : CEILING */ -/* CodeRange : $67 */ -/* f26.6 --> f26.6 */ - - static void Ins_CEILING( INS_ARG ) - { - DO_CEILING - } - -/*******************************************/ -/* RS[] : Read Store */ -/* CodeRange : $43 */ -/* Stack : uint32 --> uint32 */ - - static void Ins_RS( INS_ARG ) - { - DO_RS - } - - -/*******************************************/ -/* WS[] : Write Store */ -/* CodeRange : $42 */ -/* Stack : uint32 uint32 --> */ - - static void Ins_WS( INS_ARG ) - { - DO_WS - } - - -/*******************************************/ -/* WCVTP[] : Write CVT in Pixel units */ -/* CodeRange : $44 */ -/* Stack : f26.6 uint32 --> */ - - static void Ins_WCVTP( INS_ARG ) - { - DO_WCVTP - } - - -/*******************************************/ -/* WCVTF[] : Write CVT in FUnits */ -/* CodeRange : $70 */ -/* Stack : uint32 uint32 --> */ - - static void Ins_WCVTF( INS_ARG ) - { - DO_WCVTF - } - - -/*******************************************/ -/* RCVT[] : Read CVT */ -/* CodeRange : $45 */ -/* Stack : uint32 --> f26.6 */ - - static void Ins_RCVT( INS_ARG ) - { - DO_RCVT - } - - -/********************************************/ -/* AA[] : Adjust Angle */ -/* CodeRange : $7F */ -/* Stack : uint32 --> */ - - static void Ins_AA( INS_ARG ) - { - /* Intentional - no longer supported */ - } - - -/********************************************/ -/* DEBUG[] : DEBUG. Unsupported */ -/* CodeRange : $4F */ -/* Stack : uint32 --> */ - -/* NOTE : The original instruction pops a value from the stack */ - - static void Ins_DEBUG( INS_ARG ) - { - DO_DEBUG - } - -/*******************************************/ -/* ROUND[ab] : ROUND value */ -/* CodeRange : $68-$6B */ -/* Stack : f26.6 --> f26.6 */ - - static void Ins_ROUND( INS_ARG ) - { - DO_ROUND - } - -/*******************************************/ -/* NROUND[ab]: No ROUNDing of value */ -/* CodeRange : $6C-$6F */ -/* Stack : f26.6 --> f26.6 */ - - static void Ins_NROUND( INS_ARG ) - { - DO_NROUND - } - - - -/*******************************************/ -/* MAX[] : MAXimum */ -/* CodeRange : $68 */ -/* Stack : int32? int32? --> int32 */ - - static void Ins_MAX( INS_ARG ) - { - DO_MAX - } - - -/*******************************************/ -/* MIN[] : MINimum */ -/* CodeRange : $69 */ -/* 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 */ -/* CodeRange : $26 */ -/* Stack : int32? --> StkElt */ - - static void Ins_MINDEX( INS_ARG ) - { - 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]; - - MEM_Move( (&CUR.stack[CUR.args - L ]), - (&CUR.stack[CUR.args - L + 1]), - (L - 1) * sizeof ( Long ) ); - - CUR.stack[CUR.args - 1] = K; - } - - -/*******************************************/ -/* ROLL[] : roll top three elements */ -/* CodeRange : $8A */ -/* Stack : 3 * StkElt --> 3 * StkElt */ - - static void Ins_ROLL( INS_ARG ) - { - Long A, B, C; - - - 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 specs' order. */ -/* */ -/****************************************************************/ - - static Bool SkipCode( EXEC_OP ) - { - CUR.IP += CUR.length; - - if ( CUR.IP < CUR.codeSize ) - if ( CALC_Length() == SUCCESS ) - return SUCCESS; - - CUR.error = TT_Err_Code_Overflow; - return FAILURE; - } - - -/*******************************************/ -/* IF[] : IF test */ -/* CodeRange : $58 */ -/* Stack : StkElt --> */ - - static void Ins_IF( INS_ARG ) - { - Int nIfs; - 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 = (nIfs == 1); - break; - - case 0x59: /* EIF */ - nIfs--; - Out = (nIfs == 0); - break; - } - } while ( Out == 0 ); - } - - -/*******************************************/ -/* ELSE[] : ELSE */ -/* CodeRange : $1B */ -/* Stack : --> */ - - static void Ins_ELSE( INS_ARG ) - { - Int nIfs; - - - 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 specs' order. */ -/* */ -/****************************************************************/ - - static PDefRecord Locate_FDef( EXEC_OPS Int n, Bool new_def ) - { - PDefRecord def; - UShort hash; - UShort cnt; - - /* The function table is interpreted as a simple hash table */ - /* with indexes computed modulo maxFDefs and the linear search */ - /* of free cells in the case of a collision. */ - /* Except for some old Apple fonts, all functions in a TrueType */ - /* font fit into 0..maxFDefs - 1 range and the lookup is */ - /* reduced to a single step. */ - - /* Minor optimization. */ - if ( !new_def && ( n < 0 || n > CUR.maxFunc ) ) - return NULL; - - for ( cnt = 0; cnt < CUR.maxFDefs; ++cnt ) - { - hash = ( (UShort)n + cnt ) % CUR.maxFDefs; - def = &CUR.FDefs[ hash ]; - if ( !def->Active ) - return new_def ? def : NULL; - if ( def->Opc == n ) - return def; - } - - /* The table is full and the entry has not been found. */ - return NULL; - } - - -/*******************************************/ -/* FDEF[] : Function DEFinition */ -/* CodeRange : $2C */ -/* Stack : uint32 --> */ - - static void Ins_FDEF( INS_ARG ) - { - Int n; - PDefRecord def; - - - /* check that there is enough room */ - if ( CUR.numFDefs >= CUR.maxFDefs ) - { - /* We could introduce a new error message, but we're too close */ - /* from the release to change all the 'po' files again.. */ - CUR.error = TT_Err_Too_Many_Ins; - return; - } - - n = (Int)args[0]; - if ( n < 0 || (ULong)n != args[0] ) - { - /* Gotcha. Function index is uint32 according to the specs */ - /* but TDefRecord.Opc is defined as Int. We cannot store */ - /* the definition of this function. */ - CUR.error = TT_Err_Bad_Argument; - return; - } - - def = Locate_FDef( EXEC_ARGS n, TRUE ); - if ( !def ) - { - /* Oh, oh. Something is wrong. Locate_FDef should never fail here. */ - CUR.error = TT_Err_Too_Many_Ins; - return; - } - - /* Some font programs are broken enough to redefine functions! */ - if ( !def->Active ) - CUR.numFDefs++; - - def->Range = CUR.curRange; - def->Opc = n; - def->Start = CUR.IP + 1; - def->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 */ -/* CodeRange : $2D */ -/* Stack : --> */ - - static void Ins_ENDF( INS_ARG ) - { - PCallRecord pRec; - - - 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: When the last intruction 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's why we do not test */ - /* the result of Ins_Goto_CodeRange() here! */ - } - - -/*******************************************/ -/* CALL[] : CALL function */ -/* CodeRange : $2B */ -/* Stack : uint32? --> */ - - static void Ins_CALL( INS_ARG ) - { - Int n; - PDefRecord def; - PCallRecord pCrec; - - - n = (Int)args[0]; - def = Locate_FDef( EXEC_ARGS n, FALSE ); - if ( !def ) - { - CUR.error = TT_Err_Invalid_Reference; - return; - } - - /* check 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; - } - - -/*******************************************/ -/* LOOPCALL[]: LOOP and CALL function */ -/* CodeRange : $2A */ -/* Stack : uint32? Eint16? --> */ - - static void Ins_LOOPCALL( INS_ARG ) - { - Int n; - Long count; - PDefRecord def; - PCallRecord pTCR; - - - n = (Int)args[1]; - def = Locate_FDef( EXEC_ARGS n, FALSE ); - if ( !def ) - { - CUR.error = TT_Err_Invalid_Reference; - return; - } - - if ( CUR.callTop >= CUR.callSize ) - { - CUR.error = TT_Err_Stack_Overflow; - return; - } - - count = (Long)args[0]; - if ( count <= 0 ) - return; - - pTCR = &CUR.callStack[CUR.callTop]; - - pTCR->Caller_Range = CUR.curRange; - pTCR->Caller_IP = CUR.IP + 1; - pTCR->Cur_Count = count; - pTCR->Cur_Restart = def->Start; - - CUR.callTop++; - - INS_Goto_CodeRange( def->Range, - def->Start ); - - CUR.step_ins = FALSE; - } - - -/*******************************************/ -/* IDEF[] : Instruction DEFinition */ -/* CodeRange : $89 */ -/* Stack : Eint8 --> */ - - static void Ins_IDEF( INS_ARG ) - { - Byte opcode; - PDefRecord def; - PDefRecord limit; - - - opcode = (Byte)args[0]; - - /* First of all, look for the same instruction in our table */ - def = CUR.IDefs; - limit = def + CUR.numIDefs; - for ( ; def < limit; def++ ) - if ( def->Opc == opcode ) - break; - - if ( def == limit ) - { - /* check that there is enough room for a new instruction */ - if ( CUR.numIDefs >= CUR.maxIDefs ) - { - /* XXX Bad error code. See FDEF[]. */ - CUR.error = TT_Err_Too_Many_Ins; - return; - } - CUR.numIDefs++; - } - - def->Opc = opcode; - def->Start = CUR.IP + 1; - def->Range = CUR.curRange; - def->Active = TRUE; - - if ( opcode > CUR.maxIns ) - CUR.maxIns = opcode; - - /* 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 specs' order. */ -/* */ -/****************************************************************/ - -/*******************************************/ -/* NPUSHB[] : PUSH N Bytes */ -/* CodeRange : $40 */ -/* Stack : --> uint32... */ - - static void Ins_NPUSHB( INS_ARG ) - { - UShort L, K; - - - L = (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 */ -/* CodeRange : $41 */ -/* Stack : --> int32... */ - - static void Ins_NPUSHW( INS_ARG ) - { - UShort L, K; - - - L = (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 */ -/* CodeRange : $B0-$B7 */ -/* Stack : --> uint32... */ - - static void Ins_PUSHB( INS_ARG ) - { - UShort L, K; - - - L = (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 */ -/* CodeRange : $B8-$BF */ -/* Stack : --> int32... */ - - static void Ins_PUSHW( INS_ARG ) - { - UShort L, K; - - - L = (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 */ -/* CodeRange : $46-$47 */ -/* Stack : uint32 --> f26.6 */ - -/* BULLSHIT: Measures from the original glyph must be taken */ -/* along the dual projection vector! */ - - static void Ins_GC( INS_ARG ) - { - ULong L; - TT_F26Dot6 R; - - - L = (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_Func_dualproj( CUR.zp2.org + L, NULL_Vector ); - else - R = CUR_Func_project( CUR.zp2.cur + L, NULL_Vector ); - } - - args[0] = R; - } - - -/**********************************************/ -/* SCFS[] : Set Coordinate From Stack */ -/* CodeRange : $48 */ -/* Stack : f26.6 uint32 --> */ -/* */ -/* Formula: */ -/* */ -/* OA := OA + ( value - OA.p )/( f.p ) * f */ -/* */ - - static void Ins_SCFS( INS_ARG ) - { - Long K; - UShort L; - - - L = (UShort)args[0]; - - if ( BOUNDS( L, CUR.zp2.n_points ) ) - { - if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; - return; - } - - K = CUR_Func_project( CUR.zp2.cur + L, NULL_Vector ); - - 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 */ -/* CodeRange : $49-$4A */ -/* 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 ) - { - UShort K, L; - TT_F26Dot6 D; - - - K = (UShort)args[1]; - L = (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; - } - else - 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 */ -/* CodeRange : $86-$87 */ -/* Stack : uint32 uint32 --> */ - - static void Ins_SDPVTL( INS_ARG ) - { - Long A, B, C; - UShort p1, p2; /* was Int in pas type ERROR */ - - - p1 = (UShort)args[1]; - p2 = (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; - } - - { - TT_Vector* v1 = CUR.zp1.org + p2; - TT_Vector* v2 = CUR.zp2.org + p1; - - - A = v1->x - v2->x; - B = v1->y - v2->y; - } - - if ( (CUR.opcode & 1) != 0 ) - { - C = B; /* CounterClockwise rotation */ - B = A; - A = -C; - } - - NORMalize( A, B, &CUR.GS.dualVector ); - - { - TT_Vector* v1 = CUR.zp1.cur + p2; - TT_Vector* v2 = CUR.zp2.cur + p1; - - - A = v1->x - v2->x; - B = v1->y - v2->y; - } - - if ( (CUR.opcode & 1) != 0 ) - { - C = B; /* CounterClockwise rotation */ - B = A; - A = -C; - } - - NORMalize( A, B, &CUR.GS.projVector ); - - COMPUTE_Funcs(); - } - - -/*******************************************/ -/* SZP0[] : Set Zone Pointer 0 */ -/* CodeRange : $13 */ -/* Stack : uint32 --> */ - - static void Ins_SZP0( INS_ARG ) - { - switch ( (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 = (UShort)args[0]; - } - - -/*******************************************/ -/* SZP1[] : Set Zone Pointer 1 */ -/* CodeRange : $14 */ -/* Stack : uint32 --> */ - - static void Ins_SZP1( INS_ARG ) - { - switch ( (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 = (UShort)args[0]; - } - - -/*******************************************/ -/* SZP2[] : Set Zone Pointer 2 */ -/* CodeRange : $15 */ -/* Stack : uint32 --> */ - - static void Ins_SZP2( INS_ARG ) - { - switch ( (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 = (UShort)args[0]; - } - - -/*******************************************/ -/* SZPS[] : Set Zone Pointers */ -/* CodeRange : $16 */ -/* Stack : uint32 --> */ - - static void Ins_SZPS( INS_ARG ) - { - switch ( (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 = (UShort)args[0]; - CUR.GS.gep1 = (UShort)args[0]; - CUR.GS.gep2 = (UShort)args[0]; - } - - -/*******************************************/ -/* INSTCTRL[]: INSTruction ConTRol */ -/* CodeRange : $8e */ -/* Stack : int32 int32 --> */ - - static void Ins_INSTCTRL( INS_ARG ) - { - 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 = - (Byte)( CUR.GS.instruct_control & ~(Byte)K ) | (Byte)L; - } - - -/*******************************************/ -/* SCANCTRL[]: SCAN ConTRol */ -/* CodeRange : $85 */ -/* Stack : uint32? --> */ - - static void Ins_SCANCTRL( INS_ARG ) - { - Int A; - - - /* Get Threshold */ - A = (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 ( (args[0] & 0x100) != 0 && CUR.metrics.pointSize <= A ) - CUR.GS.scan_control = TRUE; - - if ( (args[0] & 0x200) != 0 && CUR.metrics.rotated ) - CUR.GS.scan_control = TRUE; - - if ( (args[0] & 0x400) != 0 && CUR.metrics.stretched ) - CUR.GS.scan_control = TRUE; - - if ( (args[0] & 0x800) != 0 && CUR.metrics.pointSize > A ) - CUR.GS.scan_control = FALSE; - - if ( (args[0] & 0x1000) != 0 && CUR.metrics.rotated ) - CUR.GS.scan_control = FALSE; - - if ( (args[0] & 0x2000) != 0 && CUR.metrics.stretched ) - CUR.GS.scan_control = FALSE; -} - - -/*******************************************/ -/* SCANTYPE[]: SCAN TYPE */ -/* CodeRange : $8D */ -/* 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 = (Int)args[0]; - } - } - - - -/****************************************************************/ -/* */ -/* MANAGING OUTLINES */ -/* */ -/* Instructions appear in the specs' order. */ -/* */ -/****************************************************************/ - -/**********************************************/ -/* FLIPPT[] : FLIP PoinT */ -/* CodeRange : $80 */ -/* Stack : uint32... --> */ - - static void Ins_FLIPPT( INS_ARG ) - { - UShort point; - - - if ( CUR.top < CUR.GS.loop ) - { - CUR.error = TT_Err_Too_Few_Arguments; - return; - } - - while ( CUR.GS.loop > 0 ) - { - CUR.args--; - - point = (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.touch[point] ^= TT_Flag_On_Curve; - - CUR.GS.loop--; - } - - CUR.GS.loop = 1; - CUR.new_top = CUR.args; - } - - -/**********************************************/ -/* FLIPRGON[]: FLIP RanGe ON */ -/* CodeRange : $81 */ -/* Stack : uint32 uint32 --> */ -/* (but UShorts are sufficient) */ - - static void Ins_FLIPRGON( INS_ARG ) - { - UShort I, K, L; - - - K = (UShort)args[1]; - L = (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.touch[I] |= TT_Flag_On_Curve; - } - - -/**********************************************/ -/* FLIPRGOFF : FLIP RanGe OFF */ -/* CodeRange : $82 */ -/* Stack : uint32 uint32 --> */ -/* (but UShorts are sufficient) */ - - static void Ins_FLIPRGOFF( INS_ARG ) - { - UShort I, K, L; - - - K = (UShort)args[1]; - L = (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.touch[I] &= ~TT_Flag_On_Curve; - } - - - static Bool Compute_Point_Displacement( EXEC_OPS - PCoordinates x, - PCoordinates y, - PGlyph_Zone zone, - UShort* refp ) - { - TGlyph_Zone zp; - UShort p; - TT_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_Displacement; - return FAILURE; - } - - *zone = zp; - *refp = p; - - d = CUR_Func_project( zp.cur + p, zp.org + p ); - - *x = TT_MulDiv(d, (Long)CUR.GS.freeVector.x * 0x10000L, CUR.F_dot_P ); - *y = TT_MulDiv(d, (Long)CUR.GS.freeVector.y * 0x10000L, CUR.F_dot_P ); - - return SUCCESS; - } - - - static void Move_Zp2_Point( EXEC_OPS - UShort point, - TT_F26Dot6 dx, - TT_F26Dot6 dy, - Bool touch ) - { - if ( CUR.GS.freeVector.x != 0 ) - { - CUR.zp2.cur[point].x += dx; - if ( touch ) - CUR.zp2.touch[point] |= TT_Flag_Touched_X; - } - - if ( CUR.GS.freeVector.y != 0 ) - { - CUR.zp2.cur[point].y += dy; - if ( touch ) - CUR.zp2.touch[point] |= TT_Flag_Touched_Y; - } - } - - -/**********************************************/ -/* SHP[a] : SHift Point by the last point */ -/* CodeRange : $32-33 */ -/* Stack : uint32... --> */ - - static void Ins_SHP( INS_ARG ) - { - TGlyph_Zone zp; - UShort refp; - - TT_F26Dot6 dx, - dy; - UShort point; - - - 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 = (UShort)CUR.stack[CUR.args]; - - if ( BOUNDS( point, CUR.zp2.n_points ) ) - { - if ( CUR.pedantic_hinting ) - { - CUR.error = TT_Err_Invalid_Reference; - return; - } - } - else - /* 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 */ -/* CodeRange : $34-35 */ -/* Stack : uint32 --> */ - - static void Ins_SHC( INS_ARG ) - { - TGlyph_Zone zp; - UShort refp; - TT_F26Dot6 dx, - dy; - - Short contour; - UShort first_point, last_point, i; - - - contour = (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 = CUR.pts.contours[contour - 1] + 1; - - last_point = CUR.pts.contours[contour]; - - /* 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 = CUR.zp2.n_points - 1; - else - last_point = 0; - } - - /* UNDOCUMENTED! SHC doesn't touch the points */ - for ( i = first_point; i <= last_point; i++ ) - { - if ( zp.cur != CUR.zp2.cur || refp != i ) - MOVE_Zp2_Point( i, dx, dy, FALSE ); - } - } - - -/**********************************************/ -/* SHZ[a] : SHift Zone */ -/* CodeRange : $36-37 */ -/* Stack : uint32 --> */ - - static void Ins_SHZ( INS_ARG ) - { - TGlyph_Zone zp; - UShort refp; - TT_F26Dot6 dx, - dy; - - 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; - - if ( CUR.zp2.n_points > 0 ) - last_point = CUR.zp2.n_points - 1; - else - last_point = 0; - - /* 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 */ -/* CodeRange : $38 */ -/* Stack : f26.6 uint32... --> */ - - static void Ins_SHPIX( INS_ARG ) - { - TT_F26Dot6 dx, dy; - UShort point; - - - if ( CUR.top < CUR.GS.loop + 1 ) - { - CUR.error = TT_Err_Invalid_Reference; - return; - } - - dx = TT_MulDiv( args[0], - (Long)CUR.GS.freeVector.x, - 0x4000 ); - dy = TT_MulDiv( args[0], - (Long)CUR.GS.freeVector.y, - 0x4000 ); - - while ( CUR.GS.loop > 0 ) - { - CUR.args--; - - point = (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 */ -/* CodeRange : $3A-$3B */ -/* Stack : f26.6 uint32 --> */ - - static void Ins_MSIRP( INS_ARG ) - { - UShort point; - TT_F26Dot6 distance; - - - point = (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.gep0 == 0 ) /* if in twilight zone */ - { - CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0]; - 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 */ -/* CodeRange : $2E-$2F */ -/* Stack : uint32 --> */ - - static void Ins_MDAP( INS_ARG ) - { - UShort point; - TT_F26Dot6 cur_dist, - distance; - - - point = (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_Func_project( CUR.zp0.cur + point, NULL_Vector ); - distance = CUR_Func_round( cur_dist, - CUR.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 */ -/* CodeRange : $3E-$3F */ -/* Stack : uint32 uint32 --> */ - - static void Ins_MIAP( INS_ARG ) - { - ULong cvtEntry; - UShort point; - TT_F26Dot6 distance, - org_dist; - - - cvtEntry = (ULong)args[1]; - point = (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; - } - - /* UNDOCUMENTED! */ - /* */ - /* The behaviour of an MIAP instruction is quite */ - /* different when used in the twilight zone. */ - /* */ - /* First, no control value cutin 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 */ - /* specs :) */ - /* */ - /* 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_MulDiv( CUR.GS.freeVector.x, - distance, 0x4000L ); - CUR.zp0.org[point].y = TT_MulDiv( CUR.GS.freeVector.y, - distance, 0x4000L ); - CUR.zp0.cur[point] = CUR.zp0.org[point]; - } - - org_dist = CUR_Func_project( CUR.zp0.cur + point, NULL_Vector ); - - if ( (CUR.opcode & 1) != 0 ) /* rounding and control cutin flag */ - { - if ( ABS( distance - org_dist ) > CUR.GS.control_value_cutin ) - distance = org_dist; - - distance = CUR_Func_round( distance, CUR.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 */ -/* CodeRange : $C0-$DF */ -/* Stack : uint32 --> */ - - static void Ins_MDRP( INS_ARG ) - { - UShort point; - TT_F26Dot6 org_dist, distance; - - - point = (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? */ - - org_dist = CUR_Func_dualproj( CUR.zp1.org + point, - CUR.zp0.org + CUR.GS.rp0 ); - - /* single width cutin test */ - - if ( ABS( org_dist ) < 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.metrics.compensations[CUR.opcode & 3] ); - else - distance = Round_None( EXEC_ARGS - org_dist, - CUR.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 */ -/* CodeRange : $E0-$FF */ -/* Stack : int32? uint32 --> */ - - static void Ins_MIRP( INS_ARG ) - { - UShort point; - ULong cvtEntry; - - TT_F26Dot6 cvt_dist, - distance, - cur_dist, - org_dist; - - - point = (UShort)args[0]; - cvtEntry = (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 ( ABS( cvt_dist ) < 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_MulDiv( cvt_dist, - CUR.GS.freeVector.x, - 0x4000 ); - - CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y + - TT_MulDiv( cvt_dist, - CUR.GS.freeVector.y, - 0x4000 ); - - CUR.zp1.cur[point] = CUR.zp1.org[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 ( ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin ) - cvt_dist = org_dist; - - distance = CUR_Func_round( cvt_dist, - CUR.metrics.compensations[CUR.opcode & 3] ); - } - else - distance = Round_None( EXEC_ARGS - cvt_dist, - CUR.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; - - /* UNDOCUMENTED! */ - - CUR.GS.rp2 = point; - } - - -/**********************************************/ -/* ALIGNRP[] : ALIGN Relative Point */ -/* CodeRange : $3C */ -/* Stack : uint32 uint32... --> */ - - static void Ins_ALIGNRP( INS_ARG ) - { - UShort point; - TT_F26Dot6 distance; - - - 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 = (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 */ -/* CodeRange : $0F */ -/* Stack : 5 * uint32 --> */ - - static void Ins_ISECT( INS_ARG ) - { - UShort point, - a0, a1, - b0, b1; - - TT_F26Dot6 discriminant; - - TT_F26Dot6 dx, dy, - dax, day, - dbx, dby; - - TT_F26Dot6 val; - - TT_Vector R; - - - point = (UShort)args[0]; - - a0 = (UShort)args[1]; - a1 = (UShort)args[2]; - b0 = (UShort)args[3]; - b1 = (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.touch[point] |= TT_Flag_Touched_Both; - - discriminant = TT_MulDiv( dax, -dby, 0x40L ) + - TT_MulDiv( day, dbx, 0x40L ); - - if ( ABS( discriminant ) >= 0x40 ) - { - val = TT_MulDiv( dx, -dby, 0x40L ) + TT_MulDiv( dy, dbx, 0x40L ); - - 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 */ -/* CodeRange : $27 */ -/* Stack : uint32 uint32 --> */ - - static void Ins_ALIGNPTS( INS_ARG ) - { - UShort p1, p2; - TT_F26Dot6 distance; - - - p1 = (UShort)args[0]; - p2 = (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 */ -/* CodeRange : $39 */ -/* Stack : uint32... --> */ - - static void Ins_IP( INS_ARG ) - { - TT_F26Dot6 org_a, org_b, org_x, - cur_a, cur_b, cur_x, - distance; - UShort point; - - - if ( CUR.top < CUR.GS.loop ) - { - CUR.error = TT_Err_Invalid_Reference; - return; - } - - /* 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 ) ) - { - org_a = cur_a = 0; - org_b = cur_b = 0; - } - else - { - org_a = CUR_Func_dualproj( CUR.zp0.org + CUR.GS.rp1, NULL_Vector ); - org_b = CUR_Func_dualproj( CUR.zp1.org + CUR.GS.rp2, NULL_Vector ); - - cur_a = CUR_Func_project( CUR.zp0.cur + CUR.GS.rp1, NULL_Vector ); - cur_b = CUR_Func_project( CUR.zp1.cur + CUR.GS.rp2, NULL_Vector ); - } - - while ( CUR.GS.loop > 0 ) - { - CUR.args--; - - point = (UShort)CUR.stack[CUR.args]; - if ( BOUNDS( point, CUR.zp2.n_points ) ) - { - if ( CUR.pedantic_hinting ) - { - CUR.error = TT_Err_Invalid_Reference; - return; - } - } - else - { - org_x = CUR_Func_dualproj( CUR.zp2.org + point, NULL_Vector ); - cur_x = CUR_Func_project ( CUR.zp2.cur + point, NULL_Vector ); - - if ( ( org_a <= org_b && org_x <= org_a ) || - ( org_a > org_b && org_x >= org_a ) ) - - distance = ( cur_a - org_a ) + ( org_x - cur_x ); - - else if ( ( org_a <= org_b && org_x >= org_b ) || - ( org_a > org_b && org_x < org_b ) ) - - distance = ( cur_b - org_b ) + ( org_x - cur_x ); - - else - /* note: it seems that rounding this value isn't a good */ - /* idea (cf. width of capital 'S' in Times) */ - - distance = TT_MulDiv( cur_b - cur_a, - org_x - org_a, - org_b - org_a ) + ( cur_a - cur_x ); - - CUR_Func_move( &CUR.zp2, point, distance ); - } - - CUR.GS.loop--; - } - - CUR.GS.loop = 1; - CUR.new_top = CUR.args; - } - - -/**********************************************/ -/* UTP[a] : UnTouch Point */ -/* CodeRange : $29 */ -/* Stack : uint32 --> */ - - static void Ins_UTP( INS_ARG ) - { - UShort point; - Byte mask; - - - point = (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 &= ~TT_Flag_Touched_X; - - if ( CUR.GS.freeVector.y != 0 ) - mask &= ~TT_Flag_Touched_Y; - - CUR.zp0.touch[point] &= mask; - } - - - /* Local variables for Ins_IUP: */ - struct LOC_Ins_IUP - { - TT_Vector* orgs; /* original and current coordinate */ - TT_Vector* curs; /* arrays */ - }; - - - static void Shift( UShort p1, - UShort p2, - UShort p, - struct LOC_Ins_IUP* LINK ) - { - UShort i; - TT_F26Dot6 x; - - - x = LINK->curs[p].x - LINK->orgs[p].x; - - for ( i = p1; i < p; i++ ) - LINK->curs[i].x += x; - - for ( i = p + 1; i <= p2; i++ ) - LINK->curs[i].x += x; - } - - - static void Interp( UShort p1, - UShort p2, - UShort ref1, - UShort ref2, - struct LOC_Ins_IUP* LINK ) - { - UShort i; - TT_F26Dot6 x, x1, x2, d1, d2; - - - if ( p1 > p2 ) - return; - - x1 = LINK->orgs[ref1].x; - d1 = LINK->curs[ref1].x - LINK->orgs[ref1].x; - x2 = LINK->orgs[ref2].x; - d2 = LINK->curs[ref2].x - LINK->orgs[ref2].x; - - if ( x1 == x2 ) - { - for ( i = p1; i <= p2; i++ ) - { - x = LINK->orgs[i].x; - - if ( x <= x1 ) - x += d1; - else - x += d2; - - LINK->curs[i].x = x; - } - return; - } - - if ( x1 < x2 ) - { - for ( i = p1; i <= p2; i++ ) - { - x = LINK->orgs[i].x; - - if ( x <= x1 ) - x += d1; - else - { - if ( x >= x2 ) - x += d2; - else - x = LINK->curs[ref1].x + - TT_MulDiv( x - x1, - LINK->curs[ref2].x - LINK->curs[ref1].x, - x2 - x1 ); - } - LINK->curs[i].x = x; - } - return; - } - - /* x2 < x1 */ - - for ( i = p1; i <= p2; i++ ) - { - x = LINK->orgs[i].x; - if ( x <= x2 ) - x += d2; - else - { - if ( x >= x1 ) - x += d1; - else - x = LINK->curs[ref1].x + - TT_MulDiv( x - x1, - LINK->curs[ref2].x - LINK->curs[ref1].x, - x2 - x1 ); - } - LINK->curs[i].x = x; - } - } - - -/**********************************************/ -/* IUP[a] : Interpolate Untouched Points */ -/* CodeRange : $30-$31 */ -/* Stack : --> */ - - static void Ins_IUP( INS_ARG ) - { - struct LOC_Ins_IUP V; - Byte mask; - - UShort first_point; /* first point of contour */ - UShort end_point; /* end point (last+1) of contour */ - - UShort first_touched; /* first touched point in contour */ - UShort cur_touched; /* current touched point in contour */ - - UShort point; /* current point */ - Short contour; /* current contour */ - - - if ( CUR.opcode & 1 ) - { - mask = TT_Flag_Touched_X; - V.orgs = CUR.pts.org; - V.curs = CUR.pts.cur; - } - else - { - mask = TT_Flag_Touched_Y; - V.orgs = (TT_Vector*)( ((TT_F26Dot6*)CUR.pts.org) + 1 ); - V.curs = (TT_Vector*)( ((TT_F26Dot6*)CUR.pts.cur) + 1 ); - } - - contour = 0; - point = 0; - - do - { - end_point = CUR.pts.contours[contour]; - first_point = point; - - while ( point <= end_point && (CUR.pts.touch[point] & mask) == 0 ) - point++; - - if ( point <= end_point ) - { - first_touched = point; - cur_touched = point; - - point++; - - while ( point <= end_point ) - { - if ( (CUR.pts.touch[point] & mask) != 0 ) - { - if ( point > 0 ) - Interp( cur_touched + 1, - point - 1, - cur_touched, - point, - &V ); - cur_touched = point; - } - - point++; - } - - if ( cur_touched == first_touched ) - Shift( first_point, end_point, cur_touched, &V ); - else - { - Interp( cur_touched + 1, - end_point, - cur_touched, - first_touched, - &V ); - - if ( first_touched > 0 ) - Interp( first_point, - first_touched - 1, - cur_touched, - first_touched, - &V ); - } - } - contour++; - } while ( contour < CUR.pts.n_contours ); - } - - -/**********************************************/ -/* DELTAPn[] : DELTA Exceptions P1, P2, P3 */ -/* CodeRange : $5D,$71,$72 */ -/* Stack : uint32 (2 * uint32)... --> */ - - static void Ins_DELTAP( INS_ARG ) - { - ULong nump, k; - UShort A; - ULong C; - Long B; - - - nump = (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 = (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 = ((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() == (Long)C ) - { - B = ((ULong)B & 0xF) - 8; - if ( B >= 0 ) - B++; - B = B * 64L / (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 */ -/* CodeRange : $73,$74,$75 */ -/* Stack : uint32 (2 * uint32)... --> */ - - static void Ins_DELTAC( INS_ARG ) - { - ULong nump, k; - ULong A, C; - Long B; - - - nump = (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 = (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 = ((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() == (Long)C ) - { - B = ((ULong)B & 0xF) - 8; - if ( B >= 0 ) - B++; - B = B * 64L / (1L << CUR.GS.delta_shift); - - CUR_Func_move_cvt( A, B ); - } - } - } - - CUR.new_top = CUR.args; - } - - - -/****************************************************************/ -/* */ -/* MISC. INSTRUCTIONS */ -/* */ -/****************************************************************/ - - -/**********************************************/ -/* GETINFO[] : GET INFOrmation */ -/* CodeRange : $88 */ -/* Stack : uint32 --> uint32 */ - -/* XXX According to Apple specs, bits 1 & 2 of the argument ought to be */ -/* consulted before rotated / stretched info is returned */ - - static void Ins_GETINFO( INS_ARG ) - { - Long K; - - - K = 0; - - /* We return then Windows 3.1 version number */ - /* for the font scaler */ - if ( (args[0] & 1) != 0 ) - K = 3; - - /* Has the glyph been rotated ? */ - if ( CUR.metrics.rotated ) - K |= 0x80; - - /* Has the glyph been stretched ? */ - if ( CUR.metrics.stretched ) - K |= 0x100; - - args[0] = K; - } - - - static void Ins_UNKNOWN( INS_ARG ) - { - /* look up the current instruction in our table */ - PDefRecord def, limit; - - def = CUR.IDefs; - limit = def + CUR.numIDefs; - for ( ; def < limit; def++ ) - { - if ( def->Opc == CUR.opcode && def->Active ) - { - PCallRecord pCrec; - - /* implement instruction as a function call */ - - /* check 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; - } - } - - 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_$28 */ 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_$7B */ Ins_UNKNOWN, - /* RUTG */ Ins_RUTG, - /* RDTG */ Ins_RDTG, - /* SANGW */ Ins_SANGW, - /* AA */ Ins_AA, - - /* FlipPT */ Ins_FLIPPT, - /* FlipRgON */ Ins_FLIPRGON, - /* FlipRgOFF */ Ins_FLIPRGOFF, - /* INS_$83 */ Ins_UNKNOWN, - /* INS_$84 */ 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_$8F */ Ins_UNKNOWN, - - /* INS_$90 */ Ins_UNKNOWN, - /* INS_$91 */ Ins_UNKNOWN, - /* INS_$92 */ Ins_UNKNOWN, - /* INS_$93 */ Ins_UNKNOWN, - /* INS_$94 */ Ins_UNKNOWN, - /* INS_$95 */ Ins_UNKNOWN, - /* INS_$96 */ Ins_UNKNOWN, - /* INS_$97 */ Ins_UNKNOWN, - /* INS_$98 */ Ins_UNKNOWN, - /* INS_$99 */ Ins_UNKNOWN, - /* INS_$9A */ Ins_UNKNOWN, - /* INS_$9B */ Ins_UNKNOWN, - /* INS_$9C */ Ins_UNKNOWN, - /* INS_$9D */ Ins_UNKNOWN, - /* INS_$9E */ Ins_UNKNOWN, - /* INS_$9F */ Ins_UNKNOWN, - - /* INS_$A0 */ Ins_UNKNOWN, - /* INS_$A1 */ Ins_UNKNOWN, - /* INS_$A2 */ Ins_UNKNOWN, - /* INS_$A3 */ Ins_UNKNOWN, - /* INS_$A4 */ Ins_UNKNOWN, - /* INS_$A5 */ Ins_UNKNOWN, - /* INS_$A6 */ Ins_UNKNOWN, - /* INS_$A7 */ Ins_UNKNOWN, - /* INS_$A8 */ Ins_UNKNOWN, - /* INS_$A9 */ Ins_UNKNOWN, - /* INS_$AA */ Ins_UNKNOWN, - /* INS_$AB */ Ins_UNKNOWN, - /* INS_$AC */ Ins_UNKNOWN, - /* INS_$AD */ Ins_UNKNOWN, - /* INS_$AE */ Ins_UNKNOWN, - /* INS_$AF */ 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 - - -/****************************************************************/ -/* */ -/* 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 whith TRUE, test IP < CodeSize to know wether it */ -/* comes from a 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 specs' order. */ -/* */ -/****************************************************************/ - - LOCAL_FUNC -#ifndef DEBUG_INTERPRETER - TT_Error RunIns( PExecution_Context exc ) -#else - TT_Error RunIns2( PExecution_Context exc ) -#endif - { - UShort A; - PDefRecord WITH; - PCallRecord WITH1; - - Long ins_counter = 0; /* executed instructions counter */ - -#ifdef TT_CONFIG_OPTION_STATIC_INTERPRETER - cur = *exc; -#endif - - /* set CVT functions */ - CUR.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( EXEC_ARGS (Byte)exc->GS.round_state ); - - do - { - if ( CALC_Length() != SUCCESS ) - { - CUR.error = TT_Err_Code_Overflow; - goto LErrorLabel_; - } - - /* 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 - { - PStorage args = CUR.stack + CUR.args; - 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 */ - { - Short AA, BB; - - - AA = (Short)(opcode & 1) << 14; - BB = AA ^ (Short)0x4000; - - if ( opcode < 4 ) - { - CUR.GS.projVector.x = AA; - CUR.GS.projVector.y = BB; - - CUR.GS.dualVector.x = AA; - CUR.GS.dualVector.y = BB; - } - - if ( (opcode & 2) == 0 ) - { - CUR.GS.freeVector.x = AA; - CUR.GS.freeVector.y = BB; - } - - 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_ARGS 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_ARGS args ); - break; - - case 0x14: /* SZP1 */ - Ins_SZP1( EXEC_ARGS args ); - break; - - case 0x15: /* SZP2 */ - Ins_SZP2( EXEC_ARGS args ); - break; - - case 0x16: /* SZPS */ - Ins_SZPS( EXEC_ARGS 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_ARGS 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_ARGS args ); - break; - - case 0x27: /* ALIGNPTS */ - Ins_ALIGNPTS( EXEC_ARGS args ); - break; - - case 0x28: /* ???? */ - Ins_UNKNOWN( EXEC_ARGS args ); - break; - - case 0x29: /* UTP */ - Ins_UTP( EXEC_ARGS args ); - break; - - case 0x2A: /* LOOPCALL */ - Ins_LOOPCALL( EXEC_ARGS args ); - break; - - case 0x2B: /* CALL */ - Ins_CALL( EXEC_ARGS args ); - break; - - case 0x2C: /* FDEF */ - Ins_FDEF( EXEC_ARGS args ); - break; - - case 0x2D: /* ENDF */ - Ins_ENDF( EXEC_ARGS args ); - break; - - case 0x2E: /* MDAP */ - case 0x2F: /* MDAP */ - Ins_MDAP( EXEC_ARGS args ); - break; - - - case 0x30: /* IUP */ - case 0x31: /* IUP */ - Ins_IUP( EXEC_ARGS args ); - break; - - case 0x32: /* SHP */ - case 0x33: /* SHP */ - Ins_SHP( EXEC_ARGS args ); - break; - - case 0x34: /* SHC */ - case 0x35: /* SHC */ - Ins_SHC( EXEC_ARGS args ); - break; - - case 0x36: /* SHZ */ - case 0x37: /* SHZ */ - Ins_SHZ( EXEC_ARGS args ); - break; - - case 0x38: /* SHPIX */ - Ins_SHPIX( EXEC_ARGS args ); - break; - - case 0x39: /* IP */ - Ins_IP( EXEC_ARGS args ); - break; - - case 0x3A: /* MSIRP */ - case 0x3B: /* MSIRP */ - Ins_MSIRP( EXEC_ARGS args ); - break; - - case 0x3C: /* AlignRP */ - Ins_ALIGNRP( EXEC_ARGS args ); - break; - - case 0x3D: /* RTDG */ - DO_RTDG - break; - - case 0x3E: /* MIAP */ - case 0x3F: /* MIAP */ - Ins_MIAP( EXEC_ARGS args ); - break; - - case 0x40: /* NPUSHB */ - Ins_NPUSHB( EXEC_ARGS args ); - break; - - case 0x41: /* NPUSHW */ - Ins_NPUSHW( EXEC_ARGS 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_ARGS args ); - break; - - case 0x48: /* SCFS */ - Ins_SCFS( EXEC_ARGS args ); - break; - - case 0x49: /* MD */ - case 0x4A: /* MD */ - Ins_MD( EXEC_ARGS 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_ARGS 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_ARGS 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_ARGS args ); - break; - - case 0x73: /* DELTAC0 */ - case 0x74: /* DELTAC1 */ - case 0x75: /* DELTAC2 */ - Ins_DELTAC( EXEC_ARGS 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_ARGS 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_ARGS args ); - break; - - case 0x81: /* FLIPRGON */ - Ins_FLIPRGON( EXEC_ARGS args ); - break; - - case 0x82: /* FLIPRGOFF */ - Ins_FLIPRGOFF( EXEC_ARGS args ); - break; - - case 0x83: /* UNKNOWN */ - case 0x84: /* UNKNOWN */ - Ins_UNKNOWN( EXEC_ARGS args ); - break; - - case 0x85: /* SCANCTRL */ - Ins_SCANCTRL( EXEC_ARGS args ); - break; - - case 0x86: /* SDPVTL */ - case 0x87: /* SDPVTL */ - Ins_SDPVTL( EXEC_ARGS args ); - break; - - case 0x88: /* GETINFO */ - Ins_GETINFO( EXEC_ARGS args ); - break; - - case 0x89: /* IDEF */ - Ins_IDEF( EXEC_ARGS args ); - break; - - case 0x8A: /* ROLL */ - Ins_ROLL( EXEC_ARGS args ); - break; - - case 0x8B: /* MAX */ - DO_MAX - break; - - case 0x8C: /* MIN */ - DO_MIN - break; - - case 0x8D: /* SCANTYPE */ - Ins_SCANTYPE( EXEC_ARGS args ); - break; - - case 0x8E: /* INSTCTRL */ - Ins_INSTCTRL( EXEC_ARGS args ); - break; - - case 0x8F: - Ins_UNKNOWN( EXEC_ARGS args ); - break; - - default: - if ( opcode >= 0xE0 ) - Ins_MIRP( EXEC_ARGS args ); - else if ( opcode >= 0xC0 ) - Ins_MDRP( EXEC_ARGS args ); - else if ( opcode >= 0xB8 ) - Ins_PUSHW( EXEC_ARGS args ); - else if ( opcode >= 0xB0 ) - Ins_PUSHB( EXEC_ARGS args ); - else - Ins_UNKNOWN( EXEC_ARGS args ); - } - - } -#else - Instruct_Dispatch[CUR.opcode]( EXEC_ARGS &CUR.stack[CUR.args] ); -#endif - if ( CUR.error != TT_Err_Ok ) - { - switch ( (Int)(CUR.error) ) - { - case TT_Err_Invalid_Opcode: /* looking for redefined instructions */ - A = 0; - - while ( A < CUR.numIDefs ) - { - WITH = &CUR.IDefs[A]; - - if ( WITH->Active && CUR.opcode == WITH->Opc ) - { - if ( CUR.callTop >= CUR.callSize ) - { - CUR.error = TT_Err_Invalid_Reference; - goto LErrorLabel_; - } - - WITH1 = &CUR.callStack[CUR.callTop]; - - WITH1->Caller_Range = CUR.curRange; - WITH1->Caller_IP = CUR.IP + 1; - WITH1->Cur_Count = 1; - WITH1->Cur_Restart = WITH->Start; - - if ( INS_Goto_CodeRange( WITH->Range, WITH->Start ) == FAILURE ) - goto LErrorLabel_; - - goto LSuiteLabel_; - } - else - { - A++; - continue; - } - } - - CUR.error = TT_Err_Invalid_Opcode; - goto LErrorLabel_; -/* break; Unreachable code warning suppress. Leave in case a later - change to remind the editor to consider break; */ - - default: - goto LErrorLabel_; -/* break; */ - } - } - - 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 ) - { - CUR.error = TT_Err_Execution_Too_Long; - goto LErrorLabel_; - } - - 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_: - CUR.error = TT_Err_Ok; - - LErrorLabel_: - -#ifdef TT_CONFIG_OPTION_STATIC_INTERPRETER - *exc = cur; -#endif - - return CUR.error; - - - } - - -#ifdef DEBUG_INTERPRETER - - /* This function must be declared by the debugger front end */ - /* in order to specify which code range to debug. */ - - int debug_coderange = TT_CodeRange_Glyph; - - - LOCAL_FUNC - TT_Error RunIns( PExecution_Context exc ) - { - Int A, diff; - ULong next_IP; - Char ch, oldch; - char *temp; - int key; - - TT_Error error = 0; - - TGlyph_Zone save; - TGlyph_Zone pts; - -#define TT_Round_Off 5 -#define TT_Round_To_Half_Grid 0 -#define TT_Round_To_Grid 1 -#define TT_Round_To_Double_Grid 2 -#define TT_Round_Up_To_Grid 4 -#define TT_Round_Down_To_Grid 3 -#define TT_Round_Super 6 -#define TT_Round_Super_45 7 - - const String* round_str[8] = - { - "to half-grid", - "to grid", - "to double grid", - "down to grid", - "up to grid", - "off", - "super", - "super 45" - }; - - /* Check that we're running the code range that is effectively */ - /* asked by the debugger front end. */ - if ( exc->curRange != debug_coderange ) - return RunIns2( exc ); - - pts = exc->pts; - - save.n_points = pts.n_points; - save.n_contours = pts.n_contours; - - MEM_Alloc( save.org, sizeof ( TT_Vector ) * save.n_points ); - MEM_Alloc( save.cur, sizeof ( TT_Vector ) * save.n_points ); - MEM_Alloc( save.touch, sizeof ( Byte ) * save.n_points ); - - exc->instruction_trap = 1; - - oldch = '\0'; - - do - { - if ( exc->IP < exc->codeSize ) - { -#ifdef TT_CONFIG_OPTION_STATIC_INTERPRETER - cur = *exc; -#endif - CALC_Length(); - - exc->args = exc->top - (Pop_Push_Count[exc->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. */ - - /* Print the current line. We use a 80-columns console with the */ - /* following formatting: */ - /* */ - /* [loc]:[addr] [opcode] [disassemby] [a][b]|[c][d] */ - /* */ - - { - char temp[80]; - int n, col, pop; - int args = CUR.args; - - - sprintf( temp, "%78c\n", ' ' ); - - /* first letter of location */ - switch ( CUR.curRange ) - { - case TT_CodeRange_Glyph: - temp[0] = 'g'; - break; - case TT_CodeRange_Cvt: - temp[0] = 'c'; - break; - default: - temp[0] = 'f'; - } - - /* current IP */ - sprintf( temp+1, "%04lx: %02x %-36.36s", - CUR.IP, - CUR.opcode, - Cur_U_Line(&CUR) ); - - strncpy( temp+46, " (", 2 ); - - args = CUR.top - 1; - pop = Pop_Push_Count[CUR.opcode] >> 4; - col = 48; - for ( n = 6; n > 0; n-- ) - { - if ( pop == 0 ) - temp[col-1] = (temp[col-1] == '(' ? ' ' : ')' ); - - if ( args < CUR.top && args >= 0 ) - sprintf( temp+col, "%04lx", CUR.stack[args] ); - else - sprintf( temp+col, " " ); - - temp[col+4] = ' '; - col += 5; - pop--; - args--; - } - temp[78] = '\n'; - temp[79] = '\0'; - PTRACE0(( temp )); - } - - /* First, check for empty stack and overflow */ - if ( CUR.args < 0 ) - { - PTRACE0(( "ERROR : Too few arguments\n" )); - exc->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 'case' */ - - if ( CUR.new_top > CUR.stackSize ) - { - PTRACE0(( "ERROR : Stack overflow\n" )); - exc->error = TT_Err_Stack_Overflow; - goto LErrorLabel_; - } - } - else - PTRACE0(( "End of program reached.\n" )); - - key = 0; - do - { - /* read keyboard */ - - ch = getch(); - - switch ( ch ) - { - /* Help - show keybindings */ - case '?': - PTRACE0(( "FDebug Help\n\n" )); - PTRACE0(( "? Show this page\n" )); - PTRACE0(( "q Quit debugger\n" )); - PTRACE0(( "n Skip to next instruction\n" )); - PTRACE0(( "s Step into\n" )); - PTRACE0(( "v Show vector info\n" )); - PTRACE0(( "g Show graphics state\n" )); - PTRACE0(( "p Show points zone\n\n" )); - break; - - /* Show vectors */ - case 'v': - PTRACE0(( "freedom (%04hx,%04hx)\n", exc->GS.freeVector.x, - exc->GS.freeVector.y )); - PTRACE0(( "projection (%04hx,%04hx)\n", exc->GS.projVector.x, - exc->GS.projVector.y )); - PTRACE0(( "dual (%04hx,%04hx)\n\n", exc->GS.dualVector.x, - exc->GS.dualVector.y )); - break; - - /* Show graphics state */ - case 'g': - PTRACE0(( "rounding %s\n", round_str[exc->GS.round_state] )); - PTRACE0(( "min dist %04lx\n", exc->GS.minimum_distance )); - PTRACE0(( "cvt_cutin %04lx\n", exc->GS.control_value_cutin )); - break; - - /* Show points table */ - case 'p': - for ( A = 0; A < exc->pts.n_points; A++ ) - { - PTRACE0(( "%02hx ", A )); - PTRACE0(( "%08lx,%08lx - ", pts.org[A].x, pts.org[A].y )); - PTRACE0(( "%08lx,%08lx\n", pts.cur[A].x, pts.cur[A].y )); - } - PTRACE0(( "\n" )); - break; - - default: - key = 1; - } - } while ( !key ); - - MEM_Copy( save.org, pts.org, pts.n_points * sizeof ( TT_Vector ) ); - MEM_Copy( save.cur, pts.cur, pts.n_points * sizeof ( TT_Vector ) ); - MEM_Copy( save.touch, pts.touch, pts.n_points ); - - /* a return indicate the last command */ - if (ch == '\r') - ch = oldch; - - switch ( ch ) - { - /* Quit debugger */ - case 'q': - goto LErrorLabel_; - - /* Step over */ - case 'n': - if ( exc->IP < exc->codeSize ) - { - /* `step over' is equivalent to `step into' except if */ - /* the current opcode is a CALL or LOOPCALL */ - if ( CUR.opcode != 0x2a && CUR.opcode != 0x2b ) - goto Step_into; - - /* otherwise, loop execution until we reach the next opcode */ - next_IP = CUR.IP + CUR.length; - while ( exc->IP != next_IP ) - { - if ( ( error = RunIns2( exc ) ) ) - goto LErrorLabel_; - } - } - oldch = ch; - break; - - /* Step into */ - case 's': - if ( exc->IP < exc->codeSize ) - - Step_into: - if ( ( error = RunIns2( exc ) ) ) - goto LErrorLabel_; - oldch = ch; - break; - - default: - PTRACE0(( "unknown command. Press ? for help\n" )); - oldch = '\0'; - } - - for ( A = 0; A < pts.n_points; A++ ) - { - diff = 0; - if ( save.org[A].x != pts.org[A].x ) diff |= 1; - if ( save.org[A].y != pts.org[A].y ) diff |= 2; - if ( save.cur[A].x != pts.cur[A].x ) diff |= 4; - if ( save.cur[A].y != pts.cur[A].y ) diff |= 8; - if ( save.touch[A] != pts.touch[A] ) diff |= 16; - - if ( diff ) - { - PTRACE0(( "%02hx ", A )); - - if ( diff & 16 ) temp = "(%01hx)"; else temp = " %01hx "; - PTRACE0(( temp, save.touch[A] & 7 )); - - if ( diff & 1 ) temp = "(%08lx)"; else temp = " %08lx "; - PTRACE0(( temp, save.org[A].x )); - - if ( diff & 2 ) temp = "(%08lx)"; else temp = " %08lx "; - PTRACE0(( temp, save.org[A].y )); - - if ( diff & 4 ) temp = "(%08lx)"; else temp = " %08lx "; - PTRACE0(( temp, save.cur[A].x )); - - if ( diff & 8 ) temp = "(%08lx)"; else temp = " %08lx "; - PTRACE0(( temp, save.cur[A].y )); - - PTRACE0(( "\n" )); - - PTRACE0(( "%02hx ", A )); - - if ( diff & 16 ) temp = "[%01hx]"; else temp = " %01hx "; - PTRACE0(( temp, pts.touch[A] & 7 )); - - if ( diff & 1 ) temp = "[%08lx]"; else temp = " %08lx "; - PTRACE0(( temp, pts.org[A].x )); - - if ( diff & 2 ) temp = "[%08lx]"; else temp = " %08lx "; - PTRACE0(( temp, pts.org[A].y )); - - if ( diff & 4 ) temp = "[%08lx]"; else temp = " %08lx "; - PTRACE0(( temp, pts.cur[A].x )); - - if ( diff & 8 ) temp = "[%08lx]"; else temp = " %08lx "; - PTRACE0(( temp, pts.cur[A].y )); - - PTRACE0(( "\n\n" )); - } - } - } while ( TRUE ); - - LErrorLabel_: - - return error; - } - -#endif /* DEBUG_INTERPRETER */ - - -#endif /* TT_CONFIG_OPTION_NO_INTERPRETER */ - -/* END */ |