summaryrefslogtreecommitdiff
path: root/Build/source/libs/freetype/freetype-1.5/lib/ttinterp.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/freetype/freetype-1.5/lib/ttinterp.c')
-rw-r--r--Build/source/libs/freetype/freetype-1.5/lib/ttinterp.c6681
1 files changed, 0 insertions, 6681 deletions
diff --git a/Build/source/libs/freetype/freetype-1.5/lib/ttinterp.c b/Build/source/libs/freetype/freetype-1.5/lib/ttinterp.c
deleted file mode 100644
index 3c991a5e130..00000000000
--- a/Build/source/libs/freetype/freetype-1.5/lib/ttinterp.c
+++ /dev/null
@@ -1,6681 +0,0 @@
-/*******************************************************************
- *
- * ttinterp.c 3.1
- *
- * TrueType bytecode intepreter.
- *
- * Copyright 1996-2002 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 issue.
- *
- ******************************************************************/
-
-#include "freetype.h"
-#include "tttypes.h"
-#include "ttdebug.h"
-#include "ttcalc.h"
-#include "ttmemory.h"
-#include "ttinterp.h"
-
-
-#ifndef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
-
- FT_INTERNAL_FUNC( TT_Error )
- RunIns( EXEC_OP )
- {
- /* do nothing - always successful */
-
-#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER
- /* make picky compilers happy */
- (void)exc;
-#endif
- return TT_Err_Ok;
- }
-
-#else /* ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
-
-
-#ifdef DEBUG_INTERPRETER
- /* The debugger uses a special version of the TrueType */
- /* interpreter, with some hooks and a simple user interface. */
- /* Here we declare the needed additions. */
-#include "ttdebug.h"
-
-/* Define the `getch()' function, used for get user inputs. */
-
-#ifndef UNIX
-
-/* Outside Unix, we rely on getch() being defined by <conio.h>. */
-/* This has become a standard, coming from MS-DOS libraries, and */
-/* has been ported to OS/2, Win32, and perhaps others. */
-/* If it does not work for you, investigate the code for Unix */
-/* (here, and in test/fdebug.c). */
-#include <conio.h>
-#if defined( _M_I86 )
- /* a recent compiler, which do not pollute name spaces... */
-#define getch(x) _getch(x)
-#endif /* modern compiler */
-
-#else /* !defined( UNIX ) */
-
-/* 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. */
-#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 386's or even 486's). */
-/* */
-/* 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 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. */
-/* */
-/* TT_CONFIG_OPTION_STATIC_INTERPRETER (in ft_conf.h) toggles */
-/* the use of the static interpreter. */
-/* */
-
-#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER /* indirect implementation */
-
-#define CUR (*exc)
-
-#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 byte addresses). */
-
-#endif /* !TT_CONFIG_OPTION_STATIC_INTERPRETER */
-
-
-/* A bunch of macros to save typing (and ease reading). */
-
-#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 ) ( (TT_UInt)(x) >= (TT_UInt)(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 : Called through the GET_ShortIns() macro.
- *
- *****************************************************************/
-
- 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 )
- {
- /* 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 )
- {
- CUR.error = TT_Err_Too_Many_FDefs;
- return;
- }
-
- n = (Int)args[0];
- if ( n < 0 || n != (int)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 )
- {
- /* We could introduce a new error message (the same as for FDEF), */
- /* but we're too close from the release to change all the 'po' */
- /* files again... */
- 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. */
-/* */
-/****************************************************************/
-
- FT_INTERNAL_FUNC( TT_Error )
-#ifndef DEBUG_INTERPRETER
- RunIns( PExecution_Context exc )
-#else
- 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)( CUR.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;
-
- FT_INTERNAL_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 ( CUR.curRange != debug_coderange )
- return RunIns2( &CUR );
-
- pts = CUR.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 );
-
- CUR.instruction_trap = 1;
-
- oldch = '\0';
-
- do
- {
- if ( CUR.IP < CUR.codeSize )
- {
-#ifdef TT_CONFIG_OPTION_STATIC_INTERPRETER
- cur = *exc;
-#endif
- CALC_Length();
-
- 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. */
-
- /* 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" ));
- 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 'case' */
-
- if ( CUR.new_top > CUR.stackSize )
- {
- PTRACE0(( "ERROR : Stack overflow\n" ));
- CUR.error = TT_Err_Stack_Overflow;
- goto LErrorLabel_;
- }
-
-#ifdef TT_CONFIG_OPTION_STATIC_INTERPRETER
- *exc = cur;
-#endif
- }
- 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", CUR.GS.freeVector.x,
- CUR.GS.freeVector.y ));
- PTRACE0(( "projection (%04hx,%04hx)\n", CUR.GS.projVector.x,
- CUR.GS.projVector.y ));
- PTRACE0(( "dual (%04hx,%04hx)\n\n", CUR.GS.dualVector.x,
- CUR.GS.dualVector.y ));
- break;
-
- /* Show graphics state */
- case 'g':
- PTRACE0(( "rounding %s\n", round_str[CUR.GS.round_state] ));
- PTRACE0(( "min dist %04lx\n", CUR.GS.minimum_distance ));
- PTRACE0(( "cvt_cutin %04lx\n", CUR.GS.control_value_cutin ));
- break;
-
- /* Show points table */
- case 'p':
- for ( A = 0; A < CUR.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 ( CUR.IP < CUR.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 ( CUR.IP != next_IP )
- {
- if ( ( error = RunIns2( &CUR ) ) != 0 )
- goto LErrorLabel_;
- }
- }
- oldch = ch;
- break;
-
- /* Step into */
- case 's':
- if ( CUR.IP < CUR.codeSize )
-
- Step_into:
- if ( ( error = RunIns2( &CUR ) ) != 0 )
- 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_BYTECODE_INTERPRETER */
-
-/* END */