1
/***************************************************************************/
5
/* TrueType bytecode interpreter (body). */
7
/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
9
/* by David Turner, Robert Wilhelm, and Werner Lemberg. */
11
/* This file is part of the FreeType project, and may only be used, */
12
/* modified, and distributed under the terms of the FreeType project */
13
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
14
/* this file you indicate that you have read the license and */
15
/* understand and accept it fully. */
17
/***************************************************************************/
21
#include FT_INTERNAL_DEBUG_H
22
#include FT_INTERNAL_CALC_H
23
#include FT_TRIGONOMETRY_H
31
#ifdef TT_USE_BYTECODE_INTERPRETER
34
#define TT_MULFIX FT_MulFix
35
#define TT_MULDIV FT_MulDiv
36
#define TT_MULDIV_NO_ROUND FT_MulDiv_No_Round
39
/*************************************************************************/
41
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
42
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
43
/* messages during execution. */
46
#define FT_COMPONENT trace_ttinterp
48
/*************************************************************************/
50
/* In order to detect infinite loops in the code, we set up a counter */
51
/* within the run loop. A single stroke of interpretation is now */
52
/* limited to a maximal number of opcodes defined below. */
54
#define MAX_RUNNABLE_OPCODES 1000000L
57
/*************************************************************************/
59
/* There are two kinds of implementations: */
61
/* a. static implementation */
63
/* The current execution context is a static variable, which fields */
64
/* are accessed directly by the interpreter during execution. The */
65
/* context is named `cur'. */
67
/* This version is non-reentrant, of course. */
69
/* b. indirect implementation */
71
/* The current execution context is passed to _each_ function as its */
72
/* first argument, and each field is thus accessed indirectly. */
74
/* This version is fully re-entrant. */
76
/* The idea is that an indirect implementation may be slower to execute */
77
/* on low-end processors that are used in some systems (like 386s or */
80
/* As a consequence, the indirect implementation is now the default, as */
81
/* its performance costs can be considered negligible in our context. */
82
/* Note, however, that we kept the same source with macros because: */
84
/* - The code is kept very close in design to the Pascal code used for */
87
/* - It's much more readable that way! */
89
/* - It's still open to experimentation and tuning. */
91
/*************************************************************************/
94
#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER /* indirect implementation */
96
#define CUR (*exc) /* see ttobjs.h */
98
/*************************************************************************/
100
/* This macro is used whenever `exec' is unused in a function, to avoid */
101
/* stupid warnings from pedantic compilers. */
103
#define FT_UNUSED_EXEC FT_UNUSED( exc )
105
#else /* static implementation */
109
#define FT_UNUSED_EXEC int __dummy = __dummy
112
TT_ExecContextRec cur; /* static exec. context variable */
114
/* apparently, we have a _lot_ of direct indexing when accessing */
115
/* the static `cur', which makes the code bigger (due to all the */
116
/* four bytes addresses). */
118
#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
121
/*************************************************************************/
123
/* The instruction argument stack. */
125
#define INS_ARG EXEC_OP_ FT_Long* args /* see ttobjs.h for EXEC_OP_ */
128
/*************************************************************************/
130
/* This macro is used whenever `args' is unused in a function, to avoid */
131
/* stupid warnings from pedantic compilers. */
133
#define FT_UNUSED_ARG FT_UNUSED_EXEC; FT_UNUSED( args )
136
/*************************************************************************/
138
/* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to */
139
/* increase readability of the code. */
141
/*************************************************************************/
144
#define SKIP_Code() \
147
#define GET_ShortIns() \
148
GetShortIns( EXEC_ARG )
150
#define NORMalize( x, y, v ) \
151
Normalize( EXEC_ARG_ x, y, v )
153
#define SET_SuperRound( scale, flags ) \
154
SetSuperRound( EXEC_ARG_ scale, flags )
156
#define ROUND_None( d, c ) \
157
Round_None( EXEC_ARG_ d, c )
159
#define INS_Goto_CodeRange( range, ip ) \
160
Ins_Goto_CodeRange( EXEC_ARG_ range, ip )
162
#define CUR_Func_move( z, p, d ) \
163
CUR.func_move( EXEC_ARG_ z, p, d )
165
#define CUR_Func_move_orig( z, p, d ) \
166
CUR.func_move_orig( EXEC_ARG_ z, p, d )
168
#define CUR_Func_round( d, c ) \
169
CUR.func_round( EXEC_ARG_ d, c )
171
#define CUR_Func_read_cvt( index ) \
172
CUR.func_read_cvt( EXEC_ARG_ index )
174
#define CUR_Func_write_cvt( index, val ) \
175
CUR.func_write_cvt( EXEC_ARG_ index, val )
177
#define CUR_Func_move_cvt( index, val ) \
178
CUR.func_move_cvt( EXEC_ARG_ index, val )
180
#define CURRENT_Ratio() \
181
Current_Ratio( EXEC_ARG )
183
#define CURRENT_Ppem() \
184
Current_Ppem( EXEC_ARG )
189
#define INS_SxVTL( a, b, c, d ) \
190
Ins_SxVTL( EXEC_ARG_ a, b, c, d )
192
#define COMPUTE_Funcs() \
193
Compute_Funcs( EXEC_ARG )
195
#define COMPUTE_Round( a ) \
196
Compute_Round( EXEC_ARG_ a )
198
#define COMPUTE_Point_Displacement( a, b, c, d ) \
199
Compute_Point_Displacement( EXEC_ARG_ a, b, c, d )
201
#define MOVE_Zp2_Point( a, b, c, t ) \
202
Move_Zp2_Point( EXEC_ARG_ a, b, c, t )
205
#define CUR_Func_project( v1, v2 ) \
206
CUR.func_project( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
208
#define CUR_Func_dualproj( v1, v2 ) \
209
CUR.func_dualproj( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
211
#define CUR_fast_project( v ) \
212
CUR.func_project( EXEC_ARG_ (v)->x, (v)->y )
214
#define CUR_fast_dualproj( v ) \
215
CUR.func_dualproj( EXEC_ARG_ (v)->x, (v)->y )
218
/*************************************************************************/
220
/* Instruction dispatch function, as used by the interpreter. */
222
typedef void (*TInstruction_Function)( INS_ARG );
225
/*************************************************************************/
227
/* Two simple bounds-checking macros. */
229
#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) )
230
#define BOUNDSL( x, n ) ( (FT_ULong)(x) >= (FT_ULong)(n) )
238
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
239
#define GUESS_VECTOR( V ) \
240
if ( CUR.face->unpatented_hinting ) \
242
CUR.GS.V.x = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0x4000 : 0 ); \
243
CUR.GS.V.y = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0 : 0x4000 ); \
246
#define GUESS_VECTOR( V )
249
/*************************************************************************/
251
/* CODERANGE FUNCTIONS */
253
/*************************************************************************/
256
/*************************************************************************/
259
/* TT_Goto_CodeRange */
262
/* Switches to a new code range (updates the code related elements in */
263
/* `exec', and `IP'). */
266
/* range :: The new execution code range. */
268
/* IP :: The new IP in the new code range. */
271
/* exec :: The target execution context. */
274
/* FreeType error code. 0 means success. */
276
FT_LOCAL_DEF( FT_Error )
277
TT_Goto_CodeRange( TT_ExecContext exec,
281
TT_CodeRange* coderange;
284
FT_ASSERT( range >= 1 && range <= 3 );
286
coderange = &exec->codeRangeTable[range - 1];
288
FT_ASSERT( coderange->base != NULL );
290
/* NOTE: Because the last instruction of a program may be a CALL */
291
/* which will return to the first byte *after* the code */
292
/* range, we test for IP <= Size instead of IP < Size. */
294
FT_ASSERT( (FT_ULong)IP <= coderange->size );
296
exec->code = coderange->base;
297
exec->codeSize = coderange->size;
299
exec->curRange = range;
305
/*************************************************************************/
308
/* TT_Set_CodeRange */
311
/* Sets a code range. */
314
/* range :: The code range index. */
316
/* base :: The new code base. */
318
/* length :: The range size in bytes. */
321
/* exec :: The target execution context. */
324
/* FreeType error code. 0 means success. */
326
FT_LOCAL_DEF( FT_Error )
327
TT_Set_CodeRange( TT_ExecContext exec,
332
FT_ASSERT( range >= 1 && range <= 3 );
334
exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
335
exec->codeRangeTable[range - 1].size = length;
341
/*************************************************************************/
344
/* TT_Clear_CodeRange */
347
/* Clears a code range. */
350
/* range :: The code range index. */
353
/* exec :: The target execution context. */
356
/* FreeType error code. 0 means success. */
359
/* Does not set the Error variable. */
361
FT_LOCAL_DEF( FT_Error )
362
TT_Clear_CodeRange( TT_ExecContext exec,
365
FT_ASSERT( range >= 1 && range <= 3 );
367
exec->codeRangeTable[range - 1].base = NULL;
368
exec->codeRangeTable[range - 1].size = 0;
374
/*************************************************************************/
376
/* EXECUTION CONTEXT ROUTINES */
378
/*************************************************************************/
381
/*************************************************************************/
384
/* TT_Done_Context */
387
/* Destroys a given context. */
390
/* exec :: A handle to the target execution context. */
392
/* memory :: A handle to the parent memory object. */
395
/* FreeType error code. 0 means success. */
398
/* Only the glyph loader and debugger should call this function. */
400
FT_LOCAL_DEF( FT_Error )
401
TT_Done_Context( TT_ExecContext exec )
403
FT_Memory memory = exec->memory;
408
exec->maxContours = 0;
411
FT_FREE( exec->stack );
414
/* free call stack */
415
FT_FREE( exec->callStack );
419
/* free glyph code range */
420
FT_FREE( exec->glyphIns );
432
/*************************************************************************/
438
/* Initializes a context object. */
441
/* memory :: A handle to the parent memory object. */
444
/* exec :: A handle to the target execution context. */
447
/* FreeType error code. 0 means success. */
450
Init_Context( TT_ExecContext exec,
456
FT_TRACE1(( "Init_Context: new object at 0x%08p\n", exec ));
458
exec->memory = memory;
461
if ( FT_NEW_ARRAY( exec->callStack, exec->callSize ) )
464
/* all values in the context are set to 0 already, but this is */
465
/* here as a remainder */
467
exec->maxContours = 0;
473
exec->glyphIns = NULL;
481
FT_ERROR(( "Init_Context: not enough memory for %p\n", exec ));
482
TT_Done_Context( exec );
488
/*************************************************************************/
494
/* Checks the size of a buffer and reallocates it if necessary. */
497
/* memory :: A handle to the parent memory object. */
499
/* multiplier :: The size in bytes of each element in the buffer. */
501
/* new_max :: The new capacity (size) of the buffer. */
504
/* size :: The address of the buffer's current size expressed */
507
/* buff :: The address of the buffer base pointer. */
510
/* FreeType error code. 0 means success. */
512
FT_LOCAL_DEF( FT_Error )
513
Update_Max( FT_Memory memory,
520
void** pbuff = (void**)_pbuff;
523
if ( *size < new_max )
525
if ( FT_REALLOC( *pbuff, *size * multiplier, new_max * multiplier ) )
534
/*************************************************************************/
537
/* TT_Load_Context */
540
/* Prepare an execution context for glyph hinting. */
543
/* face :: A handle to the source face object. */
545
/* size :: A handle to the source size object. */
548
/* exec :: A handle to the target execution context. */
551
/* FreeType error code. 0 means success. */
554
/* Only the glyph loader and debugger should call this function. */
556
FT_LOCAL_DEF( FT_Error )
557
TT_Load_Context( TT_ExecContext exec,
568
maxp = &face->max_profile;
573
exec->numFDefs = size->num_function_defs;
574
exec->maxFDefs = size->max_function_defs;
575
exec->numIDefs = size->num_instruction_defs;
576
exec->maxIDefs = size->max_instruction_defs;
577
exec->FDefs = size->function_defs;
578
exec->IDefs = size->instruction_defs;
579
exec->tt_metrics = size->ttmetrics;
580
exec->metrics = size->metrics;
582
exec->maxFunc = size->max_func;
583
exec->maxIns = size->max_ins;
585
for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
586
exec->codeRangeTable[i] = size->codeRangeTable[i];
588
/* set graphics state */
591
exec->cvtSize = size->cvt_size;
592
exec->cvt = size->cvt;
594
exec->storeSize = size->storage_size;
595
exec->storage = size->storage;
597
exec->twilight = size->twilight;
599
/* In case of multi-threading it can happen that the old size object */
600
/* no longer exists, thus we must clear all glyph zone references. */
601
ft_memset( &exec->zp0, 0, sizeof ( exec->zp0 ) );
602
exec->zp1 = exec->zp0;
603
exec->zp2 = exec->zp0;
606
/* XXX: We reserve a little more elements on the stack to deal safely */
607
/* with broken fonts like arialbs, courbs, timesbs, etc. */
608
tmp = exec->stackSize;
609
error = Update_Max( exec->memory,
611
sizeof ( FT_F26Dot6 ),
613
maxp->maxStackElements + 32 );
614
exec->stackSize = (FT_UInt)tmp;
618
tmp = exec->glyphSize;
619
error = Update_Max( exec->memory,
622
(void*)&exec->glyphIns,
623
maxp->maxSizeOfInstructions );
624
exec->glyphSize = (FT_UShort)tmp;
628
exec->pts.n_points = 0;
629
exec->pts.n_contours = 0;
631
exec->zp1 = exec->pts;
632
exec->zp2 = exec->pts;
633
exec->zp0 = exec->pts;
635
exec->instruction_trap = FALSE;
641
/*************************************************************************/
644
/* TT_Save_Context */
647
/* Saves the code ranges in a `size' object. */
650
/* exec :: A handle to the source execution context. */
653
/* size :: A handle to the target size object. */
656
/* FreeType error code. 0 means success. */
659
/* Only the glyph loader and debugger should call this function. */
661
FT_LOCAL_DEF( FT_Error )
662
TT_Save_Context( TT_ExecContext exec,
668
/* XXXX: Will probably disappear soon with all the code range */
669
/* management, which is now rather obsolete. */
671
size->num_function_defs = exec->numFDefs;
672
size->num_instruction_defs = exec->numIDefs;
674
size->max_func = exec->maxFunc;
675
size->max_ins = exec->maxIns;
677
for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
678
size->codeRangeTable[i] = exec->codeRangeTable[i];
684
/*************************************************************************/
690
/* Executes one or more instructions in the execution context. */
693
/* debug :: A Boolean flag. If set, the function sets some internal */
694
/* variables and returns immediately, otherwise TT_RunIns() */
697
/* This is commented out currently. */
700
/* exec :: A handle to the target execution context. */
703
/* TrueType error code. 0 means success. */
706
/* Only the glyph loader and debugger should call this function. */
708
FT_LOCAL_DEF( FT_Error )
709
TT_Run_Context( TT_ExecContext exec,
715
if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) )
719
exec->zp0 = exec->pts;
720
exec->zp1 = exec->pts;
721
exec->zp2 = exec->pts;
727
exec->GS.projVector.x = 0x4000;
728
exec->GS.projVector.y = 0x0000;
730
exec->GS.freeVector = exec->GS.projVector;
731
exec->GS.dualVector = exec->GS.projVector;
733
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
734
exec->GS.both_x_axis = TRUE;
737
exec->GS.round_state = 1;
740
/* some glyphs leave something on the stack. so we clean it */
741
/* before a new execution. */
748
return exec->face->interpreter( exec );
751
return TT_RunIns( exec );
758
/* The default value for `scan_control' is documented as FALSE in the */
759
/* TrueType specification. This is confusing since it implies a */
760
/* Boolean value. However, this is not the case, thus both the */
761
/* default values of our `scan_type' and `scan_control' fields (which */
762
/* the documentation's `scan_control' variable is split into) are */
765
const TT_GraphicsState tt_default_graphics_state =
772
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
777
TRUE, 68, 0, 0, 9, 3,
782
/* documentation is in ttinterp.h */
784
FT_EXPORT_DEF( TT_ExecContext )
785
TT_New_Context( TT_Driver driver )
791
memory = driver->root.root.memory;
792
exec = driver->context;
794
if ( !driver->context )
799
/* allocate object */
800
if ( FT_NEW( exec ) )
803
/* initialize it; in case of error this deallocates `exec' too */
804
error = Init_Context( exec, memory );
808
/* store it into the driver */
809
driver->context = exec;
812
return driver->context;
819
/*************************************************************************/
821
/* Before an opcode is executed, the interpreter verifies that there are */
822
/* enough arguments on the stack, with the help of the `Pop_Push_Count' */
825
/* For each opcode, the first column gives the number of arguments that */
826
/* are popped from the stack; the second one gives the number of those */
827
/* that are pushed in result. */
829
/* Opcodes which have a varying number of parameters in the data stream */
830
/* (NPUSHB, NPUSHW) are handled specially; they have a negative value in */
831
/* the `opcode_length' table, and the value in `Pop_Push_Count' is set */
834
/*************************************************************************/
838
#define PACK( x, y ) ( ( x << 4 ) | y )
842
const FT_Byte Pop_Push_Count[256] =
844
/* opcodes are gathered in groups of 16 */
845
/* please keep the spaces as they are */
847
/* SVTCA y */ PACK( 0, 0 ),
848
/* SVTCA x */ PACK( 0, 0 ),
849
/* SPvTCA y */ PACK( 0, 0 ),
850
/* SPvTCA x */ PACK( 0, 0 ),
851
/* SFvTCA y */ PACK( 0, 0 ),
852
/* SFvTCA x */ PACK( 0, 0 ),
853
/* SPvTL // */ PACK( 2, 0 ),
854
/* SPvTL + */ PACK( 2, 0 ),
855
/* SFvTL // */ PACK( 2, 0 ),
856
/* SFvTL + */ PACK( 2, 0 ),
857
/* SPvFS */ PACK( 2, 0 ),
858
/* SFvFS */ PACK( 2, 0 ),
859
/* GPV */ PACK( 0, 2 ),
860
/* GFV */ PACK( 0, 2 ),
861
/* SFvTPv */ PACK( 0, 0 ),
862
/* ISECT */ PACK( 5, 0 ),
864
/* SRP0 */ PACK( 1, 0 ),
865
/* SRP1 */ PACK( 1, 0 ),
866
/* SRP2 */ PACK( 1, 0 ),
867
/* SZP0 */ PACK( 1, 0 ),
868
/* SZP1 */ PACK( 1, 0 ),
869
/* SZP2 */ PACK( 1, 0 ),
870
/* SZPS */ PACK( 1, 0 ),
871
/* SLOOP */ PACK( 1, 0 ),
872
/* RTG */ PACK( 0, 0 ),
873
/* RTHG */ PACK( 0, 0 ),
874
/* SMD */ PACK( 1, 0 ),
875
/* ELSE */ PACK( 0, 0 ),
876
/* JMPR */ PACK( 1, 0 ),
877
/* SCvTCi */ PACK( 1, 0 ),
878
/* SSwCi */ PACK( 1, 0 ),
879
/* SSW */ PACK( 1, 0 ),
881
/* DUP */ PACK( 1, 2 ),
882
/* POP */ PACK( 1, 0 ),
883
/* CLEAR */ PACK( 0, 0 ),
884
/* SWAP */ PACK( 2, 2 ),
885
/* DEPTH */ PACK( 0, 1 ),
886
/* CINDEX */ PACK( 1, 1 ),
887
/* MINDEX */ PACK( 1, 0 ),
888
/* AlignPTS */ PACK( 2, 0 ),
889
/* INS_$28 */ PACK( 0, 0 ),
890
/* UTP */ PACK( 1, 0 ),
891
/* LOOPCALL */ PACK( 2, 0 ),
892
/* CALL */ PACK( 1, 0 ),
893
/* FDEF */ PACK( 1, 0 ),
894
/* ENDF */ PACK( 0, 0 ),
895
/* MDAP[0] */ PACK( 1, 0 ),
896
/* MDAP[1] */ PACK( 1, 0 ),
898
/* IUP[0] */ PACK( 0, 0 ),
899
/* IUP[1] */ PACK( 0, 0 ),
900
/* SHP[0] */ PACK( 0, 0 ),
901
/* SHP[1] */ PACK( 0, 0 ),
902
/* SHC[0] */ PACK( 1, 0 ),
903
/* SHC[1] */ PACK( 1, 0 ),
904
/* SHZ[0] */ PACK( 1, 0 ),
905
/* SHZ[1] */ PACK( 1, 0 ),
906
/* SHPIX */ PACK( 1, 0 ),
907
/* IP */ PACK( 0, 0 ),
908
/* MSIRP[0] */ PACK( 2, 0 ),
909
/* MSIRP[1] */ PACK( 2, 0 ),
910
/* AlignRP */ PACK( 0, 0 ),
911
/* RTDG */ PACK( 0, 0 ),
912
/* MIAP[0] */ PACK( 2, 0 ),
913
/* MIAP[1] */ PACK( 2, 0 ),
915
/* NPushB */ PACK( 0, 0 ),
916
/* NPushW */ PACK( 0, 0 ),
917
/* WS */ PACK( 2, 0 ),
918
/* RS */ PACK( 1, 1 ),
919
/* WCvtP */ PACK( 2, 0 ),
920
/* RCvt */ PACK( 1, 1 ),
921
/* GC[0] */ PACK( 1, 1 ),
922
/* GC[1] */ PACK( 1, 1 ),
923
/* SCFS */ PACK( 2, 0 ),
924
/* MD[0] */ PACK( 2, 1 ),
925
/* MD[1] */ PACK( 2, 1 ),
926
/* MPPEM */ PACK( 0, 1 ),
927
/* MPS */ PACK( 0, 1 ),
928
/* FlipON */ PACK( 0, 0 ),
929
/* FlipOFF */ PACK( 0, 0 ),
930
/* DEBUG */ PACK( 1, 0 ),
932
/* LT */ PACK( 2, 1 ),
933
/* LTEQ */ PACK( 2, 1 ),
934
/* GT */ PACK( 2, 1 ),
935
/* GTEQ */ PACK( 2, 1 ),
936
/* EQ */ PACK( 2, 1 ),
937
/* NEQ */ PACK( 2, 1 ),
938
/* ODD */ PACK( 1, 1 ),
939
/* EVEN */ PACK( 1, 1 ),
940
/* IF */ PACK( 1, 0 ),
941
/* EIF */ PACK( 0, 0 ),
942
/* AND */ PACK( 2, 1 ),
943
/* OR */ PACK( 2, 1 ),
944
/* NOT */ PACK( 1, 1 ),
945
/* DeltaP1 */ PACK( 1, 0 ),
946
/* SDB */ PACK( 1, 0 ),
947
/* SDS */ PACK( 1, 0 ),
949
/* ADD */ PACK( 2, 1 ),
950
/* SUB */ PACK( 2, 1 ),
951
/* DIV */ PACK( 2, 1 ),
952
/* MUL */ PACK( 2, 1 ),
953
/* ABS */ PACK( 1, 1 ),
954
/* NEG */ PACK( 1, 1 ),
955
/* FLOOR */ PACK( 1, 1 ),
956
/* CEILING */ PACK( 1, 1 ),
957
/* ROUND[0] */ PACK( 1, 1 ),
958
/* ROUND[1] */ PACK( 1, 1 ),
959
/* ROUND[2] */ PACK( 1, 1 ),
960
/* ROUND[3] */ PACK( 1, 1 ),
961
/* NROUND[0] */ PACK( 1, 1 ),
962
/* NROUND[1] */ PACK( 1, 1 ),
963
/* NROUND[2] */ PACK( 1, 1 ),
964
/* NROUND[3] */ PACK( 1, 1 ),
966
/* WCvtF */ PACK( 2, 0 ),
967
/* DeltaP2 */ PACK( 1, 0 ),
968
/* DeltaP3 */ PACK( 1, 0 ),
969
/* DeltaCn[0] */ PACK( 1, 0 ),
970
/* DeltaCn[1] */ PACK( 1, 0 ),
971
/* DeltaCn[2] */ PACK( 1, 0 ),
972
/* SROUND */ PACK( 1, 0 ),
973
/* S45Round */ PACK( 1, 0 ),
974
/* JROT */ PACK( 2, 0 ),
975
/* JROF */ PACK( 2, 0 ),
976
/* ROFF */ PACK( 0, 0 ),
977
/* INS_$7B */ PACK( 0, 0 ),
978
/* RUTG */ PACK( 0, 0 ),
979
/* RDTG */ PACK( 0, 0 ),
980
/* SANGW */ PACK( 1, 0 ),
981
/* AA */ PACK( 1, 0 ),
983
/* FlipPT */ PACK( 0, 0 ),
984
/* FlipRgON */ PACK( 2, 0 ),
985
/* FlipRgOFF */ PACK( 2, 0 ),
986
/* INS_$83 */ PACK( 0, 0 ),
987
/* INS_$84 */ PACK( 0, 0 ),
988
/* ScanCTRL */ PACK( 1, 0 ),
989
/* SDVPTL[0] */ PACK( 2, 0 ),
990
/* SDVPTL[1] */ PACK( 2, 0 ),
991
/* GetINFO */ PACK( 1, 1 ),
992
/* IDEF */ PACK( 1, 0 ),
993
/* ROLL */ PACK( 3, 3 ),
994
/* MAX */ PACK( 2, 1 ),
995
/* MIN */ PACK( 2, 1 ),
996
/* ScanTYPE */ PACK( 1, 0 ),
997
/* InstCTRL */ PACK( 2, 0 ),
998
/* INS_$8F */ PACK( 0, 0 ),
1000
/* INS_$90 */ PACK( 0, 0 ),
1001
/* INS_$91 */ PACK( 0, 0 ),
1002
/* INS_$92 */ PACK( 0, 0 ),
1003
/* INS_$93 */ PACK( 0, 0 ),
1004
/* INS_$94 */ PACK( 0, 0 ),
1005
/* INS_$95 */ PACK( 0, 0 ),
1006
/* INS_$96 */ PACK( 0, 0 ),
1007
/* INS_$97 */ PACK( 0, 0 ),
1008
/* INS_$98 */ PACK( 0, 0 ),
1009
/* INS_$99 */ PACK( 0, 0 ),
1010
/* INS_$9A */ PACK( 0, 0 ),
1011
/* INS_$9B */ PACK( 0, 0 ),
1012
/* INS_$9C */ PACK( 0, 0 ),
1013
/* INS_$9D */ PACK( 0, 0 ),
1014
/* INS_$9E */ PACK( 0, 0 ),
1015
/* INS_$9F */ PACK( 0, 0 ),
1017
/* INS_$A0 */ PACK( 0, 0 ),
1018
/* INS_$A1 */ PACK( 0, 0 ),
1019
/* INS_$A2 */ PACK( 0, 0 ),
1020
/* INS_$A3 */ PACK( 0, 0 ),
1021
/* INS_$A4 */ PACK( 0, 0 ),
1022
/* INS_$A5 */ PACK( 0, 0 ),
1023
/* INS_$A6 */ PACK( 0, 0 ),
1024
/* INS_$A7 */ PACK( 0, 0 ),
1025
/* INS_$A8 */ PACK( 0, 0 ),
1026
/* INS_$A9 */ PACK( 0, 0 ),
1027
/* INS_$AA */ PACK( 0, 0 ),
1028
/* INS_$AB */ PACK( 0, 0 ),
1029
/* INS_$AC */ PACK( 0, 0 ),
1030
/* INS_$AD */ PACK( 0, 0 ),
1031
/* INS_$AE */ PACK( 0, 0 ),
1032
/* INS_$AF */ PACK( 0, 0 ),
1034
/* PushB[0] */ PACK( 0, 1 ),
1035
/* PushB[1] */ PACK( 0, 2 ),
1036
/* PushB[2] */ PACK( 0, 3 ),
1037
/* PushB[3] */ PACK( 0, 4 ),
1038
/* PushB[4] */ PACK( 0, 5 ),
1039
/* PushB[5] */ PACK( 0, 6 ),
1040
/* PushB[6] */ PACK( 0, 7 ),
1041
/* PushB[7] */ PACK( 0, 8 ),
1042
/* PushW[0] */ PACK( 0, 1 ),
1043
/* PushW[1] */ PACK( 0, 2 ),
1044
/* PushW[2] */ PACK( 0, 3 ),
1045
/* PushW[3] */ PACK( 0, 4 ),
1046
/* PushW[4] */ PACK( 0, 5 ),
1047
/* PushW[5] */ PACK( 0, 6 ),
1048
/* PushW[6] */ PACK( 0, 7 ),
1049
/* PushW[7] */ PACK( 0, 8 ),
1051
/* MDRP[00] */ PACK( 1, 0 ),
1052
/* MDRP[01] */ PACK( 1, 0 ),
1053
/* MDRP[02] */ PACK( 1, 0 ),
1054
/* MDRP[03] */ PACK( 1, 0 ),
1055
/* MDRP[04] */ PACK( 1, 0 ),
1056
/* MDRP[05] */ PACK( 1, 0 ),
1057
/* MDRP[06] */ PACK( 1, 0 ),
1058
/* MDRP[07] */ PACK( 1, 0 ),
1059
/* MDRP[08] */ PACK( 1, 0 ),
1060
/* MDRP[09] */ PACK( 1, 0 ),
1061
/* MDRP[10] */ PACK( 1, 0 ),
1062
/* MDRP[11] */ PACK( 1, 0 ),
1063
/* MDRP[12] */ PACK( 1, 0 ),
1064
/* MDRP[13] */ PACK( 1, 0 ),
1065
/* MDRP[14] */ PACK( 1, 0 ),
1066
/* MDRP[15] */ PACK( 1, 0 ),
1068
/* MDRP[16] */ PACK( 1, 0 ),
1069
/* MDRP[17] */ PACK( 1, 0 ),
1070
/* MDRP[18] */ PACK( 1, 0 ),
1071
/* MDRP[19] */ PACK( 1, 0 ),
1072
/* MDRP[20] */ PACK( 1, 0 ),
1073
/* MDRP[21] */ PACK( 1, 0 ),
1074
/* MDRP[22] */ PACK( 1, 0 ),
1075
/* MDRP[23] */ PACK( 1, 0 ),
1076
/* MDRP[24] */ PACK( 1, 0 ),
1077
/* MDRP[25] */ PACK( 1, 0 ),
1078
/* MDRP[26] */ PACK( 1, 0 ),
1079
/* MDRP[27] */ PACK( 1, 0 ),
1080
/* MDRP[28] */ PACK( 1, 0 ),
1081
/* MDRP[29] */ PACK( 1, 0 ),
1082
/* MDRP[30] */ PACK( 1, 0 ),
1083
/* MDRP[31] */ PACK( 1, 0 ),
1085
/* MIRP[00] */ PACK( 2, 0 ),
1086
/* MIRP[01] */ PACK( 2, 0 ),
1087
/* MIRP[02] */ PACK( 2, 0 ),
1088
/* MIRP[03] */ PACK( 2, 0 ),
1089
/* MIRP[04] */ PACK( 2, 0 ),
1090
/* MIRP[05] */ PACK( 2, 0 ),
1091
/* MIRP[06] */ PACK( 2, 0 ),
1092
/* MIRP[07] */ PACK( 2, 0 ),
1093
/* MIRP[08] */ PACK( 2, 0 ),
1094
/* MIRP[09] */ PACK( 2, 0 ),
1095
/* MIRP[10] */ PACK( 2, 0 ),
1096
/* MIRP[11] */ PACK( 2, 0 ),
1097
/* MIRP[12] */ PACK( 2, 0 ),
1098
/* MIRP[13] */ PACK( 2, 0 ),
1099
/* MIRP[14] */ PACK( 2, 0 ),
1100
/* MIRP[15] */ PACK( 2, 0 ),
1102
/* MIRP[16] */ PACK( 2, 0 ),
1103
/* MIRP[17] */ PACK( 2, 0 ),
1104
/* MIRP[18] */ PACK( 2, 0 ),
1105
/* MIRP[19] */ PACK( 2, 0 ),
1106
/* MIRP[20] */ PACK( 2, 0 ),
1107
/* MIRP[21] */ PACK( 2, 0 ),
1108
/* MIRP[22] */ PACK( 2, 0 ),
1109
/* MIRP[23] */ PACK( 2, 0 ),
1110
/* MIRP[24] */ PACK( 2, 0 ),
1111
/* MIRP[25] */ PACK( 2, 0 ),
1112
/* MIRP[26] */ PACK( 2, 0 ),
1113
/* MIRP[27] */ PACK( 2, 0 ),
1114
/* MIRP[28] */ PACK( 2, 0 ),
1115
/* MIRP[29] */ PACK( 2, 0 ),
1116
/* MIRP[30] */ PACK( 2, 0 ),
1117
/* MIRP[31] */ PACK( 2, 0 )
1121
#ifdef FT_DEBUG_LEVEL_TRACE
1124
const char* const opcode_name[256] =
1399
#endif /* FT_DEBUG_LEVEL_TRACE */
1403
const FT_Char opcode_length[256] =
1405
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1406
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1407
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1408
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1410
-1,-2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1411
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1412
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1413
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1415
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1416
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1417
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1418
2, 3, 4, 5, 6, 7, 8, 9, 3, 5, 7, 9, 11,13,15,17,
1420
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1421
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1422
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1423
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
1431
TT_MulFix14( FT_Int32 a,
1435
FT_UInt32 ah, al, mid, lo, hi;
1445
ah = (FT_UInt32)( ( a >> 16 ) & 0xFFFFU );
1446
al = (FT_UInt32)( a & 0xFFFFU );
1451
mid = ( mid << 16 ) + ( 1 << 13 ); /* rounding */
1456
mid = ( lo >> 14 ) | ( hi << 18 );
1458
return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid;
1463
/* compute (a*b)/2^14 with maximal accuracy and rounding */
1465
TT_MulFix14( FT_Int32 a,
1472
/* compute ax*bx as 64-bit value */
1473
l = (FT_UInt32)( ( a & 0xFFFFU ) * b );
1474
m = ( a >> 16 ) * b;
1476
lo = l + (FT_UInt32)( m << 16 );
1477
hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l );
1479
/* divide the result by 2^14 with rounding */
1481
l = lo + (FT_UInt32)s;
1482
hi += s + ( l < lo );
1488
return ( hi << 18 ) | ( l >> 14 );
1493
/* compute (ax*bx+ay*by)/2^14 with maximal accuracy and rounding */
1495
TT_DotFix14( FT_Int32 ax,
1500
FT_Int32 m, s, hi1, hi2, hi;
1501
FT_UInt32 l, lo1, lo2, lo;
1504
/* compute ax*bx as 64-bit value */
1505
l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx );
1506
m = ( ax >> 16 ) * bx;
1508
lo1 = l + (FT_UInt32)( m << 16 );
1509
hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l );
1511
/* compute ay*by as 64-bit value */
1512
l = (FT_UInt32)( ( ay & 0xFFFFU ) * by );
1513
m = ( ay >> 16 ) * by;
1515
lo2 = l + (FT_UInt32)( m << 16 );
1516
hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l );
1520
hi = hi1 + hi2 + ( lo < lo1 );
1522
/* divide the result by 2^14 with rounding */
1524
l = lo + (FT_UInt32)s;
1525
hi += s + ( l < lo );
1531
return ( hi << 18 ) | ( l >> 14 );
1535
/* return length of given vector */
1540
TT_VecLen( FT_Int32 x,
1543
FT_Int32 m, hi1, hi2, hi;
1544
FT_UInt32 l, lo1, lo2, lo;
1547
/* compute x*x as 64-bit value */
1548
lo = (FT_UInt32)( x & 0xFFFFU );
1555
lo1 = l + (FT_UInt32)( m << 17 );
1556
hi1 = hi + ( m >> 15 ) + ( lo1 < l );
1558
/* compute y*y as 64-bit value */
1559
lo = (FT_UInt32)( y & 0xFFFFU );
1566
lo2 = l + (FT_UInt32)( m << 17 );
1567
hi2 = hi + ( m >> 15 ) + ( lo2 < l );
1569
/* add them to get 'x*x+y*y' as 64-bit value */
1571
hi = hi1 + hi2 + ( lo < lo1 );
1573
/* compute the square root of this value */
1575
FT_UInt32 root, rem, test_div;
1586
rem = ( rem << 2 ) | ( (FT_UInt32)hi >> 30 );
1587
hi = ( hi << 2 ) | ( lo >> 30 );
1590
test_div = ( root << 1 ) + 1;
1592
if ( rem >= test_div )
1597
} while ( --count );
1600
return (FT_Int32)root;
1606
/* this version uses FT_Vector_Length which computes the same value */
1607
/* much, much faster.. */
1610
TT_VecLen( FT_F26Dot6 X,
1619
return FT_Vector_Length( &v );
1625
/*************************************************************************/
1631
/* Returns the current aspect ratio scaling factor depending on the */
1632
/* projection vector's state and device resolutions. */
1635
/* The aspect ratio in 16.16 format, always <= 1.0 . */
1638
Current_Ratio( EXEC_OP )
1640
if ( !CUR.tt_metrics.ratio )
1642
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
1643
if ( CUR.face->unpatented_hinting )
1645
if ( CUR.GS.both_x_axis )
1646
CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
1648
CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
1653
if ( CUR.GS.projVector.y == 0 )
1654
CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
1656
else if ( CUR.GS.projVector.x == 0 )
1657
CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
1664
x = TT_MULDIV( CUR.GS.projVector.x,
1665
CUR.tt_metrics.x_ratio, 0x4000 );
1666
y = TT_MULDIV( CUR.GS.projVector.y,
1667
CUR.tt_metrics.y_ratio, 0x4000 );
1668
CUR.tt_metrics.ratio = TT_VecLen( x, y );
1672
return CUR.tt_metrics.ratio;
1677
Current_Ppem( EXEC_OP )
1679
return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() );
1683
/*************************************************************************/
1685
/* Functions related to the control value table (CVT). */
1687
/*************************************************************************/
1690
FT_CALLBACK_DEF( FT_F26Dot6 )
1691
Read_CVT( EXEC_OP_ FT_ULong idx )
1693
return CUR.cvt[idx];
1697
FT_CALLBACK_DEF( FT_F26Dot6 )
1698
Read_CVT_Stretched( EXEC_OP_ FT_ULong idx )
1700
return TT_MULFIX( CUR.cvt[idx], CURRENT_Ratio() );
1704
FT_CALLBACK_DEF( void )
1705
Write_CVT( EXEC_OP_ FT_ULong idx,
1708
CUR.cvt[idx] = value;
1712
FT_CALLBACK_DEF( void )
1713
Write_CVT_Stretched( EXEC_OP_ FT_ULong idx,
1716
CUR.cvt[idx] = FT_DivFix( value, CURRENT_Ratio() );
1720
FT_CALLBACK_DEF( void )
1721
Move_CVT( EXEC_OP_ FT_ULong idx,
1724
CUR.cvt[idx] += value;
1728
FT_CALLBACK_DEF( void )
1729
Move_CVT_Stretched( EXEC_OP_ FT_ULong idx,
1732
CUR.cvt[idx] += FT_DivFix( value, CURRENT_Ratio() );
1736
/*************************************************************************/
1742
/* Returns a short integer taken from the instruction stream at */
1746
/* Short read at code[IP]. */
1749
/* This one could become a macro. */
1752
GetShortIns( EXEC_OP )
1754
/* Reading a byte stream so there is no endianess (DaveP) */
1756
return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) +
1757
CUR.code[CUR.IP - 1] );
1761
/*************************************************************************/
1764
/* Ins_Goto_CodeRange */
1767
/* Goes to a certain code range in the instruction stream. */
1770
/* aRange :: The index of the code range. */
1772
/* aIP :: The new IP address in the code range. */
1775
/* SUCCESS or FAILURE. */
1778
Ins_Goto_CodeRange( EXEC_OP_ FT_Int aRange,
1781
TT_CodeRange* range;
1784
if ( aRange < 1 || aRange > 3 )
1786
CUR.error = TT_Err_Bad_Argument;
1790
range = &CUR.codeRangeTable[aRange - 1];
1792
if ( range->base == NULL ) /* invalid coderange */
1794
CUR.error = TT_Err_Invalid_CodeRange;
1798
/* NOTE: Because the last instruction of a program may be a CALL */
1799
/* which will return to the first byte *after* the code */
1800
/* range, we test for AIP <= Size, instead of AIP < Size. */
1802
if ( aIP > range->size )
1804
CUR.error = TT_Err_Code_Overflow;
1808
CUR.code = range->base;
1809
CUR.codeSize = range->size;
1811
CUR.curRange = aRange;
1817
/*************************************************************************/
1823
/* Moves a point by a given distance along the freedom vector. The */
1824
/* point will be `touched'. */
1827
/* point :: The index of the point to move. */
1829
/* distance :: The distance to apply. */
1832
/* zone :: The affected glyph zone. */
1835
Direct_Move( EXEC_OP_ TT_GlyphZone zone,
1837
FT_F26Dot6 distance )
1842
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
1843
FT_ASSERT( !CUR.face->unpatented_hinting );
1846
v = CUR.GS.freeVector.x;
1850
zone->cur[point].x += TT_MULDIV( distance,
1854
zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
1857
v = CUR.GS.freeVector.y;
1861
zone->cur[point].y += TT_MULDIV( distance,
1865
zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
1870
/*************************************************************************/
1873
/* Direct_Move_Orig */
1876
/* Moves the *original* position of a point by a given distance along */
1877
/* the freedom vector. Obviously, the point will not be `touched'. */
1880
/* point :: The index of the point to move. */
1882
/* distance :: The distance to apply. */
1885
/* zone :: The affected glyph zone. */
1888
Direct_Move_Orig( EXEC_OP_ TT_GlyphZone zone,
1890
FT_F26Dot6 distance )
1895
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
1896
FT_ASSERT( !CUR.face->unpatented_hinting );
1899
v = CUR.GS.freeVector.x;
1902
zone->org[point].x += TT_MULDIV( distance,
1906
v = CUR.GS.freeVector.y;
1909
zone->org[point].y += TT_MULDIV( distance,
1915
/*************************************************************************/
1917
/* Special versions of Direct_Move() */
1919
/* The following versions are used whenever both vectors are both */
1920
/* along one of the coordinate unit vectors, i.e. in 90% of the cases. */
1922
/*************************************************************************/
1926
Direct_Move_X( EXEC_OP_ TT_GlyphZone zone,
1928
FT_F26Dot6 distance )
1932
zone->cur[point].x += distance;
1933
zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
1938
Direct_Move_Y( EXEC_OP_ TT_GlyphZone zone,
1940
FT_F26Dot6 distance )
1944
zone->cur[point].y += distance;
1945
zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
1949
/*************************************************************************/
1951
/* Special versions of Direct_Move_Orig() */
1953
/* The following versions are used whenever both vectors are both */
1954
/* along one of the coordinate unit vectors, i.e. in 90% of the cases. */
1956
/*************************************************************************/
1960
Direct_Move_Orig_X( EXEC_OP_ TT_GlyphZone zone,
1962
FT_F26Dot6 distance )
1966
zone->org[point].x += distance;
1971
Direct_Move_Orig_Y( EXEC_OP_ TT_GlyphZone zone,
1973
FT_F26Dot6 distance )
1977
zone->org[point].y += distance;
1981
/*************************************************************************/
1987
/* Does not round, but adds engine compensation. */
1990
/* distance :: The distance (not) to round. */
1992
/* compensation :: The engine compensation. */
1995
/* The compensated distance. */
1998
/* The TrueType specification says very few about the relationship */
1999
/* between rounding and engine compensation. However, it seems from */
2000
/* the description of super round that we should add the compensation */
2001
/* before rounding. */
2004
Round_None( EXEC_OP_ FT_F26Dot6 distance,
2005
FT_F26Dot6 compensation )
2012
if ( distance >= 0 )
2014
val = distance + compensation;
2015
if ( distance && val < 0 )
2020
val = distance - compensation;
2028
/*************************************************************************/
2034
/* Rounds value to grid after adding engine compensation. */
2037
/* distance :: The distance to round. */
2039
/* compensation :: The engine compensation. */
2042
/* Rounded distance. */
2045
Round_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
2046
FT_F26Dot6 compensation )
2053
if ( distance >= 0 )
2055
val = distance + compensation + 32;
2056
if ( distance && val > 0 )
2063
val = -FT_PIX_ROUND( compensation - distance );
2072
/*************************************************************************/
2075
/* Round_To_Half_Grid */
2078
/* Rounds value to half grid after adding engine compensation. */
2081
/* distance :: The distance to round. */
2083
/* compensation :: The engine compensation. */
2086
/* Rounded distance. */
2089
Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6 distance,
2090
FT_F26Dot6 compensation )
2097
if ( distance >= 0 )
2099
val = FT_PIX_FLOOR( distance + compensation ) + 32;
2100
if ( distance && val < 0 )
2105
val = -( FT_PIX_FLOOR( compensation - distance ) + 32 );
2114
/*************************************************************************/
2117
/* Round_Down_To_Grid */
2120
/* Rounds value down to grid after adding engine compensation. */
2123
/* distance :: The distance to round. */
2125
/* compensation :: The engine compensation. */
2128
/* Rounded distance. */
2131
Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
2132
FT_F26Dot6 compensation )
2139
if ( distance >= 0 )
2141
val = distance + compensation;
2142
if ( distance && val > 0 )
2149
val = -( ( compensation - distance ) & -64 );
2158
/*************************************************************************/
2161
/* Round_Up_To_Grid */
2164
/* Rounds value up to grid after adding engine compensation. */
2167
/* distance :: The distance to round. */
2169
/* compensation :: The engine compensation. */
2172
/* Rounded distance. */
2175
Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
2176
FT_F26Dot6 compensation )
2183
if ( distance >= 0 )
2185
val = distance + compensation + 63;
2186
if ( distance && val > 0 )
2193
val = - FT_PIX_CEIL( compensation - distance );
2202
/*************************************************************************/
2205
/* Round_To_Double_Grid */
2208
/* Rounds value to double grid after adding engine compensation. */
2211
/* distance :: The distance to round. */
2213
/* compensation :: The engine compensation. */
2216
/* Rounded distance. */
2219
Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6 distance,
2220
FT_F26Dot6 compensation )
2227
if ( distance >= 0 )
2229
val = distance + compensation + 16;
2230
if ( distance && val > 0 )
2237
val = -FT_PAD_ROUND( compensation - distance, 32 );
2246
/*************************************************************************/
2252
/* Super-rounds value to grid after adding engine compensation. */
2255
/* distance :: The distance to round. */
2257
/* compensation :: The engine compensation. */
2260
/* Rounded distance. */
2263
/* The TrueType specification says very few about the relationship */
2264
/* between rounding and engine compensation. However, it seems from */
2265
/* the description of super round that we should add the compensation */
2266
/* before rounding. */
2269
Round_Super( EXEC_OP_ FT_F26Dot6 distance,
2270
FT_F26Dot6 compensation )
2275
if ( distance >= 0 )
2277
val = ( distance - CUR.phase + CUR.threshold + compensation ) &
2279
if ( distance && val < 0 )
2285
val = -( ( CUR.threshold - CUR.phase - distance + compensation ) &
2296
/*************************************************************************/
2299
/* Round_Super_45 */
2302
/* Super-rounds value to grid after adding engine compensation. */
2305
/* distance :: The distance to round. */
2307
/* compensation :: The engine compensation. */
2310
/* Rounded distance. */
2313
/* There is a separate function for Round_Super_45() as we may need */
2314
/* greater precision. */
2317
Round_Super_45( EXEC_OP_ FT_F26Dot6 distance,
2318
FT_F26Dot6 compensation )
2323
if ( distance >= 0 )
2325
val = ( ( distance - CUR.phase + CUR.threshold + compensation ) /
2326
CUR.period ) * CUR.period;
2327
if ( distance && val < 0 )
2333
val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) /
2334
CUR.period ) * CUR.period );
2344
/*************************************************************************/
2350
/* Sets the rounding mode. */
2353
/* round_mode :: The rounding mode to be used. */
2356
Compute_Round( EXEC_OP_ FT_Byte round_mode )
2358
switch ( round_mode )
2361
CUR.func_round = (TT_Round_Func)Round_None;
2364
case TT_Round_To_Grid:
2365
CUR.func_round = (TT_Round_Func)Round_To_Grid;
2368
case TT_Round_Up_To_Grid:
2369
CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
2372
case TT_Round_Down_To_Grid:
2373
CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
2376
case TT_Round_To_Half_Grid:
2377
CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
2380
case TT_Round_To_Double_Grid:
2381
CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
2384
case TT_Round_Super:
2385
CUR.func_round = (TT_Round_Func)Round_Super;
2388
case TT_Round_Super_45:
2389
CUR.func_round = (TT_Round_Func)Round_Super_45;
2395
/*************************************************************************/
2401
/* Sets Super Round parameters. */
2404
/* GridPeriod :: Grid period */
2405
/* selector :: SROUND opcode */
2408
SetSuperRound( EXEC_OP_ FT_F26Dot6 GridPeriod,
2411
switch ( (FT_Int)( selector & 0xC0 ) )
2414
CUR.period = GridPeriod / 2;
2418
CUR.period = GridPeriod;
2422
CUR.period = GridPeriod * 2;
2425
/* This opcode is reserved, but... */
2428
CUR.period = GridPeriod;
2432
switch ( (FT_Int)( selector & 0x30 ) )
2439
CUR.phase = CUR.period / 4;
2443
CUR.phase = CUR.period / 2;
2447
CUR.phase = CUR.period * 3 / 4;
2451
if ( ( selector & 0x0F ) == 0 )
2452
CUR.threshold = CUR.period - 1;
2454
CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8;
2458
CUR.threshold /= 256;
2462
/*************************************************************************/
2468
/* Computes the projection of vector given by (v2-v1) along the */
2469
/* current projection vector. */
2472
/* v1 :: First input vector. */
2473
/* v2 :: Second input vector. */
2476
/* The distance in F26dot6 format. */
2479
Project( EXEC_OP_ FT_Pos dx,
2482
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
2483
FT_ASSERT( !CUR.face->unpatented_hinting );
2486
return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,
2487
CUR.GS.projVector.x,
2488
CUR.GS.projVector.y );
2492
/*************************************************************************/
2498
/* Computes the projection of the vector given by (v2-v1) along the */
2499
/* current dual vector. */
2502
/* v1 :: First input vector. */
2503
/* v2 :: Second input vector. */
2506
/* The distance in F26dot6 format. */
2509
Dual_Project( EXEC_OP_ FT_Pos dx,
2512
return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,
2513
CUR.GS.dualVector.x,
2514
CUR.GS.dualVector.y );
2518
/*************************************************************************/
2524
/* Computes the projection of the vector given by (v2-v1) along the */
2525
/* horizontal axis. */
2528
/* v1 :: First input vector. */
2529
/* v2 :: Second input vector. */
2532
/* The distance in F26dot6 format. */
2535
Project_x( EXEC_OP_ FT_Pos dx,
2545
/*************************************************************************/
2551
/* Computes the projection of the vector given by (v2-v1) along the */
2552
/* vertical axis. */
2555
/* v1 :: First input vector. */
2556
/* v2 :: Second input vector. */
2559
/* The distance in F26dot6 format. */
2562
Project_y( EXEC_OP_ FT_Pos dx,
2572
/*************************************************************************/
2578
/* Computes the projection and movement function pointers according */
2579
/* to the current graphics state. */
2582
Compute_Funcs( EXEC_OP )
2584
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
2585
if ( CUR.face->unpatented_hinting )
2587
/* If both vectors point rightwards along the x axis, set */
2588
/* `both-x-axis' true, otherwise set it false. The x values only */
2589
/* need be tested because the vector has been normalised to a unit */
2590
/* vector of length 0x4000 = unity. */
2591
CUR.GS.both_x_axis = (FT_Bool)( CUR.GS.projVector.x == 0x4000 &&
2592
CUR.GS.freeVector.x == 0x4000 );
2594
/* Throw away projection and freedom vector information */
2595
/* because the patents don't allow them to be stored. */
2596
/* The relevant US Patents are 5155805 and 5325479. */
2597
CUR.GS.projVector.x = 0;
2598
CUR.GS.projVector.y = 0;
2599
CUR.GS.freeVector.x = 0;
2600
CUR.GS.freeVector.y = 0;
2602
if ( CUR.GS.both_x_axis )
2604
CUR.func_project = Project_x;
2605
CUR.func_move = Direct_Move_X;
2606
CUR.func_move_orig = Direct_Move_Orig_X;
2610
CUR.func_project = Project_y;
2611
CUR.func_move = Direct_Move_Y;
2612
CUR.func_move_orig = Direct_Move_Orig_Y;
2615
if ( CUR.GS.dualVector.x == 0x4000 )
2616
CUR.func_dualproj = Project_x;
2619
if ( CUR.GS.dualVector.y == 0x4000 )
2620
CUR.func_dualproj = Project_y;
2622
CUR.func_dualproj = Dual_Project;
2625
/* Force recalculation of cached aspect ratio */
2626
CUR.tt_metrics.ratio = 0;
2630
#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */
2632
if ( CUR.GS.freeVector.x == 0x4000 )
2633
CUR.F_dot_P = CUR.GS.projVector.x * 0x10000L;
2636
if ( CUR.GS.freeVector.y == 0x4000 )
2637
CUR.F_dot_P = CUR.GS.projVector.y * 0x10000L;
2639
CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 +
2640
(FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4;
2643
if ( CUR.GS.projVector.x == 0x4000 )
2644
CUR.func_project = (TT_Project_Func)Project_x;
2647
if ( CUR.GS.projVector.y == 0x4000 )
2648
CUR.func_project = (TT_Project_Func)Project_y;
2650
CUR.func_project = (TT_Project_Func)Project;
2653
if ( CUR.GS.dualVector.x == 0x4000 )
2654
CUR.func_dualproj = (TT_Project_Func)Project_x;
2657
if ( CUR.GS.dualVector.y == 0x4000 )
2658
CUR.func_dualproj = (TT_Project_Func)Project_y;
2660
CUR.func_dualproj = (TT_Project_Func)Dual_Project;
2663
CUR.func_move = (TT_Move_Func)Direct_Move;
2664
CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig;
2666
if ( CUR.F_dot_P == 0x40000000L )
2668
if ( CUR.GS.freeVector.x == 0x4000 )
2670
CUR.func_move = (TT_Move_Func)Direct_Move_X;
2671
CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
2675
if ( CUR.GS.freeVector.y == 0x4000 )
2677
CUR.func_move = (TT_Move_Func)Direct_Move_Y;
2678
CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
2683
/* at small sizes, F_dot_P can become too small, resulting */
2684
/* in overflows and `spikes' in a number of glyphs like `w'. */
2686
if ( FT_ABS( CUR.F_dot_P ) < 0x4000000L )
2687
CUR.F_dot_P = 0x40000000L;
2689
/* Disable cached aspect ratio */
2690
CUR.tt_metrics.ratio = 0;
2694
/*************************************************************************/
2700
/* Norms a vector. */
2703
/* Vx :: The horizontal input vector coordinate. */
2704
/* Vy :: The vertical input vector coordinate. */
2707
/* R :: The normed unit vector. */
2710
/* Returns FAILURE if a vector parameter is zero. */
2713
/* In case Vx and Vy are both zero, Normalize() returns SUCCESS, and */
2714
/* R is undefined. */
2719
Normalize( EXEC_OP_ FT_F26Dot6 Vx,
2729
if ( FT_ABS( Vx ) < 0x10000L && FT_ABS( Vy ) < 0x10000L )
2734
W = TT_VecLen( Vx, Vy );
2738
/* XXX: UNDOCUMENTED! It seems that it is possible to try */
2739
/* to normalize the vector (0,0). Return immediately. */
2743
R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W );
2744
R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W );
2749
W = TT_VecLen( Vx, Vy );
2751
Vx = FT_MulDiv( Vx, 0x4000L, W );
2752
Vy = FT_MulDiv( Vy, 0x4000L, W );
2754
W = Vx * Vx + Vy * Vy;
2756
/* Now, we want that Sqrt( W ) = 0x4000 */
2757
/* Or 0x10000000 <= W < 0x10004000 */
2775
while ( W < 0x10000000L )
2777
/* We need to increase W by a minimal amount */
2783
W = Vx * Vx + Vy * Vy;
2786
while ( W >= 0x10004000L )
2788
/* We need to decrease W by a minimal amount */
2794
W = Vx * Vx + Vy * Vy;
2797
/* Note that in various cases, we can only */
2798
/* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */
2806
R->x = (FT_F2Dot14)Vx; /* Type conversion */
2807
R->y = (FT_F2Dot14)Vy; /* Type conversion */
2813
/*************************************************************************/
2815
/* Here we start with the implementation of the various opcodes. */
2817
/*************************************************************************/
2821
Ins_SxVTL( EXEC_OP_ FT_UShort aIdx1,
2824
FT_UnitVector* Vec )
2831
if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||
2832
BOUNDS( aIdx2, CUR.zp1.n_points ) )
2834
if ( CUR.pedantic_hinting )
2835
CUR.error = TT_Err_Invalid_Reference;
2839
p1 = CUR.zp1.cur + aIdx2;
2840
p2 = CUR.zp2.cur + aIdx1;
2845
if ( ( aOpc & 1 ) != 0 )
2847
C = B; /* counter clockwise rotation */
2852
NORMalize( A, B, Vec );
2858
/* When not using the big switch statements, the interpreter uses a */
2859
/* call table defined later below in this source. Each opcode must */
2860
/* thus have a corresponding function, even trivial ones. */
2862
/* They are all defined there. */
2869
A = (FT_Short)( CUR.opcode & 1 ) << 14; \
2870
B = A ^ (FT_Short)0x4000; \
2872
CUR.GS.freeVector.x = A; \
2873
CUR.GS.projVector.x = A; \
2874
CUR.GS.dualVector.x = A; \
2876
CUR.GS.freeVector.y = B; \
2877
CUR.GS.projVector.y = B; \
2878
CUR.GS.dualVector.y = B; \
2889
A = (FT_Short)( CUR.opcode & 1 ) << 14; \
2890
B = A ^ (FT_Short)0x4000; \
2892
CUR.GS.projVector.x = A; \
2893
CUR.GS.dualVector.x = A; \
2895
CUR.GS.projVector.y = B; \
2896
CUR.GS.dualVector.y = B; \
2898
GUESS_VECTOR( freeVector ); \
2909
A = (FT_Short)( CUR.opcode & 1 ) << 14; \
2910
B = A ^ (FT_Short)0x4000; \
2912
CUR.GS.freeVector.x = A; \
2913
CUR.GS.freeVector.y = B; \
2915
GUESS_VECTOR( projVector ); \
2922
if ( INS_SxVTL( (FT_UShort)args[1], \
2923
(FT_UShort)args[0], \
2925
&CUR.GS.projVector ) == SUCCESS ) \
2927
CUR.GS.dualVector = CUR.GS.projVector; \
2928
GUESS_VECTOR( freeVector ); \
2934
if ( INS_SxVTL( (FT_UShort)args[1], \
2935
(FT_UShort)args[0], \
2937
&CUR.GS.freeVector ) == SUCCESS ) \
2939
GUESS_VECTOR( projVector ); \
2945
GUESS_VECTOR( projVector ); \
2946
CUR.GS.freeVector = CUR.GS.projVector; \
2956
/* Only use low 16bits, then sign extend */ \
2957
S = (FT_Short)args[1]; \
2959
S = (FT_Short)args[0]; \
2962
NORMalize( X, Y, &CUR.GS.projVector ); \
2964
CUR.GS.dualVector = CUR.GS.projVector; \
2965
GUESS_VECTOR( freeVector ); \
2976
/* Only use low 16bits, then sign extend */ \
2977
S = (FT_Short)args[1]; \
2979
S = (FT_Short)args[0]; \
2982
NORMalize( X, Y, &CUR.GS.freeVector ); \
2983
GUESS_VECTOR( projVector ); \
2988
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
2990
if ( CUR.face->unpatented_hinting ) \
2992
args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
2993
args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
2997
args[0] = CUR.GS.projVector.x; \
2998
args[1] = CUR.GS.projVector.y; \
3002
args[0] = CUR.GS.projVector.x; \
3003
args[1] = CUR.GS.projVector.y;
3007
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
3009
if ( CUR.face->unpatented_hinting ) \
3011
args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
3012
args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
3016
args[0] = CUR.GS.freeVector.x; \
3017
args[1] = CUR.GS.freeVector.y; \
3021
args[0] = CUR.GS.freeVector.x; \
3022
args[1] = CUR.GS.freeVector.y;
3027
CUR.GS.rp0 = (FT_UShort)args[0];
3031
CUR.GS.rp1 = (FT_UShort)args[0];
3035
CUR.GS.rp2 = (FT_UShort)args[0];
3039
CUR.GS.round_state = TT_Round_To_Half_Grid; \
3040
CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
3044
CUR.GS.round_state = TT_Round_To_Grid; \
3045
CUR.func_round = (TT_Round_Func)Round_To_Grid;
3049
CUR.GS.round_state = TT_Round_To_Double_Grid; \
3050
CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
3054
CUR.GS.round_state = TT_Round_Up_To_Grid; \
3055
CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
3059
CUR.GS.round_state = TT_Round_Down_To_Grid; \
3060
CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
3064
CUR.GS.round_state = TT_Round_Off; \
3065
CUR.func_round = (TT_Round_Func)Round_None;
3069
SET_SuperRound( 0x4000, args[0] ); \
3070
CUR.GS.round_state = TT_Round_Super; \
3071
CUR.func_round = (TT_Round_Func)Round_Super;
3074
#define DO_S45ROUND \
3075
SET_SuperRound( 0x2D41, args[0] ); \
3076
CUR.GS.round_state = TT_Round_Super_45; \
3077
CUR.func_round = (TT_Round_Func)Round_Super_45;
3081
if ( args[0] < 0 ) \
3082
CUR.error = TT_Err_Bad_Argument; \
3084
CUR.GS.loop = args[0];
3088
CUR.GS.minimum_distance = args[0];
3092
CUR.GS.control_value_cutin = (FT_F26Dot6)args[0];
3096
CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];
3099
/* XXX: UNDOCUMENTED! or bug in the Windows engine? */
3101
/* It seems that the value that is read here is */
3102
/* expressed in 16.16 format rather than in font */
3106
CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 );
3110
CUR.GS.auto_flip = TRUE;
3113
#define DO_FLIPOFF \
3114
CUR.GS.auto_flip = FALSE;
3118
CUR.GS.delta_base = (FT_Short)args[0];
3122
CUR.GS.delta_shift = (FT_Short)args[0];
3125
#define DO_MD /* nothing */
3129
args[0] = CURRENT_Ppem();
3132
/* Note: The pointSize should be irrelevant in a given font program; */
3133
/* we thus decide to return only the ppem. */
3137
args[0] = CUR.metrics.pointSize;
3142
args[0] = CURRENT_Ppem();
3161
args[0] = args[1]; \
3177
if ( L <= 0 || L > CUR.args ) \
3178
CUR.error = TT_Err_Invalid_Reference; \
3180
args[0] = CUR.stack[CUR.args - L]; \
3185
if ( args[1] != 0 ) \
3187
CUR.IP += args[0]; \
3189
CUR.error = TT_Err_Bad_Argument; \
3190
CUR.step_ins = FALSE; \
3195
CUR.IP += args[0]; \
3197
CUR.error = TT_Err_Bad_Argument; \
3198
CUR.step_ins = FALSE;
3202
if ( args[1] == 0 ) \
3204
CUR.IP += args[0]; \
3206
CUR.error = TT_Err_Bad_Argument; \
3207
CUR.step_ins = FALSE; \
3212
args[0] = ( args[0] < args[1] );
3216
args[0] = ( args[0] <= args[1] );
3220
args[0] = ( args[0] > args[1] );
3224
args[0] = ( args[0] >= args[1] );
3228
args[0] = ( args[0] == args[1] );
3232
args[0] = ( args[0] != args[1] );
3236
args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 );
3240
args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 );
3244
args[0] = ( args[0] && args[1] );
3248
args[0] = ( args[0] || args[1] );
3264
if ( args[1] == 0 ) \
3265
CUR.error = TT_Err_Divide_By_Zero; \
3267
args[0] = TT_MULDIV_NO_ROUND( args[0], 64L, args[1] );
3271
args[0] = TT_MULDIV( args[0], args[1], 64L );
3275
args[0] = FT_ABS( args[0] );
3283
args[0] = FT_PIX_FLOOR( args[0] );
3286
#define DO_CEILING \
3287
args[0] = FT_PIX_CEIL( args[0] );
3292
FT_ULong I = (FT_ULong)args[0]; \
3295
if ( BOUNDSL( I, CUR.storeSize ) ) \
3297
if ( CUR.pedantic_hinting ) \
3299
ARRAY_BOUND_ERROR; \
3305
args[0] = CUR.storage[I]; \
3311
FT_ULong I = (FT_ULong)args[0]; \
3314
if ( BOUNDSL( I, CUR.storeSize ) ) \
3316
if ( CUR.pedantic_hinting ) \
3318
ARRAY_BOUND_ERROR; \
3322
CUR.storage[I] = args[1]; \
3328
FT_ULong I = (FT_ULong)args[0]; \
3331
if ( BOUNDSL( I, CUR.cvtSize ) ) \
3333
if ( CUR.pedantic_hinting ) \
3335
ARRAY_BOUND_ERROR; \
3341
args[0] = CUR_Func_read_cvt( I ); \
3347
FT_ULong I = (FT_ULong)args[0]; \
3350
if ( BOUNDSL( I, CUR.cvtSize ) ) \
3352
if ( CUR.pedantic_hinting ) \
3354
ARRAY_BOUND_ERROR; \
3358
CUR_Func_write_cvt( I, args[1] ); \
3364
FT_ULong I = (FT_ULong)args[0]; \
3367
if ( BOUNDSL( I, CUR.cvtSize ) ) \
3369
if ( CUR.pedantic_hinting ) \
3371
ARRAY_BOUND_ERROR; \
3375
CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \
3380
CUR.error = TT_Err_Debug_OpCode;
3384
args[0] = CUR_Func_round( \
3386
CUR.tt_metrics.compensations[CUR.opcode - 0x68] );
3390
args[0] = ROUND_None( args[0], \
3391
CUR.tt_metrics.compensations[CUR.opcode - 0x6C] );
3395
if ( args[1] > args[0] ) \
3400
if ( args[1] < args[0] ) \
3404
#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
3407
#undef ARRAY_BOUND_ERROR
3408
#define ARRAY_BOUND_ERROR \
3410
CUR.error = TT_Err_Invalid_Reference; \
3415
/*************************************************************************/
3417
/* SVTCA[a]: Set (F and P) Vectors to Coordinate Axis */
3418
/* Opcode range: 0x00-0x01 */
3422
Ins_SVTCA( INS_ARG )
3428
/*************************************************************************/
3430
/* SPVTCA[a]: Set PVector to Coordinate Axis */
3431
/* Opcode range: 0x02-0x03 */
3435
Ins_SPVTCA( INS_ARG )
3441
/*************************************************************************/
3443
/* SFVTCA[a]: Set FVector to Coordinate Axis */
3444
/* Opcode range: 0x04-0x05 */
3448
Ins_SFVTCA( INS_ARG )
3454
/*************************************************************************/
3456
/* SPVTL[a]: Set PVector To Line */
3457
/* Opcode range: 0x06-0x07 */
3458
/* Stack: uint32 uint32 --> */
3461
Ins_SPVTL( INS_ARG )
3467
/*************************************************************************/
3469
/* SFVTL[a]: Set FVector To Line */
3470
/* Opcode range: 0x08-0x09 */
3471
/* Stack: uint32 uint32 --> */
3474
Ins_SFVTL( INS_ARG )
3480
/*************************************************************************/
3482
/* SFVTPV[]: Set FVector To PVector */
3483
/* Opcode range: 0x0E */
3487
Ins_SFVTPV( INS_ARG )
3493
/*************************************************************************/
3495
/* SPVFS[]: Set PVector From Stack */
3496
/* Opcode range: 0x0A */
3497
/* Stack: f2.14 f2.14 --> */
3500
Ins_SPVFS( INS_ARG )
3506
/*************************************************************************/
3508
/* SFVFS[]: Set FVector From Stack */
3509
/* Opcode range: 0x0B */
3510
/* Stack: f2.14 f2.14 --> */
3513
Ins_SFVFS( INS_ARG )
3519
/*************************************************************************/
3521
/* GPV[]: Get Projection Vector */
3522
/* Opcode range: 0x0C */
3523
/* Stack: ef2.14 --> ef2.14 */
3532
/*************************************************************************/
3533
/* GFV[]: Get Freedom Vector */
3534
/* Opcode range: 0x0D */
3535
/* Stack: ef2.14 --> ef2.14 */
3544
/*************************************************************************/
3546
/* SRP0[]: Set Reference Point 0 */
3547
/* Opcode range: 0x10 */
3548
/* Stack: uint32 --> */
3557
/*************************************************************************/
3559
/* SRP1[]: Set Reference Point 1 */
3560
/* Opcode range: 0x11 */
3561
/* Stack: uint32 --> */
3570
/*************************************************************************/
3572
/* SRP2[]: Set Reference Point 2 */
3573
/* Opcode range: 0x12 */
3574
/* Stack: uint32 --> */
3583
/*************************************************************************/
3585
/* RTHG[]: Round To Half Grid */
3586
/* Opcode range: 0x19 */
3596
/*************************************************************************/
3598
/* RTG[]: Round To Grid */
3599
/* Opcode range: 0x18 */
3609
/*************************************************************************/
3610
/* RTDG[]: Round To Double Grid */
3611
/* Opcode range: 0x3D */
3621
/*************************************************************************/
3622
/* RUTG[]: Round Up To Grid */
3623
/* Opcode range: 0x7C */
3633
/*************************************************************************/
3635
/* RDTG[]: Round Down To Grid */
3636
/* Opcode range: 0x7D */
3646
/*************************************************************************/
3648
/* ROFF[]: Round OFF */
3649
/* Opcode range: 0x7A */
3659
/*************************************************************************/
3661
/* SROUND[]: Super ROUND */
3662
/* Opcode range: 0x76 */
3663
/* Stack: Eint8 --> */
3666
Ins_SROUND( INS_ARG )
3672
/*************************************************************************/
3674
/* S45ROUND[]: Super ROUND 45 degrees */
3675
/* Opcode range: 0x77 */
3676
/* Stack: uint32 --> */
3679
Ins_S45ROUND( INS_ARG )
3685
/*************************************************************************/
3687
/* SLOOP[]: Set LOOP variable */
3688
/* Opcode range: 0x17 */
3689
/* Stack: int32? --> */
3692
Ins_SLOOP( INS_ARG )
3698
/*************************************************************************/
3700
/* SMD[]: Set Minimum Distance */
3701
/* Opcode range: 0x1A */
3702
/* Stack: f26.6 --> */
3711
/*************************************************************************/
3713
/* SCVTCI[]: Set Control Value Table Cut In */
3714
/* Opcode range: 0x1D */
3715
/* Stack: f26.6 --> */
3718
Ins_SCVTCI( INS_ARG )
3724
/*************************************************************************/
3726
/* SSWCI[]: Set Single Width Cut In */
3727
/* Opcode range: 0x1E */
3728
/* Stack: f26.6 --> */
3731
Ins_SSWCI( INS_ARG )
3737
/*************************************************************************/
3739
/* SSW[]: Set Single Width */
3740
/* Opcode range: 0x1F */
3741
/* Stack: int32? --> */
3750
/*************************************************************************/
3752
/* FLIPON[]: Set auto-FLIP to ON */
3753
/* Opcode range: 0x4D */
3757
Ins_FLIPON( INS_ARG )
3763
/*************************************************************************/
3765
/* FLIPOFF[]: Set auto-FLIP to OFF */
3766
/* Opcode range: 0x4E */
3770
Ins_FLIPOFF( INS_ARG )
3776
/*************************************************************************/
3778
/* SANGW[]: Set ANGle Weight */
3779
/* Opcode range: 0x7E */
3780
/* Stack: uint32 --> */
3783
Ins_SANGW( INS_ARG )
3785
/* instruction not supported anymore */
3789
/*************************************************************************/
3791
/* SDB[]: Set Delta Base */
3792
/* Opcode range: 0x5E */
3793
/* Stack: uint32 --> */
3802
/*************************************************************************/
3804
/* SDS[]: Set Delta Shift */
3805
/* Opcode range: 0x5F */
3806
/* Stack: uint32 --> */
3815
/*************************************************************************/
3817
/* MPPEM[]: Measure Pixel Per EM */
3818
/* Opcode range: 0x4B */
3819
/* Stack: --> Euint16 */
3822
Ins_MPPEM( INS_ARG )
3828
/*************************************************************************/
3830
/* MPS[]: Measure Point Size */
3831
/* Opcode range: 0x4C */
3832
/* Stack: --> Euint16 */
3841
/*************************************************************************/
3843
/* DUP[]: DUPlicate the top stack's element */
3844
/* Opcode range: 0x20 */
3845
/* Stack: StkElt --> StkElt StkElt */
3854
/*************************************************************************/
3856
/* POP[]: POP the stack's top element */
3857
/* Opcode range: 0x21 */
3858
/* Stack: StkElt --> */
3867
/*************************************************************************/
3869
/* CLEAR[]: CLEAR the entire stack */
3870
/* Opcode range: 0x22 */
3871
/* Stack: StkElt... --> */
3874
Ins_CLEAR( INS_ARG )
3880
/*************************************************************************/
3882
/* SWAP[]: SWAP the stack's top two elements */
3883
/* Opcode range: 0x23 */
3884
/* Stack: 2 * StkElt --> 2 * StkElt */
3893
/*************************************************************************/
3895
/* DEPTH[]: return the stack DEPTH */
3896
/* Opcode range: 0x24 */
3897
/* Stack: --> uint32 */
3900
Ins_DEPTH( INS_ARG )
3906
/*************************************************************************/
3908
/* CINDEX[]: Copy INDEXed element */
3909
/* Opcode range: 0x25 */
3910
/* Stack: int32 --> StkElt */
3913
Ins_CINDEX( INS_ARG )
3919
/*************************************************************************/
3922
/* Opcode range: 0x59 */
3932
/*************************************************************************/
3934
/* JROT[]: Jump Relative On True */
3935
/* Opcode range: 0x78 */
3936
/* Stack: StkElt int32 --> */
3945
/*************************************************************************/
3947
/* JMPR[]: JuMP Relative */
3948
/* Opcode range: 0x1C */
3949
/* Stack: int32 --> */
3958
/*************************************************************************/
3960
/* JROF[]: Jump Relative On False */
3961
/* Opcode range: 0x79 */
3962
/* Stack: StkElt int32 --> */
3971
/*************************************************************************/
3973
/* LT[]: Less Than */
3974
/* Opcode range: 0x50 */
3975
/* Stack: int32? int32? --> bool */
3984
/*************************************************************************/
3986
/* LTEQ[]: Less Than or EQual */
3987
/* Opcode range: 0x51 */
3988
/* Stack: int32? int32? --> bool */
3997
/*************************************************************************/
3999
/* GT[]: Greater Than */
4000
/* Opcode range: 0x52 */
4001
/* Stack: int32? int32? --> bool */
4010
/*************************************************************************/
4012
/* GTEQ[]: Greater Than or EQual */
4013
/* Opcode range: 0x53 */
4014
/* Stack: int32? int32? --> bool */
4023
/*************************************************************************/
4026
/* Opcode range: 0x54 */
4027
/* Stack: StkElt StkElt --> bool */
4036
/*************************************************************************/
4038
/* NEQ[]: Not EQual */
4039
/* Opcode range: 0x55 */
4040
/* Stack: StkElt StkElt --> bool */
4049
/*************************************************************************/
4052
/* Opcode range: 0x56 */
4053
/* Stack: f26.6 --> bool */
4062
/*************************************************************************/
4064
/* EVEN[]: Is EVEN */
4065
/* Opcode range: 0x57 */
4066
/* Stack: f26.6 --> bool */
4075
/*************************************************************************/
4077
/* AND[]: logical AND */
4078
/* Opcode range: 0x5A */
4079
/* Stack: uint32 uint32 --> uint32 */
4088
/*************************************************************************/
4090
/* OR[]: logical OR */
4091
/* Opcode range: 0x5B */
4092
/* Stack: uint32 uint32 --> uint32 */
4101
/*************************************************************************/
4103
/* NOT[]: logical NOT */
4104
/* Opcode range: 0x5C */
4105
/* Stack: StkElt --> uint32 */
4114
/*************************************************************************/
4117
/* Opcode range: 0x60 */
4118
/* Stack: f26.6 f26.6 --> f26.6 */
4127
/*************************************************************************/
4129
/* SUB[]: SUBtract */
4130
/* Opcode range: 0x61 */
4131
/* Stack: f26.6 f26.6 --> f26.6 */
4140
/*************************************************************************/
4143
/* Opcode range: 0x62 */
4144
/* Stack: f26.6 f26.6 --> f26.6 */
4153
/*************************************************************************/
4155
/* MUL[]: MULtiply */
4156
/* Opcode range: 0x63 */
4157
/* Stack: f26.6 f26.6 --> f26.6 */
4166
/*************************************************************************/
4168
/* ABS[]: ABSolute value */
4169
/* Opcode range: 0x64 */
4170
/* Stack: f26.6 --> f26.6 */
4179
/*************************************************************************/
4182
/* Opcode range: 0x65 */
4183
/* Stack: f26.6 --> f26.6 */
4192
/*************************************************************************/
4194
/* FLOOR[]: FLOOR */
4195
/* Opcode range: 0x66 */
4196
/* Stack: f26.6 --> f26.6 */
4199
Ins_FLOOR( INS_ARG )
4205
/*************************************************************************/
4207
/* CEILING[]: CEILING */
4208
/* Opcode range: 0x67 */
4209
/* Stack: f26.6 --> f26.6 */
4212
Ins_CEILING( INS_ARG )
4218
/*************************************************************************/
4220
/* RS[]: Read Store */
4221
/* Opcode range: 0x43 */
4222
/* Stack: uint32 --> uint32 */
4231
/*************************************************************************/
4233
/* WS[]: Write Store */
4234
/* Opcode range: 0x42 */
4235
/* Stack: uint32 uint32 --> */
4244
/*************************************************************************/
4246
/* WCVTP[]: Write CVT in Pixel units */
4247
/* Opcode range: 0x44 */
4248
/* Stack: f26.6 uint32 --> */
4251
Ins_WCVTP( INS_ARG )
4257
/*************************************************************************/
4259
/* WCVTF[]: Write CVT in Funits */
4260
/* Opcode range: 0x70 */
4261
/* Stack: uint32 uint32 --> */
4264
Ins_WCVTF( INS_ARG )
4270
/*************************************************************************/
4272
/* RCVT[]: Read CVT */
4273
/* Opcode range: 0x45 */
4274
/* Stack: uint32 --> f26.6 */
4283
/*************************************************************************/
4285
/* AA[]: Adjust Angle */
4286
/* Opcode range: 0x7F */
4287
/* Stack: uint32 --> */
4292
/* intentionally no longer supported */
4296
/*************************************************************************/
4298
/* DEBUG[]: DEBUG. Unsupported. */
4299
/* Opcode range: 0x4F */
4300
/* Stack: uint32 --> */
4302
/* Note: The original instruction pops a value from the stack. */
4305
Ins_DEBUG( INS_ARG )
4311
/*************************************************************************/
4313
/* ROUND[ab]: ROUND value */
4314
/* Opcode range: 0x68-0x6B */
4315
/* Stack: f26.6 --> f26.6 */
4318
Ins_ROUND( INS_ARG )
4324
/*************************************************************************/
4326
/* NROUND[ab]: No ROUNDing of value */
4327
/* Opcode range: 0x6C-0x6F */
4328
/* Stack: f26.6 --> f26.6 */
4331
Ins_NROUND( INS_ARG )
4337
/*************************************************************************/
4339
/* MAX[]: MAXimum */
4340
/* Opcode range: 0x68 */
4341
/* Stack: int32? int32? --> int32 */
4350
/*************************************************************************/
4352
/* MIN[]: MINimum */
4353
/* Opcode range: 0x69 */
4354
/* Stack: int32? int32? --> int32 */
4363
#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
4366
/*************************************************************************/
4368
/* The following functions are called as is within the switch statement. */
4370
/*************************************************************************/
4373
/*************************************************************************/
4375
/* MINDEX[]: Move INDEXed element */
4376
/* Opcode range: 0x26 */
4377
/* Stack: int32? --> StkElt */
4380
Ins_MINDEX( INS_ARG )
4387
if ( L <= 0 || L > CUR.args )
4389
CUR.error = TT_Err_Invalid_Reference;
4393
K = CUR.stack[CUR.args - L];
4395
FT_ARRAY_MOVE( &CUR.stack[CUR.args - L ],
4396
&CUR.stack[CUR.args - L + 1],
4399
CUR.stack[CUR.args - 1] = K;
4403
/*************************************************************************/
4405
/* ROLL[]: ROLL top three elements */
4406
/* Opcode range: 0x8A */
4407
/* Stack: 3 * StkElt --> 3 * StkElt */
4427
/*************************************************************************/
4429
/* MANAGING THE FLOW OF CONTROL */
4431
/* Instructions appear in the specification's order. */
4433
/*************************************************************************/
4439
CUR.IP += CUR.length;
4441
if ( CUR.IP < CUR.codeSize )
4443
CUR.opcode = CUR.code[CUR.IP];
4445
CUR.length = opcode_length[CUR.opcode];
4446
if ( CUR.length < 0 )
4448
if ( CUR.IP + 1 > CUR.codeSize )
4450
CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
4453
if ( CUR.IP + CUR.length <= CUR.codeSize )
4458
CUR.error = TT_Err_Code_Overflow;
4463
/*************************************************************************/
4466
/* Opcode range: 0x58 */
4467
/* Stack: StkElt --> */
4484
if ( SKIP_Code() == FAILURE )
4487
switch ( CUR.opcode )
4493
case 0x1B: /* ELSE */
4494
Out = FT_BOOL( nIfs == 1 );
4497
case 0x59: /* EIF */
4499
Out = FT_BOOL( nIfs == 0 );
4502
} while ( Out == 0 );
4506
/*************************************************************************/
4509
/* Opcode range: 0x1B */
4524
if ( SKIP_Code() == FAILURE )
4527
switch ( CUR.opcode )
4533
case 0x59: /* EIF */
4537
} while ( nIfs != 0 );
4541
/*************************************************************************/
4543
/* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS */
4545
/* Instructions appear in the specification's order. */
4547
/*************************************************************************/
4550
/*************************************************************************/
4552
/* FDEF[]: Function DEFinition */
4553
/* Opcode range: 0x2C */
4554
/* Stack: uint32 --> */
4561
TT_DefRecord* limit;
4564
/* some font programs are broken enough to redefine functions! */
4565
/* We will then parse the current table. */
4568
limit = rec + CUR.numFDefs;
4571
for ( ; rec < limit; rec++ )
4573
if ( rec->opc == n )
4579
/* check that there is enough room for new functions */
4580
if ( CUR.numFDefs >= CUR.maxFDefs )
4582
CUR.error = TT_Err_Too_Many_Function_Defs;
4588
/* Although FDEF takes unsigned 32-bit integer, */
4589
/* func # must be within unsigned 16-bit integer */
4592
CUR.error = TT_Err_Too_Many_Function_Defs;
4596
rec->range = CUR.curRange;
4597
rec->opc = (FT_UInt16)n;
4598
rec->start = CUR.IP + 1;
4601
if ( n > CUR.maxFunc )
4602
CUR.maxFunc = (FT_UInt16)n;
4604
/* Now skip the whole function definition. */
4605
/* We don't allow nested IDEFS & FDEFs. */
4607
while ( SKIP_Code() == SUCCESS )
4609
switch ( CUR.opcode )
4611
case 0x89: /* IDEF */
4612
case 0x2C: /* FDEF */
4613
CUR.error = TT_Err_Nested_DEFS;
4616
case 0x2D: /* ENDF */
4623
/*************************************************************************/
4625
/* ENDF[]: END Function definition */
4626
/* Opcode range: 0x2D */
4637
if ( CUR.callTop <= 0 ) /* We encountered an ENDF without a call */
4639
CUR.error = TT_Err_ENDF_In_Exec_Stream;
4645
pRec = &CUR.callStack[CUR.callTop];
4649
CUR.step_ins = FALSE;
4651
if ( pRec->Cur_Count > 0 )
4654
CUR.IP = pRec->Cur_Restart;
4657
/* Loop through the current function */
4658
INS_Goto_CodeRange( pRec->Caller_Range,
4661
/* Exit the current call frame. */
4663
/* NOTE: If the last instruction of a program is a */
4664
/* CALL or LOOPCALL, the return address is */
4665
/* always out of the code range. This is a */
4666
/* valid address, and it is why we do not test */
4667
/* the result of Ins_Goto_CodeRange() here! */
4671
/*************************************************************************/
4673
/* CALL[]: CALL function */
4674
/* Opcode range: 0x2B */
4675
/* Stack: uint32? --> */
4685
/* first of all, check the index */
4688
if ( BOUNDSL( F, CUR.maxFunc + 1 ) )
4691
/* Except for some old Apple fonts, all functions in a TrueType */
4692
/* font are defined in increasing order, starting from 0. This */
4693
/* means that we normally have */
4695
/* CUR.maxFunc+1 == CUR.numFDefs */
4696
/* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */
4698
/* If this isn't true, we need to look up the function table. */
4700
def = CUR.FDefs + F;
4701
if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
4703
/* look up the FDefs table */
4704
TT_DefRecord* limit;
4708
limit = def + CUR.numFDefs;
4710
while ( def < limit && def->opc != F )
4717
/* check that the function is active */
4721
/* check the call stack */
4722
if ( CUR.callTop >= CUR.callSize )
4724
CUR.error = TT_Err_Stack_Overflow;
4728
pCrec = CUR.callStack + CUR.callTop;
4730
pCrec->Caller_Range = CUR.curRange;
4731
pCrec->Caller_IP = CUR.IP + 1;
4732
pCrec->Cur_Count = 1;
4733
pCrec->Cur_Restart = def->start;
4737
INS_Goto_CodeRange( def->range,
4740
CUR.step_ins = FALSE;
4744
CUR.error = TT_Err_Invalid_Reference;
4748
/*************************************************************************/
4750
/* LOOPCALL[]: LOOP and CALL function */
4751
/* Opcode range: 0x2A */
4752
/* Stack: uint32? Eint16? --> */
4755
Ins_LOOPCALL( INS_ARG )
4762
/* first of all, check the index */
4764
if ( BOUNDSL( F, CUR.maxFunc + 1 ) )
4767
/* Except for some old Apple fonts, all functions in a TrueType */
4768
/* font are defined in increasing order, starting from 0. This */
4769
/* means that we normally have */
4771
/* CUR.maxFunc+1 == CUR.numFDefs */
4772
/* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */
4774
/* If this isn't true, we need to look up the function table. */
4776
def = CUR.FDefs + F;
4777
if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
4779
/* look up the FDefs table */
4780
TT_DefRecord* limit;
4784
limit = def + CUR.numFDefs;
4786
while ( def < limit && def->opc != F )
4793
/* check that the function is active */
4798
if ( CUR.callTop >= CUR.callSize )
4800
CUR.error = TT_Err_Stack_Overflow;
4806
pCrec = CUR.callStack + CUR.callTop;
4808
pCrec->Caller_Range = CUR.curRange;
4809
pCrec->Caller_IP = CUR.IP + 1;
4810
pCrec->Cur_Count = (FT_Int)args[0];
4811
pCrec->Cur_Restart = def->start;
4815
INS_Goto_CodeRange( def->range, def->start );
4817
CUR.step_ins = FALSE;
4822
CUR.error = TT_Err_Invalid_Reference;
4826
/*************************************************************************/
4828
/* IDEF[]: Instruction DEFinition */
4829
/* Opcode range: 0x89 */
4830
/* Stack: Eint8 --> */
4836
TT_DefRecord* limit;
4839
/* First of all, look for the same function in our table */
4842
limit = def + CUR.numIDefs;
4844
for ( ; def < limit; def++ )
4845
if ( def->opc == (FT_ULong)args[0] )
4850
/* check that there is enough room for a new instruction */
4851
if ( CUR.numIDefs >= CUR.maxIDefs )
4853
CUR.error = TT_Err_Too_Many_Instruction_Defs;
4859
/* opcode must be unsigned 8-bit integer */
4860
if ( 0 > args[0] || args[0] > 0x00FF )
4862
CUR.error = TT_Err_Too_Many_Instruction_Defs;
4866
def->opc = (FT_Byte)args[0];
4867
def->start = CUR.IP + 1;
4868
def->range = CUR.curRange;
4871
if ( (FT_ULong)args[0] > CUR.maxIns )
4872
CUR.maxIns = (FT_Byte)args[0];
4874
/* Now skip the whole function definition. */
4875
/* We don't allow nested IDEFs & FDEFs. */
4877
while ( SKIP_Code() == SUCCESS )
4879
switch ( CUR.opcode )
4881
case 0x89: /* IDEF */
4882
case 0x2C: /* FDEF */
4883
CUR.error = TT_Err_Nested_DEFS;
4885
case 0x2D: /* ENDF */
4892
/*************************************************************************/
4894
/* PUSHING DATA ONTO THE INTERPRETER STACK */
4896
/* Instructions appear in the specification's order. */
4898
/*************************************************************************/
4901
/*************************************************************************/
4903
/* NPUSHB[]: PUSH N Bytes */
4904
/* Opcode range: 0x40 */
4905
/* Stack: --> uint32... */
4908
Ins_NPUSHB( INS_ARG )
4913
L = (FT_UShort)CUR.code[CUR.IP + 1];
4915
if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
4917
CUR.error = TT_Err_Stack_Overflow;
4921
for ( K = 1; K <= L; K++ )
4922
args[K - 1] = CUR.code[CUR.IP + K + 1];
4928
/*************************************************************************/
4930
/* NPUSHW[]: PUSH N Words */
4931
/* Opcode range: 0x41 */
4932
/* Stack: --> int32... */
4935
Ins_NPUSHW( INS_ARG )
4940
L = (FT_UShort)CUR.code[CUR.IP + 1];
4942
if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
4944
CUR.error = TT_Err_Stack_Overflow;
4950
for ( K = 0; K < L; K++ )
4951
args[K] = GET_ShortIns();
4953
CUR.step_ins = FALSE;
4958
/*************************************************************************/
4960
/* PUSHB[abc]: PUSH Bytes */
4961
/* Opcode range: 0xB0-0xB7 */
4962
/* Stack: --> uint32... */
4965
Ins_PUSHB( INS_ARG )
4970
L = (FT_UShort)( CUR.opcode - 0xB0 + 1 );
4972
if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
4974
CUR.error = TT_Err_Stack_Overflow;
4978
for ( K = 1; K <= L; K++ )
4979
args[K - 1] = CUR.code[CUR.IP + K];
4983
/*************************************************************************/
4985
/* PUSHW[abc]: PUSH Words */
4986
/* Opcode range: 0xB8-0xBF */
4987
/* Stack: --> int32... */
4990
Ins_PUSHW( INS_ARG )
4995
L = (FT_UShort)( CUR.opcode - 0xB8 + 1 );
4997
if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
4999
CUR.error = TT_Err_Stack_Overflow;
5005
for ( K = 0; K < L; K++ )
5006
args[K] = GET_ShortIns();
5008
CUR.step_ins = FALSE;
5012
/*************************************************************************/
5014
/* MANAGING THE GRAPHICS STATE */
5016
/* Instructions appear in the specs' order. */
5018
/*************************************************************************/
5021
/*************************************************************************/
5023
/* GC[a]: Get Coordinate projected onto */
5024
/* Opcode range: 0x46-0x47 */
5025
/* Stack: uint32 --> f26.6 */
5027
/* BULLSHIT: Measures from the original glyph must be taken along the */
5028
/* dual projection vector! */
5037
L = (FT_ULong)args[0];
5039
if ( BOUNDSL( L, CUR.zp2.n_points ) )
5041
if ( CUR.pedantic_hinting )
5043
CUR.error = TT_Err_Invalid_Reference;
5051
if ( CUR.opcode & 1 )
5052
R = CUR_fast_dualproj( &CUR.zp2.org[L] );
5054
R = CUR_fast_project( &CUR.zp2.cur[L] );
5061
/*************************************************************************/
5063
/* SCFS[]: Set Coordinate From Stack */
5064
/* Opcode range: 0x48 */
5065
/* Stack: f26.6 uint32 --> */
5069
/* OA := OA + ( value - OA.p )/( f.p ) * f */
5078
L = (FT_UShort)args[0];
5080
if ( BOUNDS( L, CUR.zp2.n_points ) )
5082
if ( CUR.pedantic_hinting )
5083
CUR.error = TT_Err_Invalid_Reference;
5087
K = CUR_fast_project( &CUR.zp2.cur[L] );
5089
CUR_Func_move( &CUR.zp2, L, args[1] - K );
5091
/* not part of the specs, but here for safety */
5093
if ( CUR.GS.gep2 == 0 )
5094
CUR.zp2.org[L] = CUR.zp2.cur[L];
5098
/*************************************************************************/
5100
/* MD[a]: Measure Distance */
5101
/* Opcode range: 0x49-0x4A */
5102
/* Stack: uint32 uint32 --> f26.6 */
5104
/* BULLSHIT: Measure taken in the original glyph must be along the dual */
5105
/* projection vector. */
5107
/* Second BULLSHIT: Flag attributes are inverted! */
5108
/* 0 => measure distance in original outline */
5109
/* 1 => measure distance in grid-fitted outline */
5111
/* Third one: `zp0 - zp1', and not `zp2 - zp1! */
5120
K = (FT_UShort)args[1];
5121
L = (FT_UShort)args[0];
5123
if ( BOUNDS( L, CUR.zp0.n_points ) ||
5124
BOUNDS( K, CUR.zp1.n_points ) )
5126
if ( CUR.pedantic_hinting )
5128
CUR.error = TT_Err_Invalid_Reference;
5135
if ( CUR.opcode & 1 )
5136
D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
5139
FT_Vector* vec1 = CUR.zp0.orus + L;
5140
FT_Vector* vec2 = CUR.zp1.orus + K;
5143
if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
5145
/* this should be faster */
5146
D = CUR_Func_dualproj( vec1, vec2 );
5147
D = TT_MULFIX( D, CUR.metrics.x_scale );
5154
vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
5155
vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
5157
D = CUR_fast_dualproj( &vec );
5166
/*************************************************************************/
5168
/* SDPVTL[a]: Set Dual PVector to Line */
5169
/* Opcode range: 0x86-0x87 */
5170
/* Stack: uint32 uint32 --> */
5173
Ins_SDPVTL( INS_ARG )
5176
FT_UShort p1, p2; /* was FT_Int in pas type ERROR */
5179
p1 = (FT_UShort)args[1];
5180
p2 = (FT_UShort)args[0];
5182
if ( BOUNDS( p2, CUR.zp1.n_points ) ||
5183
BOUNDS( p1, CUR.zp2.n_points ) )
5185
if ( CUR.pedantic_hinting )
5186
CUR.error = TT_Err_Invalid_Reference;
5191
FT_Vector* v1 = CUR.zp1.org + p2;
5192
FT_Vector* v2 = CUR.zp2.org + p1;
5199
if ( ( CUR.opcode & 1 ) != 0 )
5201
C = B; /* counter clockwise rotation */
5206
NORMalize( A, B, &CUR.GS.dualVector );
5209
FT_Vector* v1 = CUR.zp1.cur + p2;
5210
FT_Vector* v2 = CUR.zp2.cur + p1;
5217
if ( ( CUR.opcode & 1 ) != 0 )
5219
C = B; /* counter clockwise rotation */
5224
NORMalize( A, B, &CUR.GS.projVector );
5226
GUESS_VECTOR( freeVector );
5232
/*************************************************************************/
5234
/* SZP0[]: Set Zone Pointer 0 */
5235
/* Opcode range: 0x13 */
5236
/* Stack: uint32 --> */
5241
switch ( (FT_Int)args[0] )
5244
CUR.zp0 = CUR.twilight;
5252
if ( CUR.pedantic_hinting )
5253
CUR.error = TT_Err_Invalid_Reference;
5257
CUR.GS.gep0 = (FT_UShort)args[0];
5261
/*************************************************************************/
5263
/* SZP1[]: Set Zone Pointer 1 */
5264
/* Opcode range: 0x14 */
5265
/* Stack: uint32 --> */
5270
switch ( (FT_Int)args[0] )
5273
CUR.zp1 = CUR.twilight;
5281
if ( CUR.pedantic_hinting )
5282
CUR.error = TT_Err_Invalid_Reference;
5286
CUR.GS.gep1 = (FT_UShort)args[0];
5290
/*************************************************************************/
5292
/* SZP2[]: Set Zone Pointer 2 */
5293
/* Opcode range: 0x15 */
5294
/* Stack: uint32 --> */
5299
switch ( (FT_Int)args[0] )
5302
CUR.zp2 = CUR.twilight;
5310
if ( CUR.pedantic_hinting )
5311
CUR.error = TT_Err_Invalid_Reference;
5315
CUR.GS.gep2 = (FT_UShort)args[0];
5319
/*************************************************************************/
5321
/* SZPS[]: Set Zone PointerS */
5322
/* Opcode range: 0x16 */
5323
/* Stack: uint32 --> */
5328
switch ( (FT_Int)args[0] )
5331
CUR.zp0 = CUR.twilight;
5339
if ( CUR.pedantic_hinting )
5340
CUR.error = TT_Err_Invalid_Reference;
5347
CUR.GS.gep0 = (FT_UShort)args[0];
5348
CUR.GS.gep1 = (FT_UShort)args[0];
5349
CUR.GS.gep2 = (FT_UShort)args[0];
5353
/*************************************************************************/
5355
/* INSTCTRL[]: INSTruction ConTRoL */
5356
/* Opcode range: 0x8e */
5357
/* Stack: int32 int32 --> */
5360
Ins_INSTCTRL( INS_ARG )
5368
if ( K < 1 || K > 2 )
5370
if ( CUR.pedantic_hinting )
5371
CUR.error = TT_Err_Invalid_Reference;
5378
CUR.GS.instruct_control = FT_BOOL(
5379
( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );
5383
/*************************************************************************/
5385
/* SCANCTRL[]: SCAN ConTRoL */
5386
/* Opcode range: 0x85 */
5387
/* Stack: uint32? --> */
5390
Ins_SCANCTRL( INS_ARG )
5396
A = (FT_Int)( args[0] & 0xFF );
5400
CUR.GS.scan_control = TRUE;
5405
CUR.GS.scan_control = FALSE;
5409
if ( ( args[0] & 0x100 ) != 0 && CUR.tt_metrics.ppem <= A )
5410
CUR.GS.scan_control = TRUE;
5412
if ( ( args[0] & 0x200 ) != 0 && CUR.tt_metrics.rotated )
5413
CUR.GS.scan_control = TRUE;
5415
if ( ( args[0] & 0x400 ) != 0 && CUR.tt_metrics.stretched )
5416
CUR.GS.scan_control = TRUE;
5418
if ( ( args[0] & 0x800 ) != 0 && CUR.tt_metrics.ppem > A )
5419
CUR.GS.scan_control = FALSE;
5421
if ( ( args[0] & 0x1000 ) != 0 && CUR.tt_metrics.rotated )
5422
CUR.GS.scan_control = FALSE;
5424
if ( ( args[0] & 0x2000 ) != 0 && CUR.tt_metrics.stretched )
5425
CUR.GS.scan_control = FALSE;
5429
/*************************************************************************/
5431
/* SCANTYPE[]: SCAN TYPE */
5432
/* Opcode range: 0x8D */
5433
/* Stack: uint32? --> */
5436
Ins_SCANTYPE( INS_ARG )
5439
CUR.GS.scan_type = (FT_Int)args[0];
5443
/*************************************************************************/
5445
/* MANAGING OUTLINES */
5447
/* Instructions appear in the specification's order. */
5449
/*************************************************************************/
5452
/*************************************************************************/
5454
/* FLIPPT[]: FLIP PoinT */
5455
/* Opcode range: 0x80 */
5456
/* Stack: uint32... --> */
5459
Ins_FLIPPT( INS_ARG )
5466
if ( CUR.top < CUR.GS.loop )
5468
CUR.error = TT_Err_Too_Few_Arguments;
5472
while ( CUR.GS.loop > 0 )
5476
point = (FT_UShort)CUR.stack[CUR.args];
5478
if ( BOUNDS( point, CUR.pts.n_points ) )
5480
if ( CUR.pedantic_hinting )
5482
CUR.error = TT_Err_Invalid_Reference;
5487
CUR.pts.tags[point] ^= FT_CURVE_TAG_ON;
5493
CUR.new_top = CUR.args;
5497
/*************************************************************************/
5499
/* FLIPRGON[]: FLIP RanGe ON */
5500
/* Opcode range: 0x81 */
5501
/* Stack: uint32 uint32 --> */
5504
Ins_FLIPRGON( INS_ARG )
5509
K = (FT_UShort)args[1];
5510
L = (FT_UShort)args[0];
5512
if ( BOUNDS( K, CUR.pts.n_points ) ||
5513
BOUNDS( L, CUR.pts.n_points ) )
5515
if ( CUR.pedantic_hinting )
5516
CUR.error = TT_Err_Invalid_Reference;
5520
for ( I = L; I <= K; I++ )
5521
CUR.pts.tags[I] |= FT_CURVE_TAG_ON;
5525
/*************************************************************************/
5527
/* FLIPRGOFF: FLIP RanGe OFF */
5528
/* Opcode range: 0x82 */
5529
/* Stack: uint32 uint32 --> */
5532
Ins_FLIPRGOFF( INS_ARG )
5537
K = (FT_UShort)args[1];
5538
L = (FT_UShort)args[0];
5540
if ( BOUNDS( K, CUR.pts.n_points ) ||
5541
BOUNDS( L, CUR.pts.n_points ) )
5543
if ( CUR.pedantic_hinting )
5544
CUR.error = TT_Err_Invalid_Reference;
5548
for ( I = L; I <= K; I++ )
5549
CUR.pts.tags[I] &= ~FT_CURVE_TAG_ON;
5554
Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6* x,
5564
if ( CUR.opcode & 1 )
5575
if ( BOUNDS( p, zp.n_points ) )
5577
if ( CUR.pedantic_hinting )
5578
CUR.error = TT_Err_Invalid_Reference;
5586
d = CUR_Func_project( zp.cur + p, zp.org + p );
5588
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
5589
if ( CUR.face->unpatented_hinting )
5591
if ( CUR.GS.both_x_axis )
5606
(FT_Long)CUR.GS.freeVector.x * 0x10000L,
5609
(FT_Long)CUR.GS.freeVector.y * 0x10000L,
5618
Move_Zp2_Point( EXEC_OP_ FT_UShort point,
5623
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
5624
if ( CUR.face->unpatented_hinting )
5626
if ( CUR.GS.both_x_axis )
5628
CUR.zp2.cur[point].x += dx;
5630
CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
5634
CUR.zp2.cur[point].y += dy;
5636
CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
5642
if ( CUR.GS.freeVector.x != 0 )
5644
CUR.zp2.cur[point].x += dx;
5646
CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
5649
if ( CUR.GS.freeVector.y != 0 )
5651
CUR.zp2.cur[point].y += dy;
5653
CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
5658
/*************************************************************************/
5660
/* SHP[a]: SHift Point by the last point */
5661
/* Opcode range: 0x32-0x33 */
5662
/* Stack: uint32... --> */
5677
if ( CUR.top < CUR.GS.loop )
5679
CUR.error = TT_Err_Invalid_Reference;
5683
if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
5686
while ( CUR.GS.loop > 0 )
5689
point = (FT_UShort)CUR.stack[CUR.args];
5691
if ( BOUNDS( point, CUR.zp2.n_points ) )
5693
if ( CUR.pedantic_hinting )
5695
CUR.error = TT_Err_Invalid_Reference;
5700
/* XXX: UNDOCUMENTED! SHP touches the points */
5701
MOVE_Zp2_Point( point, dx, dy, TRUE );
5707
CUR.new_top = CUR.args;
5711
/*************************************************************************/
5713
/* SHC[a]: SHift Contour */
5714
/* Opcode range: 0x34-35 */
5715
/* Stack: uint32 --> */
5726
FT_UShort first_point, last_point, i;
5729
contour = (FT_UShort)args[0];
5731
if ( BOUNDS( contour, CUR.pts.n_contours ) )
5733
if ( CUR.pedantic_hinting )
5734
CUR.error = TT_Err_Invalid_Reference;
5738
if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
5744
first_point = (FT_UShort)( CUR.pts.contours[contour - 1] + 1 -
5745
CUR.pts.first_point );
5747
last_point = (FT_UShort)( CUR.pts.contours[contour] -
5748
CUR.pts.first_point );
5750
/* XXX: this is probably wrong... at least it prevents memory */
5751
/* corruption when zp2 is the twilight zone */
5752
if ( BOUNDS( last_point, CUR.zp2.n_points ) )
5754
if ( CUR.zp2.n_points > 0 )
5755
last_point = (FT_UShort)(CUR.zp2.n_points - 1);
5760
/* XXX: UNDOCUMENTED! SHC touches the points */
5761
for ( i = first_point; i <= last_point; i++ )
5763
if ( zp.cur != CUR.zp2.cur || refp != i )
5764
MOVE_Zp2_Point( i, dx, dy, TRUE );
5769
/*************************************************************************/
5771
/* SHZ[a]: SHift Zone */
5772
/* Opcode range: 0x36-37 */
5773
/* Stack: uint32 --> */
5783
FT_UShort last_point, i;
5786
if ( BOUNDS( args[0], 2 ) )
5788
if ( CUR.pedantic_hinting )
5789
CUR.error = TT_Err_Invalid_Reference;
5793
if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
5796
/* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points. */
5797
/* Twilight zone has no contours, so use `n_points'. */
5798
/* Normal zone's `n_points' includes phantoms, so must */
5799
/* use end of last contour. */
5800
if ( CUR.GS.gep2 == 0 && CUR.zp2.n_points > 0 )
5801
last_point = (FT_UShort)( CUR.zp2.n_points - 1 );
5802
else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 )
5804
last_point = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] );
5806
if ( BOUNDS( last_point, CUR.zp2.n_points ) )
5808
if ( CUR.pedantic_hinting )
5809
CUR.error = TT_Err_Invalid_Reference;
5816
/* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
5817
for ( i = 0; i <= last_point; i++ )
5819
if ( zp.cur != CUR.zp2.cur || refp != i )
5820
MOVE_Zp2_Point( i, dx, dy, FALSE );
5825
/*************************************************************************/
5827
/* SHPIX[]: SHift points by a PIXel amount */
5828
/* Opcode range: 0x38 */
5829
/* Stack: f26.6 uint32... --> */
5832
Ins_SHPIX( INS_ARG )
5838
if ( CUR.top < CUR.GS.loop + 1 )
5840
CUR.error = TT_Err_Invalid_Reference;
5844
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
5845
if ( CUR.face->unpatented_hinting )
5847
if ( CUR.GS.both_x_axis )
5849
dx = TT_MulFix14( (FT_UInt32)args[0], 0x4000 );
5855
dy = TT_MulFix14( (FT_UInt32)args[0], 0x4000 );
5861
dx = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.x );
5862
dy = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.y );
5865
while ( CUR.GS.loop > 0 )
5869
point = (FT_UShort)CUR.stack[CUR.args];
5871
if ( BOUNDS( point, CUR.zp2.n_points ) )
5873
if ( CUR.pedantic_hinting )
5875
CUR.error = TT_Err_Invalid_Reference;
5880
MOVE_Zp2_Point( point, dx, dy, TRUE );
5886
CUR.new_top = CUR.args;
5890
/*************************************************************************/
5892
/* MSIRP[a]: Move Stack Indirect Relative Position */
5893
/* Opcode range: 0x3A-0x3B */
5894
/* Stack: f26.6 uint32 --> */
5897
Ins_MSIRP( INS_ARG )
5900
FT_F26Dot6 distance;
5903
point = (FT_UShort)args[0];
5905
if ( BOUNDS( point, CUR.zp1.n_points ) ||
5906
BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
5908
if ( CUR.pedantic_hinting )
5909
CUR.error = TT_Err_Invalid_Reference;
5913
/* XXX: UNDOCUMENTED! behaviour */
5914
if ( CUR.GS.gep1 == 0 ) /* if the point that is to be moved */
5915
/* is in twilight zone */
5917
CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
5918
CUR_Func_move_orig( &CUR.zp1, point, args[1] );
5919
CUR.zp1.cur[point] = CUR.zp1.org[point];
5922
distance = CUR_Func_project( CUR.zp1.cur + point,
5923
CUR.zp0.cur + CUR.GS.rp0 );
5925
CUR_Func_move( &CUR.zp1, point, args[1] - distance );
5927
CUR.GS.rp1 = CUR.GS.rp0;
5930
if ( ( CUR.opcode & 1 ) != 0 )
5935
/*************************************************************************/
5937
/* MDAP[a]: Move Direct Absolute Point */
5938
/* Opcode range: 0x2E-0x2F */
5939
/* Stack: uint32 --> */
5945
FT_F26Dot6 cur_dist,
5949
point = (FT_UShort)args[0];
5951
if ( BOUNDS( point, CUR.zp0.n_points ) )
5953
if ( CUR.pedantic_hinting )
5954
CUR.error = TT_Err_Invalid_Reference;
5958
/* XXX: Is there some undocumented feature while in the */
5959
/* twilight zone? ? */
5960
if ( ( CUR.opcode & 1 ) != 0 )
5962
cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
5963
distance = CUR_Func_round( cur_dist,
5964
CUR.tt_metrics.compensations[0] ) - cur_dist;
5969
CUR_Func_move( &CUR.zp0, point, distance );
5976
/*************************************************************************/
5978
/* MIAP[a]: Move Indirect Absolute Point */
5979
/* Opcode range: 0x3E-0x3F */
5980
/* Stack: uint32 uint32 --> */
5987
FT_F26Dot6 distance,
5991
cvtEntry = (FT_ULong)args[1];
5992
point = (FT_UShort)args[0];
5994
if ( BOUNDS( point, CUR.zp0.n_points ) ||
5995
BOUNDSL( cvtEntry, CUR.cvtSize ) )
5997
if ( CUR.pedantic_hinting )
5998
CUR.error = TT_Err_Invalid_Reference;
6002
/* XXX: UNDOCUMENTED! */
6004
/* The behaviour of an MIAP instruction is quite */
6005
/* different when used in the twilight zone. */
6007
/* First, no control value cut-in test is performed */
6008
/* as it would fail anyway. Second, the original */
6009
/* point, i.e. (org_x,org_y) of zp0.point, is set */
6010
/* to the absolute, unrounded distance found in */
6013
/* This is used in the CVT programs of the Microsoft */
6014
/* fonts Arial, Times, etc., in order to re-adjust */
6015
/* some key font heights. It allows the use of the */
6016
/* IP instruction in the twilight zone, which */
6017
/* otherwise would be `illegal' according to the */
6018
/* specification. */
6020
/* We implement it with a special sequence for the */
6021
/* twilight zone. This is a bad hack, but it seems */
6024
distance = CUR_Func_read_cvt( cvtEntry );
6026
if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */
6028
CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance, CUR.GS.freeVector.x );
6029
CUR.zp0.org[point].y = TT_MulFix14( (FT_UInt32)distance, CUR.GS.freeVector.y ),
6030
CUR.zp0.cur[point] = CUR.zp0.org[point];
6033
org_dist = CUR_fast_project( &CUR.zp0.cur[point] );
6035
if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cutin flag */
6037
if ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin )
6038
distance = org_dist;
6040
distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );
6043
CUR_Func_move( &CUR.zp0, point, distance - org_dist );
6050
/*************************************************************************/
6052
/* MDRP[abcde]: Move Direct Relative Point */
6053
/* Opcode range: 0xC0-0xDF */
6054
/* Stack: uint32 --> */
6060
FT_F26Dot6 org_dist, distance;
6063
point = (FT_UShort)args[0];
6065
if ( BOUNDS( point, CUR.zp1.n_points ) ||
6066
BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
6068
if ( CUR.pedantic_hinting )
6069
CUR.error = TT_Err_Invalid_Reference;
6073
/* XXX: Is there some undocumented feature while in the */
6074
/* twilight zone? */
6076
/* XXX: UNDOCUMENTED: twilight zone special case */
6078
if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )
6080
FT_Vector* vec1 = &CUR.zp1.org[point];
6081
FT_Vector* vec2 = &CUR.zp0.org[CUR.GS.rp0];
6084
org_dist = CUR_Func_dualproj( vec1, vec2 );
6088
FT_Vector* vec1 = &CUR.zp1.orus[point];
6089
FT_Vector* vec2 = &CUR.zp0.orus[CUR.GS.rp0];
6092
if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
6094
/* this should be faster */
6095
org_dist = CUR_Func_dualproj( vec1, vec2 );
6096
org_dist = TT_MULFIX( org_dist, CUR.metrics.x_scale );
6103
vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
6104
vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
6106
org_dist = CUR_fast_dualproj( &vec );
6110
/* single width cut-in test */
6112
if ( FT_ABS( org_dist - CUR.GS.single_width_value ) <
6113
CUR.GS.single_width_cutin )
6115
if ( org_dist >= 0 )
6116
org_dist = CUR.GS.single_width_value;
6118
org_dist = -CUR.GS.single_width_value;
6123
if ( ( CUR.opcode & 4 ) != 0 )
6124
distance = CUR_Func_round(
6126
CUR.tt_metrics.compensations[CUR.opcode & 3] );
6128
distance = ROUND_None(
6130
CUR.tt_metrics.compensations[CUR.opcode & 3] );
6132
/* minimum distance flag */
6134
if ( ( CUR.opcode & 8 ) != 0 )
6136
if ( org_dist >= 0 )
6138
if ( distance < CUR.GS.minimum_distance )
6139
distance = CUR.GS.minimum_distance;
6143
if ( distance > -CUR.GS.minimum_distance )
6144
distance = -CUR.GS.minimum_distance;
6148
/* now move the point */
6150
org_dist = CUR_Func_project( CUR.zp1.cur + point,
6151
CUR.zp0.cur + CUR.GS.rp0 );
6153
CUR_Func_move( &CUR.zp1, point, distance - org_dist );
6155
CUR.GS.rp1 = CUR.GS.rp0;
6158
if ( ( CUR.opcode & 16 ) != 0 )
6163
/*************************************************************************/
6165
/* MIRP[abcde]: Move Indirect Relative Point */
6166
/* Opcode range: 0xE0-0xFF */
6167
/* Stack: int32? uint32 --> */
6175
FT_F26Dot6 cvt_dist,
6181
point = (FT_UShort)args[0];
6182
cvtEntry = (FT_ULong)( args[1] + 1 );
6184
/* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
6186
if ( BOUNDS( point, CUR.zp1.n_points ) ||
6187
BOUNDSL( cvtEntry, CUR.cvtSize + 1 ) ||
6188
BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
6190
if ( CUR.pedantic_hinting )
6191
CUR.error = TT_Err_Invalid_Reference;
6198
cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
6200
/* single width test */
6202
if ( FT_ABS( cvt_dist - CUR.GS.single_width_value ) <
6203
CUR.GS.single_width_cutin )
6205
if ( cvt_dist >= 0 )
6206
cvt_dist = CUR.GS.single_width_value;
6208
cvt_dist = -CUR.GS.single_width_value;
6211
/* XXX: UNDOCUMENTED! -- twilight zone */
6213
if ( CUR.GS.gep1 == 0 )
6215
CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
6216
TT_MulFix14( (FT_UInt32)cvt_dist,
6217
CUR.GS.freeVector.x );
6219
CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +
6220
TT_MulFix14( (FT_UInt32)cvt_dist,
6221
CUR.GS.freeVector.y );
6223
CUR.zp1.cur[point] = CUR.zp0.cur[point];
6226
org_dist = CUR_Func_dualproj( &CUR.zp1.org[point],
6227
&CUR.zp0.org[CUR.GS.rp0] );
6228
cur_dist = CUR_Func_project ( &CUR.zp1.cur[point],
6229
&CUR.zp0.cur[CUR.GS.rp0] );
6231
/* auto-flip test */
6233
if ( CUR.GS.auto_flip )
6235
if ( ( org_dist ^ cvt_dist ) < 0 )
6236
cvt_dist = -cvt_dist;
6239
/* control value cutin and round */
6241
if ( ( CUR.opcode & 4 ) != 0 )
6243
/* XXX: UNDOCUMENTED! Only perform cut-in test when both points */
6244
/* refer to the same zone. */
6246
if ( CUR.GS.gep0 == CUR.GS.gep1 )
6247
if ( FT_ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )
6248
cvt_dist = org_dist;
6250
distance = CUR_Func_round(
6252
CUR.tt_metrics.compensations[CUR.opcode & 3] );
6255
distance = ROUND_None(
6257
CUR.tt_metrics.compensations[CUR.opcode & 3] );
6259
/* minimum distance test */
6261
if ( ( CUR.opcode & 8 ) != 0 )
6263
if ( org_dist >= 0 )
6265
if ( distance < CUR.GS.minimum_distance )
6266
distance = CUR.GS.minimum_distance;
6270
if ( distance > -CUR.GS.minimum_distance )
6271
distance = -CUR.GS.minimum_distance;
6275
CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
6277
CUR.GS.rp1 = CUR.GS.rp0;
6279
if ( ( CUR.opcode & 16 ) != 0 )
6282
/* XXX: UNDOCUMENTED! */
6287
/*************************************************************************/
6289
/* ALIGNRP[]: ALIGN Relative Point */
6290
/* Opcode range: 0x3C */
6291
/* Stack: uint32 uint32... --> */
6294
Ins_ALIGNRP( INS_ARG )
6297
FT_F26Dot6 distance;
6302
if ( CUR.top < CUR.GS.loop ||
6303
BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
6305
if ( CUR.pedantic_hinting )
6306
CUR.error = TT_Err_Invalid_Reference;
6310
while ( CUR.GS.loop > 0 )
6314
point = (FT_UShort)CUR.stack[CUR.args];
6316
if ( BOUNDS( point, CUR.zp1.n_points ) )
6318
if ( CUR.pedantic_hinting )
6320
CUR.error = TT_Err_Invalid_Reference;
6326
distance = CUR_Func_project( CUR.zp1.cur + point,
6327
CUR.zp0.cur + CUR.GS.rp0 );
6329
CUR_Func_move( &CUR.zp1, point, -distance );
6336
CUR.new_top = CUR.args;
6340
/*************************************************************************/
6342
/* ISECT[]: moves point to InterSECTion */
6343
/* Opcode range: 0x0F */
6344
/* Stack: 5 * uint32 --> */
6347
Ins_ISECT( INS_ARG )
6353
FT_F26Dot6 discriminant;
6364
point = (FT_UShort)args[0];
6366
a0 = (FT_UShort)args[1];
6367
a1 = (FT_UShort)args[2];
6368
b0 = (FT_UShort)args[3];
6369
b1 = (FT_UShort)args[4];
6371
if ( BOUNDS( b0, CUR.zp0.n_points ) ||
6372
BOUNDS( b1, CUR.zp0.n_points ) ||
6373
BOUNDS( a0, CUR.zp1.n_points ) ||
6374
BOUNDS( a1, CUR.zp1.n_points ) ||
6375
BOUNDS( point, CUR.zp2.n_points ) )
6377
if ( CUR.pedantic_hinting )
6378
CUR.error = TT_Err_Invalid_Reference;
6382
dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
6383
dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
6385
dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x;
6386
day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y;
6388
dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x;
6389
dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y;
6391
CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
6393
discriminant = TT_MULDIV( dax, -dby, 0x40 ) +
6394
TT_MULDIV( day, dbx, 0x40 );
6396
if ( FT_ABS( discriminant ) >= 0x40 )
6398
val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );
6400
R.x = TT_MULDIV( val, dax, discriminant );
6401
R.y = TT_MULDIV( val, day, discriminant );
6403
CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;
6404
CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
6408
/* else, take the middle of the middles of A and B */
6410
CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x +
6413
CUR.zp0.cur[b1].x ) / 4;
6414
CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y +
6417
CUR.zp0.cur[b1].y ) / 4;
6422
/*************************************************************************/
6424
/* ALIGNPTS[]: ALIGN PoinTS */
6425
/* Opcode range: 0x27 */
6426
/* Stack: uint32 uint32 --> */
6429
Ins_ALIGNPTS( INS_ARG )
6432
FT_F26Dot6 distance;
6435
p1 = (FT_UShort)args[0];
6436
p2 = (FT_UShort)args[1];
6438
if ( BOUNDS( p1, CUR.zp1.n_points ) ||
6439
BOUNDS( p2, CUR.zp0.n_points ) )
6441
if ( CUR.pedantic_hinting )
6442
CUR.error = TT_Err_Invalid_Reference;
6446
distance = CUR_Func_project( CUR.zp0.cur + p2,
6447
CUR.zp1.cur + p1 ) / 2;
6449
CUR_Func_move( &CUR.zp1, p1, distance );
6450
CUR_Func_move( &CUR.zp0, p2, -distance );
6454
/*************************************************************************/
6456
/* IP[]: Interpolate Point */
6457
/* Opcode range: 0x39 */
6458
/* Stack: uint32... --> */
6461
/* SOMETIMES, DUMBER CODE IS BETTER CODE */
6466
FT_F26Dot6 old_range, cur_range;
6467
FT_Vector* orus_base;
6468
FT_Vector* cur_base;
6474
if ( CUR.top < CUR.GS.loop )
6476
CUR.error = TT_Err_Invalid_Reference;
6481
* We need to deal in a special way with the twilight zone.
6482
* Otherwise, by definition, the value of CUR.twilight.orus[n] is (0,0),
6485
twilight = CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 || CUR.GS.gep2 == 0;
6487
if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) )
6489
if ( CUR.pedantic_hinting )
6490
CUR.error = TT_Err_Invalid_Reference;
6495
orus_base = &CUR.zp0.org[CUR.GS.rp1];
6497
orus_base = &CUR.zp0.orus[CUR.GS.rp1];
6499
cur_base = &CUR.zp0.cur[CUR.GS.rp1];
6501
/* XXX: There are some glyphs in some braindead but popular */
6502
/* fonts out there (e.g. [aeu]grave in monotype.ttf) */
6503
/* calling IP[] with bad values of rp[12]. */
6504
/* Do something sane when this odd thing happens. */
6505
if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ||
6506
BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) )
6514
old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2],
6517
old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2],
6520
cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base );
6523
for ( ; CUR.GS.loop > 0; --CUR.GS.loop )
6525
FT_UInt point = (FT_UInt)CUR.stack[--CUR.args];
6526
FT_F26Dot6 org_dist, cur_dist, new_dist;
6529
/* check point bounds */
6530
if ( BOUNDS( point, CUR.zp2.n_points ) )
6532
if ( CUR.pedantic_hinting )
6534
CUR.error = TT_Err_Invalid_Reference;
6541
org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base );
6543
org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base );
6545
cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base );
6548
new_dist = ( old_range != 0 )
6549
? TT_MULDIV( org_dist, cur_range, old_range )
6554
CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
6557
CUR.new_top = CUR.args;
6561
/*************************************************************************/
6563
/* UTP[a]: UnTouch Point */
6564
/* Opcode range: 0x29 */
6565
/* Stack: uint32 --> */
6574
point = (FT_UShort)args[0];
6576
if ( BOUNDS( point, CUR.zp0.n_points ) )
6578
if ( CUR.pedantic_hinting )
6579
CUR.error = TT_Err_Invalid_Reference;
6585
if ( CUR.GS.freeVector.x != 0 )
6586
mask &= ~FT_CURVE_TAG_TOUCH_X;
6588
if ( CUR.GS.freeVector.y != 0 )
6589
mask &= ~FT_CURVE_TAG_TOUCH_Y;
6591
CUR.zp0.tags[point] &= mask;
6595
/* Local variables for Ins_IUP: */
6596
typedef struct IUP_WorkerRec_
6598
FT_Vector* orgs; /* original and current coordinate */
6599
FT_Vector* curs; /* arrays */
6603
} IUP_WorkerRec, *IUP_Worker;
6607
_iup_worker_shift( IUP_Worker worker,
6616
dx = worker->curs[p].x - worker->orgs[p].x;
6619
for ( i = p1; i < p; i++ )
6620
worker->curs[i].x += dx;
6622
for ( i = p + 1; i <= p2; i++ )
6623
worker->curs[i].x += dx;
6629
_iup_worker_interpolate( IUP_Worker worker,
6636
FT_F26Dot6 orus1, orus2, org1, org2, delta1, delta2;
6642
if ( BOUNDS( ref1, worker->max_points ) ||
6643
BOUNDS( ref2, worker->max_points ) )
6646
orus1 = worker->orus[ref1].x;
6647
orus2 = worker->orus[ref2].x;
6649
if ( orus1 > orus2 )
6664
org1 = worker->orgs[ref1].x;
6665
org2 = worker->orgs[ref2].x;
6666
delta1 = worker->curs[ref1].x - org1;
6667
delta2 = worker->curs[ref2].x - org2;
6669
if ( orus1 == orus2 )
6671
/* simple shift of untouched points */
6672
for ( i = p1; i <= p2; i++ )
6674
FT_F26Dot6 x = worker->orgs[i].x;
6682
worker->curs[i].x = x;
6688
FT_Bool scale_valid = 0;
6692
for ( i = p1; i <= p2; i++ )
6694
FT_F26Dot6 x = worker->orgs[i].x;
6700
else if ( x >= org2 )
6708
scale = TT_MULDIV( org2 + delta2 - ( org1 + delta1 ),
6709
0x10000L, orus2 - orus1 );
6712
x = ( org1 + delta1 ) +
6713
TT_MULFIX( worker->orus[i].x - orus1, scale );
6715
worker->curs[i].x = x;
6721
/*************************************************************************/
6723
/* IUP[a]: Interpolate Untouched Points */
6724
/* Opcode range: 0x30-0x31 */
6733
FT_UInt first_point; /* first point of contour */
6734
FT_UInt end_point; /* end point (last+1) of contour */
6736
FT_UInt first_touched; /* first touched point in contour */
6737
FT_UInt cur_touched; /* current touched point in contour */
6739
FT_UInt point; /* current point */
6740
FT_Short contour; /* current contour */
6745
/* ignore empty outlines */
6746
if ( CUR.pts.n_contours == 0 )
6749
if ( CUR.opcode & 1 )
6751
mask = FT_CURVE_TAG_TOUCH_X;
6752
V.orgs = CUR.pts.org;
6753
V.curs = CUR.pts.cur;
6754
V.orus = CUR.pts.orus;
6758
mask = FT_CURVE_TAG_TOUCH_Y;
6759
V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
6760
V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
6761
V.orus = (FT_Vector*)( (FT_Pos*)CUR.pts.orus + 1 );
6763
V.max_points = CUR.pts.n_points;
6770
end_point = CUR.pts.contours[contour] - CUR.pts.first_point;
6771
first_point = point;
6773
if ( BOUNDS ( end_point, CUR.pts.n_points ) )
6774
end_point = CUR.pts.n_points - 1;
6776
while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 )
6779
if ( point <= end_point )
6781
first_touched = point;
6782
cur_touched = point;
6786
while ( point <= end_point )
6788
if ( ( CUR.pts.tags[point] & mask ) != 0 )
6790
_iup_worker_interpolate( &V,
6795
cur_touched = point;
6801
if ( cur_touched == first_touched )
6802
_iup_worker_shift( &V, first_point, end_point, cur_touched );
6805
_iup_worker_interpolate( &V,
6806
(FT_UShort)( cur_touched + 1 ),
6811
if ( first_touched > 0 )
6812
_iup_worker_interpolate( &V,
6820
} while ( contour < CUR.pts.n_contours );
6824
/*************************************************************************/
6826
/* DELTAPn[]: DELTA exceptions P1, P2, P3 */
6827
/* Opcode range: 0x5D,0x71,0x72 */
6828
/* Stack: uint32 (2 * uint32)... --> */
6831
Ins_DELTAP( INS_ARG )
6839
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
6840
/* Delta hinting is covered by US Patent 5159668. */
6841
if ( CUR.face->unpatented_hinting )
6843
FT_Long n = args[0] * 2;
6848
CUR.error = TT_Err_Too_Few_Arguments;
6853
CUR.new_top = CUR.args;
6858
nump = (FT_ULong)args[0]; /* some points theoretically may occur more
6859
than once, thus UShort isn't enough */
6861
for ( k = 1; k <= nump; k++ )
6865
CUR.error = TT_Err_Too_Few_Arguments;
6871
A = (FT_UShort)CUR.stack[CUR.args + 1];
6872
B = CUR.stack[CUR.args];
6874
/* XXX: Because some popular fonts contain some invalid DeltaP */
6875
/* instructions, we simply ignore them when the stacked */
6876
/* point reference is off limit, rather than returning an */
6877
/* error. As a delta instruction doesn't change a glyph */
6878
/* in great ways, this shouldn't be a problem. */
6880
if ( !BOUNDS( A, CUR.zp0.n_points ) )
6882
C = ( (FT_ULong)B & 0xF0 ) >> 4;
6884
switch ( CUR.opcode )
6898
C += CUR.GS.delta_base;
6900
if ( CURRENT_Ppem() == (FT_Long)C )
6902
B = ( (FT_ULong)B & 0xF ) - 8;
6905
B = B * 64 / ( 1L << CUR.GS.delta_shift );
6907
CUR_Func_move( &CUR.zp0, A, B );
6911
if ( CUR.pedantic_hinting )
6912
CUR.error = TT_Err_Invalid_Reference;
6915
CUR.new_top = CUR.args;
6919
/*************************************************************************/
6921
/* DELTACn[]: DELTA exceptions C1, C2, C3 */
6922
/* Opcode range: 0x73,0x74,0x75 */
6923
/* Stack: uint32 (2 * uint32)... --> */
6926
Ins_DELTAC( INS_ARG )
6933
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
6934
/* Delta hinting is covered by US Patent 5159668. */
6935
if ( CUR.face->unpatented_hinting )
6937
FT_Long n = args[0] * 2;
6942
CUR.error = TT_Err_Too_Few_Arguments;
6947
CUR.new_top = CUR.args;
6952
nump = (FT_ULong)args[0];
6954
for ( k = 1; k <= nump; k++ )
6958
CUR.error = TT_Err_Too_Few_Arguments;
6964
A = (FT_ULong)CUR.stack[CUR.args + 1];
6965
B = CUR.stack[CUR.args];
6967
if ( BOUNDSL( A, CUR.cvtSize ) )
6969
if ( CUR.pedantic_hinting )
6971
CUR.error = TT_Err_Invalid_Reference;
6977
C = ( (FT_ULong)B & 0xF0 ) >> 4;
6979
switch ( CUR.opcode )
6993
C += CUR.GS.delta_base;
6995
if ( CURRENT_Ppem() == (FT_Long)C )
6997
B = ( (FT_ULong)B & 0xF ) - 8;
7000
B = B * 64 / ( 1L << CUR.GS.delta_shift );
7002
CUR_Func_move_cvt( A, B );
7007
CUR.new_top = CUR.args;
7011
/*************************************************************************/
7013
/* MISC. INSTRUCTIONS */
7015
/*************************************************************************/
7018
/*************************************************************************/
7020
/* GETINFO[]: GET INFOrmation */
7021
/* Opcode range: 0x88 */
7022
/* Stack: uint32 --> uint32 */
7025
Ins_GETINFO( INS_ARG )
7032
/* We return MS rasterizer version 1.7 for the font scaler. */
7033
if ( ( args[0] & 1 ) != 0 )
7036
/* Has the glyph been rotated? */
7037
if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated )
7040
/* Has the glyph been stretched? */
7041
if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched )
7044
/* Are we hinting for grayscale? */
7045
if ( ( args[0] & 32 ) != 0 && CUR.grayscale )
7053
Ins_UNKNOWN( INS_ARG )
7055
TT_DefRecord* def = CUR.IDefs;
7056
TT_DefRecord* limit = def + CUR.numIDefs;
7061
for ( ; def < limit; def++ )
7063
if ( (FT_Byte)def->opc == CUR.opcode && def->active )
7068
if ( CUR.callTop >= CUR.callSize )
7070
CUR.error = TT_Err_Stack_Overflow;
7074
call = CUR.callStack + CUR.callTop++;
7076
call->Caller_Range = CUR.curRange;
7077
call->Caller_IP = CUR.IP + 1;
7078
call->Cur_Count = 1;
7079
call->Cur_Restart = def->start;
7081
INS_Goto_CodeRange( def->range, def->start );
7083
CUR.step_ins = FALSE;
7088
CUR.error = TT_Err_Invalid_Opcode;
7092
#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
7096
TInstruction_Function Instruct_Dispatch[256] =
7098
/* Opcodes are gathered in groups of 16. */
7099
/* Please keep the spaces as they are. */
7101
/* SVTCA y */ Ins_SVTCA,
7102
/* SVTCA x */ Ins_SVTCA,
7103
/* SPvTCA y */ Ins_SPVTCA,
7104
/* SPvTCA x */ Ins_SPVTCA,
7105
/* SFvTCA y */ Ins_SFVTCA,
7106
/* SFvTCA x */ Ins_SFVTCA,
7107
/* SPvTL // */ Ins_SPVTL,
7108
/* SPvTL + */ Ins_SPVTL,
7109
/* SFvTL // */ Ins_SFVTL,
7110
/* SFvTL + */ Ins_SFVTL,
7111
/* SPvFS */ Ins_SPVFS,
7112
/* SFvFS */ Ins_SFVFS,
7115
/* SFvTPv */ Ins_SFVTPV,
7116
/* ISECT */ Ins_ISECT,
7118
/* SRP0 */ Ins_SRP0,
7119
/* SRP1 */ Ins_SRP1,
7120
/* SRP2 */ Ins_SRP2,
7121
/* SZP0 */ Ins_SZP0,
7122
/* SZP1 */ Ins_SZP1,
7123
/* SZP2 */ Ins_SZP2,
7124
/* SZPS */ Ins_SZPS,
7125
/* SLOOP */ Ins_SLOOP,
7127
/* RTHG */ Ins_RTHG,
7129
/* ELSE */ Ins_ELSE,
7130
/* JMPR */ Ins_JMPR,
7131
/* SCvTCi */ Ins_SCVTCI,
7132
/* SSwCi */ Ins_SSWCI,
7137
/* CLEAR */ Ins_CLEAR,
7138
/* SWAP */ Ins_SWAP,
7139
/* DEPTH */ Ins_DEPTH,
7140
/* CINDEX */ Ins_CINDEX,
7141
/* MINDEX */ Ins_MINDEX,
7142
/* AlignPTS */ Ins_ALIGNPTS,
7143
/* INS_0x28 */ Ins_UNKNOWN,
7145
/* LOOPCALL */ Ins_LOOPCALL,
7146
/* CALL */ Ins_CALL,
7147
/* FDEF */ Ins_FDEF,
7148
/* ENDF */ Ins_ENDF,
7149
/* MDAP[0] */ Ins_MDAP,
7150
/* MDAP[1] */ Ins_MDAP,
7152
/* IUP[0] */ Ins_IUP,
7153
/* IUP[1] */ Ins_IUP,
7154
/* SHP[0] */ Ins_SHP,
7155
/* SHP[1] */ Ins_SHP,
7156
/* SHC[0] */ Ins_SHC,
7157
/* SHC[1] */ Ins_SHC,
7158
/* SHZ[0] */ Ins_SHZ,
7159
/* SHZ[1] */ Ins_SHZ,
7160
/* SHPIX */ Ins_SHPIX,
7162
/* MSIRP[0] */ Ins_MSIRP,
7163
/* MSIRP[1] */ Ins_MSIRP,
7164
/* AlignRP */ Ins_ALIGNRP,
7165
/* RTDG */ Ins_RTDG,
7166
/* MIAP[0] */ Ins_MIAP,
7167
/* MIAP[1] */ Ins_MIAP,
7169
/* NPushB */ Ins_NPUSHB,
7170
/* NPushW */ Ins_NPUSHW,
7173
/* WCvtP */ Ins_WCVTP,
7174
/* RCvt */ Ins_RCVT,
7177
/* SCFS */ Ins_SCFS,
7180
/* MPPEM */ Ins_MPPEM,
7182
/* FlipON */ Ins_FLIPON,
7183
/* FlipOFF */ Ins_FLIPOFF,
7184
/* DEBUG */ Ins_DEBUG,
7187
/* LTEQ */ Ins_LTEQ,
7189
/* GTEQ */ Ins_GTEQ,
7193
/* EVEN */ Ins_EVEN,
7199
/* DeltaP1 */ Ins_DELTAP,
7209
/* FLOOR */ Ins_FLOOR,
7210
/* CEILING */ Ins_CEILING,
7211
/* ROUND[0] */ Ins_ROUND,
7212
/* ROUND[1] */ Ins_ROUND,
7213
/* ROUND[2] */ Ins_ROUND,
7214
/* ROUND[3] */ Ins_ROUND,
7215
/* NROUND[0] */ Ins_NROUND,
7216
/* NROUND[1] */ Ins_NROUND,
7217
/* NROUND[2] */ Ins_NROUND,
7218
/* NROUND[3] */ Ins_NROUND,
7220
/* WCvtF */ Ins_WCVTF,
7221
/* DeltaP2 */ Ins_DELTAP,
7222
/* DeltaP3 */ Ins_DELTAP,
7223
/* DeltaCn[0] */ Ins_DELTAC,
7224
/* DeltaCn[1] */ Ins_DELTAC,
7225
/* DeltaCn[2] */ Ins_DELTAC,
7226
/* SROUND */ Ins_SROUND,
7227
/* S45Round */ Ins_S45ROUND,
7228
/* JROT */ Ins_JROT,
7229
/* JROF */ Ins_JROF,
7230
/* ROFF */ Ins_ROFF,
7231
/* INS_0x7B */ Ins_UNKNOWN,
7232
/* RUTG */ Ins_RUTG,
7233
/* RDTG */ Ins_RDTG,
7234
/* SANGW */ Ins_SANGW,
7237
/* FlipPT */ Ins_FLIPPT,
7238
/* FlipRgON */ Ins_FLIPRGON,
7239
/* FlipRgOFF */ Ins_FLIPRGOFF,
7240
/* INS_0x83 */ Ins_UNKNOWN,
7241
/* INS_0x84 */ Ins_UNKNOWN,
7242
/* ScanCTRL */ Ins_SCANCTRL,
7243
/* SDPVTL[0] */ Ins_SDPVTL,
7244
/* SDPVTL[1] */ Ins_SDPVTL,
7245
/* GetINFO */ Ins_GETINFO,
7246
/* IDEF */ Ins_IDEF,
7247
/* ROLL */ Ins_ROLL,
7250
/* ScanTYPE */ Ins_SCANTYPE,
7251
/* InstCTRL */ Ins_INSTCTRL,
7252
/* INS_0x8F */ Ins_UNKNOWN,
7254
/* INS_0x90 */ Ins_UNKNOWN,
7255
/* INS_0x91 */ Ins_UNKNOWN,
7256
/* INS_0x92 */ Ins_UNKNOWN,
7257
/* INS_0x93 */ Ins_UNKNOWN,
7258
/* INS_0x94 */ Ins_UNKNOWN,
7259
/* INS_0x95 */ Ins_UNKNOWN,
7260
/* INS_0x96 */ Ins_UNKNOWN,
7261
/* INS_0x97 */ Ins_UNKNOWN,
7262
/* INS_0x98 */ Ins_UNKNOWN,
7263
/* INS_0x99 */ Ins_UNKNOWN,
7264
/* INS_0x9A */ Ins_UNKNOWN,
7265
/* INS_0x9B */ Ins_UNKNOWN,
7266
/* INS_0x9C */ Ins_UNKNOWN,
7267
/* INS_0x9D */ Ins_UNKNOWN,
7268
/* INS_0x9E */ Ins_UNKNOWN,
7269
/* INS_0x9F */ Ins_UNKNOWN,
7271
/* INS_0xA0 */ Ins_UNKNOWN,
7272
/* INS_0xA1 */ Ins_UNKNOWN,
7273
/* INS_0xA2 */ Ins_UNKNOWN,
7274
/* INS_0xA3 */ Ins_UNKNOWN,
7275
/* INS_0xA4 */ Ins_UNKNOWN,
7276
/* INS_0xA5 */ Ins_UNKNOWN,
7277
/* INS_0xA6 */ Ins_UNKNOWN,
7278
/* INS_0xA7 */ Ins_UNKNOWN,
7279
/* INS_0xA8 */ Ins_UNKNOWN,
7280
/* INS_0xA9 */ Ins_UNKNOWN,
7281
/* INS_0xAA */ Ins_UNKNOWN,
7282
/* INS_0xAB */ Ins_UNKNOWN,
7283
/* INS_0xAC */ Ins_UNKNOWN,
7284
/* INS_0xAD */ Ins_UNKNOWN,
7285
/* INS_0xAE */ Ins_UNKNOWN,
7286
/* INS_0xAF */ Ins_UNKNOWN,
7288
/* PushB[0] */ Ins_PUSHB,
7289
/* PushB[1] */ Ins_PUSHB,
7290
/* PushB[2] */ Ins_PUSHB,
7291
/* PushB[3] */ Ins_PUSHB,
7292
/* PushB[4] */ Ins_PUSHB,
7293
/* PushB[5] */ Ins_PUSHB,
7294
/* PushB[6] */ Ins_PUSHB,
7295
/* PushB[7] */ Ins_PUSHB,
7296
/* PushW[0] */ Ins_PUSHW,
7297
/* PushW[1] */ Ins_PUSHW,
7298
/* PushW[2] */ Ins_PUSHW,
7299
/* PushW[3] */ Ins_PUSHW,
7300
/* PushW[4] */ Ins_PUSHW,
7301
/* PushW[5] */ Ins_PUSHW,
7302
/* PushW[6] */ Ins_PUSHW,
7303
/* PushW[7] */ Ins_PUSHW,
7305
/* MDRP[00] */ Ins_MDRP,
7306
/* MDRP[01] */ Ins_MDRP,
7307
/* MDRP[02] */ Ins_MDRP,
7308
/* MDRP[03] */ Ins_MDRP,
7309
/* MDRP[04] */ Ins_MDRP,
7310
/* MDRP[05] */ Ins_MDRP,
7311
/* MDRP[06] */ Ins_MDRP,
7312
/* MDRP[07] */ Ins_MDRP,
7313
/* MDRP[08] */ Ins_MDRP,
7314
/* MDRP[09] */ Ins_MDRP,
7315
/* MDRP[10] */ Ins_MDRP,
7316
/* MDRP[11] */ Ins_MDRP,
7317
/* MDRP[12] */ Ins_MDRP,
7318
/* MDRP[13] */ Ins_MDRP,
7319
/* MDRP[14] */ Ins_MDRP,
7320
/* MDRP[15] */ Ins_MDRP,
7322
/* MDRP[16] */ Ins_MDRP,
7323
/* MDRP[17] */ Ins_MDRP,
7324
/* MDRP[18] */ Ins_MDRP,
7325
/* MDRP[19] */ Ins_MDRP,
7326
/* MDRP[20] */ Ins_MDRP,
7327
/* MDRP[21] */ Ins_MDRP,
7328
/* MDRP[22] */ Ins_MDRP,
7329
/* MDRP[23] */ Ins_MDRP,
7330
/* MDRP[24] */ Ins_MDRP,
7331
/* MDRP[25] */ Ins_MDRP,
7332
/* MDRP[26] */ Ins_MDRP,
7333
/* MDRP[27] */ Ins_MDRP,
7334
/* MDRP[28] */ Ins_MDRP,
7335
/* MDRP[29] */ Ins_MDRP,
7336
/* MDRP[30] */ Ins_MDRP,
7337
/* MDRP[31] */ Ins_MDRP,
7339
/* MIRP[00] */ Ins_MIRP,
7340
/* MIRP[01] */ Ins_MIRP,
7341
/* MIRP[02] */ Ins_MIRP,
7342
/* MIRP[03] */ Ins_MIRP,
7343
/* MIRP[04] */ Ins_MIRP,
7344
/* MIRP[05] */ Ins_MIRP,
7345
/* MIRP[06] */ Ins_MIRP,
7346
/* MIRP[07] */ Ins_MIRP,
7347
/* MIRP[08] */ Ins_MIRP,
7348
/* MIRP[09] */ Ins_MIRP,
7349
/* MIRP[10] */ Ins_MIRP,
7350
/* MIRP[11] */ Ins_MIRP,
7351
/* MIRP[12] */ Ins_MIRP,
7352
/* MIRP[13] */ Ins_MIRP,
7353
/* MIRP[14] */ Ins_MIRP,
7354
/* MIRP[15] */ Ins_MIRP,
7356
/* MIRP[16] */ Ins_MIRP,
7357
/* MIRP[17] */ Ins_MIRP,
7358
/* MIRP[18] */ Ins_MIRP,
7359
/* MIRP[19] */ Ins_MIRP,
7360
/* MIRP[20] */ Ins_MIRP,
7361
/* MIRP[21] */ Ins_MIRP,
7362
/* MIRP[22] */ Ins_MIRP,
7363
/* MIRP[23] */ Ins_MIRP,
7364
/* MIRP[24] */ Ins_MIRP,
7365
/* MIRP[25] */ Ins_MIRP,
7366
/* MIRP[26] */ Ins_MIRP,
7367
/* MIRP[27] */ Ins_MIRP,
7368
/* MIRP[28] */ Ins_MIRP,
7369
/* MIRP[29] */ Ins_MIRP,
7370
/* MIRP[30] */ Ins_MIRP,
7371
/* MIRP[31] */ Ins_MIRP
7375
#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
7378
/*************************************************************************/
7382
/* This function executes a run of opcodes. It will exit in the */
7383
/* following cases: */
7385
/* - Errors (in which case it returns FALSE). */
7387
/* - Reaching the end of the main code range (returns TRUE). */
7388
/* Reaching the end of a code range within a function call is an */
7391
/* - After executing one single opcode, if the flag `Instruction_Trap' */
7392
/* is set to TRUE (returns TRUE). */
7394
/* On exit with TRUE, test IP < CodeSize to know whether it comes from */
7395
/* an instruction trap or a normal termination. */
7398
/* Note: The documented DEBUG opcode pops a value from the stack. This */
7399
/* behaviour is unsupported; here a DEBUG opcode is always an */
7403
/* THIS IS THE INTERPRETER'S MAIN LOOP. */
7405
/* Instructions appear in the specification's order. */
7407
/*************************************************************************/
7410
/* documentation is in ttinterp.h */
7412
FT_EXPORT_DEF( FT_Error )
7413
TT_RunIns( TT_ExecContext exc )
7415
FT_Long ins_counter = 0; /* executed instructions counter */
7418
#ifdef TT_CONFIG_OPTION_STATIC_RASTER
7422
/* set CVT functions */
7423
CUR.tt_metrics.ratio = 0;
7424
if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
7426
/* non-square pixels, use the stretched routines */
7427
CUR.func_read_cvt = Read_CVT_Stretched;
7428
CUR.func_write_cvt = Write_CVT_Stretched;
7429
CUR.func_move_cvt = Move_CVT_Stretched;
7433
/* square pixels, use normal routines */
7434
CUR.func_read_cvt = Read_CVT;
7435
CUR.func_write_cvt = Write_CVT;
7436
CUR.func_move_cvt = Move_CVT;
7440
COMPUTE_Round( (FT_Byte)exc->GS.round_state );
7444
CUR.opcode = CUR.code[CUR.IP];
7447
FT_TRACE7(( opcode_name[CUR.opcode] ));
7448
FT_TRACE7(( "\n" ));
7450
if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
7452
if ( CUR.IP + 1 > CUR.codeSize )
7453
goto LErrorCodeOverflow_;
7455
CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
7458
if ( CUR.IP + CUR.length > CUR.codeSize )
7459
goto LErrorCodeOverflow_;
7461
/* First, let's check for empty stack and overflow */
7462
CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );
7464
/* `args' is the top of the stack once arguments have been popped. */
7465
/* One can also interpret it as the index of the last argument. */
7468
CUR.error = TT_Err_Too_Few_Arguments;
7472
CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
7474
/* `new_top' is the new top of the stack, after the instruction's */
7475
/* execution. `top' will be set to `new_top' after the `switch' */
7477
if ( CUR.new_top > CUR.stackSize )
7479
CUR.error = TT_Err_Stack_Overflow;
7483
CUR.step_ins = TRUE;
7484
CUR.error = TT_Err_Ok;
7486
#ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
7489
FT_Long* args = CUR.stack + CUR.args;
7490
FT_Byte opcode = CUR.opcode;
7493
#undef ARRAY_BOUND_ERROR
7494
#define ARRAY_BOUND_ERROR goto Set_Invalid_Ref
7499
case 0x00: /* SVTCA y */
7500
case 0x01: /* SVTCA x */
7501
case 0x02: /* SPvTCA y */
7502
case 0x03: /* SPvTCA x */
7503
case 0x04: /* SFvTCA y */
7504
case 0x05: /* SFvTCA x */
7509
AA = (FT_Short)( ( opcode & 1 ) << 14 );
7510
BB = (FT_Short)( AA ^ 0x4000 );
7514
CUR.GS.projVector.x = AA;
7515
CUR.GS.projVector.y = BB;
7517
CUR.GS.dualVector.x = AA;
7518
CUR.GS.dualVector.y = BB;
7522
GUESS_VECTOR( projVector );
7525
if ( ( opcode & 2 ) == 0 )
7527
CUR.GS.freeVector.x = AA;
7528
CUR.GS.freeVector.y = BB;
7532
GUESS_VECTOR( freeVector );
7539
case 0x06: /* SPvTL // */
7540
case 0x07: /* SPvTL + */
7544
case 0x08: /* SFvTL // */
7545
case 0x09: /* SFvTL + */
7549
case 0x0A: /* SPvFS */
7553
case 0x0B: /* SFvFS */
7557
case 0x0C: /* GPV */
7561
case 0x0D: /* GFV */
7565
case 0x0E: /* SFvTPv */
7569
case 0x0F: /* ISECT */
7570
Ins_ISECT( EXEC_ARG_ args );
7573
case 0x10: /* SRP0 */
7577
case 0x11: /* SRP1 */
7581
case 0x12: /* SRP2 */
7585
case 0x13: /* SZP0 */
7586
Ins_SZP0( EXEC_ARG_ args );
7589
case 0x14: /* SZP1 */
7590
Ins_SZP1( EXEC_ARG_ args );
7593
case 0x15: /* SZP2 */
7594
Ins_SZP2( EXEC_ARG_ args );
7597
case 0x16: /* SZPS */
7598
Ins_SZPS( EXEC_ARG_ args );
7601
case 0x17: /* SLOOP */
7605
case 0x18: /* RTG */
7609
case 0x19: /* RTHG */
7613
case 0x1A: /* SMD */
7617
case 0x1B: /* ELSE */
7618
Ins_ELSE( EXEC_ARG_ args );
7621
case 0x1C: /* JMPR */
7625
case 0x1D: /* SCVTCI */
7629
case 0x1E: /* SSWCI */
7633
case 0x1F: /* SSW */
7637
case 0x20: /* DUP */
7641
case 0x21: /* POP */
7645
case 0x22: /* CLEAR */
7649
case 0x23: /* SWAP */
7653
case 0x24: /* DEPTH */
7657
case 0x25: /* CINDEX */
7661
case 0x26: /* MINDEX */
7662
Ins_MINDEX( EXEC_ARG_ args );
7665
case 0x27: /* ALIGNPTS */
7666
Ins_ALIGNPTS( EXEC_ARG_ args );
7669
case 0x28: /* ???? */
7670
Ins_UNKNOWN( EXEC_ARG_ args );
7673
case 0x29: /* UTP */
7674
Ins_UTP( EXEC_ARG_ args );
7677
case 0x2A: /* LOOPCALL */
7678
Ins_LOOPCALL( EXEC_ARG_ args );
7681
case 0x2B: /* CALL */
7682
Ins_CALL( EXEC_ARG_ args );
7685
case 0x2C: /* FDEF */
7686
Ins_FDEF( EXEC_ARG_ args );
7689
case 0x2D: /* ENDF */
7690
Ins_ENDF( EXEC_ARG_ args );
7693
case 0x2E: /* MDAP */
7694
case 0x2F: /* MDAP */
7695
Ins_MDAP( EXEC_ARG_ args );
7699
case 0x30: /* IUP */
7700
case 0x31: /* IUP */
7701
Ins_IUP( EXEC_ARG_ args );
7704
case 0x32: /* SHP */
7705
case 0x33: /* SHP */
7706
Ins_SHP( EXEC_ARG_ args );
7709
case 0x34: /* SHC */
7710
case 0x35: /* SHC */
7711
Ins_SHC( EXEC_ARG_ args );
7714
case 0x36: /* SHZ */
7715
case 0x37: /* SHZ */
7716
Ins_SHZ( EXEC_ARG_ args );
7719
case 0x38: /* SHPIX */
7720
Ins_SHPIX( EXEC_ARG_ args );
7724
Ins_IP( EXEC_ARG_ args );
7727
case 0x3A: /* MSIRP */
7728
case 0x3B: /* MSIRP */
7729
Ins_MSIRP( EXEC_ARG_ args );
7732
case 0x3C: /* AlignRP */
7733
Ins_ALIGNRP( EXEC_ARG_ args );
7736
case 0x3D: /* RTDG */
7740
case 0x3E: /* MIAP */
7741
case 0x3F: /* MIAP */
7742
Ins_MIAP( EXEC_ARG_ args );
7745
case 0x40: /* NPUSHB */
7746
Ins_NPUSHB( EXEC_ARG_ args );
7749
case 0x41: /* NPUSHW */
7750
Ins_NPUSHW( EXEC_ARG_ args );
7758
CUR.error = TT_Err_Invalid_Reference;
7765
case 0x44: /* WCVTP */
7769
case 0x45: /* RCVT */
7775
Ins_GC( EXEC_ARG_ args );
7778
case 0x48: /* SCFS */
7779
Ins_SCFS( EXEC_ARG_ args );
7784
Ins_MD( EXEC_ARG_ args );
7787
case 0x4B: /* MPPEM */
7791
case 0x4C: /* MPS */
7795
case 0x4D: /* FLIPON */
7799
case 0x4E: /* FLIPOFF */
7803
case 0x4F: /* DEBUG */
7811
case 0x51: /* LTEQ */
7819
case 0x53: /* GTEQ */
7827
case 0x55: /* NEQ */
7831
case 0x56: /* ODD */
7835
case 0x57: /* EVEN */
7840
Ins_IF( EXEC_ARG_ args );
7843
case 0x59: /* EIF */
7847
case 0x5A: /* AND */
7855
case 0x5C: /* NOT */
7859
case 0x5D: /* DELTAP1 */
7860
Ins_DELTAP( EXEC_ARG_ args );
7863
case 0x5E: /* SDB */
7867
case 0x5F: /* SDS */
7871
case 0x60: /* ADD */
7875
case 0x61: /* SUB */
7879
case 0x62: /* DIV */
7883
case 0x63: /* MUL */
7887
case 0x64: /* ABS */
7891
case 0x65: /* NEG */
7895
case 0x66: /* FLOOR */
7899
case 0x67: /* CEILING */
7903
case 0x68: /* ROUND */
7904
case 0x69: /* ROUND */
7905
case 0x6A: /* ROUND */
7906
case 0x6B: /* ROUND */
7910
case 0x6C: /* NROUND */
7911
case 0x6D: /* NROUND */
7912
case 0x6E: /* NRRUND */
7913
case 0x6F: /* NROUND */
7917
case 0x70: /* WCVTF */
7921
case 0x71: /* DELTAP2 */
7922
case 0x72: /* DELTAP3 */
7923
Ins_DELTAP( EXEC_ARG_ args );
7926
case 0x73: /* DELTAC0 */
7927
case 0x74: /* DELTAC1 */
7928
case 0x75: /* DELTAC2 */
7929
Ins_DELTAC( EXEC_ARG_ args );
7932
case 0x76: /* SROUND */
7936
case 0x77: /* S45Round */
7940
case 0x78: /* JROT */
7944
case 0x79: /* JROF */
7948
case 0x7A: /* ROFF */
7952
case 0x7B: /* ???? */
7953
Ins_UNKNOWN( EXEC_ARG_ args );
7956
case 0x7C: /* RUTG */
7960
case 0x7D: /* RDTG */
7964
case 0x7E: /* SANGW */
7966
/* nothing - obsolete */
7969
case 0x80: /* FLIPPT */
7970
Ins_FLIPPT( EXEC_ARG_ args );
7973
case 0x81: /* FLIPRGON */
7974
Ins_FLIPRGON( EXEC_ARG_ args );
7977
case 0x82: /* FLIPRGOFF */
7978
Ins_FLIPRGOFF( EXEC_ARG_ args );
7981
case 0x83: /* UNKNOWN */
7982
case 0x84: /* UNKNOWN */
7983
Ins_UNKNOWN( EXEC_ARG_ args );
7986
case 0x85: /* SCANCTRL */
7987
Ins_SCANCTRL( EXEC_ARG_ args );
7990
case 0x86: /* SDPVTL */
7991
case 0x87: /* SDPVTL */
7992
Ins_SDPVTL( EXEC_ARG_ args );
7995
case 0x88: /* GETINFO */
7996
Ins_GETINFO( EXEC_ARG_ args );
7999
case 0x89: /* IDEF */
8000
Ins_IDEF( EXEC_ARG_ args );
8003
case 0x8A: /* ROLL */
8004
Ins_ROLL( EXEC_ARG_ args );
8007
case 0x8B: /* MAX */
8011
case 0x8C: /* MIN */
8015
case 0x8D: /* SCANTYPE */
8016
Ins_SCANTYPE( EXEC_ARG_ args );
8019
case 0x8E: /* INSTCTRL */
8020
Ins_INSTCTRL( EXEC_ARG_ args );
8024
Ins_UNKNOWN( EXEC_ARG_ args );
8028
if ( opcode >= 0xE0 )
8029
Ins_MIRP( EXEC_ARG_ args );
8030
else if ( opcode >= 0xC0 )
8031
Ins_MDRP( EXEC_ARG_ args );
8032
else if ( opcode >= 0xB8 )
8033
Ins_PUSHW( EXEC_ARG_ args );
8034
else if ( opcode >= 0xB0 )
8035
Ins_PUSHB( EXEC_ARG_ args );
8037
Ins_UNKNOWN( EXEC_ARG_ args );
8044
Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );
8046
#endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
8048
if ( CUR.error != TT_Err_Ok )
8050
switch ( CUR.error )
8052
case TT_Err_Invalid_Opcode: /* looking for redefined instructions */
8054
TT_DefRecord* def = CUR.IDefs;
8055
TT_DefRecord* limit = def + CUR.numIDefs;
8058
for ( ; def < limit; def++ )
8060
if ( def->active && CUR.opcode == (FT_Byte)def->opc )
8062
TT_CallRec* callrec;
8065
if ( CUR.callTop >= CUR.callSize )
8067
CUR.error = TT_Err_Invalid_Reference;
8071
callrec = &CUR.callStack[CUR.callTop];
8073
callrec->Caller_Range = CUR.curRange;
8074
callrec->Caller_IP = CUR.IP + 1;
8075
callrec->Cur_Count = 1;
8076
callrec->Cur_Restart = def->start;
8078
if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
8086
CUR.error = TT_Err_Invalid_Opcode;
8090
break; /* Unreachable code warning suppression. */
8091
/* Leave to remind in case a later change the editor */
8092
/* to consider break; */
8104
CUR.top = CUR.new_top;
8107
CUR.IP += CUR.length;
8109
/* increment instruction counter and check if we didn't */
8110
/* run this program for too long (e.g. infinite loops). */
8111
if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
8112
return TT_Err_Execution_Too_Long;
8115
if ( CUR.IP >= CUR.codeSize )
8117
if ( CUR.callTop > 0 )
8119
CUR.error = TT_Err_Code_Overflow;
8125
} while ( !CUR.instruction_trap );
8129
#ifdef TT_CONFIG_OPTION_STATIC_RASTER
8135
LErrorCodeOverflow_:
8136
CUR.error = TT_Err_Code_Overflow;
8140
#ifdef TT_CONFIG_OPTION_STATIC_RASTER
8144
/* If any errors have occurred, function tables may be broken. */
8145
/* Force a re-execution of `prep' and `fpgm' tables if no */
8146
/* bytecode debugger is run. */
8147
if ( CUR.error && !CUR.instruction_trap )
8149
FT_TRACE1(( " The interpreter returned error 0x%x\n", CUR.error ));
8150
exc->size->cvt_ready = FALSE;
8157
#endif /* TT_USE_BYTECODE_INTERPRETER */