1999-12-17 00:11:37 +01:00
|
|
|
/***************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* ttinterp.c */
|
|
|
|
/* */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* TrueType bytecode interpreter (body). */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
2001-06-28 19:49:10 +02:00
|
|
|
/* Copyright 1996-2001 by */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
|
|
|
|
/* */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* This file is part of the FreeType project, and may only be used, */
|
|
|
|
/* modified, and distributed under the terms of the FreeType project */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* 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. */
|
|
|
|
/* */
|
|
|
|
/***************************************************************************/
|
|
|
|
|
2000-12-08 17:17:16 +01:00
|
|
|
|
2000-12-08 03:42:29 +01:00
|
|
|
#include <ft2build.h>
|
|
|
|
#include FT_INTERNAL_DEBUG_H
|
|
|
|
#include FT_INTERNAL_CALC_H
|
2001-06-14 14:34:00 +02:00
|
|
|
#include FT_TRIGONOMETRY_H
|
2000-12-08 03:42:29 +01:00
|
|
|
#include FT_SYSTEM_H
|
Complete redesign of error codes. Please check ftmoderr.h for more
details.
* include/freetype/internal/cfferrs.h,
include/freetype/internal/tterrors.h,
include/freetype/internal/t1errors.h: Removed. Replaced with files
local to the module. All extra error codes have been moved to
`fterrors.h'.
* src/sfnt/ttpost.h: Move error codes to `fterrors.h'.
* src/autohint/aherrors.h, src/cache/ftcerror.h, src/cff/cfferrs.h,
src/cid/ciderrs.h, src/pcf/pcferror.h, src/psaux/psauxerr.h,
src/psnames/psnamerr.h, src/raster/rasterrs.h, src/sfnt/sferrors.h,
src/smooth/ftsmerrs.h, src/truetype/tterrors.h,
src/type1/t1errors.h, src/winfonts/fnterrs.h: New files defining the
error names for the module it belongs to.
* include/freetype/ftmoderr.h: New file, defining the module error
offsets. Its structure is similar to `fterrors.h'.
* include/freetype/fterrors.h (FT_NOERRORDEF): New macro.
(FT_ERRORDEF): Redefined to use module error offsets.
All internal error codes are now public; unused error codes have
been removed, some are new.
* include/freetype/config/ftheader.h (FT_MODULE_ERRORS_H): New
macro.
* include/freetype/config/ftoption.h
(FT_CONFIG_OPTION_USE_MODULE_ERRORS): New macro.
All other source files have been updated to use the new error codes;
some already existing (internal) error codes local to a module have
been renamed to give them the same name as in the base module.
All make files have been updated to include the local error files.
* src/cid/cidtokens.h: Replaced with...
* src/cid/cidtoken.h: This file for 8+3 consistency.
* src/raster/ftraster.c: Use macros for header file names.
2001-06-06 19:30:41 +02:00
|
|
|
|
2001-03-20 12:14:24 +01:00
|
|
|
#include "ttinterp.h"
|
Complete redesign of error codes. Please check ftmoderr.h for more
details.
* include/freetype/internal/cfferrs.h,
include/freetype/internal/tterrors.h,
include/freetype/internal/t1errors.h: Removed. Replaced with files
local to the module. All extra error codes have been moved to
`fterrors.h'.
* src/sfnt/ttpost.h: Move error codes to `fterrors.h'.
* src/autohint/aherrors.h, src/cache/ftcerror.h, src/cff/cfferrs.h,
src/cid/ciderrs.h, src/pcf/pcferror.h, src/psaux/psauxerr.h,
src/psnames/psnamerr.h, src/raster/rasterrs.h, src/sfnt/sferrors.h,
src/smooth/ftsmerrs.h, src/truetype/tterrors.h,
src/type1/t1errors.h, src/winfonts/fnterrs.h: New files defining the
error names for the module it belongs to.
* include/freetype/ftmoderr.h: New file, defining the module error
offsets. Its structure is similar to `fterrors.h'.
* include/freetype/fterrors.h (FT_NOERRORDEF): New macro.
(FT_ERRORDEF): Redefined to use module error offsets.
All internal error codes are now public; unused error codes have
been removed, some are new.
* include/freetype/config/ftheader.h (FT_MODULE_ERRORS_H): New
macro.
* include/freetype/config/ftoption.h
(FT_CONFIG_OPTION_USE_MODULE_ERRORS): New macro.
All other source files have been updated to use the new error codes;
some already existing (internal) error codes local to a module have
been renamed to give them the same name as in the base module.
All make files have been updated to include the local error files.
* src/cid/cidtokens.h: Replaced with...
* src/cid/cidtoken.h: This file for 8+3 consistency.
* src/raster/ftraster.c: Use macros for header file names.
2001-06-06 19:30:41 +02:00
|
|
|
|
|
|
|
#include "tterrors.h"
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
2000-02-10 19:08:17 +01:00
|
|
|
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
|
|
|
|
|
|
|
|
|
2000-12-08 17:17:16 +01:00
|
|
|
#define TT_MULFIX FT_MulFix
|
|
|
|
#define TT_MULDIV FT_MulDiv
|
|
|
|
#define TT_INT64 FT_Int64
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
|
|
|
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
|
|
|
/* messages during execution. */
|
|
|
|
/* */
|
1999-12-17 00:11:37 +01:00
|
|
|
#undef FT_COMPONENT
|
2000-06-12 21:36:41 +02:00
|
|
|
#define FT_COMPONENT trace_ttinterp
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-01-27 14:56:02 +01:00
|
|
|
#undef NO_APPLE_PATENT
|
2000-06-12 21:36:41 +02:00
|
|
|
#define APPLE_THRESHOLD 0x4000000L
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* In order to detect infinite loops in the code, we set up a counter */
|
|
|
|
/* within the run loop. A single stroke of interpretation is now */
|
|
|
|
/* limitet to a maximal number of opcodes defined below. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
2000-06-12 21:36:41 +02:00
|
|
|
#define MAX_RUNNABLE_OPCODES 1000000L
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* There are two kinds of implementations: */
|
|
|
|
/* */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* a. static implementation */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* 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. */
|
|
|
|
/* */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* b. indirect implementation */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* The current execution context is passed to _each_ function as its */
|
|
|
|
/* first argument, and each field is thus accessed indirectly. */
|
|
|
|
/* */
|
|
|
|
/* This version is fully re-entrant. */
|
|
|
|
/* */
|
|
|
|
/* The idea is that an indirect implementation may be slower to execute */
|
|
|
|
/* on low-end processors that are used in some systems (like 386s or */
|
|
|
|
/* even 486s). */
|
|
|
|
/* */
|
|
|
|
/* As a consequence, the indirect implementation is now the default, as */
|
|
|
|
/* its performance costs can be considered negligible in our context. */
|
|
|
|
/* Note, however, that we kept the same source with macros because: */
|
|
|
|
/* */
|
|
|
|
/* - The code is kept very close in design to the Pascal code used for */
|
|
|
|
/* development. */
|
|
|
|
/* */
|
|
|
|
/* - It's much more readable that way! */
|
|
|
|
/* */
|
|
|
|
/* - It's still open to experimentation and tuning. */
|
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER /* indirect implementation */
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#define CUR (*exc) /* see ttobjs.h */
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#else /* static implementation */
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#define CUR cur
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
static
|
|
|
|
TT_ExecContextRec cur; /* static exec. context variable */
|
|
|
|
|
|
|
|
/* apparently, we have a _lot_ of direct indexing when accessing */
|
|
|
|
/* the static `cur', which makes the code bigger (due to all the */
|
|
|
|
/* four bytes addresses). */
|
|
|
|
|
|
|
|
#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* The instruction argument stack. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
2000-06-16 21:34:52 +02:00
|
|
|
#define INS_ARG EXEC_OP_ FT_Long* args /* see ttobjs.h for EXEC_OP_ */
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* This macro is used whenever `exec' is unused in a function, to avoid */
|
|
|
|
/* stupid warnings from pedantic compilers. */
|
|
|
|
/* */
|
2000-07-04 20:12:13 +02:00
|
|
|
#define FT_UNUSED_EXEC FT_UNUSED( CUR )
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* This macro is used whenever `args' is unused in a function, to avoid */
|
|
|
|
/* stupid warnings from pedantic compilers. */
|
|
|
|
/* */
|
2000-07-04 20:12:13 +02:00
|
|
|
#define FT_UNUSED_ARG FT_UNUSED_EXEC; FT_UNUSED( args )
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* increase readabilty of the code. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
#define SKIP_Code() \
|
|
|
|
SkipCode( EXEC_ARG )
|
|
|
|
|
|
|
|
#define GET_ShortIns() \
|
|
|
|
GetShortIns( EXEC_ARG )
|
|
|
|
|
|
|
|
#define NORMalize( x, y, v ) \
|
|
|
|
Normalize( EXEC_ARG_ x, y, v )
|
|
|
|
|
|
|
|
#define SET_SuperRound( scale, flags ) \
|
|
|
|
SetSuperRound( EXEC_ARG_ scale, flags )
|
|
|
|
|
|
|
|
#define ROUND_None( d, c ) \
|
|
|
|
Round_None( EXEC_ARG_ d, c )
|
|
|
|
|
|
|
|
#define INS_Goto_CodeRange( range, ip ) \
|
|
|
|
Ins_Goto_CodeRange( EXEC_ARG_ range, ip )
|
|
|
|
|
|
|
|
#define CUR_Func_project( x, y ) \
|
|
|
|
CUR.func_project( EXEC_ARG_ x, y )
|
|
|
|
|
|
|
|
#define CUR_Func_move( z, p, d ) \
|
|
|
|
CUR.func_move( EXEC_ARG_ z, p, d )
|
|
|
|
|
|
|
|
#define CUR_Func_dualproj( x, y ) \
|
|
|
|
CUR.func_dualproj( EXEC_ARG_ x, y )
|
|
|
|
|
|
|
|
#define CUR_Func_freeProj( x, y ) \
|
|
|
|
CUR.func_freeProj( EXEC_ARG_ x, y )
|
|
|
|
|
|
|
|
#define CUR_Func_round( d, c ) \
|
|
|
|
CUR.func_round( EXEC_ARG_ d, c )
|
|
|
|
|
|
|
|
#define CUR_Func_read_cvt( index ) \
|
|
|
|
CUR.func_read_cvt( EXEC_ARG_ index )
|
|
|
|
|
|
|
|
#define CUR_Func_write_cvt( index, val ) \
|
|
|
|
CUR.func_write_cvt( EXEC_ARG_ index, val )
|
|
|
|
|
|
|
|
#define CUR_Func_move_cvt( index, val ) \
|
|
|
|
CUR.func_move_cvt( EXEC_ARG_ index, val )
|
|
|
|
|
|
|
|
#define CURRENT_Ratio() \
|
|
|
|
Current_Ratio( EXEC_ARG )
|
|
|
|
|
|
|
|
#define CURRENT_Ppem() \
|
|
|
|
Current_Ppem( EXEC_ARG )
|
|
|
|
|
|
|
|
#define CUR_Ppem() \
|
|
|
|
Cur_PPEM( EXEC_ARG )
|
|
|
|
|
|
|
|
#define INS_SxVTL( a, b, c, d ) \
|
|
|
|
Ins_SxVTL( EXEC_ARG_ a, b, c, d )
|
|
|
|
|
|
|
|
#define COMPUTE_Funcs() \
|
|
|
|
Compute_Funcs( EXEC_ARG )
|
|
|
|
|
|
|
|
#define COMPUTE_Round( a ) \
|
|
|
|
Compute_Round( EXEC_ARG_ a )
|
|
|
|
|
|
|
|
#define COMPUTE_Point_Displacement( a, b, c, d ) \
|
|
|
|
Compute_Point_Displacement( EXEC_ARG_ a, b, c, d )
|
|
|
|
|
|
|
|
#define MOVE_Zp2_Point( a, b, c, t ) \
|
|
|
|
Move_Zp2_Point( EXEC_ARG_ a, b, c, t )
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* Instruction dispatch function, as used by the interpreter. */
|
|
|
|
/* */
|
|
|
|
typedef void (*TInstruction_Function)( INS_ARG );
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* A simple bounds-checking macro. */
|
|
|
|
/* */
|
2000-06-16 21:34:52 +02:00
|
|
|
#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) )
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#undef SUCCESS
|
|
|
|
#define SUCCESS 0
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#undef FAILURE
|
|
|
|
#define FAILURE 1
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* CODERANGE FUNCTIONS */
|
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Goto_CodeRange */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Switches to a new code range (updates the code related elements in */
|
|
|
|
/* `exec', and `IP'). */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* range :: The new execution code range. */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* */
|
|
|
|
/* IP :: The new IP in the new code range. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* <InOut> */
|
|
|
|
/* exec :: The target execution context. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
2002-03-01 03:26:22 +01:00
|
|
|
FT_LOCAL_DEF( FT_Error )
|
2001-06-28 09:17:51 +02:00
|
|
|
TT_Goto_CodeRange( TT_ExecContext exec,
|
|
|
|
FT_Int range,
|
|
|
|
FT_Long IP )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
TT_CodeRange* coderange;
|
|
|
|
|
|
|
|
|
|
|
|
FT_Assert( range >= 1 && range <= 3 );
|
|
|
|
|
|
|
|
coderange = &exec->codeRangeTable[range - 1];
|
|
|
|
|
|
|
|
FT_Assert( coderange->base != NULL );
|
|
|
|
|
|
|
|
/* NOTE: Because the last instruction of a program may be a CALL */
|
|
|
|
/* which will return to the first byte *after* the code */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* range, we test for IP <= Size instead of IP < Size. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Assert( (FT_ULong)IP <= coderange->size );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
exec->code = coderange->base;
|
|
|
|
exec->codeSize = coderange->size;
|
|
|
|
exec->IP = IP;
|
|
|
|
exec->curRange = range;
|
|
|
|
|
|
|
|
return TT_Err_Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Set_CodeRange */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Sets a code range. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* range :: The code range index. */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* base :: The new code base. */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* length :: The range size in bytes. */
|
|
|
|
/* */
|
|
|
|
/* <InOut> */
|
|
|
|
/* exec :: The target execution context. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
2002-03-01 03:26:22 +01:00
|
|
|
FT_LOCAL_DEF( FT_Error )
|
2001-06-28 09:17:51 +02:00
|
|
|
TT_Set_CodeRange( TT_ExecContext exec,
|
|
|
|
FT_Int range,
|
|
|
|
void* base,
|
|
|
|
FT_Long length )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
FT_Assert( range >= 1 && range <= 3 );
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
|
1999-12-17 00:11:37 +01:00
|
|
|
exec->codeRangeTable[range - 1].size = length;
|
|
|
|
|
|
|
|
return TT_Err_Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Clear_CodeRange */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Clears a code range. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* range :: The code range index. */
|
|
|
|
/* */
|
|
|
|
/* <InOut> */
|
|
|
|
/* exec :: The target execution context. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* <Note> */
|
|
|
|
/* Does not set the Error variable. */
|
|
|
|
/* */
|
2002-03-01 03:26:22 +01:00
|
|
|
FT_LOCAL_DEF( FT_Error )
|
2001-06-28 09:17:51 +02:00
|
|
|
TT_Clear_CodeRange( TT_ExecContext exec,
|
|
|
|
FT_Int range )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
FT_Assert( range >= 1 && range <= 3 );
|
|
|
|
|
|
|
|
exec->codeRangeTable[range - 1].base = NULL;
|
|
|
|
exec->codeRangeTable[range - 1].size = 0;
|
|
|
|
|
|
|
|
return TT_Err_Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* EXECUTION CONTEXT ROUTINES */
|
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Destroy_Context */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Destroys a given context. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* exec :: A handle to the target execution context. */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* */
|
|
|
|
/* memory :: A handle to the parent memory object. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* <Note> */
|
|
|
|
/* Only the glyph loader and debugger should call this function. */
|
|
|
|
/* */
|
2002-03-01 03:26:22 +01:00
|
|
|
FT_LOCAL_DEF( FT_Error )
|
2001-06-28 09:17:51 +02:00
|
|
|
TT_Destroy_Context( TT_ExecContext exec,
|
|
|
|
FT_Memory memory )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
/* free composite load stack */
|
|
|
|
FREE( exec->loadStack );
|
|
|
|
exec->loadSize = 0;
|
|
|
|
|
|
|
|
/* points zone */
|
|
|
|
exec->maxPoints = 0;
|
|
|
|
exec->maxContours = 0;
|
|
|
|
|
|
|
|
/* free stack */
|
|
|
|
FREE( exec->stack );
|
|
|
|
exec->stackSize = 0;
|
|
|
|
|
|
|
|
/* free call stack */
|
|
|
|
FREE( exec->callStack );
|
|
|
|
exec->callSize = 0;
|
|
|
|
exec->callTop = 0;
|
|
|
|
|
|
|
|
/* free glyph code range */
|
|
|
|
FREE( exec->glyphIns );
|
|
|
|
exec->glyphSize = 0;
|
|
|
|
|
|
|
|
exec->size = NULL;
|
|
|
|
exec->face = NULL;
|
|
|
|
|
|
|
|
FREE( exec );
|
|
|
|
return TT_Err_Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Init_Context */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Initializes a context object. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* memory :: A handle to the parent memory object. */
|
|
|
|
/* */
|
|
|
|
/* face :: A handle to the source TrueType face object. */
|
|
|
|
/* */
|
|
|
|
/* <InOut> */
|
|
|
|
/* exec :: A handle to the target execution context. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_Error
|
|
|
|
Init_Context( TT_ExecContext exec,
|
|
|
|
TT_Face face,
|
|
|
|
FT_Memory memory )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-07-02 15:53:16 +02:00
|
|
|
FT_TRACE1(( "Init_Context: new object at 0x%08p, parent = 0x%08p\n",
|
2000-05-18 18:18:05 +02:00
|
|
|
exec, face ));
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
exec->memory = memory;
|
|
|
|
exec->callSize = 32;
|
|
|
|
|
|
|
|
if ( ALLOC_ARRAY( exec->callStack, exec->callSize, TT_CallRec ) )
|
|
|
|
goto Fail_Memory;
|
|
|
|
|
|
|
|
/* all values in the context are set to 0 already, but this is */
|
|
|
|
/* here as a remainder */
|
|
|
|
exec->maxPoints = 0;
|
|
|
|
exec->maxContours = 0;
|
|
|
|
|
|
|
|
exec->stackSize = 0;
|
|
|
|
exec->loadSize = 0;
|
|
|
|
exec->glyphSize = 0;
|
|
|
|
|
|
|
|
exec->stack = NULL;
|
|
|
|
exec->loadStack = NULL;
|
|
|
|
exec->glyphIns = NULL;
|
|
|
|
|
|
|
|
exec->face = face;
|
|
|
|
exec->size = NULL;
|
|
|
|
|
|
|
|
return TT_Err_Ok;
|
|
|
|
|
|
|
|
Fail_Memory:
|
2000-07-02 15:53:16 +02:00
|
|
|
FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n",
|
|
|
|
(FT_Long)exec ));
|
1999-12-17 00:11:37 +01:00
|
|
|
TT_Destroy_Context( exec, memory );
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Update_Max */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Checks the size of a buffer and reallocates it if necessary. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* memory :: A handle to the parent memory object. */
|
|
|
|
/* */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* multiplier :: The size in bytes of each element in the buffer. */
|
|
|
|
/* */
|
|
|
|
/* new_max :: The new capacity (size) of the buffer. */
|
|
|
|
/* */
|
|
|
|
/* <InOut> */
|
|
|
|
/* size :: The address of the buffer's current size expressed */
|
|
|
|
/* in elements. */
|
|
|
|
/* */
|
|
|
|
/* buff :: The address of the buffer base pointer. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_Error
|
|
|
|
Update_Max( FT_Memory memory,
|
|
|
|
FT_ULong* size,
|
|
|
|
FT_Long multiplier,
|
|
|
|
void** buff,
|
|
|
|
FT_ULong new_max )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
if ( *size < new_max )
|
|
|
|
{
|
|
|
|
FREE( *buff );
|
|
|
|
if ( ALLOC( *buff, new_max * multiplier ) )
|
|
|
|
return error;
|
|
|
|
*size = new_max;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TT_Err_Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Load_Context */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Prepare an execution context for glyph hinting. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* face :: A handle to the source face object. */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* size :: A handle to the source size object. */
|
|
|
|
/* */
|
|
|
|
/* <InOut> */
|
|
|
|
/* exec :: A handle to the target execution context. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* <Note> */
|
|
|
|
/* Only the glyph loader and debugger should call this function. */
|
|
|
|
/* */
|
2002-03-01 03:26:22 +01:00
|
|
|
FT_LOCAL_DEF( FT_Error )
|
2001-06-28 09:17:51 +02:00
|
|
|
TT_Load_Context( TT_ExecContext exec,
|
|
|
|
TT_Face face,
|
|
|
|
TT_Size size )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Int i;
|
|
|
|
FT_ULong tmp;
|
1999-12-17 00:11:37 +01:00
|
|
|
TT_MaxProfile* maxp;
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
exec->face = face;
|
|
|
|
maxp = &face->max_profile;
|
|
|
|
exec->size = size;
|
|
|
|
|
|
|
|
if ( size )
|
|
|
|
{
|
|
|
|
exec->numFDefs = size->num_function_defs;
|
|
|
|
exec->maxFDefs = size->max_function_defs;
|
|
|
|
exec->numIDefs = size->num_instruction_defs;
|
|
|
|
exec->maxIDefs = size->max_instruction_defs;
|
|
|
|
exec->FDefs = size->function_defs;
|
|
|
|
exec->IDefs = size->instruction_defs;
|
|
|
|
exec->tt_metrics = size->ttmetrics;
|
|
|
|
exec->metrics = size->root.metrics;
|
|
|
|
|
|
|
|
exec->maxFunc = size->max_func;
|
|
|
|
exec->maxIns = size->max_ins;
|
|
|
|
|
|
|
|
for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
|
|
|
|
exec->codeRangeTable[i] = size->codeRangeTable[i];
|
|
|
|
|
|
|
|
/* set graphics state */
|
|
|
|
exec->GS = size->GS;
|
|
|
|
|
|
|
|
exec->cvtSize = size->cvt_size;
|
|
|
|
exec->cvt = size->cvt;
|
|
|
|
|
|
|
|
exec->storeSize = size->storage_size;
|
|
|
|
exec->storage = size->storage;
|
|
|
|
|
|
|
|
exec->twilight = size->twilight;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = Update_Max( exec->memory,
|
|
|
|
&exec->loadSize,
|
|
|
|
sizeof ( TT_SubGlyphRec ),
|
|
|
|
(void**)&exec->loadStack,
|
|
|
|
exec->face->max_components + 1 );
|
|
|
|
if ( error )
|
|
|
|
return error;
|
|
|
|
|
|
|
|
/* XXX: We reserve a little more elements on the stack to deal safely */
|
|
|
|
/* with broken fonts like arialbs, courbs, timesbs, etc. */
|
|
|
|
tmp = exec->stackSize;
|
|
|
|
error = Update_Max( exec->memory,
|
|
|
|
&tmp,
|
2000-06-16 21:34:52 +02:00
|
|
|
sizeof ( FT_F26Dot6 ),
|
1999-12-17 00:11:37 +01:00
|
|
|
(void**)&exec->stack,
|
|
|
|
maxp->maxStackElements + 32 );
|
2000-06-16 21:34:52 +02:00
|
|
|
exec->stackSize = (FT_UInt)tmp;
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( error )
|
|
|
|
return error;
|
|
|
|
|
|
|
|
tmp = exec->glyphSize;
|
|
|
|
error = Update_Max( exec->memory,
|
|
|
|
&tmp,
|
2000-06-16 21:34:52 +02:00
|
|
|
sizeof ( FT_Byte ),
|
1999-12-17 00:11:37 +01:00
|
|
|
(void**)&exec->glyphIns,
|
|
|
|
maxp->maxSizeOfInstructions );
|
2000-06-16 21:34:52 +02:00
|
|
|
exec->glyphSize = (FT_UShort)tmp;
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( error )
|
|
|
|
return error;
|
|
|
|
|
|
|
|
exec->pts.n_points = 0;
|
|
|
|
exec->pts.n_contours = 0;
|
|
|
|
|
|
|
|
exec->instruction_trap = FALSE;
|
|
|
|
|
|
|
|
return TT_Err_Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Save_Context */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Saves the code ranges in a `size' object. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* exec :: A handle to the source execution context. */
|
|
|
|
/* */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* <InOut> */
|
|
|
|
/* size :: A handle to the target size object. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* <Note> */
|
|
|
|
/* Only the glyph loader and debugger should call this function. */
|
|
|
|
/* */
|
2002-03-01 03:26:22 +01:00
|
|
|
FT_LOCAL_DEF( FT_Error )
|
2001-06-28 09:17:51 +02:00
|
|
|
TT_Save_Context( TT_ExecContext exec,
|
|
|
|
TT_Size size )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Int i;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* XXXX: Will probably disappear soon with all the code range */
|
|
|
|
/* management, which is now rather obsolete. */
|
|
|
|
/* */
|
|
|
|
size->num_function_defs = exec->numFDefs;
|
|
|
|
size->num_instruction_defs = exec->numIDefs;
|
|
|
|
|
|
|
|
size->max_func = exec->maxFunc;
|
|
|
|
size->max_ins = exec->maxIns;
|
|
|
|
|
|
|
|
for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
|
|
|
|
size->codeRangeTable[i] = exec->codeRangeTable[i];
|
|
|
|
|
|
|
|
return TT_Err_Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Run_Context */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Executes one or more instructions in the execution context. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* debug :: A Boolean flag. If set, the function sets some internal */
|
|
|
|
/* variables and returns immediately, otherwise TT_RunIns() */
|
|
|
|
/* is called. */
|
|
|
|
/* */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* This is commented out currently. */
|
|
|
|
/* */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* <Input> */
|
|
|
|
/* exec :: A handle to the target execution context. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
- MAJOR INTERNAL REDESIGN:
A lot of internal modifications have been performed lately on the
source in order to provide the following enhancements:
- more generic module support:
The FT_Module type is now defined to represent a handle to a given
module. The file <freetype/ftmodule.h> contains the FT_Module_Class
definition, as well as the module-loading public API
The FT_Driver type is still defined, and still represents a pointer
to a font driver. Note that FT_Add_Driver is replaced by FT_Add_Module,
FT_Get_Driver by FT_Get_Module, etc..
- support for generic glyph image types:
The FT_Renderer type is a pointer to a module used to perform various
operations on glyph image.
Each renderer is capable of handling images in a single format
(e.g. ft_glyph_format_outline). Its functions are used to:
- transform an glyph image
- render a glyph image into a bitmap
- return the control box (dimensions) of a given glyph image
The scan converters "ftraster.c" and "ftgrays.c" have been moved
to the new directory "src/renderer", and are used to provide two
default renderer modules.
One corresponds to the "standard" scan-converter, the other to the
"smooth" one.
The current renderer can be set through the new function
FT_Set_Renderer.
The old raster-related function FT_Set_Raster, FT_Get_Raster and
FT_Set_Raster_Mode have now disappeared, in favor of the new:
FT_Get_Renderer
FT_Set_Renderer
see the file <freetype/ftrender.h> for more details..
These changes were necessary to properly support different scalable
formats in the future, like bi-color glyphs, etc..
- glyph loader object:
A new internal object, called a 'glyph loader' has been introduced
in the base layer. It is used by all scalable format font drivers
to load glyphs and composites.
This object has been created to reduce the code size of each driver,
as each one of them basically re-implemented its functionality.
See <freetype/internal/ftobjs.h> and the FT_GlyphLoader type for
more information..
- FT_GlyphSlot had new fields:
In order to support extended features (see below), the FT_GlyphSlot
structure has a few new fields:
linearHoriAdvance: this field gives the linearly scaled (i.e.
scaled but unhinted) advance width for the glyph,
expressed as a 16.16 fixed pixel value. This
is useful to perform WYSIWYG text.
linearVertAdvance: this field gives the linearly scaled advance
height for the glyph (relevant in vertical glyph
layouts only). This is useful to perform
WYSIWYG text.
Note that the two above field replace the removed "metrics2" field
in the glyph slot.
advance: this field is a vector that gives the transformed
advance for the glyph. By default, it corresponds
to the advance width, unless FT_LOAD_VERTICAL_LAYOUT
was specified when calling FT_Load_Glyph or FT_Load_Char
bitmap_left: this field gives the distance in integer pixels from
the current pen position to the left-most pixel of
a glyph image WHEN IT IS A BITMAP. It is only valid
when the "format" field is set to
"ft_glyph_format_bitmap", for example, after calling
the new function FT_Render_Glyph.
bitmap_top: this field gives the distance in integer pixels from
the current pen position (located on the baseline) to
the top-most pixel of the glyph image WHEN IT IS A
BITMAP. Positive values correspond to upwards Y.
loader: this is a new private field for the glyph slot. Client
applications should not touch it..
- support for transforms and direct rendering in FT_Load_Glyph:
Most of the functionality found in <freetype/ftglyph.h> has been
moved to the core library. Hence, the following:
- a transform can be specified for a face through FT_Set_Transform.
this transform is applied by FT_Load_Glyph to scalable glyph images
(i.e. NOT TO BITMAPS) before the function returns, unless the
bit flag FT_LOAD_IGNORE_TRANSFORM was set in the load flags..
- once a glyph image has been loaded, it can be directly converted to
a bitmap by using the new FT_Render_Glyph function. Note that this
function takes the glyph image from the glyph slot, and converts
it to a bitmap whose properties are returned in "face.glyph.bitmap",
"face.glyph.bitmap_left" and "face.glyph.bitmap_top". The original
native image might be lost after the conversion.
- when using the new bit flag FT_LOAD_RENDER, the FT_Load_Glyph
and FT_Load_Char functions will call FT_Render_Glyph automatically
when needed.
2000-06-22 02:17:42 +02:00
|
|
|
/* TrueTyoe error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* <Note> */
|
|
|
|
/* Only the glyph loader and debugger should call this function. */
|
|
|
|
/* */
|
2002-03-01 03:26:22 +01:00
|
|
|
FT_LOCAL_DEF( FT_Error )
|
2001-06-28 09:17:51 +02:00
|
|
|
TT_Run_Context( TT_ExecContext exec,
|
|
|
|
FT_Bool debug )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
|
|
|
if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) )
|
1999-12-17 00:11:37 +01:00
|
|
|
!= TT_Err_Ok )
|
|
|
|
return error;
|
|
|
|
|
|
|
|
exec->zp0 = exec->pts;
|
|
|
|
exec->zp1 = exec->pts;
|
|
|
|
exec->zp2 = exec->pts;
|
|
|
|
|
|
|
|
exec->GS.gep0 = 1;
|
|
|
|
exec->GS.gep1 = 1;
|
|
|
|
exec->GS.gep2 = 1;
|
|
|
|
|
|
|
|
exec->GS.projVector.x = 0x4000;
|
|
|
|
exec->GS.projVector.y = 0x0000;
|
|
|
|
|
|
|
|
exec->GS.freeVector = exec->GS.projVector;
|
|
|
|
exec->GS.dualVector = exec->GS.projVector;
|
|
|
|
|
|
|
|
exec->GS.round_state = 1;
|
|
|
|
exec->GS.loop = 1;
|
|
|
|
|
|
|
|
/* some glyphs leave something on the stack. so we clean it */
|
|
|
|
/* before a new execution. */
|
|
|
|
exec->top = 0;
|
|
|
|
exec->callTop = 0;
|
|
|
|
|
|
|
|
#if 1
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED( debug );
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
return exec->face->interpreter( exec );
|
|
|
|
#else
|
|
|
|
if ( !debug )
|
|
|
|
return TT_RunIns( exec );
|
|
|
|
else
|
|
|
|
return TT_Err_Ok;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const TT_GraphicsState tt_default_graphics_state =
|
|
|
|
{
|
|
|
|
0, 0, 0,
|
|
|
|
{ 0x4000, 0 },
|
|
|
|
{ 0x4000, 0 },
|
|
|
|
{ 0x4000, 0 },
|
|
|
|
1, 64, 1,
|
|
|
|
TRUE, 68, 0, 0, 9, 3,
|
|
|
|
0, FALSE, 2, 1, 1, 1
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2000-11-07 18:21:11 +01:00
|
|
|
/* documentation is in ttinterp.h */
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
FT_EXPORT_DEF( TT_ExecContext )
|
|
|
|
TT_New_Context( TT_Face face )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
TT_Driver driver;
|
1999-12-17 00:11:37 +01:00
|
|
|
TT_ExecContext exec;
|
2000-06-12 21:36:41 +02:00
|
|
|
FT_Memory memory;
|
|
|
|
|
|
|
|
|
|
|
|
if ( !face )
|
|
|
|
return 0;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
driver = (TT_Driver)face->root.driver;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
- MAJOR INTERNAL REDESIGN:
A lot of internal modifications have been performed lately on the
source in order to provide the following enhancements:
- more generic module support:
The FT_Module type is now defined to represent a handle to a given
module. The file <freetype/ftmodule.h> contains the FT_Module_Class
definition, as well as the module-loading public API
The FT_Driver type is still defined, and still represents a pointer
to a font driver. Note that FT_Add_Driver is replaced by FT_Add_Module,
FT_Get_Driver by FT_Get_Module, etc..
- support for generic glyph image types:
The FT_Renderer type is a pointer to a module used to perform various
operations on glyph image.
Each renderer is capable of handling images in a single format
(e.g. ft_glyph_format_outline). Its functions are used to:
- transform an glyph image
- render a glyph image into a bitmap
- return the control box (dimensions) of a given glyph image
The scan converters "ftraster.c" and "ftgrays.c" have been moved
to the new directory "src/renderer", and are used to provide two
default renderer modules.
One corresponds to the "standard" scan-converter, the other to the
"smooth" one.
The current renderer can be set through the new function
FT_Set_Renderer.
The old raster-related function FT_Set_Raster, FT_Get_Raster and
FT_Set_Raster_Mode have now disappeared, in favor of the new:
FT_Get_Renderer
FT_Set_Renderer
see the file <freetype/ftrender.h> for more details..
These changes were necessary to properly support different scalable
formats in the future, like bi-color glyphs, etc..
- glyph loader object:
A new internal object, called a 'glyph loader' has been introduced
in the base layer. It is used by all scalable format font drivers
to load glyphs and composites.
This object has been created to reduce the code size of each driver,
as each one of them basically re-implemented its functionality.
See <freetype/internal/ftobjs.h> and the FT_GlyphLoader type for
more information..
- FT_GlyphSlot had new fields:
In order to support extended features (see below), the FT_GlyphSlot
structure has a few new fields:
linearHoriAdvance: this field gives the linearly scaled (i.e.
scaled but unhinted) advance width for the glyph,
expressed as a 16.16 fixed pixel value. This
is useful to perform WYSIWYG text.
linearVertAdvance: this field gives the linearly scaled advance
height for the glyph (relevant in vertical glyph
layouts only). This is useful to perform
WYSIWYG text.
Note that the two above field replace the removed "metrics2" field
in the glyph slot.
advance: this field is a vector that gives the transformed
advance for the glyph. By default, it corresponds
to the advance width, unless FT_LOAD_VERTICAL_LAYOUT
was specified when calling FT_Load_Glyph or FT_Load_Char
bitmap_left: this field gives the distance in integer pixels from
the current pen position to the left-most pixel of
a glyph image WHEN IT IS A BITMAP. It is only valid
when the "format" field is set to
"ft_glyph_format_bitmap", for example, after calling
the new function FT_Render_Glyph.
bitmap_top: this field gives the distance in integer pixels from
the current pen position (located on the baseline) to
the top-most pixel of the glyph image WHEN IT IS A
BITMAP. Positive values correspond to upwards Y.
loader: this is a new private field for the glyph slot. Client
applications should not touch it..
- support for transforms and direct rendering in FT_Load_Glyph:
Most of the functionality found in <freetype/ftglyph.h> has been
moved to the core library. Hence, the following:
- a transform can be specified for a face through FT_Set_Transform.
this transform is applied by FT_Load_Glyph to scalable glyph images
(i.e. NOT TO BITMAPS) before the function returns, unless the
bit flag FT_LOAD_IGNORE_TRANSFORM was set in the load flags..
- once a glyph image has been loaded, it can be directly converted to
a bitmap by using the new FT_Render_Glyph function. Note that this
function takes the glyph image from the glyph slot, and converts
it to a bitmap whose properties are returned in "face.glyph.bitmap",
"face.glyph.bitmap_left" and "face.glyph.bitmap_top". The original
native image might be lost after the conversion.
- when using the new bit flag FT_LOAD_RENDER, the FT_Load_Glyph
and FT_Load_Char functions will call FT_Render_Glyph automatically
when needed.
2000-06-22 02:17:42 +02:00
|
|
|
memory = driver->root.root.memory;
|
2000-06-12 21:36:41 +02:00
|
|
|
exec = driver->context;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( !driver->context )
|
|
|
|
{
|
2000-07-02 15:53:16 +02:00
|
|
|
FT_Error error;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
/* allocate object */
|
|
|
|
if ( ALLOC( exec, sizeof ( *exec ) ) )
|
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
/* initialize it */
|
|
|
|
error = Init_Context( exec, face, memory );
|
|
|
|
if ( error )
|
|
|
|
goto Fail;
|
|
|
|
|
|
|
|
/* store it into the driver */
|
|
|
|
driver->context = exec;
|
|
|
|
}
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return driver->context;
|
|
|
|
|
|
|
|
Fail:
|
|
|
|
FREE( exec );
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Done_Context */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Discards an execution context. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* exec :: A handle to the target execution context. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* <Note> */
|
|
|
|
/* Only the glyph loader and debugger should call this function. */
|
|
|
|
/* */
|
2002-03-01 03:26:22 +01:00
|
|
|
FT_LOCAL_DEF( FT_Error )
|
2001-06-28 09:17:51 +02:00
|
|
|
TT_Done_Context( TT_ExecContext exec )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
/* Nothing at all for now */
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED( exec );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
return TT_Err_Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-14 14:34:00 +02:00
|
|
|
/* return length of given vector */
|
2000-05-02 13:01:12 +02:00
|
|
|
#ifdef FT_CONFIG_OPTION_OLD_CALCS
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_F26Dot6
|
|
|
|
Norm( FT_F26Dot6 X,
|
|
|
|
FT_F26Dot6 Y )
|
2000-05-02 13:01:12 +02:00
|
|
|
{
|
2000-07-05 06:32:02 +02:00
|
|
|
TT_INT64 T1, T2;
|
2000-06-12 21:36:41 +02:00
|
|
|
|
2000-05-02 13:01:12 +02:00
|
|
|
|
|
|
|
MUL_64( X, X, T1 );
|
|
|
|
MUL_64( Y, Y, T2 );
|
|
|
|
|
|
|
|
ADD_64( T1, T2, T1 );
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
return (FT_F26Dot6)SQRT_64( T1 );
|
2000-05-02 13:01:12 +02:00
|
|
|
}
|
2000-06-12 21:36:41 +02:00
|
|
|
|
2001-06-14 14:34:00 +02:00
|
|
|
#else /* !FT_CONFIG_OPTION_OLD_CALCS */
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_F26Dot6
|
|
|
|
Norm( FT_F26Dot6 X,
|
|
|
|
FT_F26Dot6 Y )
|
2001-06-14 14:34:00 +02:00
|
|
|
{
|
|
|
|
FT_Vector v;
|
2001-06-28 19:49:10 +02:00
|
|
|
|
2001-06-14 14:34:00 +02:00
|
|
|
v.x = X;
|
|
|
|
v.y = Y;
|
|
|
|
return FT_Vector_Length( &v );
|
2001-06-28 19:49:10 +02:00
|
|
|
}
|
2001-06-14 14:34:00 +02:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#endif /* FT_CONFIG_OPTION_OLD_CALCS */
|
2000-05-02 13:01:12 +02:00
|
|
|
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* 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
|
2000-06-12 21:36:41 +02:00
|
|
|
#define PACK( x, y ) ( ( x << 4 ) | y )
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
static
|
2000-06-16 21:34:52 +02:00
|
|
|
const FT_Byte Pop_Push_Count[256] =
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
/* 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
|
2000-06-16 21:34:52 +02:00
|
|
|
const FT_Char opcode_length[256] =
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
|
|
|
|
-1,-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
2, 3, 4, 5, 6, 7, 8, 9, 3, 5, 7, 9, 11,13,15,17,
|
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
|
|
|
};
|
|
|
|
|
|
|
|
static
|
2000-06-16 21:34:52 +02:00
|
|
|
const FT_Vector Null_Vector = {0,0};
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-07-02 15:53:16 +02:00
|
|
|
#undef PACK
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
#undef NULL_Vector
|
2000-06-16 21:34:52 +02:00
|
|
|
#define NULL_Vector (FT_Vector*)&Null_Vector
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Current_Ratio */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Returns the current aspect ratio scaling factor depending on the */
|
|
|
|
/* projection vector's state and device resolutions. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
|
|
|
/* The aspect ratio in 16.16 format, always <= 1.0 . */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_Long
|
|
|
|
Current_Ratio( EXEC_OP )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
if ( CUR.tt_metrics.ratio )
|
|
|
|
return CUR.tt_metrics.ratio;
|
|
|
|
|
|
|
|
if ( CUR.GS.projVector.y == 0 )
|
|
|
|
CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
|
|
|
|
|
|
|
|
else if ( CUR.GS.projVector.x == 0 )
|
|
|
|
CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Long x, y;
|
2000-07-02 15:53:16 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
x = TT_MULDIV( CUR.GS.projVector.x, CUR.tt_metrics.x_ratio, 0x4000 );
|
|
|
|
y = TT_MULDIV( CUR.GS.projVector.y, CUR.tt_metrics.y_ratio, 0x4000 );
|
|
|
|
CUR.tt_metrics.ratio = Norm( x, y );
|
|
|
|
}
|
|
|
|
|
|
|
|
return CUR.tt_metrics.ratio;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_Long
|
|
|
|
Current_Ppem( EXEC_OP )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* Functions related to the control value table (CVT). */
|
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
FT_CALLBACK_DEF( FT_F26Dot6 )
|
|
|
|
Read_CVT( EXEC_OP_ FT_ULong index )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
return CUR.cvt[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
FT_CALLBACK_DEF( FT_F26Dot6 )
|
|
|
|
Read_CVT_Stretched( EXEC_OP_ FT_ULong index )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
return TT_MULFIX( CUR.cvt[index], CURRENT_Ratio() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
FT_CALLBACK_DEF( void )
|
|
|
|
Write_CVT( EXEC_OP_ FT_ULong index,
|
|
|
|
FT_F26Dot6 value )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
CUR.cvt[index] = value;
|
|
|
|
}
|
|
|
|
|
2000-07-02 15:53:16 +02:00
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
FT_CALLBACK_DEF( void )
|
|
|
|
Write_CVT_Stretched( EXEC_OP_ FT_ULong index,
|
|
|
|
FT_F26Dot6 value )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
CUR.cvt[index] = FT_DivFix( value, CURRENT_Ratio() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
FT_CALLBACK_DEF( void )
|
|
|
|
Move_CVT( EXEC_OP_ FT_ULong index,
|
|
|
|
FT_F26Dot6 value )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
CUR.cvt[index] += value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
FT_CALLBACK_DEF( void )
|
|
|
|
Move_CVT_Stretched( EXEC_OP_ FT_ULong index,
|
|
|
|
FT_F26Dot6 value )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
CUR.cvt[index] += FT_DivFix( value, CURRENT_Ratio() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* GetShortIns */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Returns a short integer taken from the instruction stream at */
|
|
|
|
/* address IP. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
|
|
|
/* Short read at code[IP]. */
|
|
|
|
/* */
|
|
|
|
/* <Note> */
|
|
|
|
/* This one could become a macro. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_Short
|
|
|
|
GetShortIns( EXEC_OP )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
/* Reading a byte stream so there is no endianess (DaveP) */
|
|
|
|
CUR.IP += 2;
|
2000-06-16 21:34:52 +02:00
|
|
|
return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) +
|
2000-06-12 21:36:41 +02:00
|
|
|
CUR.code[CUR.IP - 1] );
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Ins_Goto_CodeRange */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Goes to a certain code range in the instruction stream. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* aRange :: The index of the code range. */
|
|
|
|
/* */
|
|
|
|
/* aIP :: The new IP address in the code range. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
|
|
|
/* SUCCESS or FAILURE. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_Bool
|
|
|
|
Ins_Goto_CodeRange( EXEC_OP_ FT_Int aRange,
|
|
|
|
FT_ULong aIP )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
TT_CodeRange* range;
|
|
|
|
|
|
|
|
|
|
|
|
if ( aRange < 1 || aRange > 3 )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Bad_Argument;
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
range = &CUR.codeRangeTable[aRange - 1];
|
|
|
|
|
|
|
|
if ( range->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 > range->size )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Code_Overflow;
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
CUR.code = range->base;
|
|
|
|
CUR.codeSize = range->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 :: The index of the point to move. */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* distance :: The distance to apply. */
|
|
|
|
/* */
|
|
|
|
/* <InOut> */
|
|
|
|
/* zone :: The affected glyph zone. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
2002-03-14 12:26:29 +01:00
|
|
|
Direct_Move( EXEC_OP_ TT_GlyphZone zone,
|
2001-06-28 09:17:51 +02:00
|
|
|
FT_UShort point,
|
|
|
|
FT_F26Dot6 distance )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_F26Dot6 v;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
v = CUR.GS.freeVector.x;
|
|
|
|
|
|
|
|
if ( v != 0 )
|
|
|
|
{
|
2000-07-02 15:53:16 +02:00
|
|
|
|
2000-01-27 14:56:02 +01:00
|
|
|
#ifdef NO_APPLE_PATENT
|
2000-07-02 15:53:16 +02:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( ABS( CUR.F_dot_P ) > APPLE_THRESHOLD )
|
2000-01-27 14:56:02 +01:00
|
|
|
zone->cur[point].x += distance;
|
2000-07-02 15:53:16 +02:00
|
|
|
|
2000-01-27 14:56:02 +01:00
|
|
|
#else
|
2000-07-02 15:53:16 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
zone->cur[point].x += TT_MULDIV( distance,
|
|
|
|
v * 0x10000L,
|
|
|
|
CUR.F_dot_P );
|
2000-07-02 15:53:16 +02:00
|
|
|
|
2000-01-27 14:56:02 +01:00
|
|
|
#endif
|
2000-07-02 15:53:16 +02:00
|
|
|
|
2000-03-09 12:46:25 +01:00
|
|
|
zone->tags[point] |= FT_Curve_Tag_Touch_X;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
v = CUR.GS.freeVector.y;
|
|
|
|
|
|
|
|
if ( v != 0 )
|
|
|
|
{
|
2000-07-02 15:53:16 +02:00
|
|
|
|
2000-01-27 14:56:02 +01:00
|
|
|
#ifdef NO_APPLE_PATENT
|
2000-07-02 15:53:16 +02:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( ABS( CUR.F_dot_P ) > APPLE_THRESHOLD )
|
2000-01-27 14:56:02 +01:00
|
|
|
zone->cur[point].y += distance;
|
2000-07-02 15:53:16 +02:00
|
|
|
|
2000-01-27 14:56:02 +01:00
|
|
|
#else
|
2000-07-02 15:53:16 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
zone->cur[point].y += TT_MULDIV( distance,
|
|
|
|
v * 0x10000L,
|
|
|
|
CUR.F_dot_P );
|
2000-07-02 15:53:16 +02:00
|
|
|
|
2000-01-27 14:56:02 +01:00
|
|
|
#endif
|
2000-07-02 15:53:16 +02:00
|
|
|
|
2000-03-09 12:46:25 +01:00
|
|
|
zone->tags[point] |= FT_Curve_Tag_Touch_Y;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* Special versions of Direct_Move() */
|
|
|
|
/* */
|
|
|
|
/* The following versions are used whenever both vectors are both */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* along one of the coordinate unit vectors, i.e. in 90% of the cases. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
2000-07-02 15:53:16 +02:00
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
2002-03-14 12:26:29 +01:00
|
|
|
Direct_Move_X( EXEC_OP_ TT_GlyphZone zone,
|
2001-06-28 09:17:51 +02:00
|
|
|
FT_UShort point,
|
|
|
|
FT_F26Dot6 distance )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_EXEC;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
zone->cur[point].x += distance;
|
2000-07-02 15:53:16 +02:00
|
|
|
zone->tags[point] |= FT_Curve_Tag_Touch_X;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
2002-03-14 12:26:29 +01:00
|
|
|
Direct_Move_Y( EXEC_OP_ TT_GlyphZone zone,
|
2001-06-28 09:17:51 +02:00
|
|
|
FT_UShort point,
|
|
|
|
FT_F26Dot6 distance )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_EXEC;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
zone->cur[point].y += distance;
|
2000-07-02 15:53:16 +02:00
|
|
|
zone->tags[point] |= FT_Curve_Tag_Touch_Y;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Round_None */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Does not round, but adds engine compensation. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* distance :: The distance (not) to round. */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* compensation :: The engine compensation. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
|
|
|
/* The compensated distance. */
|
|
|
|
/* */
|
|
|
|
/* <Note> */
|
|
|
|
/* The TrueType specification says very few about the relationship */
|
|
|
|
/* between rounding and engine compensation. However, it seems from */
|
|
|
|
/* the description of super round that we should add the compensation */
|
|
|
|
/* before rounding. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_F26Dot6
|
|
|
|
Round_None( EXEC_OP_ FT_F26Dot6 distance,
|
|
|
|
FT_F26Dot6 compensation )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_F26Dot6 val;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_EXEC;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
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 :: The distance to round. */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* compensation :: The engine compensation. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
|
|
|
/* Rounded distance. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_F26Dot6
|
|
|
|
Round_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
|
|
|
|
FT_F26Dot6 compensation )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_F26Dot6 val;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_EXEC;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( distance >= 0 )
|
|
|
|
{
|
|
|
|
val = distance + compensation + 32;
|
|
|
|
if ( val > 0 )
|
|
|
|
val &= ~63;
|
|
|
|
else
|
|
|
|
val = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
val = -( ( compensation - distance + 32 ) & -64 );
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( val > 0 )
|
|
|
|
val = 0;
|
|
|
|
}
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Round_To_Half_Grid */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Rounds value to half grid after adding engine compensation. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* distance :: The distance to round. */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* compensation :: The engine compensation. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
|
|
|
/* Rounded distance. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_F26Dot6
|
|
|
|
Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6 distance,
|
|
|
|
FT_F26Dot6 compensation )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_F26Dot6 val;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_EXEC;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( distance >= 0 )
|
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
val = ( ( distance + compensation ) & -64 ) + 32;
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( val < 0 )
|
|
|
|
val = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
val = -( ( (compensation - distance) & -64 ) + 32 );
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( val > 0 )
|
|
|
|
val = 0;
|
|
|
|
}
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Round_Down_To_Grid */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Rounds value down to grid after adding engine compensation. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* distance :: The distance to round. */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* compensation :: The engine compensation. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
|
|
|
/* Rounded distance. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_F26Dot6
|
|
|
|
Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
|
|
|
|
FT_F26Dot6 compensation )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_F26Dot6 val;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_EXEC;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( distance >= 0 )
|
|
|
|
{
|
|
|
|
val = distance + compensation;
|
|
|
|
if ( val > 0 )
|
|
|
|
val &= ~63;
|
|
|
|
else
|
|
|
|
val = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
val = -( ( compensation - distance ) & -64 );
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( val > 0 )
|
|
|
|
val = 0;
|
|
|
|
}
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Round_Up_To_Grid */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Rounds value up to grid after adding engine compensation. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* distance :: The distance to round. */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* compensation :: The engine compensation. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
|
|
|
/* Rounded distance. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_F26Dot6
|
|
|
|
Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
|
|
|
|
FT_F26Dot6 compensation )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_F26Dot6 val;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_EXEC;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( distance >= 0 )
|
|
|
|
{
|
|
|
|
val = distance + compensation + 63;
|
|
|
|
if ( val > 0 )
|
|
|
|
val &= ~63;
|
|
|
|
else
|
|
|
|
val = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
val = -( ( compensation - distance + 63 ) & -64 );
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( val > 0 )
|
|
|
|
val = 0;
|
|
|
|
}
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Round_To_Double_Grid */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Rounds value to double grid after adding engine compensation. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* distance :: The distance to round. */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* compensation :: The engine compensation. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
|
|
|
/* Rounded distance. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_F26Dot6
|
|
|
|
Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6 distance,
|
|
|
|
FT_F26Dot6 compensation )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_F26Dot6 val;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_EXEC;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( distance >= 0 )
|
|
|
|
{
|
|
|
|
val = distance + compensation + 16;
|
|
|
|
if ( val > 0 )
|
|
|
|
val &= ~31;
|
|
|
|
else
|
|
|
|
val = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
val = -( ( compensation - distance + 16 ) & -32 );
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( val > 0 )
|
|
|
|
val = 0;
|
|
|
|
}
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Round_Super */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Super-rounds value to grid after adding engine compensation. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* distance :: The distance to round. */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* compensation :: The engine compensation. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
|
|
|
/* Rounded distance. */
|
|
|
|
/* */
|
|
|
|
/* <Note> */
|
|
|
|
/* The TrueType specification says very few about the relationship */
|
|
|
|
/* between rounding and engine compensation. However, it seems from */
|
|
|
|
/* the description of super round that we should add the compensation */
|
|
|
|
/* before rounding. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_F26Dot6
|
|
|
|
Round_Super( EXEC_OP_ FT_F26Dot6 distance,
|
|
|
|
FT_F26Dot6 compensation )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_F26Dot6 val;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
if ( distance >= 0 )
|
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
val = ( distance - CUR.phase + CUR.threshold + compensation ) &
|
|
|
|
-CUR.period;
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( val < 0 )
|
|
|
|
val = 0;
|
|
|
|
val += CUR.phase;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
val = -( ( CUR.threshold - CUR.phase - distance + compensation ) &
|
|
|
|
-CUR.period );
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( val > 0 )
|
|
|
|
val = 0;
|
|
|
|
val -= CUR.phase;
|
|
|
|
}
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Round_Super_45 */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Super-rounds value to grid after adding engine compensation. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* distance :: The distance to round. */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* compensation :: The engine compensation. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
|
|
|
/* Rounded distance. */
|
|
|
|
/* */
|
|
|
|
/* <Note> */
|
|
|
|
/* There is a separate function for Round_Super_45() as we may need */
|
|
|
|
/* greater precision. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_F26Dot6
|
|
|
|
Round_Super_45( EXEC_OP_ FT_F26Dot6 distance,
|
|
|
|
FT_F26Dot6 compensation )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_F26Dot6 val;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
if ( distance >= 0 )
|
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
val = ( ( distance - CUR.phase + CUR.threshold + compensation ) /
|
1999-12-17 00:11:37 +01:00
|
|
|
CUR.period ) * CUR.period;
|
|
|
|
if ( val < 0 )
|
|
|
|
val = 0;
|
|
|
|
val += CUR.phase;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) /
|
1999-12-17 00:11:37 +01:00
|
|
|
CUR.period ) * CUR.period );
|
|
|
|
if ( val > 0 )
|
|
|
|
val = 0;
|
|
|
|
val -= CUR.phase;
|
|
|
|
}
|
|
|
|
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Compute_Round */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Sets the rounding mode. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* round_mode :: The rounding mode to be used. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Compute_Round( EXEC_OP_ FT_Byte round_mode )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
switch ( round_mode )
|
|
|
|
{
|
|
|
|
case TT_Round_Off:
|
|
|
|
CUR.func_round = (TT_Round_Func)Round_None;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TT_Round_To_Grid:
|
|
|
|
CUR.func_round = (TT_Round_Func)Round_To_Grid;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TT_Round_Up_To_Grid:
|
|
|
|
CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TT_Round_Down_To_Grid:
|
|
|
|
CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TT_Round_To_Half_Grid:
|
|
|
|
CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TT_Round_To_Double_Grid:
|
|
|
|
CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TT_Round_Super:
|
|
|
|
CUR.func_round = (TT_Round_Func)Round_Super;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TT_Round_Super_45:
|
|
|
|
CUR.func_round = (TT_Round_Func)Round_Super_45;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* SetSuperRound */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Sets Super Round parameters. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* GridPeriod :: Grid period */
|
|
|
|
/* selector :: SROUND opcode */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
SetSuperRound( EXEC_OP_ FT_F26Dot6 GridPeriod,
|
|
|
|
FT_Long selector )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
switch ( (FT_Int)( selector & 0xC0 ) )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
switch ( (FT_Int)( selector & 0x30 ) )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
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
|
2000-06-16 21:34:52 +02:00
|
|
|
CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
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 :: First input vector. */
|
|
|
|
/* v2 :: Second input vector. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
|
|
|
/* The distance in F26dot6 format. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_F26Dot6
|
|
|
|
Project( EXEC_OP_ FT_Vector* v1,
|
|
|
|
FT_Vector* v2 )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
return TT_MULDIV( v1->x - v2->x, CUR.GS.projVector.x, 0x4000 ) +
|
|
|
|
TT_MULDIV( v1->y - v2->y, CUR.GS.projVector.y, 0x4000 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Dual_Project */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Computes the projection of the vector given by (v2-v1) along the */
|
|
|
|
/* current dual vector. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* v1 :: First input vector. */
|
|
|
|
/* v2 :: Second input vector. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
|
|
|
/* The distance in F26dot6 format. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_F26Dot6
|
|
|
|
Dual_Project( EXEC_OP_ FT_Vector* v1,
|
|
|
|
FT_Vector* v2 )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
return TT_MULDIV( v1->x - v2->x, CUR.GS.dualVector.x, 0x4000 ) +
|
|
|
|
TT_MULDIV( v1->y - v2->y, CUR.GS.dualVector.y, 0x4000 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Free_Project */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Computes the projection of the vector given by (v2-v1) along the */
|
|
|
|
/* current freedom vector. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* v1 :: First input vector. */
|
|
|
|
/* v2 :: Second input vector. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
|
|
|
/* The distance in F26dot6 format. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_F26Dot6
|
|
|
|
Free_Project( EXEC_OP_ FT_Vector* v1,
|
|
|
|
FT_Vector* v2 )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
return TT_MULDIV( v1->x - v2->x, CUR.GS.freeVector.x, 0x4000 ) +
|
|
|
|
TT_MULDIV( v1->y - v2->y, CUR.GS.freeVector.y, 0x4000 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Project_x */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Computes the projection of the vector given by (v2-v1) along the */
|
|
|
|
/* horizontal axis. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* v1 :: First input vector. */
|
|
|
|
/* v2 :: Second input vector. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
|
|
|
/* The distance in F26dot6 format. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_F26Dot6
|
|
|
|
Project_x( EXEC_OP_ FT_Vector* v1,
|
|
|
|
FT_Vector* v2 )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_EXEC;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
return ( v1->x - v2->x );
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Project_y */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Computes the projection of the vector given by (v2-v1) along the */
|
|
|
|
/* vertical axis. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* v1 :: First input vector. */
|
|
|
|
/* v2 :: Second input vector. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
|
|
|
/* The distance in F26dot6 format. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_F26Dot6
|
|
|
|
Project_y( EXEC_OP_ FT_Vector* v1,
|
|
|
|
FT_Vector* v2 )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_EXEC;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
return ( v1->y - v2->y );
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Compute_Funcs */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Computes the projection and movement function pointers according */
|
|
|
|
/* to the current graphics state. */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Compute_Funcs( EXEC_OP )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
if ( CUR.GS.freeVector.x == 0x4000 )
|
|
|
|
{
|
|
|
|
CUR.func_freeProj = (TT_Project_Func)Project_x;
|
|
|
|
CUR.F_dot_P = CUR.GS.projVector.x * 0x10000L;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( CUR.GS.freeVector.y == 0x4000 )
|
|
|
|
{
|
|
|
|
CUR.func_freeProj = (TT_Project_Func)Project_y;
|
|
|
|
CUR.F_dot_P = CUR.GS.projVector.y * 0x10000L;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CUR.func_freeProj = (TT_Project_Func)Free_Project;
|
2000-06-16 21:34:52 +02:00
|
|
|
CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 +
|
|
|
|
(FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( CUR.GS.projVector.x == 0x4000 )
|
|
|
|
CUR.func_project = (TT_Project_Func)Project_x;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( CUR.GS.projVector.y == 0x4000 )
|
|
|
|
CUR.func_project = (TT_Project_Func)Project_y;
|
|
|
|
else
|
|
|
|
CUR.func_project = (TT_Project_Func)Project;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( CUR.GS.dualVector.x == 0x4000 )
|
|
|
|
CUR.func_dualproj = (TT_Project_Func)Project_x;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( CUR.GS.dualVector.y == 0x4000 )
|
|
|
|
CUR.func_dualproj = (TT_Project_Func)Project_y;
|
|
|
|
else
|
|
|
|
CUR.func_dualproj = (TT_Project_Func)Dual_Project;
|
|
|
|
}
|
|
|
|
|
|
|
|
CUR.func_move = (TT_Move_Func)Direct_Move;
|
|
|
|
|
|
|
|
if ( CUR.F_dot_P == 0x40000000L )
|
|
|
|
{
|
|
|
|
if ( CUR.GS.freeVector.x == 0x4000 )
|
|
|
|
CUR.func_move = (TT_Move_Func)Direct_Move_X;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( CUR.GS.freeVector.y == 0x4000 )
|
|
|
|
CUR.func_move = (TT_Move_Func)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.tt_metrics.ratio = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* Normalize */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Norms a vector. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* Vx :: The horizontal input vector coordinate. */
|
|
|
|
/* Vy :: The vertical input vector coordinate. */
|
|
|
|
/* */
|
|
|
|
/* <Output> */
|
|
|
|
/* R :: The normed unit vector. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
|
|
|
/* Returns FAILURE if a vector parameter is zero. */
|
|
|
|
/* */
|
|
|
|
/* <Note> */
|
|
|
|
/* In case Vx and Vy are both zero, Normalize() returns SUCCESS, and */
|
|
|
|
/* R is undefined. */
|
|
|
|
/* */
|
2000-05-02 13:01:12 +02:00
|
|
|
|
|
|
|
#ifdef FT_CONFIG_OPTION_OLD_CALCS
|
2000-06-12 21:36:41 +02:00
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_Bool
|
|
|
|
Normalize( EXEC_OP_ FT_F26Dot6 Vx,
|
|
|
|
FT_F26Dot6 Vy,
|
|
|
|
FT_UnitVector* R )
|
2000-05-02 13:01:12 +02:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_F26Dot6 W;
|
|
|
|
FT_Bool S1, S2;
|
2000-05-02 13:01:12 +02:00
|
|
|
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_EXEC;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
2000-05-02 13:01:12 +02:00
|
|
|
if ( ABS( Vx ) < 0x10000L && ABS( Vy ) < 0x10000L )
|
|
|
|
{
|
|
|
|
Vx *= 0x100;
|
|
|
|
Vy *= 0x100;
|
|
|
|
|
|
|
|
W = Norm( Vx, Vy );
|
|
|
|
|
|
|
|
if ( W == 0 )
|
|
|
|
{
|
2000-07-02 15:53:16 +02:00
|
|
|
/* XXX: UNDOCUMENTED! It seems that it is possible to try */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* to normalize the vector (0,0). Return immediately. */
|
2000-05-02 13:01:12 +02:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W );
|
|
|
|
R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W );
|
2000-05-02 13:01:12 +02:00
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
W = Norm( Vx, Vy );
|
|
|
|
|
|
|
|
Vx = FT_MulDiv( Vx, 0x4000L, W );
|
|
|
|
Vy = FT_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 )
|
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
/* We need to increase W by a minimal amount */
|
2000-05-02 13:01:12 +02:00
|
|
|
if ( Vx < Vy )
|
|
|
|
Vx++;
|
|
|
|
else
|
|
|
|
Vy++;
|
|
|
|
|
|
|
|
W = Vx * Vx + Vy * Vy;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ( W >= 0x1004000L )
|
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
/* We need to decrease W by a minimal amount */
|
2000-05-02 13:01:12 +02:00
|
|
|
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;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
R->x = (FT_F2Dot14)Vx; /* Type conversion */
|
|
|
|
R->y = (FT_F2Dot14)Vy; /* Type conversion */
|
2000-05-02 13:01:12 +02:00
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
2000-06-12 21:36:41 +02:00
|
|
|
|
2000-05-17 01:44:38 +02:00
|
|
|
#else
|
2000-06-12 21:36:41 +02:00
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_Bool
|
|
|
|
Normalize( EXEC_OP_ FT_F26Dot6 Vx,
|
|
|
|
FT_F26Dot6 Vy,
|
|
|
|
FT_UnitVector* R )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2001-06-14 14:34:00 +02:00
|
|
|
FT_Vector v;
|
|
|
|
FT_Angle angle;
|
2001-06-28 19:49:10 +02:00
|
|
|
|
2001-07-07 18:12:14 +02:00
|
|
|
FT_UNUSED_EXEC;
|
|
|
|
|
2001-06-14 14:34:00 +02:00
|
|
|
angle = FT_Atan2( Vx, Vy );
|
|
|
|
|
|
|
|
FT_Vector_Unit( &v, angle );
|
2001-06-28 19:49:10 +02:00
|
|
|
|
2001-07-07 18:12:14 +02:00
|
|
|
R->x = (short)(v.x >> 2);
|
|
|
|
R->y = (short)(v.y >> 2);
|
2001-06-28 19:49:10 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
2000-06-12 21:36:41 +02:00
|
|
|
|
|
|
|
#endif /* FT_CONFIG_OPTION_OLD_CALCS */
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* Here we start with the implementation of the various opcodes. */
|
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_Bool
|
|
|
|
Ins_SxVTL( EXEC_OP_ FT_UShort aIdx1,
|
|
|
|
FT_UShort aIdx2,
|
|
|
|
FT_Int aOpc,
|
|
|
|
FT_UnitVector* Vec )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Long A, B, C;
|
|
|
|
FT_Vector* p1;
|
|
|
|
FT_Vector* p2;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( ( aOpc & 1 ) != 0 )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
C = B; /* counter clockwise rotation */
|
1999-12-17 00:11:37 +01:00
|
|
|
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. */
|
|
|
|
/* */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* They are all defined there. */
|
|
|
|
|
|
|
|
#define DO_SVTCA \
|
|
|
|
{ \
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Short A, B; \
|
2000-06-12 21:36:41 +02:00
|
|
|
\
|
|
|
|
\
|
2000-06-16 21:34:52 +02:00
|
|
|
A = (FT_Short)( CUR.opcode & 1 ) << 14; \
|
|
|
|
B = A ^ (FT_Short)0x4000; \
|
2000-06-12 21:36:41 +02:00
|
|
|
\
|
|
|
|
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 \
|
|
|
|
{ \
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Short A, B; \
|
2000-06-12 21:36:41 +02:00
|
|
|
\
|
|
|
|
\
|
2000-06-16 21:34:52 +02:00
|
|
|
A = (FT_Short)( CUR.opcode & 1 ) << 14; \
|
|
|
|
B = A ^ (FT_Short)0x4000; \
|
2000-06-12 21:36:41 +02:00
|
|
|
\
|
|
|
|
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 \
|
|
|
|
{ \
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Short A, B; \
|
2000-06-12 21:36:41 +02:00
|
|
|
\
|
|
|
|
\
|
2000-06-16 21:34:52 +02:00
|
|
|
A = (FT_Short)( CUR.opcode & 1 ) << 14; \
|
|
|
|
B = A ^ (FT_Short)0x4000; \
|
2000-06-12 21:36:41 +02:00
|
|
|
\
|
|
|
|
CUR.GS.freeVector.x = A; \
|
|
|
|
CUR.GS.freeVector.y = B; \
|
|
|
|
\
|
|
|
|
COMPUTE_Funcs(); \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_SPVTL \
|
2000-06-16 21:34:52 +02:00
|
|
|
if ( INS_SxVTL( (FT_UShort)args[1], \
|
|
|
|
(FT_UShort)args[0], \
|
2000-06-12 21:36:41 +02:00
|
|
|
CUR.opcode, \
|
|
|
|
&CUR.GS.projVector ) == SUCCESS ) \
|
|
|
|
{ \
|
|
|
|
CUR.GS.dualVector = CUR.GS.projVector; \
|
|
|
|
COMPUTE_Funcs(); \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_SFVTL \
|
2000-06-16 21:34:52 +02:00
|
|
|
if ( INS_SxVTL( (FT_UShort)args[1], \
|
|
|
|
(FT_UShort)args[0], \
|
2000-06-12 21:36:41 +02:00
|
|
|
CUR.opcode, \
|
|
|
|
&CUR.GS.freeVector ) == SUCCESS ) \
|
1999-12-17 00:11:37 +01:00
|
|
|
COMPUTE_Funcs();
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_SFVTPV \
|
|
|
|
CUR.GS.freeVector = CUR.GS.projVector; \
|
|
|
|
COMPUTE_Funcs();
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_SPVFS \
|
|
|
|
{ \
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Short S; \
|
|
|
|
FT_Long X, Y; \
|
1999-12-17 00:11:37 +01:00
|
|
|
\
|
|
|
|
\
|
|
|
|
/* Only use low 16bits, then sign extend */ \
|
2000-06-16 21:34:52 +02:00
|
|
|
S = (FT_Short)args[1]; \
|
|
|
|
Y = (FT_Long)S; \
|
|
|
|
S = (FT_Short)args[0]; \
|
|
|
|
X = (FT_Long)S; \
|
1999-12-17 00:11:37 +01:00
|
|
|
\
|
|
|
|
NORMalize( X, Y, &CUR.GS.projVector ); \
|
|
|
|
\
|
|
|
|
CUR.GS.dualVector = CUR.GS.projVector; \
|
|
|
|
COMPUTE_Funcs(); \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_SFVFS \
|
|
|
|
{ \
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Short S; \
|
|
|
|
FT_Long X, Y; \
|
1999-12-17 00:11:37 +01:00
|
|
|
\
|
|
|
|
\
|
|
|
|
/* Only use low 16bits, then sign extend */ \
|
2000-06-16 21:34:52 +02:00
|
|
|
S = (FT_Short)args[1]; \
|
|
|
|
Y = (FT_Long)S; \
|
|
|
|
S = (FT_Short)args[0]; \
|
1999-12-17 00:11:37 +01:00
|
|
|
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;
|
|
|
|
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#define DO_SRP0 \
|
2000-06-16 21:34:52 +02:00
|
|
|
CUR.GS.rp0 = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#define DO_SRP1 \
|
2000-06-16 21:34:52 +02:00
|
|
|
CUR.GS.rp1 = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#define DO_SRP2 \
|
2000-06-16 21:34:52 +02:00
|
|
|
CUR.GS.rp2 = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
#define DO_RTHG \
|
|
|
|
CUR.GS.round_state = TT_Round_To_Half_Grid; \
|
|
|
|
CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_RTG \
|
|
|
|
CUR.GS.round_state = TT_Round_To_Grid; \
|
|
|
|
CUR.func_round = (TT_Round_Func)Round_To_Grid;
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_RTDG \
|
|
|
|
CUR.GS.round_state = TT_Round_To_Double_Grid; \
|
|
|
|
CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_RUTG \
|
|
|
|
CUR.GS.round_state = TT_Round_Up_To_Grid; \
|
|
|
|
CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_RDTG \
|
|
|
|
CUR.GS.round_state = TT_Round_Down_To_Grid; \
|
|
|
|
CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_ROFF \
|
|
|
|
CUR.GS.round_state = TT_Round_Off; \
|
|
|
|
CUR.func_round = (TT_Round_Func)Round_None;
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_SROUND \
|
|
|
|
SET_SuperRound( 0x4000, args[0] ); \
|
|
|
|
CUR.GS.round_state = TT_Round_Super; \
|
|
|
|
CUR.func_round = (TT_Round_Func)Round_Super;
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_S45ROUND \
|
|
|
|
SET_SuperRound( 0x2D41, args[0] ); \
|
|
|
|
CUR.GS.round_state = TT_Round_Super_45; \
|
|
|
|
CUR.func_round = (TT_Round_Func)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 = args[0];
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_SCVTCI \
|
2000-06-16 21:34:52 +02:00
|
|
|
CUR.GS.control_value_cutin = (FT_F26Dot6)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
#define DO_SSWCI \
|
2000-06-16 21:34:52 +02:00
|
|
|
CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
/* 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 */
|
2000-07-02 15:53:16 +02:00
|
|
|
/* units. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
2000-06-12 21:36:41 +02:00
|
|
|
#define DO_SSW \
|
2000-06-16 21:34:52 +02:00
|
|
|
CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
#define DO_FLIPON \
|
|
|
|
CUR.GS.auto_flip = TRUE;
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_FLIPOFF \
|
|
|
|
CUR.GS.auto_flip = FALSE;
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_SDB \
|
2000-06-16 21:34:52 +02:00
|
|
|
CUR.GS.delta_base = (FT_Short)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
#define DO_SDS \
|
2000-06-16 21:34:52 +02:00
|
|
|
CUR.GS.delta_shift = (FT_Short)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
#define DO_MD /* nothing */
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_MPPEM \
|
|
|
|
args[0] = CURRENT_Ppem();
|
|
|
|
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
/* Note: The pointSize should be irrelevant in a given font program; */
|
|
|
|
/* we thus decide to return only the ppem. */
|
1999-12-17 00:11:37 +01:00
|
|
|
#if 0
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
#define DO_MPS \
|
|
|
|
args[0] = CUR.metrics.pointSize;
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
#else
|
2000-06-12 21:36:41 +02:00
|
|
|
|
|
|
|
#define DO_MPS \
|
1999-12-17 00:11:37 +01:00
|
|
|
args[0] = CURRENT_Ppem();
|
2000-06-12 21:36:41 +02:00
|
|
|
|
|
|
|
#endif /* 0 */
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
#define DO_DUP \
|
|
|
|
args[1] = args[0];
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_CLEAR \
|
|
|
|
CUR.new_top = 0;
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_SWAP \
|
|
|
|
{ \
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Long L; \
|
1999-12-17 00:11:37 +01:00
|
|
|
\
|
2000-06-12 21:36:41 +02:00
|
|
|
\
|
1999-12-17 00:11:37 +01:00
|
|
|
L = args[0]; \
|
|
|
|
args[0] = args[1]; \
|
|
|
|
args[1] = L; \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_DEPTH \
|
|
|
|
args[0] = CUR.top;
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_CINDEX \
|
|
|
|
{ \
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Long L; \
|
1999-12-17 00:11:37 +01:00
|
|
|
\
|
|
|
|
\
|
|
|
|
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; \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#define DO_LT \
|
|
|
|
args[0] = ( args[0] < args[1] );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#define DO_LTEQ \
|
|
|
|
args[0] = ( args[0] <= args[1] );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#define DO_GT \
|
|
|
|
args[0] = ( args[0] > args[1] );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#define DO_GTEQ \
|
|
|
|
args[0] = ( args[0] >= args[1] );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#define DO_EQ \
|
|
|
|
args[0] = ( args[0] == args[1] );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#define DO_NEQ \
|
|
|
|
args[0] = ( args[0] != args[1] );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#define DO_ODD \
|
|
|
|
args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#define DO_EVEN \
|
|
|
|
args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
#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 \
|
2000-06-12 21:36:41 +02:00
|
|
|
args[0] = ( args[0] + 63 ) & -64;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
#define DO_RS \
|
|
|
|
{ \
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong I = (FT_ULong)args[0]; \
|
1999-12-17 00:11:37 +01:00
|
|
|
\
|
|
|
|
\
|
|
|
|
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 \
|
|
|
|
{ \
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong I = (FT_ULong)args[0]; \
|
1999-12-17 00:11:37 +01:00
|
|
|
\
|
|
|
|
\
|
|
|
|
if ( BOUNDS( I, CUR.storeSize ) ) \
|
|
|
|
{ \
|
|
|
|
if ( CUR.pedantic_hinting ) \
|
|
|
|
{ \
|
|
|
|
ARRAY_BOUND_ERROR; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
else \
|
|
|
|
CUR.storage[I] = args[1]; \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#define DO_RCVT \
|
|
|
|
{ \
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong I = (FT_ULong)args[0]; \
|
2000-06-12 21:36:41 +02:00
|
|
|
\
|
|
|
|
\
|
|
|
|
if ( BOUNDS( I, CUR.cvtSize ) ) \
|
|
|
|
{ \
|
|
|
|
if ( CUR.pedantic_hinting ) \
|
|
|
|
{ \
|
|
|
|
ARRAY_BOUND_ERROR; \
|
|
|
|
} \
|
|
|
|
else \
|
|
|
|
args[0] = 0; \
|
|
|
|
} \
|
|
|
|
else \
|
|
|
|
args[0] = CUR_Func_read_cvt( I ); \
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_WCVTP \
|
|
|
|
{ \
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong I = (FT_ULong)args[0]; \
|
1999-12-17 00:11:37 +01:00
|
|
|
\
|
|
|
|
\
|
|
|
|
if ( BOUNDS( I, CUR.cvtSize ) ) \
|
|
|
|
{ \
|
|
|
|
if ( CUR.pedantic_hinting ) \
|
|
|
|
{ \
|
|
|
|
ARRAY_BOUND_ERROR; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
else \
|
|
|
|
CUR_Func_write_cvt( I, args[1] ); \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_WCVTF \
|
|
|
|
{ \
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong I = (FT_ULong)args[0]; \
|
1999-12-17 00:11:37 +01:00
|
|
|
\
|
|
|
|
\
|
|
|
|
if ( BOUNDS( I, CUR.cvtSize ) ) \
|
|
|
|
{ \
|
|
|
|
if ( CUR.pedantic_hinting ) \
|
|
|
|
{ \
|
|
|
|
ARRAY_BOUND_ERROR; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
else \
|
|
|
|
CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_DEBUG \
|
|
|
|
CUR.error = TT_Err_Debug_OpCode;
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_ROUND \
|
|
|
|
args[0] = CUR_Func_round( \
|
|
|
|
args[0], \
|
|
|
|
CUR.tt_metrics.compensations[CUR.opcode - 0x68] );
|
|
|
|
|
|
|
|
|
|
|
|
#define DO_NROUND \
|
|
|
|
args[0] = ROUND_None( args[0], \
|
|
|
|
CUR.tt_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
|
2000-06-12 21:36:41 +02:00
|
|
|
#define ARRAY_BOUND_ERROR \
|
|
|
|
{ \
|
|
|
|
CUR.error = TT_Err_Invalid_Reference; \
|
|
|
|
return; \
|
|
|
|
}
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SVTCA[a]: Set (F and P) Vectors to Coordinate Axis */
|
|
|
|
/* Opcode range: 0x00-0x01 */
|
|
|
|
/* Stack: --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SVTCA( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SVTCA
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SPVTCA[a]: Set PVector to Coordinate Axis */
|
|
|
|
/* Opcode range: 0x02-0x03 */
|
|
|
|
/* Stack: --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SPVTCA( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SPVTCA
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SFVTCA[a]: Set FVector to Coordinate Axis */
|
|
|
|
/* Opcode range: 0x04-0x05 */
|
|
|
|
/* Stack: --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SFVTCA( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SFVTCA
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SPVTL[a]: Set PVector To Line */
|
|
|
|
/* Opcode range: 0x06-0x07 */
|
|
|
|
/* Stack: uint32 uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SPVTL( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SPVTL
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SFVTL[a]: Set FVector To Line */
|
|
|
|
/* Opcode range: 0x08-0x09 */
|
|
|
|
/* Stack: uint32 uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SFVTL( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SFVTL
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SFVTPV[]: Set FVector To PVector */
|
|
|
|
/* Opcode range: 0x0E */
|
|
|
|
/* Stack: --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SFVTPV( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SFVTPV
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SPVFS[]: Set PVector From Stack */
|
|
|
|
/* Opcode range: 0x0A */
|
|
|
|
/* Stack: f2.14 f2.14 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SPVFS( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SPVFS
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SFVFS[]: Set FVector From Stack */
|
|
|
|
/* Opcode range: 0x0B */
|
|
|
|
/* Stack: f2.14 f2.14 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SFVFS( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SFVFS
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* GPV[]: Get Projection Vector */
|
|
|
|
/* Opcode range: 0x0C */
|
|
|
|
/* Stack: ef2.14 --> ef2.14 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_GPV( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_GPV
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* GFV[]: Get Freedom Vector */
|
|
|
|
/* Opcode range: 0x0D */
|
|
|
|
/* Stack: ef2.14 --> ef2.14 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_GFV( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_GFV
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SRP0[]: Set Reference Point 0 */
|
|
|
|
/* Opcode range: 0x10 */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SRP0( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SRP0
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SRP1[]: Set Reference Point 1 */
|
|
|
|
/* Opcode range: 0x11 */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SRP1( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SRP1
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SRP2[]: Set Reference Point 2 */
|
|
|
|
/* Opcode range: 0x12 */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SRP2( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SRP2
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* RTHG[]: Round To Half Grid */
|
|
|
|
/* Opcode range: 0x19 */
|
|
|
|
/* Stack: --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_RTHG( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_RTHG
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* RTG[]: Round To Grid */
|
|
|
|
/* Opcode range: 0x18 */
|
|
|
|
/* Stack: --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_RTG( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_RTG
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* RTDG[]: Round To Double Grid */
|
|
|
|
/* Opcode range: 0x3D */
|
|
|
|
/* Stack: --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_RTDG( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_RTDG
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* RUTG[]: Round Up To Grid */
|
|
|
|
/* Opcode range: 0x7C */
|
|
|
|
/* Stack: --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_RUTG( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_RUTG
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* RDTG[]: Round Down To Grid */
|
|
|
|
/* Opcode range: 0x7D */
|
|
|
|
/* Stack: --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_RDTG( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_RDTG
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* ROFF[]: Round OFF */
|
|
|
|
/* Opcode range: 0x7A */
|
|
|
|
/* Stack: --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_ROFF( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_ROFF
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SROUND[]: Super ROUND */
|
|
|
|
/* Opcode range: 0x76 */
|
|
|
|
/* Stack: Eint8 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SROUND( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SROUND
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* S45ROUND[]: Super ROUND 45 degrees */
|
|
|
|
/* Opcode range: 0x77 */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_S45ROUND( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_S45ROUND
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SLOOP[]: Set LOOP variable */
|
|
|
|
/* Opcode range: 0x17 */
|
|
|
|
/* Stack: int32? --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SLOOP( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SLOOP
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SMD[]: Set Minimum Distance */
|
|
|
|
/* Opcode range: 0x1A */
|
|
|
|
/* Stack: f26.6 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SMD( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SMD
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SCVTCI[]: Set Control Value Table Cut In */
|
|
|
|
/* Opcode range: 0x1D */
|
|
|
|
/* Stack: f26.6 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SCVTCI( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SCVTCI
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SSWCI[]: Set Single Width Cut In */
|
|
|
|
/* Opcode range: 0x1E */
|
|
|
|
/* Stack: f26.6 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SSWCI( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SSWCI
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SSW[]: Set Single Width */
|
|
|
|
/* Opcode range: 0x1F */
|
|
|
|
/* Stack: int32? --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SSW( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SSW
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* FLIPON[]: Set auto-FLIP to ON */
|
|
|
|
/* Opcode range: 0x4D */
|
|
|
|
/* Stack: --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_FLIPON( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_FLIPON
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* FLIPOFF[]: Set auto-FLIP to OFF */
|
|
|
|
/* Opcode range: 0x4E */
|
|
|
|
/* Stack: --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_FLIPOFF( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_FLIPOFF
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SANGW[]: Set ANGle Weight */
|
|
|
|
/* Opcode range: 0x7E */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SANGW( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
/* instruction not supported anymore */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SDB[]: Set Delta Base */
|
|
|
|
/* Opcode range: 0x5E */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SDB( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SDB
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SDS[]: Set Delta Shift */
|
|
|
|
/* Opcode range: 0x5F */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SDS( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SDS
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* MPPEM[]: Measure Pixel Per EM */
|
|
|
|
/* Opcode range: 0x4B */
|
|
|
|
/* Stack: --> Euint16 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_MPPEM( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_MPPEM
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* MPS[]: Measure Point Size */
|
|
|
|
/* Opcode range: 0x4C */
|
|
|
|
/* Stack: --> Euint16 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_MPS( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_MPS
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* DUP[]: DUPlicate the top stack's element */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* Opcode range: 0x20 */
|
|
|
|
/* Stack: StkElt --> StkElt StkElt */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_DUP( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_DUP
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* POP[]: POP the stack's top element */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* Opcode range: 0x21 */
|
|
|
|
/* Stack: StkElt --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_POP( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
/* nothing to do */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* CLEAR[]: CLEAR the entire stack */
|
|
|
|
/* Opcode range: 0x22 */
|
|
|
|
/* Stack: StkElt... --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_CLEAR( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_CLEAR
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* SWAP[]: SWAP the stack's top two elements */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* Opcode range: 0x23 */
|
|
|
|
/* Stack: 2 * StkElt --> 2 * StkElt */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SWAP( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SWAP
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* DEPTH[]: return the stack DEPTH */
|
|
|
|
/* Opcode range: 0x24 */
|
|
|
|
/* Stack: --> uint32 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_DEPTH( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_DEPTH
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* CINDEX[]: Copy INDEXed element */
|
|
|
|
/* Opcode range: 0x25 */
|
|
|
|
/* Stack: int32 --> StkElt */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_CINDEX( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_CINDEX
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* EIF[]: End IF */
|
|
|
|
/* Opcode range: 0x59 */
|
|
|
|
/* Stack: --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_EIF( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
/* nothing to do */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* JROT[]: Jump Relative On True */
|
|
|
|
/* Opcode range: 0x78 */
|
|
|
|
/* Stack: StkElt int32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_JROT( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_JROT
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* JMPR[]: JuMP Relative */
|
|
|
|
/* Opcode range: 0x1C */
|
|
|
|
/* Stack: int32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_JMPR( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_JMPR
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* JROF[]: Jump Relative On False */
|
|
|
|
/* Opcode range: 0x79 */
|
|
|
|
/* Stack: StkElt int32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_JROF( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_JROF
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* LT[]: Less Than */
|
|
|
|
/* Opcode range: 0x50 */
|
|
|
|
/* Stack: int32? int32? --> bool */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_LT( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_LT
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* LTEQ[]: Less Than or EQual */
|
|
|
|
/* Opcode range: 0x51 */
|
|
|
|
/* Stack: int32? int32? --> bool */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_LTEQ( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_LTEQ
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* GT[]: Greater Than */
|
|
|
|
/* Opcode range: 0x52 */
|
|
|
|
/* Stack: int32? int32? --> bool */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_GT( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_GT
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* GTEQ[]: Greater Than or EQual */
|
|
|
|
/* Opcode range: 0x53 */
|
|
|
|
/* Stack: int32? int32? --> bool */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_GTEQ( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_GTEQ
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* EQ[]: EQual */
|
|
|
|
/* Opcode range: 0x54 */
|
|
|
|
/* Stack: StkElt StkElt --> bool */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_EQ( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_EQ
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* NEQ[]: Not EQual */
|
|
|
|
/* Opcode range: 0x55 */
|
|
|
|
/* Stack: StkElt StkElt --> bool */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_NEQ( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_NEQ
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* ODD[]: Is ODD */
|
|
|
|
/* Opcode range: 0x56 */
|
|
|
|
/* Stack: f26.6 --> bool */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_ODD( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_ODD
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* EVEN[]: Is EVEN */
|
|
|
|
/* Opcode range: 0x57 */
|
|
|
|
/* Stack: f26.6 --> bool */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_EVEN( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_EVEN
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* AND[]: logical AND */
|
|
|
|
/* Opcode range: 0x5A */
|
|
|
|
/* Stack: uint32 uint32 --> uint32 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_AND( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_AND
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* OR[]: logical OR */
|
|
|
|
/* Opcode range: 0x5B */
|
|
|
|
/* Stack: uint32 uint32 --> uint32 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_OR( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_OR
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* NOT[]: logical NOT */
|
|
|
|
/* Opcode range: 0x5C */
|
|
|
|
/* Stack: StkElt --> uint32 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_NOT( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_NOT
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* ADD[]: ADD */
|
|
|
|
/* Opcode range: 0x60 */
|
|
|
|
/* Stack: f26.6 f26.6 --> f26.6 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_ADD( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_ADD
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SUB[]: SUBtract */
|
|
|
|
/* Opcode range: 0x61 */
|
|
|
|
/* Stack: f26.6 f26.6 --> f26.6 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SUB( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_SUB
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* DIV[]: DIVide */
|
|
|
|
/* Opcode range: 0x62 */
|
|
|
|
/* Stack: f26.6 f26.6 --> f26.6 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_DIV( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_DIV
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* MUL[]: MULtiply */
|
|
|
|
/* Opcode range: 0x63 */
|
|
|
|
/* Stack: f26.6 f26.6 --> f26.6 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_MUL( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_MUL
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* ABS[]: ABSolute value */
|
|
|
|
/* Opcode range: 0x64 */
|
|
|
|
/* Stack: f26.6 --> f26.6 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_ABS( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_ABS
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* NEG[]: NEGate */
|
|
|
|
/* Opcode range: 0x65 */
|
|
|
|
/* Stack: f26.6 --> f26.6 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_NEG( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_NEG
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* FLOOR[]: FLOOR */
|
|
|
|
/* Opcode range: 0x66 */
|
|
|
|
/* Stack: f26.6 --> f26.6 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_FLOOR( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_FLOOR
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* CEILING[]: CEILING */
|
|
|
|
/* Opcode range: 0x67 */
|
|
|
|
/* Stack: f26.6 --> f26.6 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_CEILING( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_CEILING
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* RS[]: Read Store */
|
|
|
|
/* Opcode range: 0x43 */
|
|
|
|
/* Stack: uint32 --> uint32 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_RS( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_RS
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* WS[]: Write Store */
|
|
|
|
/* Opcode range: 0x42 */
|
|
|
|
/* Stack: uint32 uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_WS( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_WS
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* WCVTP[]: Write CVT in Pixel units */
|
|
|
|
/* Opcode range: 0x44 */
|
|
|
|
/* Stack: f26.6 uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_WCVTP( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_WCVTP
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* WCVTF[]: Write CVT in Funits */
|
|
|
|
/* Opcode range: 0x70 */
|
|
|
|
/* Stack: uint32 uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_WCVTF( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_WCVTF
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* RCVT[]: Read CVT */
|
|
|
|
/* Opcode range: 0x45 */
|
|
|
|
/* Stack: uint32 --> f26.6 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_RCVT( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_RCVT
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* AA[]: Adjust Angle */
|
|
|
|
/* Opcode range: 0x7F */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_AA( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-07-02 15:53:16 +02:00
|
|
|
/* intentionally no longer supported */
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* DEBUG[]: DEBUG. Unsupported. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* Opcode range: 0x4F */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* Note: The original instruction pops a value from the stack. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_DEBUG( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_DEBUG
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* ROUND[ab]: ROUND value */
|
|
|
|
/* Opcode range: 0x68-0x6B */
|
|
|
|
/* Stack: f26.6 --> f26.6 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_ROUND( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_ROUND
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* NROUND[ab]: No ROUNDing of value */
|
|
|
|
/* Opcode range: 0x6C-0x6F */
|
|
|
|
/* Stack: f26.6 --> f26.6 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_NROUND( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_NROUND
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* MAX[]: MAXimum */
|
|
|
|
/* Opcode range: 0x68 */
|
|
|
|
/* Stack: int32? int32? --> int32 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_MAX( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_MAX
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* MIN[]: MINimum */
|
|
|
|
/* Opcode range: 0x69 */
|
|
|
|
/* Stack: int32? int32? --> int32 */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_MIN( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
DO_MIN
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* The following functions are called as is within the switch statement. */
|
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* MINDEX[]: Move INDEXed element */
|
|
|
|
/* Opcode range: 0x26 */
|
|
|
|
/* Stack: int32? --> StkElt */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_MINDEX( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Long L, K;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
L = args[0];
|
|
|
|
|
|
|
|
if ( L <= 0 || L > CUR.args )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Invalid_Reference;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
K = CUR.stack[CUR.args - L];
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
MEM_Move( &CUR.stack[CUR.args - L ],
|
|
|
|
&CUR.stack[CUR.args - L + 1],
|
2000-06-16 21:34:52 +02:00
|
|
|
( L - 1 ) * sizeof ( FT_Long ) );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
CUR.stack[CUR.args - 1] = K;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* ROLL[]: ROLL top three elements */
|
|
|
|
/* Opcode range: 0x8A */
|
|
|
|
/* Stack: 3 * StkElt --> 3 * StkElt */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_ROLL( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Long A, B, C;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_EXEC;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
A = args[2];
|
|
|
|
B = args[1];
|
|
|
|
C = args[0];
|
|
|
|
|
|
|
|
args[2] = C;
|
|
|
|
args[1] = A;
|
|
|
|
args[0] = B;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* MANAGING THE FLOW OF CONTROL */
|
|
|
|
/* */
|
2000-07-02 15:53:16 +02:00
|
|
|
/* Instructions appear in the specification's order. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_Bool
|
|
|
|
SkipCode( EXEC_OP )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
CUR.IP += CUR.length;
|
|
|
|
|
|
|
|
if ( CUR.IP < CUR.codeSize )
|
|
|
|
{
|
|
|
|
CUR.opcode = CUR.code[CUR.IP];
|
|
|
|
|
|
|
|
CUR.length = opcode_length[CUR.opcode];
|
|
|
|
if ( CUR.length < 0 )
|
|
|
|
{
|
|
|
|
if ( CUR.IP + 1 > CUR.codeSize )
|
|
|
|
goto Fail_Overflow;
|
|
|
|
CUR.length = CUR.code[CUR.IP + 1] + 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( CUR.IP + CUR.length <= CUR.codeSize )
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
Fail_Overflow:
|
|
|
|
CUR.error = TT_Err_Code_Overflow;
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* IF[]: IF test */
|
|
|
|
/* Opcode range: 0x58 */
|
|
|
|
/* Stack: StkElt --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_IF( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Int nIfs;
|
|
|
|
FT_Bool Out;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
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 */
|
2001-07-07 18:12:14 +02:00
|
|
|
Out = FT_BOOL( nIfs == 1 );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x59: /* EIF */
|
|
|
|
nIfs--;
|
2001-07-07 18:12:14 +02:00
|
|
|
Out = FT_BOOL( nIfs == 0 );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while ( Out == 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* ELSE[]: ELSE */
|
|
|
|
/* Opcode range: 0x1B */
|
|
|
|
/* Stack: --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_ELSE( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Int nIfs;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_ARG;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
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 */
|
|
|
|
/* */
|
2000-07-02 15:53:16 +02:00
|
|
|
/* Instructions appear in the specification's order. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* FDEF[]: Function DEFinition */
|
|
|
|
/* Opcode range: 0x2C */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_FDEF( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong n;
|
1999-12-17 00:11:37 +01:00
|
|
|
TT_DefRecord* rec;
|
|
|
|
TT_DefRecord* limit;
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* some font programs are broken enough to redefine functions! */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* We will then parse the current table. */
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
rec = CUR.FDefs;
|
|
|
|
limit = rec + CUR.numFDefs;
|
|
|
|
n = args[0];
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
for ( ; rec < limit; rec++ )
|
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( rec->opc == n )
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
}
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( rec == limit )
|
|
|
|
{
|
|
|
|
/* check that there is enough room for new functions */
|
|
|
|
if ( CUR.numFDefs >= CUR.maxFDefs )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Too_Many_Function_Defs;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
CUR.numFDefs++;
|
|
|
|
}
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
rec->range = CUR.curRange;
|
|
|
|
rec->opc = n;
|
2000-06-12 21:36:41 +02:00
|
|
|
rec->start = CUR.IP + 1;
|
1999-12-17 00:11:37 +01:00
|
|
|
rec->active = TRUE;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( n > CUR.maxFunc )
|
|
|
|
CUR.maxFunc = n;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* Now skip the whole function definition. */
|
|
|
|
/* We don't allow nested IDEFS & FDEFs. */
|
|
|
|
|
|
|
|
while ( SKIP_Code() == SUCCESS )
|
|
|
|
{
|
|
|
|
switch ( CUR.opcode )
|
|
|
|
{
|
|
|
|
case 0x89: /* IDEF */
|
|
|
|
case 0x2C: /* FDEF */
|
|
|
|
CUR.error = TT_Err_Nested_DEFS;
|
|
|
|
return;
|
|
|
|
|
|
|
|
case 0x2D: /* ENDF */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* ENDF[]: END Function definition */
|
|
|
|
/* Opcode range: 0x2D */
|
|
|
|
/* Stack: --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_ENDF( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
TT_CallRec* pRec;
|
|
|
|
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_ARG;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
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 );
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
/* Exit the current call frame. */
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
/* NOTE: If 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 is why we do not test */
|
|
|
|
/* the result of Ins_Goto_CodeRange() here! */
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* CALL[]: CALL function */
|
|
|
|
/* Opcode range: 0x2B */
|
|
|
|
/* Stack: uint32? --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_CALL( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong F;
|
1999-12-17 00:11:37 +01:00
|
|
|
TT_CallRec* pCrec;
|
|
|
|
TT_DefRecord* def;
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* first of all, check the index */
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
F = args[0];
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( BOUNDS( F, CUR.maxFunc + 1 ) )
|
|
|
|
goto Fail;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* Except for some old Apple fonts, all functions in a TrueType */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* font are defined in increasing order, starting from 0. This */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* means that we normally have */
|
|
|
|
/* */
|
|
|
|
/* CUR.maxFunc+1 == CUR.numFDefs */
|
|
|
|
/* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */
|
|
|
|
/* */
|
|
|
|
/* If this isn't true, we need to look up the function table. */
|
|
|
|
|
|
|
|
def = CUR.FDefs + F;
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
/* look up the FDefs table */
|
|
|
|
TT_DefRecord* limit;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
def = CUR.FDefs;
|
|
|
|
limit = def + CUR.numFDefs;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
while ( def < limit && def->opc != F )
|
1999-12-17 00:11:37 +01:00
|
|
|
def++;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( def == limit )
|
|
|
|
goto Fail;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* check that the function is active */
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( !def->active )
|
1999-12-17 00:11:37 +01:00
|
|
|
goto Fail;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* check the call stack */
|
|
|
|
if ( CUR.callTop >= CUR.callSize )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Stack_Overflow;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pCrec = CUR.callStack + CUR.callTop;
|
|
|
|
|
|
|
|
pCrec->Caller_Range = CUR.curRange;
|
|
|
|
pCrec->Caller_IP = CUR.IP + 1;
|
|
|
|
pCrec->Cur_Count = 1;
|
|
|
|
pCrec->Cur_Restart = def->start;
|
|
|
|
|
|
|
|
CUR.callTop++;
|
|
|
|
|
|
|
|
INS_Goto_CodeRange( def->range,
|
|
|
|
def->start );
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
CUR.step_ins = FALSE;
|
|
|
|
return;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
Fail:
|
|
|
|
CUR.error = TT_Err_Invalid_Reference;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* LOOPCALL[]: LOOP and CALL function */
|
|
|
|
/* Opcode range: 0x2A */
|
|
|
|
/* Stack: uint32? Eint16? --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_LOOPCALL( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong F;
|
1999-12-17 00:11:37 +01:00
|
|
|
TT_CallRec* pCrec;
|
|
|
|
TT_DefRecord* def;
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* first of all, check the index */
|
|
|
|
F = args[1];
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( BOUNDS( F, CUR.maxFunc + 1 ) )
|
|
|
|
goto Fail;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* Except for some old Apple fonts, all functions in a TrueType */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* font are defined in increasing order, starting from 0. This */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* means that we normally have */
|
|
|
|
/* */
|
|
|
|
/* CUR.maxFunc+1 == CUR.numFDefs */
|
|
|
|
/* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */
|
|
|
|
/* */
|
|
|
|
/* If this isn't true, we need to look up the function table. */
|
|
|
|
|
|
|
|
def = CUR.FDefs + F;
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
/* look up the FDefs table */
|
|
|
|
TT_DefRecord* limit;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
def = CUR.FDefs;
|
|
|
|
limit = def + CUR.numFDefs;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
while ( def < limit && def->opc != F )
|
1999-12-17 00:11:37 +01:00
|
|
|
def++;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( def == limit )
|
|
|
|
goto Fail;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* check that the function is active */
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( !def->active )
|
1999-12-17 00:11:37 +01:00
|
|
|
goto Fail;
|
|
|
|
|
2000-05-17 01:44:38 +02:00
|
|
|
/* check stack */
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( CUR.callTop >= CUR.callSize )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Stack_Overflow;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( args[0] > 0 )
|
|
|
|
{
|
|
|
|
pCrec = CUR.callStack + CUR.callTop;
|
|
|
|
|
|
|
|
pCrec->Caller_Range = CUR.curRange;
|
|
|
|
pCrec->Caller_IP = CUR.IP + 1;
|
2000-06-16 21:34:52 +02:00
|
|
|
pCrec->Cur_Count = (FT_Int)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
pCrec->Cur_Restart = def->start;
|
|
|
|
|
|
|
|
CUR.callTop++;
|
|
|
|
|
|
|
|
INS_Goto_CodeRange( def->range, def->start );
|
|
|
|
|
|
|
|
CUR.step_ins = FALSE;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
|
|
|
|
Fail:
|
|
|
|
CUR.error = TT_Err_Invalid_Reference;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* IDEF[]: Instruction DEFinition */
|
|
|
|
/* Opcode range: 0x89 */
|
|
|
|
/* Stack: Eint8 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_IDEF( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
TT_DefRecord* def;
|
|
|
|
TT_DefRecord* limit;
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* First of all, look for the same function in our table */
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
def = CUR.IDefs;
|
|
|
|
limit = def + CUR.numIDefs;
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
for ( ; def < limit; def++ )
|
2000-06-16 21:34:52 +02:00
|
|
|
if ( def->opc == (FT_ULong)args[0] )
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( def == limit )
|
|
|
|
{
|
|
|
|
/* check that there is enough room for a new instruction */
|
|
|
|
if ( CUR.numIDefs >= CUR.maxIDefs )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Too_Many_Instruction_Defs;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
CUR.numIDefs++;
|
|
|
|
}
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
def->opc = args[0];
|
|
|
|
def->start = CUR.IP+1;
|
|
|
|
def->range = CUR.curRange;
|
|
|
|
def->active = TRUE;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
if ( (FT_ULong)args[0] > CUR.maxIns )
|
1999-12-17 00:11:37 +01:00
|
|
|
CUR.maxIns = args[0];
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* 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 */
|
|
|
|
/* */
|
2000-07-02 15:53:16 +02:00
|
|
|
/* Instructions appear in the specification's order. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* NPUSHB[]: PUSH N Bytes */
|
|
|
|
/* Opcode range: 0x40 */
|
|
|
|
/* Stack: --> uint32... */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_NPUSHB( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort L, K;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
L = (FT_UShort)CUR.code[CUR.IP + 1];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Stack_Overflow;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( K = 1; K <= L; K++ )
|
|
|
|
args[K - 1] = CUR.code[CUR.IP + K + 1];
|
|
|
|
|
|
|
|
CUR.new_top += L;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* NPUSHW[]: PUSH N Words */
|
|
|
|
/* Opcode range: 0x41 */
|
|
|
|
/* Stack: --> int32... */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_NPUSHW( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort L, K;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
L = (FT_UShort)CUR.code[CUR.IP + 1];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Stack_Overflow;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CUR.IP += 2;
|
|
|
|
|
|
|
|
for ( K = 0; K < L; K++ )
|
|
|
|
args[K] = GET_ShortIns();
|
|
|
|
|
|
|
|
CUR.step_ins = FALSE;
|
|
|
|
CUR.new_top += L;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* PUSHB[abc]: PUSH Bytes */
|
|
|
|
/* Opcode range: 0xB0-0xB7 */
|
|
|
|
/* Stack: --> uint32... */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_PUSHB( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort L, K;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2001-07-07 18:12:14 +02:00
|
|
|
L = (FT_UShort)(CUR.opcode - 0xB0 + 1);
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Stack_Overflow;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( K = 1; K <= L; K++ )
|
|
|
|
args[K - 1] = CUR.code[CUR.IP + K];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* PUSHW[abc]: PUSH Words */
|
|
|
|
/* Opcode range: 0xB8-0xBF */
|
|
|
|
/* Stack: --> int32... */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_PUSHW( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort L, K;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2001-07-07 18:12:14 +02:00
|
|
|
L = (FT_UShort)(CUR.opcode - 0xB8 + 1);
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Stack_Overflow;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CUR.IP++;
|
|
|
|
|
|
|
|
for ( K = 0; K < L; K++ )
|
|
|
|
args[K] = GET_ShortIns();
|
|
|
|
|
|
|
|
CUR.step_ins = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* MANAGING THE GRAPHICS STATE */
|
|
|
|
/* */
|
|
|
|
/* Instructions appear in the specs' order. */
|
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* GC[a]: Get Coordinate projected onto */
|
|
|
|
/* Opcode range: 0x46-0x47 */
|
|
|
|
/* Stack: uint32 --> f26.6 */
|
|
|
|
/* */
|
|
|
|
/* BULLSHIT: Measures from the original glyph must be taken along the */
|
|
|
|
/* dual projection vector! */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_GC( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong L;
|
|
|
|
FT_F26Dot6 R;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
L = (FT_ULong)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
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 */
|
|
|
|
/* Opcode range: 0x48 */
|
|
|
|
/* Stack: f26.6 uint32 --> */
|
|
|
|
/* */
|
|
|
|
/* Formula: */
|
|
|
|
/* */
|
|
|
|
/* OA := OA + ( value - OA.p )/( f.p ) * f */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SCFS( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Long K;
|
|
|
|
FT_UShort L;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
L = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
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 */
|
|
|
|
/* Opcode range: 0x49-0x4A */
|
|
|
|
/* Stack: uint32 uint32 --> f26.6 */
|
|
|
|
/* */
|
|
|
|
/* BULLSHIT: Measure taken in the original glyph must be along the dual */
|
|
|
|
/* projection vector. */
|
|
|
|
/* */
|
|
|
|
/* Second BULLSHIT: Flag attributes are inverted! */
|
|
|
|
/* 0 => measure distance in original outline */
|
|
|
|
/* 1 => measure distance in grid-fitted outline */
|
|
|
|
/* */
|
|
|
|
/* Third one: `zp0 - zp1', and not `zp2 - zp1! */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_MD( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort K, L;
|
|
|
|
FT_F26Dot6 D;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
K = (FT_UShort)args[1];
|
|
|
|
L = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if( BOUNDS( L, CUR.zp0.n_points ) ||
|
|
|
|
BOUNDS( K, CUR.zp1.n_points ) )
|
|
|
|
{
|
|
|
|
if ( CUR.pedantic_hinting )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Invalid_Reference;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
D = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( CUR.opcode & 1 )
|
|
|
|
D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
|
|
|
|
else
|
|
|
|
D = CUR_Func_dualproj( CUR.zp0.org + L, CUR.zp1.org + K );
|
|
|
|
}
|
|
|
|
|
|
|
|
args[0] = D;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SDPVTL[a]: Set Dual PVector to Line */
|
|
|
|
/* Opcode range: 0x86-0x87 */
|
|
|
|
/* Stack: uint32 uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SDPVTL( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Long A, B, C;
|
|
|
|
FT_UShort p1, p2; /* was FT_Int in pas type ERROR */
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
p1 = (FT_UShort)args[1];
|
|
|
|
p2 = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( BOUNDS( p2, CUR.zp1.n_points ) ||
|
|
|
|
BOUNDS( p1, CUR.zp2.n_points ) )
|
|
|
|
{
|
|
|
|
if ( CUR.pedantic_hinting )
|
|
|
|
CUR.error = TT_Err_Invalid_Reference;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Vector* v1 = CUR.zp1.org + p2;
|
|
|
|
FT_Vector* v2 = CUR.zp2.org + p1;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
A = v1->x - v2->x;
|
|
|
|
B = v1->y - v2->y;
|
|
|
|
}
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( ( CUR.opcode & 1 ) != 0 )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
C = B; /* counter clockwise rotation */
|
1999-12-17 00:11:37 +01:00
|
|
|
B = A;
|
|
|
|
A = -C;
|
|
|
|
}
|
|
|
|
|
|
|
|
NORMalize( A, B, &CUR.GS.dualVector );
|
|
|
|
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Vector* v1 = CUR.zp1.cur + p2;
|
|
|
|
FT_Vector* v2 = CUR.zp2.cur + p1;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
A = v1->x - v2->x;
|
|
|
|
B = v1->y - v2->y;
|
|
|
|
}
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( ( CUR.opcode & 1 ) != 0 )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
C = B; /* counter clockwise rotation */
|
1999-12-17 00:11:37 +01:00
|
|
|
B = A;
|
|
|
|
A = -C;
|
|
|
|
}
|
|
|
|
|
|
|
|
NORMalize( A, B, &CUR.GS.projVector );
|
|
|
|
|
|
|
|
COMPUTE_Funcs();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SZP0[]: Set Zone Pointer 0 */
|
|
|
|
/* Opcode range: 0x13 */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SZP0( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
switch ( (FT_Int)args[0] )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
CUR.GS.gep0 = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SZP1[]: Set Zone Pointer 1 */
|
|
|
|
/* Opcode range: 0x14 */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SZP1( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
switch ( (FT_Int)args[0] )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
CUR.GS.gep1 = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SZP2[]: Set Zone Pointer 2 */
|
|
|
|
/* Opcode range: 0x15 */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SZP2( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
switch ( (FT_Int)args[0] )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
CUR.GS.gep2 = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SZPS[]: Set Zone PointerS */
|
|
|
|
/* Opcode range: 0x16 */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SZPS( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
switch ( (FT_Int)args[0] )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
CUR.GS.gep0 = (FT_UShort)args[0];
|
|
|
|
CUR.GS.gep1 = (FT_UShort)args[0];
|
|
|
|
CUR.GS.gep2 = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* INSTCTRL[]: INSTruction ConTRoL */
|
|
|
|
/* Opcode range: 0x8e */
|
|
|
|
/* Stack: int32 int32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_INSTCTRL( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Long K, L;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2001-07-07 18:12:14 +02:00
|
|
|
CUR.GS.instruct_control = FT_BOOL(
|
|
|
|
( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SCANCTRL[]: SCAN ConTRoL */
|
|
|
|
/* Opcode range: 0x85 */
|
|
|
|
/* Stack: uint32? --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SCANCTRL( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Int A;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
/* Get Threshold */
|
2000-06-16 21:34:52 +02:00
|
|
|
A = (FT_Int)( args[0] & 0xFF );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( A == 0xFF )
|
|
|
|
{
|
|
|
|
CUR.GS.scan_control = TRUE;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if ( A == 0 )
|
|
|
|
{
|
|
|
|
CUR.GS.scan_control = FALSE;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
A *= 64;
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#if 0
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( (args[0] & 0x100) != 0 && CUR.metrics.pointSize <= A )
|
|
|
|
CUR.GS.scan_control = TRUE;
|
2000-06-12 21:36:41 +02:00
|
|
|
#endif
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( (args[0] & 0x200) != 0 && CUR.tt_metrics.rotated )
|
|
|
|
CUR.GS.scan_control = TRUE;
|
|
|
|
|
|
|
|
if ( (args[0] & 0x400) != 0 && CUR.tt_metrics.stretched )
|
|
|
|
CUR.GS.scan_control = TRUE;
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
#if 0
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( (args[0] & 0x800) != 0 && CUR.metrics.pointSize > A )
|
|
|
|
CUR.GS.scan_control = FALSE;
|
2000-06-12 21:36:41 +02:00
|
|
|
#endif
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( (args[0] & 0x1000) != 0 && CUR.tt_metrics.rotated )
|
|
|
|
CUR.GS.scan_control = FALSE;
|
|
|
|
|
|
|
|
if ( (args[0] & 0x2000) != 0 && CUR.tt_metrics.stretched )
|
|
|
|
CUR.GS.scan_control = FALSE;
|
2001-06-28 09:17:51 +02:00
|
|
|
}
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SCANTYPE[]: SCAN TYPE */
|
|
|
|
/* Opcode range: 0x8D */
|
|
|
|
/* Stack: uint32? --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SCANTYPE( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-07-02 15:53:16 +02:00
|
|
|
/* for compatibility with future enhancements, */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* we must ignore new modes */
|
|
|
|
|
|
|
|
if ( args[0] >= 0 && args[0] <= 5 )
|
|
|
|
{
|
|
|
|
if ( args[0] == 3 )
|
|
|
|
args[0] = 2;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
CUR.GS.scan_type = (FT_Int)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* MANAGING OUTLINES */
|
|
|
|
/* */
|
2000-07-02 15:53:16 +02:00
|
|
|
/* Instructions appear in the specification's order. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* FLIPPT[]: FLIP PoinT */
|
|
|
|
/* Opcode range: 0x80 */
|
|
|
|
/* Stack: uint32... --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_FLIPPT( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort point;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_ARG;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-07-02 15:53:16 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( CUR.top < CUR.GS.loop )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Too_Few_Arguments;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ( CUR.GS.loop > 0 )
|
|
|
|
{
|
|
|
|
CUR.args--;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
point = (FT_UShort)CUR.stack[CUR.args];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( BOUNDS( point, CUR.pts.n_points ) )
|
|
|
|
{
|
|
|
|
if ( CUR.pedantic_hinting )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Invalid_Reference;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2000-03-09 12:46:25 +01:00
|
|
|
CUR.pts.tags[point] ^= FT_Curve_Tag_On;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
CUR.GS.loop--;
|
|
|
|
}
|
|
|
|
|
|
|
|
CUR.GS.loop = 1;
|
|
|
|
CUR.new_top = CUR.args;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* FLIPRGON[]: FLIP RanGe ON */
|
|
|
|
/* Opcode range: 0x81 */
|
|
|
|
/* Stack: uint32 uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_FLIPRGON( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort I, K, L;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
K = (FT_UShort)args[1];
|
|
|
|
L = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
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++ )
|
2000-03-09 12:46:25 +01:00
|
|
|
CUR.pts.tags[I] |= FT_Curve_Tag_On;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* FLIPRGOFF: FLIP RanGe OFF */
|
|
|
|
/* Opcode range: 0x82 */
|
|
|
|
/* Stack: uint32 uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_FLIPRGOFF( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort I, K, L;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
K = (FT_UShort)args[1];
|
|
|
|
L = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
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++ )
|
2000-03-09 12:46:25 +01:00
|
|
|
CUR.pts.tags[I] &= ~FT_Curve_Tag_On;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
static FT_Bool
|
|
|
|
Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6* x,
|
|
|
|
FT_F26Dot6* y,
|
2002-03-14 12:26:29 +01:00
|
|
|
TT_GlyphZone zone,
|
2001-06-28 09:17:51 +02:00
|
|
|
FT_UShort* refp )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2002-03-14 12:26:29 +01:00
|
|
|
TT_GlyphZoneRec zp;
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort p;
|
|
|
|
FT_F26Dot6 d;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
if ( CUR.opcode & 1 )
|
|
|
|
{
|
|
|
|
zp = CUR.zp0;
|
|
|
|
p = CUR.GS.rp1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
zp = CUR.zp1;
|
|
|
|
p = CUR.GS.rp2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( BOUNDS( p, zp.n_points ) )
|
|
|
|
{
|
|
|
|
if ( CUR.pedantic_hinting )
|
|
|
|
CUR.error = TT_Err_Invalid_Reference;
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*zone = zp;
|
|
|
|
*refp = p;
|
|
|
|
|
|
|
|
d = CUR_Func_project( zp.cur + p, zp.org + p );
|
|
|
|
|
2000-01-27 14:56:02 +01:00
|
|
|
#ifdef NO_APPLE_PATENT
|
2000-06-12 21:36:41 +02:00
|
|
|
|
2000-01-27 14:56:02 +01:00
|
|
|
*x = TT_MULDIV( d, CUR.GS.freeVector.x, 0x4000 );
|
|
|
|
*y = TT_MULDIV( d, CUR.GS.freeVector.y, 0x4000 );
|
2000-06-12 21:36:41 +02:00
|
|
|
|
2000-01-27 14:56:02 +01:00
|
|
|
#else
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
*x = TT_MULDIV( d,
|
2000-06-16 21:34:52 +02:00
|
|
|
(FT_Long)CUR.GS.freeVector.x * 0x10000L,
|
1999-12-17 00:11:37 +01:00
|
|
|
CUR.F_dot_P );
|
|
|
|
*y = TT_MULDIV( d,
|
2000-06-16 21:34:52 +02:00
|
|
|
(FT_Long)CUR.GS.freeVector.y * 0x10000L,
|
1999-12-17 00:11:37 +01:00
|
|
|
CUR.F_dot_P );
|
2000-06-12 21:36:41 +02:00
|
|
|
|
|
|
|
#endif /* NO_APPLE_PATENT */
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Move_Zp2_Point( EXEC_OP_ FT_UShort point,
|
|
|
|
FT_F26Dot6 dx,
|
|
|
|
FT_F26Dot6 dy,
|
|
|
|
FT_Bool touch )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
if ( CUR.GS.freeVector.x != 0 )
|
|
|
|
{
|
|
|
|
CUR.zp2.cur[point].x += dx;
|
|
|
|
if ( touch )
|
2000-03-09 12:46:25 +01:00
|
|
|
CUR.zp2.tags[point] |= FT_Curve_Tag_Touch_X;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( CUR.GS.freeVector.y != 0 )
|
|
|
|
{
|
|
|
|
CUR.zp2.cur[point].y += dy;
|
|
|
|
if ( touch )
|
2000-03-09 12:46:25 +01:00
|
|
|
CUR.zp2.tags[point] |= FT_Curve_Tag_Touch_Y;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SHP[a]: SHift Point by the last point */
|
|
|
|
/* Opcode range: 0x32-0x33 */
|
|
|
|
/* Stack: uint32... --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SHP( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2002-03-14 12:26:29 +01:00
|
|
|
TT_GlyphZoneRec zp;
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort refp;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_F26Dot6 dx,
|
1999-12-17 00:11:37 +01:00
|
|
|
dy;
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort point;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_ARG;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
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--;
|
2000-06-16 21:34:52 +02:00
|
|
|
point = (FT_UShort)CUR.stack[CUR.args];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( BOUNDS( point, CUR.zp2.n_points ) )
|
|
|
|
{
|
|
|
|
if ( CUR.pedantic_hinting )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Invalid_Reference;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
/* XXX: UNDOCUMENTED! SHP touches the points */
|
|
|
|
MOVE_Zp2_Point( point, dx, dy, TRUE );
|
|
|
|
|
|
|
|
CUR.GS.loop--;
|
|
|
|
}
|
|
|
|
|
|
|
|
CUR.GS.loop = 1;
|
|
|
|
CUR.new_top = CUR.args;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SHC[a]: SHift Contour */
|
|
|
|
/* Opcode range: 0x34-35 */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SHC( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2002-03-14 12:26:29 +01:00
|
|
|
TT_GlyphZoneRec zp;
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort refp;
|
|
|
|
FT_F26Dot6 dx,
|
1999-12-17 00:11:37 +01:00
|
|
|
dy;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Short contour;
|
|
|
|
FT_UShort first_point, last_point, i;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
contour = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
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
|
2001-07-07 18:12:14 +02:00
|
|
|
first_point = (FT_UShort)(CUR.pts.contours[contour - 1] + 1);
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
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 )
|
2001-07-07 18:12:14 +02:00
|
|
|
last_point = (FT_UShort)(CUR.zp2.n_points - 1);
|
1999-12-17 00:11:37 +01:00
|
|
|
else
|
|
|
|
last_point = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX: 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 */
|
|
|
|
/* Opcode range: 0x36-37 */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SHZ( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2002-03-14 12:26:29 +01:00
|
|
|
TT_GlyphZoneRec zp;
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort refp;
|
|
|
|
FT_F26Dot6 dx,
|
1999-12-17 00:11:37 +01:00
|
|
|
dy;
|
|
|
|
|
2000-07-02 15:53:16 +02:00
|
|
|
FT_UShort last_point, i;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
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 )
|
2001-07-07 18:12:14 +02:00
|
|
|
last_point = (FT_UShort)(CUR.zp2.n_points - 1);
|
1999-12-17 00:11:37 +01:00
|
|
|
else
|
|
|
|
last_point = 0;
|
|
|
|
|
|
|
|
/* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
|
|
|
|
for ( i = 0; i <= last_point; i++ )
|
|
|
|
{
|
|
|
|
if ( zp.cur != CUR.zp2.cur || refp != i )
|
|
|
|
MOVE_Zp2_Point( i, dx, dy, FALSE );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* SHPIX[]: SHift points by a PIXel amount */
|
|
|
|
/* Opcode range: 0x38 */
|
|
|
|
/* Stack: f26.6 uint32... --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_SHPIX( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_F26Dot6 dx, dy;
|
|
|
|
FT_UShort point;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
if ( CUR.top < CUR.GS.loop + 1 )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Invalid_Reference;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
dx = TT_MULDIV( args[0],
|
2000-06-16 21:34:52 +02:00
|
|
|
(FT_Long)CUR.GS.freeVector.x,
|
1999-12-17 00:11:37 +01:00
|
|
|
0x4000 );
|
|
|
|
dy = TT_MULDIV( args[0],
|
2000-06-16 21:34:52 +02:00
|
|
|
(FT_Long)CUR.GS.freeVector.y,
|
1999-12-17 00:11:37 +01:00
|
|
|
0x4000 );
|
|
|
|
|
|
|
|
while ( CUR.GS.loop > 0 )
|
|
|
|
{
|
|
|
|
CUR.args--;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
point = (FT_UShort)CUR.stack[CUR.args];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( BOUNDS( point, CUR.zp2.n_points ) )
|
|
|
|
{
|
|
|
|
if ( CUR.pedantic_hinting )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Invalid_Reference;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
MOVE_Zp2_Point( point, dx, dy, TRUE );
|
|
|
|
|
|
|
|
CUR.GS.loop--;
|
|
|
|
}
|
|
|
|
|
|
|
|
CUR.GS.loop = 1;
|
|
|
|
CUR.new_top = CUR.args;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* MSIRP[a]: Move Stack Indirect Relative Position */
|
|
|
|
/* Opcode range: 0x3A-0x3B */
|
|
|
|
/* Stack: f26.6 uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_MSIRP( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort point;
|
|
|
|
FT_F26Dot6 distance;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
point = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
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 */
|
|
|
|
/* Opcode range: 0x2E-0x2F */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_MDAP( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort point;
|
|
|
|
FT_F26Dot6 cur_dist,
|
1999-12-17 00:11:37 +01:00
|
|
|
distance;
|
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
point = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
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? ? */
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( ( CUR.opcode & 1 ) != 0 )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
cur_dist = CUR_Func_project( CUR.zp0.cur + point, NULL_Vector );
|
|
|
|
distance = CUR_Func_round( cur_dist,
|
|
|
|
CUR.tt_metrics.compensations[0] ) - cur_dist;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
distance = 0;
|
|
|
|
|
|
|
|
CUR_Func_move( &CUR.zp0, point, distance );
|
|
|
|
|
|
|
|
CUR.GS.rp0 = point;
|
|
|
|
CUR.GS.rp1 = point;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* MIAP[a]: Move Indirect Absolute Point */
|
|
|
|
/* Opcode range: 0x3E-0x3F */
|
|
|
|
/* Stack: uint32 uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_MIAP( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong cvtEntry;
|
|
|
|
FT_UShort point;
|
|
|
|
FT_F26Dot6 distance,
|
1999-12-17 00:11:37 +01:00
|
|
|
org_dist;
|
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
cvtEntry = (FT_ULong)args[1];
|
|
|
|
point = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
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 */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* specification. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* 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, 0x4000 );
|
|
|
|
CUR.zp0.org[point].y = TT_MULDIV( CUR.GS.freeVector.y,
|
|
|
|
distance, 0x4000 );
|
|
|
|
CUR.zp0.cur[point] = CUR.zp0.org[point];
|
|
|
|
}
|
|
|
|
|
|
|
|
org_dist = CUR_Func_project( CUR.zp0.cur + point, NULL_Vector );
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cutin flag */
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
if ( ABS( distance - org_dist ) > CUR.GS.control_value_cutin )
|
|
|
|
distance = org_dist;
|
|
|
|
|
|
|
|
distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );
|
|
|
|
}
|
|
|
|
|
|
|
|
CUR_Func_move( &CUR.zp0, point, distance - org_dist );
|
|
|
|
|
|
|
|
CUR.GS.rp0 = point;
|
|
|
|
CUR.GS.rp1 = point;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* MDRP[abcde]: Move Direct Relative Point */
|
|
|
|
/* Opcode range: 0xC0-0xDF */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_MDRP( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort point;
|
|
|
|
FT_F26Dot6 org_dist, distance;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
point = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
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 */
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( ( CUR.opcode & 4 ) != 0 )
|
|
|
|
distance = CUR_Func_round(
|
|
|
|
org_dist,
|
|
|
|
CUR.tt_metrics.compensations[CUR.opcode & 3] );
|
1999-12-17 00:11:37 +01:00
|
|
|
else
|
2000-06-12 21:36:41 +02:00
|
|
|
distance = ROUND_None(
|
|
|
|
org_dist,
|
|
|
|
CUR.tt_metrics.compensations[CUR.opcode & 3] );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
/* minimum distance flag */
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( ( CUR.opcode & 8 ) != 0 )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( ( CUR.opcode & 16 ) != 0 )
|
1999-12-17 00:11:37 +01:00
|
|
|
CUR.GS.rp0 = point;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* MIRP[abcde]: Move Indirect Relative Point */
|
|
|
|
/* Opcode range: 0xE0-0xFF */
|
|
|
|
/* Stack: int32? uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_MIRP( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort point;
|
|
|
|
FT_ULong cvtEntry;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_F26Dot6 cvt_dist,
|
1999-12-17 00:11:37 +01:00
|
|
|
distance,
|
|
|
|
cur_dist,
|
|
|
|
org_dist;
|
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
point = (FT_UShort)args[0];
|
|
|
|
cvtEntry = (FT_ULong)( args[1] + 1 );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
/* 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 )
|
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( ( org_dist ^ cvt_dist ) < 0 )
|
1999-12-17 00:11:37 +01:00
|
|
|
cvt_dist = -cvt_dist;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* control value cutin and round */
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( ( CUR.opcode & 4 ) != 0 )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
/* 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;
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
distance = CUR_Func_round(
|
|
|
|
cvt_dist,
|
|
|
|
CUR.tt_metrics.compensations[CUR.opcode & 3] );
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
else
|
2000-06-12 21:36:41 +02:00
|
|
|
distance = ROUND_None(
|
|
|
|
cvt_dist,
|
|
|
|
CUR.tt_metrics.compensations[CUR.opcode & 3] );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
/* minimum distance test */
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( ( CUR.opcode & 8 ) != 0 )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( ( CUR.opcode & 16 ) != 0 )
|
1999-12-17 00:11:37 +01:00
|
|
|
CUR.GS.rp0 = point;
|
|
|
|
|
|
|
|
/* XXX: UNDOCUMENTED! */
|
|
|
|
|
|
|
|
CUR.GS.rp2 = point;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* ALIGNRP[]: ALIGN Relative Point */
|
|
|
|
/* Opcode range: 0x3C */
|
|
|
|
/* Stack: uint32 uint32... --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_ALIGNRP( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort point;
|
|
|
|
FT_F26Dot6 distance;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_ARG;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
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--;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
point = (FT_UShort)CUR.stack[CUR.args];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( BOUNDS( point, CUR.zp1.n_points ) )
|
|
|
|
{
|
|
|
|
if ( CUR.pedantic_hinting )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Invalid_Reference;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
distance = CUR_Func_project( CUR.zp1.cur + point,
|
|
|
|
CUR.zp0.cur + CUR.GS.rp0 );
|
|
|
|
|
|
|
|
CUR_Func_move( &CUR.zp1, point, -distance );
|
|
|
|
}
|
|
|
|
|
|
|
|
CUR.GS.loop--;
|
|
|
|
}
|
|
|
|
|
|
|
|
CUR.GS.loop = 1;
|
|
|
|
CUR.new_top = CUR.args;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* ISECT[]: moves point to InterSECTion */
|
|
|
|
/* Opcode range: 0x0F */
|
|
|
|
/* Stack: 5 * uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_ISECT( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort point,
|
1999-12-17 00:11:37 +01:00
|
|
|
a0, a1,
|
|
|
|
b0, b1;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_F26Dot6 discriminant;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_F26Dot6 dx, dy,
|
1999-12-17 00:11:37 +01:00
|
|
|
dax, day,
|
|
|
|
dbx, dby;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_F26Dot6 val;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Vector R;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
point = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
a0 = (FT_UShort)args[1];
|
|
|
|
a1 = (FT_UShort)args[2];
|
|
|
|
b0 = (FT_UShort)args[3];
|
|
|
|
b1 = (FT_UShort)args[4];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2000-03-09 12:46:25 +01:00
|
|
|
CUR.zp2.tags[point] |= FT_Curve_Tag_Touch_Both;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
discriminant = TT_MULDIV( dax, -dby, 0x40 ) +
|
|
|
|
TT_MULDIV( day, dbx, 0x40 );
|
|
|
|
|
|
|
|
if ( ABS( discriminant ) >= 0x40 )
|
|
|
|
{
|
|
|
|
val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );
|
|
|
|
|
|
|
|
R.x = TT_MULDIV( val, dax, discriminant );
|
|
|
|
R.y = TT_MULDIV( val, day, discriminant );
|
|
|
|
|
|
|
|
CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;
|
|
|
|
CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* else, take the middle of the middles of A and B */
|
|
|
|
|
|
|
|
CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x +
|
|
|
|
CUR.zp1.cur[a1].x +
|
|
|
|
CUR.zp0.cur[b0].x +
|
|
|
|
CUR.zp0.cur[b1].x ) / 4;
|
|
|
|
CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y +
|
|
|
|
CUR.zp1.cur[a1].y +
|
|
|
|
CUR.zp0.cur[b0].y +
|
|
|
|
CUR.zp0.cur[b1].y ) / 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* ALIGNPTS[]: ALIGN PoinTS */
|
|
|
|
/* Opcode range: 0x27 */
|
|
|
|
/* Stack: uint32 uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_ALIGNPTS( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort p1, p2;
|
|
|
|
FT_F26Dot6 distance;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
p1 = (FT_UShort)args[0];
|
|
|
|
p2 = (FT_UShort)args[1];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( BOUNDS( args[0], CUR.zp1.n_points ) ||
|
|
|
|
BOUNDS( args[1], CUR.zp0.n_points ) )
|
|
|
|
{
|
|
|
|
if ( CUR.pedantic_hinting )
|
|
|
|
CUR.error = TT_Err_Invalid_Reference;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
distance = CUR_Func_project( CUR.zp0.cur + p2,
|
|
|
|
CUR.zp1.cur + p1 ) / 2;
|
|
|
|
|
|
|
|
CUR_Func_move( &CUR.zp1, p1, distance );
|
|
|
|
CUR_Func_move( &CUR.zp0, p2, -distance );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* IP[]: Interpolate Point */
|
|
|
|
/* Opcode range: 0x39 */
|
|
|
|
/* Stack: uint32... --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_IP( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_F26Dot6 org_a, org_b, org_x,
|
1999-12-17 00:11:37 +01:00
|
|
|
cur_a, cur_b, cur_x,
|
|
|
|
distance;
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort point;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_ARG;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( CUR.top < CUR.GS.loop )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Invalid_Reference;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2000-07-02 15:53:16 +02:00
|
|
|
/* XXX: There are some glyphs in some braindead but popular */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* 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--;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
point = (FT_UShort)CUR.stack[CUR.args];
|
1999-12-17 00:11:37 +01:00
|
|
|
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 */
|
|
|
|
/* Opcode range: 0x29 */
|
|
|
|
/* Stack: uint32 --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_UTP( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UShort point;
|
|
|
|
FT_Byte mask;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
point = (FT_UShort)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( BOUNDS( point, CUR.zp0.n_points ) )
|
|
|
|
{
|
|
|
|
if ( CUR.pedantic_hinting )
|
|
|
|
CUR.error = TT_Err_Invalid_Reference;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mask = 0xFF;
|
|
|
|
|
|
|
|
if ( CUR.GS.freeVector.x != 0 )
|
|
|
|
mask &= ~FT_Curve_Tag_Touch_X;
|
|
|
|
|
|
|
|
if ( CUR.GS.freeVector.y != 0 )
|
|
|
|
mask &= ~FT_Curve_Tag_Touch_Y;
|
|
|
|
|
2000-03-09 12:46:25 +01:00
|
|
|
CUR.zp0.tags[point] &= mask;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Local variables for Ins_IUP: */
|
2000-07-02 15:53:16 +02:00
|
|
|
struct LOC_Ins_IUP
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Vector* orgs; /* original and current coordinate */
|
|
|
|
FT_Vector* curs; /* arrays */
|
1999-12-17 00:11:37 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Shift( FT_UInt p1,
|
|
|
|
FT_UInt p2,
|
|
|
|
FT_UInt p,
|
|
|
|
struct LOC_Ins_IUP* LINK )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UInt i;
|
|
|
|
FT_F26Dot6 x;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Interp( FT_UInt p1,
|
|
|
|
FT_UInt p2,
|
|
|
|
FT_UInt ref1,
|
|
|
|
FT_UInt ref2,
|
|
|
|
struct LOC_Ins_IUP* LINK )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UInt i;
|
|
|
|
FT_F26Dot6 x, x1, x2, d1, d2;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
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 */
|
|
|
|
/* Opcode range: 0x30-0x31 */
|
|
|
|
/* Stack: --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_IUP( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
struct LOC_Ins_IUP V;
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Byte mask;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UInt first_point; /* first point of contour */
|
|
|
|
FT_UInt end_point; /* end point (last+1) of contour */
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UInt first_touched; /* first touched point in contour */
|
|
|
|
FT_UInt cur_touched; /* current touched point in contour */
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UInt point; /* current point */
|
|
|
|
FT_Short contour; /* current contour */
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_ARG;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( CUR.opcode & 1 )
|
|
|
|
{
|
|
|
|
mask = FT_Curve_Tag_Touch_X;
|
|
|
|
V.orgs = CUR.pts.org;
|
|
|
|
V.curs = CUR.pts.cur;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mask = FT_Curve_Tag_Touch_Y;
|
2000-07-05 20:23:38 +02:00
|
|
|
V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
|
|
|
|
V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
contour = 0;
|
|
|
|
point = 0;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
end_point = CUR.pts.contours[contour];
|
|
|
|
first_point = point;
|
|
|
|
|
2000-03-09 12:46:25 +01:00
|
|
|
while ( point <= end_point && (CUR.pts.tags[point] & mask) == 0 )
|
1999-12-17 00:11:37 +01:00
|
|
|
point++;
|
|
|
|
|
|
|
|
if ( point <= end_point )
|
|
|
|
{
|
|
|
|
first_touched = point;
|
|
|
|
cur_touched = point;
|
|
|
|
|
|
|
|
point++;
|
|
|
|
|
|
|
|
while ( point <= end_point )
|
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( ( CUR.pts.tags[point] & mask ) != 0 )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
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
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
Interp( (FT_UShort)( cur_touched + 1 ),
|
1999-12-17 00:11:37 +01:00
|
|
|
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 */
|
|
|
|
/* Opcode range: 0x5D,0x71,0x72 */
|
|
|
|
/* Stack: uint32 (2 * uint32)... --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_DELTAP( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong k, nump;
|
|
|
|
FT_UShort A;
|
|
|
|
FT_ULong C;
|
|
|
|
FT_Long B;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
nump = (FT_ULong)args[0]; /* some points theoretically may occur more
|
1999-12-17 00:11:37 +01:00
|
|
|
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;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
A = (FT_UShort)CUR.stack[CUR.args + 1];
|
1999-12-17 00:11:37 +01:00
|
|
|
B = CUR.stack[CUR.args];
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
/* 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. */
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( !BOUNDS( A, CUR.zp0.n_points ) )
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
C = ( (FT_ULong)B & 0xF0 ) >> 4;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
switch ( CUR.opcode )
|
|
|
|
{
|
|
|
|
case 0x5D:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x71:
|
|
|
|
C += 16;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x72:
|
|
|
|
C += 32;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
C += CUR.GS.delta_base;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
if ( CURRENT_Ppem() == (FT_Long)C )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
B = ( (FT_ULong)B & 0xF ) - 8;
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( B >= 0 )
|
|
|
|
B++;
|
2000-06-12 21:36:41 +02:00
|
|
|
B = B * 64 / ( 1L << CUR.GS.delta_shift );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
CUR_Func_move( &CUR.zp0, A, B );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if ( CUR.pedantic_hinting )
|
|
|
|
CUR.error = TT_Err_Invalid_Reference;
|
|
|
|
}
|
|
|
|
|
|
|
|
CUR.new_top = CUR.args;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* DELTACn[]: DELTA exceptions C1, C2, C3 */
|
|
|
|
/* Opcode range: 0x73,0x74,0x75 */
|
|
|
|
/* Stack: uint32 (2 * uint32)... --> */
|
|
|
|
/* */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_DELTAC( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong nump, k;
|
|
|
|
FT_ULong A, C;
|
|
|
|
FT_Long B;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
nump = (FT_ULong)args[0];
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
for ( k = 1; k <= nump; k++ )
|
|
|
|
{
|
|
|
|
if ( CUR.args < 2 )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Too_Few_Arguments;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CUR.args -= 2;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
A = (FT_ULong)CUR.stack[CUR.args + 1];
|
1999-12-17 00:11:37 +01:00
|
|
|
B = CUR.stack[CUR.args];
|
|
|
|
|
|
|
|
if ( BOUNDS( A, CUR.cvtSize ) )
|
|
|
|
{
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( CUR.pedantic_hinting )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Invalid_Reference;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
C = ( (FT_ULong)B & 0xF0 ) >> 4;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
switch ( CUR.opcode )
|
|
|
|
{
|
|
|
|
case 0x73:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x74:
|
|
|
|
C += 16;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x75:
|
|
|
|
C += 32;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
C += CUR.GS.delta_base;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
if ( CURRENT_Ppem() == (FT_Long)C )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
B = ( (FT_ULong)B & 0xF ) - 8;
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( B >= 0 )
|
|
|
|
B++;
|
2000-06-12 21:36:41 +02:00
|
|
|
B = B * 64 / ( 1L << CUR.GS.delta_shift );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
CUR_Func_move_cvt( A, B );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CUR.new_top = CUR.args;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* MISC. INSTRUCTIONS */
|
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* GETINFO[]: GET INFOrmation */
|
|
|
|
/* Opcode range: 0x88 */
|
|
|
|
/* Stack: uint32 --> uint32 */
|
|
|
|
/* */
|
|
|
|
/* XXX: According to Apple specs, bits 1 & 2 of the argument ought to be */
|
|
|
|
/* consulted before rotated/stretched info is returned. */
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_GETINFO( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Long K;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
K = 0;
|
|
|
|
|
|
|
|
/* We return then Windows 3.1 version number */
|
|
|
|
/* for the font scaler */
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( ( args[0] & 1 ) != 0 )
|
1999-12-17 00:11:37 +01:00
|
|
|
K = 3;
|
|
|
|
|
|
|
|
/* Has the glyph been rotated ? */
|
|
|
|
if ( CUR.tt_metrics.rotated )
|
|
|
|
K |= 0x80;
|
|
|
|
|
|
|
|
/* Has the glyph been stretched ? */
|
|
|
|
if ( CUR.tt_metrics.stretched )
|
|
|
|
K |= 0x100;
|
|
|
|
|
|
|
|
args[0] = K;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
static void
|
|
|
|
Ins_UNKNOWN( INS_ARG )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
TT_DefRecord* def = CUR.IDefs;
|
|
|
|
TT_DefRecord* limit = def + CUR.numIDefs;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-07-04 20:12:13 +02:00
|
|
|
FT_UNUSED_ARG;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
for ( ; def < limit; def++ )
|
|
|
|
{
|
2000-12-01 00:48:22 +01:00
|
|
|
if ( (FT_Byte)def->opc == CUR.opcode && def->active )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
TT_CallRec* call;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( CUR.callTop >= CUR.callSize )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Stack_Overflow;
|
|
|
|
return;
|
|
|
|
}
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
call = CUR.callStack + CUR.callTop++;
|
|
|
|
|
|
|
|
call->Caller_Range = CUR.curRange;
|
|
|
|
call->Caller_IP = CUR.IP+1;
|
|
|
|
call->Cur_Count = 1;
|
|
|
|
call->Cur_Restart = def->start;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
INS_Goto_CodeRange( def->range, def->start );
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
CUR.step_ins = FALSE;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CUR.error = TT_Err_Invalid_Opcode;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
|
2000-06-12 21:36:41 +02:00
|
|
|
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
static
|
|
|
|
TInstruction_Function Instruct_Dispatch[256] =
|
|
|
|
{
|
|
|
|
/* Opcodes are gathered in groups of 16. */
|
|
|
|
/* Please keep the spaces as they are. */
|
|
|
|
|
|
|
|
/* SVTCA y */ Ins_SVTCA,
|
|
|
|
/* SVTCA x */ Ins_SVTCA,
|
|
|
|
/* SPvTCA y */ Ins_SPVTCA,
|
|
|
|
/* SPvTCA x */ Ins_SPVTCA,
|
|
|
|
/* SFvTCA y */ Ins_SFVTCA,
|
|
|
|
/* SFvTCA x */ Ins_SFVTCA,
|
|
|
|
/* SPvTL // */ Ins_SPVTL,
|
|
|
|
/* SPvTL + */ Ins_SPVTL,
|
|
|
|
/* SFvTL // */ Ins_SFVTL,
|
|
|
|
/* SFvTL + */ Ins_SFVTL,
|
|
|
|
/* SPvFS */ Ins_SPVFS,
|
|
|
|
/* SFvFS */ Ins_SFVFS,
|
|
|
|
/* GPV */ Ins_GPV,
|
|
|
|
/* GFV */ Ins_GFV,
|
|
|
|
/* SFvTPv */ Ins_SFVTPV,
|
|
|
|
/* ISECT */ Ins_ISECT,
|
|
|
|
|
|
|
|
/* SRP0 */ Ins_SRP0,
|
|
|
|
/* SRP1 */ Ins_SRP1,
|
|
|
|
/* SRP2 */ Ins_SRP2,
|
|
|
|
/* SZP0 */ Ins_SZP0,
|
|
|
|
/* SZP1 */ Ins_SZP1,
|
|
|
|
/* SZP2 */ Ins_SZP2,
|
|
|
|
/* SZPS */ Ins_SZPS,
|
|
|
|
/* SLOOP */ Ins_SLOOP,
|
|
|
|
/* RTG */ Ins_RTG,
|
|
|
|
/* RTHG */ Ins_RTHG,
|
|
|
|
/* SMD */ Ins_SMD,
|
|
|
|
/* ELSE */ Ins_ELSE,
|
|
|
|
/* JMPR */ Ins_JMPR,
|
|
|
|
/* SCvTCi */ Ins_SCVTCI,
|
|
|
|
/* SSwCi */ Ins_SSWCI,
|
|
|
|
/* SSW */ Ins_SSW,
|
|
|
|
|
|
|
|
/* DUP */ Ins_DUP,
|
|
|
|
/* POP */ Ins_POP,
|
|
|
|
/* CLEAR */ Ins_CLEAR,
|
|
|
|
/* SWAP */ Ins_SWAP,
|
|
|
|
/* DEPTH */ Ins_DEPTH,
|
|
|
|
/* CINDEX */ Ins_CINDEX,
|
|
|
|
/* MINDEX */ Ins_MINDEX,
|
|
|
|
/* AlignPTS */ Ins_ALIGNPTS,
|
|
|
|
/* INS_0x28 */ Ins_UNKNOWN,
|
|
|
|
/* UTP */ Ins_UTP,
|
|
|
|
/* LOOPCALL */ Ins_LOOPCALL,
|
|
|
|
/* CALL */ Ins_CALL,
|
|
|
|
/* FDEF */ Ins_FDEF,
|
|
|
|
/* ENDF */ Ins_ENDF,
|
|
|
|
/* MDAP[0] */ Ins_MDAP,
|
|
|
|
/* MDAP[1] */ Ins_MDAP,
|
|
|
|
|
|
|
|
/* IUP[0] */ Ins_IUP,
|
|
|
|
/* IUP[1] */ Ins_IUP,
|
|
|
|
/* SHP[0] */ Ins_SHP,
|
|
|
|
/* SHP[1] */ Ins_SHP,
|
|
|
|
/* SHC[0] */ Ins_SHC,
|
|
|
|
/* SHC[1] */ Ins_SHC,
|
|
|
|
/* SHZ[0] */ Ins_SHZ,
|
|
|
|
/* SHZ[1] */ Ins_SHZ,
|
|
|
|
/* SHPIX */ Ins_SHPIX,
|
|
|
|
/* IP */ Ins_IP,
|
|
|
|
/* MSIRP[0] */ Ins_MSIRP,
|
|
|
|
/* MSIRP[1] */ Ins_MSIRP,
|
|
|
|
/* AlignRP */ Ins_ALIGNRP,
|
|
|
|
/* RTDG */ Ins_RTDG,
|
|
|
|
/* MIAP[0] */ Ins_MIAP,
|
|
|
|
/* MIAP[1] */ Ins_MIAP,
|
|
|
|
|
|
|
|
/* NPushB */ Ins_NPUSHB,
|
|
|
|
/* NPushW */ Ins_NPUSHW,
|
|
|
|
/* WS */ Ins_WS,
|
|
|
|
/* RS */ Ins_RS,
|
|
|
|
/* WCvtP */ Ins_WCVTP,
|
|
|
|
/* RCvt */ Ins_RCVT,
|
|
|
|
/* GC[0] */ Ins_GC,
|
|
|
|
/* GC[1] */ Ins_GC,
|
|
|
|
/* SCFS */ Ins_SCFS,
|
|
|
|
/* MD[0] */ Ins_MD,
|
|
|
|
/* MD[1] */ Ins_MD,
|
|
|
|
/* MPPEM */ Ins_MPPEM,
|
|
|
|
/* MPS */ Ins_MPS,
|
|
|
|
/* FlipON */ Ins_FLIPON,
|
|
|
|
/* FlipOFF */ Ins_FLIPOFF,
|
|
|
|
/* DEBUG */ Ins_DEBUG,
|
|
|
|
|
|
|
|
/* LT */ Ins_LT,
|
|
|
|
/* LTEQ */ Ins_LTEQ,
|
|
|
|
/* GT */ Ins_GT,
|
|
|
|
/* GTEQ */ Ins_GTEQ,
|
|
|
|
/* EQ */ Ins_EQ,
|
|
|
|
/* NEQ */ Ins_NEQ,
|
|
|
|
/* ODD */ Ins_ODD,
|
|
|
|
/* EVEN */ Ins_EVEN,
|
|
|
|
/* IF */ Ins_IF,
|
|
|
|
/* EIF */ Ins_EIF,
|
|
|
|
/* AND */ Ins_AND,
|
|
|
|
/* OR */ Ins_OR,
|
|
|
|
/* NOT */ Ins_NOT,
|
|
|
|
/* DeltaP1 */ Ins_DELTAP,
|
|
|
|
/* SDB */ Ins_SDB,
|
|
|
|
/* SDS */ Ins_SDS,
|
|
|
|
|
|
|
|
/* ADD */ Ins_ADD,
|
|
|
|
/* SUB */ Ins_SUB,
|
|
|
|
/* DIV */ Ins_DIV,
|
|
|
|
/* MUL */ Ins_MUL,
|
|
|
|
/* ABS */ Ins_ABS,
|
|
|
|
/* NEG */ Ins_NEG,
|
|
|
|
/* FLOOR */ Ins_FLOOR,
|
|
|
|
/* CEILING */ Ins_CEILING,
|
|
|
|
/* ROUND[0] */ Ins_ROUND,
|
|
|
|
/* ROUND[1] */ Ins_ROUND,
|
|
|
|
/* ROUND[2] */ Ins_ROUND,
|
|
|
|
/* ROUND[3] */ Ins_ROUND,
|
|
|
|
/* NROUND[0] */ Ins_NROUND,
|
|
|
|
/* NROUND[1] */ Ins_NROUND,
|
|
|
|
/* NROUND[2] */ Ins_NROUND,
|
|
|
|
/* NROUND[3] */ Ins_NROUND,
|
|
|
|
|
|
|
|
/* WCvtF */ Ins_WCVTF,
|
|
|
|
/* DeltaP2 */ Ins_DELTAP,
|
|
|
|
/* DeltaP3 */ Ins_DELTAP,
|
|
|
|
/* DeltaCn[0] */ Ins_DELTAC,
|
|
|
|
/* DeltaCn[1] */ Ins_DELTAC,
|
|
|
|
/* DeltaCn[2] */ Ins_DELTAC,
|
|
|
|
/* SROUND */ Ins_SROUND,
|
|
|
|
/* S45Round */ Ins_S45ROUND,
|
|
|
|
/* JROT */ Ins_JROT,
|
|
|
|
/* JROF */ Ins_JROF,
|
|
|
|
/* ROFF */ Ins_ROFF,
|
|
|
|
/* INS_0x7B */ Ins_UNKNOWN,
|
|
|
|
/* RUTG */ Ins_RUTG,
|
|
|
|
/* RDTG */ Ins_RDTG,
|
|
|
|
/* SANGW */ Ins_SANGW,
|
|
|
|
/* AA */ Ins_AA,
|
|
|
|
|
|
|
|
/* FlipPT */ Ins_FLIPPT,
|
|
|
|
/* FlipRgON */ Ins_FLIPRGON,
|
|
|
|
/* FlipRgOFF */ Ins_FLIPRGOFF,
|
|
|
|
/* INS_0x83 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0x84 */ Ins_UNKNOWN,
|
|
|
|
/* ScanCTRL */ Ins_SCANCTRL,
|
|
|
|
/* SDPVTL[0] */ Ins_SDPVTL,
|
|
|
|
/* SDPVTL[1] */ Ins_SDPVTL,
|
|
|
|
/* GetINFO */ Ins_GETINFO,
|
|
|
|
/* IDEF */ Ins_IDEF,
|
|
|
|
/* ROLL */ Ins_ROLL,
|
|
|
|
/* MAX */ Ins_MAX,
|
|
|
|
/* MIN */ Ins_MIN,
|
|
|
|
/* ScanTYPE */ Ins_SCANTYPE,
|
|
|
|
/* InstCTRL */ Ins_INSTCTRL,
|
|
|
|
/* INS_0x8F */ Ins_UNKNOWN,
|
|
|
|
|
|
|
|
/* INS_0x90 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0x91 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0x92 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0x93 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0x94 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0x95 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0x96 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0x97 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0x98 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0x99 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0x9A */ Ins_UNKNOWN,
|
|
|
|
/* INS_0x9B */ Ins_UNKNOWN,
|
|
|
|
/* INS_0x9C */ Ins_UNKNOWN,
|
|
|
|
/* INS_0x9D */ Ins_UNKNOWN,
|
|
|
|
/* INS_0x9E */ Ins_UNKNOWN,
|
|
|
|
/* INS_0x9F */ Ins_UNKNOWN,
|
|
|
|
|
|
|
|
/* INS_0xA0 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0xA1 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0xA2 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0xA3 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0xA4 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0xA5 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0xA6 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0xA7 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0xA8 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0xA9 */ Ins_UNKNOWN,
|
|
|
|
/* INS_0xAA */ Ins_UNKNOWN,
|
|
|
|
/* INS_0xAB */ Ins_UNKNOWN,
|
|
|
|
/* INS_0xAC */ Ins_UNKNOWN,
|
|
|
|
/* INS_0xAD */ Ins_UNKNOWN,
|
|
|
|
/* INS_0xAE */ Ins_UNKNOWN,
|
|
|
|
/* INS_0xAF */ Ins_UNKNOWN,
|
|
|
|
|
|
|
|
/* PushB[0] */ Ins_PUSHB,
|
|
|
|
/* PushB[1] */ Ins_PUSHB,
|
|
|
|
/* PushB[2] */ Ins_PUSHB,
|
|
|
|
/* PushB[3] */ Ins_PUSHB,
|
|
|
|
/* PushB[4] */ Ins_PUSHB,
|
|
|
|
/* PushB[5] */ Ins_PUSHB,
|
|
|
|
/* PushB[6] */ Ins_PUSHB,
|
|
|
|
/* PushB[7] */ Ins_PUSHB,
|
|
|
|
/* PushW[0] */ Ins_PUSHW,
|
|
|
|
/* PushW[1] */ Ins_PUSHW,
|
|
|
|
/* PushW[2] */ Ins_PUSHW,
|
|
|
|
/* PushW[3] */ Ins_PUSHW,
|
|
|
|
/* PushW[4] */ Ins_PUSHW,
|
|
|
|
/* PushW[5] */ Ins_PUSHW,
|
|
|
|
/* PushW[6] */ Ins_PUSHW,
|
|
|
|
/* PushW[7] */ Ins_PUSHW,
|
|
|
|
|
|
|
|
/* MDRP[00] */ Ins_MDRP,
|
|
|
|
/* MDRP[01] */ Ins_MDRP,
|
|
|
|
/* MDRP[02] */ Ins_MDRP,
|
|
|
|
/* MDRP[03] */ Ins_MDRP,
|
|
|
|
/* MDRP[04] */ Ins_MDRP,
|
|
|
|
/* MDRP[05] */ Ins_MDRP,
|
|
|
|
/* MDRP[06] */ Ins_MDRP,
|
|
|
|
/* MDRP[07] */ Ins_MDRP,
|
|
|
|
/* MDRP[08] */ Ins_MDRP,
|
|
|
|
/* MDRP[09] */ Ins_MDRP,
|
|
|
|
/* MDRP[10] */ Ins_MDRP,
|
|
|
|
/* MDRP[11] */ Ins_MDRP,
|
|
|
|
/* MDRP[12] */ Ins_MDRP,
|
|
|
|
/* MDRP[13] */ Ins_MDRP,
|
|
|
|
/* MDRP[14] */ Ins_MDRP,
|
|
|
|
/* MDRP[15] */ Ins_MDRP,
|
|
|
|
|
|
|
|
/* MDRP[16] */ Ins_MDRP,
|
|
|
|
/* MDRP[17] */ Ins_MDRP,
|
|
|
|
/* MDRP[18] */ Ins_MDRP,
|
|
|
|
/* MDRP[19] */ Ins_MDRP,
|
|
|
|
/* MDRP[20] */ Ins_MDRP,
|
|
|
|
/* MDRP[21] */ Ins_MDRP,
|
|
|
|
/* MDRP[22] */ Ins_MDRP,
|
|
|
|
/* MDRP[23] */ Ins_MDRP,
|
|
|
|
/* MDRP[24] */ Ins_MDRP,
|
|
|
|
/* MDRP[25] */ Ins_MDRP,
|
|
|
|
/* MDRP[26] */ Ins_MDRP,
|
|
|
|
/* MDRP[27] */ Ins_MDRP,
|
|
|
|
/* MDRP[28] */ Ins_MDRP,
|
|
|
|
/* MDRP[29] */ Ins_MDRP,
|
|
|
|
/* MDRP[30] */ Ins_MDRP,
|
|
|
|
/* MDRP[31] */ Ins_MDRP,
|
|
|
|
|
|
|
|
/* MIRP[00] */ Ins_MIRP,
|
|
|
|
/* MIRP[01] */ Ins_MIRP,
|
|
|
|
/* MIRP[02] */ Ins_MIRP,
|
|
|
|
/* MIRP[03] */ Ins_MIRP,
|
|
|
|
/* MIRP[04] */ Ins_MIRP,
|
|
|
|
/* MIRP[05] */ Ins_MIRP,
|
|
|
|
/* MIRP[06] */ Ins_MIRP,
|
|
|
|
/* MIRP[07] */ Ins_MIRP,
|
|
|
|
/* MIRP[08] */ Ins_MIRP,
|
|
|
|
/* MIRP[09] */ Ins_MIRP,
|
|
|
|
/* MIRP[10] */ Ins_MIRP,
|
|
|
|
/* MIRP[11] */ Ins_MIRP,
|
|
|
|
/* MIRP[12] */ Ins_MIRP,
|
|
|
|
/* MIRP[13] */ Ins_MIRP,
|
|
|
|
/* MIRP[14] */ Ins_MIRP,
|
|
|
|
/* MIRP[15] */ Ins_MIRP,
|
|
|
|
|
|
|
|
/* MIRP[16] */ Ins_MIRP,
|
|
|
|
/* MIRP[17] */ Ins_MIRP,
|
|
|
|
/* MIRP[18] */ Ins_MIRP,
|
|
|
|
/* MIRP[19] */ Ins_MIRP,
|
|
|
|
/* MIRP[20] */ Ins_MIRP,
|
|
|
|
/* MIRP[21] */ Ins_MIRP,
|
|
|
|
/* MIRP[22] */ Ins_MIRP,
|
|
|
|
/* MIRP[23] */ Ins_MIRP,
|
|
|
|
/* MIRP[24] */ Ins_MIRP,
|
|
|
|
/* MIRP[25] */ Ins_MIRP,
|
|
|
|
/* MIRP[26] */ Ins_MIRP,
|
|
|
|
/* MIRP[27] */ Ins_MIRP,
|
|
|
|
/* MIRP[28] */ Ins_MIRP,
|
|
|
|
/* MIRP[29] */ Ins_MIRP,
|
|
|
|
/* MIRP[30] */ Ins_MIRP,
|
|
|
|
/* MIRP[31] */ Ins_MIRP
|
|
|
|
};
|
2000-06-12 21:36:41 +02:00
|
|
|
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* RUN */
|
|
|
|
/* */
|
|
|
|
/* This function executes a run of opcodes. It will exit in the */
|
|
|
|
/* following cases: */
|
|
|
|
/* */
|
|
|
|
/* - Errors (in which case it returns FALSE). */
|
|
|
|
/* */
|
|
|
|
/* - Reaching the end of the main code range (returns TRUE). */
|
|
|
|
/* Reaching the end of a code range within a function call is an */
|
|
|
|
/* error. */
|
|
|
|
/* */
|
|
|
|
/* - After executing one single opcode, if the flag `Instruction_Trap' */
|
|
|
|
/* is set to TRUE (returns TRUE). */
|
|
|
|
/* */
|
|
|
|
/* On exit whith TRUE, test IP < CodeSize to know wether it comes from */
|
|
|
|
/* an instruction trap or a normal termination. */
|
|
|
|
/* */
|
|
|
|
/* */
|
|
|
|
/* Note: The documented DEBUG opcode pops a value from the stack. This */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* behaviour is unsupported; here a DEBUG opcode is always an */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* error. */
|
|
|
|
/* */
|
|
|
|
/* */
|
|
|
|
/* THIS IS THE INTERPRETER'S MAIN LOOP. */
|
|
|
|
/* */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* Instructions appear in the specification's order. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
|
2000-11-07 18:21:11 +01:00
|
|
|
/* documentation is in ttinterp.h */
|
|
|
|
|
2001-06-28 09:17:51 +02:00
|
|
|
FT_EXPORT_DEF( FT_Error )
|
|
|
|
TT_RunIns( TT_ExecContext exc )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Long ins_counter = 0; /* executed instructions counter */
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
|
|
|
#ifdef TT_CONFIG_OPTION_STATIC_RASTER
|
1999-12-17 00:11:37 +01:00
|
|
|
cur = *exc;
|
2000-06-12 21:36:41 +02:00
|
|
|
#endif
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
/* set CVT functions */
|
|
|
|
CUR.tt_metrics.ratio = 0;
|
|
|
|
if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
|
|
|
|
{
|
|
|
|
/* non-square pixels, use the stretched routines */
|
|
|
|
CUR.func_read_cvt = Read_CVT_Stretched;
|
|
|
|
CUR.func_write_cvt = Write_CVT_Stretched;
|
|
|
|
CUR.func_move_cvt = Move_CVT_Stretched;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* square pixels, use normal routines */
|
|
|
|
CUR.func_read_cvt = Read_CVT;
|
|
|
|
CUR.func_write_cvt = Write_CVT;
|
|
|
|
CUR.func_move_cvt = Move_CVT;
|
|
|
|
}
|
|
|
|
|
|
|
|
COMPUTE_Funcs();
|
2000-06-16 21:34:52 +02:00
|
|
|
COMPUTE_Round( (FT_Byte)exc->GS.round_state );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
CUR.opcode = CUR.code[CUR.IP];
|
|
|
|
|
|
|
|
if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
|
|
|
|
{
|
|
|
|
if ( CUR.IP + 1 > CUR.codeSize )
|
|
|
|
goto LErrorCodeOverflow_;
|
|
|
|
|
|
|
|
CUR.length = CUR.code[CUR.IP + 1] + 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( CUR.IP + CUR.length > CUR.codeSize )
|
|
|
|
goto LErrorCodeOverflow_;
|
|
|
|
|
|
|
|
/* First, let's check for empty stack and overflow */
|
2000-06-12 21:36:41 +02:00
|
|
|
CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
/* `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_;
|
|
|
|
}
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
/* `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
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Long* args = CUR.stack + CUR.args;
|
|
|
|
FT_Byte opcode = CUR.opcode;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2000-12-14 00:44:37 +01:00
|
|
|
#undef ARRAY_BOUND_ERROR
|
|
|
|
#define ARRAY_BOUND_ERROR goto Set_Invalid_Ref
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
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 */
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Short AA, BB;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2001-07-08 01:24:02 +02:00
|
|
|
AA = (FT_Short)( ( opcode & 1 ) << 14 );
|
2001-07-07 18:12:14 +02:00
|
|
|
BB = (FT_Short)( AA ^ 0x4000 );
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( opcode < 4 )
|
|
|
|
{
|
|
|
|
CUR.GS.projVector.x = AA;
|
|
|
|
CUR.GS.projVector.y = BB;
|
|
|
|
|
|
|
|
CUR.GS.dualVector.x = AA;
|
|
|
|
CUR.GS.dualVector.y = BB;
|
|
|
|
}
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
if ( ( opcode & 2 ) == 0 )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
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 */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_ISECT( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x10: /* SRP0 */
|
|
|
|
DO_SRP0
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x11: /* SRP1 */
|
|
|
|
DO_SRP1
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x12: /* SRP2 */
|
|
|
|
DO_SRP2
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x13: /* SZP0 */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_SZP0( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x14: /* SZP1 */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_SZP1( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x15: /* SZP2 */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_SZP2( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x16: /* SZPS */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_SZPS( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
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 */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_ELSE( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
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 */
|
2000-06-12 21:36:41 +02:00
|
|
|
/* nothing :-) */
|
1999-12-17 00:11:37 +01:00
|
|
|
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 */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_MINDEX( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x27: /* ALIGNPTS */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_ALIGNPTS( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x28: /* ???? */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_UNKNOWN( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x29: /* UTP */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_UTP( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x2A: /* LOOPCALL */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_LOOPCALL( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x2B: /* CALL */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_CALL( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x2C: /* FDEF */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_FDEF( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x2D: /* ENDF */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_ENDF( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x2E: /* MDAP */
|
|
|
|
case 0x2F: /* MDAP */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_MDAP( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 0x30: /* IUP */
|
|
|
|
case 0x31: /* IUP */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_IUP( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x32: /* SHP */
|
|
|
|
case 0x33: /* SHP */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_SHP( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x34: /* SHC */
|
|
|
|
case 0x35: /* SHC */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_SHC( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x36: /* SHZ */
|
|
|
|
case 0x37: /* SHZ */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_SHZ( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x38: /* SHPIX */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_SHPIX( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x39: /* IP */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_IP( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x3A: /* MSIRP */
|
|
|
|
case 0x3B: /* MSIRP */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_MSIRP( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x3C: /* AlignRP */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_ALIGNRP( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x3D: /* RTDG */
|
|
|
|
DO_RTDG
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x3E: /* MIAP */
|
|
|
|
case 0x3F: /* MIAP */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_MIAP( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x40: /* NPUSHB */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_NPUSHB( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x41: /* NPUSHW */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_NPUSHW( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x42: /* WS */
|
|
|
|
DO_WS
|
|
|
|
break;
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
Set_Invalid_Ref:
|
1999-12-17 00:11:37 +01:00
|
|
|
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 */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_GC( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x48: /* SCFS */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_SCFS( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x49: /* MD */
|
|
|
|
case 0x4A: /* MD */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_MD( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
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 */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_IF( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
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 */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_DELTAP( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
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 */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_DELTAP( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x73: /* DELTAC0 */
|
|
|
|
case 0x74: /* DELTAC1 */
|
|
|
|
case 0x75: /* DELTAC2 */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_DELTAC( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
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: /* ???? */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_UNKNOWN( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
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 */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_FLIPPT( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x81: /* FLIPRGON */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_FLIPRGON( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x82: /* FLIPRGOFF */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_FLIPRGOFF( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x83: /* UNKNOWN */
|
|
|
|
case 0x84: /* UNKNOWN */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_UNKNOWN( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x85: /* SCANCTRL */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_SCANCTRL( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x86: /* SDPVTL */
|
|
|
|
case 0x87: /* SDPVTL */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_SDPVTL( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x88: /* GETINFO */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_GETINFO( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x89: /* IDEF */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_IDEF( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x8A: /* ROLL */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_ROLL( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x8B: /* MAX */
|
|
|
|
DO_MAX
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x8C: /* MIN */
|
|
|
|
DO_MIN
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x8D: /* SCANTYPE */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_SCANTYPE( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x8E: /* INSTCTRL */
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_INSTCTRL( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x8F:
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_UNKNOWN( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
if ( opcode >= 0xE0 )
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_MIRP( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
else if ( opcode >= 0xC0 )
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_MDRP( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
else if ( opcode >= 0xB8 )
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_PUSHW( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
else if ( opcode >= 0xB0 )
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_PUSHB( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
else
|
2000-06-12 21:36:41 +02:00
|
|
|
Ins_UNKNOWN( EXEC_ARG_ args );
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
#else
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );
|
2000-06-12 21:36:41 +02:00
|
|
|
|
|
|
|
#endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
|
|
|
|
|
2001-06-08 23:17:29 +02:00
|
|
|
if ( CUR.error != TT_Err_Ok )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
switch ( CUR.error )
|
|
|
|
{
|
|
|
|
case TT_Err_Invalid_Opcode: /* looking for redefined instructions */
|
|
|
|
{
|
|
|
|
TT_DefRecord* def = CUR.IDefs;
|
|
|
|
TT_DefRecord* limit = def + CUR.numIDefs;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
for ( ; def < limit; def++ )
|
|
|
|
{
|
2000-12-01 00:48:22 +01:00
|
|
|
if ( def->active && CUR.opcode == (FT_Byte)def->opc )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
TT_CallRec* callrec;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( CUR.callTop >= CUR.callSize )
|
|
|
|
{
|
|
|
|
CUR.error = TT_Err_Invalid_Reference;
|
|
|
|
goto LErrorLabel_;
|
|
|
|
}
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
callrec = &CUR.callStack[CUR.callTop];
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
callrec->Caller_Range = CUR.curRange;
|
|
|
|
callrec->Caller_IP = CUR.IP + 1;
|
|
|
|
callrec->Cur_Count = 1;
|
|
|
|
callrec->Cur_Restart = def->start;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
|
|
|
|
goto LErrorLabel_;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
goto LSuiteLabel_;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CUR.error = TT_Err_Invalid_Opcode;
|
|
|
|
goto LErrorLabel_;
|
2000-06-12 21:36:41 +02:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
break; /* Unreachable code warning suppression. */
|
|
|
|
/* Leave to remind in case a later change the editor */
|
|
|
|
/* to consider break; */
|
|
|
|
#endif
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
default:
|
|
|
|
goto LErrorLabel_;
|
2000-06-12 21:36:41 +02:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
break;
|
|
|
|
#endif
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CUR.top = CUR.new_top;
|
|
|
|
|
|
|
|
if ( CUR.step_ins )
|
|
|
|
CUR.IP += CUR.length;
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
/* increment instruction counter and check if we didn't */
|
|
|
|
/* run this program for too long (e.g. infinite loops). */
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
|
|
|
|
return TT_Err_Execution_Too_Long;
|
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
LSuiteLabel_:
|
1999-12-17 00:11:37 +01:00
|
|
|
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_:
|
2000-06-12 21:36:41 +02:00
|
|
|
|
|
|
|
#ifdef TT_CONFIG_OPTION_STATIC_RASTER
|
1999-12-17 00:11:37 +01:00
|
|
|
*exc = cur;
|
2000-06-12 21:36:41 +02:00
|
|
|
#endif
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
return TT_Err_Ok;
|
|
|
|
|
|
|
|
LErrorCodeOverflow_:
|
|
|
|
CUR.error = TT_Err_Code_Overflow;
|
|
|
|
|
|
|
|
LErrorLabel_:
|
2000-06-12 21:36:41 +02:00
|
|
|
|
|
|
|
#ifdef TT_CONFIG_OPTION_STATIC_RASTER
|
1999-12-17 00:11:37 +01:00
|
|
|
*exc = cur;
|
2000-06-12 21:36:41 +02:00
|
|
|
#endif
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
return CUR.error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-02-10 19:08:17 +01:00
|
|
|
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-12 21:36:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* END */
|