blob: da2c8839f7861262b928be309631e1135ccae8ee [file] [log] [blame]
David Turnerd2b1f351999-12-16 23:11:37 +00001/***************************************************************************/
2/* */
3/* ttinterp.c */
4/* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00005/* TrueType bytecode interpreter (body). */
David Turnerd2b1f351999-12-16 23:11:37 +00006/* */
Werner Lemberg28464c42008-02-18 20:34:42 +00007/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by */
David Turnerd2b1f351999-12-16 23:11:37 +00008/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
Werner Lemberg78575dc2000-06-12 19:36:41 +000010/* This file is part of the FreeType project, and may only be used, */
11/* modified, and distributed under the terms of the FreeType project */
David Turnerd2b1f351999-12-16 23:11:37 +000012/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13/* this file you indicate that you have read the license and */
14/* understand and accept it fully. */
15/* */
16/***************************************************************************/
17
Werner Lembergcc069be2000-12-08 16:17:16 +000018
David Turner19ed8af2000-12-08 02:42:29 +000019#include <ft2build.h>
20#include FT_INTERNAL_DEBUG_H
21#include FT_INTERNAL_CALC_H
David Turnerac6cc412001-06-14 12:34:00 +000022#include FT_TRIGONOMETRY_H
David Turner19ed8af2000-12-08 02:42:29 +000023#include FT_SYSTEM_H
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000024
David Turner8d3a4012001-03-20 11:14:24 +000025#include "ttinterp.h"
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000026
27#include "tterrors.h"
David Turnerd2b1f351999-12-16 23:11:37 +000028
Werner Lemberg78575dc2000-06-12 19:36:41 +000029
David Turner6aa260c2006-08-25 22:45:13 +000030#ifdef TT_USE_BYTECODE_INTERPRETER
David Turner1ab77fd2000-02-10 18:08:17 +000031
32
Werner Lemberg9f051a72003-11-25 18:15:56 +000033#define TT_MULFIX FT_MulFix
34#define TT_MULDIV FT_MulDiv
35#define TT_MULDIV_NO_ROUND FT_MulDiv_No_Round
36
David Turnerd2b1f351999-12-16 23:11:37 +000037
David Turnerd2b1f351999-12-16 23:11:37 +000038 /*************************************************************************/
39 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +000040 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
41 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
42 /* messages during execution. */
David Turnerd2b1f351999-12-16 23:11:37 +000043 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +000044#undef FT_COMPONENT
45#define FT_COMPONENT trace_ttinterp
46
Werner Lemberg78575dc2000-06-12 19:36:41 +000047 /*************************************************************************/
48 /* */
49 /* In order to detect infinite loops in the code, we set up a counter */
50 /* within the run loop. A single stroke of interpretation is now */
Werner Lemberg6e87ed92007-01-26 22:18:56 +000051 /* limited to a maximal number of opcodes defined below. */
Werner Lemberg78575dc2000-06-12 19:36:41 +000052 /* */
53#define MAX_RUNNABLE_OPCODES 1000000L
David Turnerd2b1f351999-12-16 23:11:37 +000054
55
56 /*************************************************************************/
57 /* */
58 /* There are two kinds of implementations: */
59 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +000060 /* a. static implementation */
David Turnerd2b1f351999-12-16 23:11:37 +000061 /* */
62 /* The current execution context is a static variable, which fields */
63 /* are accessed directly by the interpreter during execution. The */
64 /* context is named `cur'. */
65 /* */
66 /* This version is non-reentrant, of course. */
67 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +000068 /* b. indirect implementation */
David Turnerd2b1f351999-12-16 23:11:37 +000069 /* */
70 /* The current execution context is passed to _each_ function as its */
71 /* first argument, and each field is thus accessed indirectly. */
72 /* */
73 /* This version is fully re-entrant. */
74 /* */
75 /* The idea is that an indirect implementation may be slower to execute */
76 /* on low-end processors that are used in some systems (like 386s or */
77 /* even 486s). */
78 /* */
79 /* As a consequence, the indirect implementation is now the default, as */
80 /* its performance costs can be considered negligible in our context. */
81 /* Note, however, that we kept the same source with macros because: */
82 /* */
83 /* - The code is kept very close in design to the Pascal code used for */
84 /* development. */
85 /* */
86 /* - It's much more readable that way! */
87 /* */
88 /* - It's still open to experimentation and tuning. */
89 /* */
90 /*************************************************************************/
91
92
Werner Lemberg78575dc2000-06-12 19:36:41 +000093#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER /* indirect implementation */
David Turnerd2b1f351999-12-16 23:11:37 +000094
Werner Lemberg78575dc2000-06-12 19:36:41 +000095#define CUR (*exc) /* see ttobjs.h */
David Turnerd2b1f351999-12-16 23:11:37 +000096
Werner Lemberg674ba912005-11-16 18:09:27 +000097 /*************************************************************************/
98 /* */
99 /* This macro is used whenever `exec' is unused in a function, to avoid */
100 /* stupid warnings from pedantic compilers. */
101 /* */
102#define FT_UNUSED_EXEC FT_UNUSED( exc )
David Turnerf7cc1812005-11-15 17:30:56 +0000103
Werner Lemberg78575dc2000-06-12 19:36:41 +0000104#else /* static implementation */
David Turnerd2b1f351999-12-16 23:11:37 +0000105
Werner Lemberg78575dc2000-06-12 19:36:41 +0000106#define CUR cur
David Turnerd2b1f351999-12-16 23:11:37 +0000107
Werner Lemberg674ba912005-11-16 18:09:27 +0000108#define FT_UNUSED_EXEC int __dummy = __dummy
David Turnerf7cc1812005-11-15 17:30:56 +0000109
David Turnerd2b1f351999-12-16 23:11:37 +0000110 static
111 TT_ExecContextRec cur; /* static exec. context variable */
112
113 /* apparently, we have a _lot_ of direct indexing when accessing */
114 /* the static `cur', which makes the code bigger (due to all the */
115 /* four bytes addresses). */
116
117#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
118
119
120 /*************************************************************************/
121 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000122 /* The instruction argument stack. */
David Turnerd2b1f351999-12-16 23:11:37 +0000123 /* */
David Turnerf9b8dec2000-06-16 19:34:52 +0000124#define INS_ARG EXEC_OP_ FT_Long* args /* see ttobjs.h for EXEC_OP_ */
David Turnerd2b1f351999-12-16 23:11:37 +0000125
126
127 /*************************************************************************/
128 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000129 /* This macro is used whenever `args' is unused in a function, to avoid */
130 /* stupid warnings from pedantic compilers. */
131 /* */
David Turnerc6a92202000-07-04 18:12:13 +0000132#define FT_UNUSED_ARG FT_UNUSED_EXEC; FT_UNUSED( args )
David Turnerd2b1f351999-12-16 23:11:37 +0000133
134
135 /*************************************************************************/
136 /* */
137 /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to */
Werner Lemberg6e87ed92007-01-26 22:18:56 +0000138 /* increase readability of the code. */
David Turnerd2b1f351999-12-16 23:11:37 +0000139 /* */
140 /*************************************************************************/
141
142
143#define SKIP_Code() \
144 SkipCode( EXEC_ARG )
145
146#define GET_ShortIns() \
147 GetShortIns( EXEC_ARG )
148
149#define NORMalize( x, y, v ) \
150 Normalize( EXEC_ARG_ x, y, v )
151
152#define SET_SuperRound( scale, flags ) \
153 SetSuperRound( EXEC_ARG_ scale, flags )
154
155#define ROUND_None( d, c ) \
156 Round_None( EXEC_ARG_ d, c )
157
158#define INS_Goto_CodeRange( range, ip ) \
159 Ins_Goto_CodeRange( EXEC_ARG_ range, ip )
160
David Turnerd2b1f351999-12-16 23:11:37 +0000161#define CUR_Func_move( z, p, d ) \
162 CUR.func_move( EXEC_ARG_ z, p, d )
163
Werner Lembergbe67c4e2003-11-24 22:54:58 +0000164#define CUR_Func_move_orig( z, p, d ) \
165 CUR.func_move_orig( EXEC_ARG_ z, p, d )
166
David Turnerd2b1f351999-12-16 23:11:37 +0000167#define CUR_Func_round( d, c ) \
168 CUR.func_round( EXEC_ARG_ d, c )
169
170#define CUR_Func_read_cvt( index ) \
171 CUR.func_read_cvt( EXEC_ARG_ index )
172
173#define CUR_Func_write_cvt( index, val ) \
174 CUR.func_write_cvt( EXEC_ARG_ index, val )
175
176#define CUR_Func_move_cvt( index, val ) \
177 CUR.func_move_cvt( EXEC_ARG_ index, val )
178
179#define CURRENT_Ratio() \
180 Current_Ratio( EXEC_ARG )
181
182#define CURRENT_Ppem() \
183 Current_Ppem( EXEC_ARG )
184
185#define CUR_Ppem() \
186 Cur_PPEM( EXEC_ARG )
187
David Turnerd2b1f351999-12-16 23:11:37 +0000188#define INS_SxVTL( a, b, c, d ) \
189 Ins_SxVTL( EXEC_ARG_ a, b, c, d )
190
191#define COMPUTE_Funcs() \
192 Compute_Funcs( EXEC_ARG )
193
194#define COMPUTE_Round( a ) \
195 Compute_Round( EXEC_ARG_ a )
196
197#define COMPUTE_Point_Displacement( a, b, c, d ) \
198 Compute_Point_Displacement( EXEC_ARG_ a, b, c, d )
199
200#define MOVE_Zp2_Point( a, b, c, t ) \
201 Move_Zp2_Point( EXEC_ARG_ a, b, c, t )
202
203
Werner Lemberg406d25f2007-02-12 22:01:18 +0000204#define CUR_Func_project( v1, v2 ) \
205 CUR.func_project( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
David Turner72a0dd22007-02-12 15:24:51 +0000206
Werner Lemberg406d25f2007-02-12 22:01:18 +0000207#define CUR_Func_dualproj( v1, v2 ) \
208 CUR.func_dualproj( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
David Turner72a0dd22007-02-12 15:24:51 +0000209
Werner Lemberg406d25f2007-02-12 22:01:18 +0000210#define CUR_fast_project( v ) \
211 CUR.func_project( EXEC_ARG_ (v)->x, (v)->y )
David Turner72a0dd22007-02-12 15:24:51 +0000212
Werner Lemberg406d25f2007-02-12 22:01:18 +0000213#define CUR_fast_dualproj( v ) \
214 CUR.func_dualproj( EXEC_ARG_ (v)->x, (v)->y )
David Turner72a0dd22007-02-12 15:24:51 +0000215
216
David Turnerd2b1f351999-12-16 23:11:37 +0000217 /*************************************************************************/
218 /* */
219 /* Instruction dispatch function, as used by the interpreter. */
220 /* */
221 typedef void (*TInstruction_Function)( INS_ARG );
222
223
224 /*************************************************************************/
225 /* */
226 /* A simple bounds-checking macro. */
227 /* */
David Turnerf9b8dec2000-06-16 19:34:52 +0000228#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) )
David Turnerd2b1f351999-12-16 23:11:37 +0000229
Werner Lemberg78575dc2000-06-12 19:36:41 +0000230#undef SUCCESS
231#define SUCCESS 0
David Turnerd2b1f351999-12-16 23:11:37 +0000232
Werner Lemberg78575dc2000-06-12 19:36:41 +0000233#undef FAILURE
234#define FAILURE 1
David Turnerd2b1f351999-12-16 23:11:37 +0000235
David Turner8b6db862003-08-17 22:09:14 +0000236#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Werner Lemberga3f4da82003-04-29 13:23:47 +0000237#define GUESS_VECTOR( V ) \
238 if ( CUR.face->unpatented_hinting ) \
239 { \
240 CUR.GS.V.x = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0x4000 : 0 ); \
241 CUR.GS.V.y = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0 : 0x4000 ); \
Graham Asher3ea859f2003-04-25 11:40:46 +0000242 }
243#else
244#define GUESS_VECTOR( V )
245#endif
David Turnerd2b1f351999-12-16 23:11:37 +0000246
247 /*************************************************************************/
248 /* */
249 /* CODERANGE FUNCTIONS */
250 /* */
251 /*************************************************************************/
252
253
254 /*************************************************************************/
255 /* */
256 /* <Function> */
257 /* TT_Goto_CodeRange */
258 /* */
259 /* <Description> */
260 /* Switches to a new code range (updates the code related elements in */
261 /* `exec', and `IP'). */
262 /* */
263 /* <Input> */
264 /* range :: The new execution code range. */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000265 /* */
266 /* IP :: The new IP in the new code range. */
David Turnerd2b1f351999-12-16 23:11:37 +0000267 /* */
268 /* <InOut> */
269 /* exec :: The target execution context. */
270 /* */
271 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +0000272 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000273 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +0000274 FT_LOCAL_DEF( FT_Error )
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000275 TT_Goto_CodeRange( TT_ExecContext exec,
276 FT_Int range,
277 FT_Long IP )
David Turnerd2b1f351999-12-16 23:11:37 +0000278 {
279 TT_CodeRange* coderange;
280
281
Werner Lembergb1e6e592002-03-29 07:43:04 +0000282 FT_ASSERT( range >= 1 && range <= 3 );
David Turnerd2b1f351999-12-16 23:11:37 +0000283
284 coderange = &exec->codeRangeTable[range - 1];
285
Werner Lembergb1e6e592002-03-29 07:43:04 +0000286 FT_ASSERT( coderange->base != NULL );
David Turnerd2b1f351999-12-16 23:11:37 +0000287
288 /* NOTE: Because the last instruction of a program may be a CALL */
289 /* which will return to the first byte *after* the code */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000290 /* range, we test for IP <= Size instead of IP < Size. */
David Turnerd2b1f351999-12-16 23:11:37 +0000291 /* */
Werner Lembergb1e6e592002-03-29 07:43:04 +0000292 FT_ASSERT( (FT_ULong)IP <= coderange->size );
David Turnerd2b1f351999-12-16 23:11:37 +0000293
294 exec->code = coderange->base;
295 exec->codeSize = coderange->size;
296 exec->IP = IP;
297 exec->curRange = range;
298
299 return TT_Err_Ok;
300 }
301
302
303 /*************************************************************************/
304 /* */
305 /* <Function> */
306 /* TT_Set_CodeRange */
307 /* */
308 /* <Description> */
309 /* Sets a code range. */
310 /* */
311 /* <Input> */
312 /* range :: The code range index. */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000313 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000314 /* base :: The new code base. */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000315 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000316 /* length :: The range size in bytes. */
317 /* */
318 /* <InOut> */
319 /* exec :: The target execution context. */
320 /* */
321 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +0000322 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000323 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +0000324 FT_LOCAL_DEF( FT_Error )
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000325 TT_Set_CodeRange( TT_ExecContext exec,
326 FT_Int range,
327 void* base,
328 FT_Long length )
David Turnerd2b1f351999-12-16 23:11:37 +0000329 {
Werner Lembergb1e6e592002-03-29 07:43:04 +0000330 FT_ASSERT( range >= 1 && range <= 3 );
David Turnerd2b1f351999-12-16 23:11:37 +0000331
David Turnerf9b8dec2000-06-16 19:34:52 +0000332 exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
David Turnerd2b1f351999-12-16 23:11:37 +0000333 exec->codeRangeTable[range - 1].size = length;
334
335 return TT_Err_Ok;
336 }
337
338
339 /*************************************************************************/
340 /* */
341 /* <Function> */
342 /* TT_Clear_CodeRange */
343 /* */
344 /* <Description> */
345 /* Clears a code range. */
346 /* */
347 /* <Input> */
348 /* range :: The code range index. */
349 /* */
350 /* <InOut> */
351 /* exec :: The target execution context. */
352 /* */
353 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +0000354 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000355 /* */
356 /* <Note> */
357 /* Does not set the Error variable. */
358 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +0000359 FT_LOCAL_DEF( FT_Error )
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000360 TT_Clear_CodeRange( TT_ExecContext exec,
361 FT_Int range )
David Turnerd2b1f351999-12-16 23:11:37 +0000362 {
Werner Lembergb1e6e592002-03-29 07:43:04 +0000363 FT_ASSERT( range >= 1 && range <= 3 );
David Turnerd2b1f351999-12-16 23:11:37 +0000364
365 exec->codeRangeTable[range - 1].base = NULL;
366 exec->codeRangeTable[range - 1].size = 0;
367
368 return TT_Err_Ok;
369 }
370
371
372 /*************************************************************************/
373 /* */
374 /* EXECUTION CONTEXT ROUTINES */
375 /* */
376 /*************************************************************************/
377
378
379 /*************************************************************************/
380 /* */
381 /* <Function> */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000382 /* TT_Done_Context */
David Turnerd2b1f351999-12-16 23:11:37 +0000383 /* */
384 /* <Description> */
385 /* Destroys a given context. */
386 /* */
387 /* <Input> */
388 /* exec :: A handle to the target execution context. */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000389 /* */
390 /* memory :: A handle to the parent memory object. */
David Turnerd2b1f351999-12-16 23:11:37 +0000391 /* */
392 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +0000393 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000394 /* */
395 /* <Note> */
396 /* Only the glyph loader and debugger should call this function. */
397 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +0000398 FT_LOCAL_DEF( FT_Error )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000399 TT_Done_Context( TT_ExecContext exec )
David Turnerd2b1f351999-12-16 23:11:37 +0000400 {
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000401 FT_Memory memory = exec->memory;
402
403
David Turnerd2b1f351999-12-16 23:11:37 +0000404 /* points zone */
David Turnerd2b1f351999-12-16 23:11:37 +0000405 exec->maxPoints = 0;
406 exec->maxContours = 0;
407
408 /* free stack */
David Turnere459d742002-03-22 13:52:37 +0000409 FT_FREE( exec->stack );
David Turnerd2b1f351999-12-16 23:11:37 +0000410 exec->stackSize = 0;
411
412 /* free call stack */
David Turnere459d742002-03-22 13:52:37 +0000413 FT_FREE( exec->callStack );
David Turnerd2b1f351999-12-16 23:11:37 +0000414 exec->callSize = 0;
415 exec->callTop = 0;
416
417 /* free glyph code range */
David Turnere459d742002-03-22 13:52:37 +0000418 FT_FREE( exec->glyphIns );
David Turnerd2b1f351999-12-16 23:11:37 +0000419 exec->glyphSize = 0;
420
421 exec->size = NULL;
422 exec->face = NULL;
423
David Turnere459d742002-03-22 13:52:37 +0000424 FT_FREE( exec );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000425
David Turnerd2b1f351999-12-16 23:11:37 +0000426 return TT_Err_Ok;
427 }
428
429
430 /*************************************************************************/
431 /* */
432 /* <Function> */
433 /* Init_Context */
434 /* */
435 /* <Description> */
436 /* Initializes a context object. */
437 /* */
438 /* <Input> */
439 /* memory :: A handle to the parent memory object. */
440 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000441 /* <InOut> */
442 /* exec :: A handle to the target execution context. */
443 /* */
444 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +0000445 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000446 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000447 static FT_Error
448 Init_Context( TT_ExecContext exec,
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000449 FT_Memory memory )
David Turnerd2b1f351999-12-16 23:11:37 +0000450 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000451 FT_Error error;
David Turnerd2b1f351999-12-16 23:11:37 +0000452
453
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000454 FT_TRACE1(( "Init_Context: new object at 0x%08p\n", exec ));
David Turnerd2b1f351999-12-16 23:11:37 +0000455
David Turnerd2b1f351999-12-16 23:11:37 +0000456 exec->memory = memory;
457 exec->callSize = 32;
458
David Turnere459d742002-03-22 13:52:37 +0000459 if ( FT_NEW_ARRAY( exec->callStack, exec->callSize ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000460 goto Fail_Memory;
461
462 /* all values in the context are set to 0 already, but this is */
463 /* here as a remainder */
464 exec->maxPoints = 0;
465 exec->maxContours = 0;
466
467 exec->stackSize = 0;
David Turnerd2b1f351999-12-16 23:11:37 +0000468 exec->glyphSize = 0;
469
470 exec->stack = NULL;
David Turnerd2b1f351999-12-16 23:11:37 +0000471 exec->glyphIns = NULL;
472
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000473 exec->face = NULL;
David Turnerd2b1f351999-12-16 23:11:37 +0000474 exec->size = NULL;
475
476 return TT_Err_Ok;
477
478 Fail_Memory:
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000479 FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n",
480 (FT_Long)exec ));
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000481 TT_Done_Context( exec );
David Turnerd2b1f351999-12-16 23:11:37 +0000482
483 return error;
484 }
485
486
487 /*************************************************************************/
488 /* */
489 /* <Function> */
490 /* Update_Max */
491 /* */
492 /* <Description> */
493 /* Checks the size of a buffer and reallocates it if necessary. */
494 /* */
495 /* <Input> */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000496 /* memory :: A handle to the parent memory object. */
497 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000498 /* multiplier :: The size in bytes of each element in the buffer. */
499 /* */
500 /* new_max :: The new capacity (size) of the buffer. */
501 /* */
502 /* <InOut> */
503 /* size :: The address of the buffer's current size expressed */
504 /* in elements. */
505 /* */
506 /* buff :: The address of the buffer base pointer. */
507 /* */
508 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +0000509 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000510 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000511 static FT_Error
512 Update_Max( FT_Memory memory,
513 FT_ULong* size,
514 FT_Long multiplier,
David Turnere3654532007-01-13 00:19:18 +0000515 void* _pbuff,
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000516 FT_ULong new_max )
David Turnerd2b1f351999-12-16 23:11:37 +0000517 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000518 FT_Error error;
David Turnere3654532007-01-13 00:19:18 +0000519 void** pbuff = (void**)_pbuff;
David Turnerd2b1f351999-12-16 23:11:37 +0000520
521
522 if ( *size < new_max )
523 {
David Turnere3654532007-01-13 00:19:18 +0000524 if ( FT_REALLOC( *pbuff, *size * multiplier, new_max * multiplier ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000525 return error;
526 *size = new_max;
527 }
528
529 return TT_Err_Ok;
530 }
531
532
David Turnerd2b1f351999-12-16 23:11:37 +0000533 /*************************************************************************/
534 /* */
535 /* <Function> */
536 /* TT_Load_Context */
537 /* */
538 /* <Description> */
539 /* Prepare an execution context for glyph hinting. */
540 /* */
541 /* <Input> */
542 /* face :: A handle to the source face object. */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000543 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000544 /* size :: A handle to the source size object. */
545 /* */
546 /* <InOut> */
547 /* exec :: A handle to the target execution context. */
548 /* */
549 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +0000550 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000551 /* */
552 /* <Note> */
553 /* Only the glyph loader and debugger should call this function. */
554 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +0000555 FT_LOCAL_DEF( FT_Error )
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000556 TT_Load_Context( TT_ExecContext exec,
557 TT_Face face,
558 TT_Size size )
David Turnerd2b1f351999-12-16 23:11:37 +0000559 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000560 FT_Int i;
561 FT_ULong tmp;
David Turnerd2b1f351999-12-16 23:11:37 +0000562 TT_MaxProfile* maxp;
David Turnerf9b8dec2000-06-16 19:34:52 +0000563 FT_Error error;
David Turnerd2b1f351999-12-16 23:11:37 +0000564
Werner Lemberg78575dc2000-06-12 19:36:41 +0000565
David Turnerd2b1f351999-12-16 23:11:37 +0000566 exec->face = face;
567 maxp = &face->max_profile;
568 exec->size = size;
569
570 if ( size )
571 {
572 exec->numFDefs = size->num_function_defs;
573 exec->maxFDefs = size->max_function_defs;
574 exec->numIDefs = size->num_instruction_defs;
575 exec->maxIDefs = size->max_instruction_defs;
576 exec->FDefs = size->function_defs;
577 exec->IDefs = size->instruction_defs;
578 exec->tt_metrics = size->ttmetrics;
David Turnerba4511b2003-02-18 22:25:22 +0000579 exec->metrics = size->metrics;
David Turnerd2b1f351999-12-16 23:11:37 +0000580
581 exec->maxFunc = size->max_func;
582 exec->maxIns = size->max_ins;
583
584 for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
585 exec->codeRangeTable[i] = size->codeRangeTable[i];
586
587 /* set graphics state */
588 exec->GS = size->GS;
589
590 exec->cvtSize = size->cvt_size;
591 exec->cvt = size->cvt;
592
593 exec->storeSize = size->storage_size;
594 exec->storage = size->storage;
595
596 exec->twilight = size->twilight;
597 }
598
David Turnerd2b1f351999-12-16 23:11:37 +0000599 /* XXX: We reserve a little more elements on the stack to deal safely */
600 /* with broken fonts like arialbs, courbs, timesbs, etc. */
601 tmp = exec->stackSize;
602 error = Update_Max( exec->memory,
603 &tmp,
David Turnerf9b8dec2000-06-16 19:34:52 +0000604 sizeof ( FT_F26Dot6 ),
David Turnere3654532007-01-13 00:19:18 +0000605 (void*)&exec->stack,
David Turnerd2b1f351999-12-16 23:11:37 +0000606 maxp->maxStackElements + 32 );
David Turnerf9b8dec2000-06-16 19:34:52 +0000607 exec->stackSize = (FT_UInt)tmp;
David Turnerd2b1f351999-12-16 23:11:37 +0000608 if ( error )
609 return error;
610
611 tmp = exec->glyphSize;
612 error = Update_Max( exec->memory,
613 &tmp,
David Turnerf9b8dec2000-06-16 19:34:52 +0000614 sizeof ( FT_Byte ),
David Turnere3654532007-01-13 00:19:18 +0000615 (void*)&exec->glyphIns,
David Turnerd2b1f351999-12-16 23:11:37 +0000616 maxp->maxSizeOfInstructions );
David Turnerf9b8dec2000-06-16 19:34:52 +0000617 exec->glyphSize = (FT_UShort)tmp;
David Turnerd2b1f351999-12-16 23:11:37 +0000618 if ( error )
619 return error;
620
David Turnerd2b1f351999-12-16 23:11:37 +0000621 exec->pts.n_points = 0;
622 exec->pts.n_contours = 0;
Werner Lemberge12ed562007-06-17 05:31:23 +0000623
David Turner815911a2007-06-16 17:07:20 +0000624 exec->zp1 = exec->pts;
625 exec->zp2 = exec->pts;
626 exec->zp0 = exec->pts;
David Turnerd2b1f351999-12-16 23:11:37 +0000627
628 exec->instruction_trap = FALSE;
629
630 return TT_Err_Ok;
631 }
632
633
634 /*************************************************************************/
635 /* */
636 /* <Function> */
637 /* TT_Save_Context */
638 /* */
639 /* <Description> */
640 /* Saves the code ranges in a `size' object. */
641 /* */
642 /* <Input> */
643 /* exec :: A handle to the source execution context. */
644 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000645 /* <InOut> */
646 /* size :: A handle to the target size object. */
David Turnerd2b1f351999-12-16 23:11:37 +0000647 /* */
648 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +0000649 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000650 /* */
651 /* <Note> */
652 /* Only the glyph loader and debugger should call this function. */
653 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +0000654 FT_LOCAL_DEF( FT_Error )
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000655 TT_Save_Context( TT_ExecContext exec,
656 TT_Size size )
David Turnerd2b1f351999-12-16 23:11:37 +0000657 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000658 FT_Int i;
David Turnerd2b1f351999-12-16 23:11:37 +0000659
Werner Lemberg78575dc2000-06-12 19:36:41 +0000660
David Turnerd2b1f351999-12-16 23:11:37 +0000661 /* XXXX: Will probably disappear soon with all the code range */
662 /* management, which is now rather obsolete. */
663 /* */
664 size->num_function_defs = exec->numFDefs;
665 size->num_instruction_defs = exec->numIDefs;
666
667 size->max_func = exec->maxFunc;
668 size->max_ins = exec->maxIns;
669
670 for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
671 size->codeRangeTable[i] = exec->codeRangeTable[i];
672
673 return TT_Err_Ok;
674 }
675
676
677 /*************************************************************************/
678 /* */
679 /* <Function> */
680 /* TT_Run_Context */
681 /* */
682 /* <Description> */
683 /* Executes one or more instructions in the execution context. */
684 /* */
685 /* <Input> */
686 /* debug :: A Boolean flag. If set, the function sets some internal */
687 /* variables and returns immediately, otherwise TT_RunIns() */
688 /* is called. */
689 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000690 /* This is commented out currently. */
691 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000692 /* <Input> */
693 /* exec :: A handle to the target execution context. */
694 /* */
695 /* <Return> */
David Turnerf0df85b2000-06-22 00:17:42 +0000696 /* TrueTyoe error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000697 /* */
698 /* <Note> */
699 /* Only the glyph loader and debugger should call this function. */
700 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +0000701 FT_LOCAL_DEF( FT_Error )
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000702 TT_Run_Context( TT_ExecContext exec,
703 FT_Bool debug )
David Turnerd2b1f351999-12-16 23:11:37 +0000704 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000705 FT_Error error;
David Turnerd2b1f351999-12-16 23:11:37 +0000706
Werner Lemberg78575dc2000-06-12 19:36:41 +0000707
708 if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000709 != TT_Err_Ok )
710 return error;
711
712 exec->zp0 = exec->pts;
713 exec->zp1 = exec->pts;
714 exec->zp2 = exec->pts;
715
716 exec->GS.gep0 = 1;
717 exec->GS.gep1 = 1;
718 exec->GS.gep2 = 1;
719
720 exec->GS.projVector.x = 0x4000;
721 exec->GS.projVector.y = 0x0000;
722
723 exec->GS.freeVector = exec->GS.projVector;
724 exec->GS.dualVector = exec->GS.projVector;
725
David Turner8b6db862003-08-17 22:09:14 +0000726#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Graham Asher3ea859f2003-04-25 11:40:46 +0000727 exec->GS.both_x_axis = TRUE;
728#endif
729
David Turnerd2b1f351999-12-16 23:11:37 +0000730 exec->GS.round_state = 1;
731 exec->GS.loop = 1;
732
733 /* some glyphs leave something on the stack. so we clean it */
734 /* before a new execution. */
735 exec->top = 0;
736 exec->callTop = 0;
737
738#if 1
David Turnerc6a92202000-07-04 18:12:13 +0000739 FT_UNUSED( debug );
Werner Lemberg78575dc2000-06-12 19:36:41 +0000740
David Turnerd2b1f351999-12-16 23:11:37 +0000741 return exec->face->interpreter( exec );
742#else
743 if ( !debug )
744 return TT_RunIns( exec );
745 else
746 return TT_Err_Ok;
747#endif
748 }
749
750
David Turnerd2b1f351999-12-16 23:11:37 +0000751 const TT_GraphicsState tt_default_graphics_state =
752 {
753 0, 0, 0,
754 { 0x4000, 0 },
755 { 0x4000, 0 },
756 { 0x4000, 0 },
Graham Asher3ea859f2003-04-25 11:40:46 +0000757
David Turner8b6db862003-08-17 22:09:14 +0000758#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Werner Lemberga3f4da82003-04-29 13:23:47 +0000759 TRUE,
Graham Asher3ea859f2003-04-25 11:40:46 +0000760#endif
761
David Turnerd2b1f351999-12-16 23:11:37 +0000762 1, 64, 1,
763 TRUE, 68, 0, 0, 9, 3,
764 0, FALSE, 2, 1, 1, 1
765 };
766
767
Werner Lemberg90a03302000-11-07 17:21:11 +0000768 /* documentation is in ttinterp.h */
769
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000770 FT_EXPORT_DEF( TT_ExecContext )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000771 TT_New_Context( TT_Driver driver )
David Turnerd2b1f351999-12-16 23:11:37 +0000772 {
David Turnerd2b1f351999-12-16 23:11:37 +0000773 TT_ExecContext exec;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000774 FT_Memory memory;
David Turnerd2b1f351999-12-16 23:11:37 +0000775
776
David Turnerf0df85b2000-06-22 00:17:42 +0000777 memory = driver->root.root.memory;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000778 exec = driver->context;
David Turnerd2b1f351999-12-16 23:11:37 +0000779
780 if ( !driver->context )
781 {
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000782 FT_Error error;
David Turnerd2b1f351999-12-16 23:11:37 +0000783
784
785 /* allocate object */
David Turnere459d742002-03-22 13:52:37 +0000786 if ( FT_NEW( exec ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000787 goto Exit;
788
789 /* initialize it */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000790 error = Init_Context( exec, memory );
David Turnerd2b1f351999-12-16 23:11:37 +0000791 if ( error )
792 goto Fail;
793
794 /* store it into the driver */
795 driver->context = exec;
796 }
797
798 Exit:
799 return driver->context;
800
801 Fail:
David Turnere459d742002-03-22 13:52:37 +0000802 FT_FREE( exec );
David Turnerd2b1f351999-12-16 23:11:37 +0000803
804 return 0;
805 }
806
807
808 /*************************************************************************/
809 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000810 /* Before an opcode is executed, the interpreter verifies that there are */
Werner Lemberg33febc02004-10-09 07:07:43 +0000811 /* enough arguments on the stack, with the help of the `Pop_Push_Count' */
David Turnerd2b1f351999-12-16 23:11:37 +0000812 /* table. */
813 /* */
814 /* For each opcode, the first column gives the number of arguments that */
815 /* are popped from the stack; the second one gives the number of those */
816 /* that are pushed in result. */
817 /* */
Werner Lemberg33febc02004-10-09 07:07:43 +0000818 /* Opcodes which have a varying number of parameters in the data stream */
819 /* (NPUSHB, NPUSHW) are handled specially; they have a negative value in */
820 /* the `opcode_length' table, and the value in `Pop_Push_Count' is set */
821 /* to zero. */
David Turnerd2b1f351999-12-16 23:11:37 +0000822 /* */
823 /*************************************************************************/
824
825
826#undef PACK
Werner Lemberg78575dc2000-06-12 19:36:41 +0000827#define PACK( x, y ) ( ( x << 4 ) | y )
David Turnerd2b1f351999-12-16 23:11:37 +0000828
829
830 static
David Turnerf9b8dec2000-06-16 19:34:52 +0000831 const FT_Byte Pop_Push_Count[256] =
David Turnerd2b1f351999-12-16 23:11:37 +0000832 {
833 /* opcodes are gathered in groups of 16 */
834 /* please keep the spaces as they are */
835
836 /* SVTCA y */ PACK( 0, 0 ),
837 /* SVTCA x */ PACK( 0, 0 ),
838 /* SPvTCA y */ PACK( 0, 0 ),
839 /* SPvTCA x */ PACK( 0, 0 ),
840 /* SFvTCA y */ PACK( 0, 0 ),
841 /* SFvTCA x */ PACK( 0, 0 ),
842 /* SPvTL // */ PACK( 2, 0 ),
843 /* SPvTL + */ PACK( 2, 0 ),
844 /* SFvTL // */ PACK( 2, 0 ),
845 /* SFvTL + */ PACK( 2, 0 ),
846 /* SPvFS */ PACK( 2, 0 ),
847 /* SFvFS */ PACK( 2, 0 ),
848 /* GPV */ PACK( 0, 2 ),
849 /* GFV */ PACK( 0, 2 ),
850 /* SFvTPv */ PACK( 0, 0 ),
851 /* ISECT */ PACK( 5, 0 ),
852
853 /* SRP0 */ PACK( 1, 0 ),
854 /* SRP1 */ PACK( 1, 0 ),
855 /* SRP2 */ PACK( 1, 0 ),
856 /* SZP0 */ PACK( 1, 0 ),
857 /* SZP1 */ PACK( 1, 0 ),
858 /* SZP2 */ PACK( 1, 0 ),
859 /* SZPS */ PACK( 1, 0 ),
860 /* SLOOP */ PACK( 1, 0 ),
861 /* RTG */ PACK( 0, 0 ),
862 /* RTHG */ PACK( 0, 0 ),
863 /* SMD */ PACK( 1, 0 ),
864 /* ELSE */ PACK( 0, 0 ),
865 /* JMPR */ PACK( 1, 0 ),
866 /* SCvTCi */ PACK( 1, 0 ),
867 /* SSwCi */ PACK( 1, 0 ),
868 /* SSW */ PACK( 1, 0 ),
869
870 /* DUP */ PACK( 1, 2 ),
871 /* POP */ PACK( 1, 0 ),
872 /* CLEAR */ PACK( 0, 0 ),
873 /* SWAP */ PACK( 2, 2 ),
874 /* DEPTH */ PACK( 0, 1 ),
875 /* CINDEX */ PACK( 1, 1 ),
876 /* MINDEX */ PACK( 1, 0 ),
877 /* AlignPTS */ PACK( 2, 0 ),
878 /* INS_$28 */ PACK( 0, 0 ),
879 /* UTP */ PACK( 1, 0 ),
880 /* LOOPCALL */ PACK( 2, 0 ),
881 /* CALL */ PACK( 1, 0 ),
882 /* FDEF */ PACK( 1, 0 ),
883 /* ENDF */ PACK( 0, 0 ),
884 /* MDAP[0] */ PACK( 1, 0 ),
885 /* MDAP[1] */ PACK( 1, 0 ),
886
887 /* IUP[0] */ PACK( 0, 0 ),
888 /* IUP[1] */ PACK( 0, 0 ),
889 /* SHP[0] */ PACK( 0, 0 ),
890 /* SHP[1] */ PACK( 0, 0 ),
891 /* SHC[0] */ PACK( 1, 0 ),
892 /* SHC[1] */ PACK( 1, 0 ),
893 /* SHZ[0] */ PACK( 1, 0 ),
894 /* SHZ[1] */ PACK( 1, 0 ),
895 /* SHPIX */ PACK( 1, 0 ),
896 /* IP */ PACK( 0, 0 ),
897 /* MSIRP[0] */ PACK( 2, 0 ),
898 /* MSIRP[1] */ PACK( 2, 0 ),
899 /* AlignRP */ PACK( 0, 0 ),
900 /* RTDG */ PACK( 0, 0 ),
901 /* MIAP[0] */ PACK( 2, 0 ),
902 /* MIAP[1] */ PACK( 2, 0 ),
903
904 /* NPushB */ PACK( 0, 0 ),
905 /* NPushW */ PACK( 0, 0 ),
906 /* WS */ PACK( 2, 0 ),
907 /* RS */ PACK( 1, 1 ),
908 /* WCvtP */ PACK( 2, 0 ),
909 /* RCvt */ PACK( 1, 1 ),
910 /* GC[0] */ PACK( 1, 1 ),
911 /* GC[1] */ PACK( 1, 1 ),
912 /* SCFS */ PACK( 2, 0 ),
913 /* MD[0] */ PACK( 2, 1 ),
914 /* MD[1] */ PACK( 2, 1 ),
915 /* MPPEM */ PACK( 0, 1 ),
916 /* MPS */ PACK( 0, 1 ),
917 /* FlipON */ PACK( 0, 0 ),
918 /* FlipOFF */ PACK( 0, 0 ),
919 /* DEBUG */ PACK( 1, 0 ),
920
921 /* LT */ PACK( 2, 1 ),
922 /* LTEQ */ PACK( 2, 1 ),
923 /* GT */ PACK( 2, 1 ),
924 /* GTEQ */ PACK( 2, 1 ),
925 /* EQ */ PACK( 2, 1 ),
926 /* NEQ */ PACK( 2, 1 ),
927 /* ODD */ PACK( 1, 1 ),
928 /* EVEN */ PACK( 1, 1 ),
929 /* IF */ PACK( 1, 0 ),
930 /* EIF */ PACK( 0, 0 ),
931 /* AND */ PACK( 2, 1 ),
932 /* OR */ PACK( 2, 1 ),
933 /* NOT */ PACK( 1, 1 ),
934 /* DeltaP1 */ PACK( 1, 0 ),
935 /* SDB */ PACK( 1, 0 ),
936 /* SDS */ PACK( 1, 0 ),
937
938 /* ADD */ PACK( 2, 1 ),
939 /* SUB */ PACK( 2, 1 ),
940 /* DIV */ PACK( 2, 1 ),
941 /* MUL */ PACK( 2, 1 ),
942 /* ABS */ PACK( 1, 1 ),
943 /* NEG */ PACK( 1, 1 ),
944 /* FLOOR */ PACK( 1, 1 ),
945 /* CEILING */ PACK( 1, 1 ),
946 /* ROUND[0] */ PACK( 1, 1 ),
947 /* ROUND[1] */ PACK( 1, 1 ),
948 /* ROUND[2] */ PACK( 1, 1 ),
949 /* ROUND[3] */ PACK( 1, 1 ),
950 /* NROUND[0] */ PACK( 1, 1 ),
951 /* NROUND[1] */ PACK( 1, 1 ),
952 /* NROUND[2] */ PACK( 1, 1 ),
953 /* NROUND[3] */ PACK( 1, 1 ),
954
955 /* WCvtF */ PACK( 2, 0 ),
956 /* DeltaP2 */ PACK( 1, 0 ),
957 /* DeltaP3 */ PACK( 1, 0 ),
958 /* DeltaCn[0] */ PACK( 1, 0 ),
959 /* DeltaCn[1] */ PACK( 1, 0 ),
960 /* DeltaCn[2] */ PACK( 1, 0 ),
961 /* SROUND */ PACK( 1, 0 ),
962 /* S45Round */ PACK( 1, 0 ),
963 /* JROT */ PACK( 2, 0 ),
964 /* JROF */ PACK( 2, 0 ),
965 /* ROFF */ PACK( 0, 0 ),
966 /* INS_$7B */ PACK( 0, 0 ),
967 /* RUTG */ PACK( 0, 0 ),
968 /* RDTG */ PACK( 0, 0 ),
969 /* SANGW */ PACK( 1, 0 ),
970 /* AA */ PACK( 1, 0 ),
971
972 /* FlipPT */ PACK( 0, 0 ),
973 /* FlipRgON */ PACK( 2, 0 ),
974 /* FlipRgOFF */ PACK( 2, 0 ),
975 /* INS_$83 */ PACK( 0, 0 ),
976 /* INS_$84 */ PACK( 0, 0 ),
977 /* ScanCTRL */ PACK( 1, 0 ),
978 /* SDVPTL[0] */ PACK( 2, 0 ),
979 /* SDVPTL[1] */ PACK( 2, 0 ),
980 /* GetINFO */ PACK( 1, 1 ),
981 /* IDEF */ PACK( 1, 0 ),
982 /* ROLL */ PACK( 3, 3 ),
983 /* MAX */ PACK( 2, 1 ),
984 /* MIN */ PACK( 2, 1 ),
985 /* ScanTYPE */ PACK( 1, 0 ),
986 /* InstCTRL */ PACK( 2, 0 ),
987 /* INS_$8F */ PACK( 0, 0 ),
988
989 /* INS_$90 */ PACK( 0, 0 ),
990 /* INS_$91 */ PACK( 0, 0 ),
991 /* INS_$92 */ PACK( 0, 0 ),
992 /* INS_$93 */ PACK( 0, 0 ),
993 /* INS_$94 */ PACK( 0, 0 ),
994 /* INS_$95 */ PACK( 0, 0 ),
995 /* INS_$96 */ PACK( 0, 0 ),
996 /* INS_$97 */ PACK( 0, 0 ),
997 /* INS_$98 */ PACK( 0, 0 ),
998 /* INS_$99 */ PACK( 0, 0 ),
999 /* INS_$9A */ PACK( 0, 0 ),
1000 /* INS_$9B */ PACK( 0, 0 ),
1001 /* INS_$9C */ PACK( 0, 0 ),
1002 /* INS_$9D */ PACK( 0, 0 ),
1003 /* INS_$9E */ PACK( 0, 0 ),
1004 /* INS_$9F */ PACK( 0, 0 ),
1005
1006 /* INS_$A0 */ PACK( 0, 0 ),
1007 /* INS_$A1 */ PACK( 0, 0 ),
1008 /* INS_$A2 */ PACK( 0, 0 ),
1009 /* INS_$A3 */ PACK( 0, 0 ),
1010 /* INS_$A4 */ PACK( 0, 0 ),
1011 /* INS_$A5 */ PACK( 0, 0 ),
1012 /* INS_$A6 */ PACK( 0, 0 ),
1013 /* INS_$A7 */ PACK( 0, 0 ),
1014 /* INS_$A8 */ PACK( 0, 0 ),
1015 /* INS_$A9 */ PACK( 0, 0 ),
1016 /* INS_$AA */ PACK( 0, 0 ),
1017 /* INS_$AB */ PACK( 0, 0 ),
1018 /* INS_$AC */ PACK( 0, 0 ),
1019 /* INS_$AD */ PACK( 0, 0 ),
1020 /* INS_$AE */ PACK( 0, 0 ),
1021 /* INS_$AF */ PACK( 0, 0 ),
1022
1023 /* PushB[0] */ PACK( 0, 1 ),
1024 /* PushB[1] */ PACK( 0, 2 ),
1025 /* PushB[2] */ PACK( 0, 3 ),
1026 /* PushB[3] */ PACK( 0, 4 ),
1027 /* PushB[4] */ PACK( 0, 5 ),
1028 /* PushB[5] */ PACK( 0, 6 ),
1029 /* PushB[6] */ PACK( 0, 7 ),
1030 /* PushB[7] */ PACK( 0, 8 ),
1031 /* PushW[0] */ PACK( 0, 1 ),
1032 /* PushW[1] */ PACK( 0, 2 ),
1033 /* PushW[2] */ PACK( 0, 3 ),
1034 /* PushW[3] */ PACK( 0, 4 ),
1035 /* PushW[4] */ PACK( 0, 5 ),
1036 /* PushW[5] */ PACK( 0, 6 ),
1037 /* PushW[6] */ PACK( 0, 7 ),
1038 /* PushW[7] */ PACK( 0, 8 ),
1039
1040 /* MDRP[00] */ PACK( 1, 0 ),
1041 /* MDRP[01] */ PACK( 1, 0 ),
1042 /* MDRP[02] */ PACK( 1, 0 ),
1043 /* MDRP[03] */ PACK( 1, 0 ),
1044 /* MDRP[04] */ PACK( 1, 0 ),
1045 /* MDRP[05] */ PACK( 1, 0 ),
1046 /* MDRP[06] */ PACK( 1, 0 ),
1047 /* MDRP[07] */ PACK( 1, 0 ),
1048 /* MDRP[08] */ PACK( 1, 0 ),
1049 /* MDRP[09] */ PACK( 1, 0 ),
1050 /* MDRP[10] */ PACK( 1, 0 ),
1051 /* MDRP[11] */ PACK( 1, 0 ),
1052 /* MDRP[12] */ PACK( 1, 0 ),
1053 /* MDRP[13] */ PACK( 1, 0 ),
1054 /* MDRP[14] */ PACK( 1, 0 ),
1055 /* MDRP[15] */ PACK( 1, 0 ),
1056
1057 /* MDRP[16] */ PACK( 1, 0 ),
1058 /* MDRP[17] */ PACK( 1, 0 ),
1059 /* MDRP[18] */ PACK( 1, 0 ),
1060 /* MDRP[19] */ PACK( 1, 0 ),
1061 /* MDRP[20] */ PACK( 1, 0 ),
1062 /* MDRP[21] */ PACK( 1, 0 ),
1063 /* MDRP[22] */ PACK( 1, 0 ),
1064 /* MDRP[23] */ PACK( 1, 0 ),
1065 /* MDRP[24] */ PACK( 1, 0 ),
1066 /* MDRP[25] */ PACK( 1, 0 ),
1067 /* MDRP[26] */ PACK( 1, 0 ),
1068 /* MDRP[27] */ PACK( 1, 0 ),
1069 /* MDRP[28] */ PACK( 1, 0 ),
1070 /* MDRP[29] */ PACK( 1, 0 ),
1071 /* MDRP[30] */ PACK( 1, 0 ),
1072 /* MDRP[31] */ PACK( 1, 0 ),
1073
1074 /* MIRP[00] */ PACK( 2, 0 ),
1075 /* MIRP[01] */ PACK( 2, 0 ),
1076 /* MIRP[02] */ PACK( 2, 0 ),
1077 /* MIRP[03] */ PACK( 2, 0 ),
1078 /* MIRP[04] */ PACK( 2, 0 ),
1079 /* MIRP[05] */ PACK( 2, 0 ),
1080 /* MIRP[06] */ PACK( 2, 0 ),
1081 /* MIRP[07] */ PACK( 2, 0 ),
1082 /* MIRP[08] */ PACK( 2, 0 ),
1083 /* MIRP[09] */ PACK( 2, 0 ),
1084 /* MIRP[10] */ PACK( 2, 0 ),
1085 /* MIRP[11] */ PACK( 2, 0 ),
1086 /* MIRP[12] */ PACK( 2, 0 ),
1087 /* MIRP[13] */ PACK( 2, 0 ),
1088 /* MIRP[14] */ PACK( 2, 0 ),
1089 /* MIRP[15] */ PACK( 2, 0 ),
1090
1091 /* MIRP[16] */ PACK( 2, 0 ),
1092 /* MIRP[17] */ PACK( 2, 0 ),
1093 /* MIRP[18] */ PACK( 2, 0 ),
1094 /* MIRP[19] */ PACK( 2, 0 ),
1095 /* MIRP[20] */ PACK( 2, 0 ),
1096 /* MIRP[21] */ PACK( 2, 0 ),
1097 /* MIRP[22] */ PACK( 2, 0 ),
1098 /* MIRP[23] */ PACK( 2, 0 ),
1099 /* MIRP[24] */ PACK( 2, 0 ),
1100 /* MIRP[25] */ PACK( 2, 0 ),
1101 /* MIRP[26] */ PACK( 2, 0 ),
1102 /* MIRP[27] */ PACK( 2, 0 ),
1103 /* MIRP[28] */ PACK( 2, 0 ),
1104 /* MIRP[29] */ PACK( 2, 0 ),
1105 /* MIRP[30] */ PACK( 2, 0 ),
1106 /* MIRP[31] */ PACK( 2, 0 )
1107 };
1108
1109
1110 static
David Turnerf9b8dec2000-06-16 19:34:52 +00001111 const FT_Char opcode_length[256] =
David Turnerd2b1f351999-12-16 23:11:37 +00001112 {
1113 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1114 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1115 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1116 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1117
Werner Lemberg33febc02004-10-09 07:07:43 +00001118 -1,-2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
David Turnerd2b1f351999-12-16 23:11:37 +00001119 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1120 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1121 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1122
1123 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1124 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1125 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1126 2, 3, 4, 5, 6, 7, 8, 9, 3, 5, 7, 9, 11,13,15,17,
1127
1128 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1129 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1130 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1131 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
1132 };
1133
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001134#undef PACK
David Turnerd2b1f351999-12-16 23:11:37 +00001135
David Turner2c4500e2007-02-14 15:08:47 +00001136#if 1
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00001137
David Turner2c4500e2007-02-14 15:08:47 +00001138 static FT_Int32
1139 TT_MulFix14( FT_Int32 a,
1140 FT_Int b )
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00001141 {
1142 FT_Int32 sign;
1143 FT_UInt32 ah, al, mid, lo, hi;
David Turner2c4500e2007-02-14 15:08:47 +00001144
David Turner2c4500e2007-02-14 15:08:47 +00001145
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00001146 sign = a ^ b;
David Turner2c4500e2007-02-14 15:08:47 +00001147
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00001148 if ( a < 0 )
1149 a = -a;
1150 if ( b < 0 )
1151 b = -b;
David Turner2c4500e2007-02-14 15:08:47 +00001152
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00001153 ah = (FT_UInt32)( ( a >> 16 ) & 0xFFFFU );
1154 al = (FT_UInt32)( a & 0xFFFFU );
David Turner2c4500e2007-02-14 15:08:47 +00001155
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00001156 lo = al * b;
1157 mid = ah * b;
1158 hi = mid >> 16;
1159 mid = ( mid << 16 ) + ( 1 << 13 ); /* rounding */
1160 lo += mid;
1161 if ( lo < mid )
1162 hi += 1;
David Turner2c4500e2007-02-14 15:08:47 +00001163
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00001164 mid = ( lo >> 14 ) | ( hi << 18 );
1165
1166 return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid;
1167 }
1168
David Turner2c4500e2007-02-14 15:08:47 +00001169#else
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00001170
Werner Lemberg91db04c2002-04-01 14:25:28 +00001171 /* compute (a*b)/2^14 with maximal accuracy and rounding */
David Turner4b29d582002-03-25 17:02:26 +00001172 static FT_Int32
Werner Lemberg91db04c2002-04-01 14:25:28 +00001173 TT_MulFix14( FT_Int32 a,
1174 FT_Int b )
David Turner4b29d582002-03-25 17:02:26 +00001175 {
1176 FT_Int32 m, s, hi;
1177 FT_UInt32 l, lo;
David Turnerb08fe2d2002-08-27 20:20:29 +00001178
Werner Lemberg91db04c2002-04-01 14:25:28 +00001179
David Turner4b29d582002-03-25 17:02:26 +00001180 /* compute ax*bx as 64-bit value */
Werner Lemberg91db04c2002-04-01 14:25:28 +00001181 l = (FT_UInt32)( ( a & 0xFFFFU ) * b );
1182 m = ( a >> 16 ) * b;
David Turnerb08fe2d2002-08-27 20:20:29 +00001183
Werner Lemberg91db04c2002-04-01 14:25:28 +00001184 lo = l + (FT_UInt32)( m << 16 );
1185 hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l );
David Turnerb08fe2d2002-08-27 20:20:29 +00001186
David Turner4b29d582002-03-25 17:02:26 +00001187 /* divide the result by 2^14 with rounding */
Werner Lemberg91db04c2002-04-01 14:25:28 +00001188 s = hi >> 31;
David Turner4b29d582002-03-25 17:02:26 +00001189 l = lo + (FT_UInt32)s;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001190 hi += s + ( l < lo );
David Turner4b29d582002-03-25 17:02:26 +00001191 lo = l;
1192
1193 l = lo + 0x2000U;
Werner Lembergc9f6c662007-03-21 13:30:14 +00001194 hi += l < lo;
David Turnerb08fe2d2002-08-27 20:20:29 +00001195
Werner Lemberg91db04c2002-04-01 14:25:28 +00001196 return ( hi << 18 ) | ( l >> 14 );
David Turner4b29d582002-03-25 17:02:26 +00001197 }
David Turner2c4500e2007-02-14 15:08:47 +00001198#endif
David Turner4b29d582002-03-25 17:02:26 +00001199
1200
Werner Lemberg91db04c2002-04-01 14:25:28 +00001201 /* compute (ax*bx+ay*by)/2^14 with maximal accuracy and rounding */
David Turner4b29d582002-03-25 17:02:26 +00001202 static FT_Int32
Werner Lemberg91db04c2002-04-01 14:25:28 +00001203 TT_DotFix14( FT_Int32 ax,
1204 FT_Int32 ay,
1205 FT_Int bx,
1206 FT_Int by )
David Turner4b29d582002-03-25 17:02:26 +00001207 {
1208 FT_Int32 m, s, hi1, hi2, hi;
1209 FT_UInt32 l, lo1, lo2, lo;
David Turnerb08fe2d2002-08-27 20:20:29 +00001210
Werner Lemberg91db04c2002-04-01 14:25:28 +00001211
David Turner4b29d582002-03-25 17:02:26 +00001212 /* compute ax*bx as 64-bit value */
Werner Lemberg91db04c2002-04-01 14:25:28 +00001213 l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx );
1214 m = ( ax >> 16 ) * bx;
David Turnerb08fe2d2002-08-27 20:20:29 +00001215
Werner Lemberg91db04c2002-04-01 14:25:28 +00001216 lo1 = l + (FT_UInt32)( m << 16 );
1217 hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l );
David Turnerb08fe2d2002-08-27 20:20:29 +00001218
David Turner4b29d582002-03-25 17:02:26 +00001219 /* compute ay*by as 64-bit value */
Werner Lemberg91db04c2002-04-01 14:25:28 +00001220 l = (FT_UInt32)( ( ay & 0xFFFFU ) * by );
1221 m = ( ay >> 16 ) * by;
David Turnerb08fe2d2002-08-27 20:20:29 +00001222
Werner Lemberg91db04c2002-04-01 14:25:28 +00001223 lo2 = l + (FT_UInt32)( m << 16 );
1224 hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l );
David Turnerb08fe2d2002-08-27 20:20:29 +00001225
David Turner4b29d582002-03-25 17:02:26 +00001226 /* add them */
1227 lo = lo1 + lo2;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001228 hi = hi1 + hi2 + ( lo < lo1 );
David Turnerb08fe2d2002-08-27 20:20:29 +00001229
David Turner4b29d582002-03-25 17:02:26 +00001230 /* divide the result by 2^14 with rounding */
Werner Lemberg91db04c2002-04-01 14:25:28 +00001231 s = hi >> 31;
David Turner4b29d582002-03-25 17:02:26 +00001232 l = lo + (FT_UInt32)s;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001233 hi += s + ( l < lo );
David Turner4b29d582002-03-25 17:02:26 +00001234 lo = l;
1235
1236 l = lo + 0x2000U;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001237 hi += ( l < lo );
David Turnerb08fe2d2002-08-27 20:20:29 +00001238
Werner Lemberg91db04c2002-04-01 14:25:28 +00001239 return ( hi << 18 ) | ( l >> 14 );
David Turner4b29d582002-03-25 17:02:26 +00001240 }
1241
Werner Lemberg91db04c2002-04-01 14:25:28 +00001242
1243 /* return length of given vector */
1244
David Turner4b29d582002-03-25 17:02:26 +00001245#if 0
1246
1247 static FT_Int32
Werner Lemberg91db04c2002-04-01 14:25:28 +00001248 TT_VecLen( FT_Int32 x,
1249 FT_Int32 y )
David Turner4b29d582002-03-25 17:02:26 +00001250 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001251 FT_Int32 m, hi1, hi2, hi;
1252 FT_UInt32 l, lo1, lo2, lo;
1253
David Turnerb08fe2d2002-08-27 20:20:29 +00001254
David Turner4b29d582002-03-25 17:02:26 +00001255 /* compute x*x as 64-bit value */
Werner Lemberg91db04c2002-04-01 14:25:28 +00001256 lo = (FT_UInt32)( x & 0xFFFFU );
1257 hi = x >> 16;
David Turnerb08fe2d2002-08-27 20:20:29 +00001258
Werner Lemberg91db04c2002-04-01 14:25:28 +00001259 l = lo * lo;
1260 m = hi * lo;
1261 hi = hi * hi;
David Turnerb08fe2d2002-08-27 20:20:29 +00001262
Werner Lemberg91db04c2002-04-01 14:25:28 +00001263 lo1 = l + (FT_UInt32)( m << 17 );
1264 hi1 = hi + ( m >> 15 ) + ( lo1 < l );
David Turnerb08fe2d2002-08-27 20:20:29 +00001265
David Turner4b29d582002-03-25 17:02:26 +00001266 /* compute y*y as 64-bit value */
Werner Lemberg91db04c2002-04-01 14:25:28 +00001267 lo = (FT_UInt32)( y & 0xFFFFU );
1268 hi = y >> 16;
David Turnerb08fe2d2002-08-27 20:20:29 +00001269
Werner Lemberg91db04c2002-04-01 14:25:28 +00001270 l = lo * lo;
1271 m = hi * lo;
1272 hi = hi * hi;
David Turnerb08fe2d2002-08-27 20:20:29 +00001273
Werner Lemberg91db04c2002-04-01 14:25:28 +00001274 lo2 = l + (FT_UInt32)( m << 17 );
1275 hi2 = hi + ( m >> 15 ) + ( lo2 < l );
David Turnerb08fe2d2002-08-27 20:20:29 +00001276
David Turner4b29d582002-03-25 17:02:26 +00001277 /* add them to get 'x*x+y*y' as 64-bit value */
1278 lo = lo1 + lo2;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001279 hi = hi1 + hi2 + ( lo < lo1 );
David Turnerb08fe2d2002-08-27 20:20:29 +00001280
David Turner4b29d582002-03-25 17:02:26 +00001281 /* compute the square root of this value */
1282 {
1283 FT_UInt32 root, rem, test_div;
1284 FT_Int count;
1285
1286
1287 root = 0;
1288
1289 {
1290 rem = 0;
1291 count = 32;
1292 do
1293 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001294 rem = ( rem << 2 ) | ( (FT_UInt32)hi >> 30 );
1295 hi = ( hi << 2 ) | ( lo >> 30 );
David Turner4b29d582002-03-25 17:02:26 +00001296 lo <<= 2;
1297 root <<= 1;
1298 test_div = ( root << 1 ) + 1;
1299
1300 if ( rem >= test_div )
1301 {
1302 rem -= test_div;
1303 root += 1;
1304 }
1305 } while ( --count );
1306 }
David Turnerb08fe2d2002-08-27 20:20:29 +00001307
David Turner4b29d582002-03-25 17:02:26 +00001308 return (FT_Int32)root;
1309 }
1310 }
Werner Lemberg91db04c2002-04-01 14:25:28 +00001311
David Turner4b29d582002-03-25 17:02:26 +00001312#else
David Turnerb08fe2d2002-08-27 20:20:29 +00001313
Werner Lemberg91db04c2002-04-01 14:25:28 +00001314 /* this version uses FT_Vector_Length which computes the same value */
1315 /* much, much faster.. */
1316 /* */
David Turner4b29d582002-03-25 17:02:26 +00001317 static FT_F26Dot6
1318 TT_VecLen( FT_F26Dot6 X,
1319 FT_F26Dot6 Y )
1320 {
1321 FT_Vector v;
1322
Werner Lemberg91db04c2002-04-01 14:25:28 +00001323
David Turner4b29d582002-03-25 17:02:26 +00001324 v.x = X;
1325 v.y = Y;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001326
David Turner4b29d582002-03-25 17:02:26 +00001327 return FT_Vector_Length( &v );
1328 }
David Turnerb08fe2d2002-08-27 20:20:29 +00001329
David Turner4b29d582002-03-25 17:02:26 +00001330#endif
1331
Werner Lemberg91db04c2002-04-01 14:25:28 +00001332
David Turnerd2b1f351999-12-16 23:11:37 +00001333 /*************************************************************************/
1334 /* */
1335 /* <Function> */
1336 /* Current_Ratio */
1337 /* */
1338 /* <Description> */
1339 /* Returns the current aspect ratio scaling factor depending on the */
1340 /* projection vector's state and device resolutions. */
1341 /* */
1342 /* <Return> */
1343 /* The aspect ratio in 16.16 format, always <= 1.0 . */
1344 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001345 static FT_Long
1346 Current_Ratio( EXEC_OP )
David Turnerd2b1f351999-12-16 23:11:37 +00001347 {
Graham Asher3ea859f2003-04-25 11:40:46 +00001348 if ( !CUR.tt_metrics.ratio )
David Turnerd2b1f351999-12-16 23:11:37 +00001349 {
David Turner8b6db862003-08-17 22:09:14 +00001350#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Graham Asher3ea859f2003-04-25 11:40:46 +00001351 if ( CUR.face->unpatented_hinting )
1352 {
1353 if ( CUR.GS.both_x_axis )
1354 CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
1355 else
1356 CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
1357 }
1358 else
1359#endif
Werner Lemberga3f4da82003-04-29 13:23:47 +00001360 {
Graham Asher3ea859f2003-04-25 11:40:46 +00001361 if ( CUR.GS.projVector.y == 0 )
1362 CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001363
Graham Asher3ea859f2003-04-25 11:40:46 +00001364 else if ( CUR.GS.projVector.x == 0 )
1365 CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
David Turnerd2b1f351999-12-16 23:11:37 +00001366
Graham Asher3ea859f2003-04-25 11:40:46 +00001367 else
1368 {
1369 FT_Long x, y;
1370
Werner Lemberga3f4da82003-04-29 13:23:47 +00001371
1372 x = TT_MULDIV( CUR.GS.projVector.x,
1373 CUR.tt_metrics.x_ratio, 0x4000 );
1374 y = TT_MULDIV( CUR.GS.projVector.y,
1375 CUR.tt_metrics.y_ratio, 0x4000 );
Graham Asher3ea859f2003-04-25 11:40:46 +00001376 CUR.tt_metrics.ratio = TT_VecLen( x, y );
1377 }
Werner Lemberga3f4da82003-04-29 13:23:47 +00001378 }
1379 }
David Turnerd2b1f351999-12-16 23:11:37 +00001380 return CUR.tt_metrics.ratio;
1381 }
1382
1383
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001384 static FT_Long
1385 Current_Ppem( EXEC_OP )
David Turnerd2b1f351999-12-16 23:11:37 +00001386 {
1387 return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() );
1388 }
1389
1390
1391 /*************************************************************************/
1392 /* */
1393 /* Functions related to the control value table (CVT). */
1394 /* */
1395 /*************************************************************************/
1396
1397
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001398 FT_CALLBACK_DEF( FT_F26Dot6 )
Werner Lemberg91db04c2002-04-01 14:25:28 +00001399 Read_CVT( EXEC_OP_ FT_ULong idx )
David Turnerd2b1f351999-12-16 23:11:37 +00001400 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001401 return CUR.cvt[idx];
David Turnerd2b1f351999-12-16 23:11:37 +00001402 }
1403
1404
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001405 FT_CALLBACK_DEF( FT_F26Dot6 )
Werner Lemberg91db04c2002-04-01 14:25:28 +00001406 Read_CVT_Stretched( EXEC_OP_ FT_ULong idx )
David Turnerd2b1f351999-12-16 23:11:37 +00001407 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001408 return TT_MULFIX( CUR.cvt[idx], CURRENT_Ratio() );
David Turnerd2b1f351999-12-16 23:11:37 +00001409 }
1410
1411
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001412 FT_CALLBACK_DEF( void )
Werner Lemberg91db04c2002-04-01 14:25:28 +00001413 Write_CVT( EXEC_OP_ FT_ULong idx,
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001414 FT_F26Dot6 value )
David Turnerd2b1f351999-12-16 23:11:37 +00001415 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001416 CUR.cvt[idx] = value;
David Turnerd2b1f351999-12-16 23:11:37 +00001417 }
1418
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001419
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001420 FT_CALLBACK_DEF( void )
Werner Lemberg91db04c2002-04-01 14:25:28 +00001421 Write_CVT_Stretched( EXEC_OP_ FT_ULong idx,
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001422 FT_F26Dot6 value )
David Turnerd2b1f351999-12-16 23:11:37 +00001423 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001424 CUR.cvt[idx] = FT_DivFix( value, CURRENT_Ratio() );
David Turnerd2b1f351999-12-16 23:11:37 +00001425 }
1426
1427
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001428 FT_CALLBACK_DEF( void )
Werner Lemberg91db04c2002-04-01 14:25:28 +00001429 Move_CVT( EXEC_OP_ FT_ULong idx,
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001430 FT_F26Dot6 value )
David Turnerd2b1f351999-12-16 23:11:37 +00001431 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001432 CUR.cvt[idx] += value;
David Turnerd2b1f351999-12-16 23:11:37 +00001433 }
1434
1435
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001436 FT_CALLBACK_DEF( void )
Werner Lemberg91db04c2002-04-01 14:25:28 +00001437 Move_CVT_Stretched( EXEC_OP_ FT_ULong idx,
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001438 FT_F26Dot6 value )
David Turnerd2b1f351999-12-16 23:11:37 +00001439 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001440 CUR.cvt[idx] += FT_DivFix( value, CURRENT_Ratio() );
David Turnerd2b1f351999-12-16 23:11:37 +00001441 }
1442
1443
1444 /*************************************************************************/
1445 /* */
1446 /* <Function> */
1447 /* GetShortIns */
1448 /* */
1449 /* <Description> */
1450 /* Returns a short integer taken from the instruction stream at */
1451 /* address IP. */
1452 /* */
1453 /* <Return> */
1454 /* Short read at code[IP]. */
1455 /* */
1456 /* <Note> */
1457 /* This one could become a macro. */
1458 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001459 static FT_Short
1460 GetShortIns( EXEC_OP )
David Turnerd2b1f351999-12-16 23:11:37 +00001461 {
1462 /* Reading a byte stream so there is no endianess (DaveP) */
1463 CUR.IP += 2;
David Turnerf9b8dec2000-06-16 19:34:52 +00001464 return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) +
Werner Lemberg78575dc2000-06-12 19:36:41 +00001465 CUR.code[CUR.IP - 1] );
David Turnerd2b1f351999-12-16 23:11:37 +00001466 }
1467
1468
1469 /*************************************************************************/
1470 /* */
1471 /* <Function> */
1472 /* Ins_Goto_CodeRange */
1473 /* */
1474 /* <Description> */
1475 /* Goes to a certain code range in the instruction stream. */
1476 /* */
1477 /* <Input> */
1478 /* aRange :: The index of the code range. */
1479 /* */
1480 /* aIP :: The new IP address in the code range. */
1481 /* */
1482 /* <Return> */
1483 /* SUCCESS or FAILURE. */
1484 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001485 static FT_Bool
1486 Ins_Goto_CodeRange( EXEC_OP_ FT_Int aRange,
1487 FT_ULong aIP )
David Turnerd2b1f351999-12-16 23:11:37 +00001488 {
1489 TT_CodeRange* range;
1490
1491
1492 if ( aRange < 1 || aRange > 3 )
1493 {
1494 CUR.error = TT_Err_Bad_Argument;
1495 return FAILURE;
1496 }
1497
1498 range = &CUR.codeRangeTable[aRange - 1];
1499
1500 if ( range->base == NULL ) /* invalid coderange */
1501 {
1502 CUR.error = TT_Err_Invalid_CodeRange;
1503 return FAILURE;
1504 }
1505
1506 /* NOTE: Because the last instruction of a program may be a CALL */
1507 /* which will return to the first byte *after* the code */
1508 /* range, we test for AIP <= Size, instead of AIP < Size. */
1509
1510 if ( aIP > range->size )
1511 {
1512 CUR.error = TT_Err_Code_Overflow;
1513 return FAILURE;
1514 }
1515
1516 CUR.code = range->base;
1517 CUR.codeSize = range->size;
1518 CUR.IP = aIP;
1519 CUR.curRange = aRange;
1520
1521 return SUCCESS;
1522 }
1523
1524
1525 /*************************************************************************/
1526 /* */
1527 /* <Function> */
1528 /* Direct_Move */
1529 /* */
1530 /* <Description> */
1531 /* Moves a point by a given distance along the freedom vector. The */
1532 /* point will be `touched'. */
1533 /* */
1534 /* <Input> */
1535 /* point :: The index of the point to move. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001536 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001537 /* distance :: The distance to apply. */
1538 /* */
1539 /* <InOut> */
1540 /* zone :: The affected glyph zone. */
1541 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001542 static void
Werner Lemberg91db04c2002-04-01 14:25:28 +00001543 Direct_Move( EXEC_OP_ TT_GlyphZone zone,
1544 FT_UShort point,
1545 FT_F26Dot6 distance )
David Turnerd2b1f351999-12-16 23:11:37 +00001546 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001547 FT_F26Dot6 v;
David Turnerd2b1f351999-12-16 23:11:37 +00001548
Werner Lemberga3f4da82003-04-29 13:23:47 +00001549
David Turner8b6db862003-08-17 22:09:14 +00001550#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Werner Lemberga3f4da82003-04-29 13:23:47 +00001551 FT_ASSERT( !CUR.face->unpatented_hinting );
Graham Asher3ea859f2003-04-25 11:40:46 +00001552#endif
David Turnerd2b1f351999-12-16 23:11:37 +00001553
1554 v = CUR.GS.freeVector.x;
1555
1556 if ( v != 0 )
1557 {
1558 zone->cur[point].x += TT_MULDIV( distance,
1559 v * 0x10000L,
1560 CUR.F_dot_P );
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001561
David Turnerb08fe2d2002-08-27 20:20:29 +00001562 zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
David Turnerd2b1f351999-12-16 23:11:37 +00001563 }
1564
1565 v = CUR.GS.freeVector.y;
1566
1567 if ( v != 0 )
1568 {
1569 zone->cur[point].y += TT_MULDIV( distance,
1570 v * 0x10000L,
1571 CUR.F_dot_P );
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001572
David Turnerb08fe2d2002-08-27 20:20:29 +00001573 zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
David Turnerd2b1f351999-12-16 23:11:37 +00001574 }
1575 }
1576
1577
1578 /*************************************************************************/
1579 /* */
Werner Lembergbe67c4e2003-11-24 22:54:58 +00001580 /* <Function> */
1581 /* Direct_Move_Orig */
1582 /* */
1583 /* <Description> */
Werner Lembergd90b6732003-11-28 22:47:26 +00001584 /* Moves the *original* position of a point by a given distance along */
1585 /* the freedom vector. Obviously, the point will not be `touched'. */
Werner Lembergbe67c4e2003-11-24 22:54:58 +00001586 /* */
1587 /* <Input> */
1588 /* point :: The index of the point to move. */
1589 /* */
1590 /* distance :: The distance to apply. */
1591 /* */
1592 /* <InOut> */
1593 /* zone :: The affected glyph zone. */
1594 /* */
1595 static void
1596 Direct_Move_Orig( EXEC_OP_ TT_GlyphZone zone,
1597 FT_UShort point,
1598 FT_F26Dot6 distance )
1599 {
1600 FT_F26Dot6 v;
1601
1602
1603#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
1604 FT_ASSERT( !CUR.face->unpatented_hinting );
1605#endif
1606
1607 v = CUR.GS.freeVector.x;
1608
1609 if ( v != 0 )
1610 zone->org[point].x += TT_MULDIV( distance,
1611 v * 0x10000L,
1612 CUR.F_dot_P );
1613
1614 v = CUR.GS.freeVector.y;
1615
1616 if ( v != 0 )
1617 zone->org[point].y += TT_MULDIV( distance,
1618 v * 0x10000L,
1619 CUR.F_dot_P );
1620 }
1621
1622
1623 /*************************************************************************/
1624 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001625 /* Special versions of Direct_Move() */
1626 /* */
1627 /* The following versions are used whenever both vectors are both */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001628 /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */
David Turnerd2b1f351999-12-16 23:11:37 +00001629 /* */
1630 /*************************************************************************/
1631
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001632
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001633 static void
Werner Lemberg91db04c2002-04-01 14:25:28 +00001634 Direct_Move_X( EXEC_OP_ TT_GlyphZone zone,
1635 FT_UShort point,
1636 FT_F26Dot6 distance )
David Turnerd2b1f351999-12-16 23:11:37 +00001637 {
David Turnerc6a92202000-07-04 18:12:13 +00001638 FT_UNUSED_EXEC;
David Turnerd2b1f351999-12-16 23:11:37 +00001639
1640 zone->cur[point].x += distance;
David Turnerb08fe2d2002-08-27 20:20:29 +00001641 zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
David Turnerd2b1f351999-12-16 23:11:37 +00001642 }
1643
1644
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001645 static void
Werner Lemberg91db04c2002-04-01 14:25:28 +00001646 Direct_Move_Y( EXEC_OP_ TT_GlyphZone zone,
1647 FT_UShort point,
1648 FT_F26Dot6 distance )
David Turnerd2b1f351999-12-16 23:11:37 +00001649 {
David Turnerc6a92202000-07-04 18:12:13 +00001650 FT_UNUSED_EXEC;
David Turnerd2b1f351999-12-16 23:11:37 +00001651
1652 zone->cur[point].y += distance;
David Turnerb08fe2d2002-08-27 20:20:29 +00001653 zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
David Turnerd2b1f351999-12-16 23:11:37 +00001654 }
1655
1656
1657 /*************************************************************************/
1658 /* */
Werner Lembergbe67c4e2003-11-24 22:54:58 +00001659 /* Special versions of Direct_Move_Orig() */
1660 /* */
1661 /* The following versions are used whenever both vectors are both */
1662 /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */
1663 /* */
1664 /*************************************************************************/
1665
1666
1667 static void
1668 Direct_Move_Orig_X( EXEC_OP_ TT_GlyphZone zone,
1669 FT_UShort point,
1670 FT_F26Dot6 distance )
1671 {
1672 FT_UNUSED_EXEC;
1673
1674 zone->org[point].x += distance;
1675 }
1676
1677
1678 static void
1679 Direct_Move_Orig_Y( EXEC_OP_ TT_GlyphZone zone,
1680 FT_UShort point,
1681 FT_F26Dot6 distance )
1682 {
1683 FT_UNUSED_EXEC;
1684
1685 zone->org[point].y += distance;
1686 }
1687
1688
1689 /*************************************************************************/
1690 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001691 /* <Function> */
1692 /* Round_None */
1693 /* */
1694 /* <Description> */
1695 /* Does not round, but adds engine compensation. */
1696 /* */
1697 /* <Input> */
1698 /* distance :: The distance (not) to round. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001699 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001700 /* compensation :: The engine compensation. */
1701 /* */
1702 /* <Return> */
1703 /* The compensated distance. */
1704 /* */
1705 /* <Note> */
1706 /* The TrueType specification says very few about the relationship */
1707 /* between rounding and engine compensation. However, it seems from */
1708 /* the description of super round that we should add the compensation */
1709 /* before rounding. */
1710 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001711 static FT_F26Dot6
1712 Round_None( EXEC_OP_ FT_F26Dot6 distance,
1713 FT_F26Dot6 compensation )
David Turnerd2b1f351999-12-16 23:11:37 +00001714 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001715 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00001716
David Turnerc6a92202000-07-04 18:12:13 +00001717 FT_UNUSED_EXEC;
David Turnerd2b1f351999-12-16 23:11:37 +00001718
Werner Lemberg78575dc2000-06-12 19:36:41 +00001719
David Turnerd2b1f351999-12-16 23:11:37 +00001720 if ( distance >= 0 )
1721 {
1722 val = distance + compensation;
Werner Lembergbe67c4e2003-11-24 22:54:58 +00001723 if ( distance && val < 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001724 val = 0;
1725 }
1726 else {
1727 val = distance - compensation;
1728 if ( val > 0 )
1729 val = 0;
1730 }
1731 return val;
1732 }
1733
1734
1735 /*************************************************************************/
1736 /* */
1737 /* <Function> */
1738 /* Round_To_Grid */
1739 /* */
1740 /* <Description> */
1741 /* Rounds value to grid after adding engine compensation. */
1742 /* */
1743 /* <Input> */
1744 /* distance :: The distance to round. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001745 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001746 /* compensation :: The engine compensation. */
1747 /* */
1748 /* <Return> */
1749 /* Rounded distance. */
1750 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001751 static FT_F26Dot6
1752 Round_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
1753 FT_F26Dot6 compensation )
David Turnerd2b1f351999-12-16 23:11:37 +00001754 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001755 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00001756
David Turnerc6a92202000-07-04 18:12:13 +00001757 FT_UNUSED_EXEC;
David Turnerd2b1f351999-12-16 23:11:37 +00001758
Werner Lemberg78575dc2000-06-12 19:36:41 +00001759
David Turnerd2b1f351999-12-16 23:11:37 +00001760 if ( distance >= 0 )
1761 {
1762 val = distance + compensation + 32;
Werner Lembergbe67c4e2003-11-24 22:54:58 +00001763 if ( distance && val > 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001764 val &= ~63;
1765 else
1766 val = 0;
1767 }
1768 else
1769 {
David Turner87c0d302003-12-24 01:10:46 +00001770 val = -FT_PIX_ROUND( compensation - distance );
David Turnerd2b1f351999-12-16 23:11:37 +00001771 if ( val > 0 )
1772 val = 0;
1773 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00001774
David Turnerd2b1f351999-12-16 23:11:37 +00001775 return val;
1776 }
1777
1778
1779 /*************************************************************************/
1780 /* */
1781 /* <Function> */
1782 /* Round_To_Half_Grid */
1783 /* */
1784 /* <Description> */
1785 /* Rounds value to half grid after adding engine compensation. */
1786 /* */
1787 /* <Input> */
1788 /* distance :: The distance to round. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001789 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001790 /* compensation :: The engine compensation. */
1791 /* */
1792 /* <Return> */
1793 /* Rounded distance. */
1794 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001795 static FT_F26Dot6
1796 Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6 distance,
1797 FT_F26Dot6 compensation )
David Turnerd2b1f351999-12-16 23:11:37 +00001798 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001799 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00001800
David Turnerc6a92202000-07-04 18:12:13 +00001801 FT_UNUSED_EXEC;
David Turnere49ab252000-05-16 23:44:38 +00001802
David Turnerd2b1f351999-12-16 23:11:37 +00001803
1804 if ( distance >= 0 )
1805 {
David Turner87c0d302003-12-24 01:10:46 +00001806 val = FT_PIX_FLOOR( distance + compensation ) + 32;
Werner Lembergbe67c4e2003-11-24 22:54:58 +00001807 if ( distance && val < 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001808 val = 0;
1809 }
1810 else
1811 {
David Turner87c0d302003-12-24 01:10:46 +00001812 val = -( FT_PIX_FLOOR( compensation - distance ) + 32 );
David Turnerd2b1f351999-12-16 23:11:37 +00001813 if ( val > 0 )
1814 val = 0;
1815 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00001816
David Turnerd2b1f351999-12-16 23:11:37 +00001817 return val;
1818 }
1819
1820
1821 /*************************************************************************/
1822 /* */
1823 /* <Function> */
1824 /* Round_Down_To_Grid */
1825 /* */
1826 /* <Description> */
1827 /* Rounds value down to grid after adding engine compensation. */
1828 /* */
1829 /* <Input> */
1830 /* distance :: The distance to round. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001831 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001832 /* compensation :: The engine compensation. */
1833 /* */
1834 /* <Return> */
1835 /* Rounded distance. */
1836 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001837 static FT_F26Dot6
1838 Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
1839 FT_F26Dot6 compensation )
David Turnerd2b1f351999-12-16 23:11:37 +00001840 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001841 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00001842
David Turnerc6a92202000-07-04 18:12:13 +00001843 FT_UNUSED_EXEC;
David Turnerd2b1f351999-12-16 23:11:37 +00001844
Werner Lemberg78575dc2000-06-12 19:36:41 +00001845
David Turnerd2b1f351999-12-16 23:11:37 +00001846 if ( distance >= 0 )
1847 {
1848 val = distance + compensation;
Werner Lembergbe67c4e2003-11-24 22:54:58 +00001849 if ( distance && val > 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001850 val &= ~63;
1851 else
1852 val = 0;
1853 }
1854 else
1855 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00001856 val = -( ( compensation - distance ) & -64 );
David Turnerd2b1f351999-12-16 23:11:37 +00001857 if ( val > 0 )
1858 val = 0;
1859 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00001860
David Turnerd2b1f351999-12-16 23:11:37 +00001861 return val;
1862 }
1863
1864
1865 /*************************************************************************/
1866 /* */
1867 /* <Function> */
1868 /* Round_Up_To_Grid */
1869 /* */
1870 /* <Description> */
1871 /* Rounds value up to grid after adding engine compensation. */
1872 /* */
1873 /* <Input> */
1874 /* distance :: The distance to round. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001875 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001876 /* compensation :: The engine compensation. */
1877 /* */
1878 /* <Return> */
1879 /* Rounded distance. */
1880 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001881 static FT_F26Dot6
1882 Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
1883 FT_F26Dot6 compensation )
David Turnerd2b1f351999-12-16 23:11:37 +00001884 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001885 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00001886
David Turnerc6a92202000-07-04 18:12:13 +00001887 FT_UNUSED_EXEC;
David Turnerd2b1f351999-12-16 23:11:37 +00001888
Werner Lembergc6a14082007-02-12 22:08:15 +00001889
David Turnerd2b1f351999-12-16 23:11:37 +00001890 if ( distance >= 0 )
1891 {
1892 val = distance + compensation + 63;
Werner Lembergbe67c4e2003-11-24 22:54:58 +00001893 if ( distance && val > 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001894 val &= ~63;
1895 else
1896 val = 0;
1897 }
1898 else
1899 {
David Turner87c0d302003-12-24 01:10:46 +00001900 val = - FT_PIX_CEIL( compensation - distance );
David Turnerd2b1f351999-12-16 23:11:37 +00001901 if ( val > 0 )
1902 val = 0;
1903 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00001904
David Turnerd2b1f351999-12-16 23:11:37 +00001905 return val;
1906 }
1907
1908
1909 /*************************************************************************/
1910 /* */
1911 /* <Function> */
1912 /* Round_To_Double_Grid */
1913 /* */
1914 /* <Description> */
1915 /* Rounds value to double grid after adding engine compensation. */
1916 /* */
1917 /* <Input> */
1918 /* distance :: The distance to round. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001919 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001920 /* compensation :: The engine compensation. */
1921 /* */
1922 /* <Return> */
1923 /* Rounded distance. */
1924 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001925 static FT_F26Dot6
1926 Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6 distance,
1927 FT_F26Dot6 compensation )
David Turnerd2b1f351999-12-16 23:11:37 +00001928 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001929 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00001930
David Turnerc6a92202000-07-04 18:12:13 +00001931 FT_UNUSED_EXEC;
David Turnerd2b1f351999-12-16 23:11:37 +00001932
Werner Lemberg78575dc2000-06-12 19:36:41 +00001933
David Turnerd2b1f351999-12-16 23:11:37 +00001934 if ( distance >= 0 )
1935 {
1936 val = distance + compensation + 16;
Werner Lembergbe67c4e2003-11-24 22:54:58 +00001937 if ( distance && val > 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001938 val &= ~31;
1939 else
1940 val = 0;
1941 }
1942 else
1943 {
David Turner87c0d302003-12-24 01:10:46 +00001944 val = -FT_PAD_ROUND( compensation - distance, 32 );
David Turnerd2b1f351999-12-16 23:11:37 +00001945 if ( val > 0 )
1946 val = 0;
1947 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00001948
David Turnerd2b1f351999-12-16 23:11:37 +00001949 return val;
1950 }
1951
1952
1953 /*************************************************************************/
1954 /* */
1955 /* <Function> */
1956 /* Round_Super */
1957 /* */
1958 /* <Description> */
1959 /* Super-rounds value to grid after adding engine compensation. */
1960 /* */
1961 /* <Input> */
1962 /* distance :: The distance to round. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001963 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001964 /* compensation :: The engine compensation. */
1965 /* */
1966 /* <Return> */
1967 /* Rounded distance. */
1968 /* */
1969 /* <Note> */
1970 /* The TrueType specification says very few about the relationship */
1971 /* between rounding and engine compensation. However, it seems from */
1972 /* the description of super round that we should add the compensation */
1973 /* before rounding. */
1974 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001975 static FT_F26Dot6
1976 Round_Super( EXEC_OP_ FT_F26Dot6 distance,
1977 FT_F26Dot6 compensation )
David Turnerd2b1f351999-12-16 23:11:37 +00001978 {
David Turnerf9b8dec2000-06-16 19:34:52 +00001979 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00001980
1981
1982 if ( distance >= 0 )
1983 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00001984 val = ( distance - CUR.phase + CUR.threshold + compensation ) &
1985 -CUR.period;
Werner Lembergbe67c4e2003-11-24 22:54:58 +00001986 if ( distance && val < 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00001987 val = 0;
1988 val += CUR.phase;
1989 }
1990 else
1991 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00001992 val = -( ( CUR.threshold - CUR.phase - distance + compensation ) &
1993 -CUR.period );
David Turnerd2b1f351999-12-16 23:11:37 +00001994 if ( val > 0 )
1995 val = 0;
1996 val -= CUR.phase;
1997 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00001998
David Turnerd2b1f351999-12-16 23:11:37 +00001999 return val;
2000 }
2001
2002
2003 /*************************************************************************/
2004 /* */
2005 /* <Function> */
2006 /* Round_Super_45 */
2007 /* */
2008 /* <Description> */
2009 /* Super-rounds value to grid after adding engine compensation. */
2010 /* */
2011 /* <Input> */
2012 /* distance :: The distance to round. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00002013 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00002014 /* compensation :: The engine compensation. */
2015 /* */
2016 /* <Return> */
2017 /* Rounded distance. */
2018 /* */
2019 /* <Note> */
2020 /* There is a separate function for Round_Super_45() as we may need */
2021 /* greater precision. */
2022 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002023 static FT_F26Dot6
2024 Round_Super_45( EXEC_OP_ FT_F26Dot6 distance,
2025 FT_F26Dot6 compensation )
David Turnerd2b1f351999-12-16 23:11:37 +00002026 {
David Turnerf9b8dec2000-06-16 19:34:52 +00002027 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00002028
2029
2030 if ( distance >= 0 )
2031 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00002032 val = ( ( distance - CUR.phase + CUR.threshold + compensation ) /
David Turnerd2b1f351999-12-16 23:11:37 +00002033 CUR.period ) * CUR.period;
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002034 if ( distance && val < 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00002035 val = 0;
2036 val += CUR.phase;
2037 }
2038 else
2039 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00002040 val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) /
David Turnerd2b1f351999-12-16 23:11:37 +00002041 CUR.period ) * CUR.period );
2042 if ( val > 0 )
2043 val = 0;
2044 val -= CUR.phase;
2045 }
2046
2047 return val;
2048 }
2049
2050
2051 /*************************************************************************/
2052 /* */
2053 /* <Function> */
2054 /* Compute_Round */
2055 /* */
2056 /* <Description> */
2057 /* Sets the rounding mode. */
2058 /* */
2059 /* <Input> */
2060 /* round_mode :: The rounding mode to be used. */
2061 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002062 static void
2063 Compute_Round( EXEC_OP_ FT_Byte round_mode )
David Turnerd2b1f351999-12-16 23:11:37 +00002064 {
2065 switch ( round_mode )
2066 {
2067 case TT_Round_Off:
2068 CUR.func_round = (TT_Round_Func)Round_None;
2069 break;
2070
2071 case TT_Round_To_Grid:
2072 CUR.func_round = (TT_Round_Func)Round_To_Grid;
2073 break;
2074
2075 case TT_Round_Up_To_Grid:
2076 CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
2077 break;
2078
2079 case TT_Round_Down_To_Grid:
2080 CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
2081 break;
2082
2083 case TT_Round_To_Half_Grid:
2084 CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
2085 break;
2086
2087 case TT_Round_To_Double_Grid:
2088 CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
2089 break;
2090
2091 case TT_Round_Super:
2092 CUR.func_round = (TT_Round_Func)Round_Super;
2093 break;
2094
2095 case TT_Round_Super_45:
2096 CUR.func_round = (TT_Round_Func)Round_Super_45;
2097 break;
2098 }
2099 }
2100
2101
2102 /*************************************************************************/
2103 /* */
2104 /* <Function> */
2105 /* SetSuperRound */
2106 /* */
2107 /* <Description> */
2108 /* Sets Super Round parameters. */
2109 /* */
2110 /* <Input> */
2111 /* GridPeriod :: Grid period */
2112 /* selector :: SROUND opcode */
2113 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002114 static void
2115 SetSuperRound( EXEC_OP_ FT_F26Dot6 GridPeriod,
2116 FT_Long selector )
David Turnerd2b1f351999-12-16 23:11:37 +00002117 {
David Turnerf9b8dec2000-06-16 19:34:52 +00002118 switch ( (FT_Int)( selector & 0xC0 ) )
David Turnerd2b1f351999-12-16 23:11:37 +00002119 {
2120 case 0:
2121 CUR.period = GridPeriod / 2;
2122 break;
2123
2124 case 0x40:
2125 CUR.period = GridPeriod;
2126 break;
2127
2128 case 0x80:
2129 CUR.period = GridPeriod * 2;
2130 break;
2131
2132 /* This opcode is reserved, but... */
2133
2134 case 0xC0:
2135 CUR.period = GridPeriod;
2136 break;
2137 }
2138
David Turnerf9b8dec2000-06-16 19:34:52 +00002139 switch ( (FT_Int)( selector & 0x30 ) )
David Turnerd2b1f351999-12-16 23:11:37 +00002140 {
2141 case 0:
2142 CUR.phase = 0;
2143 break;
2144
2145 case 0x10:
2146 CUR.phase = CUR.period / 4;
2147 break;
2148
2149 case 0x20:
2150 CUR.phase = CUR.period / 2;
2151 break;
2152
2153 case 0x30:
Werner Lemberg6e9b3182003-06-10 10:54:33 +00002154 CUR.phase = CUR.period * 3 / 4;
David Turnerd2b1f351999-12-16 23:11:37 +00002155 break;
2156 }
2157
Werner Lembergc9f6c662007-03-21 13:30:14 +00002158 if ( ( selector & 0x0F ) == 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00002159 CUR.threshold = CUR.period - 1;
2160 else
David Turnerf9b8dec2000-06-16 19:34:52 +00002161 CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8;
David Turnerd2b1f351999-12-16 23:11:37 +00002162
2163 CUR.period /= 256;
2164 CUR.phase /= 256;
2165 CUR.threshold /= 256;
2166 }
2167
2168
2169 /*************************************************************************/
2170 /* */
2171 /* <Function> */
2172 /* Project */
2173 /* */
2174 /* <Description> */
2175 /* Computes the projection of vector given by (v2-v1) along the */
2176 /* current projection vector. */
2177 /* */
2178 /* <Input> */
2179 /* v1 :: First input vector. */
2180 /* v2 :: Second input vector. */
2181 /* */
2182 /* <Return> */
2183 /* The distance in F26dot6 format. */
2184 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002185 static FT_F26Dot6
David Turner72a0dd22007-02-12 15:24:51 +00002186 Project( EXEC_OP_ FT_Pos dx,
2187 FT_Pos dy )
Werner Lemberg406d25f2007-02-12 22:01:18 +00002188 {
David Turner8b6db862003-08-17 22:09:14 +00002189#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Werner Lemberga3f4da82003-04-29 13:23:47 +00002190 FT_ASSERT( !CUR.face->unpatented_hinting );
Graham Asher3ea859f2003-04-25 11:40:46 +00002191#endif
Werner Lemberga3f4da82003-04-29 13:23:47 +00002192
David Turner72a0dd22007-02-12 15:24:51 +00002193 return TT_DotFix14( dx, dy,
David Turner4b29d582002-03-25 17:02:26 +00002194 CUR.GS.projVector.x,
2195 CUR.GS.projVector.y );
Werner Lemberg406d25f2007-02-12 22:01:18 +00002196 }
2197
David Turnerd2b1f351999-12-16 23:11:37 +00002198
David Turnerd2b1f351999-12-16 23:11:37 +00002199 /*************************************************************************/
2200 /* */
2201 /* <Function> */
2202 /* Dual_Project */
2203 /* */
2204 /* <Description> */
2205 /* Computes the projection of the vector given by (v2-v1) along the */
2206 /* current dual vector. */
2207 /* */
2208 /* <Input> */
2209 /* v1 :: First input vector. */
2210 /* v2 :: Second input vector. */
2211 /* */
2212 /* <Return> */
2213 /* The distance in F26dot6 format. */
2214 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002215 static FT_F26Dot6
David Turner72a0dd22007-02-12 15:24:51 +00002216 Dual_Project( EXEC_OP_ FT_Pos dx,
2217 FT_Pos dy )
David Turnerd2b1f351999-12-16 23:11:37 +00002218 {
David Turner72a0dd22007-02-12 15:24:51 +00002219 return TT_DotFix14( dx, dy,
David Turner4b29d582002-03-25 17:02:26 +00002220 CUR.GS.dualVector.x,
2221 CUR.GS.dualVector.y );
David Turnerd2b1f351999-12-16 23:11:37 +00002222 }
2223
Werner Lemberg406d25f2007-02-12 22:01:18 +00002224
David Turnerd2b1f351999-12-16 23:11:37 +00002225 /*************************************************************************/
2226 /* */
2227 /* <Function> */
David Turnerd2b1f351999-12-16 23:11:37 +00002228 /* Project_x */
2229 /* */
2230 /* <Description> */
2231 /* Computes the projection of the vector given by (v2-v1) along the */
2232 /* horizontal axis. */
2233 /* */
2234 /* <Input> */
2235 /* v1 :: First input vector. */
2236 /* v2 :: Second input vector. */
2237 /* */
2238 /* <Return> */
2239 /* The distance in F26dot6 format. */
2240 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002241 static FT_F26Dot6
David Turner72a0dd22007-02-12 15:24:51 +00002242 Project_x( EXEC_OP_ FT_Pos dx,
2243 FT_Pos dy )
David Turnerd2b1f351999-12-16 23:11:37 +00002244 {
David Turnerc6a92202000-07-04 18:12:13 +00002245 FT_UNUSED_EXEC;
Werner Lembergc6a14082007-02-12 22:08:15 +00002246 FT_UNUSED( dy );
David Turnerd2b1f351999-12-16 23:11:37 +00002247
David Turner72a0dd22007-02-12 15:24:51 +00002248 return dx;
David Turnerd2b1f351999-12-16 23:11:37 +00002249 }
2250
Werner Lemberg406d25f2007-02-12 22:01:18 +00002251
David Turnerd2b1f351999-12-16 23:11:37 +00002252 /*************************************************************************/
2253 /* */
2254 /* <Function> */
2255 /* Project_y */
2256 /* */
2257 /* <Description> */
2258 /* Computes the projection of the vector given by (v2-v1) along the */
2259 /* vertical axis. */
2260 /* */
2261 /* <Input> */
2262 /* v1 :: First input vector. */
2263 /* v2 :: Second input vector. */
2264 /* */
2265 /* <Return> */
2266 /* The distance in F26dot6 format. */
2267 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002268 static FT_F26Dot6
David Turner72a0dd22007-02-12 15:24:51 +00002269 Project_y( EXEC_OP_ FT_Pos dx,
2270 FT_Pos dy )
David Turnerd2b1f351999-12-16 23:11:37 +00002271 {
David Turnerc6a92202000-07-04 18:12:13 +00002272 FT_UNUSED_EXEC;
Werner Lembergc6a14082007-02-12 22:08:15 +00002273 FT_UNUSED( dx );
David Turnere49ab252000-05-16 23:44:38 +00002274
David Turner72a0dd22007-02-12 15:24:51 +00002275 return dy;
David Turnerd2b1f351999-12-16 23:11:37 +00002276 }
2277
Werner Lemberg406d25f2007-02-12 22:01:18 +00002278
David Turnerd2b1f351999-12-16 23:11:37 +00002279 /*************************************************************************/
2280 /* */
2281 /* <Function> */
2282 /* Compute_Funcs */
2283 /* */
2284 /* <Description> */
2285 /* Computes the projection and movement function pointers according */
2286 /* to the current graphics state. */
2287 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002288 static void
2289 Compute_Funcs( EXEC_OP )
David Turnerd2b1f351999-12-16 23:11:37 +00002290 {
David Turner8b6db862003-08-17 22:09:14 +00002291#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Graham Asher3ea859f2003-04-25 11:40:46 +00002292 if ( CUR.face->unpatented_hinting )
Werner Lemberga3f4da82003-04-29 13:23:47 +00002293 {
Graham Asher3ea859f2003-04-25 11:40:46 +00002294 /* If both vectors point rightwards along the x axis, set */
Werner Lemberga3f4da82003-04-29 13:23:47 +00002295 /* `both-x-axis' true, otherwise set it false. The x values only */
2296 /* need be tested because the vector has been normalised to a unit */
2297 /* vector of length 0x4000 = unity. */
2298 CUR.GS.both_x_axis = (FT_Bool)( CUR.GS.projVector.x == 0x4000 &&
2299 CUR.GS.freeVector.x == 0x4000 );
Graham Asher3ea859f2003-04-25 11:40:46 +00002300
Werner Lemberga3f4da82003-04-29 13:23:47 +00002301 /* Throw away projection and freedom vector information */
2302 /* because the patents don't allow them to be stored. */
2303 /* The relevant US Patents are 5155805 and 5325479. */
Graham Asher3ea859f2003-04-25 11:40:46 +00002304 CUR.GS.projVector.x = 0;
2305 CUR.GS.projVector.y = 0;
2306 CUR.GS.freeVector.x = 0;
2307 CUR.GS.freeVector.y = 0;
2308
2309 if ( CUR.GS.both_x_axis )
2310 {
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002311 CUR.func_project = Project_x;
2312 CUR.func_move = Direct_Move_X;
2313 CUR.func_move_orig = Direct_Move_Orig_X;
Graham Asher3ea859f2003-04-25 11:40:46 +00002314 }
Werner Lemberga3f4da82003-04-29 13:23:47 +00002315 else
Graham Asher3ea859f2003-04-25 11:40:46 +00002316 {
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002317 CUR.func_project = Project_y;
2318 CUR.func_move = Direct_Move_Y;
2319 CUR.func_move_orig = Direct_Move_Orig_Y;
Graham Asher3ea859f2003-04-25 11:40:46 +00002320 }
2321
2322 if ( CUR.GS.dualVector.x == 0x4000 )
2323 CUR.func_dualproj = Project_x;
2324 else
2325 {
2326 if ( CUR.GS.dualVector.y == 0x4000 )
Werner Lemberga3f4da82003-04-29 13:23:47 +00002327 CUR.func_dualproj = Project_y;
Graham Asher3ea859f2003-04-25 11:40:46 +00002328 else
2329 CUR.func_dualproj = Dual_Project;
2330 }
2331
2332 /* Force recalculation of cached aspect ratio */
2333 CUR.tt_metrics.ratio = 0;
2334
Werner Lemberga3f4da82003-04-29 13:23:47 +00002335 return;
2336 }
David Turner8b6db862003-08-17 22:09:14 +00002337#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */
Graham Asher3ea859f2003-04-25 11:40:46 +00002338
David Turnerd2b1f351999-12-16 23:11:37 +00002339 if ( CUR.GS.freeVector.x == 0x4000 )
David Turnerd2b1f351999-12-16 23:11:37 +00002340 CUR.F_dot_P = CUR.GS.projVector.x * 0x10000L;
David Turnerd2b1f351999-12-16 23:11:37 +00002341 else
2342 {
2343 if ( CUR.GS.freeVector.y == 0x4000 )
David Turnerd2b1f351999-12-16 23:11:37 +00002344 CUR.F_dot_P = CUR.GS.projVector.y * 0x10000L;
David Turnerd2b1f351999-12-16 23:11:37 +00002345 else
David Turnerf9b8dec2000-06-16 19:34:52 +00002346 CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 +
2347 (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4;
David Turnerd2b1f351999-12-16 23:11:37 +00002348 }
2349
2350 if ( CUR.GS.projVector.x == 0x4000 )
2351 CUR.func_project = (TT_Project_Func)Project_x;
2352 else
2353 {
2354 if ( CUR.GS.projVector.y == 0x4000 )
2355 CUR.func_project = (TT_Project_Func)Project_y;
2356 else
2357 CUR.func_project = (TT_Project_Func)Project;
2358 }
2359
2360 if ( CUR.GS.dualVector.x == 0x4000 )
2361 CUR.func_dualproj = (TT_Project_Func)Project_x;
2362 else
2363 {
2364 if ( CUR.GS.dualVector.y == 0x4000 )
2365 CUR.func_dualproj = (TT_Project_Func)Project_y;
2366 else
2367 CUR.func_dualproj = (TT_Project_Func)Dual_Project;
2368 }
2369
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002370 CUR.func_move = (TT_Move_Func)Direct_Move;
2371 CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig;
David Turnerd2b1f351999-12-16 23:11:37 +00002372
2373 if ( CUR.F_dot_P == 0x40000000L )
2374 {
2375 if ( CUR.GS.freeVector.x == 0x4000 )
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002376 {
2377 CUR.func_move = (TT_Move_Func)Direct_Move_X;
2378 CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
2379 }
David Turnerd2b1f351999-12-16 23:11:37 +00002380 else
2381 {
2382 if ( CUR.GS.freeVector.y == 0x4000 )
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002383 {
2384 CUR.func_move = (TT_Move_Func)Direct_Move_Y;
2385 CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
2386 }
David Turnerd2b1f351999-12-16 23:11:37 +00002387 }
2388 }
2389
2390 /* at small sizes, F_dot_P can become too small, resulting */
2391 /* in overflows and `spikes' in a number of glyphs like `w'. */
2392
Werner Lembergdfa46192004-03-05 09:26:24 +00002393 if ( FT_ABS( CUR.F_dot_P ) < 0x4000000L )
David Turnerd2b1f351999-12-16 23:11:37 +00002394 CUR.F_dot_P = 0x40000000L;
2395
2396 /* Disable cached aspect ratio */
2397 CUR.tt_metrics.ratio = 0;
2398 }
2399
2400
2401 /*************************************************************************/
2402 /* */
2403 /* <Function> */
2404 /* Normalize */
2405 /* */
2406 /* <Description> */
2407 /* Norms a vector. */
2408 /* */
2409 /* <Input> */
2410 /* Vx :: The horizontal input vector coordinate. */
2411 /* Vy :: The vertical input vector coordinate. */
2412 /* */
2413 /* <Output> */
2414 /* R :: The normed unit vector. */
2415 /* */
2416 /* <Return> */
2417 /* Returns FAILURE if a vector parameter is zero. */
2418 /* */
2419 /* <Note> */
2420 /* In case Vx and Vy are both zero, Normalize() returns SUCCESS, and */
2421 /* R is undefined. */
2422 /* */
David Turnerb7ef2b02000-05-02 11:01:12 +00002423
Werner Lemberg78575dc2000-06-12 19:36:41 +00002424
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002425 static FT_Bool
2426 Normalize( EXEC_OP_ FT_F26Dot6 Vx,
2427 FT_F26Dot6 Vy,
2428 FT_UnitVector* R )
David Turnerb7ef2b02000-05-02 11:01:12 +00002429 {
David Turnerf9b8dec2000-06-16 19:34:52 +00002430 FT_F26Dot6 W;
2431 FT_Bool S1, S2;
David Turnerb7ef2b02000-05-02 11:01:12 +00002432
David Turnerc6a92202000-07-04 18:12:13 +00002433 FT_UNUSED_EXEC;
David Turnere49ab252000-05-16 23:44:38 +00002434
Werner Lemberg78575dc2000-06-12 19:36:41 +00002435
Werner Lembergdfa46192004-03-05 09:26:24 +00002436 if ( FT_ABS( Vx ) < 0x10000L && FT_ABS( Vy ) < 0x10000L )
David Turnerb7ef2b02000-05-02 11:01:12 +00002437 {
2438 Vx *= 0x100;
2439 Vy *= 0x100;
2440
David Turner4b29d582002-03-25 17:02:26 +00002441 W = TT_VecLen( Vx, Vy );
David Turnerb7ef2b02000-05-02 11:01:12 +00002442
2443 if ( W == 0 )
2444 {
Werner Lemberg5811c7c2000-07-02 13:53:16 +00002445 /* XXX: UNDOCUMENTED! It seems that it is possible to try */
Werner Lemberg78575dc2000-06-12 19:36:41 +00002446 /* to normalize the vector (0,0). Return immediately. */
David Turnerb7ef2b02000-05-02 11:01:12 +00002447 return SUCCESS;
2448 }
2449
David Turnerf9b8dec2000-06-16 19:34:52 +00002450 R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W );
2451 R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W );
David Turnerb7ef2b02000-05-02 11:01:12 +00002452
2453 return SUCCESS;
2454 }
2455
David Turner4b29d582002-03-25 17:02:26 +00002456 W = TT_VecLen( Vx, Vy );
David Turnerb7ef2b02000-05-02 11:01:12 +00002457
2458 Vx = FT_MulDiv( Vx, 0x4000L, W );
2459 Vy = FT_MulDiv( Vy, 0x4000L, W );
2460
2461 W = Vx * Vx + Vy * Vy;
2462
2463 /* Now, we want that Sqrt( W ) = 0x4000 */
David Turner5ab41362004-07-18 07:15:18 +00002464 /* Or 0x10000000 <= W < 0x10004000 */
David Turnerb7ef2b02000-05-02 11:01:12 +00002465
2466 if ( Vx < 0 )
2467 {
2468 Vx = -Vx;
2469 S1 = TRUE;
2470 }
2471 else
2472 S1 = FALSE;
2473
2474 if ( Vy < 0 )
2475 {
2476 Vy = -Vy;
2477 S2 = TRUE;
2478 }
2479 else
2480 S2 = FALSE;
2481
David Turner5ab41362004-07-18 07:15:18 +00002482 while ( W < 0x10000000L )
David Turnerb7ef2b02000-05-02 11:01:12 +00002483 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00002484 /* We need to increase W by a minimal amount */
David Turnerb7ef2b02000-05-02 11:01:12 +00002485 if ( Vx < Vy )
2486 Vx++;
2487 else
2488 Vy++;
2489
2490 W = Vx * Vx + Vy * Vy;
2491 }
2492
David Turner5ab41362004-07-18 07:15:18 +00002493 while ( W >= 0x10004000L )
David Turnerb7ef2b02000-05-02 11:01:12 +00002494 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00002495 /* We need to decrease W by a minimal amount */
David Turnerb7ef2b02000-05-02 11:01:12 +00002496 if ( Vx < Vy )
2497 Vx--;
2498 else
2499 Vy--;
2500
2501 W = Vx * Vx + Vy * Vy;
2502 }
2503
2504 /* Note that in various cases, we can only */
2505 /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */
2506
2507 if ( S1 )
2508 Vx = -Vx;
2509
2510 if ( S2 )
2511 Vy = -Vy;
2512
David Turnerf9b8dec2000-06-16 19:34:52 +00002513 R->x = (FT_F2Dot14)Vx; /* Type conversion */
2514 R->y = (FT_F2Dot14)Vy; /* Type conversion */
David Turnerb7ef2b02000-05-02 11:01:12 +00002515
2516 return SUCCESS;
2517 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00002518
David Turnerd2b1f351999-12-16 23:11:37 +00002519
2520 /*************************************************************************/
2521 /* */
2522 /* Here we start with the implementation of the various opcodes. */
2523 /* */
2524 /*************************************************************************/
2525
2526
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002527 static FT_Bool
2528 Ins_SxVTL( EXEC_OP_ FT_UShort aIdx1,
2529 FT_UShort aIdx2,
2530 FT_Int aOpc,
2531 FT_UnitVector* Vec )
David Turnerd2b1f351999-12-16 23:11:37 +00002532 {
David Turnerf9b8dec2000-06-16 19:34:52 +00002533 FT_Long A, B, C;
2534 FT_Vector* p1;
2535 FT_Vector* p2;
David Turnerd2b1f351999-12-16 23:11:37 +00002536
2537
2538 if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||
2539 BOUNDS( aIdx2, CUR.zp1.n_points ) )
2540 {
2541 if ( CUR.pedantic_hinting )
2542 CUR.error = TT_Err_Invalid_Reference;
2543 return FAILURE;
2544 }
2545
2546 p1 = CUR.zp1.cur + aIdx2;
2547 p2 = CUR.zp2.cur + aIdx1;
2548
2549 A = p1->x - p2->x;
2550 B = p1->y - p2->y;
2551
Werner Lemberg78575dc2000-06-12 19:36:41 +00002552 if ( ( aOpc & 1 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00002553 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00002554 C = B; /* counter clockwise rotation */
David Turnerd2b1f351999-12-16 23:11:37 +00002555 B = A;
2556 A = -C;
2557 }
2558
2559 NORMalize( A, B, Vec );
2560
2561 return SUCCESS;
2562 }
2563
2564
2565 /* When not using the big switch statements, the interpreter uses a */
2566 /* call table defined later below in this source. Each opcode must */
2567 /* thus have a corresponding function, even trivial ones. */
2568 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00002569 /* They are all defined there. */
David Turnerd2b1f351999-12-16 23:11:37 +00002570
Werner Lemberg78575dc2000-06-12 19:36:41 +00002571#define DO_SVTCA \
2572 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00002573 FT_Short A, B; \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002574 \
2575 \
David Turnerf9b8dec2000-06-16 19:34:52 +00002576 A = (FT_Short)( CUR.opcode & 1 ) << 14; \
2577 B = A ^ (FT_Short)0x4000; \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002578 \
2579 CUR.GS.freeVector.x = A; \
2580 CUR.GS.projVector.x = A; \
2581 CUR.GS.dualVector.x = A; \
2582 \
2583 CUR.GS.freeVector.y = B; \
2584 CUR.GS.projVector.y = B; \
2585 CUR.GS.dualVector.y = B; \
2586 \
2587 COMPUTE_Funcs(); \
David Turnerd2b1f351999-12-16 23:11:37 +00002588 }
2589
2590
Werner Lemberg78575dc2000-06-12 19:36:41 +00002591#define DO_SPVTCA \
2592 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00002593 FT_Short A, B; \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002594 \
2595 \
David Turnerf9b8dec2000-06-16 19:34:52 +00002596 A = (FT_Short)( CUR.opcode & 1 ) << 14; \
2597 B = A ^ (FT_Short)0x4000; \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002598 \
2599 CUR.GS.projVector.x = A; \
2600 CUR.GS.dualVector.x = A; \
2601 \
2602 CUR.GS.projVector.y = B; \
2603 CUR.GS.dualVector.y = B; \
2604 \
Graham Asher3ea859f2003-04-25 11:40:46 +00002605 GUESS_VECTOR( freeVector ); \
2606 \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002607 COMPUTE_Funcs(); \
David Turnerd2b1f351999-12-16 23:11:37 +00002608 }
2609
2610
Werner Lemberg78575dc2000-06-12 19:36:41 +00002611#define DO_SFVTCA \
2612 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00002613 FT_Short A, B; \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002614 \
2615 \
David Turnerf9b8dec2000-06-16 19:34:52 +00002616 A = (FT_Short)( CUR.opcode & 1 ) << 14; \
2617 B = A ^ (FT_Short)0x4000; \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002618 \
2619 CUR.GS.freeVector.x = A; \
2620 CUR.GS.freeVector.y = B; \
2621 \
Graham Asher3ea859f2003-04-25 11:40:46 +00002622 GUESS_VECTOR( projVector ); \
2623 \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002624 COMPUTE_Funcs(); \
David Turnerd2b1f351999-12-16 23:11:37 +00002625 }
2626
2627
Werner Lemberg78575dc2000-06-12 19:36:41 +00002628#define DO_SPVTL \
David Turnerf9b8dec2000-06-16 19:34:52 +00002629 if ( INS_SxVTL( (FT_UShort)args[1], \
2630 (FT_UShort)args[0], \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002631 CUR.opcode, \
2632 &CUR.GS.projVector ) == SUCCESS ) \
2633 { \
2634 CUR.GS.dualVector = CUR.GS.projVector; \
Graham Asher3ea859f2003-04-25 11:40:46 +00002635 GUESS_VECTOR( freeVector ); \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002636 COMPUTE_Funcs(); \
David Turnerd2b1f351999-12-16 23:11:37 +00002637 }
2638
2639
Werner Lemberg78575dc2000-06-12 19:36:41 +00002640#define DO_SFVTL \
David Turnerf9b8dec2000-06-16 19:34:52 +00002641 if ( INS_SxVTL( (FT_UShort)args[1], \
2642 (FT_UShort)args[0], \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002643 CUR.opcode, \
2644 &CUR.GS.freeVector ) == SUCCESS ) \
Werner Lembergf79a7ae2003-05-21 21:47:25 +00002645 { \
Graham Asher3ea859f2003-04-25 11:40:46 +00002646 GUESS_VECTOR( projVector ); \
Werner Lembergf79a7ae2003-05-21 21:47:25 +00002647 COMPUTE_Funcs(); \
2648 }
David Turnerd2b1f351999-12-16 23:11:37 +00002649
2650
2651#define DO_SFVTPV \
Graham Asher3ea859f2003-04-25 11:40:46 +00002652 GUESS_VECTOR( projVector ); \
David Turnerd2b1f351999-12-16 23:11:37 +00002653 CUR.GS.freeVector = CUR.GS.projVector; \
2654 COMPUTE_Funcs();
2655
2656
2657#define DO_SPVFS \
2658 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00002659 FT_Short S; \
2660 FT_Long X, Y; \
David Turnerd2b1f351999-12-16 23:11:37 +00002661 \
2662 \
2663 /* Only use low 16bits, then sign extend */ \
David Turnerf9b8dec2000-06-16 19:34:52 +00002664 S = (FT_Short)args[1]; \
2665 Y = (FT_Long)S; \
2666 S = (FT_Short)args[0]; \
2667 X = (FT_Long)S; \
David Turnerd2b1f351999-12-16 23:11:37 +00002668 \
2669 NORMalize( X, Y, &CUR.GS.projVector ); \
2670 \
2671 CUR.GS.dualVector = CUR.GS.projVector; \
Graham Asher3ea859f2003-04-25 11:40:46 +00002672 GUESS_VECTOR( freeVector ); \
David Turnerd2b1f351999-12-16 23:11:37 +00002673 COMPUTE_Funcs(); \
2674 }
2675
2676
2677#define DO_SFVFS \
2678 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00002679 FT_Short S; \
2680 FT_Long X, Y; \
David Turnerd2b1f351999-12-16 23:11:37 +00002681 \
2682 \
2683 /* Only use low 16bits, then sign extend */ \
David Turnerf9b8dec2000-06-16 19:34:52 +00002684 S = (FT_Short)args[1]; \
2685 Y = (FT_Long)S; \
2686 S = (FT_Short)args[0]; \
David Turnerd2b1f351999-12-16 23:11:37 +00002687 X = S; \
2688 \
2689 NORMalize( X, Y, &CUR.GS.freeVector ); \
Graham Asher3ea859f2003-04-25 11:40:46 +00002690 GUESS_VECTOR( projVector ); \
David Turnerd2b1f351999-12-16 23:11:37 +00002691 COMPUTE_Funcs(); \
2692 }
2693
2694
David Turner8b6db862003-08-17 22:09:14 +00002695#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Werner Lemberga3f4da82003-04-29 13:23:47 +00002696#define DO_GPV \
2697 if ( CUR.face->unpatented_hinting ) \
2698 { \
2699 args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
2700 args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
2701 } \
2702 else \
2703 { \
2704 args[0] = CUR.GS.projVector.x; \
2705 args[1] = CUR.GS.projVector.y; \
Graham Asher3ea859f2003-04-25 11:40:46 +00002706 }
2707#else
Werner Lemberga3f4da82003-04-29 13:23:47 +00002708#define DO_GPV \
2709 args[0] = CUR.GS.projVector.x; \
David Turnerd2b1f351999-12-16 23:11:37 +00002710 args[1] = CUR.GS.projVector.y;
Graham Asher3ea859f2003-04-25 11:40:46 +00002711#endif
David Turnerd2b1f351999-12-16 23:11:37 +00002712
2713
David Turner8b6db862003-08-17 22:09:14 +00002714#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Werner Lemberga3f4da82003-04-29 13:23:47 +00002715#define DO_GFV \
2716 if ( CUR.face->unpatented_hinting ) \
2717 { \
2718 args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
2719 args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
2720 } \
2721 else \
2722 { \
2723 args[0] = CUR.GS.freeVector.x; \
2724 args[1] = CUR.GS.freeVector.y; \
Graham Asher3ea859f2003-04-25 11:40:46 +00002725 }
2726#else
Werner Lemberga3f4da82003-04-29 13:23:47 +00002727#define DO_GFV \
2728 args[0] = CUR.GS.freeVector.x; \
David Turnerd2b1f351999-12-16 23:11:37 +00002729 args[1] = CUR.GS.freeVector.y;
Graham Asher3ea859f2003-04-25 11:40:46 +00002730#endif
David Turnerd2b1f351999-12-16 23:11:37 +00002731
2732
Werner Lemberg78575dc2000-06-12 19:36:41 +00002733#define DO_SRP0 \
David Turnerf9b8dec2000-06-16 19:34:52 +00002734 CUR.GS.rp0 = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00002735
2736
Werner Lemberg78575dc2000-06-12 19:36:41 +00002737#define DO_SRP1 \
David Turnerf9b8dec2000-06-16 19:34:52 +00002738 CUR.GS.rp1 = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00002739
2740
Werner Lemberg78575dc2000-06-12 19:36:41 +00002741#define DO_SRP2 \
David Turnerf9b8dec2000-06-16 19:34:52 +00002742 CUR.GS.rp2 = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00002743
2744
2745#define DO_RTHG \
2746 CUR.GS.round_state = TT_Round_To_Half_Grid; \
2747 CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
2748
2749
2750#define DO_RTG \
2751 CUR.GS.round_state = TT_Round_To_Grid; \
2752 CUR.func_round = (TT_Round_Func)Round_To_Grid;
2753
2754
2755#define DO_RTDG \
2756 CUR.GS.round_state = TT_Round_To_Double_Grid; \
2757 CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
2758
2759
2760#define DO_RUTG \
2761 CUR.GS.round_state = TT_Round_Up_To_Grid; \
2762 CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
2763
2764
2765#define DO_RDTG \
2766 CUR.GS.round_state = TT_Round_Down_To_Grid; \
2767 CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
2768
2769
2770#define DO_ROFF \
2771 CUR.GS.round_state = TT_Round_Off; \
2772 CUR.func_round = (TT_Round_Func)Round_None;
2773
2774
2775#define DO_SROUND \
2776 SET_SuperRound( 0x4000, args[0] ); \
2777 CUR.GS.round_state = TT_Round_Super; \
2778 CUR.func_round = (TT_Round_Func)Round_Super;
2779
2780
2781#define DO_S45ROUND \
2782 SET_SuperRound( 0x2D41, args[0] ); \
2783 CUR.GS.round_state = TT_Round_Super_45; \
2784 CUR.func_round = (TT_Round_Func)Round_Super_45;
2785
2786
2787#define DO_SLOOP \
2788 if ( args[0] < 0 ) \
2789 CUR.error = TT_Err_Bad_Argument; \
2790 else \
2791 CUR.GS.loop = args[0];
2792
2793
2794#define DO_SMD \
2795 CUR.GS.minimum_distance = args[0];
2796
2797
2798#define DO_SCVTCI \
David Turnerf9b8dec2000-06-16 19:34:52 +00002799 CUR.GS.control_value_cutin = (FT_F26Dot6)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00002800
2801
2802#define DO_SSWCI \
David Turnerf9b8dec2000-06-16 19:34:52 +00002803 CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00002804
2805
Werner Lemberg555258f2007-01-21 09:46:37 +00002806 /* XXX: UNDOCUMENTED! or bug in the Windows engine? */
2807 /* */
2808 /* It seems that the value that is read here is */
2809 /* expressed in 16.16 format rather than in font */
2810 /* units. */
2811 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00002812#define DO_SSW \
David Turnerf9b8dec2000-06-16 19:34:52 +00002813 CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 );
David Turnerd2b1f351999-12-16 23:11:37 +00002814
2815
2816#define DO_FLIPON \
2817 CUR.GS.auto_flip = TRUE;
2818
2819
2820#define DO_FLIPOFF \
2821 CUR.GS.auto_flip = FALSE;
2822
2823
2824#define DO_SDB \
David Turnerf9b8dec2000-06-16 19:34:52 +00002825 CUR.GS.delta_base = (FT_Short)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00002826
2827
2828#define DO_SDS \
David Turnerf9b8dec2000-06-16 19:34:52 +00002829 CUR.GS.delta_shift = (FT_Short)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00002830
2831
2832#define DO_MD /* nothing */
2833
2834
2835#define DO_MPPEM \
2836 args[0] = CURRENT_Ppem();
2837
2838
Werner Lemberg78575dc2000-06-12 19:36:41 +00002839 /* Note: The pointSize should be irrelevant in a given font program; */
2840 /* we thus decide to return only the ppem. */
David Turnerd2b1f351999-12-16 23:11:37 +00002841#if 0
Werner Lemberg78575dc2000-06-12 19:36:41 +00002842
David Turnerd2b1f351999-12-16 23:11:37 +00002843#define DO_MPS \
2844 args[0] = CUR.metrics.pointSize;
Werner Lemberg78575dc2000-06-12 19:36:41 +00002845
David Turnerd2b1f351999-12-16 23:11:37 +00002846#else
Werner Lemberg78575dc2000-06-12 19:36:41 +00002847
2848#define DO_MPS \
David Turnerd2b1f351999-12-16 23:11:37 +00002849 args[0] = CURRENT_Ppem();
Werner Lemberg78575dc2000-06-12 19:36:41 +00002850
2851#endif /* 0 */
2852
David Turnerd2b1f351999-12-16 23:11:37 +00002853
2854#define DO_DUP \
2855 args[1] = args[0];
2856
2857
2858#define DO_CLEAR \
2859 CUR.new_top = 0;
2860
2861
2862#define DO_SWAP \
2863 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00002864 FT_Long L; \
David Turnerd2b1f351999-12-16 23:11:37 +00002865 \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002866 \
David Turnerd2b1f351999-12-16 23:11:37 +00002867 L = args[0]; \
2868 args[0] = args[1]; \
2869 args[1] = L; \
2870 }
2871
2872
2873#define DO_DEPTH \
2874 args[0] = CUR.top;
2875
2876
2877#define DO_CINDEX \
2878 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00002879 FT_Long L; \
David Turnerd2b1f351999-12-16 23:11:37 +00002880 \
2881 \
2882 L = args[0]; \
2883 \
2884 if ( L <= 0 || L > CUR.args ) \
2885 CUR.error = TT_Err_Invalid_Reference; \
2886 else \
2887 args[0] = CUR.stack[CUR.args - L]; \
2888 }
2889
2890
2891#define DO_JROT \
2892 if ( args[1] != 0 ) \
2893 { \
2894 CUR.IP += args[0]; \
2895 CUR.step_ins = FALSE; \
2896 }
2897
2898
2899#define DO_JMPR \
2900 CUR.IP += args[0]; \
2901 CUR.step_ins = FALSE;
2902
2903
2904#define DO_JROF \
2905 if ( args[1] == 0 ) \
2906 { \
2907 CUR.IP += args[0]; \
2908 CUR.step_ins = FALSE; \
2909 }
2910
2911
Werner Lemberg78575dc2000-06-12 19:36:41 +00002912#define DO_LT \
2913 args[0] = ( args[0] < args[1] );
David Turnerd2b1f351999-12-16 23:11:37 +00002914
2915
Werner Lemberg78575dc2000-06-12 19:36:41 +00002916#define DO_LTEQ \
2917 args[0] = ( args[0] <= args[1] );
David Turnerd2b1f351999-12-16 23:11:37 +00002918
2919
Werner Lemberg78575dc2000-06-12 19:36:41 +00002920#define DO_GT \
2921 args[0] = ( args[0] > args[1] );
David Turnerd2b1f351999-12-16 23:11:37 +00002922
2923
Werner Lemberg78575dc2000-06-12 19:36:41 +00002924#define DO_GTEQ \
2925 args[0] = ( args[0] >= args[1] );
David Turnerd2b1f351999-12-16 23:11:37 +00002926
2927
Werner Lemberg78575dc2000-06-12 19:36:41 +00002928#define DO_EQ \
2929 args[0] = ( args[0] == args[1] );
David Turnerd2b1f351999-12-16 23:11:37 +00002930
2931
Werner Lemberg78575dc2000-06-12 19:36:41 +00002932#define DO_NEQ \
2933 args[0] = ( args[0] != args[1] );
David Turnerd2b1f351999-12-16 23:11:37 +00002934
2935
Werner Lemberg78575dc2000-06-12 19:36:41 +00002936#define DO_ODD \
2937 args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 );
David Turnerd2b1f351999-12-16 23:11:37 +00002938
2939
Werner Lemberg78575dc2000-06-12 19:36:41 +00002940#define DO_EVEN \
2941 args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 );
David Turnerd2b1f351999-12-16 23:11:37 +00002942
2943
2944#define DO_AND \
2945 args[0] = ( args[0] && args[1] );
2946
2947
2948#define DO_OR \
2949 args[0] = ( args[0] || args[1] );
2950
2951
2952#define DO_NOT \
2953 args[0] = !args[0];
2954
2955
2956#define DO_ADD \
2957 args[0] += args[1];
2958
2959
2960#define DO_SUB \
2961 args[0] -= args[1];
2962
2963
Werner Lemberg9f051a72003-11-25 18:15:56 +00002964#define DO_DIV \
2965 if ( args[1] == 0 ) \
2966 CUR.error = TT_Err_Divide_By_Zero; \
2967 else \
2968 args[0] = TT_MULDIV_NO_ROUND( args[0], 64L, args[1] );
David Turnerd2b1f351999-12-16 23:11:37 +00002969
2970
2971#define DO_MUL \
2972 args[0] = TT_MULDIV( args[0], args[1], 64L );
2973
2974
Werner Lembergdfa46192004-03-05 09:26:24 +00002975#define DO_ABS \
2976 args[0] = FT_ABS( args[0] );
David Turnerd2b1f351999-12-16 23:11:37 +00002977
2978
2979#define DO_NEG \
2980 args[0] = -args[0];
2981
2982
2983#define DO_FLOOR \
David Turner87c0d302003-12-24 01:10:46 +00002984 args[0] = FT_PIX_FLOOR( args[0] );
David Turnerd2b1f351999-12-16 23:11:37 +00002985
2986
2987#define DO_CEILING \
David Turner87c0d302003-12-24 01:10:46 +00002988 args[0] = FT_PIX_CEIL( args[0] );
David Turnerd2b1f351999-12-16 23:11:37 +00002989
2990
2991#define DO_RS \
2992 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00002993 FT_ULong I = (FT_ULong)args[0]; \
David Turnerd2b1f351999-12-16 23:11:37 +00002994 \
2995 \
2996 if ( BOUNDS( I, CUR.storeSize ) ) \
2997 { \
2998 if ( CUR.pedantic_hinting ) \
2999 { \
3000 ARRAY_BOUND_ERROR; \
3001 } \
3002 else \
3003 args[0] = 0; \
3004 } \
3005 else \
3006 args[0] = CUR.storage[I]; \
3007 }
3008
3009
3010#define DO_WS \
3011 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00003012 FT_ULong I = (FT_ULong)args[0]; \
David Turnerd2b1f351999-12-16 23:11:37 +00003013 \
3014 \
3015 if ( BOUNDS( I, CUR.storeSize ) ) \
3016 { \
3017 if ( CUR.pedantic_hinting ) \
3018 { \
3019 ARRAY_BOUND_ERROR; \
3020 } \
3021 } \
3022 else \
3023 CUR.storage[I] = args[1]; \
3024 }
3025
3026
Werner Lemberg78575dc2000-06-12 19:36:41 +00003027#define DO_RCVT \
3028 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00003029 FT_ULong I = (FT_ULong)args[0]; \
Werner Lemberg78575dc2000-06-12 19:36:41 +00003030 \
3031 \
3032 if ( BOUNDS( I, CUR.cvtSize ) ) \
3033 { \
3034 if ( CUR.pedantic_hinting ) \
3035 { \
3036 ARRAY_BOUND_ERROR; \
3037 } \
3038 else \
3039 args[0] = 0; \
3040 } \
3041 else \
3042 args[0] = CUR_Func_read_cvt( I ); \
David Turnerd2b1f351999-12-16 23:11:37 +00003043 }
3044
3045
3046#define DO_WCVTP \
3047 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00003048 FT_ULong I = (FT_ULong)args[0]; \
David Turnerd2b1f351999-12-16 23:11:37 +00003049 \
3050 \
3051 if ( BOUNDS( I, CUR.cvtSize ) ) \
3052 { \
3053 if ( CUR.pedantic_hinting ) \
3054 { \
3055 ARRAY_BOUND_ERROR; \
3056 } \
3057 } \
3058 else \
3059 CUR_Func_write_cvt( I, args[1] ); \
3060 }
3061
3062
3063#define DO_WCVTF \
3064 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00003065 FT_ULong I = (FT_ULong)args[0]; \
David Turnerd2b1f351999-12-16 23:11:37 +00003066 \
3067 \
3068 if ( BOUNDS( I, CUR.cvtSize ) ) \
3069 { \
3070 if ( CUR.pedantic_hinting ) \
3071 { \
3072 ARRAY_BOUND_ERROR; \
3073 } \
3074 } \
3075 else \
3076 CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \
3077 }
3078
3079
3080#define DO_DEBUG \
3081 CUR.error = TT_Err_Debug_OpCode;
3082
3083
3084#define DO_ROUND \
3085 args[0] = CUR_Func_round( \
3086 args[0], \
3087 CUR.tt_metrics.compensations[CUR.opcode - 0x68] );
3088
3089
3090#define DO_NROUND \
3091 args[0] = ROUND_None( args[0], \
3092 CUR.tt_metrics.compensations[CUR.opcode - 0x6C] );
3093
3094
3095#define DO_MAX \
3096 if ( args[1] > args[0] ) \
3097 args[0] = args[1];
3098
3099
3100#define DO_MIN \
3101 if ( args[1] < args[0] ) \
3102 args[0] = args[1];
3103
3104
3105#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
3106
3107
3108#undef ARRAY_BOUND_ERROR
Werner Lemberg78575dc2000-06-12 19:36:41 +00003109#define ARRAY_BOUND_ERROR \
3110 { \
3111 CUR.error = TT_Err_Invalid_Reference; \
3112 return; \
3113 }
David Turnerd2b1f351999-12-16 23:11:37 +00003114
3115
3116 /*************************************************************************/
3117 /* */
3118 /* SVTCA[a]: Set (F and P) Vectors to Coordinate Axis */
3119 /* Opcode range: 0x00-0x01 */
3120 /* Stack: --> */
3121 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003122 static void
3123 Ins_SVTCA( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003124 {
3125 DO_SVTCA
3126 }
3127
3128
3129 /*************************************************************************/
3130 /* */
3131 /* SPVTCA[a]: Set PVector to Coordinate Axis */
3132 /* Opcode range: 0x02-0x03 */
3133 /* Stack: --> */
3134 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003135 static void
3136 Ins_SPVTCA( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003137 {
3138 DO_SPVTCA
3139 }
3140
3141
3142 /*************************************************************************/
3143 /* */
3144 /* SFVTCA[a]: Set FVector to Coordinate Axis */
3145 /* Opcode range: 0x04-0x05 */
3146 /* Stack: --> */
3147 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003148 static void
3149 Ins_SFVTCA( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003150 {
3151 DO_SFVTCA
3152 }
3153
3154
3155 /*************************************************************************/
3156 /* */
3157 /* SPVTL[a]: Set PVector To Line */
3158 /* Opcode range: 0x06-0x07 */
3159 /* Stack: uint32 uint32 --> */
3160 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003161 static void
3162 Ins_SPVTL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003163 {
3164 DO_SPVTL
3165 }
3166
3167
3168 /*************************************************************************/
3169 /* */
3170 /* SFVTL[a]: Set FVector To Line */
3171 /* Opcode range: 0x08-0x09 */
3172 /* Stack: uint32 uint32 --> */
3173 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003174 static void
3175 Ins_SFVTL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003176 {
3177 DO_SFVTL
3178 }
3179
3180
3181 /*************************************************************************/
3182 /* */
3183 /* SFVTPV[]: Set FVector To PVector */
3184 /* Opcode range: 0x0E */
3185 /* Stack: --> */
3186 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003187 static void
3188 Ins_SFVTPV( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003189 {
3190 DO_SFVTPV
3191 }
3192
3193
3194 /*************************************************************************/
3195 /* */
3196 /* SPVFS[]: Set PVector From Stack */
3197 /* Opcode range: 0x0A */
3198 /* Stack: f2.14 f2.14 --> */
3199 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003200 static void
3201 Ins_SPVFS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003202 {
3203 DO_SPVFS
3204 }
3205
3206
3207 /*************************************************************************/
3208 /* */
3209 /* SFVFS[]: Set FVector From Stack */
3210 /* Opcode range: 0x0B */
3211 /* Stack: f2.14 f2.14 --> */
3212 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003213 static void
3214 Ins_SFVFS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003215 {
3216 DO_SFVFS
3217 }
3218
3219
3220 /*************************************************************************/
3221 /* */
3222 /* GPV[]: Get Projection Vector */
3223 /* Opcode range: 0x0C */
3224 /* Stack: ef2.14 --> ef2.14 */
3225 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003226 static void
3227 Ins_GPV( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003228 {
3229 DO_GPV
3230 }
3231
3232
3233 /*************************************************************************/
3234 /* GFV[]: Get Freedom Vector */
3235 /* Opcode range: 0x0D */
3236 /* Stack: ef2.14 --> ef2.14 */
3237 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003238 static void
3239 Ins_GFV( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003240 {
3241 DO_GFV
3242 }
3243
3244
3245 /*************************************************************************/
3246 /* */
3247 /* SRP0[]: Set Reference Point 0 */
3248 /* Opcode range: 0x10 */
3249 /* Stack: uint32 --> */
3250 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003251 static void
3252 Ins_SRP0( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003253 {
3254 DO_SRP0
3255 }
3256
3257
3258 /*************************************************************************/
3259 /* */
3260 /* SRP1[]: Set Reference Point 1 */
3261 /* Opcode range: 0x11 */
3262 /* Stack: uint32 --> */
3263 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003264 static void
3265 Ins_SRP1( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003266 {
3267 DO_SRP1
3268 }
3269
3270
3271 /*************************************************************************/
3272 /* */
3273 /* SRP2[]: Set Reference Point 2 */
3274 /* Opcode range: 0x12 */
3275 /* Stack: uint32 --> */
3276 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003277 static void
3278 Ins_SRP2( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003279 {
3280 DO_SRP2
3281 }
3282
3283
3284 /*************************************************************************/
3285 /* */
3286 /* RTHG[]: Round To Half Grid */
3287 /* Opcode range: 0x19 */
3288 /* Stack: --> */
3289 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003290 static void
3291 Ins_RTHG( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003292 {
3293 DO_RTHG
3294 }
3295
3296
3297 /*************************************************************************/
3298 /* */
3299 /* RTG[]: Round To Grid */
3300 /* Opcode range: 0x18 */
3301 /* Stack: --> */
3302 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003303 static void
3304 Ins_RTG( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003305 {
3306 DO_RTG
3307 }
3308
3309
3310 /*************************************************************************/
3311 /* RTDG[]: Round To Double Grid */
3312 /* Opcode range: 0x3D */
3313 /* Stack: --> */
3314 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003315 static void
3316 Ins_RTDG( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003317 {
3318 DO_RTDG
3319 }
3320
3321
3322 /*************************************************************************/
3323 /* RUTG[]: Round Up To Grid */
3324 /* Opcode range: 0x7C */
3325 /* Stack: --> */
3326 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003327 static void
3328 Ins_RUTG( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003329 {
3330 DO_RUTG
3331 }
3332
3333
3334 /*************************************************************************/
3335 /* */
3336 /* RDTG[]: Round Down To Grid */
3337 /* Opcode range: 0x7D */
3338 /* Stack: --> */
3339 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003340 static void
3341 Ins_RDTG( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003342 {
3343 DO_RDTG
3344 }
3345
3346
3347 /*************************************************************************/
3348 /* */
3349 /* ROFF[]: Round OFF */
3350 /* Opcode range: 0x7A */
3351 /* Stack: --> */
3352 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003353 static void
3354 Ins_ROFF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003355 {
3356 DO_ROFF
3357 }
3358
3359
3360 /*************************************************************************/
3361 /* */
3362 /* SROUND[]: Super ROUND */
3363 /* Opcode range: 0x76 */
3364 /* Stack: Eint8 --> */
3365 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003366 static void
3367 Ins_SROUND( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003368 {
3369 DO_SROUND
3370 }
3371
3372
3373 /*************************************************************************/
3374 /* */
3375 /* S45ROUND[]: Super ROUND 45 degrees */
3376 /* Opcode range: 0x77 */
3377 /* Stack: uint32 --> */
3378 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003379 static void
3380 Ins_S45ROUND( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003381 {
3382 DO_S45ROUND
3383 }
3384
3385
3386 /*************************************************************************/
3387 /* */
3388 /* SLOOP[]: Set LOOP variable */
3389 /* Opcode range: 0x17 */
3390 /* Stack: int32? --> */
3391 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003392 static void
3393 Ins_SLOOP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003394 {
3395 DO_SLOOP
3396 }
3397
3398
3399 /*************************************************************************/
3400 /* */
3401 /* SMD[]: Set Minimum Distance */
3402 /* Opcode range: 0x1A */
3403 /* Stack: f26.6 --> */
3404 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003405 static void
3406 Ins_SMD( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003407 {
3408 DO_SMD
3409 }
3410
3411
3412 /*************************************************************************/
3413 /* */
3414 /* SCVTCI[]: Set Control Value Table Cut In */
3415 /* Opcode range: 0x1D */
3416 /* Stack: f26.6 --> */
3417 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003418 static void
3419 Ins_SCVTCI( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003420 {
3421 DO_SCVTCI
3422 }
3423
3424
3425 /*************************************************************************/
3426 /* */
3427 /* SSWCI[]: Set Single Width Cut In */
3428 /* Opcode range: 0x1E */
3429 /* Stack: f26.6 --> */
3430 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003431 static void
3432 Ins_SSWCI( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003433 {
3434 DO_SSWCI
3435 }
3436
3437
3438 /*************************************************************************/
3439 /* */
3440 /* SSW[]: Set Single Width */
3441 /* Opcode range: 0x1F */
3442 /* Stack: int32? --> */
3443 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003444 static void
3445 Ins_SSW( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003446 {
3447 DO_SSW
3448 }
3449
3450
3451 /*************************************************************************/
3452 /* */
3453 /* FLIPON[]: Set auto-FLIP to ON */
3454 /* Opcode range: 0x4D */
3455 /* Stack: --> */
3456 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003457 static void
3458 Ins_FLIPON( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003459 {
3460 DO_FLIPON
3461 }
3462
3463
3464 /*************************************************************************/
3465 /* */
3466 /* FLIPOFF[]: Set auto-FLIP to OFF */
3467 /* Opcode range: 0x4E */
3468 /* Stack: --> */
3469 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003470 static void
3471 Ins_FLIPOFF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003472 {
3473 DO_FLIPOFF
3474 }
3475
3476
3477 /*************************************************************************/
3478 /* */
3479 /* SANGW[]: Set ANGle Weight */
3480 /* Opcode range: 0x7E */
3481 /* Stack: uint32 --> */
3482 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003483 static void
3484 Ins_SANGW( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003485 {
3486 /* instruction not supported anymore */
3487 }
3488
3489
3490 /*************************************************************************/
3491 /* */
3492 /* SDB[]: Set Delta Base */
3493 /* Opcode range: 0x5E */
3494 /* Stack: uint32 --> */
3495 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003496 static void
3497 Ins_SDB( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003498 {
3499 DO_SDB
3500 }
3501
3502
3503 /*************************************************************************/
3504 /* */
3505 /* SDS[]: Set Delta Shift */
3506 /* Opcode range: 0x5F */
3507 /* Stack: uint32 --> */
3508 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003509 static void
3510 Ins_SDS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003511 {
3512 DO_SDS
3513 }
3514
3515
3516 /*************************************************************************/
3517 /* */
3518 /* MPPEM[]: Measure Pixel Per EM */
3519 /* Opcode range: 0x4B */
3520 /* Stack: --> Euint16 */
3521 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003522 static void
3523 Ins_MPPEM( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003524 {
3525 DO_MPPEM
3526 }
3527
3528
3529 /*************************************************************************/
3530 /* */
3531 /* MPS[]: Measure Point Size */
3532 /* Opcode range: 0x4C */
3533 /* Stack: --> Euint16 */
3534 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003535 static void
3536 Ins_MPS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003537 {
3538 DO_MPS
3539 }
3540
3541
3542 /*************************************************************************/
3543 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00003544 /* DUP[]: DUPlicate the top stack's element */
David Turnerd2b1f351999-12-16 23:11:37 +00003545 /* Opcode range: 0x20 */
3546 /* Stack: StkElt --> StkElt StkElt */
3547 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003548 static void
3549 Ins_DUP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003550 {
3551 DO_DUP
3552 }
3553
3554
3555 /*************************************************************************/
3556 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00003557 /* POP[]: POP the stack's top element */
David Turnerd2b1f351999-12-16 23:11:37 +00003558 /* Opcode range: 0x21 */
3559 /* Stack: StkElt --> */
3560 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003561 static void
3562 Ins_POP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003563 {
3564 /* nothing to do */
3565 }
3566
3567
3568 /*************************************************************************/
3569 /* */
3570 /* CLEAR[]: CLEAR the entire stack */
3571 /* Opcode range: 0x22 */
3572 /* Stack: StkElt... --> */
3573 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003574 static void
3575 Ins_CLEAR( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003576 {
3577 DO_CLEAR
3578 }
3579
3580
3581 /*************************************************************************/
3582 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00003583 /* SWAP[]: SWAP the stack's top two elements */
David Turnerd2b1f351999-12-16 23:11:37 +00003584 /* Opcode range: 0x23 */
3585 /* Stack: 2 * StkElt --> 2 * StkElt */
3586 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003587 static void
3588 Ins_SWAP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003589 {
3590 DO_SWAP
3591 }
3592
3593
3594 /*************************************************************************/
3595 /* */
3596 /* DEPTH[]: return the stack DEPTH */
3597 /* Opcode range: 0x24 */
3598 /* Stack: --> uint32 */
3599 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003600 static void
3601 Ins_DEPTH( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003602 {
3603 DO_DEPTH
3604 }
3605
3606
3607 /*************************************************************************/
3608 /* */
3609 /* CINDEX[]: Copy INDEXed element */
3610 /* Opcode range: 0x25 */
3611 /* Stack: int32 --> StkElt */
3612 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003613 static void
3614 Ins_CINDEX( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003615 {
3616 DO_CINDEX
3617 }
3618
3619
3620 /*************************************************************************/
3621 /* */
3622 /* EIF[]: End IF */
3623 /* Opcode range: 0x59 */
3624 /* Stack: --> */
3625 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003626 static void
3627 Ins_EIF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003628 {
3629 /* nothing to do */
3630 }
3631
3632
3633 /*************************************************************************/
3634 /* */
3635 /* JROT[]: Jump Relative On True */
3636 /* Opcode range: 0x78 */
3637 /* Stack: StkElt int32 --> */
3638 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003639 static void
3640 Ins_JROT( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003641 {
3642 DO_JROT
3643 }
3644
3645
3646 /*************************************************************************/
3647 /* */
3648 /* JMPR[]: JuMP Relative */
3649 /* Opcode range: 0x1C */
3650 /* Stack: int32 --> */
3651 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003652 static void
3653 Ins_JMPR( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003654 {
3655 DO_JMPR
3656 }
3657
3658
3659 /*************************************************************************/
3660 /* */
3661 /* JROF[]: Jump Relative On False */
3662 /* Opcode range: 0x79 */
3663 /* Stack: StkElt int32 --> */
3664 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003665 static void
3666 Ins_JROF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003667 {
3668 DO_JROF
3669 }
3670
3671
3672 /*************************************************************************/
3673 /* */
3674 /* LT[]: Less Than */
3675 /* Opcode range: 0x50 */
3676 /* Stack: int32? int32? --> bool */
3677 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003678 static void
3679 Ins_LT( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003680 {
3681 DO_LT
3682 }
3683
3684
3685 /*************************************************************************/
3686 /* */
3687 /* LTEQ[]: Less Than or EQual */
3688 /* Opcode range: 0x51 */
3689 /* Stack: int32? int32? --> bool */
3690 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003691 static void
3692 Ins_LTEQ( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003693 {
3694 DO_LTEQ
3695 }
3696
3697
3698 /*************************************************************************/
3699 /* */
3700 /* GT[]: Greater Than */
3701 /* Opcode range: 0x52 */
3702 /* Stack: int32? int32? --> bool */
3703 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003704 static void
3705 Ins_GT( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003706 {
3707 DO_GT
3708 }
3709
3710
3711 /*************************************************************************/
3712 /* */
3713 /* GTEQ[]: Greater Than or EQual */
3714 /* Opcode range: 0x53 */
3715 /* Stack: int32? int32? --> bool */
3716 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003717 static void
3718 Ins_GTEQ( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003719 {
3720 DO_GTEQ
3721 }
3722
3723
3724 /*************************************************************************/
3725 /* */
3726 /* EQ[]: EQual */
3727 /* Opcode range: 0x54 */
3728 /* Stack: StkElt StkElt --> bool */
3729 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003730 static void
3731 Ins_EQ( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003732 {
3733 DO_EQ
3734 }
3735
3736
3737 /*************************************************************************/
3738 /* */
3739 /* NEQ[]: Not EQual */
3740 /* Opcode range: 0x55 */
3741 /* Stack: StkElt StkElt --> bool */
3742 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003743 static void
3744 Ins_NEQ( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003745 {
3746 DO_NEQ
3747 }
3748
3749
3750 /*************************************************************************/
3751 /* */
3752 /* ODD[]: Is ODD */
3753 /* Opcode range: 0x56 */
3754 /* Stack: f26.6 --> bool */
3755 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003756 static void
3757 Ins_ODD( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003758 {
3759 DO_ODD
3760 }
3761
3762
3763 /*************************************************************************/
3764 /* */
3765 /* EVEN[]: Is EVEN */
3766 /* Opcode range: 0x57 */
3767 /* Stack: f26.6 --> bool */
3768 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003769 static void
3770 Ins_EVEN( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003771 {
3772 DO_EVEN
3773 }
3774
3775
3776 /*************************************************************************/
3777 /* */
3778 /* AND[]: logical AND */
3779 /* Opcode range: 0x5A */
3780 /* Stack: uint32 uint32 --> uint32 */
3781 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003782 static void
3783 Ins_AND( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003784 {
3785 DO_AND
3786 }
3787
3788
3789 /*************************************************************************/
3790 /* */
3791 /* OR[]: logical OR */
3792 /* Opcode range: 0x5B */
3793 /* Stack: uint32 uint32 --> uint32 */
3794 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003795 static void
3796 Ins_OR( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003797 {
3798 DO_OR
3799 }
3800
3801
3802 /*************************************************************************/
3803 /* */
3804 /* NOT[]: logical NOT */
3805 /* Opcode range: 0x5C */
3806 /* Stack: StkElt --> uint32 */
3807 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003808 static void
3809 Ins_NOT( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003810 {
3811 DO_NOT
3812 }
3813
3814
3815 /*************************************************************************/
3816 /* */
3817 /* ADD[]: ADD */
3818 /* Opcode range: 0x60 */
3819 /* Stack: f26.6 f26.6 --> f26.6 */
3820 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003821 static void
3822 Ins_ADD( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003823 {
3824 DO_ADD
3825 }
3826
3827
3828 /*************************************************************************/
3829 /* */
3830 /* SUB[]: SUBtract */
3831 /* Opcode range: 0x61 */
3832 /* Stack: f26.6 f26.6 --> f26.6 */
3833 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003834 static void
3835 Ins_SUB( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003836 {
3837 DO_SUB
3838 }
3839
3840
3841 /*************************************************************************/
3842 /* */
3843 /* DIV[]: DIVide */
3844 /* Opcode range: 0x62 */
3845 /* Stack: f26.6 f26.6 --> f26.6 */
3846 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003847 static void
3848 Ins_DIV( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003849 {
3850 DO_DIV
3851 }
3852
3853
3854 /*************************************************************************/
3855 /* */
3856 /* MUL[]: MULtiply */
3857 /* Opcode range: 0x63 */
3858 /* Stack: f26.6 f26.6 --> f26.6 */
3859 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003860 static void
3861 Ins_MUL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003862 {
3863 DO_MUL
3864 }
3865
3866
3867 /*************************************************************************/
3868 /* */
3869 /* ABS[]: ABSolute value */
3870 /* Opcode range: 0x64 */
3871 /* Stack: f26.6 --> f26.6 */
3872 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003873 static void
3874 Ins_ABS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003875 {
3876 DO_ABS
3877 }
3878
3879
3880 /*************************************************************************/
3881 /* */
3882 /* NEG[]: NEGate */
3883 /* Opcode range: 0x65 */
3884 /* Stack: f26.6 --> f26.6 */
3885 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003886 static void
3887 Ins_NEG( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003888 {
3889 DO_NEG
3890 }
3891
3892
3893 /*************************************************************************/
3894 /* */
3895 /* FLOOR[]: FLOOR */
3896 /* Opcode range: 0x66 */
3897 /* Stack: f26.6 --> f26.6 */
3898 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003899 static void
3900 Ins_FLOOR( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003901 {
3902 DO_FLOOR
3903 }
3904
3905
3906 /*************************************************************************/
3907 /* */
3908 /* CEILING[]: CEILING */
3909 /* Opcode range: 0x67 */
3910 /* Stack: f26.6 --> f26.6 */
3911 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003912 static void
3913 Ins_CEILING( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003914 {
3915 DO_CEILING
3916 }
3917
3918
3919 /*************************************************************************/
3920 /* */
3921 /* RS[]: Read Store */
3922 /* Opcode range: 0x43 */
3923 /* Stack: uint32 --> uint32 */
3924 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003925 static void
3926 Ins_RS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003927 {
3928 DO_RS
3929 }
3930
3931
3932 /*************************************************************************/
3933 /* */
3934 /* WS[]: Write Store */
3935 /* Opcode range: 0x42 */
3936 /* Stack: uint32 uint32 --> */
3937 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003938 static void
3939 Ins_WS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003940 {
3941 DO_WS
3942 }
3943
3944
3945 /*************************************************************************/
3946 /* */
3947 /* WCVTP[]: Write CVT in Pixel units */
3948 /* Opcode range: 0x44 */
3949 /* Stack: f26.6 uint32 --> */
3950 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003951 static void
3952 Ins_WCVTP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003953 {
3954 DO_WCVTP
3955 }
3956
3957
3958 /*************************************************************************/
3959 /* */
3960 /* WCVTF[]: Write CVT in Funits */
3961 /* Opcode range: 0x70 */
3962 /* Stack: uint32 uint32 --> */
3963 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003964 static void
3965 Ins_WCVTF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003966 {
3967 DO_WCVTF
3968 }
3969
3970
3971 /*************************************************************************/
3972 /* */
3973 /* RCVT[]: Read CVT */
3974 /* Opcode range: 0x45 */
3975 /* Stack: uint32 --> f26.6 */
3976 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003977 static void
3978 Ins_RCVT( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003979 {
3980 DO_RCVT
3981 }
3982
3983
3984 /*************************************************************************/
3985 /* */
3986 /* AA[]: Adjust Angle */
3987 /* Opcode range: 0x7F */
3988 /* Stack: uint32 --> */
3989 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003990 static void
3991 Ins_AA( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003992 {
Werner Lemberg5811c7c2000-07-02 13:53:16 +00003993 /* intentionally no longer supported */
David Turnerd2b1f351999-12-16 23:11:37 +00003994 }
3995
3996
3997 /*************************************************************************/
3998 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00003999 /* DEBUG[]: DEBUG. Unsupported. */
David Turnerd2b1f351999-12-16 23:11:37 +00004000 /* Opcode range: 0x4F */
4001 /* Stack: uint32 --> */
4002 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004003 /* Note: The original instruction pops a value from the stack. */
David Turnerd2b1f351999-12-16 23:11:37 +00004004 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004005 static void
4006 Ins_DEBUG( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004007 {
4008 DO_DEBUG
4009 }
4010
4011
4012 /*************************************************************************/
4013 /* */
4014 /* ROUND[ab]: ROUND value */
4015 /* Opcode range: 0x68-0x6B */
4016 /* Stack: f26.6 --> f26.6 */
4017 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004018 static void
4019 Ins_ROUND( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004020 {
4021 DO_ROUND
4022 }
4023
4024
4025 /*************************************************************************/
4026 /* */
4027 /* NROUND[ab]: No ROUNDing of value */
4028 /* Opcode range: 0x6C-0x6F */
4029 /* Stack: f26.6 --> f26.6 */
4030 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004031 static void
4032 Ins_NROUND( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004033 {
4034 DO_NROUND
4035 }
4036
4037
4038 /*************************************************************************/
4039 /* */
4040 /* MAX[]: MAXimum */
4041 /* Opcode range: 0x68 */
4042 /* Stack: int32? int32? --> int32 */
4043 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004044 static void
4045 Ins_MAX( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004046 {
4047 DO_MAX
4048 }
4049
4050
4051 /*************************************************************************/
4052 /* */
4053 /* MIN[]: MINimum */
4054 /* Opcode range: 0x69 */
4055 /* Stack: int32? int32? --> int32 */
4056 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004057 static void
4058 Ins_MIN( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004059 {
4060 DO_MIN
4061 }
4062
4063
4064#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
4065
4066
4067 /*************************************************************************/
4068 /* */
4069 /* The following functions are called as is within the switch statement. */
4070 /* */
4071 /*************************************************************************/
4072
4073
4074 /*************************************************************************/
4075 /* */
4076 /* MINDEX[]: Move INDEXed element */
4077 /* Opcode range: 0x26 */
4078 /* Stack: int32? --> StkElt */
4079 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004080 static void
4081 Ins_MINDEX( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004082 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004083 FT_Long L, K;
David Turnerd2b1f351999-12-16 23:11:37 +00004084
4085
4086 L = args[0];
4087
4088 if ( L <= 0 || L > CUR.args )
4089 {
4090 CUR.error = TT_Err_Invalid_Reference;
4091 return;
4092 }
4093
4094 K = CUR.stack[CUR.args - L];
4095
David Turner4632fcc2004-01-15 19:07:44 +00004096 FT_ARRAY_MOVE( &CUR.stack[CUR.args - L ],
4097 &CUR.stack[CUR.args - L + 1],
4098 ( L - 1 ) );
David Turnerd2b1f351999-12-16 23:11:37 +00004099
4100 CUR.stack[CUR.args - 1] = K;
4101 }
4102
4103
4104 /*************************************************************************/
4105 /* */
4106 /* ROLL[]: ROLL top three elements */
4107 /* Opcode range: 0x8A */
4108 /* Stack: 3 * StkElt --> 3 * StkElt */
4109 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004110 static void
4111 Ins_ROLL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004112 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004113 FT_Long A, B, C;
David Turnerd2b1f351999-12-16 23:11:37 +00004114
David Turnerc6a92202000-07-04 18:12:13 +00004115 FT_UNUSED_EXEC;
David Turnerd2b1f351999-12-16 23:11:37 +00004116
Werner Lemberg78575dc2000-06-12 19:36:41 +00004117
David Turnerd2b1f351999-12-16 23:11:37 +00004118 A = args[2];
4119 B = args[1];
4120 C = args[0];
4121
4122 args[2] = C;
4123 args[1] = A;
4124 args[0] = B;
4125 }
4126
4127
4128 /*************************************************************************/
4129 /* */
4130 /* MANAGING THE FLOW OF CONTROL */
4131 /* */
Werner Lemberg5811c7c2000-07-02 13:53:16 +00004132 /* Instructions appear in the specification's order. */
David Turnerd2b1f351999-12-16 23:11:37 +00004133 /* */
4134 /*************************************************************************/
4135
4136
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004137 static FT_Bool
4138 SkipCode( EXEC_OP )
David Turnerd2b1f351999-12-16 23:11:37 +00004139 {
4140 CUR.IP += CUR.length;
4141
4142 if ( CUR.IP < CUR.codeSize )
4143 {
4144 CUR.opcode = CUR.code[CUR.IP];
4145
4146 CUR.length = opcode_length[CUR.opcode];
4147 if ( CUR.length < 0 )
4148 {
4149 if ( CUR.IP + 1 > CUR.codeSize )
4150 goto Fail_Overflow;
Werner Lemberg33febc02004-10-09 07:07:43 +00004151 CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
David Turnerd2b1f351999-12-16 23:11:37 +00004152 }
4153
4154 if ( CUR.IP + CUR.length <= CUR.codeSize )
4155 return SUCCESS;
4156 }
4157
4158 Fail_Overflow:
4159 CUR.error = TT_Err_Code_Overflow;
4160 return FAILURE;
4161 }
4162
4163
4164 /*************************************************************************/
4165 /* */
4166 /* IF[]: IF test */
4167 /* Opcode range: 0x58 */
4168 /* Stack: StkElt --> */
4169 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004170 static void
4171 Ins_IF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004172 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004173 FT_Int nIfs;
4174 FT_Bool Out;
David Turnerd2b1f351999-12-16 23:11:37 +00004175
4176
4177 if ( args[0] != 0 )
4178 return;
4179
4180 nIfs = 1;
4181 Out = 0;
4182
4183 do
4184 {
4185 if ( SKIP_Code() == FAILURE )
4186 return;
4187
4188 switch ( CUR.opcode )
4189 {
4190 case 0x58: /* IF */
4191 nIfs++;
4192 break;
4193
4194 case 0x1B: /* ELSE */
David Turner3b7049f2001-07-07 16:12:14 +00004195 Out = FT_BOOL( nIfs == 1 );
David Turnerd2b1f351999-12-16 23:11:37 +00004196 break;
4197
4198 case 0x59: /* EIF */
4199 nIfs--;
David Turner3b7049f2001-07-07 16:12:14 +00004200 Out = FT_BOOL( nIfs == 0 );
David Turnerd2b1f351999-12-16 23:11:37 +00004201 break;
4202 }
4203 } while ( Out == 0 );
4204 }
4205
4206
4207 /*************************************************************************/
4208 /* */
4209 /* ELSE[]: ELSE */
4210 /* Opcode range: 0x1B */
4211 /* Stack: --> */
4212 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004213 static void
4214 Ins_ELSE( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004215 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004216 FT_Int nIfs;
David Turnerd2b1f351999-12-16 23:11:37 +00004217
David Turnerc6a92202000-07-04 18:12:13 +00004218 FT_UNUSED_ARG;
David Turnerd2b1f351999-12-16 23:11:37 +00004219
Werner Lemberg78575dc2000-06-12 19:36:41 +00004220
David Turnerd2b1f351999-12-16 23:11:37 +00004221 nIfs = 1;
4222
4223 do
4224 {
4225 if ( SKIP_Code() == FAILURE )
4226 return;
4227
4228 switch ( CUR.opcode )
4229 {
4230 case 0x58: /* IF */
4231 nIfs++;
4232 break;
4233
4234 case 0x59: /* EIF */
4235 nIfs--;
4236 break;
4237 }
4238 } while ( nIfs != 0 );
4239 }
4240
4241
4242 /*************************************************************************/
4243 /* */
4244 /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS */
4245 /* */
Werner Lemberg5811c7c2000-07-02 13:53:16 +00004246 /* Instructions appear in the specification's order. */
David Turnerd2b1f351999-12-16 23:11:37 +00004247 /* */
4248 /*************************************************************************/
4249
4250
4251 /*************************************************************************/
4252 /* */
4253 /* FDEF[]: Function DEFinition */
4254 /* Opcode range: 0x2C */
4255 /* Stack: uint32 --> */
4256 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004257 static void
4258 Ins_FDEF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004259 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004260 FT_ULong n;
David Turnerd2b1f351999-12-16 23:11:37 +00004261 TT_DefRecord* rec;
4262 TT_DefRecord* limit;
4263
Werner Lemberg78575dc2000-06-12 19:36:41 +00004264
David Turnerd2b1f351999-12-16 23:11:37 +00004265 /* some font programs are broken enough to redefine functions! */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004266 /* We will then parse the current table. */
4267
David Turnerd2b1f351999-12-16 23:11:37 +00004268 rec = CUR.FDefs;
4269 limit = rec + CUR.numFDefs;
4270 n = args[0];
David Turnere49ab252000-05-16 23:44:38 +00004271
David Turnerd2b1f351999-12-16 23:11:37 +00004272 for ( ; rec < limit; rec++ )
4273 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00004274 if ( rec->opc == n )
David Turnerd2b1f351999-12-16 23:11:37 +00004275 break;
4276 }
David Turnere49ab252000-05-16 23:44:38 +00004277
David Turnerd2b1f351999-12-16 23:11:37 +00004278 if ( rec == limit )
4279 {
4280 /* check that there is enough room for new functions */
4281 if ( CUR.numFDefs >= CUR.maxFDefs )
4282 {
4283 CUR.error = TT_Err_Too_Many_Function_Defs;
4284 return;
4285 }
4286 CUR.numFDefs++;
4287 }
David Turnere49ab252000-05-16 23:44:38 +00004288
David Turnerd2b1f351999-12-16 23:11:37 +00004289 rec->range = CUR.curRange;
4290 rec->opc = n;
Werner Lemberg78575dc2000-06-12 19:36:41 +00004291 rec->start = CUR.IP + 1;
David Turnerd2b1f351999-12-16 23:11:37 +00004292 rec->active = TRUE;
David Turnere49ab252000-05-16 23:44:38 +00004293
David Turnerd2b1f351999-12-16 23:11:37 +00004294 if ( n > CUR.maxFunc )
4295 CUR.maxFunc = n;
David Turnere49ab252000-05-16 23:44:38 +00004296
David Turnerd2b1f351999-12-16 23:11:37 +00004297 /* Now skip the whole function definition. */
4298 /* We don't allow nested IDEFS & FDEFs. */
4299
4300 while ( SKIP_Code() == SUCCESS )
4301 {
4302 switch ( CUR.opcode )
4303 {
4304 case 0x89: /* IDEF */
4305 case 0x2C: /* FDEF */
4306 CUR.error = TT_Err_Nested_DEFS;
4307 return;
4308
4309 case 0x2D: /* ENDF */
4310 return;
4311 }
4312 }
4313 }
4314
4315
4316 /*************************************************************************/
4317 /* */
4318 /* ENDF[]: END Function definition */
4319 /* Opcode range: 0x2D */
4320 /* Stack: --> */
4321 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004322 static void
4323 Ins_ENDF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004324 {
4325 TT_CallRec* pRec;
4326
David Turnerc6a92202000-07-04 18:12:13 +00004327 FT_UNUSED_ARG;
David Turnerd2b1f351999-12-16 23:11:37 +00004328
Werner Lemberg78575dc2000-06-12 19:36:41 +00004329
David Turnerd2b1f351999-12-16 23:11:37 +00004330 if ( CUR.callTop <= 0 ) /* We encountered an ENDF without a call */
4331 {
4332 CUR.error = TT_Err_ENDF_In_Exec_Stream;
4333 return;
4334 }
4335
4336 CUR.callTop--;
4337
4338 pRec = &CUR.callStack[CUR.callTop];
4339
4340 pRec->Cur_Count--;
4341
4342 CUR.step_ins = FALSE;
4343
4344 if ( pRec->Cur_Count > 0 )
4345 {
4346 CUR.callTop++;
4347 CUR.IP = pRec->Cur_Restart;
4348 }
4349 else
4350 /* Loop through the current function */
4351 INS_Goto_CodeRange( pRec->Caller_Range,
4352 pRec->Caller_IP );
4353
Werner Lemberg78575dc2000-06-12 19:36:41 +00004354 /* Exit the current call frame. */
David Turnerd2b1f351999-12-16 23:11:37 +00004355
Werner Lemberg6e87ed92007-01-26 22:18:56 +00004356 /* NOTE: If the last instruction of a program is a */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004357 /* CALL or LOOPCALL, the return address is */
4358 /* always out of the code range. This is a */
4359 /* valid address, and it is why we do not test */
4360 /* the result of Ins_Goto_CodeRange() here! */
David Turnerd2b1f351999-12-16 23:11:37 +00004361 }
4362
4363
4364 /*************************************************************************/
4365 /* */
4366 /* CALL[]: CALL function */
4367 /* Opcode range: 0x2B */
4368 /* Stack: uint32? --> */
4369 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004370 static void
4371 Ins_CALL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004372 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004373 FT_ULong F;
David Turnerd2b1f351999-12-16 23:11:37 +00004374 TT_CallRec* pCrec;
4375 TT_DefRecord* def;
4376
Werner Lemberg78575dc2000-06-12 19:36:41 +00004377
David Turnerd2b1f351999-12-16 23:11:37 +00004378 /* first of all, check the index */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004379
David Turnerd2b1f351999-12-16 23:11:37 +00004380 F = args[0];
Werner Lemberg78575dc2000-06-12 19:36:41 +00004381 if ( BOUNDS( F, CUR.maxFunc + 1 ) )
4382 goto Fail;
David Turnere49ab252000-05-16 23:44:38 +00004383
David Turnerd2b1f351999-12-16 23:11:37 +00004384 /* Except for some old Apple fonts, all functions in a TrueType */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004385 /* font are defined in increasing order, starting from 0. This */
David Turnerd2b1f351999-12-16 23:11:37 +00004386 /* means that we normally have */
4387 /* */
4388 /* CUR.maxFunc+1 == CUR.numFDefs */
4389 /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */
4390 /* */
4391 /* If this isn't true, we need to look up the function table. */
4392
4393 def = CUR.FDefs + F;
Werner Lemberg78575dc2000-06-12 19:36:41 +00004394 if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
David Turnerd2b1f351999-12-16 23:11:37 +00004395 {
4396 /* look up the FDefs table */
4397 TT_DefRecord* limit;
David Turnere49ab252000-05-16 23:44:38 +00004398
Werner Lemberg78575dc2000-06-12 19:36:41 +00004399
David Turnerd2b1f351999-12-16 23:11:37 +00004400 def = CUR.FDefs;
4401 limit = def + CUR.numFDefs;
David Turnere49ab252000-05-16 23:44:38 +00004402
Werner Lemberg78575dc2000-06-12 19:36:41 +00004403 while ( def < limit && def->opc != F )
David Turnerd2b1f351999-12-16 23:11:37 +00004404 def++;
David Turnere49ab252000-05-16 23:44:38 +00004405
Werner Lemberg78575dc2000-06-12 19:36:41 +00004406 if ( def == limit )
4407 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00004408 }
David Turnere49ab252000-05-16 23:44:38 +00004409
David Turnerd2b1f351999-12-16 23:11:37 +00004410 /* check that the function is active */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004411 if ( !def->active )
David Turnerd2b1f351999-12-16 23:11:37 +00004412 goto Fail;
David Turnere49ab252000-05-16 23:44:38 +00004413
David Turnerd2b1f351999-12-16 23:11:37 +00004414 /* check the call stack */
4415 if ( CUR.callTop >= CUR.callSize )
4416 {
4417 CUR.error = TT_Err_Stack_Overflow;
4418 return;
4419 }
4420
4421 pCrec = CUR.callStack + CUR.callTop;
4422
4423 pCrec->Caller_Range = CUR.curRange;
4424 pCrec->Caller_IP = CUR.IP + 1;
4425 pCrec->Cur_Count = 1;
4426 pCrec->Cur_Restart = def->start;
4427
4428 CUR.callTop++;
4429
4430 INS_Goto_CodeRange( def->range,
4431 def->start );
David Turnere49ab252000-05-16 23:44:38 +00004432
David Turnerd2b1f351999-12-16 23:11:37 +00004433 CUR.step_ins = FALSE;
4434 return;
David Turnere49ab252000-05-16 23:44:38 +00004435
David Turnerd2b1f351999-12-16 23:11:37 +00004436 Fail:
4437 CUR.error = TT_Err_Invalid_Reference;
4438 }
4439
4440
4441 /*************************************************************************/
4442 /* */
4443 /* LOOPCALL[]: LOOP and CALL function */
4444 /* Opcode range: 0x2A */
4445 /* Stack: uint32? Eint16? --> */
4446 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004447 static void
4448 Ins_LOOPCALL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004449 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004450 FT_ULong F;
David Turnerd2b1f351999-12-16 23:11:37 +00004451 TT_CallRec* pCrec;
4452 TT_DefRecord* def;
4453
Werner Lemberg78575dc2000-06-12 19:36:41 +00004454
David Turnerd2b1f351999-12-16 23:11:37 +00004455 /* first of all, check the index */
4456 F = args[1];
Werner Lemberg78575dc2000-06-12 19:36:41 +00004457 if ( BOUNDS( F, CUR.maxFunc + 1 ) )
4458 goto Fail;
David Turnere49ab252000-05-16 23:44:38 +00004459
David Turnerd2b1f351999-12-16 23:11:37 +00004460 /* Except for some old Apple fonts, all functions in a TrueType */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004461 /* font are defined in increasing order, starting from 0. This */
David Turnerd2b1f351999-12-16 23:11:37 +00004462 /* means that we normally have */
4463 /* */
4464 /* CUR.maxFunc+1 == CUR.numFDefs */
4465 /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */
4466 /* */
4467 /* If this isn't true, we need to look up the function table. */
4468
4469 def = CUR.FDefs + F;
Werner Lemberg78575dc2000-06-12 19:36:41 +00004470 if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
David Turnerd2b1f351999-12-16 23:11:37 +00004471 {
4472 /* look up the FDefs table */
4473 TT_DefRecord* limit;
David Turnere49ab252000-05-16 23:44:38 +00004474
Werner Lemberg78575dc2000-06-12 19:36:41 +00004475
David Turnerd2b1f351999-12-16 23:11:37 +00004476 def = CUR.FDefs;
4477 limit = def + CUR.numFDefs;
David Turnere49ab252000-05-16 23:44:38 +00004478
Werner Lemberg78575dc2000-06-12 19:36:41 +00004479 while ( def < limit && def->opc != F )
David Turnerd2b1f351999-12-16 23:11:37 +00004480 def++;
David Turnere49ab252000-05-16 23:44:38 +00004481
Werner Lemberg78575dc2000-06-12 19:36:41 +00004482 if ( def == limit )
4483 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00004484 }
David Turnere49ab252000-05-16 23:44:38 +00004485
David Turnerd2b1f351999-12-16 23:11:37 +00004486 /* check that the function is active */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004487 if ( !def->active )
David Turnerd2b1f351999-12-16 23:11:37 +00004488 goto Fail;
4489
David Turnere49ab252000-05-16 23:44:38 +00004490 /* check stack */
David Turnerd2b1f351999-12-16 23:11:37 +00004491 if ( CUR.callTop >= CUR.callSize )
4492 {
4493 CUR.error = TT_Err_Stack_Overflow;
4494 return;
4495 }
4496
4497 if ( args[0] > 0 )
4498 {
4499 pCrec = CUR.callStack + CUR.callTop;
4500
4501 pCrec->Caller_Range = CUR.curRange;
4502 pCrec->Caller_IP = CUR.IP + 1;
David Turnerf9b8dec2000-06-16 19:34:52 +00004503 pCrec->Cur_Count = (FT_Int)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00004504 pCrec->Cur_Restart = def->start;
4505
4506 CUR.callTop++;
4507
4508 INS_Goto_CodeRange( def->range, def->start );
4509
4510 CUR.step_ins = FALSE;
4511 }
4512 return;
4513
4514 Fail:
4515 CUR.error = TT_Err_Invalid_Reference;
4516 }
4517
4518
4519 /*************************************************************************/
4520 /* */
4521 /* IDEF[]: Instruction DEFinition */
4522 /* Opcode range: 0x89 */
4523 /* Stack: Eint8 --> */
4524 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004525 static void
4526 Ins_IDEF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004527 {
4528 TT_DefRecord* def;
4529 TT_DefRecord* limit;
4530
Werner Lemberg78575dc2000-06-12 19:36:41 +00004531
David Turnerd2b1f351999-12-16 23:11:37 +00004532 /* First of all, look for the same function in our table */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004533
David Turnerd2b1f351999-12-16 23:11:37 +00004534 def = CUR.IDefs;
4535 limit = def + CUR.numIDefs;
Werner Lemberg78575dc2000-06-12 19:36:41 +00004536
David Turnerd2b1f351999-12-16 23:11:37 +00004537 for ( ; def < limit; def++ )
David Turnerf9b8dec2000-06-16 19:34:52 +00004538 if ( def->opc == (FT_ULong)args[0] )
David Turnerd2b1f351999-12-16 23:11:37 +00004539 break;
David Turnere49ab252000-05-16 23:44:38 +00004540
David Turnerd2b1f351999-12-16 23:11:37 +00004541 if ( def == limit )
4542 {
4543 /* check that there is enough room for a new instruction */
4544 if ( CUR.numIDefs >= CUR.maxIDefs )
4545 {
4546 CUR.error = TT_Err_Too_Many_Instruction_Defs;
4547 return;
4548 }
4549 CUR.numIDefs++;
4550 }
David Turnere49ab252000-05-16 23:44:38 +00004551
David Turnerd2b1f351999-12-16 23:11:37 +00004552 def->opc = args[0];
4553 def->start = CUR.IP+1;
4554 def->range = CUR.curRange;
4555 def->active = TRUE;
David Turnere49ab252000-05-16 23:44:38 +00004556
David Turnerf9b8dec2000-06-16 19:34:52 +00004557 if ( (FT_ULong)args[0] > CUR.maxIns )
David Turnerd2b1f351999-12-16 23:11:37 +00004558 CUR.maxIns = args[0];
David Turnere49ab252000-05-16 23:44:38 +00004559
David Turnerd2b1f351999-12-16 23:11:37 +00004560 /* Now skip the whole function definition. */
4561 /* We don't allow nested IDEFs & FDEFs. */
4562
4563 while ( SKIP_Code() == SUCCESS )
4564 {
4565 switch ( CUR.opcode )
4566 {
4567 case 0x89: /* IDEF */
4568 case 0x2C: /* FDEF */
4569 CUR.error = TT_Err_Nested_DEFS;
4570 return;
4571 case 0x2D: /* ENDF */
4572 return;
4573 }
4574 }
4575 }
4576
4577
4578 /*************************************************************************/
4579 /* */
4580 /* PUSHING DATA ONTO THE INTERPRETER STACK */
4581 /* */
Werner Lemberg5811c7c2000-07-02 13:53:16 +00004582 /* Instructions appear in the specification's order. */
David Turnerd2b1f351999-12-16 23:11:37 +00004583 /* */
4584 /*************************************************************************/
4585
4586
4587 /*************************************************************************/
4588 /* */
4589 /* NPUSHB[]: PUSH N Bytes */
4590 /* Opcode range: 0x40 */
4591 /* Stack: --> uint32... */
4592 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004593 static void
4594 Ins_NPUSHB( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004595 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004596 FT_UShort L, K;
David Turnerd2b1f351999-12-16 23:11:37 +00004597
4598
David Turnerf9b8dec2000-06-16 19:34:52 +00004599 L = (FT_UShort)CUR.code[CUR.IP + 1];
David Turnerd2b1f351999-12-16 23:11:37 +00004600
4601 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
4602 {
4603 CUR.error = TT_Err_Stack_Overflow;
4604 return;
4605 }
4606
4607 for ( K = 1; K <= L; K++ )
4608 args[K - 1] = CUR.code[CUR.IP + K + 1];
4609
4610 CUR.new_top += L;
4611 }
4612
4613
4614 /*************************************************************************/
4615 /* */
4616 /* NPUSHW[]: PUSH N Words */
4617 /* Opcode range: 0x41 */
4618 /* Stack: --> int32... */
4619 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004620 static void
4621 Ins_NPUSHW( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004622 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004623 FT_UShort L, K;
David Turnerd2b1f351999-12-16 23:11:37 +00004624
4625
David Turnerf9b8dec2000-06-16 19:34:52 +00004626 L = (FT_UShort)CUR.code[CUR.IP + 1];
David Turnerd2b1f351999-12-16 23:11:37 +00004627
4628 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
4629 {
4630 CUR.error = TT_Err_Stack_Overflow;
4631 return;
4632 }
4633
4634 CUR.IP += 2;
4635
4636 for ( K = 0; K < L; K++ )
4637 args[K] = GET_ShortIns();
4638
4639 CUR.step_ins = FALSE;
4640 CUR.new_top += L;
4641 }
4642
4643
4644 /*************************************************************************/
4645 /* */
4646 /* PUSHB[abc]: PUSH Bytes */
4647 /* Opcode range: 0xB0-0xB7 */
4648 /* Stack: --> uint32... */
4649 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004650 static void
4651 Ins_PUSHB( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004652 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004653 FT_UShort L, K;
David Turnerd2b1f351999-12-16 23:11:37 +00004654
4655
Werner Lembergc9f6c662007-03-21 13:30:14 +00004656 L = (FT_UShort)( CUR.opcode - 0xB0 + 1 );
David Turnerd2b1f351999-12-16 23:11:37 +00004657
4658 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
4659 {
4660 CUR.error = TT_Err_Stack_Overflow;
4661 return;
4662 }
4663
4664 for ( K = 1; K <= L; K++ )
4665 args[K - 1] = CUR.code[CUR.IP + K];
4666 }
4667
4668
4669 /*************************************************************************/
4670 /* */
4671 /* PUSHW[abc]: PUSH Words */
4672 /* Opcode range: 0xB8-0xBF */
4673 /* Stack: --> int32... */
4674 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004675 static void
4676 Ins_PUSHW( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004677 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004678 FT_UShort L, K;
David Turnerd2b1f351999-12-16 23:11:37 +00004679
4680
Werner Lembergc9f6c662007-03-21 13:30:14 +00004681 L = (FT_UShort)( CUR.opcode - 0xB8 + 1 );
David Turnerd2b1f351999-12-16 23:11:37 +00004682
4683 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
4684 {
4685 CUR.error = TT_Err_Stack_Overflow;
4686 return;
4687 }
4688
4689 CUR.IP++;
4690
4691 for ( K = 0; K < L; K++ )
4692 args[K] = GET_ShortIns();
4693
4694 CUR.step_ins = FALSE;
4695 }
4696
4697
4698 /*************************************************************************/
4699 /* */
4700 /* MANAGING THE GRAPHICS STATE */
4701 /* */
4702 /* Instructions appear in the specs' order. */
4703 /* */
4704 /*************************************************************************/
4705
4706
4707 /*************************************************************************/
4708 /* */
4709 /* GC[a]: Get Coordinate projected onto */
4710 /* Opcode range: 0x46-0x47 */
4711 /* Stack: uint32 --> f26.6 */
4712 /* */
4713 /* BULLSHIT: Measures from the original glyph must be taken along the */
4714 /* dual projection vector! */
4715 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004716 static void
4717 Ins_GC( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004718 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004719 FT_ULong L;
4720 FT_F26Dot6 R;
David Turnerd2b1f351999-12-16 23:11:37 +00004721
4722
David Turnerf9b8dec2000-06-16 19:34:52 +00004723 L = (FT_ULong)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00004724
4725 if ( BOUNDS( L, CUR.zp2.n_points ) )
4726 {
4727 if ( CUR.pedantic_hinting )
4728 {
4729 CUR.error = TT_Err_Invalid_Reference;
4730 return;
4731 }
4732 else
4733 R = 0;
4734 }
4735 else
4736 {
4737 if ( CUR.opcode & 1 )
David Turner72a0dd22007-02-12 15:24:51 +00004738 R = CUR_fast_dualproj( &CUR.zp2.org[L] );
David Turnerd2b1f351999-12-16 23:11:37 +00004739 else
David Turner72a0dd22007-02-12 15:24:51 +00004740 R = CUR_fast_project( &CUR.zp2.cur[L] );
David Turnerd2b1f351999-12-16 23:11:37 +00004741 }
4742
4743 args[0] = R;
4744 }
4745
4746
4747 /*************************************************************************/
4748 /* */
4749 /* SCFS[]: Set Coordinate From Stack */
4750 /* Opcode range: 0x48 */
4751 /* Stack: f26.6 uint32 --> */
4752 /* */
4753 /* Formula: */
4754 /* */
4755 /* OA := OA + ( value - OA.p )/( f.p ) * f */
4756 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004757 static void
4758 Ins_SCFS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004759 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004760 FT_Long K;
4761 FT_UShort L;
David Turnerd2b1f351999-12-16 23:11:37 +00004762
4763
David Turnerf9b8dec2000-06-16 19:34:52 +00004764 L = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00004765
4766 if ( BOUNDS( L, CUR.zp2.n_points ) )
4767 {
4768 if ( CUR.pedantic_hinting )
4769 CUR.error = TT_Err_Invalid_Reference;
4770 return;
4771 }
4772
David Turner72a0dd22007-02-12 15:24:51 +00004773 K = CUR_fast_project( &CUR.zp2.cur[L] );
David Turnerd2b1f351999-12-16 23:11:37 +00004774
4775 CUR_Func_move( &CUR.zp2, L, args[1] - K );
4776
4777 /* not part of the specs, but here for safety */
4778
4779 if ( CUR.GS.gep2 == 0 )
4780 CUR.zp2.org[L] = CUR.zp2.cur[L];
4781 }
4782
4783
4784 /*************************************************************************/
4785 /* */
4786 /* MD[a]: Measure Distance */
4787 /* Opcode range: 0x49-0x4A */
4788 /* Stack: uint32 uint32 --> f26.6 */
4789 /* */
4790 /* BULLSHIT: Measure taken in the original glyph must be along the dual */
4791 /* projection vector. */
4792 /* */
4793 /* Second BULLSHIT: Flag attributes are inverted! */
4794 /* 0 => measure distance in original outline */
4795 /* 1 => measure distance in grid-fitted outline */
4796 /* */
4797 /* Third one: `zp0 - zp1', and not `zp2 - zp1! */
4798 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004799 static void
4800 Ins_MD( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004801 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004802 FT_UShort K, L;
4803 FT_F26Dot6 D;
David Turnerd2b1f351999-12-16 23:11:37 +00004804
4805
David Turnerf9b8dec2000-06-16 19:34:52 +00004806 K = (FT_UShort)args[1];
4807 L = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00004808
4809 if( BOUNDS( L, CUR.zp0.n_points ) ||
4810 BOUNDS( K, CUR.zp1.n_points ) )
4811 {
4812 if ( CUR.pedantic_hinting )
4813 {
4814 CUR.error = TT_Err_Invalid_Reference;
4815 return;
4816 }
4817 D = 0;
4818 }
4819 else
4820 {
4821 if ( CUR.opcode & 1 )
4822 D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
4823 else
Werner Lembergc94fa662008-05-27 23:24:07 +00004824 {
4825 FT_Vector* vec1 = CUR.zp0.orus + L;
4826 FT_Vector* vec2 = CUR.zp1.orus + K;
4827
4828
4829 if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
4830 {
4831 /* this should be faster */
4832 D = CUR_Func_dualproj( vec1, vec2 );
4833 D = TT_MULFIX( D, CUR.metrics.x_scale );
4834 }
4835 else
4836 {
4837 FT_Vector vec;
4838
4839
4840 vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
4841 vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
4842
4843 D = CUR_fast_dualproj( &vec );
4844 }
4845 }
David Turnerd2b1f351999-12-16 23:11:37 +00004846 }
4847
4848 args[0] = D;
4849 }
4850
4851
4852 /*************************************************************************/
4853 /* */
4854 /* SDPVTL[a]: Set Dual PVector to Line */
4855 /* Opcode range: 0x86-0x87 */
4856 /* Stack: uint32 uint32 --> */
4857 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004858 static void
4859 Ins_SDPVTL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004860 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004861 FT_Long A, B, C;
4862 FT_UShort p1, p2; /* was FT_Int in pas type ERROR */
David Turnerd2b1f351999-12-16 23:11:37 +00004863
4864
David Turnerf9b8dec2000-06-16 19:34:52 +00004865 p1 = (FT_UShort)args[1];
4866 p2 = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00004867
4868 if ( BOUNDS( p2, CUR.zp1.n_points ) ||
4869 BOUNDS( p1, CUR.zp2.n_points ) )
4870 {
4871 if ( CUR.pedantic_hinting )
4872 CUR.error = TT_Err_Invalid_Reference;
4873 return;
4874 }
4875
4876 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004877 FT_Vector* v1 = CUR.zp1.org + p2;
4878 FT_Vector* v2 = CUR.zp2.org + p1;
David Turnerd2b1f351999-12-16 23:11:37 +00004879
4880
4881 A = v1->x - v2->x;
4882 B = v1->y - v2->y;
4883 }
4884
Werner Lemberg78575dc2000-06-12 19:36:41 +00004885 if ( ( CUR.opcode & 1 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00004886 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00004887 C = B; /* counter clockwise rotation */
David Turnerd2b1f351999-12-16 23:11:37 +00004888 B = A;
4889 A = -C;
4890 }
4891
4892 NORMalize( A, B, &CUR.GS.dualVector );
4893
4894 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004895 FT_Vector* v1 = CUR.zp1.cur + p2;
4896 FT_Vector* v2 = CUR.zp2.cur + p1;
David Turnerd2b1f351999-12-16 23:11:37 +00004897
4898
4899 A = v1->x - v2->x;
4900 B = v1->y - v2->y;
4901 }
4902
Werner Lemberg78575dc2000-06-12 19:36:41 +00004903 if ( ( CUR.opcode & 1 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00004904 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00004905 C = B; /* counter clockwise rotation */
David Turnerd2b1f351999-12-16 23:11:37 +00004906 B = A;
4907 A = -C;
4908 }
4909
4910 NORMalize( A, B, &CUR.GS.projVector );
4911
Graham Asher3ea859f2003-04-25 11:40:46 +00004912 GUESS_VECTOR( freeVector );
4913
David Turnerd2b1f351999-12-16 23:11:37 +00004914 COMPUTE_Funcs();
4915 }
4916
4917
4918 /*************************************************************************/
4919 /* */
4920 /* SZP0[]: Set Zone Pointer 0 */
4921 /* Opcode range: 0x13 */
4922 /* Stack: uint32 --> */
4923 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004924 static void
4925 Ins_SZP0( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004926 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004927 switch ( (FT_Int)args[0] )
David Turnerd2b1f351999-12-16 23:11:37 +00004928 {
4929 case 0:
4930 CUR.zp0 = CUR.twilight;
4931 break;
4932
4933 case 1:
4934 CUR.zp0 = CUR.pts;
4935 break;
4936
4937 default:
4938 if ( CUR.pedantic_hinting )
4939 CUR.error = TT_Err_Invalid_Reference;
4940 return;
4941 }
4942
David Turnerf9b8dec2000-06-16 19:34:52 +00004943 CUR.GS.gep0 = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00004944 }
4945
4946
4947 /*************************************************************************/
4948 /* */
4949 /* SZP1[]: Set Zone Pointer 1 */
4950 /* Opcode range: 0x14 */
4951 /* Stack: uint32 --> */
4952 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004953 static void
4954 Ins_SZP1( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004955 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004956 switch ( (FT_Int)args[0] )
David Turnerd2b1f351999-12-16 23:11:37 +00004957 {
4958 case 0:
4959 CUR.zp1 = CUR.twilight;
4960 break;
4961
4962 case 1:
4963 CUR.zp1 = CUR.pts;
4964 break;
4965
4966 default:
4967 if ( CUR.pedantic_hinting )
4968 CUR.error = TT_Err_Invalid_Reference;
4969 return;
4970 }
4971
David Turnerf9b8dec2000-06-16 19:34:52 +00004972 CUR.GS.gep1 = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00004973 }
4974
4975
4976 /*************************************************************************/
4977 /* */
4978 /* SZP2[]: Set Zone Pointer 2 */
4979 /* Opcode range: 0x15 */
4980 /* Stack: uint32 --> */
4981 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004982 static void
4983 Ins_SZP2( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004984 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004985 switch ( (FT_Int)args[0] )
David Turnerd2b1f351999-12-16 23:11:37 +00004986 {
4987 case 0:
4988 CUR.zp2 = CUR.twilight;
4989 break;
4990
4991 case 1:
4992 CUR.zp2 = CUR.pts;
4993 break;
4994
4995 default:
4996 if ( CUR.pedantic_hinting )
4997 CUR.error = TT_Err_Invalid_Reference;
4998 return;
4999 }
5000
David Turnerf9b8dec2000-06-16 19:34:52 +00005001 CUR.GS.gep2 = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005002 }
5003
5004
5005 /*************************************************************************/
5006 /* */
5007 /* SZPS[]: Set Zone PointerS */
5008 /* Opcode range: 0x16 */
5009 /* Stack: uint32 --> */
5010 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005011 static void
5012 Ins_SZPS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005013 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005014 switch ( (FT_Int)args[0] )
David Turnerd2b1f351999-12-16 23:11:37 +00005015 {
5016 case 0:
5017 CUR.zp0 = CUR.twilight;
5018 break;
5019
5020 case 1:
5021 CUR.zp0 = CUR.pts;
5022 break;
5023
5024 default:
5025 if ( CUR.pedantic_hinting )
5026 CUR.error = TT_Err_Invalid_Reference;
5027 return;
5028 }
5029
5030 CUR.zp1 = CUR.zp0;
5031 CUR.zp2 = CUR.zp0;
5032
David Turnerf9b8dec2000-06-16 19:34:52 +00005033 CUR.GS.gep0 = (FT_UShort)args[0];
5034 CUR.GS.gep1 = (FT_UShort)args[0];
5035 CUR.GS.gep2 = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005036 }
5037
5038
5039 /*************************************************************************/
5040 /* */
5041 /* INSTCTRL[]: INSTruction ConTRoL */
5042 /* Opcode range: 0x8e */
5043 /* Stack: int32 int32 --> */
5044 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005045 static void
5046 Ins_INSTCTRL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005047 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005048 FT_Long K, L;
David Turnerd2b1f351999-12-16 23:11:37 +00005049
5050
5051 K = args[1];
5052 L = args[0];
5053
5054 if ( K < 1 || K > 2 )
5055 {
5056 if ( CUR.pedantic_hinting )
5057 CUR.error = TT_Err_Invalid_Reference;
5058 return;
5059 }
5060
5061 if ( L != 0 )
5062 L = K;
5063
David Turner3b7049f2001-07-07 16:12:14 +00005064 CUR.GS.instruct_control = FT_BOOL(
5065 ( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );
David Turnerd2b1f351999-12-16 23:11:37 +00005066 }
5067
5068
5069 /*************************************************************************/
5070 /* */
5071 /* SCANCTRL[]: SCAN ConTRoL */
5072 /* Opcode range: 0x85 */
5073 /* Stack: uint32? --> */
5074 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005075 static void
5076 Ins_SCANCTRL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005077 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005078 FT_Int A;
David Turnerd2b1f351999-12-16 23:11:37 +00005079
5080
5081 /* Get Threshold */
David Turnerf9b8dec2000-06-16 19:34:52 +00005082 A = (FT_Int)( args[0] & 0xFF );
David Turnerd2b1f351999-12-16 23:11:37 +00005083
5084 if ( A == 0xFF )
5085 {
5086 CUR.GS.scan_control = TRUE;
5087 return;
5088 }
5089 else if ( A == 0 )
5090 {
5091 CUR.GS.scan_control = FALSE;
5092 return;
5093 }
5094
5095 A *= 64;
5096
Werner Lemberg78575dc2000-06-12 19:36:41 +00005097#if 0
Werner Lembergc9f6c662007-03-21 13:30:14 +00005098 if ( ( args[0] & 0x100 ) != 0 && CUR.metrics.pointSize <= A )
David Turnerd2b1f351999-12-16 23:11:37 +00005099 CUR.GS.scan_control = TRUE;
Werner Lemberg78575dc2000-06-12 19:36:41 +00005100#endif
David Turnerd2b1f351999-12-16 23:11:37 +00005101
Werner Lembergc9f6c662007-03-21 13:30:14 +00005102 if ( ( args[0] & 0x200 ) != 0 && CUR.tt_metrics.rotated )
David Turnerd2b1f351999-12-16 23:11:37 +00005103 CUR.GS.scan_control = TRUE;
5104
Werner Lembergc9f6c662007-03-21 13:30:14 +00005105 if ( ( args[0] & 0x400 ) != 0 && CUR.tt_metrics.stretched )
David Turnerd2b1f351999-12-16 23:11:37 +00005106 CUR.GS.scan_control = TRUE;
5107
Werner Lemberg78575dc2000-06-12 19:36:41 +00005108#if 0
Werner Lembergc9f6c662007-03-21 13:30:14 +00005109 if ( ( args[0] & 0x800 ) != 0 && CUR.metrics.pointSize > A )
David Turnerd2b1f351999-12-16 23:11:37 +00005110 CUR.GS.scan_control = FALSE;
Werner Lemberg78575dc2000-06-12 19:36:41 +00005111#endif
David Turnerd2b1f351999-12-16 23:11:37 +00005112
Werner Lembergc9f6c662007-03-21 13:30:14 +00005113 if ( ( args[0] & 0x1000 ) != 0 && CUR.tt_metrics.rotated )
David Turnerd2b1f351999-12-16 23:11:37 +00005114 CUR.GS.scan_control = FALSE;
5115
Werner Lembergc9f6c662007-03-21 13:30:14 +00005116 if ( ( args[0] & 0x2000 ) != 0 && CUR.tt_metrics.stretched )
David Turnerd2b1f351999-12-16 23:11:37 +00005117 CUR.GS.scan_control = FALSE;
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005118 }
David Turnerd2b1f351999-12-16 23:11:37 +00005119
5120
5121 /*************************************************************************/
5122 /* */
5123 /* SCANTYPE[]: SCAN TYPE */
5124 /* Opcode range: 0x8D */
5125 /* Stack: uint32? --> */
5126 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005127 static void
5128 Ins_SCANTYPE( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005129 {
Werner Lemberg5811c7c2000-07-02 13:53:16 +00005130 /* for compatibility with future enhancements, */
David Turnerd2b1f351999-12-16 23:11:37 +00005131 /* we must ignore new modes */
5132
5133 if ( args[0] >= 0 && args[0] <= 5 )
5134 {
5135 if ( args[0] == 3 )
5136 args[0] = 2;
5137
David Turnerf9b8dec2000-06-16 19:34:52 +00005138 CUR.GS.scan_type = (FT_Int)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005139 }
5140 }
5141
5142
5143 /*************************************************************************/
5144 /* */
5145 /* MANAGING OUTLINES */
5146 /* */
Werner Lemberg5811c7c2000-07-02 13:53:16 +00005147 /* Instructions appear in the specification's order. */
David Turnerd2b1f351999-12-16 23:11:37 +00005148 /* */
5149 /*************************************************************************/
5150
5151
5152 /*************************************************************************/
5153 /* */
5154 /* FLIPPT[]: FLIP PoinT */
5155 /* Opcode range: 0x80 */
5156 /* Stack: uint32... --> */
5157 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005158 static void
5159 Ins_FLIPPT( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005160 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005161 FT_UShort point;
David Turnerd2b1f351999-12-16 23:11:37 +00005162
David Turnerc6a92202000-07-04 18:12:13 +00005163 FT_UNUSED_ARG;
David Turnerd2b1f351999-12-16 23:11:37 +00005164
Werner Lemberg5811c7c2000-07-02 13:53:16 +00005165
David Turnerd2b1f351999-12-16 23:11:37 +00005166 if ( CUR.top < CUR.GS.loop )
5167 {
5168 CUR.error = TT_Err_Too_Few_Arguments;
5169 return;
5170 }
5171
5172 while ( CUR.GS.loop > 0 )
5173 {
5174 CUR.args--;
5175
David Turnerf9b8dec2000-06-16 19:34:52 +00005176 point = (FT_UShort)CUR.stack[CUR.args];
David Turnerd2b1f351999-12-16 23:11:37 +00005177
5178 if ( BOUNDS( point, CUR.pts.n_points ) )
5179 {
5180 if ( CUR.pedantic_hinting )
5181 {
5182 CUR.error = TT_Err_Invalid_Reference;
5183 return;
5184 }
5185 }
5186 else
David Turnerb08fe2d2002-08-27 20:20:29 +00005187 CUR.pts.tags[point] ^= FT_CURVE_TAG_ON;
David Turnerd2b1f351999-12-16 23:11:37 +00005188
5189 CUR.GS.loop--;
5190 }
5191
5192 CUR.GS.loop = 1;
5193 CUR.new_top = CUR.args;
5194 }
5195
5196
5197 /*************************************************************************/
5198 /* */
5199 /* FLIPRGON[]: FLIP RanGe ON */
5200 /* Opcode range: 0x81 */
5201 /* Stack: uint32 uint32 --> */
5202 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005203 static void
5204 Ins_FLIPRGON( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005205 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005206 FT_UShort I, K, L;
David Turnerd2b1f351999-12-16 23:11:37 +00005207
5208
David Turnerf9b8dec2000-06-16 19:34:52 +00005209 K = (FT_UShort)args[1];
5210 L = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005211
5212 if ( BOUNDS( K, CUR.pts.n_points ) ||
5213 BOUNDS( L, CUR.pts.n_points ) )
5214 {
5215 if ( CUR.pedantic_hinting )
5216 CUR.error = TT_Err_Invalid_Reference;
5217 return;
5218 }
5219
5220 for ( I = L; I <= K; I++ )
David Turnerb08fe2d2002-08-27 20:20:29 +00005221 CUR.pts.tags[I] |= FT_CURVE_TAG_ON;
David Turnerd2b1f351999-12-16 23:11:37 +00005222 }
5223
5224
5225 /*************************************************************************/
5226 /* */
5227 /* FLIPRGOFF: FLIP RanGe OFF */
5228 /* Opcode range: 0x82 */
5229 /* Stack: uint32 uint32 --> */
5230 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005231 static void
5232 Ins_FLIPRGOFF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005233 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005234 FT_UShort I, K, L;
David Turnerd2b1f351999-12-16 23:11:37 +00005235
5236
David Turnerf9b8dec2000-06-16 19:34:52 +00005237 K = (FT_UShort)args[1];
5238 L = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005239
5240 if ( BOUNDS( K, CUR.pts.n_points ) ||
5241 BOUNDS( L, CUR.pts.n_points ) )
5242 {
5243 if ( CUR.pedantic_hinting )
5244 CUR.error = TT_Err_Invalid_Reference;
5245 return;
5246 }
5247
5248 for ( I = L; I <= K; I++ )
David Turnerb08fe2d2002-08-27 20:20:29 +00005249 CUR.pts.tags[I] &= ~FT_CURVE_TAG_ON;
David Turnerd2b1f351999-12-16 23:11:37 +00005250 }
5251
5252
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005253 static FT_Bool
Werner Lemberg91db04c2002-04-01 14:25:28 +00005254 Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6* x,
5255 FT_F26Dot6* y,
5256 TT_GlyphZone zone,
5257 FT_UShort* refp )
David Turnerd2b1f351999-12-16 23:11:37 +00005258 {
David Turnerb5713c52002-03-14 11:26:29 +00005259 TT_GlyphZoneRec zp;
Werner Lemberg91db04c2002-04-01 14:25:28 +00005260 FT_UShort p;
5261 FT_F26Dot6 d;
David Turnerd2b1f351999-12-16 23:11:37 +00005262
5263
5264 if ( CUR.opcode & 1 )
5265 {
5266 zp = CUR.zp0;
5267 p = CUR.GS.rp1;
5268 }
5269 else
5270 {
5271 zp = CUR.zp1;
5272 p = CUR.GS.rp2;
5273 }
5274
5275 if ( BOUNDS( p, zp.n_points ) )
5276 {
5277 if ( CUR.pedantic_hinting )
5278 CUR.error = TT_Err_Invalid_Reference;
Werner Lemberg8c4120d2007-01-15 06:42:40 +00005279 *refp = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00005280 return FAILURE;
5281 }
5282
5283 *zone = zp;
5284 *refp = p;
5285
5286 d = CUR_Func_project( zp.cur + p, zp.org + p );
5287
David Turner8b6db862003-08-17 22:09:14 +00005288#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Graham Asher3ea859f2003-04-25 11:40:46 +00005289 if ( CUR.face->unpatented_hinting )
5290 {
5291 if ( CUR.GS.both_x_axis )
5292 {
5293 *x = d;
5294 *y = 0;
5295 }
5296 else
5297 {
5298 *x = 0;
5299 *y = d;
David Turner87c0d302003-12-24 01:10:46 +00005300 }
Graham Asher3ea859f2003-04-25 11:40:46 +00005301 }
5302 else
5303#endif
5304 {
5305 *x = TT_MULDIV( d,
5306 (FT_Long)CUR.GS.freeVector.x * 0x10000L,
5307 CUR.F_dot_P );
5308 *y = TT_MULDIV( d,
5309 (FT_Long)CUR.GS.freeVector.y * 0x10000L,
5310 CUR.F_dot_P );
5311 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00005312
David Turnerd2b1f351999-12-16 23:11:37 +00005313 return SUCCESS;
5314 }
5315
5316
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005317 static void
5318 Move_Zp2_Point( EXEC_OP_ FT_UShort point,
5319 FT_F26Dot6 dx,
5320 FT_F26Dot6 dy,
5321 FT_Bool touch )
David Turnerd2b1f351999-12-16 23:11:37 +00005322 {
David Turner8b6db862003-08-17 22:09:14 +00005323#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Werner Lemberga3f4da82003-04-29 13:23:47 +00005324 if ( CUR.face->unpatented_hinting )
Graham Asher3ea859f2003-04-25 11:40:46 +00005325 {
5326 if ( CUR.GS.both_x_axis )
5327 {
5328 CUR.zp2.cur[point].x += dx;
5329 if ( touch )
5330 CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
5331 }
5332 else
5333 {
5334 CUR.zp2.cur[point].y += dy;
5335 if ( touch )
5336 CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
5337 }
5338 return;
5339 }
5340#endif
5341
David Turnerd2b1f351999-12-16 23:11:37 +00005342 if ( CUR.GS.freeVector.x != 0 )
5343 {
5344 CUR.zp2.cur[point].x += dx;
5345 if ( touch )
David Turnerb08fe2d2002-08-27 20:20:29 +00005346 CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
David Turnerd2b1f351999-12-16 23:11:37 +00005347 }
5348
5349 if ( CUR.GS.freeVector.y != 0 )
5350 {
5351 CUR.zp2.cur[point].y += dy;
5352 if ( touch )
David Turnerb08fe2d2002-08-27 20:20:29 +00005353 CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
David Turnerd2b1f351999-12-16 23:11:37 +00005354 }
5355 }
5356
5357
5358 /*************************************************************************/
5359 /* */
5360 /* SHP[a]: SHift Point by the last point */
5361 /* Opcode range: 0x32-0x33 */
5362 /* Stack: uint32... --> */
5363 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005364 static void
5365 Ins_SHP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005366 {
David Turnerb5713c52002-03-14 11:26:29 +00005367 TT_GlyphZoneRec zp;
Werner Lemberg91db04c2002-04-01 14:25:28 +00005368 FT_UShort refp;
David Turnerd2b1f351999-12-16 23:11:37 +00005369
Werner Lemberg91db04c2002-04-01 14:25:28 +00005370 FT_F26Dot6 dx,
5371 dy;
5372 FT_UShort point;
David Turnerd2b1f351999-12-16 23:11:37 +00005373
David Turnerc6a92202000-07-04 18:12:13 +00005374 FT_UNUSED_ARG;
David Turnerd2b1f351999-12-16 23:11:37 +00005375
Werner Lemberg78575dc2000-06-12 19:36:41 +00005376
David Turnerd2b1f351999-12-16 23:11:37 +00005377 if ( CUR.top < CUR.GS.loop )
5378 {
5379 CUR.error = TT_Err_Invalid_Reference;
5380 return;
5381 }
5382
5383 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
5384 return;
5385
5386 while ( CUR.GS.loop > 0 )
5387 {
5388 CUR.args--;
David Turnerf9b8dec2000-06-16 19:34:52 +00005389 point = (FT_UShort)CUR.stack[CUR.args];
David Turnerd2b1f351999-12-16 23:11:37 +00005390
5391 if ( BOUNDS( point, CUR.zp2.n_points ) )
5392 {
5393 if ( CUR.pedantic_hinting )
5394 {
5395 CUR.error = TT_Err_Invalid_Reference;
5396 return;
5397 }
5398 }
5399 else
5400 /* XXX: UNDOCUMENTED! SHP touches the points */
5401 MOVE_Zp2_Point( point, dx, dy, TRUE );
5402
5403 CUR.GS.loop--;
5404 }
5405
5406 CUR.GS.loop = 1;
5407 CUR.new_top = CUR.args;
5408 }
5409
5410
5411 /*************************************************************************/
5412 /* */
5413 /* SHC[a]: SHift Contour */
5414 /* Opcode range: 0x34-35 */
5415 /* Stack: uint32 --> */
5416 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005417 static void
5418 Ins_SHC( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005419 {
David Turnerb5713c52002-03-14 11:26:29 +00005420 TT_GlyphZoneRec zp;
Werner Lemberg91db04c2002-04-01 14:25:28 +00005421 FT_UShort refp;
5422 FT_F26Dot6 dx,
5423 dy;
David Turnerd2b1f351999-12-16 23:11:37 +00005424
Werner Lemberg91db04c2002-04-01 14:25:28 +00005425 FT_Short contour;
5426 FT_UShort first_point, last_point, i;
David Turnerd2b1f351999-12-16 23:11:37 +00005427
5428
David Turnerf9b8dec2000-06-16 19:34:52 +00005429 contour = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005430
5431 if ( BOUNDS( contour, CUR.pts.n_contours ) )
5432 {
5433 if ( CUR.pedantic_hinting )
5434 CUR.error = TT_Err_Invalid_Reference;
5435 return;
5436 }
5437
5438 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
5439 return;
5440
5441 if ( contour == 0 )
5442 first_point = 0;
5443 else
Werner Lemberga2da05c2006-06-25 06:27:27 +00005444 first_point = (FT_UShort)( CUR.pts.contours[contour - 1] + 1 -
5445 CUR.pts.first_point );
David Turnerd2b1f351999-12-16 23:11:37 +00005446
Werner Lembergb4142d52007-01-17 12:45:26 +00005447 last_point = (FT_UShort)( CUR.pts.contours[contour] -
5448 CUR.pts.first_point );
David Turnerd2b1f351999-12-16 23:11:37 +00005449
5450 /* XXX: this is probably wrong... at least it prevents memory */
5451 /* corruption when zp2 is the twilight zone */
5452 if ( last_point > CUR.zp2.n_points )
5453 {
5454 if ( CUR.zp2.n_points > 0 )
David Turner3b7049f2001-07-07 16:12:14 +00005455 last_point = (FT_UShort)(CUR.zp2.n_points - 1);
David Turnerd2b1f351999-12-16 23:11:37 +00005456 else
5457 last_point = 0;
5458 }
5459
Werner Lemberg555258f2007-01-21 09:46:37 +00005460 /* XXX: UNDOCUMENTED! SHC touches the points */
David Turnerd2b1f351999-12-16 23:11:37 +00005461 for ( i = first_point; i <= last_point; i++ )
5462 {
5463 if ( zp.cur != CUR.zp2.cur || refp != i )
Werner Lembergbe67c4e2003-11-24 22:54:58 +00005464 MOVE_Zp2_Point( i, dx, dy, TRUE );
David Turnerd2b1f351999-12-16 23:11:37 +00005465 }
5466 }
5467
5468
5469 /*************************************************************************/
5470 /* */
5471 /* SHZ[a]: SHift Zone */
5472 /* Opcode range: 0x36-37 */
5473 /* Stack: uint32 --> */
5474 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005475 static void
5476 Ins_SHZ( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005477 {
David Turnerb5713c52002-03-14 11:26:29 +00005478 TT_GlyphZoneRec zp;
Werner Lemberg91db04c2002-04-01 14:25:28 +00005479 FT_UShort refp;
5480 FT_F26Dot6 dx,
5481 dy;
David Turnerd2b1f351999-12-16 23:11:37 +00005482
Werner Lemberg91db04c2002-04-01 14:25:28 +00005483 FT_UShort last_point, i;
David Turnerd2b1f351999-12-16 23:11:37 +00005484
5485
5486 if ( BOUNDS( args[0], 2 ) )
5487 {
5488 if ( CUR.pedantic_hinting )
5489 CUR.error = TT_Err_Invalid_Reference;
5490 return;
5491 }
5492
5493 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
5494 return;
5495
Werner Lemberg555258f2007-01-21 09:46:37 +00005496 /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points. */
5497 /* Twilight zone has no contours, so use `n_points'. */
5498 /* Normal zone's `n_points' includes phantoms, so must */
5499 /* use end of last contour. */
5500 if ( CUR.GS.gep2 == 0 && CUR.zp2.n_points > 0 )
5501 last_point = (FT_UShort)( CUR.zp2.n_points - 1 );
5502 else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 )
5503 last_point = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] );
David Turnerd2b1f351999-12-16 23:11:37 +00005504 else
5505 last_point = 0;
5506
5507 /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
5508 for ( i = 0; i <= last_point; i++ )
5509 {
5510 if ( zp.cur != CUR.zp2.cur || refp != i )
5511 MOVE_Zp2_Point( i, dx, dy, FALSE );
5512 }
5513 }
5514
5515
5516 /*************************************************************************/
5517 /* */
5518 /* SHPIX[]: SHift points by a PIXel amount */
5519 /* Opcode range: 0x38 */
5520 /* Stack: f26.6 uint32... --> */
5521 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005522 static void
5523 Ins_SHPIX( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005524 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005525 FT_F26Dot6 dx, dy;
5526 FT_UShort point;
David Turnerd2b1f351999-12-16 23:11:37 +00005527
5528
5529 if ( CUR.top < CUR.GS.loop + 1 )
5530 {
5531 CUR.error = TT_Err_Invalid_Reference;
5532 return;
5533 }
5534
David Turner8b6db862003-08-17 22:09:14 +00005535#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Werner Lemberga3f4da82003-04-29 13:23:47 +00005536 if ( CUR.face->unpatented_hinting )
Graham Asher3ea859f2003-04-25 11:40:46 +00005537 {
5538 if ( CUR.GS.both_x_axis )
5539 {
5540 dx = TT_MulFix14( args[0], 0x4000 );
Werner Lemberga3f4da82003-04-29 13:23:47 +00005541 dy = 0;
Graham Asher3ea859f2003-04-25 11:40:46 +00005542 }
5543 else
5544 {
Werner Lemberga3f4da82003-04-29 13:23:47 +00005545 dx = 0;
Graham Asher3ea859f2003-04-25 11:40:46 +00005546 dy = TT_MulFix14( args[0], 0x4000 );
5547 }
5548 }
5549 else
5550#endif
5551 {
5552 dx = TT_MulFix14( args[0], CUR.GS.freeVector.x );
5553 dy = TT_MulFix14( args[0], CUR.GS.freeVector.y );
5554 }
David Turnerd2b1f351999-12-16 23:11:37 +00005555
5556 while ( CUR.GS.loop > 0 )
5557 {
5558 CUR.args--;
5559
David Turnerf9b8dec2000-06-16 19:34:52 +00005560 point = (FT_UShort)CUR.stack[CUR.args];
David Turnerd2b1f351999-12-16 23:11:37 +00005561
5562 if ( BOUNDS( point, CUR.zp2.n_points ) )
5563 {
5564 if ( CUR.pedantic_hinting )
5565 {
5566 CUR.error = TT_Err_Invalid_Reference;
5567 return;
5568 }
5569 }
5570 else
5571 MOVE_Zp2_Point( point, dx, dy, TRUE );
5572
5573 CUR.GS.loop--;
5574 }
5575
5576 CUR.GS.loop = 1;
5577 CUR.new_top = CUR.args;
5578 }
5579
5580
5581 /*************************************************************************/
5582 /* */
5583 /* MSIRP[a]: Move Stack Indirect Relative Position */
5584 /* Opcode range: 0x3A-0x3B */
5585 /* Stack: f26.6 uint32 --> */
5586 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005587 static void
5588 Ins_MSIRP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005589 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005590 FT_UShort point;
5591 FT_F26Dot6 distance;
David Turnerd2b1f351999-12-16 23:11:37 +00005592
5593
David Turnerf9b8dec2000-06-16 19:34:52 +00005594 point = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005595
5596 if ( BOUNDS( point, CUR.zp1.n_points ) ||
5597 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
5598 {
5599 if ( CUR.pedantic_hinting )
5600 CUR.error = TT_Err_Invalid_Reference;
5601 return;
5602 }
5603
5604 /* XXX: UNDOCUMENTED! behaviour */
Werner Lembergbe67c4e2003-11-24 22:54:58 +00005605 if ( CUR.GS.gep1 == 0 ) /* if the point that is to be moved */
5606 /* is in twilight zone */
David Turnerd2b1f351999-12-16 23:11:37 +00005607 {
5608 CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
Werner Lembergbe67c4e2003-11-24 22:54:58 +00005609 CUR_Func_move_orig( &CUR.zp1, point, args[1] );
David Turnerd2b1f351999-12-16 23:11:37 +00005610 CUR.zp1.cur[point] = CUR.zp1.org[point];
5611 }
5612
5613 distance = CUR_Func_project( CUR.zp1.cur + point,
5614 CUR.zp0.cur + CUR.GS.rp0 );
5615
5616 CUR_Func_move( &CUR.zp1, point, args[1] - distance );
5617
5618 CUR.GS.rp1 = CUR.GS.rp0;
5619 CUR.GS.rp2 = point;
5620
Werner Lembergc9f6c662007-03-21 13:30:14 +00005621 if ( ( CUR.opcode & 1 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00005622 CUR.GS.rp0 = point;
5623 }
5624
5625
5626 /*************************************************************************/
5627 /* */
5628 /* MDAP[a]: Move Direct Absolute Point */
5629 /* Opcode range: 0x2E-0x2F */
5630 /* Stack: uint32 --> */
5631 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005632 static void
5633 Ins_MDAP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005634 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005635 FT_UShort point;
5636 FT_F26Dot6 cur_dist,
David Turnerd2b1f351999-12-16 23:11:37 +00005637 distance;
5638
5639
David Turnerf9b8dec2000-06-16 19:34:52 +00005640 point = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005641
5642 if ( BOUNDS( point, CUR.zp0.n_points ) )
5643 {
5644 if ( CUR.pedantic_hinting )
5645 CUR.error = TT_Err_Invalid_Reference;
5646 return;
5647 }
5648
5649 /* XXX: Is there some undocumented feature while in the */
5650 /* twilight zone? ? */
Werner Lemberg78575dc2000-06-12 19:36:41 +00005651 if ( ( CUR.opcode & 1 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00005652 {
David Turner72a0dd22007-02-12 15:24:51 +00005653 cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
David Turnerd2b1f351999-12-16 23:11:37 +00005654 distance = CUR_Func_round( cur_dist,
5655 CUR.tt_metrics.compensations[0] ) - cur_dist;
5656 }
5657 else
5658 distance = 0;
5659
5660 CUR_Func_move( &CUR.zp0, point, distance );
5661
5662 CUR.GS.rp0 = point;
5663 CUR.GS.rp1 = point;
5664 }
5665
5666
5667 /*************************************************************************/
5668 /* */
5669 /* MIAP[a]: Move Indirect Absolute Point */
5670 /* Opcode range: 0x3E-0x3F */
5671 /* Stack: uint32 uint32 --> */
5672 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005673 static void
5674 Ins_MIAP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005675 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005676 FT_ULong cvtEntry;
5677 FT_UShort point;
5678 FT_F26Dot6 distance,
David Turnerd2b1f351999-12-16 23:11:37 +00005679 org_dist;
5680
5681
David Turnerf9b8dec2000-06-16 19:34:52 +00005682 cvtEntry = (FT_ULong)args[1];
5683 point = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005684
5685 if ( BOUNDS( point, CUR.zp0.n_points ) ||
5686 BOUNDS( cvtEntry, CUR.cvtSize ) )
5687 {
5688 if ( CUR.pedantic_hinting )
5689 CUR.error = TT_Err_Invalid_Reference;
5690 return;
5691 }
5692
Werner Lembergc9f6c662007-03-21 13:30:14 +00005693 /* XXX: UNDOCUMENTED! */
David Turnerd2b1f351999-12-16 23:11:37 +00005694 /* */
5695 /* The behaviour of an MIAP instruction is quite */
5696 /* different when used in the twilight zone. */
5697 /* */
Werner Lemberg406d25f2007-02-12 22:01:18 +00005698 /* First, no control value cut-in test is performed */
David Turnerd2b1f351999-12-16 23:11:37 +00005699 /* as it would fail anyway. Second, the original */
5700 /* point, i.e. (org_x,org_y) of zp0.point, is set */
5701 /* to the absolute, unrounded distance found in */
5702 /* the CVT. */
5703 /* */
5704 /* This is used in the CVT programs of the Microsoft */
5705 /* fonts Arial, Times, etc., in order to re-adjust */
5706 /* some key font heights. It allows the use of the */
5707 /* IP instruction in the twilight zone, which */
5708 /* otherwise would be `illegal' according to the */
Werner Lemberg78575dc2000-06-12 19:36:41 +00005709 /* specification. */
David Turnerd2b1f351999-12-16 23:11:37 +00005710 /* */
5711 /* We implement it with a special sequence for the */
5712 /* twilight zone. This is a bad hack, but it seems */
5713 /* to work. */
5714
5715 distance = CUR_Func_read_cvt( cvtEntry );
5716
5717 if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */
5718 {
David Turner4b29d582002-03-25 17:02:26 +00005719 CUR.zp0.org[point].x = TT_MulFix14( distance, CUR.GS.freeVector.x );
5720 CUR.zp0.org[point].y = TT_MulFix14( distance, CUR.GS.freeVector.y ),
5721 CUR.zp0.cur[point] = CUR.zp0.org[point];
David Turnerd2b1f351999-12-16 23:11:37 +00005722 }
5723
David Turner72a0dd22007-02-12 15:24:51 +00005724 org_dist = CUR_fast_project( &CUR.zp0.cur[point] );
David Turnerd2b1f351999-12-16 23:11:37 +00005725
Werner Lemberg78575dc2000-06-12 19:36:41 +00005726 if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cutin flag */
David Turnerd2b1f351999-12-16 23:11:37 +00005727 {
Werner Lembergdfa46192004-03-05 09:26:24 +00005728 if ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin )
David Turnerd2b1f351999-12-16 23:11:37 +00005729 distance = org_dist;
5730
5731 distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );
5732 }
5733
5734 CUR_Func_move( &CUR.zp0, point, distance - org_dist );
5735
5736 CUR.GS.rp0 = point;
5737 CUR.GS.rp1 = point;
5738 }
5739
5740
5741 /*************************************************************************/
5742 /* */
5743 /* MDRP[abcde]: Move Direct Relative Point */
5744 /* Opcode range: 0xC0-0xDF */
5745 /* Stack: uint32 --> */
5746 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005747 static void
5748 Ins_MDRP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005749 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005750 FT_UShort point;
5751 FT_F26Dot6 org_dist, distance;
David Turnerd2b1f351999-12-16 23:11:37 +00005752
5753
David Turnerf9b8dec2000-06-16 19:34:52 +00005754 point = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005755
5756 if ( BOUNDS( point, CUR.zp1.n_points ) ||
5757 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
5758 {
5759 if ( CUR.pedantic_hinting )
5760 CUR.error = TT_Err_Invalid_Reference;
5761 return;
5762 }
5763
5764 /* XXX: Is there some undocumented feature while in the */
5765 /* twilight zone? */
5766
Werner Lembergc9f6c662007-03-21 13:30:14 +00005767 /* XXX: UNDOCUMENTED: twilight zone special case */
David Turner74c34eb2007-03-18 07:19:31 +00005768
5769 if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )
5770 {
5771 FT_Vector* vec1 = &CUR.zp1.org[point];
5772 FT_Vector* vec2 = &CUR.zp0.org[CUR.GS.rp0];
5773
Werner Lembergc9f6c662007-03-21 13:30:14 +00005774
David Turner74c34eb2007-03-18 07:19:31 +00005775 org_dist = CUR_Func_dualproj( vec1, vec2 );
5776 }
5777 else
David Turner33f5f242006-08-16 16:50:55 +00005778 {
David Turner2c4500e2007-02-14 15:08:47 +00005779 FT_Vector* vec1 = &CUR.zp1.orus[point];
5780 FT_Vector* vec2 = &CUR.zp0.orus[CUR.GS.rp0];
David Turner33f5f242006-08-16 16:50:55 +00005781
Werner Lemberg12342992006-08-19 11:18:09 +00005782
David Turner89020d92007-03-17 17:48:57 +00005783 if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
David Turner2c4500e2007-02-14 15:08:47 +00005784 {
5785 /* this should be faster */
5786 org_dist = CUR_Func_dualproj( vec1, vec2 );
5787 org_dist = TT_MULFIX( org_dist, CUR.metrics.x_scale );
5788 }
David Turner89020d92007-03-17 17:48:57 +00005789 else
David Turner2c4500e2007-02-14 15:08:47 +00005790 {
5791 FT_Vector vec;
David Turner33f5f242006-08-16 16:50:55 +00005792
Werner Lembergc9f6c662007-03-21 13:30:14 +00005793
David Turner2c4500e2007-02-14 15:08:47 +00005794 vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
5795 vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
David Turner33f5f242006-08-16 16:50:55 +00005796
David Turner2c4500e2007-02-14 15:08:47 +00005797 org_dist = CUR_fast_dualproj( &vec );
5798 }
David Turner33f5f242006-08-16 16:50:55 +00005799 }
Werner Lemberg12342992006-08-19 11:18:09 +00005800
Werner Lemberg12342992006-08-19 11:18:09 +00005801 /* single width cut-in test */
David Turnerd2b1f351999-12-16 23:11:37 +00005802
Werner Lembergdfa46192004-03-05 09:26:24 +00005803 if ( FT_ABS( org_dist - CUR.GS.single_width_value ) <
Werner Lemberg6e9b3182003-06-10 10:54:33 +00005804 CUR.GS.single_width_cutin )
David Turnerd2b1f351999-12-16 23:11:37 +00005805 {
5806 if ( org_dist >= 0 )
5807 org_dist = CUR.GS.single_width_value;
5808 else
5809 org_dist = -CUR.GS.single_width_value;
5810 }
5811
5812 /* round flag */
5813
Werner Lemberg78575dc2000-06-12 19:36:41 +00005814 if ( ( CUR.opcode & 4 ) != 0 )
5815 distance = CUR_Func_round(
5816 org_dist,
5817 CUR.tt_metrics.compensations[CUR.opcode & 3] );
David Turnerd2b1f351999-12-16 23:11:37 +00005818 else
Werner Lemberg78575dc2000-06-12 19:36:41 +00005819 distance = ROUND_None(
5820 org_dist,
5821 CUR.tt_metrics.compensations[CUR.opcode & 3] );
David Turnerd2b1f351999-12-16 23:11:37 +00005822
5823 /* minimum distance flag */
5824
Werner Lemberg78575dc2000-06-12 19:36:41 +00005825 if ( ( CUR.opcode & 8 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00005826 {
5827 if ( org_dist >= 0 )
5828 {
5829 if ( distance < CUR.GS.minimum_distance )
5830 distance = CUR.GS.minimum_distance;
5831 }
5832 else
5833 {
5834 if ( distance > -CUR.GS.minimum_distance )
5835 distance = -CUR.GS.minimum_distance;
5836 }
5837 }
5838
5839 /* now move the point */
5840
5841 org_dist = CUR_Func_project( CUR.zp1.cur + point,
5842 CUR.zp0.cur + CUR.GS.rp0 );
5843
5844 CUR_Func_move( &CUR.zp1, point, distance - org_dist );
5845
5846 CUR.GS.rp1 = CUR.GS.rp0;
5847 CUR.GS.rp2 = point;
5848
Werner Lemberg78575dc2000-06-12 19:36:41 +00005849 if ( ( CUR.opcode & 16 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00005850 CUR.GS.rp0 = point;
5851 }
5852
5853
5854 /*************************************************************************/
5855 /* */
5856 /* MIRP[abcde]: Move Indirect Relative Point */
5857 /* Opcode range: 0xE0-0xFF */
5858 /* Stack: int32? uint32 --> */
5859 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005860 static void
5861 Ins_MIRP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005862 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005863 FT_UShort point;
5864 FT_ULong cvtEntry;
David Turnerd2b1f351999-12-16 23:11:37 +00005865
David Turnerf9b8dec2000-06-16 19:34:52 +00005866 FT_F26Dot6 cvt_dist,
David Turnerd2b1f351999-12-16 23:11:37 +00005867 distance,
5868 cur_dist,
5869 org_dist;
5870
5871
David Turnerf9b8dec2000-06-16 19:34:52 +00005872 point = (FT_UShort)args[0];
5873 cvtEntry = (FT_ULong)( args[1] + 1 );
David Turnerd2b1f351999-12-16 23:11:37 +00005874
5875 /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
5876
5877 if ( BOUNDS( point, CUR.zp1.n_points ) ||
5878 BOUNDS( cvtEntry, CUR.cvtSize + 1 ) ||
5879 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
5880 {
5881 if ( CUR.pedantic_hinting )
5882 CUR.error = TT_Err_Invalid_Reference;
5883 return;
5884 }
5885
5886 if ( !cvtEntry )
5887 cvt_dist = 0;
5888 else
5889 cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
5890
5891 /* single width test */
5892
Werner Lembergdfa46192004-03-05 09:26:24 +00005893 if ( FT_ABS( cvt_dist - CUR.GS.single_width_value ) <
Werner Lemberg6e9b3182003-06-10 10:54:33 +00005894 CUR.GS.single_width_cutin )
David Turnerd2b1f351999-12-16 23:11:37 +00005895 {
5896 if ( cvt_dist >= 0 )
5897 cvt_dist = CUR.GS.single_width_value;
5898 else
5899 cvt_dist = -CUR.GS.single_width_value;
5900 }
5901
5902 /* XXX: UNDOCUMENTED! -- twilight zone */
5903
5904 if ( CUR.GS.gep1 == 0 )
5905 {
5906 CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
David Turner4b29d582002-03-25 17:02:26 +00005907 TT_MulFix14( cvt_dist, CUR.GS.freeVector.x );
David Turnerd2b1f351999-12-16 23:11:37 +00005908
5909 CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +
David Turner4b29d582002-03-25 17:02:26 +00005910 TT_MulFix14( cvt_dist, CUR.GS.freeVector.y );
David Turnerd2b1f351999-12-16 23:11:37 +00005911
David Turner2c4500e2007-02-14 15:08:47 +00005912 CUR.zp1.cur[point] = CUR.zp0.cur[point];
David Turnerd2b1f351999-12-16 23:11:37 +00005913 }
5914
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00005915 org_dist = CUR_Func_dualproj( &CUR.zp1.org[point],
5916 &CUR.zp0.org[CUR.GS.rp0] );
5917 cur_dist = CUR_Func_project ( &CUR.zp1.cur[point],
5918 &CUR.zp0.cur[CUR.GS.rp0] );
David Turnerd2b1f351999-12-16 23:11:37 +00005919
5920 /* auto-flip test */
5921
5922 if ( CUR.GS.auto_flip )
5923 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00005924 if ( ( org_dist ^ cvt_dist ) < 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00005925 cvt_dist = -cvt_dist;
5926 }
5927
5928 /* control value cutin and round */
5929
Werner Lemberg78575dc2000-06-12 19:36:41 +00005930 if ( ( CUR.opcode & 4 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00005931 {
5932 /* XXX: UNDOCUMENTED! Only perform cut-in test when both points */
5933 /* refer to the same zone. */
5934
5935 if ( CUR.GS.gep0 == CUR.GS.gep1 )
Werner Lembergdfa46192004-03-05 09:26:24 +00005936 if ( FT_ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )
David Turnerd2b1f351999-12-16 23:11:37 +00005937 cvt_dist = org_dist;
5938
Werner Lemberg78575dc2000-06-12 19:36:41 +00005939 distance = CUR_Func_round(
5940 cvt_dist,
5941 CUR.tt_metrics.compensations[CUR.opcode & 3] );
David Turnerd2b1f351999-12-16 23:11:37 +00005942 }
5943 else
Werner Lemberg78575dc2000-06-12 19:36:41 +00005944 distance = ROUND_None(
5945 cvt_dist,
5946 CUR.tt_metrics.compensations[CUR.opcode & 3] );
David Turnerd2b1f351999-12-16 23:11:37 +00005947
5948 /* minimum distance test */
5949
Werner Lemberg78575dc2000-06-12 19:36:41 +00005950 if ( ( CUR.opcode & 8 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00005951 {
5952 if ( org_dist >= 0 )
5953 {
5954 if ( distance < CUR.GS.minimum_distance )
5955 distance = CUR.GS.minimum_distance;
5956 }
5957 else
5958 {
5959 if ( distance > -CUR.GS.minimum_distance )
5960 distance = -CUR.GS.minimum_distance;
5961 }
5962 }
5963
5964 CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
5965
5966 CUR.GS.rp1 = CUR.GS.rp0;
5967
Werner Lemberg78575dc2000-06-12 19:36:41 +00005968 if ( ( CUR.opcode & 16 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00005969 CUR.GS.rp0 = point;
5970
5971 /* XXX: UNDOCUMENTED! */
David Turnerd2b1f351999-12-16 23:11:37 +00005972 CUR.GS.rp2 = point;
5973 }
5974
5975
5976 /*************************************************************************/
5977 /* */
5978 /* ALIGNRP[]: ALIGN Relative Point */
5979 /* Opcode range: 0x3C */
5980 /* Stack: uint32 uint32... --> */
5981 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005982 static void
5983 Ins_ALIGNRP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005984 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005985 FT_UShort point;
5986 FT_F26Dot6 distance;
David Turnerd2b1f351999-12-16 23:11:37 +00005987
David Turnerc6a92202000-07-04 18:12:13 +00005988 FT_UNUSED_ARG;
David Turnerd2b1f351999-12-16 23:11:37 +00005989
Werner Lemberg78575dc2000-06-12 19:36:41 +00005990
David Turnerd2b1f351999-12-16 23:11:37 +00005991 if ( CUR.top < CUR.GS.loop ||
5992 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
5993 {
5994 if ( CUR.pedantic_hinting )
5995 CUR.error = TT_Err_Invalid_Reference;
5996 return;
5997 }
5998
5999 while ( CUR.GS.loop > 0 )
6000 {
6001 CUR.args--;
6002
David Turnerf9b8dec2000-06-16 19:34:52 +00006003 point = (FT_UShort)CUR.stack[CUR.args];
David Turnerd2b1f351999-12-16 23:11:37 +00006004
6005 if ( BOUNDS( point, CUR.zp1.n_points ) )
6006 {
6007 if ( CUR.pedantic_hinting )
6008 {
6009 CUR.error = TT_Err_Invalid_Reference;
6010 return;
6011 }
6012 }
6013 else
6014 {
6015 distance = CUR_Func_project( CUR.zp1.cur + point,
6016 CUR.zp0.cur + CUR.GS.rp0 );
6017
6018 CUR_Func_move( &CUR.zp1, point, -distance );
6019 }
6020
6021 CUR.GS.loop--;
6022 }
6023
6024 CUR.GS.loop = 1;
6025 CUR.new_top = CUR.args;
6026 }
6027
6028
6029 /*************************************************************************/
6030 /* */
6031 /* ISECT[]: moves point to InterSECTion */
6032 /* Opcode range: 0x0F */
6033 /* Stack: 5 * uint32 --> */
6034 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006035 static void
6036 Ins_ISECT( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00006037 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006038 FT_UShort point,
David Turnerd2b1f351999-12-16 23:11:37 +00006039 a0, a1,
6040 b0, b1;
6041
David Turnerf9b8dec2000-06-16 19:34:52 +00006042 FT_F26Dot6 discriminant;
David Turnerd2b1f351999-12-16 23:11:37 +00006043
David Turnerf9b8dec2000-06-16 19:34:52 +00006044 FT_F26Dot6 dx, dy,
David Turnerd2b1f351999-12-16 23:11:37 +00006045 dax, day,
6046 dbx, dby;
6047
David Turnerf9b8dec2000-06-16 19:34:52 +00006048 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00006049
David Turnerf9b8dec2000-06-16 19:34:52 +00006050 FT_Vector R;
David Turnerd2b1f351999-12-16 23:11:37 +00006051
6052
David Turnerf9b8dec2000-06-16 19:34:52 +00006053 point = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00006054
David Turnerf9b8dec2000-06-16 19:34:52 +00006055 a0 = (FT_UShort)args[1];
6056 a1 = (FT_UShort)args[2];
6057 b0 = (FT_UShort)args[3];
6058 b1 = (FT_UShort)args[4];
David Turnerd2b1f351999-12-16 23:11:37 +00006059
6060 if ( BOUNDS( b0, CUR.zp0.n_points ) ||
6061 BOUNDS( b1, CUR.zp0.n_points ) ||
6062 BOUNDS( a0, CUR.zp1.n_points ) ||
6063 BOUNDS( a1, CUR.zp1.n_points ) ||
6064 BOUNDS( point, CUR.zp2.n_points ) )
6065 {
6066 if ( CUR.pedantic_hinting )
6067 CUR.error = TT_Err_Invalid_Reference;
6068 return;
6069 }
6070
6071 dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
6072 dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
6073
6074 dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x;
6075 day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y;
6076
6077 dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x;
6078 dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y;
6079
David Turnerb08fe2d2002-08-27 20:20:29 +00006080 CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
David Turnerd2b1f351999-12-16 23:11:37 +00006081
6082 discriminant = TT_MULDIV( dax, -dby, 0x40 ) +
6083 TT_MULDIV( day, dbx, 0x40 );
6084
Werner Lembergdfa46192004-03-05 09:26:24 +00006085 if ( FT_ABS( discriminant ) >= 0x40 )
David Turnerd2b1f351999-12-16 23:11:37 +00006086 {
6087 val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );
6088
6089 R.x = TT_MULDIV( val, dax, discriminant );
6090 R.y = TT_MULDIV( val, day, discriminant );
6091
6092 CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;
6093 CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
6094 }
6095 else
6096 {
6097 /* else, take the middle of the middles of A and B */
6098
6099 CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x +
6100 CUR.zp1.cur[a1].x +
6101 CUR.zp0.cur[b0].x +
6102 CUR.zp0.cur[b1].x ) / 4;
6103 CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y +
6104 CUR.zp1.cur[a1].y +
6105 CUR.zp0.cur[b0].y +
6106 CUR.zp0.cur[b1].y ) / 4;
6107 }
6108 }
6109
6110
6111 /*************************************************************************/
6112 /* */
6113 /* ALIGNPTS[]: ALIGN PoinTS */
6114 /* Opcode range: 0x27 */
6115 /* Stack: uint32 uint32 --> */
6116 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006117 static void
6118 Ins_ALIGNPTS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00006119 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006120 FT_UShort p1, p2;
6121 FT_F26Dot6 distance;
David Turnerd2b1f351999-12-16 23:11:37 +00006122
6123
David Turnerf9b8dec2000-06-16 19:34:52 +00006124 p1 = (FT_UShort)args[0];
6125 p2 = (FT_UShort)args[1];
David Turnerd2b1f351999-12-16 23:11:37 +00006126
6127 if ( BOUNDS( args[0], CUR.zp1.n_points ) ||
6128 BOUNDS( args[1], CUR.zp0.n_points ) )
6129 {
6130 if ( CUR.pedantic_hinting )
6131 CUR.error = TT_Err_Invalid_Reference;
6132 return;
6133 }
6134
6135 distance = CUR_Func_project( CUR.zp0.cur + p2,
6136 CUR.zp1.cur + p1 ) / 2;
6137
6138 CUR_Func_move( &CUR.zp1, p1, distance );
6139 CUR_Func_move( &CUR.zp0, p2, -distance );
6140 }
6141
6142
6143 /*************************************************************************/
6144 /* */
6145 /* IP[]: Interpolate Point */
6146 /* Opcode range: 0x39 */
6147 /* Stack: uint32... --> */
6148 /* */
David Turner2c4500e2007-02-14 15:08:47 +00006149
6150 /* SOMETIMES, DUMBER CODE IS BETTER CODE */
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00006151
David Turner2c4500e2007-02-14 15:08:47 +00006152 static void
6153 Ins_IP( INS_ARG )
6154 {
6155 FT_F26Dot6 old_range, cur_range;
6156 FT_Vector* orus_base;
6157 FT_Vector* cur_base;
David Turner89020d92007-03-17 17:48:57 +00006158 FT_Int twilight;
David Turner2c4500e2007-02-14 15:08:47 +00006159
6160 FT_UNUSED_ARG;
6161
6162
6163 if ( CUR.top < CUR.GS.loop )
6164 {
6165 CUR.error = TT_Err_Invalid_Reference;
6166 return;
6167 }
6168
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00006169 /*
David Turner89020d92007-03-17 17:48:57 +00006170 * We need to deal in a special way with the twilight zone.
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00006171 * Otherwise, by definition, the value of CUR.twilight.orus[n] is (0,0),
David Turner89020d92007-03-17 17:48:57 +00006172 * for every n.
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00006173 */
Werner Lembergc9f6c662007-03-21 13:30:14 +00006174 twilight = CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 || CUR.GS.gep2 == 0;
David Turner2c4500e2007-02-14 15:08:47 +00006175
Werner Lemberge12ed562007-06-17 05:31:23 +00006176 if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) )
David Turner815911a2007-06-16 17:07:20 +00006177 {
6178 if ( CUR.pedantic_hinting )
6179 CUR.error = TT_Err_Invalid_Reference;
6180 return;
6181 }
6182
Werner Lembergc9f6c662007-03-21 13:30:14 +00006183 if ( twilight )
6184 orus_base = &CUR.zp0.org[CUR.GS.rp1];
David Turner89020d92007-03-17 17:48:57 +00006185 else
Werner Lembergc9f6c662007-03-21 13:30:14 +00006186 orus_base = &CUR.zp0.orus[CUR.GS.rp1];
David Turner89020d92007-03-17 17:48:57 +00006187
6188 cur_base = &CUR.zp0.cur[CUR.GS.rp1];
David Turner2c4500e2007-02-14 15:08:47 +00006189
Werner Lembergc9f6c662007-03-21 13:30:14 +00006190 /* XXX: There are some glyphs in some braindead but popular */
6191 /* fonts out there (e.g. [aeu]grave in monotype.ttf) */
6192 /* calling IP[] with bad values of rp[12]. */
6193 /* Do something sane when this odd thing happens. */
David Turner2c4500e2007-02-14 15:08:47 +00006194 if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ||
6195 BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) )
6196 {
6197 old_range = 0;
6198 cur_range = 0;
6199 }
6200 else
6201 {
Werner Lembergc9f6c662007-03-21 13:30:14 +00006202 if ( twilight )
6203 old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2],
6204 orus_base );
David Turner89020d92007-03-17 17:48:57 +00006205 else
Werner Lembergc9f6c662007-03-21 13:30:14 +00006206 old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2],
6207 orus_base );
David Turner89020d92007-03-17 17:48:57 +00006208
Werner Lembergc9f6c662007-03-21 13:30:14 +00006209 cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base );
David Turner2c4500e2007-02-14 15:08:47 +00006210 }
6211
6212 for ( ; CUR.GS.loop > 0; --CUR.GS.loop )
6213 {
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00006214 FT_UInt point = (FT_UInt)CUR.stack[--CUR.args];
David Turner2c4500e2007-02-14 15:08:47 +00006215 FT_F26Dot6 org_dist, cur_dist, new_dist;
6216
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00006217
David Turner2c4500e2007-02-14 15:08:47 +00006218 /* check point bounds */
6219 if ( BOUNDS( point, CUR.zp2.n_points ) )
6220 {
6221 if ( CUR.pedantic_hinting )
6222 {
6223 CUR.error = TT_Err_Invalid_Reference;
6224 return;
6225 }
6226 continue;
6227 }
6228
Werner Lembergc9f6c662007-03-21 13:30:14 +00006229 if ( twilight )
David Turner89020d92007-03-17 17:48:57 +00006230 org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base );
6231 else
6232 org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base );
6233
David Turner2c4500e2007-02-14 15:08:47 +00006234 cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base );
Werner Lembergc9f6c662007-03-21 13:30:14 +00006235 new_dist = ( old_range != 0 )
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00006236 ? TT_MULDIV( org_dist, cur_range, old_range )
6237 : cur_dist;
David Turner2c4500e2007-02-14 15:08:47 +00006238
Werner Lemberg94be20e2007-05-09 20:02:55 +00006239 CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
David Turner2c4500e2007-02-14 15:08:47 +00006240 }
6241 CUR.GS.loop = 1;
6242 CUR.new_top = CUR.args;
6243 }
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00006244
David Turnerd2b1f351999-12-16 23:11:37 +00006245
6246 /*************************************************************************/
6247 /* */
6248 /* UTP[a]: UnTouch Point */
6249 /* Opcode range: 0x29 */
6250 /* Stack: uint32 --> */
6251 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006252 static void
6253 Ins_UTP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00006254 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006255 FT_UShort point;
6256 FT_Byte mask;
David Turnerd2b1f351999-12-16 23:11:37 +00006257
6258
David Turnerf9b8dec2000-06-16 19:34:52 +00006259 point = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00006260
6261 if ( BOUNDS( point, CUR.zp0.n_points ) )
6262 {
6263 if ( CUR.pedantic_hinting )
6264 CUR.error = TT_Err_Invalid_Reference;
6265 return;
6266 }
6267
6268 mask = 0xFF;
6269
6270 if ( CUR.GS.freeVector.x != 0 )
David Turnerb08fe2d2002-08-27 20:20:29 +00006271 mask &= ~FT_CURVE_TAG_TOUCH_X;
David Turnerd2b1f351999-12-16 23:11:37 +00006272
6273 if ( CUR.GS.freeVector.y != 0 )
David Turnerb08fe2d2002-08-27 20:20:29 +00006274 mask &= ~FT_CURVE_TAG_TOUCH_Y;
David Turnerd2b1f351999-12-16 23:11:37 +00006275
David Turner41dbcbf2000-03-09 11:46:25 +00006276 CUR.zp0.tags[point] &= mask;
David Turnerd2b1f351999-12-16 23:11:37 +00006277 }
6278
6279
6280 /* Local variables for Ins_IUP: */
Werner Lemberg2b0b4222008-05-28 22:17:28 +00006281 typedef struct IUP_WorkerRec_
David Turnerd2b1f351999-12-16 23:11:37 +00006282 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006283 FT_Vector* orgs; /* original and current coordinate */
6284 FT_Vector* curs; /* arrays */
David Turner33f5f242006-08-16 16:50:55 +00006285 FT_Vector* orus;
David Turner815911a2007-06-16 17:07:20 +00006286 FT_UInt max_points;
David Turner33f5f242006-08-16 16:50:55 +00006287
6288 } IUP_WorkerRec, *IUP_Worker;
David Turnerd2b1f351999-12-16 23:11:37 +00006289
6290
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006291 static void
David Turner33f5f242006-08-16 16:50:55 +00006292 _iup_worker_shift( IUP_Worker worker,
6293 FT_UInt p1,
6294 FT_UInt p2,
6295 FT_UInt p )
David Turnerd2b1f351999-12-16 23:11:37 +00006296 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006297 FT_UInt i;
David Turner33f5f242006-08-16 16:50:55 +00006298 FT_F26Dot6 dx;
David Turnerd2b1f351999-12-16 23:11:37 +00006299
Werner Lemberg78575dc2000-06-12 19:36:41 +00006300
David Turner33f5f242006-08-16 16:50:55 +00006301 dx = worker->curs[p].x - worker->orgs[p].x;
6302 if ( dx != 0 )
6303 {
6304 for ( i = p1; i < p; i++ )
6305 worker->curs[i].x += dx;
David Turnerd2b1f351999-12-16 23:11:37 +00006306
David Turner33f5f242006-08-16 16:50:55 +00006307 for ( i = p + 1; i <= p2; i++ )
6308 worker->curs[i].x += dx;
6309 }
David Turnerd2b1f351999-12-16 23:11:37 +00006310 }
6311
6312
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006313 static void
David Turner33f5f242006-08-16 16:50:55 +00006314 _iup_worker_interpolate( IUP_Worker worker,
6315 FT_UInt p1,
6316 FT_UInt p2,
6317 FT_UInt ref1,
6318 FT_UInt ref2 )
David Turnerd2b1f351999-12-16 23:11:37 +00006319 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006320 FT_UInt i;
David Turner33f5f242006-08-16 16:50:55 +00006321 FT_F26Dot6 orus1, orus2, org1, org2, delta1, delta2;
David Turnerd2b1f351999-12-16 23:11:37 +00006322
Werner Lemberg78575dc2000-06-12 19:36:41 +00006323
David Turnerd2b1f351999-12-16 23:11:37 +00006324 if ( p1 > p2 )
6325 return;
6326
Werner Lemberge12ed562007-06-17 05:31:23 +00006327 if ( BOUNDS( ref1, worker->max_points ) ||
6328 BOUNDS( ref2, worker->max_points ) )
David Turner815911a2007-06-16 17:07:20 +00006329 return;
6330
David Turner33f5f242006-08-16 16:50:55 +00006331 orus1 = worker->orus[ref1].x;
6332 orus2 = worker->orus[ref2].x;
David Turnerd2b1f351999-12-16 23:11:37 +00006333
Werner Lemberg12342992006-08-19 11:18:09 +00006334 if ( orus1 > orus2 )
David Turnerd2b1f351999-12-16 23:11:37 +00006335 {
David Turner33f5f242006-08-16 16:50:55 +00006336 FT_F26Dot6 tmp_o;
6337 FT_UInt tmp_r;
David Turnerd2b1f351999-12-16 23:11:37 +00006338
Werner Lemberg12342992006-08-19 11:18:09 +00006339
6340 tmp_o = orus1;
6341 orus1 = orus2;
6342 orus2 = tmp_o;
6343
6344 tmp_r = ref1;
6345 ref1 = ref2;
6346 ref2 = tmp_r;
David Turnerd2b1f351999-12-16 23:11:37 +00006347 }
6348
David Turner33f5f242006-08-16 16:50:55 +00006349 org1 = worker->orgs[ref1].x;
6350 org2 = worker->orgs[ref2].x;
6351 delta1 = worker->curs[ref1].x - org1;
6352 delta2 = worker->curs[ref2].x - org2;
6353
6354 if ( orus1 == orus2 )
David Turnerd2b1f351999-12-16 23:11:37 +00006355 {
David Turner33f5f242006-08-16 16:50:55 +00006356 /* simple shift of untouched points */
David Turnerd2b1f351999-12-16 23:11:37 +00006357 for ( i = p1; i <= p2; i++ )
6358 {
David Turner33f5f242006-08-16 16:50:55 +00006359 FT_F26Dot6 x = worker->orgs[i].x;
David Turnerd2b1f351999-12-16 23:11:37 +00006360
Werner Lemberg12342992006-08-19 11:18:09 +00006361
David Turner33f5f242006-08-16 16:50:55 +00006362 if ( x <= org1 )
6363 x += delta1;
6364 else
6365 x += delta2;
6366
6367 worker->curs[i].x = x;
6368 }
6369 }
6370 else
6371 {
6372 FT_Fixed scale = 0;
6373 FT_Bool scale_valid = 0;
6374
Werner Lemberg12342992006-08-19 11:18:09 +00006375
David Turner33f5f242006-08-16 16:50:55 +00006376 /* interpolation */
6377 for ( i = p1; i <= p2; i++ )
6378 {
6379 FT_F26Dot6 x = worker->orgs[i].x;
6380
Werner Lemberg12342992006-08-19 11:18:09 +00006381
David Turner33f5f242006-08-16 16:50:55 +00006382 if ( x <= org1 )
6383 x += delta1;
6384
6385 else if ( x >= org2 )
6386 x += delta2;
6387
David Turnerd2b1f351999-12-16 23:11:37 +00006388 else
6389 {
David Turner33f5f242006-08-16 16:50:55 +00006390 if ( !scale_valid )
6391 {
6392 scale_valid = 1;
Werner Lemberg12342992006-08-19 11:18:09 +00006393 scale = TT_MULDIV( org2 + delta2 - ( org1 + delta1 ),
6394 0x10000, orus2 - orus1 );
David Turner33f5f242006-08-16 16:50:55 +00006395 }
6396
Werner Lemberg12342992006-08-19 11:18:09 +00006397 x = ( org1 + delta1 ) +
6398 TT_MULFIX( worker->orus[i].x - orus1, scale );
David Turnerd2b1f351999-12-16 23:11:37 +00006399 }
David Turner33f5f242006-08-16 16:50:55 +00006400 worker->curs[i].x = x;
David Turnerd2b1f351999-12-16 23:11:37 +00006401 }
David Turnerd2b1f351999-12-16 23:11:37 +00006402 }
6403 }
6404
6405
6406 /*************************************************************************/
6407 /* */
6408 /* IUP[a]: Interpolate Untouched Points */
6409 /* Opcode range: 0x30-0x31 */
6410 /* Stack: --> */
6411 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006412 static void
6413 Ins_IUP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00006414 {
David Turner33f5f242006-08-16 16:50:55 +00006415 IUP_WorkerRec V;
6416 FT_Byte mask;
David Turnerd2b1f351999-12-16 23:11:37 +00006417
David Turnerf9b8dec2000-06-16 19:34:52 +00006418 FT_UInt first_point; /* first point of contour */
6419 FT_UInt end_point; /* end point (last+1) of contour */
David Turnerd2b1f351999-12-16 23:11:37 +00006420
David Turnerf9b8dec2000-06-16 19:34:52 +00006421 FT_UInt first_touched; /* first touched point in contour */
6422 FT_UInt cur_touched; /* current touched point in contour */
David Turnerd2b1f351999-12-16 23:11:37 +00006423
David Turnerf9b8dec2000-06-16 19:34:52 +00006424 FT_UInt point; /* current point */
6425 FT_Short contour; /* current contour */
David Turnerd2b1f351999-12-16 23:11:37 +00006426
David Turnerc6a92202000-07-04 18:12:13 +00006427 FT_UNUSED_ARG;
David Turnerd2b1f351999-12-16 23:11:37 +00006428
Werner Lemberge12ed562007-06-17 05:31:23 +00006429
David Turner815911a2007-06-16 17:07:20 +00006430 /* ignore empty outlines */
6431 if ( CUR.pts.n_contours == 0 )
6432 return;
Werner Lemberg78575dc2000-06-12 19:36:41 +00006433
David Turnerd2b1f351999-12-16 23:11:37 +00006434 if ( CUR.opcode & 1 )
6435 {
David Turnerb08fe2d2002-08-27 20:20:29 +00006436 mask = FT_CURVE_TAG_TOUCH_X;
David Turnerd2b1f351999-12-16 23:11:37 +00006437 V.orgs = CUR.pts.org;
6438 V.curs = CUR.pts.cur;
David Turner33f5f242006-08-16 16:50:55 +00006439 V.orus = CUR.pts.orus;
David Turnerd2b1f351999-12-16 23:11:37 +00006440 }
6441 else
6442 {
David Turnerb08fe2d2002-08-27 20:20:29 +00006443 mask = FT_CURVE_TAG_TOUCH_Y;
David Turner43a2f652000-07-05 18:23:38 +00006444 V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
6445 V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
David Turner33f5f242006-08-16 16:50:55 +00006446 V.orus = (FT_Vector*)( (FT_Pos*)CUR.pts.orus + 1 );
David Turnerd2b1f351999-12-16 23:11:37 +00006447 }
David Turner74cc0e92007-06-30 22:54:12 +00006448 V.max_points = CUR.pts.n_points;
David Turnerd2b1f351999-12-16 23:11:37 +00006449
6450 contour = 0;
6451 point = 0;
6452
6453 do
6454 {
Werner Lemberga2da05c2006-06-25 06:27:27 +00006455 end_point = CUR.pts.contours[contour] - CUR.pts.first_point;
David Turnerd2b1f351999-12-16 23:11:37 +00006456 first_point = point;
6457
Werner Lemberg28464c42008-02-18 20:34:42 +00006458 if ( CUR.pts.n_points <= end_point )
6459 end_point = CUR.pts.n_points;
6460
Werner Lembergc9f6c662007-03-21 13:30:14 +00006461 while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00006462 point++;
6463
6464 if ( point <= end_point )
6465 {
6466 first_touched = point;
6467 cur_touched = point;
6468
6469 point++;
6470
6471 while ( point <= end_point )
6472 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00006473 if ( ( CUR.pts.tags[point] & mask ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00006474 {
6475 if ( point > 0 )
David Turner33f5f242006-08-16 16:50:55 +00006476 _iup_worker_interpolate( &V,
6477 cur_touched + 1,
6478 point - 1,
6479 cur_touched,
6480 point );
David Turnerd2b1f351999-12-16 23:11:37 +00006481 cur_touched = point;
6482 }
6483
6484 point++;
6485 }
6486
6487 if ( cur_touched == first_touched )
David Turner33f5f242006-08-16 16:50:55 +00006488 _iup_worker_shift( &V, first_point, end_point, cur_touched );
David Turnerd2b1f351999-12-16 23:11:37 +00006489 else
6490 {
David Turner33f5f242006-08-16 16:50:55 +00006491 _iup_worker_interpolate( &V,
6492 (FT_UShort)( cur_touched + 1 ),
6493 end_point,
6494 cur_touched,
6495 first_touched );
David Turnerd2b1f351999-12-16 23:11:37 +00006496
6497 if ( first_touched > 0 )
David Turner33f5f242006-08-16 16:50:55 +00006498 _iup_worker_interpolate( &V,
6499 first_point,
6500 first_touched - 1,
6501 cur_touched,
6502 first_touched );
David Turnerd2b1f351999-12-16 23:11:37 +00006503 }
6504 }
6505 contour++;
6506 } while ( contour < CUR.pts.n_contours );
6507 }
6508
6509
6510 /*************************************************************************/
6511 /* */
6512 /* DELTAPn[]: DELTA exceptions P1, P2, P3 */
6513 /* Opcode range: 0x5D,0x71,0x72 */
6514 /* Stack: uint32 (2 * uint32)... --> */
6515 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006516 static void
6517 Ins_DELTAP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00006518 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006519 FT_ULong k, nump;
6520 FT_UShort A;
6521 FT_ULong C;
6522 FT_Long B;
David Turnerd2b1f351999-12-16 23:11:37 +00006523
Werner Lemberg82ee38e2006-11-20 09:19:26 +00006524
David Turner8b6db862003-08-17 22:09:14 +00006525#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Graham Asher3ea859f2003-04-25 11:40:46 +00006526 /* Delta hinting is covered by US Patent 5159668. */
6527 if ( CUR.face->unpatented_hinting )
Werner Lemberg82ee38e2006-11-20 09:19:26 +00006528 {
6529 FT_Long n = args[0] * 2;
6530
6531
Graham Asher3ea859f2003-04-25 11:40:46 +00006532 if ( CUR.args < n )
6533 {
6534 CUR.error = TT_Err_Too_Few_Arguments;
6535 return;
6536 }
6537
Werner Lemberga3f4da82003-04-29 13:23:47 +00006538 CUR.args -= n;
Graham Asher3ea859f2003-04-25 11:40:46 +00006539 CUR.new_top = CUR.args;
6540 return;
6541 }
6542#endif
David Turnerd2b1f351999-12-16 23:11:37 +00006543
David Turnerf9b8dec2000-06-16 19:34:52 +00006544 nump = (FT_ULong)args[0]; /* some points theoretically may occur more
David Turnerd2b1f351999-12-16 23:11:37 +00006545 than once, thus UShort isn't enough */
6546
6547 for ( k = 1; k <= nump; k++ )
6548 {
6549 if ( CUR.args < 2 )
6550 {
6551 CUR.error = TT_Err_Too_Few_Arguments;
6552 return;
6553 }
6554
6555 CUR.args -= 2;
6556
David Turnerf9b8dec2000-06-16 19:34:52 +00006557 A = (FT_UShort)CUR.stack[CUR.args + 1];
David Turnerd2b1f351999-12-16 23:11:37 +00006558 B = CUR.stack[CUR.args];
6559
Werner Lemberg78575dc2000-06-12 19:36:41 +00006560 /* XXX: Because some popular fonts contain some invalid DeltaP */
6561 /* instructions, we simply ignore them when the stacked */
6562 /* point reference is off limit, rather than returning an */
6563 /* error. As a delta instruction doesn't change a glyph */
6564 /* in great ways, this shouldn't be a problem. */
David Turnerd2b1f351999-12-16 23:11:37 +00006565
6566 if ( !BOUNDS( A, CUR.zp0.n_points ) )
6567 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006568 C = ( (FT_ULong)B & 0xF0 ) >> 4;
David Turnerd2b1f351999-12-16 23:11:37 +00006569
6570 switch ( CUR.opcode )
6571 {
6572 case 0x5D:
6573 break;
6574
6575 case 0x71:
6576 C += 16;
6577 break;
6578
6579 case 0x72:
6580 C += 32;
6581 break;
6582 }
6583
6584 C += CUR.GS.delta_base;
6585
David Turnerf9b8dec2000-06-16 19:34:52 +00006586 if ( CURRENT_Ppem() == (FT_Long)C )
David Turnerd2b1f351999-12-16 23:11:37 +00006587 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006588 B = ( (FT_ULong)B & 0xF ) - 8;
David Turnerd2b1f351999-12-16 23:11:37 +00006589 if ( B >= 0 )
6590 B++;
Werner Lemberg78575dc2000-06-12 19:36:41 +00006591 B = B * 64 / ( 1L << CUR.GS.delta_shift );
David Turnerd2b1f351999-12-16 23:11:37 +00006592
6593 CUR_Func_move( &CUR.zp0, A, B );
6594 }
6595 }
6596 else
6597 if ( CUR.pedantic_hinting )
6598 CUR.error = TT_Err_Invalid_Reference;
6599 }
6600
6601 CUR.new_top = CUR.args;
6602 }
6603
6604
6605 /*************************************************************************/
6606 /* */
6607 /* DELTACn[]: DELTA exceptions C1, C2, C3 */
6608 /* Opcode range: 0x73,0x74,0x75 */
6609 /* Stack: uint32 (2 * uint32)... --> */
6610 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006611 static void
6612 Ins_DELTAC( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00006613 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006614 FT_ULong nump, k;
6615 FT_ULong A, C;
6616 FT_Long B;
David Turnerd2b1f351999-12-16 23:11:37 +00006617
Werner Lemberga3f4da82003-04-29 13:23:47 +00006618
David Turner8b6db862003-08-17 22:09:14 +00006619#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Graham Asher3ea859f2003-04-25 11:40:46 +00006620 /* Delta hinting is covered by US Patent 5159668. */
6621 if ( CUR.face->unpatented_hinting )
Werner Lemberga3f4da82003-04-29 13:23:47 +00006622 {
6623 FT_Long n = args[0] * 2;
6624
6625
Graham Asher3ea859f2003-04-25 11:40:46 +00006626 if ( CUR.args < n )
6627 {
6628 CUR.error = TT_Err_Too_Few_Arguments;
6629 return;
6630 }
6631
Werner Lemberga3f4da82003-04-29 13:23:47 +00006632 CUR.args -= n;
Graham Asher3ea859f2003-04-25 11:40:46 +00006633 CUR.new_top = CUR.args;
6634 return;
6635 }
6636#endif
David Turnerd2b1f351999-12-16 23:11:37 +00006637
David Turnerf9b8dec2000-06-16 19:34:52 +00006638 nump = (FT_ULong)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00006639
6640 for ( k = 1; k <= nump; k++ )
6641 {
6642 if ( CUR.args < 2 )
6643 {
6644 CUR.error = TT_Err_Too_Few_Arguments;
6645 return;
6646 }
6647
6648 CUR.args -= 2;
6649
David Turnerf9b8dec2000-06-16 19:34:52 +00006650 A = (FT_ULong)CUR.stack[CUR.args + 1];
David Turnerd2b1f351999-12-16 23:11:37 +00006651 B = CUR.stack[CUR.args];
6652
6653 if ( BOUNDS( A, CUR.cvtSize ) )
6654 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00006655 if ( CUR.pedantic_hinting )
David Turnerd2b1f351999-12-16 23:11:37 +00006656 {
6657 CUR.error = TT_Err_Invalid_Reference;
6658 return;
6659 }
6660 }
6661 else
6662 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006663 C = ( (FT_ULong)B & 0xF0 ) >> 4;
David Turnerd2b1f351999-12-16 23:11:37 +00006664
6665 switch ( CUR.opcode )
6666 {
6667 case 0x73:
6668 break;
6669
6670 case 0x74:
6671 C += 16;
6672 break;
6673
6674 case 0x75:
6675 C += 32;
6676 break;
6677 }
6678
6679 C += CUR.GS.delta_base;
6680
David Turnerf9b8dec2000-06-16 19:34:52 +00006681 if ( CURRENT_Ppem() == (FT_Long)C )
David Turnerd2b1f351999-12-16 23:11:37 +00006682 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006683 B = ( (FT_ULong)B & 0xF ) - 8;
David Turnerd2b1f351999-12-16 23:11:37 +00006684 if ( B >= 0 )
6685 B++;
Werner Lemberg78575dc2000-06-12 19:36:41 +00006686 B = B * 64 / ( 1L << CUR.GS.delta_shift );
David Turnerd2b1f351999-12-16 23:11:37 +00006687
6688 CUR_Func_move_cvt( A, B );
6689 }
6690 }
6691 }
6692
6693 CUR.new_top = CUR.args;
6694 }
6695
6696
6697 /*************************************************************************/
6698 /* */
6699 /* MISC. INSTRUCTIONS */
6700 /* */
6701 /*************************************************************************/
6702
6703
6704 /*************************************************************************/
6705 /* */
6706 /* GETINFO[]: GET INFOrmation */
6707 /* Opcode range: 0x88 */
6708 /* Stack: uint32 --> uint32 */
6709 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006710 static void
6711 Ins_GETINFO( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00006712 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006713 FT_Long K;
David Turnerd2b1f351999-12-16 23:11:37 +00006714
6715
6716 K = 0;
6717
Werner Lembergdea712b2004-08-07 15:08:33 +00006718 /* We return MS rasterizer version 1.7 for the font scaler. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00006719 if ( ( args[0] & 1 ) != 0 )
Werner Lembergdea712b2004-08-07 15:08:33 +00006720 K = 35;
David Turnerd2b1f351999-12-16 23:11:37 +00006721
Werner Lembergdea712b2004-08-07 15:08:33 +00006722 /* Has the glyph been rotated? */
6723 if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated )
David Turnerd2b1f351999-12-16 23:11:37 +00006724 K |= 0x80;
6725
Werner Lembergdea712b2004-08-07 15:08:33 +00006726 /* Has the glyph been stretched? */
6727 if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched )
6728 K |= 1 << 8;
6729
6730 /* Are we hinting for grayscale? */
6731 if ( ( args[0] & 32 ) != 0 && CUR.grayscale )
Werner Lemberg2bad8ff2006-11-22 09:37:03 +00006732 K |= 1 << 12;
David Turnerd2b1f351999-12-16 23:11:37 +00006733
6734 args[0] = K;
6735 }
6736
6737
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006738 static void
6739 Ins_UNKNOWN( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00006740 {
6741 TT_DefRecord* def = CUR.IDefs;
6742 TT_DefRecord* limit = def + CUR.numIDefs;
David Turnere49ab252000-05-16 23:44:38 +00006743
David Turnerc6a92202000-07-04 18:12:13 +00006744 FT_UNUSED_ARG;
David Turnere49ab252000-05-16 23:44:38 +00006745
Werner Lemberg78575dc2000-06-12 19:36:41 +00006746
David Turnerd2b1f351999-12-16 23:11:37 +00006747 for ( ; def < limit; def++ )
6748 {
David Turnerb1aabf42000-11-30 23:48:22 +00006749 if ( (FT_Byte)def->opc == CUR.opcode && def->active )
David Turnerd2b1f351999-12-16 23:11:37 +00006750 {
6751 TT_CallRec* call;
David Turnere49ab252000-05-16 23:44:38 +00006752
Werner Lemberg78575dc2000-06-12 19:36:41 +00006753
David Turnerd2b1f351999-12-16 23:11:37 +00006754 if ( CUR.callTop >= CUR.callSize )
6755 {
6756 CUR.error = TT_Err_Stack_Overflow;
6757 return;
6758 }
David Turnere49ab252000-05-16 23:44:38 +00006759
David Turnerd2b1f351999-12-16 23:11:37 +00006760 call = CUR.callStack + CUR.callTop++;
6761
6762 call->Caller_Range = CUR.curRange;
6763 call->Caller_IP = CUR.IP+1;
6764 call->Cur_Count = 1;
6765 call->Cur_Restart = def->start;
David Turnere49ab252000-05-16 23:44:38 +00006766
David Turnerd2b1f351999-12-16 23:11:37 +00006767 INS_Goto_CodeRange( def->range, def->start );
David Turnere49ab252000-05-16 23:44:38 +00006768
David Turnerd2b1f351999-12-16 23:11:37 +00006769 CUR.step_ins = FALSE;
6770 return;
6771 }
6772 }
6773
6774 CUR.error = TT_Err_Invalid_Opcode;
6775 }
6776
6777
6778#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
Werner Lemberg78575dc2000-06-12 19:36:41 +00006779
6780
David Turnerd2b1f351999-12-16 23:11:37 +00006781 static
6782 TInstruction_Function Instruct_Dispatch[256] =
6783 {
6784 /* Opcodes are gathered in groups of 16. */
6785 /* Please keep the spaces as they are. */
6786
6787 /* SVTCA y */ Ins_SVTCA,
6788 /* SVTCA x */ Ins_SVTCA,
6789 /* SPvTCA y */ Ins_SPVTCA,
6790 /* SPvTCA x */ Ins_SPVTCA,
6791 /* SFvTCA y */ Ins_SFVTCA,
6792 /* SFvTCA x */ Ins_SFVTCA,
6793 /* SPvTL // */ Ins_SPVTL,
6794 /* SPvTL + */ Ins_SPVTL,
6795 /* SFvTL // */ Ins_SFVTL,
6796 /* SFvTL + */ Ins_SFVTL,
6797 /* SPvFS */ Ins_SPVFS,
6798 /* SFvFS */ Ins_SFVFS,
6799 /* GPV */ Ins_GPV,
6800 /* GFV */ Ins_GFV,
6801 /* SFvTPv */ Ins_SFVTPV,
6802 /* ISECT */ Ins_ISECT,
6803
6804 /* SRP0 */ Ins_SRP0,
6805 /* SRP1 */ Ins_SRP1,
6806 /* SRP2 */ Ins_SRP2,
6807 /* SZP0 */ Ins_SZP0,
6808 /* SZP1 */ Ins_SZP1,
6809 /* SZP2 */ Ins_SZP2,
6810 /* SZPS */ Ins_SZPS,
6811 /* SLOOP */ Ins_SLOOP,
6812 /* RTG */ Ins_RTG,
6813 /* RTHG */ Ins_RTHG,
6814 /* SMD */ Ins_SMD,
6815 /* ELSE */ Ins_ELSE,
6816 /* JMPR */ Ins_JMPR,
6817 /* SCvTCi */ Ins_SCVTCI,
6818 /* SSwCi */ Ins_SSWCI,
6819 /* SSW */ Ins_SSW,
6820
6821 /* DUP */ Ins_DUP,
6822 /* POP */ Ins_POP,
6823 /* CLEAR */ Ins_CLEAR,
6824 /* SWAP */ Ins_SWAP,
6825 /* DEPTH */ Ins_DEPTH,
6826 /* CINDEX */ Ins_CINDEX,
6827 /* MINDEX */ Ins_MINDEX,
6828 /* AlignPTS */ Ins_ALIGNPTS,
6829 /* INS_0x28 */ Ins_UNKNOWN,
6830 /* UTP */ Ins_UTP,
6831 /* LOOPCALL */ Ins_LOOPCALL,
6832 /* CALL */ Ins_CALL,
6833 /* FDEF */ Ins_FDEF,
6834 /* ENDF */ Ins_ENDF,
6835 /* MDAP[0] */ Ins_MDAP,
6836 /* MDAP[1] */ Ins_MDAP,
6837
6838 /* IUP[0] */ Ins_IUP,
6839 /* IUP[1] */ Ins_IUP,
6840 /* SHP[0] */ Ins_SHP,
6841 /* SHP[1] */ Ins_SHP,
6842 /* SHC[0] */ Ins_SHC,
6843 /* SHC[1] */ Ins_SHC,
6844 /* SHZ[0] */ Ins_SHZ,
6845 /* SHZ[1] */ Ins_SHZ,
6846 /* SHPIX */ Ins_SHPIX,
6847 /* IP */ Ins_IP,
6848 /* MSIRP[0] */ Ins_MSIRP,
6849 /* MSIRP[1] */ Ins_MSIRP,
6850 /* AlignRP */ Ins_ALIGNRP,
6851 /* RTDG */ Ins_RTDG,
6852 /* MIAP[0] */ Ins_MIAP,
6853 /* MIAP[1] */ Ins_MIAP,
6854
6855 /* NPushB */ Ins_NPUSHB,
6856 /* NPushW */ Ins_NPUSHW,
6857 /* WS */ Ins_WS,
6858 /* RS */ Ins_RS,
6859 /* WCvtP */ Ins_WCVTP,
6860 /* RCvt */ Ins_RCVT,
6861 /* GC[0] */ Ins_GC,
6862 /* GC[1] */ Ins_GC,
6863 /* SCFS */ Ins_SCFS,
6864 /* MD[0] */ Ins_MD,
6865 /* MD[1] */ Ins_MD,
6866 /* MPPEM */ Ins_MPPEM,
6867 /* MPS */ Ins_MPS,
6868 /* FlipON */ Ins_FLIPON,
6869 /* FlipOFF */ Ins_FLIPOFF,
6870 /* DEBUG */ Ins_DEBUG,
6871
6872 /* LT */ Ins_LT,
6873 /* LTEQ */ Ins_LTEQ,
6874 /* GT */ Ins_GT,
6875 /* GTEQ */ Ins_GTEQ,
6876 /* EQ */ Ins_EQ,
6877 /* NEQ */ Ins_NEQ,
6878 /* ODD */ Ins_ODD,
6879 /* EVEN */ Ins_EVEN,
6880 /* IF */ Ins_IF,
6881 /* EIF */ Ins_EIF,
6882 /* AND */ Ins_AND,
6883 /* OR */ Ins_OR,
6884 /* NOT */ Ins_NOT,
6885 /* DeltaP1 */ Ins_DELTAP,
6886 /* SDB */ Ins_SDB,
6887 /* SDS */ Ins_SDS,
6888
6889 /* ADD */ Ins_ADD,
6890 /* SUB */ Ins_SUB,
6891 /* DIV */ Ins_DIV,
6892 /* MUL */ Ins_MUL,
6893 /* ABS */ Ins_ABS,
6894 /* NEG */ Ins_NEG,
6895 /* FLOOR */ Ins_FLOOR,
6896 /* CEILING */ Ins_CEILING,
6897 /* ROUND[0] */ Ins_ROUND,
6898 /* ROUND[1] */ Ins_ROUND,
6899 /* ROUND[2] */ Ins_ROUND,
6900 /* ROUND[3] */ Ins_ROUND,
6901 /* NROUND[0] */ Ins_NROUND,
6902 /* NROUND[1] */ Ins_NROUND,
6903 /* NROUND[2] */ Ins_NROUND,
6904 /* NROUND[3] */ Ins_NROUND,
6905
6906 /* WCvtF */ Ins_WCVTF,
6907 /* DeltaP2 */ Ins_DELTAP,
6908 /* DeltaP3 */ Ins_DELTAP,
6909 /* DeltaCn[0] */ Ins_DELTAC,
6910 /* DeltaCn[1] */ Ins_DELTAC,
6911 /* DeltaCn[2] */ Ins_DELTAC,
6912 /* SROUND */ Ins_SROUND,
6913 /* S45Round */ Ins_S45ROUND,
6914 /* JROT */ Ins_JROT,
6915 /* JROF */ Ins_JROF,
6916 /* ROFF */ Ins_ROFF,
6917 /* INS_0x7B */ Ins_UNKNOWN,
6918 /* RUTG */ Ins_RUTG,
6919 /* RDTG */ Ins_RDTG,
6920 /* SANGW */ Ins_SANGW,
6921 /* AA */ Ins_AA,
6922
6923 /* FlipPT */ Ins_FLIPPT,
6924 /* FlipRgON */ Ins_FLIPRGON,
6925 /* FlipRgOFF */ Ins_FLIPRGOFF,
6926 /* INS_0x83 */ Ins_UNKNOWN,
6927 /* INS_0x84 */ Ins_UNKNOWN,
6928 /* ScanCTRL */ Ins_SCANCTRL,
6929 /* SDPVTL[0] */ Ins_SDPVTL,
6930 /* SDPVTL[1] */ Ins_SDPVTL,
6931 /* GetINFO */ Ins_GETINFO,
6932 /* IDEF */ Ins_IDEF,
6933 /* ROLL */ Ins_ROLL,
6934 /* MAX */ Ins_MAX,
6935 /* MIN */ Ins_MIN,
6936 /* ScanTYPE */ Ins_SCANTYPE,
6937 /* InstCTRL */ Ins_INSTCTRL,
6938 /* INS_0x8F */ Ins_UNKNOWN,
6939
6940 /* INS_0x90 */ Ins_UNKNOWN,
6941 /* INS_0x91 */ Ins_UNKNOWN,
6942 /* INS_0x92 */ Ins_UNKNOWN,
6943 /* INS_0x93 */ Ins_UNKNOWN,
6944 /* INS_0x94 */ Ins_UNKNOWN,
6945 /* INS_0x95 */ Ins_UNKNOWN,
6946 /* INS_0x96 */ Ins_UNKNOWN,
6947 /* INS_0x97 */ Ins_UNKNOWN,
6948 /* INS_0x98 */ Ins_UNKNOWN,
6949 /* INS_0x99 */ Ins_UNKNOWN,
6950 /* INS_0x9A */ Ins_UNKNOWN,
6951 /* INS_0x9B */ Ins_UNKNOWN,
6952 /* INS_0x9C */ Ins_UNKNOWN,
6953 /* INS_0x9D */ Ins_UNKNOWN,
6954 /* INS_0x9E */ Ins_UNKNOWN,
6955 /* INS_0x9F */ Ins_UNKNOWN,
6956
6957 /* INS_0xA0 */ Ins_UNKNOWN,
6958 /* INS_0xA1 */ Ins_UNKNOWN,
6959 /* INS_0xA2 */ Ins_UNKNOWN,
6960 /* INS_0xA3 */ Ins_UNKNOWN,
6961 /* INS_0xA4 */ Ins_UNKNOWN,
6962 /* INS_0xA5 */ Ins_UNKNOWN,
6963 /* INS_0xA6 */ Ins_UNKNOWN,
6964 /* INS_0xA7 */ Ins_UNKNOWN,
6965 /* INS_0xA8 */ Ins_UNKNOWN,
6966 /* INS_0xA9 */ Ins_UNKNOWN,
6967 /* INS_0xAA */ Ins_UNKNOWN,
6968 /* INS_0xAB */ Ins_UNKNOWN,
6969 /* INS_0xAC */ Ins_UNKNOWN,
6970 /* INS_0xAD */ Ins_UNKNOWN,
6971 /* INS_0xAE */ Ins_UNKNOWN,
6972 /* INS_0xAF */ Ins_UNKNOWN,
6973
6974 /* PushB[0] */ Ins_PUSHB,
6975 /* PushB[1] */ Ins_PUSHB,
6976 /* PushB[2] */ Ins_PUSHB,
6977 /* PushB[3] */ Ins_PUSHB,
6978 /* PushB[4] */ Ins_PUSHB,
6979 /* PushB[5] */ Ins_PUSHB,
6980 /* PushB[6] */ Ins_PUSHB,
6981 /* PushB[7] */ Ins_PUSHB,
6982 /* PushW[0] */ Ins_PUSHW,
6983 /* PushW[1] */ Ins_PUSHW,
6984 /* PushW[2] */ Ins_PUSHW,
6985 /* PushW[3] */ Ins_PUSHW,
6986 /* PushW[4] */ Ins_PUSHW,
6987 /* PushW[5] */ Ins_PUSHW,
6988 /* PushW[6] */ Ins_PUSHW,
6989 /* PushW[7] */ Ins_PUSHW,
6990
6991 /* MDRP[00] */ Ins_MDRP,
6992 /* MDRP[01] */ Ins_MDRP,
6993 /* MDRP[02] */ Ins_MDRP,
6994 /* MDRP[03] */ Ins_MDRP,
6995 /* MDRP[04] */ Ins_MDRP,
6996 /* MDRP[05] */ Ins_MDRP,
6997 /* MDRP[06] */ Ins_MDRP,
6998 /* MDRP[07] */ Ins_MDRP,
6999 /* MDRP[08] */ Ins_MDRP,
7000 /* MDRP[09] */ Ins_MDRP,
7001 /* MDRP[10] */ Ins_MDRP,
7002 /* MDRP[11] */ Ins_MDRP,
7003 /* MDRP[12] */ Ins_MDRP,
7004 /* MDRP[13] */ Ins_MDRP,
7005 /* MDRP[14] */ Ins_MDRP,
7006 /* MDRP[15] */ Ins_MDRP,
7007
7008 /* MDRP[16] */ Ins_MDRP,
7009 /* MDRP[17] */ Ins_MDRP,
7010 /* MDRP[18] */ Ins_MDRP,
7011 /* MDRP[19] */ Ins_MDRP,
7012 /* MDRP[20] */ Ins_MDRP,
7013 /* MDRP[21] */ Ins_MDRP,
7014 /* MDRP[22] */ Ins_MDRP,
7015 /* MDRP[23] */ Ins_MDRP,
7016 /* MDRP[24] */ Ins_MDRP,
7017 /* MDRP[25] */ Ins_MDRP,
7018 /* MDRP[26] */ Ins_MDRP,
7019 /* MDRP[27] */ Ins_MDRP,
7020 /* MDRP[28] */ Ins_MDRP,
7021 /* MDRP[29] */ Ins_MDRP,
7022 /* MDRP[30] */ Ins_MDRP,
7023 /* MDRP[31] */ Ins_MDRP,
7024
7025 /* MIRP[00] */ Ins_MIRP,
7026 /* MIRP[01] */ Ins_MIRP,
7027 /* MIRP[02] */ Ins_MIRP,
7028 /* MIRP[03] */ Ins_MIRP,
7029 /* MIRP[04] */ Ins_MIRP,
7030 /* MIRP[05] */ Ins_MIRP,
7031 /* MIRP[06] */ Ins_MIRP,
7032 /* MIRP[07] */ Ins_MIRP,
7033 /* MIRP[08] */ Ins_MIRP,
7034 /* MIRP[09] */ Ins_MIRP,
7035 /* MIRP[10] */ Ins_MIRP,
7036 /* MIRP[11] */ Ins_MIRP,
7037 /* MIRP[12] */ Ins_MIRP,
7038 /* MIRP[13] */ Ins_MIRP,
7039 /* MIRP[14] */ Ins_MIRP,
7040 /* MIRP[15] */ Ins_MIRP,
7041
7042 /* MIRP[16] */ Ins_MIRP,
7043 /* MIRP[17] */ Ins_MIRP,
7044 /* MIRP[18] */ Ins_MIRP,
7045 /* MIRP[19] */ Ins_MIRP,
7046 /* MIRP[20] */ Ins_MIRP,
7047 /* MIRP[21] */ Ins_MIRP,
7048 /* MIRP[22] */ Ins_MIRP,
7049 /* MIRP[23] */ Ins_MIRP,
7050 /* MIRP[24] */ Ins_MIRP,
7051 /* MIRP[25] */ Ins_MIRP,
7052 /* MIRP[26] */ Ins_MIRP,
7053 /* MIRP[27] */ Ins_MIRP,
7054 /* MIRP[28] */ Ins_MIRP,
7055 /* MIRP[29] */ Ins_MIRP,
7056 /* MIRP[30] */ Ins_MIRP,
7057 /* MIRP[31] */ Ins_MIRP
7058 };
Werner Lemberg78575dc2000-06-12 19:36:41 +00007059
7060
David Turnerd2b1f351999-12-16 23:11:37 +00007061#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
7062
7063
7064 /*************************************************************************/
7065 /* */
7066 /* RUN */
7067 /* */
7068 /* This function executes a run of opcodes. It will exit in the */
7069 /* following cases: */
7070 /* */
7071 /* - Errors (in which case it returns FALSE). */
7072 /* */
7073 /* - Reaching the end of the main code range (returns TRUE). */
7074 /* Reaching the end of a code range within a function call is an */
7075 /* error. */
7076 /* */
7077 /* - After executing one single opcode, if the flag `Instruction_Trap' */
7078 /* is set to TRUE (returns TRUE). */
7079 /* */
Werner Lemberg6e87ed92007-01-26 22:18:56 +00007080 /* On exit with TRUE, test IP < CodeSize to know whether it comes from */
David Turnerd2b1f351999-12-16 23:11:37 +00007081 /* an instruction trap or a normal termination. */
7082 /* */
7083 /* */
7084 /* Note: The documented DEBUG opcode pops a value from the stack. This */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007085 /* behaviour is unsupported; here a DEBUG opcode is always an */
David Turnerd2b1f351999-12-16 23:11:37 +00007086 /* error. */
7087 /* */
7088 /* */
7089 /* THIS IS THE INTERPRETER'S MAIN LOOP. */
7090 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007091 /* Instructions appear in the specification's order. */
David Turnerd2b1f351999-12-16 23:11:37 +00007092 /* */
7093 /*************************************************************************/
7094
7095
Werner Lemberg90a03302000-11-07 17:21:11 +00007096 /* documentation is in ttinterp.h */
7097
Werner Lemberg4a2305c2001-06-28 07:17:51 +00007098 FT_EXPORT_DEF( FT_Error )
7099 TT_RunIns( TT_ExecContext exc )
David Turnerd2b1f351999-12-16 23:11:37 +00007100 {
David Turnerf9b8dec2000-06-16 19:34:52 +00007101 FT_Long ins_counter = 0; /* executed instructions counter */
David Turnerd2b1f351999-12-16 23:11:37 +00007102
Werner Lemberg78575dc2000-06-12 19:36:41 +00007103
7104#ifdef TT_CONFIG_OPTION_STATIC_RASTER
David Turnerd2b1f351999-12-16 23:11:37 +00007105 cur = *exc;
Werner Lemberg78575dc2000-06-12 19:36:41 +00007106#endif
David Turnerd2b1f351999-12-16 23:11:37 +00007107
7108 /* set CVT functions */
7109 CUR.tt_metrics.ratio = 0;
7110 if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
7111 {
7112 /* non-square pixels, use the stretched routines */
7113 CUR.func_read_cvt = Read_CVT_Stretched;
7114 CUR.func_write_cvt = Write_CVT_Stretched;
7115 CUR.func_move_cvt = Move_CVT_Stretched;
7116 }
7117 else
7118 {
7119 /* square pixels, use normal routines */
7120 CUR.func_read_cvt = Read_CVT;
7121 CUR.func_write_cvt = Write_CVT;
7122 CUR.func_move_cvt = Move_CVT;
7123 }
7124
7125 COMPUTE_Funcs();
David Turnerf9b8dec2000-06-16 19:34:52 +00007126 COMPUTE_Round( (FT_Byte)exc->GS.round_state );
David Turnerd2b1f351999-12-16 23:11:37 +00007127
7128 do
7129 {
7130 CUR.opcode = CUR.code[CUR.IP];
7131
7132 if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
7133 {
7134 if ( CUR.IP + 1 > CUR.codeSize )
7135 goto LErrorCodeOverflow_;
7136
Werner Lemberg33febc02004-10-09 07:07:43 +00007137 CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
David Turnerd2b1f351999-12-16 23:11:37 +00007138 }
7139
7140 if ( CUR.IP + CUR.length > CUR.codeSize )
7141 goto LErrorCodeOverflow_;
7142
7143 /* First, let's check for empty stack and overflow */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007144 CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );
David Turnerd2b1f351999-12-16 23:11:37 +00007145
7146 /* `args' is the top of the stack once arguments have been popped. */
7147 /* One can also interpret it as the index of the last argument. */
7148 if ( CUR.args < 0 )
7149 {
7150 CUR.error = TT_Err_Too_Few_Arguments;
7151 goto LErrorLabel_;
7152 }
7153
Werner Lemberg78575dc2000-06-12 19:36:41 +00007154 CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
David Turnerd2b1f351999-12-16 23:11:37 +00007155
7156 /* `new_top' is the new top of the stack, after the instruction's */
7157 /* execution. `top' will be set to `new_top' after the `switch' */
7158 /* statement. */
7159 if ( CUR.new_top > CUR.stackSize )
7160 {
7161 CUR.error = TT_Err_Stack_Overflow;
7162 goto LErrorLabel_;
7163 }
7164
7165 CUR.step_ins = TRUE;
7166 CUR.error = TT_Err_Ok;
7167
7168#ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
Werner Lemberg78575dc2000-06-12 19:36:41 +00007169
David Turnerd2b1f351999-12-16 23:11:37 +00007170 {
David Turnerf9b8dec2000-06-16 19:34:52 +00007171 FT_Long* args = CUR.stack + CUR.args;
7172 FT_Byte opcode = CUR.opcode;
David Turnerd2b1f351999-12-16 23:11:37 +00007173
7174
Werner Lemberg63408a12000-12-13 23:44:37 +00007175#undef ARRAY_BOUND_ERROR
7176#define ARRAY_BOUND_ERROR goto Set_Invalid_Ref
David Turnerd2b1f351999-12-16 23:11:37 +00007177
7178
7179 switch ( opcode )
7180 {
7181 case 0x00: /* SVTCA y */
7182 case 0x01: /* SVTCA x */
7183 case 0x02: /* SPvTCA y */
7184 case 0x03: /* SPvTCA x */
7185 case 0x04: /* SFvTCA y */
7186 case 0x05: /* SFvTCA x */
7187 {
David Turnerf9b8dec2000-06-16 19:34:52 +00007188 FT_Short AA, BB;
David Turnerd2b1f351999-12-16 23:11:37 +00007189
7190
Werner Lemberg2b6248b2001-07-07 23:24:02 +00007191 AA = (FT_Short)( ( opcode & 1 ) << 14 );
David Turner3b7049f2001-07-07 16:12:14 +00007192 BB = (FT_Short)( AA ^ 0x4000 );
David Turnerd2b1f351999-12-16 23:11:37 +00007193
7194 if ( opcode < 4 )
7195 {
7196 CUR.GS.projVector.x = AA;
7197 CUR.GS.projVector.y = BB;
7198
7199 CUR.GS.dualVector.x = AA;
7200 CUR.GS.dualVector.y = BB;
7201 }
Graham Asher3ea859f2003-04-25 11:40:46 +00007202 else
7203 {
7204 GUESS_VECTOR( projVector );
7205 }
David Turnerd2b1f351999-12-16 23:11:37 +00007206
Werner Lemberg78575dc2000-06-12 19:36:41 +00007207 if ( ( opcode & 2 ) == 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00007208 {
7209 CUR.GS.freeVector.x = AA;
7210 CUR.GS.freeVector.y = BB;
7211 }
Graham Asher3ea859f2003-04-25 11:40:46 +00007212 else
7213 {
7214 GUESS_VECTOR( freeVector );
7215 }
David Turnerd2b1f351999-12-16 23:11:37 +00007216
7217 COMPUTE_Funcs();
7218 }
7219 break;
7220
7221 case 0x06: /* SPvTL // */
7222 case 0x07: /* SPvTL + */
7223 DO_SPVTL
7224 break;
7225
7226 case 0x08: /* SFvTL // */
7227 case 0x09: /* SFvTL + */
7228 DO_SFVTL
7229 break;
7230
7231 case 0x0A: /* SPvFS */
7232 DO_SPVFS
7233 break;
7234
7235 case 0x0B: /* SFvFS */
7236 DO_SFVFS
7237 break;
7238
7239 case 0x0C: /* GPV */
7240 DO_GPV
7241 break;
7242
7243 case 0x0D: /* GFV */
7244 DO_GFV
7245 break;
7246
7247 case 0x0E: /* SFvTPv */
7248 DO_SFVTPV
7249 break;
7250
7251 case 0x0F: /* ISECT */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007252 Ins_ISECT( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007253 break;
7254
7255 case 0x10: /* SRP0 */
7256 DO_SRP0
7257 break;
7258
7259 case 0x11: /* SRP1 */
7260 DO_SRP1
7261 break;
7262
7263 case 0x12: /* SRP2 */
7264 DO_SRP2
7265 break;
7266
7267 case 0x13: /* SZP0 */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007268 Ins_SZP0( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007269 break;
7270
7271 case 0x14: /* SZP1 */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007272 Ins_SZP1( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007273 break;
7274
7275 case 0x15: /* SZP2 */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007276 Ins_SZP2( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007277 break;
7278
7279 case 0x16: /* SZPS */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007280 Ins_SZPS( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007281 break;
7282
7283 case 0x17: /* SLOOP */
7284 DO_SLOOP
7285 break;
7286
7287 case 0x18: /* RTG */
7288 DO_RTG
7289 break;
7290
7291 case 0x19: /* RTHG */
7292 DO_RTHG
7293 break;
7294
7295 case 0x1A: /* SMD */
7296 DO_SMD
7297 break;
7298
7299 case 0x1B: /* ELSE */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007300 Ins_ELSE( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007301 break;
7302
7303 case 0x1C: /* JMPR */
7304 DO_JMPR
7305 break;
7306
7307 case 0x1D: /* SCVTCI */
7308 DO_SCVTCI
7309 break;
7310
7311 case 0x1E: /* SSWCI */
7312 DO_SSWCI
7313 break;
7314
7315 case 0x1F: /* SSW */
7316 DO_SSW
7317 break;
7318
7319 case 0x20: /* DUP */
7320 DO_DUP
7321 break;
7322
7323 case 0x21: /* POP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007324 /* nothing :-) */
David Turnerd2b1f351999-12-16 23:11:37 +00007325 break;
7326
7327 case 0x22: /* CLEAR */
7328 DO_CLEAR
7329 break;
7330
7331 case 0x23: /* SWAP */
7332 DO_SWAP
7333 break;
7334
7335 case 0x24: /* DEPTH */
7336 DO_DEPTH
7337 break;
7338
7339 case 0x25: /* CINDEX */
7340 DO_CINDEX
7341 break;
7342
7343 case 0x26: /* MINDEX */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007344 Ins_MINDEX( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007345 break;
7346
7347 case 0x27: /* ALIGNPTS */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007348 Ins_ALIGNPTS( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007349 break;
7350
7351 case 0x28: /* ???? */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007352 Ins_UNKNOWN( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007353 break;
7354
7355 case 0x29: /* UTP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007356 Ins_UTP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007357 break;
7358
7359 case 0x2A: /* LOOPCALL */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007360 Ins_LOOPCALL( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007361 break;
7362
7363 case 0x2B: /* CALL */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007364 Ins_CALL( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007365 break;
7366
7367 case 0x2C: /* FDEF */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007368 Ins_FDEF( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007369 break;
7370
7371 case 0x2D: /* ENDF */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007372 Ins_ENDF( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007373 break;
7374
7375 case 0x2E: /* MDAP */
7376 case 0x2F: /* MDAP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007377 Ins_MDAP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007378 break;
7379
7380
7381 case 0x30: /* IUP */
7382 case 0x31: /* IUP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007383 Ins_IUP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007384 break;
7385
7386 case 0x32: /* SHP */
7387 case 0x33: /* SHP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007388 Ins_SHP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007389 break;
7390
7391 case 0x34: /* SHC */
7392 case 0x35: /* SHC */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007393 Ins_SHC( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007394 break;
7395
7396 case 0x36: /* SHZ */
7397 case 0x37: /* SHZ */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007398 Ins_SHZ( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007399 break;
7400
7401 case 0x38: /* SHPIX */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007402 Ins_SHPIX( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007403 break;
7404
7405 case 0x39: /* IP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007406 Ins_IP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007407 break;
7408
7409 case 0x3A: /* MSIRP */
7410 case 0x3B: /* MSIRP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007411 Ins_MSIRP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007412 break;
7413
7414 case 0x3C: /* AlignRP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007415 Ins_ALIGNRP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007416 break;
7417
7418 case 0x3D: /* RTDG */
7419 DO_RTDG
7420 break;
7421
7422 case 0x3E: /* MIAP */
7423 case 0x3F: /* MIAP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007424 Ins_MIAP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007425 break;
7426
7427 case 0x40: /* NPUSHB */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007428 Ins_NPUSHB( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007429 break;
7430
7431 case 0x41: /* NPUSHW */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007432 Ins_NPUSHW( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007433 break;
7434
7435 case 0x42: /* WS */
7436 DO_WS
7437 break;
7438
Werner Lemberg78575dc2000-06-12 19:36:41 +00007439 Set_Invalid_Ref:
David Turnerd2b1f351999-12-16 23:11:37 +00007440 CUR.error = TT_Err_Invalid_Reference;
7441 break;
7442
7443 case 0x43: /* RS */
7444 DO_RS
7445 break;
7446
7447 case 0x44: /* WCVTP */
7448 DO_WCVTP
7449 break;
7450
7451 case 0x45: /* RCVT */
7452 DO_RCVT
7453 break;
7454
7455 case 0x46: /* GC */
7456 case 0x47: /* GC */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007457 Ins_GC( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007458 break;
7459
7460 case 0x48: /* SCFS */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007461 Ins_SCFS( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007462 break;
7463
7464 case 0x49: /* MD */
7465 case 0x4A: /* MD */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007466 Ins_MD( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007467 break;
7468
7469 case 0x4B: /* MPPEM */
7470 DO_MPPEM
7471 break;
7472
7473 case 0x4C: /* MPS */
7474 DO_MPS
7475 break;
7476
7477 case 0x4D: /* FLIPON */
7478 DO_FLIPON
7479 break;
7480
7481 case 0x4E: /* FLIPOFF */
7482 DO_FLIPOFF
7483 break;
7484
7485 case 0x4F: /* DEBUG */
7486 DO_DEBUG
7487 break;
7488
7489 case 0x50: /* LT */
7490 DO_LT
7491 break;
7492
7493 case 0x51: /* LTEQ */
7494 DO_LTEQ
7495 break;
7496
7497 case 0x52: /* GT */
7498 DO_GT
7499 break;
7500
7501 case 0x53: /* GTEQ */
7502 DO_GTEQ
7503 break;
7504
7505 case 0x54: /* EQ */
7506 DO_EQ
7507 break;
7508
7509 case 0x55: /* NEQ */
7510 DO_NEQ
7511 break;
7512
7513 case 0x56: /* ODD */
7514 DO_ODD
7515 break;
7516
7517 case 0x57: /* EVEN */
7518 DO_EVEN
7519 break;
7520
7521 case 0x58: /* IF */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007522 Ins_IF( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007523 break;
7524
7525 case 0x59: /* EIF */
7526 /* do nothing */
7527 break;
7528
7529 case 0x5A: /* AND */
7530 DO_AND
7531 break;
7532
7533 case 0x5B: /* OR */
7534 DO_OR
7535 break;
7536
7537 case 0x5C: /* NOT */
7538 DO_NOT
7539 break;
7540
7541 case 0x5D: /* DELTAP1 */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007542 Ins_DELTAP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007543 break;
7544
7545 case 0x5E: /* SDB */
7546 DO_SDB
7547 break;
7548
7549 case 0x5F: /* SDS */
7550 DO_SDS
7551 break;
7552
7553 case 0x60: /* ADD */
7554 DO_ADD
7555 break;
7556
7557 case 0x61: /* SUB */
7558 DO_SUB
7559 break;
7560
7561 case 0x62: /* DIV */
7562 DO_DIV
7563 break;
7564
7565 case 0x63: /* MUL */
7566 DO_MUL
7567 break;
7568
7569 case 0x64: /* ABS */
7570 DO_ABS
7571 break;
7572
7573 case 0x65: /* NEG */
7574 DO_NEG
7575 break;
7576
7577 case 0x66: /* FLOOR */
7578 DO_FLOOR
7579 break;
7580
7581 case 0x67: /* CEILING */
7582 DO_CEILING
7583 break;
7584
7585 case 0x68: /* ROUND */
7586 case 0x69: /* ROUND */
7587 case 0x6A: /* ROUND */
7588 case 0x6B: /* ROUND */
7589 DO_ROUND
7590 break;
7591
7592 case 0x6C: /* NROUND */
7593 case 0x6D: /* NROUND */
7594 case 0x6E: /* NRRUND */
7595 case 0x6F: /* NROUND */
7596 DO_NROUND
7597 break;
7598
7599 case 0x70: /* WCVTF */
7600 DO_WCVTF
7601 break;
7602
7603 case 0x71: /* DELTAP2 */
7604 case 0x72: /* DELTAP3 */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007605 Ins_DELTAP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007606 break;
7607
7608 case 0x73: /* DELTAC0 */
7609 case 0x74: /* DELTAC1 */
7610 case 0x75: /* DELTAC2 */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007611 Ins_DELTAC( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007612 break;
7613
7614 case 0x76: /* SROUND */
7615 DO_SROUND
7616 break;
7617
7618 case 0x77: /* S45Round */
7619 DO_S45ROUND
7620 break;
7621
7622 case 0x78: /* JROT */
7623 DO_JROT
7624 break;
7625
7626 case 0x79: /* JROF */
7627 DO_JROF
7628 break;
7629
7630 case 0x7A: /* ROFF */
7631 DO_ROFF
7632 break;
7633
7634 case 0x7B: /* ???? */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007635 Ins_UNKNOWN( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007636 break;
7637
7638 case 0x7C: /* RUTG */
7639 DO_RUTG
7640 break;
7641
7642 case 0x7D: /* RDTG */
7643 DO_RDTG
7644 break;
7645
7646 case 0x7E: /* SANGW */
7647 case 0x7F: /* AA */
7648 /* nothing - obsolete */
7649 break;
7650
7651 case 0x80: /* FLIPPT */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007652 Ins_FLIPPT( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007653 break;
7654
7655 case 0x81: /* FLIPRGON */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007656 Ins_FLIPRGON( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007657 break;
7658
7659 case 0x82: /* FLIPRGOFF */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007660 Ins_FLIPRGOFF( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007661 break;
7662
7663 case 0x83: /* UNKNOWN */
7664 case 0x84: /* UNKNOWN */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007665 Ins_UNKNOWN( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007666 break;
7667
7668 case 0x85: /* SCANCTRL */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007669 Ins_SCANCTRL( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007670 break;
7671
7672 case 0x86: /* SDPVTL */
7673 case 0x87: /* SDPVTL */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007674 Ins_SDPVTL( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007675 break;
7676
7677 case 0x88: /* GETINFO */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007678 Ins_GETINFO( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007679 break;
7680
7681 case 0x89: /* IDEF */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007682 Ins_IDEF( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007683 break;
7684
7685 case 0x8A: /* ROLL */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007686 Ins_ROLL( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007687 break;
7688
7689 case 0x8B: /* MAX */
7690 DO_MAX
7691 break;
7692
7693 case 0x8C: /* MIN */
7694 DO_MIN
7695 break;
7696
7697 case 0x8D: /* SCANTYPE */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007698 Ins_SCANTYPE( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007699 break;
7700
7701 case 0x8E: /* INSTCTRL */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007702 Ins_INSTCTRL( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007703 break;
7704
7705 case 0x8F:
Werner Lemberg78575dc2000-06-12 19:36:41 +00007706 Ins_UNKNOWN( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007707 break;
7708
7709 default:
7710 if ( opcode >= 0xE0 )
Werner Lemberg78575dc2000-06-12 19:36:41 +00007711 Ins_MIRP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007712 else if ( opcode >= 0xC0 )
Werner Lemberg78575dc2000-06-12 19:36:41 +00007713 Ins_MDRP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007714 else if ( opcode >= 0xB8 )
Werner Lemberg78575dc2000-06-12 19:36:41 +00007715 Ins_PUSHW( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007716 else if ( opcode >= 0xB0 )
Werner Lemberg78575dc2000-06-12 19:36:41 +00007717 Ins_PUSHB( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007718 else
Werner Lemberg78575dc2000-06-12 19:36:41 +00007719 Ins_UNKNOWN( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007720 }
7721
7722 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00007723
David Turnerd2b1f351999-12-16 23:11:37 +00007724#else
Werner Lemberg78575dc2000-06-12 19:36:41 +00007725
David Turnerd2b1f351999-12-16 23:11:37 +00007726 Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );
Werner Lemberg78575dc2000-06-12 19:36:41 +00007727
7728#endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
7729
Werner Lemberg79860702001-06-08 21:17:29 +00007730 if ( CUR.error != TT_Err_Ok )
David Turnerd2b1f351999-12-16 23:11:37 +00007731 {
7732 switch ( CUR.error )
7733 {
7734 case TT_Err_Invalid_Opcode: /* looking for redefined instructions */
7735 {
7736 TT_DefRecord* def = CUR.IDefs;
7737 TT_DefRecord* limit = def + CUR.numIDefs;
David Turnere49ab252000-05-16 23:44:38 +00007738
Werner Lemberg78575dc2000-06-12 19:36:41 +00007739
David Turnerd2b1f351999-12-16 23:11:37 +00007740 for ( ; def < limit; def++ )
7741 {
David Turnerb1aabf42000-11-30 23:48:22 +00007742 if ( def->active && CUR.opcode == (FT_Byte)def->opc )
David Turnerd2b1f351999-12-16 23:11:37 +00007743 {
7744 TT_CallRec* callrec;
David Turnere49ab252000-05-16 23:44:38 +00007745
Werner Lemberg78575dc2000-06-12 19:36:41 +00007746
David Turnerd2b1f351999-12-16 23:11:37 +00007747 if ( CUR.callTop >= CUR.callSize )
7748 {
7749 CUR.error = TT_Err_Invalid_Reference;
7750 goto LErrorLabel_;
7751 }
David Turnere49ab252000-05-16 23:44:38 +00007752
David Turnerd2b1f351999-12-16 23:11:37 +00007753 callrec = &CUR.callStack[CUR.callTop];
David Turnere49ab252000-05-16 23:44:38 +00007754
David Turnerd2b1f351999-12-16 23:11:37 +00007755 callrec->Caller_Range = CUR.curRange;
7756 callrec->Caller_IP = CUR.IP + 1;
7757 callrec->Cur_Count = 1;
7758 callrec->Cur_Restart = def->start;
David Turnere49ab252000-05-16 23:44:38 +00007759
David Turnerd2b1f351999-12-16 23:11:37 +00007760 if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
7761 goto LErrorLabel_;
David Turnere49ab252000-05-16 23:44:38 +00007762
David Turnerd2b1f351999-12-16 23:11:37 +00007763 goto LSuiteLabel_;
7764 }
7765 }
7766 }
7767
7768 CUR.error = TT_Err_Invalid_Opcode;
7769 goto LErrorLabel_;
Werner Lemberg78575dc2000-06-12 19:36:41 +00007770
7771#if 0
7772 break; /* Unreachable code warning suppression. */
7773 /* Leave to remind in case a later change the editor */
7774 /* to consider break; */
7775#endif
David Turnerd2b1f351999-12-16 23:11:37 +00007776
7777 default:
7778 goto LErrorLabel_;
Werner Lemberg78575dc2000-06-12 19:36:41 +00007779
7780#if 0
7781 break;
7782#endif
David Turnerd2b1f351999-12-16 23:11:37 +00007783 }
7784 }
7785
7786 CUR.top = CUR.new_top;
7787
7788 if ( CUR.step_ins )
7789 CUR.IP += CUR.length;
7790
Werner Lemberg78575dc2000-06-12 19:36:41 +00007791 /* increment instruction counter and check if we didn't */
7792 /* run this program for too long (e.g. infinite loops). */
David Turnerd2b1f351999-12-16 23:11:37 +00007793 if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
7794 return TT_Err_Execution_Too_Long;
7795
Werner Lemberg78575dc2000-06-12 19:36:41 +00007796 LSuiteLabel_:
David Turnerd2b1f351999-12-16 23:11:37 +00007797 if ( CUR.IP >= CUR.codeSize )
7798 {
7799 if ( CUR.callTop > 0 )
7800 {
7801 CUR.error = TT_Err_Code_Overflow;
7802 goto LErrorLabel_;
7803 }
7804 else
7805 goto LNo_Error_;
7806 }
7807 } while ( !CUR.instruction_trap );
7808
7809 LNo_Error_:
Werner Lemberg78575dc2000-06-12 19:36:41 +00007810
7811#ifdef TT_CONFIG_OPTION_STATIC_RASTER
David Turnerd2b1f351999-12-16 23:11:37 +00007812 *exc = cur;
Werner Lemberg78575dc2000-06-12 19:36:41 +00007813#endif
7814
David Turnerd2b1f351999-12-16 23:11:37 +00007815 return TT_Err_Ok;
7816
7817 LErrorCodeOverflow_:
7818 CUR.error = TT_Err_Code_Overflow;
7819
7820 LErrorLabel_:
Werner Lemberg78575dc2000-06-12 19:36:41 +00007821
7822#ifdef TT_CONFIG_OPTION_STATIC_RASTER
David Turnerd2b1f351999-12-16 23:11:37 +00007823 *exc = cur;
Werner Lemberg78575dc2000-06-12 19:36:41 +00007824#endif
7825
David Turnerd2b1f351999-12-16 23:11:37 +00007826 return CUR.error;
7827 }
7828
7829
David Turner6aa260c2006-08-25 22:45:13 +00007830#endif /* TT_USE_BYTECODE_INTERPRETER */
David Turnerd2b1f351999-12-16 23:11:37 +00007831
Werner Lemberg78575dc2000-06-12 19:36:41 +00007832
David Turnerd2b1f351999-12-16 23:11:37 +00007833/* END */