blob: d568926bf94a73ff4b9c3e50c10f44686ddf28f6 [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 Lemberg06822512011-01-30 16:38:09 +01007/* Copyright 1996-2011 */
Werner Lemberg6da023d2010-05-20 15:38:00 +02008/* by David Turner, Robert Wilhelm, and Werner Lemberg. */
David Turnerd2b1f351999-12-16 23:11:37 +00009/* */
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 /* */
Werner Lemberg346f1862010-08-06 00:47:57 +0200226 /* Two simple bounds-checking macros. */
David Turnerd2b1f351999-12-16 23:11:37 +0000227 /* */
Werner Lemberg346f1862010-08-06 00:47:57 +0200228#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) )
229#define BOUNDSL( x, n ) ( (FT_ULong)(x) >= (FT_ULong)(n) )
David Turnerd2b1f351999-12-16 23:11:37 +0000230
Werner Lemberg78575dc2000-06-12 19:36:41 +0000231#undef SUCCESS
232#define SUCCESS 0
David Turnerd2b1f351999-12-16 23:11:37 +0000233
Werner Lemberg78575dc2000-06-12 19:36:41 +0000234#undef FAILURE
235#define FAILURE 1
David Turnerd2b1f351999-12-16 23:11:37 +0000236
David Turner8b6db862003-08-17 22:09:14 +0000237#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Werner Lemberga3f4da82003-04-29 13:23:47 +0000238#define GUESS_VECTOR( V ) \
239 if ( CUR.face->unpatented_hinting ) \
240 { \
241 CUR.GS.V.x = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0x4000 : 0 ); \
242 CUR.GS.V.y = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0 : 0x4000 ); \
Graham Asher3ea859f2003-04-25 11:40:46 +0000243 }
244#else
245#define GUESS_VECTOR( V )
246#endif
David Turnerd2b1f351999-12-16 23:11:37 +0000247
248 /*************************************************************************/
249 /* */
250 /* CODERANGE FUNCTIONS */
251 /* */
252 /*************************************************************************/
253
254
255 /*************************************************************************/
256 /* */
257 /* <Function> */
258 /* TT_Goto_CodeRange */
259 /* */
260 /* <Description> */
261 /* Switches to a new code range (updates the code related elements in */
262 /* `exec', and `IP'). */
263 /* */
264 /* <Input> */
265 /* range :: The new execution code range. */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000266 /* */
267 /* IP :: The new IP in the new code range. */
David Turnerd2b1f351999-12-16 23:11:37 +0000268 /* */
269 /* <InOut> */
270 /* exec :: The target execution context. */
271 /* */
272 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +0000273 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000274 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +0000275 FT_LOCAL_DEF( FT_Error )
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000276 TT_Goto_CodeRange( TT_ExecContext exec,
277 FT_Int range,
278 FT_Long IP )
David Turnerd2b1f351999-12-16 23:11:37 +0000279 {
280 TT_CodeRange* coderange;
281
282
Werner Lembergb1e6e592002-03-29 07:43:04 +0000283 FT_ASSERT( range >= 1 && range <= 3 );
David Turnerd2b1f351999-12-16 23:11:37 +0000284
285 coderange = &exec->codeRangeTable[range - 1];
286
Werner Lembergb1e6e592002-03-29 07:43:04 +0000287 FT_ASSERT( coderange->base != NULL );
David Turnerd2b1f351999-12-16 23:11:37 +0000288
289 /* NOTE: Because the last instruction of a program may be a CALL */
290 /* which will return to the first byte *after* the code */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000291 /* range, we test for IP <= Size instead of IP < Size. */
David Turnerd2b1f351999-12-16 23:11:37 +0000292 /* */
Werner Lembergb1e6e592002-03-29 07:43:04 +0000293 FT_ASSERT( (FT_ULong)IP <= coderange->size );
David Turnerd2b1f351999-12-16 23:11:37 +0000294
295 exec->code = coderange->base;
296 exec->codeSize = coderange->size;
297 exec->IP = IP;
298 exec->curRange = range;
299
300 return TT_Err_Ok;
301 }
302
303
304 /*************************************************************************/
305 /* */
306 /* <Function> */
307 /* TT_Set_CodeRange */
308 /* */
309 /* <Description> */
310 /* Sets a code range. */
311 /* */
312 /* <Input> */
313 /* range :: The code range index. */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000314 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000315 /* base :: The new code base. */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000316 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000317 /* length :: The range size in bytes. */
318 /* */
319 /* <InOut> */
320 /* exec :: The target execution context. */
321 /* */
322 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +0000323 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000324 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +0000325 FT_LOCAL_DEF( FT_Error )
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000326 TT_Set_CodeRange( TT_ExecContext exec,
327 FT_Int range,
328 void* base,
329 FT_Long length )
David Turnerd2b1f351999-12-16 23:11:37 +0000330 {
Werner Lembergb1e6e592002-03-29 07:43:04 +0000331 FT_ASSERT( range >= 1 && range <= 3 );
David Turnerd2b1f351999-12-16 23:11:37 +0000332
David Turnerf9b8dec2000-06-16 19:34:52 +0000333 exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
David Turnerd2b1f351999-12-16 23:11:37 +0000334 exec->codeRangeTable[range - 1].size = length;
335
336 return TT_Err_Ok;
337 }
338
339
340 /*************************************************************************/
341 /* */
342 /* <Function> */
343 /* TT_Clear_CodeRange */
344 /* */
345 /* <Description> */
346 /* Clears a code range. */
347 /* */
348 /* <Input> */
349 /* range :: The code range index. */
350 /* */
351 /* <InOut> */
352 /* exec :: The target execution context. */
353 /* */
354 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +0000355 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000356 /* */
357 /* <Note> */
358 /* Does not set the Error variable. */
359 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +0000360 FT_LOCAL_DEF( FT_Error )
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000361 TT_Clear_CodeRange( TT_ExecContext exec,
362 FT_Int range )
David Turnerd2b1f351999-12-16 23:11:37 +0000363 {
Werner Lembergb1e6e592002-03-29 07:43:04 +0000364 FT_ASSERT( range >= 1 && range <= 3 );
David Turnerd2b1f351999-12-16 23:11:37 +0000365
366 exec->codeRangeTable[range - 1].base = NULL;
367 exec->codeRangeTable[range - 1].size = 0;
368
369 return TT_Err_Ok;
370 }
371
372
373 /*************************************************************************/
374 /* */
375 /* EXECUTION CONTEXT ROUTINES */
376 /* */
377 /*************************************************************************/
378
379
380 /*************************************************************************/
381 /* */
382 /* <Function> */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000383 /* TT_Done_Context */
David Turnerd2b1f351999-12-16 23:11:37 +0000384 /* */
385 /* <Description> */
386 /* Destroys a given context. */
387 /* */
388 /* <Input> */
389 /* exec :: A handle to the target execution context. */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000390 /* */
391 /* memory :: A handle to the parent memory object. */
David Turnerd2b1f351999-12-16 23:11:37 +0000392 /* */
393 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +0000394 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000395 /* */
396 /* <Note> */
397 /* Only the glyph loader and debugger should call this function. */
398 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +0000399 FT_LOCAL_DEF( FT_Error )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000400 TT_Done_Context( TT_ExecContext exec )
David Turnerd2b1f351999-12-16 23:11:37 +0000401 {
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000402 FT_Memory memory = exec->memory;
403
404
David Turnerd2b1f351999-12-16 23:11:37 +0000405 /* points zone */
David Turnerd2b1f351999-12-16 23:11:37 +0000406 exec->maxPoints = 0;
407 exec->maxContours = 0;
408
409 /* free stack */
David Turnere459d742002-03-22 13:52:37 +0000410 FT_FREE( exec->stack );
David Turnerd2b1f351999-12-16 23:11:37 +0000411 exec->stackSize = 0;
412
413 /* free call stack */
David Turnere459d742002-03-22 13:52:37 +0000414 FT_FREE( exec->callStack );
David Turnerd2b1f351999-12-16 23:11:37 +0000415 exec->callSize = 0;
416 exec->callTop = 0;
417
418 /* free glyph code range */
David Turnere459d742002-03-22 13:52:37 +0000419 FT_FREE( exec->glyphIns );
David Turnerd2b1f351999-12-16 23:11:37 +0000420 exec->glyphSize = 0;
421
422 exec->size = NULL;
423 exec->face = NULL;
424
David Turnere459d742002-03-22 13:52:37 +0000425 FT_FREE( exec );
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000426
David Turnerd2b1f351999-12-16 23:11:37 +0000427 return TT_Err_Ok;
428 }
429
430
431 /*************************************************************************/
432 /* */
433 /* <Function> */
434 /* Init_Context */
435 /* */
436 /* <Description> */
437 /* Initializes a context object. */
438 /* */
439 /* <Input> */
440 /* memory :: A handle to the parent memory object. */
441 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000442 /* <InOut> */
443 /* exec :: A handle to the target execution context. */
444 /* */
445 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +0000446 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000447 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000448 static FT_Error
449 Init_Context( TT_ExecContext exec,
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000450 FT_Memory memory )
David Turnerd2b1f351999-12-16 23:11:37 +0000451 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000452 FT_Error error;
David Turnerd2b1f351999-12-16 23:11:37 +0000453
454
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000455 FT_TRACE1(( "Init_Context: new object at 0x%08p\n", exec ));
David Turnerd2b1f351999-12-16 23:11:37 +0000456
David Turnerd2b1f351999-12-16 23:11:37 +0000457 exec->memory = memory;
458 exec->callSize = 32;
459
David Turnere459d742002-03-22 13:52:37 +0000460 if ( FT_NEW_ARRAY( exec->callStack, exec->callSize ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000461 goto Fail_Memory;
462
463 /* all values in the context are set to 0 already, but this is */
464 /* here as a remainder */
465 exec->maxPoints = 0;
466 exec->maxContours = 0;
467
468 exec->stackSize = 0;
David Turnerd2b1f351999-12-16 23:11:37 +0000469 exec->glyphSize = 0;
470
471 exec->stack = NULL;
David Turnerd2b1f351999-12-16 23:11:37 +0000472 exec->glyphIns = NULL;
473
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000474 exec->face = NULL;
David Turnerd2b1f351999-12-16 23:11:37 +0000475 exec->size = NULL;
476
477 return TT_Err_Ok;
478
479 Fail_Memory:
suzuki toshiya46c371c2010-10-25 00:14:13 +0900480 FT_ERROR(( "Init_Context: not enough memory for %p\n", 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 Lemberg6da023d2010-05-20 15:38:00 +0200511 FT_LOCAL_DEF( FT_Error )
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000512 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;
Johnson Y. Yan9073e7c2010-11-26 11:58:08 +0100597
598 /* In case of multi-threading it can happen that the old size object */
599 /* no longer exists, thus we must clear all glyph zone references. */
600 ft_memset( &exec->zp0, 0, sizeof ( exec->zp0 ) );
601 exec->zp1 = exec->zp0;
602 exec->zp2 = exec->zp0;
David Turnerd2b1f351999-12-16 23:11:37 +0000603 }
604
David Turnerd2b1f351999-12-16 23:11:37 +0000605 /* XXX: We reserve a little more elements on the stack to deal safely */
606 /* with broken fonts like arialbs, courbs, timesbs, etc. */
607 tmp = exec->stackSize;
608 error = Update_Max( exec->memory,
609 &tmp,
David Turnerf9b8dec2000-06-16 19:34:52 +0000610 sizeof ( FT_F26Dot6 ),
David Turnere3654532007-01-13 00:19:18 +0000611 (void*)&exec->stack,
David Turnerd2b1f351999-12-16 23:11:37 +0000612 maxp->maxStackElements + 32 );
David Turnerf9b8dec2000-06-16 19:34:52 +0000613 exec->stackSize = (FT_UInt)tmp;
David Turnerd2b1f351999-12-16 23:11:37 +0000614 if ( error )
615 return error;
616
617 tmp = exec->glyphSize;
618 error = Update_Max( exec->memory,
619 &tmp,
David Turnerf9b8dec2000-06-16 19:34:52 +0000620 sizeof ( FT_Byte ),
David Turnere3654532007-01-13 00:19:18 +0000621 (void*)&exec->glyphIns,
David Turnerd2b1f351999-12-16 23:11:37 +0000622 maxp->maxSizeOfInstructions );
David Turnerf9b8dec2000-06-16 19:34:52 +0000623 exec->glyphSize = (FT_UShort)tmp;
David Turnerd2b1f351999-12-16 23:11:37 +0000624 if ( error )
625 return error;
626
David Turnerd2b1f351999-12-16 23:11:37 +0000627 exec->pts.n_points = 0;
628 exec->pts.n_contours = 0;
Werner Lemberge12ed562007-06-17 05:31:23 +0000629
David Turner815911a2007-06-16 17:07:20 +0000630 exec->zp1 = exec->pts;
631 exec->zp2 = exec->pts;
632 exec->zp0 = exec->pts;
David Turnerd2b1f351999-12-16 23:11:37 +0000633
634 exec->instruction_trap = FALSE;
635
636 return TT_Err_Ok;
637 }
638
639
640 /*************************************************************************/
641 /* */
642 /* <Function> */
643 /* TT_Save_Context */
644 /* */
645 /* <Description> */
646 /* Saves the code ranges in a `size' object. */
647 /* */
648 /* <Input> */
649 /* exec :: A handle to the source execution context. */
650 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000651 /* <InOut> */
652 /* size :: A handle to the target size object. */
David Turnerd2b1f351999-12-16 23:11:37 +0000653 /* */
654 /* <Return> */
Werner Lemberga929ba92000-06-25 06:47:11 +0000655 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000656 /* */
657 /* <Note> */
658 /* Only the glyph loader and debugger should call this function. */
659 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +0000660 FT_LOCAL_DEF( FT_Error )
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000661 TT_Save_Context( TT_ExecContext exec,
662 TT_Size size )
David Turnerd2b1f351999-12-16 23:11:37 +0000663 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000664 FT_Int i;
David Turnerd2b1f351999-12-16 23:11:37 +0000665
Werner Lemberg78575dc2000-06-12 19:36:41 +0000666
David Turnerd2b1f351999-12-16 23:11:37 +0000667 /* XXXX: Will probably disappear soon with all the code range */
668 /* management, which is now rather obsolete. */
669 /* */
670 size->num_function_defs = exec->numFDefs;
671 size->num_instruction_defs = exec->numIDefs;
672
673 size->max_func = exec->maxFunc;
674 size->max_ins = exec->maxIns;
675
676 for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
677 size->codeRangeTable[i] = exec->codeRangeTable[i];
678
679 return TT_Err_Ok;
680 }
681
682
683 /*************************************************************************/
684 /* */
685 /* <Function> */
686 /* TT_Run_Context */
687 /* */
688 /* <Description> */
689 /* Executes one or more instructions in the execution context. */
690 /* */
691 /* <Input> */
692 /* debug :: A Boolean flag. If set, the function sets some internal */
693 /* variables and returns immediately, otherwise TT_RunIns() */
694 /* is called. */
695 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000696 /* This is commented out currently. */
697 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000698 /* <Input> */
699 /* exec :: A handle to the target execution context. */
700 /* */
701 /* <Return> */
Werner Lemberg5df5dbb2008-06-22 13:40:08 +0000702 /* TrueType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000703 /* */
704 /* <Note> */
705 /* Only the glyph loader and debugger should call this function. */
706 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +0000707 FT_LOCAL_DEF( FT_Error )
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000708 TT_Run_Context( TT_ExecContext exec,
709 FT_Bool debug )
David Turnerd2b1f351999-12-16 23:11:37 +0000710 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000711 FT_Error error;
David Turnerd2b1f351999-12-16 23:11:37 +0000712
Werner Lemberg78575dc2000-06-12 19:36:41 +0000713
714 if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000715 != TT_Err_Ok )
716 return error;
717
718 exec->zp0 = exec->pts;
719 exec->zp1 = exec->pts;
720 exec->zp2 = exec->pts;
721
722 exec->GS.gep0 = 1;
723 exec->GS.gep1 = 1;
724 exec->GS.gep2 = 1;
725
726 exec->GS.projVector.x = 0x4000;
727 exec->GS.projVector.y = 0x0000;
728
729 exec->GS.freeVector = exec->GS.projVector;
730 exec->GS.dualVector = exec->GS.projVector;
731
David Turner8b6db862003-08-17 22:09:14 +0000732#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Graham Asher3ea859f2003-04-25 11:40:46 +0000733 exec->GS.both_x_axis = TRUE;
734#endif
735
David Turnerd2b1f351999-12-16 23:11:37 +0000736 exec->GS.round_state = 1;
737 exec->GS.loop = 1;
738
739 /* some glyphs leave something on the stack. so we clean it */
740 /* before a new execution. */
741 exec->top = 0;
742 exec->callTop = 0;
743
744#if 1
David Turnerc6a92202000-07-04 18:12:13 +0000745 FT_UNUSED( debug );
Werner Lemberg78575dc2000-06-12 19:36:41 +0000746
David Turnerd2b1f351999-12-16 23:11:37 +0000747 return exec->face->interpreter( exec );
748#else
749 if ( !debug )
750 return TT_RunIns( exec );
751 else
752 return TT_Err_Ok;
753#endif
754 }
755
756
Werner Lemberg105721a2008-11-15 10:35:51 +0000757 /* The default value for `scan_control' is documented as FALSE in the */
758 /* TrueType specification. This is confusing since it implies a */
759 /* Boolean value. However, this is not the case, thus both the */
760 /* default values of our `scan_type' and `scan_control' fields (which */
761 /* the documentation's `scan_control' variable is split into) are */
762 /* zero. */
763
David Turnerd2b1f351999-12-16 23:11:37 +0000764 const TT_GraphicsState tt_default_graphics_state =
765 {
766 0, 0, 0,
767 { 0x4000, 0 },
768 { 0x4000, 0 },
769 { 0x4000, 0 },
Graham Asher3ea859f2003-04-25 11:40:46 +0000770
David Turner8b6db862003-08-17 22:09:14 +0000771#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Werner Lemberga3f4da82003-04-29 13:23:47 +0000772 TRUE,
Graham Asher3ea859f2003-04-25 11:40:46 +0000773#endif
774
David Turnerd2b1f351999-12-16 23:11:37 +0000775 1, 64, 1,
776 TRUE, 68, 0, 0, 9, 3,
Werner Lemberg105721a2008-11-15 10:35:51 +0000777 0, FALSE, 0, 1, 1, 1
David Turnerd2b1f351999-12-16 23:11:37 +0000778 };
779
780
Werner Lemberg90a03302000-11-07 17:21:11 +0000781 /* documentation is in ttinterp.h */
782
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000783 FT_EXPORT_DEF( TT_ExecContext )
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000784 TT_New_Context( TT_Driver driver )
David Turnerd2b1f351999-12-16 23:11:37 +0000785 {
David Turnerd2b1f351999-12-16 23:11:37 +0000786 TT_ExecContext exec;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000787 FT_Memory memory;
David Turnerd2b1f351999-12-16 23:11:37 +0000788
789
David Turnerf0df85b2000-06-22 00:17:42 +0000790 memory = driver->root.root.memory;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000791 exec = driver->context;
David Turnerd2b1f351999-12-16 23:11:37 +0000792
793 if ( !driver->context )
794 {
Werner Lemberg5811c7c2000-07-02 13:53:16 +0000795 FT_Error error;
David Turnerd2b1f351999-12-16 23:11:37 +0000796
797
798 /* allocate object */
David Turnere459d742002-03-22 13:52:37 +0000799 if ( FT_NEW( exec ) )
Werner Lembergc6788a32009-06-07 13:09:21 +0200800 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +0000801
Werner Lembergc6788a32009-06-07 13:09:21 +0200802 /* initialize it; in case of error this deallocates `exec' too */
Wu, Chia-I (吳佳一)0142e6a2005-08-16 01:54:59 +0000803 error = Init_Context( exec, memory );
David Turnerd2b1f351999-12-16 23:11:37 +0000804 if ( error )
805 goto Fail;
806
807 /* store it into the driver */
808 driver->context = exec;
809 }
810
David Turnerd2b1f351999-12-16 23:11:37 +0000811 return driver->context;
812
813 Fail:
Werner Lembergc6788a32009-06-07 13:09:21 +0200814 return NULL;
David Turnerd2b1f351999-12-16 23:11:37 +0000815 }
816
817
818 /*************************************************************************/
819 /* */
David Turnerd2b1f351999-12-16 23:11:37 +0000820 /* Before an opcode is executed, the interpreter verifies that there are */
Werner Lemberg33febc02004-10-09 07:07:43 +0000821 /* enough arguments on the stack, with the help of the `Pop_Push_Count' */
David Turnerd2b1f351999-12-16 23:11:37 +0000822 /* table. */
823 /* */
824 /* For each opcode, the first column gives the number of arguments that */
825 /* are popped from the stack; the second one gives the number of those */
826 /* that are pushed in result. */
827 /* */
Werner Lemberg33febc02004-10-09 07:07:43 +0000828 /* Opcodes which have a varying number of parameters in the data stream */
829 /* (NPUSHB, NPUSHW) are handled specially; they have a negative value in */
830 /* the `opcode_length' table, and the value in `Pop_Push_Count' is set */
831 /* to zero. */
David Turnerd2b1f351999-12-16 23:11:37 +0000832 /* */
833 /*************************************************************************/
834
835
836#undef PACK
Werner Lemberg78575dc2000-06-12 19:36:41 +0000837#define PACK( x, y ) ( ( x << 4 ) | y )
David Turnerd2b1f351999-12-16 23:11:37 +0000838
839
840 static
David Turnerf9b8dec2000-06-16 19:34:52 +0000841 const FT_Byte Pop_Push_Count[256] =
David Turnerd2b1f351999-12-16 23:11:37 +0000842 {
843 /* opcodes are gathered in groups of 16 */
844 /* please keep the spaces as they are */
845
846 /* SVTCA y */ PACK( 0, 0 ),
847 /* SVTCA x */ PACK( 0, 0 ),
848 /* SPvTCA y */ PACK( 0, 0 ),
849 /* SPvTCA x */ PACK( 0, 0 ),
850 /* SFvTCA y */ PACK( 0, 0 ),
851 /* SFvTCA x */ PACK( 0, 0 ),
852 /* SPvTL // */ PACK( 2, 0 ),
853 /* SPvTL + */ PACK( 2, 0 ),
854 /* SFvTL // */ PACK( 2, 0 ),
855 /* SFvTL + */ PACK( 2, 0 ),
856 /* SPvFS */ PACK( 2, 0 ),
857 /* SFvFS */ PACK( 2, 0 ),
858 /* GPV */ PACK( 0, 2 ),
859 /* GFV */ PACK( 0, 2 ),
860 /* SFvTPv */ PACK( 0, 0 ),
861 /* ISECT */ PACK( 5, 0 ),
862
863 /* SRP0 */ PACK( 1, 0 ),
864 /* SRP1 */ PACK( 1, 0 ),
865 /* SRP2 */ PACK( 1, 0 ),
866 /* SZP0 */ PACK( 1, 0 ),
867 /* SZP1 */ PACK( 1, 0 ),
868 /* SZP2 */ PACK( 1, 0 ),
869 /* SZPS */ PACK( 1, 0 ),
870 /* SLOOP */ PACK( 1, 0 ),
871 /* RTG */ PACK( 0, 0 ),
872 /* RTHG */ PACK( 0, 0 ),
873 /* SMD */ PACK( 1, 0 ),
874 /* ELSE */ PACK( 0, 0 ),
875 /* JMPR */ PACK( 1, 0 ),
876 /* SCvTCi */ PACK( 1, 0 ),
877 /* SSwCi */ PACK( 1, 0 ),
878 /* SSW */ PACK( 1, 0 ),
879
880 /* DUP */ PACK( 1, 2 ),
881 /* POP */ PACK( 1, 0 ),
882 /* CLEAR */ PACK( 0, 0 ),
883 /* SWAP */ PACK( 2, 2 ),
884 /* DEPTH */ PACK( 0, 1 ),
885 /* CINDEX */ PACK( 1, 1 ),
886 /* MINDEX */ PACK( 1, 0 ),
887 /* AlignPTS */ PACK( 2, 0 ),
888 /* INS_$28 */ PACK( 0, 0 ),
889 /* UTP */ PACK( 1, 0 ),
890 /* LOOPCALL */ PACK( 2, 0 ),
891 /* CALL */ PACK( 1, 0 ),
892 /* FDEF */ PACK( 1, 0 ),
893 /* ENDF */ PACK( 0, 0 ),
894 /* MDAP[0] */ PACK( 1, 0 ),
895 /* MDAP[1] */ PACK( 1, 0 ),
896
897 /* IUP[0] */ PACK( 0, 0 ),
898 /* IUP[1] */ PACK( 0, 0 ),
899 /* SHP[0] */ PACK( 0, 0 ),
900 /* SHP[1] */ PACK( 0, 0 ),
901 /* SHC[0] */ PACK( 1, 0 ),
902 /* SHC[1] */ PACK( 1, 0 ),
903 /* SHZ[0] */ PACK( 1, 0 ),
904 /* SHZ[1] */ PACK( 1, 0 ),
905 /* SHPIX */ PACK( 1, 0 ),
906 /* IP */ PACK( 0, 0 ),
907 /* MSIRP[0] */ PACK( 2, 0 ),
908 /* MSIRP[1] */ PACK( 2, 0 ),
909 /* AlignRP */ PACK( 0, 0 ),
910 /* RTDG */ PACK( 0, 0 ),
911 /* MIAP[0] */ PACK( 2, 0 ),
912 /* MIAP[1] */ PACK( 2, 0 ),
913
914 /* NPushB */ PACK( 0, 0 ),
915 /* NPushW */ PACK( 0, 0 ),
916 /* WS */ PACK( 2, 0 ),
917 /* RS */ PACK( 1, 1 ),
918 /* WCvtP */ PACK( 2, 0 ),
919 /* RCvt */ PACK( 1, 1 ),
920 /* GC[0] */ PACK( 1, 1 ),
921 /* GC[1] */ PACK( 1, 1 ),
922 /* SCFS */ PACK( 2, 0 ),
923 /* MD[0] */ PACK( 2, 1 ),
924 /* MD[1] */ PACK( 2, 1 ),
925 /* MPPEM */ PACK( 0, 1 ),
926 /* MPS */ PACK( 0, 1 ),
927 /* FlipON */ PACK( 0, 0 ),
928 /* FlipOFF */ PACK( 0, 0 ),
929 /* DEBUG */ PACK( 1, 0 ),
930
931 /* LT */ PACK( 2, 1 ),
932 /* LTEQ */ PACK( 2, 1 ),
933 /* GT */ PACK( 2, 1 ),
934 /* GTEQ */ PACK( 2, 1 ),
935 /* EQ */ PACK( 2, 1 ),
936 /* NEQ */ PACK( 2, 1 ),
937 /* ODD */ PACK( 1, 1 ),
938 /* EVEN */ PACK( 1, 1 ),
939 /* IF */ PACK( 1, 0 ),
940 /* EIF */ PACK( 0, 0 ),
941 /* AND */ PACK( 2, 1 ),
942 /* OR */ PACK( 2, 1 ),
943 /* NOT */ PACK( 1, 1 ),
944 /* DeltaP1 */ PACK( 1, 0 ),
945 /* SDB */ PACK( 1, 0 ),
946 /* SDS */ PACK( 1, 0 ),
947
948 /* ADD */ PACK( 2, 1 ),
949 /* SUB */ PACK( 2, 1 ),
950 /* DIV */ PACK( 2, 1 ),
951 /* MUL */ PACK( 2, 1 ),
952 /* ABS */ PACK( 1, 1 ),
953 /* NEG */ PACK( 1, 1 ),
954 /* FLOOR */ PACK( 1, 1 ),
955 /* CEILING */ PACK( 1, 1 ),
956 /* ROUND[0] */ PACK( 1, 1 ),
957 /* ROUND[1] */ PACK( 1, 1 ),
958 /* ROUND[2] */ PACK( 1, 1 ),
959 /* ROUND[3] */ PACK( 1, 1 ),
960 /* NROUND[0] */ PACK( 1, 1 ),
961 /* NROUND[1] */ PACK( 1, 1 ),
962 /* NROUND[2] */ PACK( 1, 1 ),
963 /* NROUND[3] */ PACK( 1, 1 ),
964
965 /* WCvtF */ PACK( 2, 0 ),
966 /* DeltaP2 */ PACK( 1, 0 ),
967 /* DeltaP3 */ PACK( 1, 0 ),
968 /* DeltaCn[0] */ PACK( 1, 0 ),
969 /* DeltaCn[1] */ PACK( 1, 0 ),
970 /* DeltaCn[2] */ PACK( 1, 0 ),
971 /* SROUND */ PACK( 1, 0 ),
972 /* S45Round */ PACK( 1, 0 ),
973 /* JROT */ PACK( 2, 0 ),
974 /* JROF */ PACK( 2, 0 ),
975 /* ROFF */ PACK( 0, 0 ),
976 /* INS_$7B */ PACK( 0, 0 ),
977 /* RUTG */ PACK( 0, 0 ),
978 /* RDTG */ PACK( 0, 0 ),
979 /* SANGW */ PACK( 1, 0 ),
980 /* AA */ PACK( 1, 0 ),
981
982 /* FlipPT */ PACK( 0, 0 ),
983 /* FlipRgON */ PACK( 2, 0 ),
984 /* FlipRgOFF */ PACK( 2, 0 ),
985 /* INS_$83 */ PACK( 0, 0 ),
986 /* INS_$84 */ PACK( 0, 0 ),
987 /* ScanCTRL */ PACK( 1, 0 ),
Werner Lembergd6a213f2011-01-31 18:51:07 +0100988 /* SDPVTL[0] */ PACK( 2, 0 ),
989 /* SDPVTL[1] */ PACK( 2, 0 ),
David Turnerd2b1f351999-12-16 23:11:37 +0000990 /* GetINFO */ PACK( 1, 1 ),
991 /* IDEF */ PACK( 1, 0 ),
992 /* ROLL */ PACK( 3, 3 ),
993 /* MAX */ PACK( 2, 1 ),
994 /* MIN */ PACK( 2, 1 ),
995 /* ScanTYPE */ PACK( 1, 0 ),
996 /* InstCTRL */ PACK( 2, 0 ),
997 /* INS_$8F */ PACK( 0, 0 ),
998
999 /* INS_$90 */ PACK( 0, 0 ),
1000 /* INS_$91 */ PACK( 0, 0 ),
1001 /* INS_$92 */ PACK( 0, 0 ),
1002 /* INS_$93 */ PACK( 0, 0 ),
1003 /* INS_$94 */ PACK( 0, 0 ),
1004 /* INS_$95 */ PACK( 0, 0 ),
1005 /* INS_$96 */ PACK( 0, 0 ),
1006 /* INS_$97 */ PACK( 0, 0 ),
1007 /* INS_$98 */ PACK( 0, 0 ),
1008 /* INS_$99 */ PACK( 0, 0 ),
1009 /* INS_$9A */ PACK( 0, 0 ),
1010 /* INS_$9B */ PACK( 0, 0 ),
1011 /* INS_$9C */ PACK( 0, 0 ),
1012 /* INS_$9D */ PACK( 0, 0 ),
1013 /* INS_$9E */ PACK( 0, 0 ),
1014 /* INS_$9F */ PACK( 0, 0 ),
1015
1016 /* INS_$A0 */ PACK( 0, 0 ),
1017 /* INS_$A1 */ PACK( 0, 0 ),
1018 /* INS_$A2 */ PACK( 0, 0 ),
1019 /* INS_$A3 */ PACK( 0, 0 ),
1020 /* INS_$A4 */ PACK( 0, 0 ),
1021 /* INS_$A5 */ PACK( 0, 0 ),
1022 /* INS_$A6 */ PACK( 0, 0 ),
1023 /* INS_$A7 */ PACK( 0, 0 ),
1024 /* INS_$A8 */ PACK( 0, 0 ),
1025 /* INS_$A9 */ PACK( 0, 0 ),
1026 /* INS_$AA */ PACK( 0, 0 ),
1027 /* INS_$AB */ PACK( 0, 0 ),
1028 /* INS_$AC */ PACK( 0, 0 ),
1029 /* INS_$AD */ PACK( 0, 0 ),
1030 /* INS_$AE */ PACK( 0, 0 ),
1031 /* INS_$AF */ PACK( 0, 0 ),
1032
1033 /* PushB[0] */ PACK( 0, 1 ),
1034 /* PushB[1] */ PACK( 0, 2 ),
1035 /* PushB[2] */ PACK( 0, 3 ),
1036 /* PushB[3] */ PACK( 0, 4 ),
1037 /* PushB[4] */ PACK( 0, 5 ),
1038 /* PushB[5] */ PACK( 0, 6 ),
1039 /* PushB[6] */ PACK( 0, 7 ),
1040 /* PushB[7] */ PACK( 0, 8 ),
1041 /* PushW[0] */ PACK( 0, 1 ),
1042 /* PushW[1] */ PACK( 0, 2 ),
1043 /* PushW[2] */ PACK( 0, 3 ),
1044 /* PushW[3] */ PACK( 0, 4 ),
1045 /* PushW[4] */ PACK( 0, 5 ),
1046 /* PushW[5] */ PACK( 0, 6 ),
1047 /* PushW[6] */ PACK( 0, 7 ),
1048 /* PushW[7] */ PACK( 0, 8 ),
1049
1050 /* MDRP[00] */ PACK( 1, 0 ),
1051 /* MDRP[01] */ PACK( 1, 0 ),
1052 /* MDRP[02] */ PACK( 1, 0 ),
1053 /* MDRP[03] */ PACK( 1, 0 ),
1054 /* MDRP[04] */ PACK( 1, 0 ),
1055 /* MDRP[05] */ PACK( 1, 0 ),
1056 /* MDRP[06] */ PACK( 1, 0 ),
1057 /* MDRP[07] */ PACK( 1, 0 ),
1058 /* MDRP[08] */ PACK( 1, 0 ),
1059 /* MDRP[09] */ PACK( 1, 0 ),
1060 /* MDRP[10] */ PACK( 1, 0 ),
1061 /* MDRP[11] */ PACK( 1, 0 ),
1062 /* MDRP[12] */ PACK( 1, 0 ),
1063 /* MDRP[13] */ PACK( 1, 0 ),
1064 /* MDRP[14] */ PACK( 1, 0 ),
1065 /* MDRP[15] */ PACK( 1, 0 ),
1066
1067 /* MDRP[16] */ PACK( 1, 0 ),
1068 /* MDRP[17] */ PACK( 1, 0 ),
1069 /* MDRP[18] */ PACK( 1, 0 ),
1070 /* MDRP[19] */ PACK( 1, 0 ),
1071 /* MDRP[20] */ PACK( 1, 0 ),
1072 /* MDRP[21] */ PACK( 1, 0 ),
1073 /* MDRP[22] */ PACK( 1, 0 ),
1074 /* MDRP[23] */ PACK( 1, 0 ),
1075 /* MDRP[24] */ PACK( 1, 0 ),
1076 /* MDRP[25] */ PACK( 1, 0 ),
1077 /* MDRP[26] */ PACK( 1, 0 ),
1078 /* MDRP[27] */ PACK( 1, 0 ),
1079 /* MDRP[28] */ PACK( 1, 0 ),
1080 /* MDRP[29] */ PACK( 1, 0 ),
1081 /* MDRP[30] */ PACK( 1, 0 ),
1082 /* MDRP[31] */ PACK( 1, 0 ),
1083
1084 /* MIRP[00] */ PACK( 2, 0 ),
1085 /* MIRP[01] */ PACK( 2, 0 ),
1086 /* MIRP[02] */ PACK( 2, 0 ),
1087 /* MIRP[03] */ PACK( 2, 0 ),
1088 /* MIRP[04] */ PACK( 2, 0 ),
1089 /* MIRP[05] */ PACK( 2, 0 ),
1090 /* MIRP[06] */ PACK( 2, 0 ),
1091 /* MIRP[07] */ PACK( 2, 0 ),
1092 /* MIRP[08] */ PACK( 2, 0 ),
1093 /* MIRP[09] */ PACK( 2, 0 ),
1094 /* MIRP[10] */ PACK( 2, 0 ),
1095 /* MIRP[11] */ PACK( 2, 0 ),
1096 /* MIRP[12] */ PACK( 2, 0 ),
1097 /* MIRP[13] */ PACK( 2, 0 ),
1098 /* MIRP[14] */ PACK( 2, 0 ),
1099 /* MIRP[15] */ PACK( 2, 0 ),
1100
1101 /* MIRP[16] */ PACK( 2, 0 ),
1102 /* MIRP[17] */ PACK( 2, 0 ),
1103 /* MIRP[18] */ PACK( 2, 0 ),
1104 /* MIRP[19] */ PACK( 2, 0 ),
1105 /* MIRP[20] */ PACK( 2, 0 ),
1106 /* MIRP[21] */ PACK( 2, 0 ),
1107 /* MIRP[22] */ PACK( 2, 0 ),
1108 /* MIRP[23] */ PACK( 2, 0 ),
1109 /* MIRP[24] */ PACK( 2, 0 ),
1110 /* MIRP[25] */ PACK( 2, 0 ),
1111 /* MIRP[26] */ PACK( 2, 0 ),
1112 /* MIRP[27] */ PACK( 2, 0 ),
1113 /* MIRP[28] */ PACK( 2, 0 ),
1114 /* MIRP[29] */ PACK( 2, 0 ),
1115 /* MIRP[30] */ PACK( 2, 0 ),
1116 /* MIRP[31] */ PACK( 2, 0 )
1117 };
1118
1119
Werner Lemberg462ddb42010-07-01 11:28:43 +02001120#ifdef FT_DEBUG_LEVEL_TRACE
1121
1122 static
1123 const char* const opcode_name[256] =
1124 {
1125 "SVTCA y",
1126 "SVTCA x",
1127 "SPvTCA y",
1128 "SPvTCA x",
1129 "SFvTCA y",
1130 "SFvTCA x",
1131 "SPvTL ||",
1132 "SPvTL +",
1133 "SFvTL ||",
1134 "SFvTL +",
1135 "SPvFS",
1136 "SFvFS",
1137 "GPV",
1138 "GFV",
1139 "SFvTPv",
1140 "ISECT",
1141
1142 "SRP0",
1143 "SRP1",
1144 "SRP2",
1145 "SZP0",
1146 "SZP1",
1147 "SZP2",
1148 "SZPS",
1149 "SLOOP",
1150 "RTG",
1151 "RTHG",
1152 "SMD",
1153 "ELSE",
1154 "JMPR",
1155 "SCvTCi",
1156 "SSwCi",
1157 "SSW",
1158
1159 "DUP",
1160 "POP",
1161 "CLEAR",
1162 "SWAP",
1163 "DEPTH",
1164 "CINDEX",
1165 "MINDEX",
1166 "AlignPTS",
1167 "INS_$28",
1168 "UTP",
1169 "LOOPCALL",
1170 "CALL",
1171 "FDEF",
1172 "ENDF",
1173 "MDAP[0]",
1174 "MDAP[1]",
1175
1176 "IUP[0]",
1177 "IUP[1]",
1178 "SHP[0]",
1179 "SHP[1]",
1180 "SHC[0]",
1181 "SHC[1]",
1182 "SHZ[0]",
1183 "SHZ[1]",
1184 "SHPIX",
1185 "IP",
1186 "MSIRP[0]",
1187 "MSIRP[1]",
1188 "AlignRP",
1189 "RTDG",
1190 "MIAP[0]",
1191 "MIAP[1]",
1192
1193 "NPushB",
1194 "NPushW",
1195 "WS",
1196 "RS",
1197 "WCvtP",
1198 "RCvt",
1199 "GC[0]",
1200 "GC[1]",
1201 "SCFS",
1202 "MD[0]",
1203 "MD[1]",
1204 "MPPEM",
1205 "MPS",
1206 "FlipON",
1207 "FlipOFF",
1208 "DEBUG",
1209
1210 "LT",
1211 "LTEQ",
1212 "GT",
1213 "GTEQ",
1214 "EQ",
1215 "NEQ",
1216 "ODD",
1217 "EVEN",
1218 "IF",
1219 "EIF",
1220 "AND",
1221 "OR",
1222 "NOT",
1223 "DeltaP1",
1224 "SDB",
1225 "SDS",
1226
1227 "ADD",
1228 "SUB",
1229 "DIV",
1230 "MUL",
1231 "ABS",
1232 "NEG",
1233 "FLOOR",
1234 "CEILING",
1235 "ROUND[0]",
1236 "ROUND[1]",
1237 "ROUND[2]",
1238 "ROUND[3]",
1239 "NROUND[0]",
1240 "NROUND[1]",
1241 "NROUND[2]",
1242 "NROUND[3]",
1243
1244 "WCvtF",
1245 "DeltaP2",
1246 "DeltaP3",
1247 "DeltaCn[0]",
1248 "DeltaCn[1]",
1249 "DeltaCn[2]",
1250 "SROUND",
1251 "S45Round",
1252 "JROT",
1253 "JROF",
1254 "ROFF",
1255 "INS_$7B",
1256 "RUTG",
1257 "RDTG",
1258 "SANGW",
1259 "AA",
1260
1261 "FlipPT",
1262 "FlipRgON",
1263 "FlipRgOFF",
1264 "INS_$83",
1265 "INS_$84",
1266 "ScanCTRL",
1267 "SDVPTL[0]",
1268 "SDVPTL[1]",
1269 "GetINFO",
1270 "IDEF",
1271 "ROLL",
1272 "MAX",
1273 "MIN",
1274 "ScanTYPE",
1275 "InstCTRL",
1276 "INS_$8F",
1277
1278 "INS_$90",
1279 "INS_$91",
1280 "INS_$92",
1281 "INS_$93",
1282 "INS_$94",
1283 "INS_$95",
1284 "INS_$96",
1285 "INS_$97",
1286 "INS_$98",
1287 "INS_$99",
1288 "INS_$9A",
1289 "INS_$9B",
1290 "INS_$9C",
1291 "INS_$9D",
1292 "INS_$9E",
1293 "INS_$9F",
1294
1295 "INS_$A0",
1296 "INS_$A1",
1297 "INS_$A2",
1298 "INS_$A3",
1299 "INS_$A4",
1300 "INS_$A5",
1301 "INS_$A6",
1302 "INS_$A7",
1303 "INS_$A8",
1304 "INS_$A9",
1305 "INS_$AA",
1306 "INS_$AB",
1307 "INS_$AC",
1308 "INS_$AD",
1309 "INS_$AE",
1310 "INS_$AF",
1311
1312 "PushB[0]",
1313 "PushB[1]",
1314 "PushB[2]",
1315 "PushB[3]",
1316 "PushB[4]",
1317 "PushB[5]",
1318 "PushB[6]",
1319 "PushB[7]",
1320 "PushW[0]",
1321 "PushW[1]",
1322 "PushW[2]",
1323 "PushW[3]",
1324 "PushW[4]",
1325 "PushW[5]",
1326 "PushW[6]",
1327 "PushW[7]",
1328
1329 "MDRP[00]",
1330 "MDRP[01]",
1331 "MDRP[02]",
1332 "MDRP[03]",
1333 "MDRP[04]",
1334 "MDRP[05]",
1335 "MDRP[06]",
1336 "MDRP[07]",
1337 "MDRP[08]",
1338 "MDRP[09]",
1339 "MDRP[10]",
1340 "MDRP[11]",
1341 "MDRP[12]",
1342 "MDRP[13]",
1343 "MDRP[14]",
1344 "MDRP[15]",
1345
1346 "MDRP[16]",
1347 "MDRP[17]",
1348 "MDRP[18]",
1349 "MDRP[19]",
1350 "MDRP[20]",
1351 "MDRP[21]",
1352 "MDRP[22]",
1353 "MDRP[23]",
1354 "MDRP[24]",
1355 "MDRP[25]",
1356 "MDRP[26]",
1357 "MDRP[27]",
1358 "MDRP[28]",
1359 "MDRP[29]",
1360 "MDRP[30]",
1361 "MDRP[31]",
1362
1363 "MIRP[00]",
1364 "MIRP[01]",
1365 "MIRP[02]",
1366 "MIRP[03]",
1367 "MIRP[04]",
1368 "MIRP[05]",
1369 "MIRP[06]",
1370 "MIRP[07]",
1371 "MIRP[08]",
1372 "MIRP[09]",
1373 "MIRP[10]",
1374 "MIRP[11]",
1375 "MIRP[12]",
1376 "MIRP[13]",
1377 "MIRP[14]",
1378 "MIRP[15]",
1379
1380 "MIRP[16]",
1381 "MIRP[17]",
1382 "MIRP[18]",
1383 "MIRP[19]",
1384 "MIRP[20]",
1385 "MIRP[21]",
1386 "MIRP[22]",
1387 "MIRP[23]",
1388 "MIRP[24]",
1389 "MIRP[25]",
1390 "MIRP[26]",
1391 "MIRP[27]",
1392 "MIRP[28]",
1393 "MIRP[29]",
1394 "MIRP[30]",
1395 "MIRP[31]"
1396 };
1397
1398#endif /* FT_DEBUG_LEVEL_TRACE */
1399
1400
David Turnerd2b1f351999-12-16 23:11:37 +00001401 static
David Turnerf9b8dec2000-06-16 19:34:52 +00001402 const FT_Char opcode_length[256] =
David Turnerd2b1f351999-12-16 23:11:37 +00001403 {
1404 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1405 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1406 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1407 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1408
Werner Lemberg33febc02004-10-09 07:07:43 +00001409 -1,-2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
David Turnerd2b1f351999-12-16 23:11:37 +00001410 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1411 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1412 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1413
1414 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1415 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1416 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1417 2, 3, 4, 5, 6, 7, 8, 9, 3, 5, 7, 9, 11,13,15,17,
1418
1419 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1420 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1421 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1422 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
1423 };
1424
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001425#undef PACK
David Turnerd2b1f351999-12-16 23:11:37 +00001426
David Turner2c4500e2007-02-14 15:08:47 +00001427#if 1
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00001428
David Turner2c4500e2007-02-14 15:08:47 +00001429 static FT_Int32
1430 TT_MulFix14( FT_Int32 a,
1431 FT_Int b )
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00001432 {
1433 FT_Int32 sign;
1434 FT_UInt32 ah, al, mid, lo, hi;
David Turner2c4500e2007-02-14 15:08:47 +00001435
David Turner2c4500e2007-02-14 15:08:47 +00001436
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00001437 sign = a ^ b;
David Turner2c4500e2007-02-14 15:08:47 +00001438
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00001439 if ( a < 0 )
1440 a = -a;
1441 if ( b < 0 )
1442 b = -b;
David Turner2c4500e2007-02-14 15:08:47 +00001443
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00001444 ah = (FT_UInt32)( ( a >> 16 ) & 0xFFFFU );
1445 al = (FT_UInt32)( a & 0xFFFFU );
David Turner2c4500e2007-02-14 15:08:47 +00001446
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00001447 lo = al * b;
1448 mid = ah * b;
1449 hi = mid >> 16;
1450 mid = ( mid << 16 ) + ( 1 << 13 ); /* rounding */
1451 lo += mid;
1452 if ( lo < mid )
1453 hi += 1;
David Turner2c4500e2007-02-14 15:08:47 +00001454
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00001455 mid = ( lo >> 14 ) | ( hi << 18 );
1456
1457 return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid;
1458 }
1459
David Turner2c4500e2007-02-14 15:08:47 +00001460#else
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00001461
Werner Lemberg91db04c2002-04-01 14:25:28 +00001462 /* compute (a*b)/2^14 with maximal accuracy and rounding */
David Turner4b29d582002-03-25 17:02:26 +00001463 static FT_Int32
Werner Lemberg91db04c2002-04-01 14:25:28 +00001464 TT_MulFix14( FT_Int32 a,
1465 FT_Int b )
David Turner4b29d582002-03-25 17:02:26 +00001466 {
1467 FT_Int32 m, s, hi;
1468 FT_UInt32 l, lo;
David Turnerb08fe2d2002-08-27 20:20:29 +00001469
Werner Lemberg91db04c2002-04-01 14:25:28 +00001470
David Turner4b29d582002-03-25 17:02:26 +00001471 /* compute ax*bx as 64-bit value */
Werner Lemberg91db04c2002-04-01 14:25:28 +00001472 l = (FT_UInt32)( ( a & 0xFFFFU ) * b );
1473 m = ( a >> 16 ) * b;
David Turnerb08fe2d2002-08-27 20:20:29 +00001474
Werner Lemberg91db04c2002-04-01 14:25:28 +00001475 lo = l + (FT_UInt32)( m << 16 );
1476 hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l );
David Turnerb08fe2d2002-08-27 20:20:29 +00001477
David Turner4b29d582002-03-25 17:02:26 +00001478 /* divide the result by 2^14 with rounding */
Werner Lemberg91db04c2002-04-01 14:25:28 +00001479 s = hi >> 31;
David Turner4b29d582002-03-25 17:02:26 +00001480 l = lo + (FT_UInt32)s;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001481 hi += s + ( l < lo );
David Turner4b29d582002-03-25 17:02:26 +00001482 lo = l;
1483
1484 l = lo + 0x2000U;
Werner Lembergc9f6c662007-03-21 13:30:14 +00001485 hi += l < lo;
David Turnerb08fe2d2002-08-27 20:20:29 +00001486
Werner Lemberg91db04c2002-04-01 14:25:28 +00001487 return ( hi << 18 ) | ( l >> 14 );
David Turner4b29d582002-03-25 17:02:26 +00001488 }
David Turner2c4500e2007-02-14 15:08:47 +00001489#endif
David Turner4b29d582002-03-25 17:02:26 +00001490
1491
Werner Lemberg91db04c2002-04-01 14:25:28 +00001492 /* compute (ax*bx+ay*by)/2^14 with maximal accuracy and rounding */
David Turner4b29d582002-03-25 17:02:26 +00001493 static FT_Int32
Werner Lemberg91db04c2002-04-01 14:25:28 +00001494 TT_DotFix14( FT_Int32 ax,
1495 FT_Int32 ay,
1496 FT_Int bx,
1497 FT_Int by )
David Turner4b29d582002-03-25 17:02:26 +00001498 {
1499 FT_Int32 m, s, hi1, hi2, hi;
1500 FT_UInt32 l, lo1, lo2, lo;
David Turnerb08fe2d2002-08-27 20:20:29 +00001501
Werner Lemberg91db04c2002-04-01 14:25:28 +00001502
David Turner4b29d582002-03-25 17:02:26 +00001503 /* compute ax*bx as 64-bit value */
Werner Lemberg91db04c2002-04-01 14:25:28 +00001504 l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx );
1505 m = ( ax >> 16 ) * bx;
David Turnerb08fe2d2002-08-27 20:20:29 +00001506
Werner Lemberg91db04c2002-04-01 14:25:28 +00001507 lo1 = l + (FT_UInt32)( m << 16 );
1508 hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l );
David Turnerb08fe2d2002-08-27 20:20:29 +00001509
David Turner4b29d582002-03-25 17:02:26 +00001510 /* compute ay*by as 64-bit value */
Werner Lemberg91db04c2002-04-01 14:25:28 +00001511 l = (FT_UInt32)( ( ay & 0xFFFFU ) * by );
1512 m = ( ay >> 16 ) * by;
David Turnerb08fe2d2002-08-27 20:20:29 +00001513
Werner Lemberg91db04c2002-04-01 14:25:28 +00001514 lo2 = l + (FT_UInt32)( m << 16 );
1515 hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l );
David Turnerb08fe2d2002-08-27 20:20:29 +00001516
David Turner4b29d582002-03-25 17:02:26 +00001517 /* add them */
1518 lo = lo1 + lo2;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001519 hi = hi1 + hi2 + ( lo < lo1 );
David Turnerb08fe2d2002-08-27 20:20:29 +00001520
David Turner4b29d582002-03-25 17:02:26 +00001521 /* divide the result by 2^14 with rounding */
Werner Lemberg91db04c2002-04-01 14:25:28 +00001522 s = hi >> 31;
David Turner4b29d582002-03-25 17:02:26 +00001523 l = lo + (FT_UInt32)s;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001524 hi += s + ( l < lo );
David Turner4b29d582002-03-25 17:02:26 +00001525 lo = l;
1526
1527 l = lo + 0x2000U;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001528 hi += ( l < lo );
David Turnerb08fe2d2002-08-27 20:20:29 +00001529
Werner Lemberg91db04c2002-04-01 14:25:28 +00001530 return ( hi << 18 ) | ( l >> 14 );
David Turner4b29d582002-03-25 17:02:26 +00001531 }
1532
Werner Lemberg91db04c2002-04-01 14:25:28 +00001533
1534 /* return length of given vector */
1535
David Turner4b29d582002-03-25 17:02:26 +00001536#if 0
1537
1538 static FT_Int32
Werner Lemberg91db04c2002-04-01 14:25:28 +00001539 TT_VecLen( FT_Int32 x,
1540 FT_Int32 y )
David Turner4b29d582002-03-25 17:02:26 +00001541 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001542 FT_Int32 m, hi1, hi2, hi;
1543 FT_UInt32 l, lo1, lo2, lo;
1544
David Turnerb08fe2d2002-08-27 20:20:29 +00001545
David Turner4b29d582002-03-25 17:02:26 +00001546 /* compute x*x as 64-bit value */
Werner Lemberg91db04c2002-04-01 14:25:28 +00001547 lo = (FT_UInt32)( x & 0xFFFFU );
1548 hi = x >> 16;
David Turnerb08fe2d2002-08-27 20:20:29 +00001549
Werner Lemberg91db04c2002-04-01 14:25:28 +00001550 l = lo * lo;
1551 m = hi * lo;
1552 hi = hi * hi;
David Turnerb08fe2d2002-08-27 20:20:29 +00001553
Werner Lemberg91db04c2002-04-01 14:25:28 +00001554 lo1 = l + (FT_UInt32)( m << 17 );
1555 hi1 = hi + ( m >> 15 ) + ( lo1 < l );
David Turnerb08fe2d2002-08-27 20:20:29 +00001556
David Turner4b29d582002-03-25 17:02:26 +00001557 /* compute y*y as 64-bit value */
Werner Lemberg91db04c2002-04-01 14:25:28 +00001558 lo = (FT_UInt32)( y & 0xFFFFU );
1559 hi = y >> 16;
David Turnerb08fe2d2002-08-27 20:20:29 +00001560
Werner Lemberg91db04c2002-04-01 14:25:28 +00001561 l = lo * lo;
1562 m = hi * lo;
1563 hi = hi * hi;
David Turnerb08fe2d2002-08-27 20:20:29 +00001564
Werner Lemberg91db04c2002-04-01 14:25:28 +00001565 lo2 = l + (FT_UInt32)( m << 17 );
1566 hi2 = hi + ( m >> 15 ) + ( lo2 < l );
David Turnerb08fe2d2002-08-27 20:20:29 +00001567
David Turner4b29d582002-03-25 17:02:26 +00001568 /* add them to get 'x*x+y*y' as 64-bit value */
1569 lo = lo1 + lo2;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001570 hi = hi1 + hi2 + ( lo < lo1 );
David Turnerb08fe2d2002-08-27 20:20:29 +00001571
David Turner4b29d582002-03-25 17:02:26 +00001572 /* compute the square root of this value */
1573 {
1574 FT_UInt32 root, rem, test_div;
1575 FT_Int count;
1576
1577
1578 root = 0;
1579
1580 {
1581 rem = 0;
1582 count = 32;
1583 do
1584 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001585 rem = ( rem << 2 ) | ( (FT_UInt32)hi >> 30 );
1586 hi = ( hi << 2 ) | ( lo >> 30 );
David Turner4b29d582002-03-25 17:02:26 +00001587 lo <<= 2;
1588 root <<= 1;
1589 test_div = ( root << 1 ) + 1;
1590
1591 if ( rem >= test_div )
1592 {
1593 rem -= test_div;
1594 root += 1;
1595 }
1596 } while ( --count );
1597 }
David Turnerb08fe2d2002-08-27 20:20:29 +00001598
David Turner4b29d582002-03-25 17:02:26 +00001599 return (FT_Int32)root;
1600 }
1601 }
Werner Lemberg91db04c2002-04-01 14:25:28 +00001602
David Turner4b29d582002-03-25 17:02:26 +00001603#else
David Turnerb08fe2d2002-08-27 20:20:29 +00001604
Werner Lemberg91db04c2002-04-01 14:25:28 +00001605 /* this version uses FT_Vector_Length which computes the same value */
1606 /* much, much faster.. */
1607 /* */
David Turner4b29d582002-03-25 17:02:26 +00001608 static FT_F26Dot6
1609 TT_VecLen( FT_F26Dot6 X,
1610 FT_F26Dot6 Y )
1611 {
1612 FT_Vector v;
1613
Werner Lemberg91db04c2002-04-01 14:25:28 +00001614
David Turner4b29d582002-03-25 17:02:26 +00001615 v.x = X;
1616 v.y = Y;
Werner Lemberg91db04c2002-04-01 14:25:28 +00001617
David Turner4b29d582002-03-25 17:02:26 +00001618 return FT_Vector_Length( &v );
1619 }
David Turnerb08fe2d2002-08-27 20:20:29 +00001620
David Turner4b29d582002-03-25 17:02:26 +00001621#endif
1622
Werner Lemberg91db04c2002-04-01 14:25:28 +00001623
David Turnerd2b1f351999-12-16 23:11:37 +00001624 /*************************************************************************/
1625 /* */
1626 /* <Function> */
1627 /* Current_Ratio */
1628 /* */
1629 /* <Description> */
1630 /* Returns the current aspect ratio scaling factor depending on the */
1631 /* projection vector's state and device resolutions. */
1632 /* */
1633 /* <Return> */
1634 /* The aspect ratio in 16.16 format, always <= 1.0 . */
1635 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001636 static FT_Long
1637 Current_Ratio( EXEC_OP )
David Turnerd2b1f351999-12-16 23:11:37 +00001638 {
Graham Asher3ea859f2003-04-25 11:40:46 +00001639 if ( !CUR.tt_metrics.ratio )
David Turnerd2b1f351999-12-16 23:11:37 +00001640 {
David Turner8b6db862003-08-17 22:09:14 +00001641#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Graham Asher3ea859f2003-04-25 11:40:46 +00001642 if ( CUR.face->unpatented_hinting )
1643 {
1644 if ( CUR.GS.both_x_axis )
1645 CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
1646 else
1647 CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
1648 }
1649 else
1650#endif
Werner Lemberga3f4da82003-04-29 13:23:47 +00001651 {
Graham Asher3ea859f2003-04-25 11:40:46 +00001652 if ( CUR.GS.projVector.y == 0 )
1653 CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001654
Graham Asher3ea859f2003-04-25 11:40:46 +00001655 else if ( CUR.GS.projVector.x == 0 )
1656 CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
David Turnerd2b1f351999-12-16 23:11:37 +00001657
Graham Asher3ea859f2003-04-25 11:40:46 +00001658 else
1659 {
1660 FT_Long x, y;
1661
Werner Lemberga3f4da82003-04-29 13:23:47 +00001662
1663 x = TT_MULDIV( CUR.GS.projVector.x,
1664 CUR.tt_metrics.x_ratio, 0x4000 );
1665 y = TT_MULDIV( CUR.GS.projVector.y,
1666 CUR.tt_metrics.y_ratio, 0x4000 );
Graham Asher3ea859f2003-04-25 11:40:46 +00001667 CUR.tt_metrics.ratio = TT_VecLen( x, y );
1668 }
Werner Lemberga3f4da82003-04-29 13:23:47 +00001669 }
1670 }
David Turnerd2b1f351999-12-16 23:11:37 +00001671 return CUR.tt_metrics.ratio;
1672 }
1673
1674
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001675 static FT_Long
1676 Current_Ppem( EXEC_OP )
David Turnerd2b1f351999-12-16 23:11:37 +00001677 {
1678 return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() );
1679 }
1680
1681
1682 /*************************************************************************/
1683 /* */
1684 /* Functions related to the control value table (CVT). */
1685 /* */
1686 /*************************************************************************/
1687
1688
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001689 FT_CALLBACK_DEF( FT_F26Dot6 )
Werner Lemberg91db04c2002-04-01 14:25:28 +00001690 Read_CVT( EXEC_OP_ FT_ULong idx )
David Turnerd2b1f351999-12-16 23:11:37 +00001691 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001692 return CUR.cvt[idx];
David Turnerd2b1f351999-12-16 23:11:37 +00001693 }
1694
1695
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001696 FT_CALLBACK_DEF( FT_F26Dot6 )
Werner Lemberg91db04c2002-04-01 14:25:28 +00001697 Read_CVT_Stretched( EXEC_OP_ FT_ULong idx )
David Turnerd2b1f351999-12-16 23:11:37 +00001698 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001699 return TT_MULFIX( CUR.cvt[idx], CURRENT_Ratio() );
David Turnerd2b1f351999-12-16 23:11:37 +00001700 }
1701
1702
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001703 FT_CALLBACK_DEF( void )
Werner Lemberg91db04c2002-04-01 14:25:28 +00001704 Write_CVT( EXEC_OP_ FT_ULong idx,
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001705 FT_F26Dot6 value )
David Turnerd2b1f351999-12-16 23:11:37 +00001706 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001707 CUR.cvt[idx] = value;
David Turnerd2b1f351999-12-16 23:11:37 +00001708 }
1709
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001710
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001711 FT_CALLBACK_DEF( void )
Werner Lemberg91db04c2002-04-01 14:25:28 +00001712 Write_CVT_Stretched( EXEC_OP_ FT_ULong idx,
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001713 FT_F26Dot6 value )
David Turnerd2b1f351999-12-16 23:11:37 +00001714 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001715 CUR.cvt[idx] = FT_DivFix( value, CURRENT_Ratio() );
David Turnerd2b1f351999-12-16 23:11:37 +00001716 }
1717
1718
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001719 FT_CALLBACK_DEF( void )
Werner Lemberg91db04c2002-04-01 14:25:28 +00001720 Move_CVT( EXEC_OP_ FT_ULong idx,
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001721 FT_F26Dot6 value )
David Turnerd2b1f351999-12-16 23:11:37 +00001722 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001723 CUR.cvt[idx] += value;
David Turnerd2b1f351999-12-16 23:11:37 +00001724 }
1725
1726
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001727 FT_CALLBACK_DEF( void )
Werner Lemberg91db04c2002-04-01 14:25:28 +00001728 Move_CVT_Stretched( EXEC_OP_ FT_ULong idx,
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001729 FT_F26Dot6 value )
David Turnerd2b1f351999-12-16 23:11:37 +00001730 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001731 CUR.cvt[idx] += FT_DivFix( value, CURRENT_Ratio() );
David Turnerd2b1f351999-12-16 23:11:37 +00001732 }
1733
1734
1735 /*************************************************************************/
1736 /* */
1737 /* <Function> */
1738 /* GetShortIns */
1739 /* */
1740 /* <Description> */
1741 /* Returns a short integer taken from the instruction stream at */
1742 /* address IP. */
1743 /* */
1744 /* <Return> */
1745 /* Short read at code[IP]. */
1746 /* */
1747 /* <Note> */
1748 /* This one could become a macro. */
1749 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001750 static FT_Short
1751 GetShortIns( EXEC_OP )
David Turnerd2b1f351999-12-16 23:11:37 +00001752 {
1753 /* Reading a byte stream so there is no endianess (DaveP) */
1754 CUR.IP += 2;
David Turnerf9b8dec2000-06-16 19:34:52 +00001755 return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) +
Werner Lemberg78575dc2000-06-12 19:36:41 +00001756 CUR.code[CUR.IP - 1] );
David Turnerd2b1f351999-12-16 23:11:37 +00001757 }
1758
1759
1760 /*************************************************************************/
1761 /* */
1762 /* <Function> */
1763 /* Ins_Goto_CodeRange */
1764 /* */
1765 /* <Description> */
1766 /* Goes to a certain code range in the instruction stream. */
1767 /* */
1768 /* <Input> */
1769 /* aRange :: The index of the code range. */
1770 /* */
1771 /* aIP :: The new IP address in the code range. */
1772 /* */
1773 /* <Return> */
1774 /* SUCCESS or FAILURE. */
1775 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001776 static FT_Bool
1777 Ins_Goto_CodeRange( EXEC_OP_ FT_Int aRange,
1778 FT_ULong aIP )
David Turnerd2b1f351999-12-16 23:11:37 +00001779 {
1780 TT_CodeRange* range;
1781
1782
1783 if ( aRange < 1 || aRange > 3 )
1784 {
1785 CUR.error = TT_Err_Bad_Argument;
1786 return FAILURE;
1787 }
1788
1789 range = &CUR.codeRangeTable[aRange - 1];
1790
1791 if ( range->base == NULL ) /* invalid coderange */
1792 {
1793 CUR.error = TT_Err_Invalid_CodeRange;
1794 return FAILURE;
1795 }
1796
1797 /* NOTE: Because the last instruction of a program may be a CALL */
1798 /* which will return to the first byte *after* the code */
1799 /* range, we test for AIP <= Size, instead of AIP < Size. */
1800
1801 if ( aIP > range->size )
1802 {
1803 CUR.error = TT_Err_Code_Overflow;
1804 return FAILURE;
1805 }
1806
1807 CUR.code = range->base;
1808 CUR.codeSize = range->size;
1809 CUR.IP = aIP;
1810 CUR.curRange = aRange;
1811
1812 return SUCCESS;
1813 }
1814
1815
1816 /*************************************************************************/
1817 /* */
1818 /* <Function> */
1819 /* Direct_Move */
1820 /* */
1821 /* <Description> */
1822 /* Moves a point by a given distance along the freedom vector. The */
1823 /* point will be `touched'. */
1824 /* */
1825 /* <Input> */
1826 /* point :: The index of the point to move. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001827 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001828 /* distance :: The distance to apply. */
1829 /* */
1830 /* <InOut> */
1831 /* zone :: The affected glyph zone. */
1832 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001833 static void
Werner Lemberg91db04c2002-04-01 14:25:28 +00001834 Direct_Move( EXEC_OP_ TT_GlyphZone zone,
1835 FT_UShort point,
1836 FT_F26Dot6 distance )
David Turnerd2b1f351999-12-16 23:11:37 +00001837 {
Werner Lemberg91db04c2002-04-01 14:25:28 +00001838 FT_F26Dot6 v;
David Turnerd2b1f351999-12-16 23:11:37 +00001839
Werner Lemberga3f4da82003-04-29 13:23:47 +00001840
David Turner8b6db862003-08-17 22:09:14 +00001841#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Werner Lemberga3f4da82003-04-29 13:23:47 +00001842 FT_ASSERT( !CUR.face->unpatented_hinting );
Graham Asher3ea859f2003-04-25 11:40:46 +00001843#endif
David Turnerd2b1f351999-12-16 23:11:37 +00001844
1845 v = CUR.GS.freeVector.x;
1846
1847 if ( v != 0 )
1848 {
1849 zone->cur[point].x += TT_MULDIV( distance,
1850 v * 0x10000L,
1851 CUR.F_dot_P );
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001852
David Turnerb08fe2d2002-08-27 20:20:29 +00001853 zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
David Turnerd2b1f351999-12-16 23:11:37 +00001854 }
1855
1856 v = CUR.GS.freeVector.y;
1857
1858 if ( v != 0 )
1859 {
1860 zone->cur[point].y += TT_MULDIV( distance,
1861 v * 0x10000L,
1862 CUR.F_dot_P );
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001863
David Turnerb08fe2d2002-08-27 20:20:29 +00001864 zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
David Turnerd2b1f351999-12-16 23:11:37 +00001865 }
1866 }
1867
1868
1869 /*************************************************************************/
1870 /* */
Werner Lembergbe67c4e2003-11-24 22:54:58 +00001871 /* <Function> */
1872 /* Direct_Move_Orig */
1873 /* */
1874 /* <Description> */
Werner Lembergd90b6732003-11-28 22:47:26 +00001875 /* Moves the *original* position of a point by a given distance along */
1876 /* the freedom vector. Obviously, the point will not be `touched'. */
Werner Lembergbe67c4e2003-11-24 22:54:58 +00001877 /* */
1878 /* <Input> */
1879 /* point :: The index of the point to move. */
1880 /* */
1881 /* distance :: The distance to apply. */
1882 /* */
1883 /* <InOut> */
1884 /* zone :: The affected glyph zone. */
1885 /* */
1886 static void
1887 Direct_Move_Orig( EXEC_OP_ TT_GlyphZone zone,
1888 FT_UShort point,
1889 FT_F26Dot6 distance )
1890 {
1891 FT_F26Dot6 v;
1892
1893
1894#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
1895 FT_ASSERT( !CUR.face->unpatented_hinting );
1896#endif
1897
1898 v = CUR.GS.freeVector.x;
1899
1900 if ( v != 0 )
1901 zone->org[point].x += TT_MULDIV( distance,
1902 v * 0x10000L,
1903 CUR.F_dot_P );
1904
1905 v = CUR.GS.freeVector.y;
1906
1907 if ( v != 0 )
1908 zone->org[point].y += TT_MULDIV( distance,
1909 v * 0x10000L,
1910 CUR.F_dot_P );
1911 }
1912
1913
1914 /*************************************************************************/
1915 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001916 /* Special versions of Direct_Move() */
1917 /* */
1918 /* The following versions are used whenever both vectors are both */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001919 /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */
David Turnerd2b1f351999-12-16 23:11:37 +00001920 /* */
1921 /*************************************************************************/
1922
Werner Lemberg5811c7c2000-07-02 13:53:16 +00001923
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001924 static void
Werner Lemberg91db04c2002-04-01 14:25:28 +00001925 Direct_Move_X( EXEC_OP_ TT_GlyphZone zone,
1926 FT_UShort point,
1927 FT_F26Dot6 distance )
David Turnerd2b1f351999-12-16 23:11:37 +00001928 {
David Turnerc6a92202000-07-04 18:12:13 +00001929 FT_UNUSED_EXEC;
David Turnerd2b1f351999-12-16 23:11:37 +00001930
1931 zone->cur[point].x += distance;
David Turnerb08fe2d2002-08-27 20:20:29 +00001932 zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
David Turnerd2b1f351999-12-16 23:11:37 +00001933 }
1934
1935
Werner Lemberg4a2305c2001-06-28 07:17:51 +00001936 static void
Werner Lemberg91db04c2002-04-01 14:25:28 +00001937 Direct_Move_Y( EXEC_OP_ TT_GlyphZone zone,
1938 FT_UShort point,
1939 FT_F26Dot6 distance )
David Turnerd2b1f351999-12-16 23:11:37 +00001940 {
David Turnerc6a92202000-07-04 18:12:13 +00001941 FT_UNUSED_EXEC;
David Turnerd2b1f351999-12-16 23:11:37 +00001942
1943 zone->cur[point].y += distance;
David Turnerb08fe2d2002-08-27 20:20:29 +00001944 zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
David Turnerd2b1f351999-12-16 23:11:37 +00001945 }
1946
1947
1948 /*************************************************************************/
1949 /* */
Werner Lembergbe67c4e2003-11-24 22:54:58 +00001950 /* Special versions of Direct_Move_Orig() */
1951 /* */
1952 /* The following versions are used whenever both vectors are both */
1953 /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */
1954 /* */
1955 /*************************************************************************/
1956
1957
1958 static void
1959 Direct_Move_Orig_X( EXEC_OP_ TT_GlyphZone zone,
1960 FT_UShort point,
1961 FT_F26Dot6 distance )
1962 {
1963 FT_UNUSED_EXEC;
1964
1965 zone->org[point].x += distance;
1966 }
1967
1968
1969 static void
1970 Direct_Move_Orig_Y( EXEC_OP_ TT_GlyphZone zone,
1971 FT_UShort point,
1972 FT_F26Dot6 distance )
1973 {
1974 FT_UNUSED_EXEC;
1975
1976 zone->org[point].y += distance;
1977 }
1978
1979
1980 /*************************************************************************/
1981 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001982 /* <Function> */
1983 /* Round_None */
1984 /* */
1985 /* <Description> */
1986 /* Does not round, but adds engine compensation. */
1987 /* */
1988 /* <Input> */
1989 /* distance :: The distance (not) to round. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00001990 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00001991 /* compensation :: The engine compensation. */
1992 /* */
1993 /* <Return> */
1994 /* The compensated distance. */
1995 /* */
1996 /* <Note> */
1997 /* The TrueType specification says very few about the relationship */
1998 /* between rounding and engine compensation. However, it seems from */
1999 /* the description of super round that we should add the compensation */
2000 /* before rounding. */
2001 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002002 static FT_F26Dot6
2003 Round_None( EXEC_OP_ FT_F26Dot6 distance,
2004 FT_F26Dot6 compensation )
David Turnerd2b1f351999-12-16 23:11:37 +00002005 {
David Turnerf9b8dec2000-06-16 19:34:52 +00002006 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00002007
David Turnerc6a92202000-07-04 18:12:13 +00002008 FT_UNUSED_EXEC;
David Turnerd2b1f351999-12-16 23:11:37 +00002009
Werner Lemberg78575dc2000-06-12 19:36:41 +00002010
David Turnerd2b1f351999-12-16 23:11:37 +00002011 if ( distance >= 0 )
2012 {
2013 val = distance + compensation;
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002014 if ( distance && val < 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00002015 val = 0;
2016 }
Werner Lemberg370aea82010-06-08 08:37:11 +02002017 else
2018 {
David Turnerd2b1f351999-12-16 23:11:37 +00002019 val = distance - compensation;
2020 if ( val > 0 )
2021 val = 0;
2022 }
2023 return val;
2024 }
2025
2026
2027 /*************************************************************************/
2028 /* */
2029 /* <Function> */
2030 /* Round_To_Grid */
2031 /* */
2032 /* <Description> */
2033 /* Rounds value to grid after adding engine compensation. */
2034 /* */
2035 /* <Input> */
2036 /* distance :: The distance to round. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00002037 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00002038 /* compensation :: The engine compensation. */
2039 /* */
2040 /* <Return> */
2041 /* Rounded distance. */
2042 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002043 static FT_F26Dot6
2044 Round_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
2045 FT_F26Dot6 compensation )
David Turnerd2b1f351999-12-16 23:11:37 +00002046 {
David Turnerf9b8dec2000-06-16 19:34:52 +00002047 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00002048
David Turnerc6a92202000-07-04 18:12:13 +00002049 FT_UNUSED_EXEC;
David Turnerd2b1f351999-12-16 23:11:37 +00002050
Werner Lemberg78575dc2000-06-12 19:36:41 +00002051
David Turnerd2b1f351999-12-16 23:11:37 +00002052 if ( distance >= 0 )
2053 {
2054 val = distance + compensation + 32;
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002055 if ( distance && val > 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00002056 val &= ~63;
2057 else
2058 val = 0;
2059 }
2060 else
2061 {
David Turner87c0d302003-12-24 01:10:46 +00002062 val = -FT_PIX_ROUND( compensation - distance );
David Turnerd2b1f351999-12-16 23:11:37 +00002063 if ( val > 0 )
2064 val = 0;
2065 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00002066
David Turnerd2b1f351999-12-16 23:11:37 +00002067 return val;
2068 }
2069
2070
2071 /*************************************************************************/
2072 /* */
2073 /* <Function> */
2074 /* Round_To_Half_Grid */
2075 /* */
2076 /* <Description> */
2077 /* Rounds value to half grid after adding engine compensation. */
2078 /* */
2079 /* <Input> */
2080 /* distance :: The distance to round. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00002081 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00002082 /* compensation :: The engine compensation. */
2083 /* */
2084 /* <Return> */
2085 /* Rounded distance. */
2086 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002087 static FT_F26Dot6
2088 Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6 distance,
2089 FT_F26Dot6 compensation )
David Turnerd2b1f351999-12-16 23:11:37 +00002090 {
David Turnerf9b8dec2000-06-16 19:34:52 +00002091 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00002092
David Turnerc6a92202000-07-04 18:12:13 +00002093 FT_UNUSED_EXEC;
David Turnere49ab252000-05-16 23:44:38 +00002094
David Turnerd2b1f351999-12-16 23:11:37 +00002095
2096 if ( distance >= 0 )
2097 {
David Turner87c0d302003-12-24 01:10:46 +00002098 val = FT_PIX_FLOOR( distance + compensation ) + 32;
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002099 if ( distance && val < 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00002100 val = 0;
2101 }
2102 else
2103 {
David Turner87c0d302003-12-24 01:10:46 +00002104 val = -( FT_PIX_FLOOR( compensation - distance ) + 32 );
David Turnerd2b1f351999-12-16 23:11:37 +00002105 if ( val > 0 )
2106 val = 0;
2107 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00002108
David Turnerd2b1f351999-12-16 23:11:37 +00002109 return val;
2110 }
2111
2112
2113 /*************************************************************************/
2114 /* */
2115 /* <Function> */
2116 /* Round_Down_To_Grid */
2117 /* */
2118 /* <Description> */
2119 /* Rounds value down to grid after adding engine compensation. */
2120 /* */
2121 /* <Input> */
2122 /* distance :: The distance to round. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00002123 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00002124 /* compensation :: The engine compensation. */
2125 /* */
2126 /* <Return> */
2127 /* Rounded distance. */
2128 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002129 static FT_F26Dot6
2130 Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
2131 FT_F26Dot6 compensation )
David Turnerd2b1f351999-12-16 23:11:37 +00002132 {
David Turnerf9b8dec2000-06-16 19:34:52 +00002133 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00002134
David Turnerc6a92202000-07-04 18:12:13 +00002135 FT_UNUSED_EXEC;
David Turnerd2b1f351999-12-16 23:11:37 +00002136
Werner Lemberg78575dc2000-06-12 19:36:41 +00002137
David Turnerd2b1f351999-12-16 23:11:37 +00002138 if ( distance >= 0 )
2139 {
2140 val = distance + compensation;
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002141 if ( distance && val > 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00002142 val &= ~63;
2143 else
2144 val = 0;
2145 }
2146 else
2147 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00002148 val = -( ( compensation - distance ) & -64 );
David Turnerd2b1f351999-12-16 23:11:37 +00002149 if ( val > 0 )
2150 val = 0;
2151 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00002152
David Turnerd2b1f351999-12-16 23:11:37 +00002153 return val;
2154 }
2155
2156
2157 /*************************************************************************/
2158 /* */
2159 /* <Function> */
2160 /* Round_Up_To_Grid */
2161 /* */
2162 /* <Description> */
2163 /* Rounds value up to grid after adding engine compensation. */
2164 /* */
2165 /* <Input> */
2166 /* distance :: The distance to round. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00002167 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00002168 /* compensation :: The engine compensation. */
2169 /* */
2170 /* <Return> */
2171 /* Rounded distance. */
2172 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002173 static FT_F26Dot6
2174 Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
2175 FT_F26Dot6 compensation )
David Turnerd2b1f351999-12-16 23:11:37 +00002176 {
David Turnerf9b8dec2000-06-16 19:34:52 +00002177 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00002178
David Turnerc6a92202000-07-04 18:12:13 +00002179 FT_UNUSED_EXEC;
David Turnerd2b1f351999-12-16 23:11:37 +00002180
Werner Lembergc6a14082007-02-12 22:08:15 +00002181
David Turnerd2b1f351999-12-16 23:11:37 +00002182 if ( distance >= 0 )
2183 {
2184 val = distance + compensation + 63;
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002185 if ( distance && val > 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00002186 val &= ~63;
2187 else
2188 val = 0;
2189 }
2190 else
2191 {
David Turner87c0d302003-12-24 01:10:46 +00002192 val = - FT_PIX_CEIL( compensation - distance );
David Turnerd2b1f351999-12-16 23:11:37 +00002193 if ( val > 0 )
2194 val = 0;
2195 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00002196
David Turnerd2b1f351999-12-16 23:11:37 +00002197 return val;
2198 }
2199
2200
2201 /*************************************************************************/
2202 /* */
2203 /* <Function> */
2204 /* Round_To_Double_Grid */
2205 /* */
2206 /* <Description> */
2207 /* Rounds value to double grid after adding engine compensation. */
2208 /* */
2209 /* <Input> */
2210 /* distance :: The distance to round. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00002211 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00002212 /* compensation :: The engine compensation. */
2213 /* */
2214 /* <Return> */
2215 /* Rounded distance. */
2216 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002217 static FT_F26Dot6
2218 Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6 distance,
2219 FT_F26Dot6 compensation )
David Turnerd2b1f351999-12-16 23:11:37 +00002220 {
David Turnerf9b8dec2000-06-16 19:34:52 +00002221 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00002222
David Turnerc6a92202000-07-04 18:12:13 +00002223 FT_UNUSED_EXEC;
David Turnerd2b1f351999-12-16 23:11:37 +00002224
Werner Lemberg78575dc2000-06-12 19:36:41 +00002225
David Turnerd2b1f351999-12-16 23:11:37 +00002226 if ( distance >= 0 )
2227 {
2228 val = distance + compensation + 16;
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002229 if ( distance && val > 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00002230 val &= ~31;
2231 else
2232 val = 0;
2233 }
2234 else
2235 {
David Turner87c0d302003-12-24 01:10:46 +00002236 val = -FT_PAD_ROUND( compensation - distance, 32 );
David Turnerd2b1f351999-12-16 23:11:37 +00002237 if ( val > 0 )
2238 val = 0;
2239 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00002240
David Turnerd2b1f351999-12-16 23:11:37 +00002241 return val;
2242 }
2243
2244
2245 /*************************************************************************/
2246 /* */
2247 /* <Function> */
2248 /* Round_Super */
2249 /* */
2250 /* <Description> */
2251 /* Super-rounds value to grid after adding engine compensation. */
2252 /* */
2253 /* <Input> */
2254 /* distance :: The distance to round. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00002255 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00002256 /* compensation :: The engine compensation. */
2257 /* */
2258 /* <Return> */
2259 /* Rounded distance. */
2260 /* */
2261 /* <Note> */
2262 /* The TrueType specification says very few about the relationship */
2263 /* between rounding and engine compensation. However, it seems from */
2264 /* the description of super round that we should add the compensation */
2265 /* before rounding. */
2266 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002267 static FT_F26Dot6
2268 Round_Super( EXEC_OP_ FT_F26Dot6 distance,
2269 FT_F26Dot6 compensation )
David Turnerd2b1f351999-12-16 23:11:37 +00002270 {
David Turnerf9b8dec2000-06-16 19:34:52 +00002271 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00002272
2273
2274 if ( distance >= 0 )
2275 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00002276 val = ( distance - CUR.phase + CUR.threshold + compensation ) &
2277 -CUR.period;
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002278 if ( distance && val < 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00002279 val = 0;
2280 val += CUR.phase;
2281 }
2282 else
2283 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00002284 val = -( ( CUR.threshold - CUR.phase - distance + compensation ) &
2285 -CUR.period );
David Turnerd2b1f351999-12-16 23:11:37 +00002286 if ( val > 0 )
2287 val = 0;
2288 val -= CUR.phase;
2289 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00002290
David Turnerd2b1f351999-12-16 23:11:37 +00002291 return val;
2292 }
2293
2294
2295 /*************************************************************************/
2296 /* */
2297 /* <Function> */
2298 /* Round_Super_45 */
2299 /* */
2300 /* <Description> */
2301 /* Super-rounds value to grid after adding engine compensation. */
2302 /* */
2303 /* <Input> */
2304 /* distance :: The distance to round. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00002305 /* */
David Turnerd2b1f351999-12-16 23:11:37 +00002306 /* compensation :: The engine compensation. */
2307 /* */
2308 /* <Return> */
2309 /* Rounded distance. */
2310 /* */
2311 /* <Note> */
2312 /* There is a separate function for Round_Super_45() as we may need */
2313 /* greater precision. */
2314 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002315 static FT_F26Dot6
2316 Round_Super_45( EXEC_OP_ FT_F26Dot6 distance,
2317 FT_F26Dot6 compensation )
David Turnerd2b1f351999-12-16 23:11:37 +00002318 {
David Turnerf9b8dec2000-06-16 19:34:52 +00002319 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00002320
2321
2322 if ( distance >= 0 )
2323 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00002324 val = ( ( distance - CUR.phase + CUR.threshold + compensation ) /
David Turnerd2b1f351999-12-16 23:11:37 +00002325 CUR.period ) * CUR.period;
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002326 if ( distance && val < 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00002327 val = 0;
2328 val += CUR.phase;
2329 }
2330 else
2331 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00002332 val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) /
David Turnerd2b1f351999-12-16 23:11:37 +00002333 CUR.period ) * CUR.period );
2334 if ( val > 0 )
2335 val = 0;
2336 val -= CUR.phase;
2337 }
2338
2339 return val;
2340 }
2341
2342
2343 /*************************************************************************/
2344 /* */
2345 /* <Function> */
2346 /* Compute_Round */
2347 /* */
2348 /* <Description> */
2349 /* Sets the rounding mode. */
2350 /* */
2351 /* <Input> */
2352 /* round_mode :: The rounding mode to be used. */
2353 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002354 static void
2355 Compute_Round( EXEC_OP_ FT_Byte round_mode )
David Turnerd2b1f351999-12-16 23:11:37 +00002356 {
2357 switch ( round_mode )
2358 {
2359 case TT_Round_Off:
2360 CUR.func_round = (TT_Round_Func)Round_None;
2361 break;
2362
2363 case TT_Round_To_Grid:
2364 CUR.func_round = (TT_Round_Func)Round_To_Grid;
2365 break;
2366
2367 case TT_Round_Up_To_Grid:
2368 CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
2369 break;
2370
2371 case TT_Round_Down_To_Grid:
2372 CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
2373 break;
2374
2375 case TT_Round_To_Half_Grid:
2376 CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
2377 break;
2378
2379 case TT_Round_To_Double_Grid:
2380 CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
2381 break;
2382
2383 case TT_Round_Super:
2384 CUR.func_round = (TT_Round_Func)Round_Super;
2385 break;
2386
2387 case TT_Round_Super_45:
2388 CUR.func_round = (TT_Round_Func)Round_Super_45;
2389 break;
2390 }
2391 }
2392
2393
2394 /*************************************************************************/
2395 /* */
2396 /* <Function> */
2397 /* SetSuperRound */
2398 /* */
2399 /* <Description> */
2400 /* Sets Super Round parameters. */
2401 /* */
2402 /* <Input> */
2403 /* GridPeriod :: Grid period */
2404 /* selector :: SROUND opcode */
2405 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002406 static void
2407 SetSuperRound( EXEC_OP_ FT_F26Dot6 GridPeriod,
2408 FT_Long selector )
David Turnerd2b1f351999-12-16 23:11:37 +00002409 {
David Turnerf9b8dec2000-06-16 19:34:52 +00002410 switch ( (FT_Int)( selector & 0xC0 ) )
David Turnerd2b1f351999-12-16 23:11:37 +00002411 {
2412 case 0:
2413 CUR.period = GridPeriod / 2;
2414 break;
2415
2416 case 0x40:
2417 CUR.period = GridPeriod;
2418 break;
2419
2420 case 0x80:
2421 CUR.period = GridPeriod * 2;
2422 break;
2423
2424 /* This opcode is reserved, but... */
2425
2426 case 0xC0:
2427 CUR.period = GridPeriod;
2428 break;
2429 }
2430
David Turnerf9b8dec2000-06-16 19:34:52 +00002431 switch ( (FT_Int)( selector & 0x30 ) )
David Turnerd2b1f351999-12-16 23:11:37 +00002432 {
2433 case 0:
2434 CUR.phase = 0;
2435 break;
2436
2437 case 0x10:
2438 CUR.phase = CUR.period / 4;
2439 break;
2440
2441 case 0x20:
2442 CUR.phase = CUR.period / 2;
2443 break;
2444
2445 case 0x30:
Werner Lemberg6e9b3182003-06-10 10:54:33 +00002446 CUR.phase = CUR.period * 3 / 4;
David Turnerd2b1f351999-12-16 23:11:37 +00002447 break;
2448 }
2449
Werner Lembergc9f6c662007-03-21 13:30:14 +00002450 if ( ( selector & 0x0F ) == 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00002451 CUR.threshold = CUR.period - 1;
2452 else
David Turnerf9b8dec2000-06-16 19:34:52 +00002453 CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8;
David Turnerd2b1f351999-12-16 23:11:37 +00002454
2455 CUR.period /= 256;
2456 CUR.phase /= 256;
2457 CUR.threshold /= 256;
2458 }
2459
2460
2461 /*************************************************************************/
2462 /* */
2463 /* <Function> */
2464 /* Project */
2465 /* */
2466 /* <Description> */
2467 /* Computes the projection of vector given by (v2-v1) along the */
2468 /* current projection vector. */
2469 /* */
2470 /* <Input> */
2471 /* v1 :: First input vector. */
2472 /* v2 :: Second input vector. */
2473 /* */
2474 /* <Return> */
2475 /* The distance in F26dot6 format. */
2476 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002477 static FT_F26Dot6
David Turner72a0dd22007-02-12 15:24:51 +00002478 Project( EXEC_OP_ FT_Pos dx,
2479 FT_Pos dy )
Werner Lemberg406d25f2007-02-12 22:01:18 +00002480 {
David Turner8b6db862003-08-17 22:09:14 +00002481#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Werner Lemberga3f4da82003-04-29 13:23:47 +00002482 FT_ASSERT( !CUR.face->unpatented_hinting );
Graham Asher3ea859f2003-04-25 11:40:46 +00002483#endif
Werner Lemberga3f4da82003-04-29 13:23:47 +00002484
suzuki toshiya3b56c4d2009-08-01 00:32:15 +09002485 return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,
David Turner4b29d582002-03-25 17:02:26 +00002486 CUR.GS.projVector.x,
2487 CUR.GS.projVector.y );
Werner Lemberg406d25f2007-02-12 22:01:18 +00002488 }
2489
David Turnerd2b1f351999-12-16 23:11:37 +00002490
David Turnerd2b1f351999-12-16 23:11:37 +00002491 /*************************************************************************/
2492 /* */
2493 /* <Function> */
2494 /* Dual_Project */
2495 /* */
2496 /* <Description> */
2497 /* Computes the projection of the vector given by (v2-v1) along the */
2498 /* current dual vector. */
2499 /* */
2500 /* <Input> */
2501 /* v1 :: First input vector. */
2502 /* v2 :: Second input vector. */
2503 /* */
2504 /* <Return> */
2505 /* The distance in F26dot6 format. */
2506 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002507 static FT_F26Dot6
David Turner72a0dd22007-02-12 15:24:51 +00002508 Dual_Project( EXEC_OP_ FT_Pos dx,
2509 FT_Pos dy )
David Turnerd2b1f351999-12-16 23:11:37 +00002510 {
suzuki toshiya3b56c4d2009-08-01 00:32:15 +09002511 return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,
David Turner4b29d582002-03-25 17:02:26 +00002512 CUR.GS.dualVector.x,
2513 CUR.GS.dualVector.y );
David Turnerd2b1f351999-12-16 23:11:37 +00002514 }
2515
Werner Lemberg406d25f2007-02-12 22:01:18 +00002516
David Turnerd2b1f351999-12-16 23:11:37 +00002517 /*************************************************************************/
2518 /* */
2519 /* <Function> */
David Turnerd2b1f351999-12-16 23:11:37 +00002520 /* Project_x */
2521 /* */
2522 /* <Description> */
2523 /* Computes the projection of the vector given by (v2-v1) along the */
2524 /* horizontal axis. */
2525 /* */
2526 /* <Input> */
2527 /* v1 :: First input vector. */
2528 /* v2 :: Second input vector. */
2529 /* */
2530 /* <Return> */
2531 /* The distance in F26dot6 format. */
2532 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002533 static FT_F26Dot6
David Turner72a0dd22007-02-12 15:24:51 +00002534 Project_x( EXEC_OP_ FT_Pos dx,
2535 FT_Pos dy )
David Turnerd2b1f351999-12-16 23:11:37 +00002536 {
David Turnerc6a92202000-07-04 18:12:13 +00002537 FT_UNUSED_EXEC;
Werner Lembergc6a14082007-02-12 22:08:15 +00002538 FT_UNUSED( dy );
David Turnerd2b1f351999-12-16 23:11:37 +00002539
David Turner72a0dd22007-02-12 15:24:51 +00002540 return dx;
David Turnerd2b1f351999-12-16 23:11:37 +00002541 }
2542
Werner Lemberg406d25f2007-02-12 22:01:18 +00002543
David Turnerd2b1f351999-12-16 23:11:37 +00002544 /*************************************************************************/
2545 /* */
2546 /* <Function> */
2547 /* Project_y */
2548 /* */
2549 /* <Description> */
2550 /* Computes the projection of the vector given by (v2-v1) along the */
2551 /* vertical axis. */
2552 /* */
2553 /* <Input> */
2554 /* v1 :: First input vector. */
2555 /* v2 :: Second input vector. */
2556 /* */
2557 /* <Return> */
2558 /* The distance in F26dot6 format. */
2559 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002560 static FT_F26Dot6
David Turner72a0dd22007-02-12 15:24:51 +00002561 Project_y( EXEC_OP_ FT_Pos dx,
2562 FT_Pos dy )
David Turnerd2b1f351999-12-16 23:11:37 +00002563 {
David Turnerc6a92202000-07-04 18:12:13 +00002564 FT_UNUSED_EXEC;
Werner Lembergc6a14082007-02-12 22:08:15 +00002565 FT_UNUSED( dx );
David Turnere49ab252000-05-16 23:44:38 +00002566
David Turner72a0dd22007-02-12 15:24:51 +00002567 return dy;
David Turnerd2b1f351999-12-16 23:11:37 +00002568 }
2569
Werner Lemberg406d25f2007-02-12 22:01:18 +00002570
David Turnerd2b1f351999-12-16 23:11:37 +00002571 /*************************************************************************/
2572 /* */
2573 /* <Function> */
2574 /* Compute_Funcs */
2575 /* */
2576 /* <Description> */
2577 /* Computes the projection and movement function pointers according */
2578 /* to the current graphics state. */
2579 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002580 static void
2581 Compute_Funcs( EXEC_OP )
David Turnerd2b1f351999-12-16 23:11:37 +00002582 {
David Turner8b6db862003-08-17 22:09:14 +00002583#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Graham Asher3ea859f2003-04-25 11:40:46 +00002584 if ( CUR.face->unpatented_hinting )
Werner Lemberga3f4da82003-04-29 13:23:47 +00002585 {
Graham Asher3ea859f2003-04-25 11:40:46 +00002586 /* If both vectors point rightwards along the x axis, set */
Werner Lemberga3f4da82003-04-29 13:23:47 +00002587 /* `both-x-axis' true, otherwise set it false. The x values only */
2588 /* need be tested because the vector has been normalised to a unit */
2589 /* vector of length 0x4000 = unity. */
2590 CUR.GS.both_x_axis = (FT_Bool)( CUR.GS.projVector.x == 0x4000 &&
2591 CUR.GS.freeVector.x == 0x4000 );
Graham Asher3ea859f2003-04-25 11:40:46 +00002592
Werner Lemberga3f4da82003-04-29 13:23:47 +00002593 /* Throw away projection and freedom vector information */
2594 /* because the patents don't allow them to be stored. */
2595 /* The relevant US Patents are 5155805 and 5325479. */
Graham Asher3ea859f2003-04-25 11:40:46 +00002596 CUR.GS.projVector.x = 0;
2597 CUR.GS.projVector.y = 0;
2598 CUR.GS.freeVector.x = 0;
2599 CUR.GS.freeVector.y = 0;
2600
2601 if ( CUR.GS.both_x_axis )
2602 {
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002603 CUR.func_project = Project_x;
2604 CUR.func_move = Direct_Move_X;
2605 CUR.func_move_orig = Direct_Move_Orig_X;
Graham Asher3ea859f2003-04-25 11:40:46 +00002606 }
Werner Lemberga3f4da82003-04-29 13:23:47 +00002607 else
Graham Asher3ea859f2003-04-25 11:40:46 +00002608 {
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002609 CUR.func_project = Project_y;
2610 CUR.func_move = Direct_Move_Y;
2611 CUR.func_move_orig = Direct_Move_Orig_Y;
Graham Asher3ea859f2003-04-25 11:40:46 +00002612 }
2613
2614 if ( CUR.GS.dualVector.x == 0x4000 )
2615 CUR.func_dualproj = Project_x;
2616 else
2617 {
2618 if ( CUR.GS.dualVector.y == 0x4000 )
Werner Lemberga3f4da82003-04-29 13:23:47 +00002619 CUR.func_dualproj = Project_y;
Graham Asher3ea859f2003-04-25 11:40:46 +00002620 else
2621 CUR.func_dualproj = Dual_Project;
2622 }
2623
2624 /* Force recalculation of cached aspect ratio */
2625 CUR.tt_metrics.ratio = 0;
2626
Werner Lemberga3f4da82003-04-29 13:23:47 +00002627 return;
2628 }
David Turner8b6db862003-08-17 22:09:14 +00002629#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */
Graham Asher3ea859f2003-04-25 11:40:46 +00002630
David Turnerd2b1f351999-12-16 23:11:37 +00002631 if ( CUR.GS.freeVector.x == 0x4000 )
David Turnerd2b1f351999-12-16 23:11:37 +00002632 CUR.F_dot_P = CUR.GS.projVector.x * 0x10000L;
David Turnerd2b1f351999-12-16 23:11:37 +00002633 else
2634 {
2635 if ( CUR.GS.freeVector.y == 0x4000 )
David Turnerd2b1f351999-12-16 23:11:37 +00002636 CUR.F_dot_P = CUR.GS.projVector.y * 0x10000L;
David Turnerd2b1f351999-12-16 23:11:37 +00002637 else
David Turnerf9b8dec2000-06-16 19:34:52 +00002638 CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 +
2639 (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4;
David Turnerd2b1f351999-12-16 23:11:37 +00002640 }
2641
2642 if ( CUR.GS.projVector.x == 0x4000 )
2643 CUR.func_project = (TT_Project_Func)Project_x;
2644 else
2645 {
2646 if ( CUR.GS.projVector.y == 0x4000 )
2647 CUR.func_project = (TT_Project_Func)Project_y;
2648 else
2649 CUR.func_project = (TT_Project_Func)Project;
2650 }
2651
2652 if ( CUR.GS.dualVector.x == 0x4000 )
2653 CUR.func_dualproj = (TT_Project_Func)Project_x;
2654 else
2655 {
2656 if ( CUR.GS.dualVector.y == 0x4000 )
2657 CUR.func_dualproj = (TT_Project_Func)Project_y;
2658 else
2659 CUR.func_dualproj = (TT_Project_Func)Dual_Project;
2660 }
2661
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002662 CUR.func_move = (TT_Move_Func)Direct_Move;
2663 CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig;
David Turnerd2b1f351999-12-16 23:11:37 +00002664
2665 if ( CUR.F_dot_P == 0x40000000L )
2666 {
2667 if ( CUR.GS.freeVector.x == 0x4000 )
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002668 {
2669 CUR.func_move = (TT_Move_Func)Direct_Move_X;
2670 CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
2671 }
David Turnerd2b1f351999-12-16 23:11:37 +00002672 else
2673 {
2674 if ( CUR.GS.freeVector.y == 0x4000 )
Werner Lembergbe67c4e2003-11-24 22:54:58 +00002675 {
2676 CUR.func_move = (TT_Move_Func)Direct_Move_Y;
2677 CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
2678 }
David Turnerd2b1f351999-12-16 23:11:37 +00002679 }
2680 }
2681
2682 /* at small sizes, F_dot_P can become too small, resulting */
2683 /* in overflows and `spikes' in a number of glyphs like `w'. */
2684
Werner Lembergdfa46192004-03-05 09:26:24 +00002685 if ( FT_ABS( CUR.F_dot_P ) < 0x4000000L )
David Turnerd2b1f351999-12-16 23:11:37 +00002686 CUR.F_dot_P = 0x40000000L;
2687
2688 /* Disable cached aspect ratio */
2689 CUR.tt_metrics.ratio = 0;
2690 }
2691
2692
2693 /*************************************************************************/
2694 /* */
2695 /* <Function> */
2696 /* Normalize */
2697 /* */
2698 /* <Description> */
2699 /* Norms a vector. */
2700 /* */
2701 /* <Input> */
2702 /* Vx :: The horizontal input vector coordinate. */
2703 /* Vy :: The vertical input vector coordinate. */
2704 /* */
2705 /* <Output> */
2706 /* R :: The normed unit vector. */
2707 /* */
2708 /* <Return> */
2709 /* Returns FAILURE if a vector parameter is zero. */
2710 /* */
2711 /* <Note> */
2712 /* In case Vx and Vy are both zero, Normalize() returns SUCCESS, and */
2713 /* R is undefined. */
2714 /* */
David Turnerb7ef2b02000-05-02 11:01:12 +00002715
Werner Lemberg78575dc2000-06-12 19:36:41 +00002716
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002717 static FT_Bool
2718 Normalize( EXEC_OP_ FT_F26Dot6 Vx,
2719 FT_F26Dot6 Vy,
2720 FT_UnitVector* R )
David Turnerb7ef2b02000-05-02 11:01:12 +00002721 {
David Turnerf9b8dec2000-06-16 19:34:52 +00002722 FT_F26Dot6 W;
2723 FT_Bool S1, S2;
David Turnerb7ef2b02000-05-02 11:01:12 +00002724
David Turnerc6a92202000-07-04 18:12:13 +00002725 FT_UNUSED_EXEC;
David Turnere49ab252000-05-16 23:44:38 +00002726
Werner Lemberg78575dc2000-06-12 19:36:41 +00002727
Werner Lembergdfa46192004-03-05 09:26:24 +00002728 if ( FT_ABS( Vx ) < 0x10000L && FT_ABS( Vy ) < 0x10000L )
David Turnerb7ef2b02000-05-02 11:01:12 +00002729 {
2730 Vx *= 0x100;
2731 Vy *= 0x100;
2732
David Turner4b29d582002-03-25 17:02:26 +00002733 W = TT_VecLen( Vx, Vy );
David Turnerb7ef2b02000-05-02 11:01:12 +00002734
2735 if ( W == 0 )
2736 {
Werner Lemberg5811c7c2000-07-02 13:53:16 +00002737 /* XXX: UNDOCUMENTED! It seems that it is possible to try */
Werner Lemberg78575dc2000-06-12 19:36:41 +00002738 /* to normalize the vector (0,0). Return immediately. */
David Turnerb7ef2b02000-05-02 11:01:12 +00002739 return SUCCESS;
2740 }
2741
David Turnerf9b8dec2000-06-16 19:34:52 +00002742 R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W );
2743 R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W );
David Turnerb7ef2b02000-05-02 11:01:12 +00002744
2745 return SUCCESS;
2746 }
2747
David Turner4b29d582002-03-25 17:02:26 +00002748 W = TT_VecLen( Vx, Vy );
David Turnerb7ef2b02000-05-02 11:01:12 +00002749
2750 Vx = FT_MulDiv( Vx, 0x4000L, W );
2751 Vy = FT_MulDiv( Vy, 0x4000L, W );
2752
2753 W = Vx * Vx + Vy * Vy;
2754
2755 /* Now, we want that Sqrt( W ) = 0x4000 */
David Turner5ab41362004-07-18 07:15:18 +00002756 /* Or 0x10000000 <= W < 0x10004000 */
David Turnerb7ef2b02000-05-02 11:01:12 +00002757
2758 if ( Vx < 0 )
2759 {
2760 Vx = -Vx;
2761 S1 = TRUE;
2762 }
2763 else
2764 S1 = FALSE;
2765
2766 if ( Vy < 0 )
2767 {
2768 Vy = -Vy;
2769 S2 = TRUE;
2770 }
2771 else
2772 S2 = FALSE;
2773
David Turner5ab41362004-07-18 07:15:18 +00002774 while ( W < 0x10000000L )
David Turnerb7ef2b02000-05-02 11:01:12 +00002775 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00002776 /* We need to increase W by a minimal amount */
David Turnerb7ef2b02000-05-02 11:01:12 +00002777 if ( Vx < Vy )
2778 Vx++;
2779 else
2780 Vy++;
2781
2782 W = Vx * Vx + Vy * Vy;
2783 }
2784
David Turner5ab41362004-07-18 07:15:18 +00002785 while ( W >= 0x10004000L )
David Turnerb7ef2b02000-05-02 11:01:12 +00002786 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00002787 /* We need to decrease W by a minimal amount */
David Turnerb7ef2b02000-05-02 11:01:12 +00002788 if ( Vx < Vy )
2789 Vx--;
2790 else
2791 Vy--;
2792
2793 W = Vx * Vx + Vy * Vy;
2794 }
2795
2796 /* Note that in various cases, we can only */
2797 /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */
2798
2799 if ( S1 )
2800 Vx = -Vx;
2801
2802 if ( S2 )
2803 Vy = -Vy;
2804
David Turnerf9b8dec2000-06-16 19:34:52 +00002805 R->x = (FT_F2Dot14)Vx; /* Type conversion */
2806 R->y = (FT_F2Dot14)Vy; /* Type conversion */
David Turnerb7ef2b02000-05-02 11:01:12 +00002807
2808 return SUCCESS;
2809 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00002810
David Turnerd2b1f351999-12-16 23:11:37 +00002811
2812 /*************************************************************************/
2813 /* */
2814 /* Here we start with the implementation of the various opcodes. */
2815 /* */
2816 /*************************************************************************/
2817
2818
Werner Lemberg4a2305c2001-06-28 07:17:51 +00002819 static FT_Bool
2820 Ins_SxVTL( EXEC_OP_ FT_UShort aIdx1,
2821 FT_UShort aIdx2,
2822 FT_Int aOpc,
2823 FT_UnitVector* Vec )
David Turnerd2b1f351999-12-16 23:11:37 +00002824 {
David Turnerf9b8dec2000-06-16 19:34:52 +00002825 FT_Long A, B, C;
2826 FT_Vector* p1;
2827 FT_Vector* p2;
David Turnerd2b1f351999-12-16 23:11:37 +00002828
2829
2830 if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||
2831 BOUNDS( aIdx2, CUR.zp1.n_points ) )
2832 {
2833 if ( CUR.pedantic_hinting )
2834 CUR.error = TT_Err_Invalid_Reference;
2835 return FAILURE;
2836 }
2837
2838 p1 = CUR.zp1.cur + aIdx2;
2839 p2 = CUR.zp2.cur + aIdx1;
2840
2841 A = p1->x - p2->x;
2842 B = p1->y - p2->y;
2843
Werner Lemberg78575dc2000-06-12 19:36:41 +00002844 if ( ( aOpc & 1 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00002845 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00002846 C = B; /* counter clockwise rotation */
David Turnerd2b1f351999-12-16 23:11:37 +00002847 B = A;
2848 A = -C;
2849 }
2850
2851 NORMalize( A, B, Vec );
2852
2853 return SUCCESS;
2854 }
2855
2856
2857 /* When not using the big switch statements, the interpreter uses a */
2858 /* call table defined later below in this source. Each opcode must */
2859 /* thus have a corresponding function, even trivial ones. */
2860 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00002861 /* They are all defined there. */
David Turnerd2b1f351999-12-16 23:11:37 +00002862
Werner Lemberg78575dc2000-06-12 19:36:41 +00002863#define DO_SVTCA \
2864 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00002865 FT_Short A, B; \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002866 \
2867 \
David Turnerf9b8dec2000-06-16 19:34:52 +00002868 A = (FT_Short)( CUR.opcode & 1 ) << 14; \
2869 B = A ^ (FT_Short)0x4000; \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002870 \
2871 CUR.GS.freeVector.x = A; \
2872 CUR.GS.projVector.x = A; \
2873 CUR.GS.dualVector.x = A; \
2874 \
2875 CUR.GS.freeVector.y = B; \
2876 CUR.GS.projVector.y = B; \
2877 CUR.GS.dualVector.y = B; \
2878 \
2879 COMPUTE_Funcs(); \
David Turnerd2b1f351999-12-16 23:11:37 +00002880 }
2881
2882
Werner Lemberg78575dc2000-06-12 19:36:41 +00002883#define DO_SPVTCA \
2884 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00002885 FT_Short A, B; \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002886 \
2887 \
David Turnerf9b8dec2000-06-16 19:34:52 +00002888 A = (FT_Short)( CUR.opcode & 1 ) << 14; \
2889 B = A ^ (FT_Short)0x4000; \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002890 \
2891 CUR.GS.projVector.x = A; \
2892 CUR.GS.dualVector.x = A; \
2893 \
2894 CUR.GS.projVector.y = B; \
2895 CUR.GS.dualVector.y = B; \
2896 \
Graham Asher3ea859f2003-04-25 11:40:46 +00002897 GUESS_VECTOR( freeVector ); \
2898 \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002899 COMPUTE_Funcs(); \
David Turnerd2b1f351999-12-16 23:11:37 +00002900 }
2901
2902
Werner Lemberg78575dc2000-06-12 19:36:41 +00002903#define DO_SFVTCA \
2904 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00002905 FT_Short A, B; \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002906 \
2907 \
David Turnerf9b8dec2000-06-16 19:34:52 +00002908 A = (FT_Short)( CUR.opcode & 1 ) << 14; \
2909 B = A ^ (FT_Short)0x4000; \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002910 \
2911 CUR.GS.freeVector.x = A; \
2912 CUR.GS.freeVector.y = B; \
2913 \
Graham Asher3ea859f2003-04-25 11:40:46 +00002914 GUESS_VECTOR( projVector ); \
2915 \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002916 COMPUTE_Funcs(); \
David Turnerd2b1f351999-12-16 23:11:37 +00002917 }
2918
2919
Werner Lemberg78575dc2000-06-12 19:36:41 +00002920#define DO_SPVTL \
David Turnerf9b8dec2000-06-16 19:34:52 +00002921 if ( INS_SxVTL( (FT_UShort)args[1], \
2922 (FT_UShort)args[0], \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002923 CUR.opcode, \
2924 &CUR.GS.projVector ) == SUCCESS ) \
2925 { \
2926 CUR.GS.dualVector = CUR.GS.projVector; \
Graham Asher3ea859f2003-04-25 11:40:46 +00002927 GUESS_VECTOR( freeVector ); \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002928 COMPUTE_Funcs(); \
David Turnerd2b1f351999-12-16 23:11:37 +00002929 }
2930
2931
Werner Lemberg78575dc2000-06-12 19:36:41 +00002932#define DO_SFVTL \
David Turnerf9b8dec2000-06-16 19:34:52 +00002933 if ( INS_SxVTL( (FT_UShort)args[1], \
2934 (FT_UShort)args[0], \
Werner Lemberg78575dc2000-06-12 19:36:41 +00002935 CUR.opcode, \
2936 &CUR.GS.freeVector ) == SUCCESS ) \
Werner Lembergf79a7ae2003-05-21 21:47:25 +00002937 { \
Graham Asher3ea859f2003-04-25 11:40:46 +00002938 GUESS_VECTOR( projVector ); \
Werner Lembergf79a7ae2003-05-21 21:47:25 +00002939 COMPUTE_Funcs(); \
2940 }
David Turnerd2b1f351999-12-16 23:11:37 +00002941
2942
2943#define DO_SFVTPV \
Graham Asher3ea859f2003-04-25 11:40:46 +00002944 GUESS_VECTOR( projVector ); \
David Turnerd2b1f351999-12-16 23:11:37 +00002945 CUR.GS.freeVector = CUR.GS.projVector; \
2946 COMPUTE_Funcs();
2947
2948
2949#define DO_SPVFS \
2950 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00002951 FT_Short S; \
2952 FT_Long X, Y; \
David Turnerd2b1f351999-12-16 23:11:37 +00002953 \
2954 \
2955 /* Only use low 16bits, then sign extend */ \
David Turnerf9b8dec2000-06-16 19:34:52 +00002956 S = (FT_Short)args[1]; \
2957 Y = (FT_Long)S; \
2958 S = (FT_Short)args[0]; \
2959 X = (FT_Long)S; \
David Turnerd2b1f351999-12-16 23:11:37 +00002960 \
2961 NORMalize( X, Y, &CUR.GS.projVector ); \
2962 \
2963 CUR.GS.dualVector = CUR.GS.projVector; \
Graham Asher3ea859f2003-04-25 11:40:46 +00002964 GUESS_VECTOR( freeVector ); \
David Turnerd2b1f351999-12-16 23:11:37 +00002965 COMPUTE_Funcs(); \
2966 }
2967
2968
2969#define DO_SFVFS \
2970 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00002971 FT_Short S; \
2972 FT_Long X, Y; \
David Turnerd2b1f351999-12-16 23:11:37 +00002973 \
2974 \
2975 /* Only use low 16bits, then sign extend */ \
David Turnerf9b8dec2000-06-16 19:34:52 +00002976 S = (FT_Short)args[1]; \
2977 Y = (FT_Long)S; \
2978 S = (FT_Short)args[0]; \
David Turnerd2b1f351999-12-16 23:11:37 +00002979 X = S; \
2980 \
2981 NORMalize( X, Y, &CUR.GS.freeVector ); \
Graham Asher3ea859f2003-04-25 11:40:46 +00002982 GUESS_VECTOR( projVector ); \
David Turnerd2b1f351999-12-16 23:11:37 +00002983 COMPUTE_Funcs(); \
2984 }
2985
2986
David Turner8b6db862003-08-17 22:09:14 +00002987#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Werner Lemberga3f4da82003-04-29 13:23:47 +00002988#define DO_GPV \
2989 if ( CUR.face->unpatented_hinting ) \
2990 { \
2991 args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
2992 args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
2993 } \
2994 else \
2995 { \
2996 args[0] = CUR.GS.projVector.x; \
2997 args[1] = CUR.GS.projVector.y; \
Graham Asher3ea859f2003-04-25 11:40:46 +00002998 }
2999#else
Werner Lemberga3f4da82003-04-29 13:23:47 +00003000#define DO_GPV \
3001 args[0] = CUR.GS.projVector.x; \
David Turnerd2b1f351999-12-16 23:11:37 +00003002 args[1] = CUR.GS.projVector.y;
Graham Asher3ea859f2003-04-25 11:40:46 +00003003#endif
David Turnerd2b1f351999-12-16 23:11:37 +00003004
3005
David Turner8b6db862003-08-17 22:09:14 +00003006#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Werner Lemberga3f4da82003-04-29 13:23:47 +00003007#define DO_GFV \
3008 if ( CUR.face->unpatented_hinting ) \
3009 { \
3010 args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
3011 args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
3012 } \
3013 else \
3014 { \
3015 args[0] = CUR.GS.freeVector.x; \
3016 args[1] = CUR.GS.freeVector.y; \
Graham Asher3ea859f2003-04-25 11:40:46 +00003017 }
3018#else
Werner Lemberga3f4da82003-04-29 13:23:47 +00003019#define DO_GFV \
3020 args[0] = CUR.GS.freeVector.x; \
David Turnerd2b1f351999-12-16 23:11:37 +00003021 args[1] = CUR.GS.freeVector.y;
Graham Asher3ea859f2003-04-25 11:40:46 +00003022#endif
David Turnerd2b1f351999-12-16 23:11:37 +00003023
3024
Werner Lemberg78575dc2000-06-12 19:36:41 +00003025#define DO_SRP0 \
David Turnerf9b8dec2000-06-16 19:34:52 +00003026 CUR.GS.rp0 = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00003027
3028
Werner Lemberg78575dc2000-06-12 19:36:41 +00003029#define DO_SRP1 \
David Turnerf9b8dec2000-06-16 19:34:52 +00003030 CUR.GS.rp1 = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00003031
3032
Werner Lemberg78575dc2000-06-12 19:36:41 +00003033#define DO_SRP2 \
David Turnerf9b8dec2000-06-16 19:34:52 +00003034 CUR.GS.rp2 = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00003035
3036
3037#define DO_RTHG \
3038 CUR.GS.round_state = TT_Round_To_Half_Grid; \
3039 CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
3040
3041
3042#define DO_RTG \
3043 CUR.GS.round_state = TT_Round_To_Grid; \
3044 CUR.func_round = (TT_Round_Func)Round_To_Grid;
3045
3046
3047#define DO_RTDG \
3048 CUR.GS.round_state = TT_Round_To_Double_Grid; \
3049 CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
3050
3051
3052#define DO_RUTG \
3053 CUR.GS.round_state = TT_Round_Up_To_Grid; \
3054 CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
3055
3056
3057#define DO_RDTG \
3058 CUR.GS.round_state = TT_Round_Down_To_Grid; \
3059 CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
3060
3061
3062#define DO_ROFF \
3063 CUR.GS.round_state = TT_Round_Off; \
3064 CUR.func_round = (TT_Round_Func)Round_None;
3065
3066
3067#define DO_SROUND \
3068 SET_SuperRound( 0x4000, args[0] ); \
3069 CUR.GS.round_state = TT_Round_Super; \
3070 CUR.func_round = (TT_Round_Func)Round_Super;
3071
3072
3073#define DO_S45ROUND \
3074 SET_SuperRound( 0x2D41, args[0] ); \
3075 CUR.GS.round_state = TT_Round_Super_45; \
3076 CUR.func_round = (TT_Round_Func)Round_Super_45;
3077
3078
3079#define DO_SLOOP \
3080 if ( args[0] < 0 ) \
3081 CUR.error = TT_Err_Bad_Argument; \
3082 else \
3083 CUR.GS.loop = args[0];
3084
3085
3086#define DO_SMD \
3087 CUR.GS.minimum_distance = args[0];
3088
3089
3090#define DO_SCVTCI \
David Turnerf9b8dec2000-06-16 19:34:52 +00003091 CUR.GS.control_value_cutin = (FT_F26Dot6)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00003092
3093
3094#define DO_SSWCI \
David Turnerf9b8dec2000-06-16 19:34:52 +00003095 CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00003096
3097
Werner Lemberg555258f2007-01-21 09:46:37 +00003098 /* XXX: UNDOCUMENTED! or bug in the Windows engine? */
3099 /* */
3100 /* It seems that the value that is read here is */
3101 /* expressed in 16.16 format rather than in font */
3102 /* units. */
3103 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00003104#define DO_SSW \
David Turnerf9b8dec2000-06-16 19:34:52 +00003105 CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 );
David Turnerd2b1f351999-12-16 23:11:37 +00003106
3107
3108#define DO_FLIPON \
3109 CUR.GS.auto_flip = TRUE;
3110
3111
3112#define DO_FLIPOFF \
3113 CUR.GS.auto_flip = FALSE;
3114
3115
3116#define DO_SDB \
David Turnerf9b8dec2000-06-16 19:34:52 +00003117 CUR.GS.delta_base = (FT_Short)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00003118
3119
3120#define DO_SDS \
David Turnerf9b8dec2000-06-16 19:34:52 +00003121 CUR.GS.delta_shift = (FT_Short)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00003122
3123
3124#define DO_MD /* nothing */
3125
3126
3127#define DO_MPPEM \
3128 args[0] = CURRENT_Ppem();
3129
3130
Werner Lemberg78575dc2000-06-12 19:36:41 +00003131 /* Note: The pointSize should be irrelevant in a given font program; */
3132 /* we thus decide to return only the ppem. */
David Turnerd2b1f351999-12-16 23:11:37 +00003133#if 0
Werner Lemberg78575dc2000-06-12 19:36:41 +00003134
David Turnerd2b1f351999-12-16 23:11:37 +00003135#define DO_MPS \
3136 args[0] = CUR.metrics.pointSize;
Werner Lemberg78575dc2000-06-12 19:36:41 +00003137
David Turnerd2b1f351999-12-16 23:11:37 +00003138#else
Werner Lemberg78575dc2000-06-12 19:36:41 +00003139
3140#define DO_MPS \
David Turnerd2b1f351999-12-16 23:11:37 +00003141 args[0] = CURRENT_Ppem();
Werner Lemberg78575dc2000-06-12 19:36:41 +00003142
3143#endif /* 0 */
3144
David Turnerd2b1f351999-12-16 23:11:37 +00003145
3146#define DO_DUP \
3147 args[1] = args[0];
3148
3149
3150#define DO_CLEAR \
3151 CUR.new_top = 0;
3152
3153
3154#define DO_SWAP \
3155 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00003156 FT_Long L; \
David Turnerd2b1f351999-12-16 23:11:37 +00003157 \
Werner Lemberg78575dc2000-06-12 19:36:41 +00003158 \
David Turnerd2b1f351999-12-16 23:11:37 +00003159 L = args[0]; \
3160 args[0] = args[1]; \
3161 args[1] = L; \
3162 }
3163
3164
3165#define DO_DEPTH \
3166 args[0] = CUR.top;
3167
3168
Werner Lembergd6a213f2011-01-31 18:51:07 +01003169#define DO_CINDEX \
3170 { \
3171 FT_Long L; \
3172 \
3173 \
3174 L = args[0]; \
3175 \
3176 if ( L <= 0 || L > CUR.args ) \
3177 { \
3178 if ( CUR.pedantic_hinting ) \
3179 CUR.error = TT_Err_Invalid_Reference; \
3180 args[0] = 0; \
3181 } \
3182 else \
3183 args[0] = CUR.stack[CUR.args - L]; \
David Turnerd2b1f351999-12-16 23:11:37 +00003184 }
3185
3186
Werner Lembergf1a981b2011-01-31 22:26:53 +01003187#define DO_JROT \
3188 if ( args[1] != 0 ) \
3189 { \
3190 if ( args[0] == 0 && CUR.args == 0 ) \
3191 CUR.error = TT_Err_Bad_Argument; \
3192 CUR.IP += args[0]; \
3193 if ( CUR.IP < 0 ) \
3194 CUR.error = TT_Err_Bad_Argument; \
3195 CUR.step_ins = FALSE; \
David Turnerd2b1f351999-12-16 23:11:37 +00003196 }
3197
3198
Werner Lembergf1a981b2011-01-31 22:26:53 +01003199#define DO_JMPR \
3200 if ( args[0] == 0 && CUR.args == 0 ) \
3201 CUR.error = TT_Err_Bad_Argument; \
3202 CUR.IP += args[0]; \
3203 if ( CUR.IP < 0 ) \
3204 CUR.error = TT_Err_Bad_Argument; \
David Turnerd2b1f351999-12-16 23:11:37 +00003205 CUR.step_ins = FALSE;
3206
3207
Werner Lembergf1a981b2011-01-31 22:26:53 +01003208#define DO_JROF \
3209 if ( args[1] == 0 ) \
3210 { \
3211 if ( args[0] == 0 && CUR.args == 0 ) \
3212 CUR.error = TT_Err_Bad_Argument; \
3213 CUR.IP += args[0]; \
3214 if ( CUR.IP < 0 ) \
3215 CUR.error = TT_Err_Bad_Argument; \
3216 CUR.step_ins = FALSE; \
David Turnerd2b1f351999-12-16 23:11:37 +00003217 }
3218
3219
Werner Lemberg78575dc2000-06-12 19:36:41 +00003220#define DO_LT \
3221 args[0] = ( args[0] < args[1] );
David Turnerd2b1f351999-12-16 23:11:37 +00003222
3223
Werner Lemberg78575dc2000-06-12 19:36:41 +00003224#define DO_LTEQ \
3225 args[0] = ( args[0] <= args[1] );
David Turnerd2b1f351999-12-16 23:11:37 +00003226
3227
Werner Lemberg78575dc2000-06-12 19:36:41 +00003228#define DO_GT \
3229 args[0] = ( args[0] > args[1] );
David Turnerd2b1f351999-12-16 23:11:37 +00003230
3231
Werner Lemberg78575dc2000-06-12 19:36:41 +00003232#define DO_GTEQ \
3233 args[0] = ( args[0] >= args[1] );
David Turnerd2b1f351999-12-16 23:11:37 +00003234
3235
Werner Lemberg78575dc2000-06-12 19:36:41 +00003236#define DO_EQ \
3237 args[0] = ( args[0] == args[1] );
David Turnerd2b1f351999-12-16 23:11:37 +00003238
3239
Werner Lemberg78575dc2000-06-12 19:36:41 +00003240#define DO_NEQ \
3241 args[0] = ( args[0] != args[1] );
David Turnerd2b1f351999-12-16 23:11:37 +00003242
3243
Werner Lemberg78575dc2000-06-12 19:36:41 +00003244#define DO_ODD \
3245 args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 );
David Turnerd2b1f351999-12-16 23:11:37 +00003246
3247
Werner Lemberg78575dc2000-06-12 19:36:41 +00003248#define DO_EVEN \
3249 args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 );
David Turnerd2b1f351999-12-16 23:11:37 +00003250
3251
3252#define DO_AND \
3253 args[0] = ( args[0] && args[1] );
3254
3255
3256#define DO_OR \
3257 args[0] = ( args[0] || args[1] );
3258
3259
3260#define DO_NOT \
3261 args[0] = !args[0];
3262
3263
3264#define DO_ADD \
3265 args[0] += args[1];
3266
3267
3268#define DO_SUB \
3269 args[0] -= args[1];
3270
3271
Werner Lemberg9f051a72003-11-25 18:15:56 +00003272#define DO_DIV \
3273 if ( args[1] == 0 ) \
3274 CUR.error = TT_Err_Divide_By_Zero; \
3275 else \
3276 args[0] = TT_MULDIV_NO_ROUND( args[0], 64L, args[1] );
David Turnerd2b1f351999-12-16 23:11:37 +00003277
3278
3279#define DO_MUL \
3280 args[0] = TT_MULDIV( args[0], args[1], 64L );
3281
3282
Werner Lembergdfa46192004-03-05 09:26:24 +00003283#define DO_ABS \
3284 args[0] = FT_ABS( args[0] );
David Turnerd2b1f351999-12-16 23:11:37 +00003285
3286
3287#define DO_NEG \
3288 args[0] = -args[0];
3289
3290
3291#define DO_FLOOR \
David Turner87c0d302003-12-24 01:10:46 +00003292 args[0] = FT_PIX_FLOOR( args[0] );
David Turnerd2b1f351999-12-16 23:11:37 +00003293
3294
3295#define DO_CEILING \
David Turner87c0d302003-12-24 01:10:46 +00003296 args[0] = FT_PIX_CEIL( args[0] );
David Turnerd2b1f351999-12-16 23:11:37 +00003297
3298
Werner Lemberg346f1862010-08-06 00:47:57 +02003299#define DO_RS \
3300 { \
3301 FT_ULong I = (FT_ULong)args[0]; \
3302 \
3303 \
3304 if ( BOUNDSL( I, CUR.storeSize ) ) \
3305 { \
3306 if ( CUR.pedantic_hinting ) \
3307 { \
3308 ARRAY_BOUND_ERROR; \
3309 } \
3310 else \
3311 args[0] = 0; \
3312 } \
3313 else \
3314 args[0] = CUR.storage[I]; \
David Turnerd2b1f351999-12-16 23:11:37 +00003315 }
3316
3317
Werner Lemberg346f1862010-08-06 00:47:57 +02003318#define DO_WS \
3319 { \
3320 FT_ULong I = (FT_ULong)args[0]; \
3321 \
3322 \
3323 if ( BOUNDSL( I, CUR.storeSize ) ) \
3324 { \
3325 if ( CUR.pedantic_hinting ) \
3326 { \
3327 ARRAY_BOUND_ERROR; \
3328 } \
3329 } \
3330 else \
3331 CUR.storage[I] = args[1]; \
David Turnerd2b1f351999-12-16 23:11:37 +00003332 }
3333
3334
Werner Lemberg78575dc2000-06-12 19:36:41 +00003335#define DO_RCVT \
3336 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00003337 FT_ULong I = (FT_ULong)args[0]; \
Werner Lemberg78575dc2000-06-12 19:36:41 +00003338 \
3339 \
Werner Lemberg346f1862010-08-06 00:47:57 +02003340 if ( BOUNDSL( I, CUR.cvtSize ) ) \
Werner Lemberg78575dc2000-06-12 19:36:41 +00003341 { \
3342 if ( CUR.pedantic_hinting ) \
3343 { \
3344 ARRAY_BOUND_ERROR; \
3345 } \
3346 else \
3347 args[0] = 0; \
3348 } \
3349 else \
3350 args[0] = CUR_Func_read_cvt( I ); \
David Turnerd2b1f351999-12-16 23:11:37 +00003351 }
3352
3353
3354#define DO_WCVTP \
3355 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00003356 FT_ULong I = (FT_ULong)args[0]; \
David Turnerd2b1f351999-12-16 23:11:37 +00003357 \
3358 \
Werner Lemberg346f1862010-08-06 00:47:57 +02003359 if ( BOUNDSL( I, CUR.cvtSize ) ) \
David Turnerd2b1f351999-12-16 23:11:37 +00003360 { \
3361 if ( CUR.pedantic_hinting ) \
3362 { \
3363 ARRAY_BOUND_ERROR; \
3364 } \
3365 } \
3366 else \
3367 CUR_Func_write_cvt( I, args[1] ); \
3368 }
3369
3370
3371#define DO_WCVTF \
3372 { \
David Turnerf9b8dec2000-06-16 19:34:52 +00003373 FT_ULong I = (FT_ULong)args[0]; \
David Turnerd2b1f351999-12-16 23:11:37 +00003374 \
3375 \
Werner Lemberg346f1862010-08-06 00:47:57 +02003376 if ( BOUNDSL( I, CUR.cvtSize ) ) \
David Turnerd2b1f351999-12-16 23:11:37 +00003377 { \
3378 if ( CUR.pedantic_hinting ) \
3379 { \
3380 ARRAY_BOUND_ERROR; \
3381 } \
3382 } \
3383 else \
3384 CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \
3385 }
3386
3387
3388#define DO_DEBUG \
3389 CUR.error = TT_Err_Debug_OpCode;
3390
3391
3392#define DO_ROUND \
3393 args[0] = CUR_Func_round( \
3394 args[0], \
3395 CUR.tt_metrics.compensations[CUR.opcode - 0x68] );
3396
3397
3398#define DO_NROUND \
3399 args[0] = ROUND_None( args[0], \
3400 CUR.tt_metrics.compensations[CUR.opcode - 0x6C] );
3401
3402
3403#define DO_MAX \
3404 if ( args[1] > args[0] ) \
3405 args[0] = args[1];
3406
3407
3408#define DO_MIN \
3409 if ( args[1] < args[0] ) \
3410 args[0] = args[1];
3411
3412
3413#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
3414
3415
3416#undef ARRAY_BOUND_ERROR
Werner Lemberg78575dc2000-06-12 19:36:41 +00003417#define ARRAY_BOUND_ERROR \
3418 { \
3419 CUR.error = TT_Err_Invalid_Reference; \
3420 return; \
3421 }
David Turnerd2b1f351999-12-16 23:11:37 +00003422
3423
3424 /*************************************************************************/
3425 /* */
3426 /* SVTCA[a]: Set (F and P) Vectors to Coordinate Axis */
3427 /* Opcode range: 0x00-0x01 */
3428 /* Stack: --> */
3429 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003430 static void
3431 Ins_SVTCA( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003432 {
3433 DO_SVTCA
3434 }
3435
3436
3437 /*************************************************************************/
3438 /* */
3439 /* SPVTCA[a]: Set PVector to Coordinate Axis */
3440 /* Opcode range: 0x02-0x03 */
3441 /* Stack: --> */
3442 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003443 static void
3444 Ins_SPVTCA( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003445 {
3446 DO_SPVTCA
3447 }
3448
3449
3450 /*************************************************************************/
3451 /* */
3452 /* SFVTCA[a]: Set FVector to Coordinate Axis */
3453 /* Opcode range: 0x04-0x05 */
3454 /* Stack: --> */
3455 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003456 static void
3457 Ins_SFVTCA( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003458 {
3459 DO_SFVTCA
3460 }
3461
3462
3463 /*************************************************************************/
3464 /* */
3465 /* SPVTL[a]: Set PVector To Line */
3466 /* Opcode range: 0x06-0x07 */
3467 /* Stack: uint32 uint32 --> */
3468 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003469 static void
3470 Ins_SPVTL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003471 {
3472 DO_SPVTL
3473 }
3474
3475
3476 /*************************************************************************/
3477 /* */
3478 /* SFVTL[a]: Set FVector To Line */
3479 /* Opcode range: 0x08-0x09 */
3480 /* Stack: uint32 uint32 --> */
3481 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003482 static void
3483 Ins_SFVTL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003484 {
3485 DO_SFVTL
3486 }
3487
3488
3489 /*************************************************************************/
3490 /* */
3491 /* SFVTPV[]: Set FVector To PVector */
3492 /* Opcode range: 0x0E */
3493 /* Stack: --> */
3494 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003495 static void
3496 Ins_SFVTPV( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003497 {
3498 DO_SFVTPV
3499 }
3500
3501
3502 /*************************************************************************/
3503 /* */
3504 /* SPVFS[]: Set PVector From Stack */
3505 /* Opcode range: 0x0A */
3506 /* Stack: f2.14 f2.14 --> */
3507 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003508 static void
3509 Ins_SPVFS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003510 {
3511 DO_SPVFS
3512 }
3513
3514
3515 /*************************************************************************/
3516 /* */
3517 /* SFVFS[]: Set FVector From Stack */
3518 /* Opcode range: 0x0B */
3519 /* Stack: f2.14 f2.14 --> */
3520 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003521 static void
3522 Ins_SFVFS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003523 {
3524 DO_SFVFS
3525 }
3526
3527
3528 /*************************************************************************/
3529 /* */
3530 /* GPV[]: Get Projection Vector */
3531 /* Opcode range: 0x0C */
3532 /* Stack: ef2.14 --> ef2.14 */
3533 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003534 static void
3535 Ins_GPV( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003536 {
3537 DO_GPV
3538 }
3539
3540
3541 /*************************************************************************/
3542 /* GFV[]: Get Freedom Vector */
3543 /* Opcode range: 0x0D */
3544 /* Stack: ef2.14 --> ef2.14 */
3545 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003546 static void
3547 Ins_GFV( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003548 {
3549 DO_GFV
3550 }
3551
3552
3553 /*************************************************************************/
3554 /* */
3555 /* SRP0[]: Set Reference Point 0 */
3556 /* Opcode range: 0x10 */
3557 /* Stack: uint32 --> */
3558 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003559 static void
3560 Ins_SRP0( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003561 {
3562 DO_SRP0
3563 }
3564
3565
3566 /*************************************************************************/
3567 /* */
3568 /* SRP1[]: Set Reference Point 1 */
3569 /* Opcode range: 0x11 */
3570 /* Stack: uint32 --> */
3571 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003572 static void
3573 Ins_SRP1( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003574 {
3575 DO_SRP1
3576 }
3577
3578
3579 /*************************************************************************/
3580 /* */
3581 /* SRP2[]: Set Reference Point 2 */
3582 /* Opcode range: 0x12 */
3583 /* Stack: uint32 --> */
3584 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003585 static void
3586 Ins_SRP2( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003587 {
3588 DO_SRP2
3589 }
3590
3591
3592 /*************************************************************************/
3593 /* */
3594 /* RTHG[]: Round To Half Grid */
3595 /* Opcode range: 0x19 */
3596 /* Stack: --> */
3597 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003598 static void
3599 Ins_RTHG( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003600 {
3601 DO_RTHG
3602 }
3603
3604
3605 /*************************************************************************/
3606 /* */
3607 /* RTG[]: Round To Grid */
3608 /* Opcode range: 0x18 */
3609 /* Stack: --> */
3610 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003611 static void
3612 Ins_RTG( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003613 {
3614 DO_RTG
3615 }
3616
3617
3618 /*************************************************************************/
3619 /* RTDG[]: Round To Double Grid */
3620 /* Opcode range: 0x3D */
3621 /* Stack: --> */
3622 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003623 static void
3624 Ins_RTDG( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003625 {
3626 DO_RTDG
3627 }
3628
3629
3630 /*************************************************************************/
3631 /* RUTG[]: Round Up To Grid */
3632 /* Opcode range: 0x7C */
3633 /* Stack: --> */
3634 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003635 static void
3636 Ins_RUTG( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003637 {
3638 DO_RUTG
3639 }
3640
3641
3642 /*************************************************************************/
3643 /* */
3644 /* RDTG[]: Round Down To Grid */
3645 /* Opcode range: 0x7D */
3646 /* Stack: --> */
3647 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003648 static void
3649 Ins_RDTG( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003650 {
3651 DO_RDTG
3652 }
3653
3654
3655 /*************************************************************************/
3656 /* */
3657 /* ROFF[]: Round OFF */
3658 /* Opcode range: 0x7A */
3659 /* Stack: --> */
3660 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003661 static void
3662 Ins_ROFF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003663 {
3664 DO_ROFF
3665 }
3666
3667
3668 /*************************************************************************/
3669 /* */
3670 /* SROUND[]: Super ROUND */
3671 /* Opcode range: 0x76 */
3672 /* Stack: Eint8 --> */
3673 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003674 static void
3675 Ins_SROUND( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003676 {
3677 DO_SROUND
3678 }
3679
3680
3681 /*************************************************************************/
3682 /* */
3683 /* S45ROUND[]: Super ROUND 45 degrees */
3684 /* Opcode range: 0x77 */
3685 /* Stack: uint32 --> */
3686 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003687 static void
3688 Ins_S45ROUND( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003689 {
3690 DO_S45ROUND
3691 }
3692
3693
3694 /*************************************************************************/
3695 /* */
3696 /* SLOOP[]: Set LOOP variable */
3697 /* Opcode range: 0x17 */
3698 /* Stack: int32? --> */
3699 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003700 static void
3701 Ins_SLOOP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003702 {
3703 DO_SLOOP
3704 }
3705
3706
3707 /*************************************************************************/
3708 /* */
3709 /* SMD[]: Set Minimum Distance */
3710 /* Opcode range: 0x1A */
3711 /* Stack: f26.6 --> */
3712 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003713 static void
3714 Ins_SMD( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003715 {
3716 DO_SMD
3717 }
3718
3719
3720 /*************************************************************************/
3721 /* */
3722 /* SCVTCI[]: Set Control Value Table Cut In */
3723 /* Opcode range: 0x1D */
3724 /* Stack: f26.6 --> */
3725 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003726 static void
3727 Ins_SCVTCI( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003728 {
3729 DO_SCVTCI
3730 }
3731
3732
3733 /*************************************************************************/
3734 /* */
3735 /* SSWCI[]: Set Single Width Cut In */
3736 /* Opcode range: 0x1E */
3737 /* Stack: f26.6 --> */
3738 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003739 static void
3740 Ins_SSWCI( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003741 {
3742 DO_SSWCI
3743 }
3744
3745
3746 /*************************************************************************/
3747 /* */
3748 /* SSW[]: Set Single Width */
3749 /* Opcode range: 0x1F */
3750 /* Stack: int32? --> */
3751 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003752 static void
3753 Ins_SSW( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003754 {
3755 DO_SSW
3756 }
3757
3758
3759 /*************************************************************************/
3760 /* */
3761 /* FLIPON[]: Set auto-FLIP to ON */
3762 /* Opcode range: 0x4D */
3763 /* Stack: --> */
3764 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003765 static void
3766 Ins_FLIPON( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003767 {
3768 DO_FLIPON
3769 }
3770
3771
3772 /*************************************************************************/
3773 /* */
3774 /* FLIPOFF[]: Set auto-FLIP to OFF */
3775 /* Opcode range: 0x4E */
3776 /* Stack: --> */
3777 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003778 static void
3779 Ins_FLIPOFF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003780 {
3781 DO_FLIPOFF
3782 }
3783
3784
3785 /*************************************************************************/
3786 /* */
3787 /* SANGW[]: Set ANGle Weight */
3788 /* Opcode range: 0x7E */
3789 /* Stack: uint32 --> */
3790 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003791 static void
3792 Ins_SANGW( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003793 {
3794 /* instruction not supported anymore */
3795 }
3796
3797
3798 /*************************************************************************/
3799 /* */
3800 /* SDB[]: Set Delta Base */
3801 /* Opcode range: 0x5E */
3802 /* Stack: uint32 --> */
3803 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003804 static void
3805 Ins_SDB( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003806 {
3807 DO_SDB
3808 }
3809
3810
3811 /*************************************************************************/
3812 /* */
3813 /* SDS[]: Set Delta Shift */
3814 /* Opcode range: 0x5F */
3815 /* Stack: uint32 --> */
3816 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003817 static void
3818 Ins_SDS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003819 {
3820 DO_SDS
3821 }
3822
3823
3824 /*************************************************************************/
3825 /* */
3826 /* MPPEM[]: Measure Pixel Per EM */
3827 /* Opcode range: 0x4B */
3828 /* Stack: --> Euint16 */
3829 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003830 static void
3831 Ins_MPPEM( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003832 {
3833 DO_MPPEM
3834 }
3835
3836
3837 /*************************************************************************/
3838 /* */
3839 /* MPS[]: Measure Point Size */
3840 /* Opcode range: 0x4C */
3841 /* Stack: --> Euint16 */
3842 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003843 static void
3844 Ins_MPS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003845 {
3846 DO_MPS
3847 }
3848
3849
3850 /*************************************************************************/
3851 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00003852 /* DUP[]: DUPlicate the top stack's element */
David Turnerd2b1f351999-12-16 23:11:37 +00003853 /* Opcode range: 0x20 */
3854 /* Stack: StkElt --> StkElt StkElt */
3855 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003856 static void
3857 Ins_DUP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003858 {
3859 DO_DUP
3860 }
3861
3862
3863 /*************************************************************************/
3864 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00003865 /* POP[]: POP the stack's top element */
David Turnerd2b1f351999-12-16 23:11:37 +00003866 /* Opcode range: 0x21 */
3867 /* Stack: StkElt --> */
3868 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003869 static void
3870 Ins_POP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003871 {
3872 /* nothing to do */
3873 }
3874
3875
3876 /*************************************************************************/
3877 /* */
3878 /* CLEAR[]: CLEAR the entire stack */
3879 /* Opcode range: 0x22 */
3880 /* Stack: StkElt... --> */
3881 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003882 static void
3883 Ins_CLEAR( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003884 {
3885 DO_CLEAR
3886 }
3887
3888
3889 /*************************************************************************/
3890 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00003891 /* SWAP[]: SWAP the stack's top two elements */
David Turnerd2b1f351999-12-16 23:11:37 +00003892 /* Opcode range: 0x23 */
3893 /* Stack: 2 * StkElt --> 2 * StkElt */
3894 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003895 static void
3896 Ins_SWAP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003897 {
3898 DO_SWAP
3899 }
3900
3901
3902 /*************************************************************************/
3903 /* */
3904 /* DEPTH[]: return the stack DEPTH */
3905 /* Opcode range: 0x24 */
3906 /* Stack: --> uint32 */
3907 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003908 static void
3909 Ins_DEPTH( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003910 {
3911 DO_DEPTH
3912 }
3913
3914
3915 /*************************************************************************/
3916 /* */
3917 /* CINDEX[]: Copy INDEXed element */
3918 /* Opcode range: 0x25 */
3919 /* Stack: int32 --> StkElt */
3920 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003921 static void
3922 Ins_CINDEX( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003923 {
3924 DO_CINDEX
3925 }
3926
3927
3928 /*************************************************************************/
3929 /* */
3930 /* EIF[]: End IF */
3931 /* Opcode range: 0x59 */
3932 /* Stack: --> */
3933 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003934 static void
3935 Ins_EIF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003936 {
3937 /* nothing to do */
3938 }
3939
3940
3941 /*************************************************************************/
3942 /* */
3943 /* JROT[]: Jump Relative On True */
3944 /* Opcode range: 0x78 */
3945 /* Stack: StkElt int32 --> */
3946 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003947 static void
3948 Ins_JROT( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003949 {
3950 DO_JROT
3951 }
3952
3953
3954 /*************************************************************************/
3955 /* */
3956 /* JMPR[]: JuMP Relative */
3957 /* Opcode range: 0x1C */
3958 /* Stack: int32 --> */
3959 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003960 static void
3961 Ins_JMPR( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003962 {
3963 DO_JMPR
3964 }
3965
3966
3967 /*************************************************************************/
3968 /* */
3969 /* JROF[]: Jump Relative On False */
3970 /* Opcode range: 0x79 */
3971 /* Stack: StkElt int32 --> */
3972 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003973 static void
3974 Ins_JROF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003975 {
3976 DO_JROF
3977 }
3978
3979
3980 /*************************************************************************/
3981 /* */
3982 /* LT[]: Less Than */
3983 /* Opcode range: 0x50 */
3984 /* Stack: int32? int32? --> bool */
3985 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003986 static void
3987 Ins_LT( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00003988 {
3989 DO_LT
3990 }
3991
3992
3993 /*************************************************************************/
3994 /* */
3995 /* LTEQ[]: Less Than or EQual */
3996 /* Opcode range: 0x51 */
3997 /* Stack: int32? int32? --> bool */
3998 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00003999 static void
4000 Ins_LTEQ( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004001 {
4002 DO_LTEQ
4003 }
4004
4005
4006 /*************************************************************************/
4007 /* */
4008 /* GT[]: Greater Than */
4009 /* Opcode range: 0x52 */
4010 /* Stack: int32? int32? --> bool */
4011 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004012 static void
4013 Ins_GT( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004014 {
4015 DO_GT
4016 }
4017
4018
4019 /*************************************************************************/
4020 /* */
4021 /* GTEQ[]: Greater Than or EQual */
4022 /* Opcode range: 0x53 */
4023 /* Stack: int32? int32? --> bool */
4024 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004025 static void
4026 Ins_GTEQ( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004027 {
4028 DO_GTEQ
4029 }
4030
4031
4032 /*************************************************************************/
4033 /* */
4034 /* EQ[]: EQual */
4035 /* Opcode range: 0x54 */
4036 /* Stack: StkElt StkElt --> bool */
4037 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004038 static void
4039 Ins_EQ( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004040 {
4041 DO_EQ
4042 }
4043
4044
4045 /*************************************************************************/
4046 /* */
4047 /* NEQ[]: Not EQual */
4048 /* Opcode range: 0x55 */
4049 /* Stack: StkElt StkElt --> bool */
4050 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004051 static void
4052 Ins_NEQ( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004053 {
4054 DO_NEQ
4055 }
4056
4057
4058 /*************************************************************************/
4059 /* */
4060 /* ODD[]: Is ODD */
4061 /* Opcode range: 0x56 */
4062 /* Stack: f26.6 --> bool */
4063 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004064 static void
4065 Ins_ODD( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004066 {
4067 DO_ODD
4068 }
4069
4070
4071 /*************************************************************************/
4072 /* */
4073 /* EVEN[]: Is EVEN */
4074 /* Opcode range: 0x57 */
4075 /* Stack: f26.6 --> bool */
4076 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004077 static void
4078 Ins_EVEN( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004079 {
4080 DO_EVEN
4081 }
4082
4083
4084 /*************************************************************************/
4085 /* */
4086 /* AND[]: logical AND */
4087 /* Opcode range: 0x5A */
4088 /* Stack: uint32 uint32 --> uint32 */
4089 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004090 static void
4091 Ins_AND( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004092 {
4093 DO_AND
4094 }
4095
4096
4097 /*************************************************************************/
4098 /* */
4099 /* OR[]: logical OR */
4100 /* Opcode range: 0x5B */
4101 /* Stack: uint32 uint32 --> uint32 */
4102 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004103 static void
4104 Ins_OR( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004105 {
4106 DO_OR
4107 }
4108
4109
4110 /*************************************************************************/
4111 /* */
4112 /* NOT[]: logical NOT */
4113 /* Opcode range: 0x5C */
4114 /* Stack: StkElt --> uint32 */
4115 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004116 static void
4117 Ins_NOT( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004118 {
4119 DO_NOT
4120 }
4121
4122
4123 /*************************************************************************/
4124 /* */
4125 /* ADD[]: ADD */
4126 /* Opcode range: 0x60 */
4127 /* Stack: f26.6 f26.6 --> f26.6 */
4128 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004129 static void
4130 Ins_ADD( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004131 {
4132 DO_ADD
4133 }
4134
4135
4136 /*************************************************************************/
4137 /* */
4138 /* SUB[]: SUBtract */
4139 /* Opcode range: 0x61 */
4140 /* Stack: f26.6 f26.6 --> f26.6 */
4141 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004142 static void
4143 Ins_SUB( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004144 {
4145 DO_SUB
4146 }
4147
4148
4149 /*************************************************************************/
4150 /* */
4151 /* DIV[]: DIVide */
4152 /* Opcode range: 0x62 */
4153 /* Stack: f26.6 f26.6 --> f26.6 */
4154 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004155 static void
4156 Ins_DIV( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004157 {
4158 DO_DIV
4159 }
4160
4161
4162 /*************************************************************************/
4163 /* */
4164 /* MUL[]: MULtiply */
4165 /* Opcode range: 0x63 */
4166 /* Stack: f26.6 f26.6 --> f26.6 */
4167 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004168 static void
4169 Ins_MUL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004170 {
4171 DO_MUL
4172 }
4173
4174
4175 /*************************************************************************/
4176 /* */
4177 /* ABS[]: ABSolute value */
4178 /* Opcode range: 0x64 */
4179 /* Stack: f26.6 --> f26.6 */
4180 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004181 static void
4182 Ins_ABS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004183 {
4184 DO_ABS
4185 }
4186
4187
4188 /*************************************************************************/
4189 /* */
4190 /* NEG[]: NEGate */
4191 /* Opcode range: 0x65 */
4192 /* Stack: f26.6 --> f26.6 */
4193 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004194 static void
4195 Ins_NEG( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004196 {
4197 DO_NEG
4198 }
4199
4200
4201 /*************************************************************************/
4202 /* */
4203 /* FLOOR[]: FLOOR */
4204 /* Opcode range: 0x66 */
4205 /* Stack: f26.6 --> f26.6 */
4206 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004207 static void
4208 Ins_FLOOR( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004209 {
4210 DO_FLOOR
4211 }
4212
4213
4214 /*************************************************************************/
4215 /* */
4216 /* CEILING[]: CEILING */
4217 /* Opcode range: 0x67 */
4218 /* Stack: f26.6 --> f26.6 */
4219 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004220 static void
4221 Ins_CEILING( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004222 {
4223 DO_CEILING
4224 }
4225
4226
4227 /*************************************************************************/
4228 /* */
4229 /* RS[]: Read Store */
4230 /* Opcode range: 0x43 */
4231 /* Stack: uint32 --> uint32 */
4232 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004233 static void
4234 Ins_RS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004235 {
4236 DO_RS
4237 }
4238
4239
4240 /*************************************************************************/
4241 /* */
4242 /* WS[]: Write Store */
4243 /* Opcode range: 0x42 */
4244 /* Stack: uint32 uint32 --> */
4245 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004246 static void
4247 Ins_WS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004248 {
4249 DO_WS
4250 }
4251
4252
4253 /*************************************************************************/
4254 /* */
4255 /* WCVTP[]: Write CVT in Pixel units */
4256 /* Opcode range: 0x44 */
4257 /* Stack: f26.6 uint32 --> */
4258 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004259 static void
4260 Ins_WCVTP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004261 {
4262 DO_WCVTP
4263 }
4264
4265
4266 /*************************************************************************/
4267 /* */
4268 /* WCVTF[]: Write CVT in Funits */
4269 /* Opcode range: 0x70 */
4270 /* Stack: uint32 uint32 --> */
4271 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004272 static void
4273 Ins_WCVTF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004274 {
4275 DO_WCVTF
4276 }
4277
4278
4279 /*************************************************************************/
4280 /* */
4281 /* RCVT[]: Read CVT */
4282 /* Opcode range: 0x45 */
4283 /* Stack: uint32 --> f26.6 */
4284 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004285 static void
4286 Ins_RCVT( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004287 {
4288 DO_RCVT
4289 }
4290
4291
4292 /*************************************************************************/
4293 /* */
4294 /* AA[]: Adjust Angle */
4295 /* Opcode range: 0x7F */
4296 /* Stack: uint32 --> */
4297 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004298 static void
4299 Ins_AA( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004300 {
Werner Lemberg5811c7c2000-07-02 13:53:16 +00004301 /* intentionally no longer supported */
David Turnerd2b1f351999-12-16 23:11:37 +00004302 }
4303
4304
4305 /*************************************************************************/
4306 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004307 /* DEBUG[]: DEBUG. Unsupported. */
David Turnerd2b1f351999-12-16 23:11:37 +00004308 /* Opcode range: 0x4F */
4309 /* Stack: uint32 --> */
4310 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004311 /* Note: The original instruction pops a value from the stack. */
David Turnerd2b1f351999-12-16 23:11:37 +00004312 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004313 static void
4314 Ins_DEBUG( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004315 {
4316 DO_DEBUG
4317 }
4318
4319
4320 /*************************************************************************/
4321 /* */
4322 /* ROUND[ab]: ROUND value */
4323 /* Opcode range: 0x68-0x6B */
4324 /* Stack: f26.6 --> f26.6 */
4325 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004326 static void
4327 Ins_ROUND( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004328 {
4329 DO_ROUND
4330 }
4331
4332
4333 /*************************************************************************/
4334 /* */
4335 /* NROUND[ab]: No ROUNDing of value */
4336 /* Opcode range: 0x6C-0x6F */
4337 /* Stack: f26.6 --> f26.6 */
4338 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004339 static void
4340 Ins_NROUND( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004341 {
4342 DO_NROUND
4343 }
4344
4345
4346 /*************************************************************************/
4347 /* */
4348 /* MAX[]: MAXimum */
4349 /* Opcode range: 0x68 */
4350 /* Stack: int32? int32? --> int32 */
4351 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004352 static void
4353 Ins_MAX( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004354 {
4355 DO_MAX
4356 }
4357
4358
4359 /*************************************************************************/
4360 /* */
4361 /* MIN[]: MINimum */
4362 /* Opcode range: 0x69 */
4363 /* Stack: int32? int32? --> int32 */
4364 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004365 static void
4366 Ins_MIN( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004367 {
4368 DO_MIN
4369 }
4370
4371
4372#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
4373
4374
4375 /*************************************************************************/
4376 /* */
4377 /* The following functions are called as is within the switch statement. */
4378 /* */
4379 /*************************************************************************/
4380
4381
4382 /*************************************************************************/
4383 /* */
4384 /* MINDEX[]: Move INDEXed element */
4385 /* Opcode range: 0x26 */
4386 /* Stack: int32? --> StkElt */
4387 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004388 static void
4389 Ins_MINDEX( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004390 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004391 FT_Long L, K;
David Turnerd2b1f351999-12-16 23:11:37 +00004392
4393
4394 L = args[0];
4395
4396 if ( L <= 0 || L > CUR.args )
4397 {
Werner Lembergd6a213f2011-01-31 18:51:07 +01004398 if ( CUR.pedantic_hinting )
4399 CUR.error = TT_Err_Invalid_Reference;
David Turnerd2b1f351999-12-16 23:11:37 +00004400 }
Werner Lembergd6a213f2011-01-31 18:51:07 +01004401 else
4402 {
4403 K = CUR.stack[CUR.args - L];
David Turnerd2b1f351999-12-16 23:11:37 +00004404
Werner Lembergd6a213f2011-01-31 18:51:07 +01004405 FT_ARRAY_MOVE( &CUR.stack[CUR.args - L ],
4406 &CUR.stack[CUR.args - L + 1],
4407 ( L - 1 ) );
David Turnerd2b1f351999-12-16 23:11:37 +00004408
Werner Lembergd6a213f2011-01-31 18:51:07 +01004409 CUR.stack[CUR.args - 1] = K;
4410 }
David Turnerd2b1f351999-12-16 23:11:37 +00004411 }
4412
4413
4414 /*************************************************************************/
4415 /* */
4416 /* ROLL[]: ROLL top three elements */
4417 /* Opcode range: 0x8A */
4418 /* Stack: 3 * StkElt --> 3 * StkElt */
4419 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004420 static void
4421 Ins_ROLL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004422 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004423 FT_Long A, B, C;
David Turnerd2b1f351999-12-16 23:11:37 +00004424
David Turnerc6a92202000-07-04 18:12:13 +00004425 FT_UNUSED_EXEC;
David Turnerd2b1f351999-12-16 23:11:37 +00004426
Werner Lemberg78575dc2000-06-12 19:36:41 +00004427
David Turnerd2b1f351999-12-16 23:11:37 +00004428 A = args[2];
4429 B = args[1];
4430 C = args[0];
4431
4432 args[2] = C;
4433 args[1] = A;
4434 args[0] = B;
4435 }
4436
4437
4438 /*************************************************************************/
4439 /* */
4440 /* MANAGING THE FLOW OF CONTROL */
4441 /* */
Werner Lemberg5811c7c2000-07-02 13:53:16 +00004442 /* Instructions appear in the specification's order. */
David Turnerd2b1f351999-12-16 23:11:37 +00004443 /* */
4444 /*************************************************************************/
4445
4446
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004447 static FT_Bool
4448 SkipCode( EXEC_OP )
David Turnerd2b1f351999-12-16 23:11:37 +00004449 {
4450 CUR.IP += CUR.length;
4451
4452 if ( CUR.IP < CUR.codeSize )
4453 {
4454 CUR.opcode = CUR.code[CUR.IP];
4455
4456 CUR.length = opcode_length[CUR.opcode];
4457 if ( CUR.length < 0 )
4458 {
4459 if ( CUR.IP + 1 > CUR.codeSize )
4460 goto Fail_Overflow;
Werner Lemberg33febc02004-10-09 07:07:43 +00004461 CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
David Turnerd2b1f351999-12-16 23:11:37 +00004462 }
4463
4464 if ( CUR.IP + CUR.length <= CUR.codeSize )
4465 return SUCCESS;
4466 }
4467
4468 Fail_Overflow:
4469 CUR.error = TT_Err_Code_Overflow;
4470 return FAILURE;
4471 }
4472
4473
4474 /*************************************************************************/
4475 /* */
4476 /* IF[]: IF test */
4477 /* Opcode range: 0x58 */
4478 /* Stack: StkElt --> */
4479 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004480 static void
4481 Ins_IF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004482 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004483 FT_Int nIfs;
4484 FT_Bool Out;
David Turnerd2b1f351999-12-16 23:11:37 +00004485
4486
4487 if ( args[0] != 0 )
4488 return;
4489
4490 nIfs = 1;
4491 Out = 0;
4492
4493 do
4494 {
4495 if ( SKIP_Code() == FAILURE )
4496 return;
4497
4498 switch ( CUR.opcode )
4499 {
4500 case 0x58: /* IF */
4501 nIfs++;
4502 break;
4503
4504 case 0x1B: /* ELSE */
David Turner3b7049f2001-07-07 16:12:14 +00004505 Out = FT_BOOL( nIfs == 1 );
David Turnerd2b1f351999-12-16 23:11:37 +00004506 break;
4507
4508 case 0x59: /* EIF */
4509 nIfs--;
David Turner3b7049f2001-07-07 16:12:14 +00004510 Out = FT_BOOL( nIfs == 0 );
David Turnerd2b1f351999-12-16 23:11:37 +00004511 break;
4512 }
4513 } while ( Out == 0 );
4514 }
4515
4516
4517 /*************************************************************************/
4518 /* */
4519 /* ELSE[]: ELSE */
4520 /* Opcode range: 0x1B */
4521 /* Stack: --> */
4522 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004523 static void
4524 Ins_ELSE( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004525 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004526 FT_Int nIfs;
David Turnerd2b1f351999-12-16 23:11:37 +00004527
David Turnerc6a92202000-07-04 18:12:13 +00004528 FT_UNUSED_ARG;
David Turnerd2b1f351999-12-16 23:11:37 +00004529
Werner Lemberg78575dc2000-06-12 19:36:41 +00004530
David Turnerd2b1f351999-12-16 23:11:37 +00004531 nIfs = 1;
4532
4533 do
4534 {
4535 if ( SKIP_Code() == FAILURE )
4536 return;
4537
4538 switch ( CUR.opcode )
4539 {
4540 case 0x58: /* IF */
4541 nIfs++;
4542 break;
4543
4544 case 0x59: /* EIF */
4545 nIfs--;
4546 break;
4547 }
4548 } while ( nIfs != 0 );
4549 }
4550
4551
4552 /*************************************************************************/
4553 /* */
4554 /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS */
4555 /* */
Werner Lemberg5811c7c2000-07-02 13:53:16 +00004556 /* Instructions appear in the specification's order. */
David Turnerd2b1f351999-12-16 23:11:37 +00004557 /* */
4558 /*************************************************************************/
4559
4560
4561 /*************************************************************************/
4562 /* */
4563 /* FDEF[]: Function DEFinition */
4564 /* Opcode range: 0x2C */
4565 /* Stack: uint32 --> */
4566 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004567 static void
4568 Ins_FDEF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004569 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004570 FT_ULong n;
David Turnerd2b1f351999-12-16 23:11:37 +00004571 TT_DefRecord* rec;
4572 TT_DefRecord* limit;
4573
Werner Lemberg78575dc2000-06-12 19:36:41 +00004574
David Turnerd2b1f351999-12-16 23:11:37 +00004575 /* some font programs are broken enough to redefine functions! */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004576 /* We will then parse the current table. */
4577
David Turnerd2b1f351999-12-16 23:11:37 +00004578 rec = CUR.FDefs;
4579 limit = rec + CUR.numFDefs;
4580 n = args[0];
David Turnere49ab252000-05-16 23:44:38 +00004581
David Turnerd2b1f351999-12-16 23:11:37 +00004582 for ( ; rec < limit; rec++ )
4583 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00004584 if ( rec->opc == n )
David Turnerd2b1f351999-12-16 23:11:37 +00004585 break;
4586 }
David Turnere49ab252000-05-16 23:44:38 +00004587
David Turnerd2b1f351999-12-16 23:11:37 +00004588 if ( rec == limit )
4589 {
4590 /* check that there is enough room for new functions */
4591 if ( CUR.numFDefs >= CUR.maxFDefs )
4592 {
4593 CUR.error = TT_Err_Too_Many_Function_Defs;
4594 return;
4595 }
4596 CUR.numFDefs++;
4597 }
David Turnere49ab252000-05-16 23:44:38 +00004598
suzuki toshiyad1c23082009-08-01 00:32:17 +09004599 /* Although FDEF takes unsigned 32-bit integer, */
4600 /* func # must be within unsigned 16-bit integer */
4601 if ( n > 0xFFFFU )
4602 {
4603 CUR.error = TT_Err_Too_Many_Function_Defs;
4604 return;
4605 }
4606
David Turnerd2b1f351999-12-16 23:11:37 +00004607 rec->range = CUR.curRange;
suzuki toshiyad1c23082009-08-01 00:32:17 +09004608 rec->opc = (FT_UInt16)n;
Werner Lemberg78575dc2000-06-12 19:36:41 +00004609 rec->start = CUR.IP + 1;
David Turnerd2b1f351999-12-16 23:11:37 +00004610 rec->active = TRUE;
David Turnere49ab252000-05-16 23:44:38 +00004611
David Turnerd2b1f351999-12-16 23:11:37 +00004612 if ( n > CUR.maxFunc )
suzuki toshiyad1c23082009-08-01 00:32:17 +09004613 CUR.maxFunc = (FT_UInt16)n;
David Turnere49ab252000-05-16 23:44:38 +00004614
David Turnerd2b1f351999-12-16 23:11:37 +00004615 /* Now skip the whole function definition. */
4616 /* We don't allow nested IDEFS & FDEFs. */
4617
4618 while ( SKIP_Code() == SUCCESS )
4619 {
4620 switch ( CUR.opcode )
4621 {
4622 case 0x89: /* IDEF */
4623 case 0x2C: /* FDEF */
4624 CUR.error = TT_Err_Nested_DEFS;
4625 return;
4626
4627 case 0x2D: /* ENDF */
4628 return;
4629 }
4630 }
4631 }
4632
4633
4634 /*************************************************************************/
4635 /* */
4636 /* ENDF[]: END Function definition */
4637 /* Opcode range: 0x2D */
4638 /* Stack: --> */
4639 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004640 static void
4641 Ins_ENDF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004642 {
4643 TT_CallRec* pRec;
4644
David Turnerc6a92202000-07-04 18:12:13 +00004645 FT_UNUSED_ARG;
David Turnerd2b1f351999-12-16 23:11:37 +00004646
Werner Lemberg78575dc2000-06-12 19:36:41 +00004647
David Turnerd2b1f351999-12-16 23:11:37 +00004648 if ( CUR.callTop <= 0 ) /* We encountered an ENDF without a call */
4649 {
4650 CUR.error = TT_Err_ENDF_In_Exec_Stream;
4651 return;
4652 }
4653
4654 CUR.callTop--;
4655
4656 pRec = &CUR.callStack[CUR.callTop];
4657
4658 pRec->Cur_Count--;
4659
4660 CUR.step_ins = FALSE;
4661
4662 if ( pRec->Cur_Count > 0 )
4663 {
4664 CUR.callTop++;
4665 CUR.IP = pRec->Cur_Restart;
4666 }
4667 else
4668 /* Loop through the current function */
4669 INS_Goto_CodeRange( pRec->Caller_Range,
4670 pRec->Caller_IP );
4671
Werner Lemberg78575dc2000-06-12 19:36:41 +00004672 /* Exit the current call frame. */
David Turnerd2b1f351999-12-16 23:11:37 +00004673
Werner Lemberg6e87ed92007-01-26 22:18:56 +00004674 /* NOTE: If the last instruction of a program is a */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004675 /* CALL or LOOPCALL, the return address is */
4676 /* always out of the code range. This is a */
4677 /* valid address, and it is why we do not test */
4678 /* the result of Ins_Goto_CodeRange() here! */
David Turnerd2b1f351999-12-16 23:11:37 +00004679 }
4680
4681
4682 /*************************************************************************/
4683 /* */
4684 /* CALL[]: CALL function */
4685 /* Opcode range: 0x2B */
4686 /* Stack: uint32? --> */
4687 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004688 static void
4689 Ins_CALL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004690 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004691 FT_ULong F;
David Turnerd2b1f351999-12-16 23:11:37 +00004692 TT_CallRec* pCrec;
4693 TT_DefRecord* def;
4694
Werner Lemberg78575dc2000-06-12 19:36:41 +00004695
David Turnerd2b1f351999-12-16 23:11:37 +00004696 /* first of all, check the index */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004697
David Turnerd2b1f351999-12-16 23:11:37 +00004698 F = args[0];
Werner Lemberg346f1862010-08-06 00:47:57 +02004699 if ( BOUNDSL( F, CUR.maxFunc + 1 ) )
Werner Lemberg78575dc2000-06-12 19:36:41 +00004700 goto Fail;
David Turnere49ab252000-05-16 23:44:38 +00004701
David Turnerd2b1f351999-12-16 23:11:37 +00004702 /* Except for some old Apple fonts, all functions in a TrueType */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004703 /* font are defined in increasing order, starting from 0. This */
David Turnerd2b1f351999-12-16 23:11:37 +00004704 /* means that we normally have */
4705 /* */
4706 /* CUR.maxFunc+1 == CUR.numFDefs */
4707 /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */
4708 /* */
4709 /* If this isn't true, we need to look up the function table. */
4710
4711 def = CUR.FDefs + F;
Werner Lemberg78575dc2000-06-12 19:36:41 +00004712 if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
David Turnerd2b1f351999-12-16 23:11:37 +00004713 {
4714 /* look up the FDefs table */
4715 TT_DefRecord* limit;
David Turnere49ab252000-05-16 23:44:38 +00004716
Werner Lemberg78575dc2000-06-12 19:36:41 +00004717
David Turnerd2b1f351999-12-16 23:11:37 +00004718 def = CUR.FDefs;
4719 limit = def + CUR.numFDefs;
David Turnere49ab252000-05-16 23:44:38 +00004720
Werner Lemberg78575dc2000-06-12 19:36:41 +00004721 while ( def < limit && def->opc != F )
David Turnerd2b1f351999-12-16 23:11:37 +00004722 def++;
David Turnere49ab252000-05-16 23:44:38 +00004723
Werner Lemberg78575dc2000-06-12 19:36:41 +00004724 if ( def == limit )
4725 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00004726 }
David Turnere49ab252000-05-16 23:44:38 +00004727
David Turnerd2b1f351999-12-16 23:11:37 +00004728 /* check that the function is active */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004729 if ( !def->active )
David Turnerd2b1f351999-12-16 23:11:37 +00004730 goto Fail;
David Turnere49ab252000-05-16 23:44:38 +00004731
David Turnerd2b1f351999-12-16 23:11:37 +00004732 /* check the call stack */
4733 if ( CUR.callTop >= CUR.callSize )
4734 {
4735 CUR.error = TT_Err_Stack_Overflow;
4736 return;
4737 }
4738
4739 pCrec = CUR.callStack + CUR.callTop;
4740
4741 pCrec->Caller_Range = CUR.curRange;
4742 pCrec->Caller_IP = CUR.IP + 1;
4743 pCrec->Cur_Count = 1;
4744 pCrec->Cur_Restart = def->start;
4745
4746 CUR.callTop++;
4747
4748 INS_Goto_CodeRange( def->range,
4749 def->start );
David Turnere49ab252000-05-16 23:44:38 +00004750
David Turnerd2b1f351999-12-16 23:11:37 +00004751 CUR.step_ins = FALSE;
4752 return;
David Turnere49ab252000-05-16 23:44:38 +00004753
David Turnerd2b1f351999-12-16 23:11:37 +00004754 Fail:
4755 CUR.error = TT_Err_Invalid_Reference;
4756 }
4757
4758
4759 /*************************************************************************/
4760 /* */
4761 /* LOOPCALL[]: LOOP and CALL function */
4762 /* Opcode range: 0x2A */
4763 /* Stack: uint32? Eint16? --> */
4764 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004765 static void
4766 Ins_LOOPCALL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004767 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004768 FT_ULong F;
David Turnerd2b1f351999-12-16 23:11:37 +00004769 TT_CallRec* pCrec;
4770 TT_DefRecord* def;
4771
Werner Lemberg78575dc2000-06-12 19:36:41 +00004772
David Turnerd2b1f351999-12-16 23:11:37 +00004773 /* first of all, check the index */
4774 F = args[1];
Werner Lemberg346f1862010-08-06 00:47:57 +02004775 if ( BOUNDSL( F, CUR.maxFunc + 1 ) )
Werner Lemberg78575dc2000-06-12 19:36:41 +00004776 goto Fail;
David Turnere49ab252000-05-16 23:44:38 +00004777
David Turnerd2b1f351999-12-16 23:11:37 +00004778 /* Except for some old Apple fonts, all functions in a TrueType */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004779 /* font are defined in increasing order, starting from 0. This */
David Turnerd2b1f351999-12-16 23:11:37 +00004780 /* means that we normally have */
4781 /* */
4782 /* CUR.maxFunc+1 == CUR.numFDefs */
4783 /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */
4784 /* */
4785 /* If this isn't true, we need to look up the function table. */
4786
4787 def = CUR.FDefs + F;
Werner Lemberg78575dc2000-06-12 19:36:41 +00004788 if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
David Turnerd2b1f351999-12-16 23:11:37 +00004789 {
4790 /* look up the FDefs table */
4791 TT_DefRecord* limit;
David Turnere49ab252000-05-16 23:44:38 +00004792
Werner Lemberg78575dc2000-06-12 19:36:41 +00004793
David Turnerd2b1f351999-12-16 23:11:37 +00004794 def = CUR.FDefs;
4795 limit = def + CUR.numFDefs;
David Turnere49ab252000-05-16 23:44:38 +00004796
Werner Lemberg78575dc2000-06-12 19:36:41 +00004797 while ( def < limit && def->opc != F )
David Turnerd2b1f351999-12-16 23:11:37 +00004798 def++;
David Turnere49ab252000-05-16 23:44:38 +00004799
Werner Lemberg78575dc2000-06-12 19:36:41 +00004800 if ( def == limit )
4801 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00004802 }
David Turnere49ab252000-05-16 23:44:38 +00004803
David Turnerd2b1f351999-12-16 23:11:37 +00004804 /* check that the function is active */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004805 if ( !def->active )
David Turnerd2b1f351999-12-16 23:11:37 +00004806 goto Fail;
4807
David Turnere49ab252000-05-16 23:44:38 +00004808 /* check stack */
David Turnerd2b1f351999-12-16 23:11:37 +00004809 if ( CUR.callTop >= CUR.callSize )
4810 {
4811 CUR.error = TT_Err_Stack_Overflow;
4812 return;
4813 }
4814
4815 if ( args[0] > 0 )
4816 {
4817 pCrec = CUR.callStack + CUR.callTop;
4818
4819 pCrec->Caller_Range = CUR.curRange;
4820 pCrec->Caller_IP = CUR.IP + 1;
David Turnerf9b8dec2000-06-16 19:34:52 +00004821 pCrec->Cur_Count = (FT_Int)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00004822 pCrec->Cur_Restart = def->start;
4823
4824 CUR.callTop++;
4825
4826 INS_Goto_CodeRange( def->range, def->start );
4827
4828 CUR.step_ins = FALSE;
4829 }
4830 return;
4831
4832 Fail:
4833 CUR.error = TT_Err_Invalid_Reference;
4834 }
4835
4836
4837 /*************************************************************************/
4838 /* */
4839 /* IDEF[]: Instruction DEFinition */
4840 /* Opcode range: 0x89 */
4841 /* Stack: Eint8 --> */
4842 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004843 static void
4844 Ins_IDEF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004845 {
4846 TT_DefRecord* def;
4847 TT_DefRecord* limit;
4848
Werner Lemberg78575dc2000-06-12 19:36:41 +00004849
David Turnerd2b1f351999-12-16 23:11:37 +00004850 /* First of all, look for the same function in our table */
Werner Lemberg78575dc2000-06-12 19:36:41 +00004851
David Turnerd2b1f351999-12-16 23:11:37 +00004852 def = CUR.IDefs;
4853 limit = def + CUR.numIDefs;
Werner Lemberg78575dc2000-06-12 19:36:41 +00004854
David Turnerd2b1f351999-12-16 23:11:37 +00004855 for ( ; def < limit; def++ )
David Turnerf9b8dec2000-06-16 19:34:52 +00004856 if ( def->opc == (FT_ULong)args[0] )
David Turnerd2b1f351999-12-16 23:11:37 +00004857 break;
David Turnere49ab252000-05-16 23:44:38 +00004858
David Turnerd2b1f351999-12-16 23:11:37 +00004859 if ( def == limit )
4860 {
4861 /* check that there is enough room for a new instruction */
4862 if ( CUR.numIDefs >= CUR.maxIDefs )
4863 {
4864 CUR.error = TT_Err_Too_Many_Instruction_Defs;
4865 return;
4866 }
4867 CUR.numIDefs++;
4868 }
David Turnere49ab252000-05-16 23:44:38 +00004869
suzuki toshiyaa1151422009-08-01 00:32:18 +09004870 /* opcode must be unsigned 8-bit integer */
4871 if ( 0 > args[0] || args[0] > 0x00FF )
4872 {
4873 CUR.error = TT_Err_Too_Many_Instruction_Defs;
4874 return;
4875 }
4876
4877 def->opc = (FT_Byte)args[0];
Werner Lemberg462ddb42010-07-01 11:28:43 +02004878 def->start = CUR.IP + 1;
David Turnerd2b1f351999-12-16 23:11:37 +00004879 def->range = CUR.curRange;
4880 def->active = TRUE;
David Turnere49ab252000-05-16 23:44:38 +00004881
David Turnerf9b8dec2000-06-16 19:34:52 +00004882 if ( (FT_ULong)args[0] > CUR.maxIns )
suzuki toshiyaa1151422009-08-01 00:32:18 +09004883 CUR.maxIns = (FT_Byte)args[0];
David Turnere49ab252000-05-16 23:44:38 +00004884
David Turnerd2b1f351999-12-16 23:11:37 +00004885 /* Now skip the whole function definition. */
4886 /* We don't allow nested IDEFs & FDEFs. */
4887
4888 while ( SKIP_Code() == SUCCESS )
4889 {
4890 switch ( CUR.opcode )
4891 {
4892 case 0x89: /* IDEF */
4893 case 0x2C: /* FDEF */
4894 CUR.error = TT_Err_Nested_DEFS;
4895 return;
4896 case 0x2D: /* ENDF */
4897 return;
4898 }
4899 }
4900 }
4901
4902
4903 /*************************************************************************/
4904 /* */
4905 /* PUSHING DATA ONTO THE INTERPRETER STACK */
4906 /* */
Werner Lemberg5811c7c2000-07-02 13:53:16 +00004907 /* Instructions appear in the specification's order. */
David Turnerd2b1f351999-12-16 23:11:37 +00004908 /* */
4909 /*************************************************************************/
4910
4911
4912 /*************************************************************************/
4913 /* */
4914 /* NPUSHB[]: PUSH N Bytes */
4915 /* Opcode range: 0x40 */
4916 /* Stack: --> uint32... */
4917 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004918 static void
4919 Ins_NPUSHB( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004920 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004921 FT_UShort L, K;
David Turnerd2b1f351999-12-16 23:11:37 +00004922
4923
David Turnerf9b8dec2000-06-16 19:34:52 +00004924 L = (FT_UShort)CUR.code[CUR.IP + 1];
David Turnerd2b1f351999-12-16 23:11:37 +00004925
4926 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
4927 {
4928 CUR.error = TT_Err_Stack_Overflow;
4929 return;
4930 }
4931
4932 for ( K = 1; K <= L; K++ )
4933 args[K - 1] = CUR.code[CUR.IP + K + 1];
4934
4935 CUR.new_top += L;
4936 }
4937
4938
4939 /*************************************************************************/
4940 /* */
4941 /* NPUSHW[]: PUSH N Words */
4942 /* Opcode range: 0x41 */
4943 /* Stack: --> int32... */
4944 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004945 static void
4946 Ins_NPUSHW( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004947 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004948 FT_UShort L, K;
David Turnerd2b1f351999-12-16 23:11:37 +00004949
4950
David Turnerf9b8dec2000-06-16 19:34:52 +00004951 L = (FT_UShort)CUR.code[CUR.IP + 1];
David Turnerd2b1f351999-12-16 23:11:37 +00004952
4953 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
4954 {
4955 CUR.error = TT_Err_Stack_Overflow;
4956 return;
4957 }
4958
4959 CUR.IP += 2;
4960
4961 for ( K = 0; K < L; K++ )
4962 args[K] = GET_ShortIns();
4963
4964 CUR.step_ins = FALSE;
4965 CUR.new_top += L;
4966 }
4967
4968
4969 /*************************************************************************/
4970 /* */
4971 /* PUSHB[abc]: PUSH Bytes */
4972 /* Opcode range: 0xB0-0xB7 */
4973 /* Stack: --> uint32... */
4974 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00004975 static void
4976 Ins_PUSHB( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00004977 {
David Turnerf9b8dec2000-06-16 19:34:52 +00004978 FT_UShort L, K;
David Turnerd2b1f351999-12-16 23:11:37 +00004979
4980
Werner Lembergc9f6c662007-03-21 13:30:14 +00004981 L = (FT_UShort)( CUR.opcode - 0xB0 + 1 );
David Turnerd2b1f351999-12-16 23:11:37 +00004982
4983 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
4984 {
4985 CUR.error = TT_Err_Stack_Overflow;
4986 return;
4987 }
4988
4989 for ( K = 1; K <= L; K++ )
4990 args[K - 1] = CUR.code[CUR.IP + K];
4991 }
4992
4993
4994 /*************************************************************************/
4995 /* */
4996 /* PUSHW[abc]: PUSH Words */
4997 /* Opcode range: 0xB8-0xBF */
4998 /* Stack: --> int32... */
4999 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005000 static void
5001 Ins_PUSHW( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005002 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005003 FT_UShort L, K;
David Turnerd2b1f351999-12-16 23:11:37 +00005004
5005
Werner Lembergc9f6c662007-03-21 13:30:14 +00005006 L = (FT_UShort)( CUR.opcode - 0xB8 + 1 );
David Turnerd2b1f351999-12-16 23:11:37 +00005007
5008 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
5009 {
5010 CUR.error = TT_Err_Stack_Overflow;
5011 return;
5012 }
5013
5014 CUR.IP++;
5015
5016 for ( K = 0; K < L; K++ )
5017 args[K] = GET_ShortIns();
5018
5019 CUR.step_ins = FALSE;
5020 }
5021
5022
5023 /*************************************************************************/
5024 /* */
5025 /* MANAGING THE GRAPHICS STATE */
5026 /* */
5027 /* Instructions appear in the specs' order. */
5028 /* */
5029 /*************************************************************************/
5030
5031
5032 /*************************************************************************/
5033 /* */
5034 /* GC[a]: Get Coordinate projected onto */
5035 /* Opcode range: 0x46-0x47 */
5036 /* Stack: uint32 --> f26.6 */
5037 /* */
5038 /* BULLSHIT: Measures from the original glyph must be taken along the */
5039 /* dual projection vector! */
5040 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005041 static void
5042 Ins_GC( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005043 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005044 FT_ULong L;
5045 FT_F26Dot6 R;
David Turnerd2b1f351999-12-16 23:11:37 +00005046
5047
David Turnerf9b8dec2000-06-16 19:34:52 +00005048 L = (FT_ULong)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005049
Werner Lemberg346f1862010-08-06 00:47:57 +02005050 if ( BOUNDSL( L, CUR.zp2.n_points ) )
David Turnerd2b1f351999-12-16 23:11:37 +00005051 {
5052 if ( CUR.pedantic_hinting )
David Turnerd2b1f351999-12-16 23:11:37 +00005053 CUR.error = TT_Err_Invalid_Reference;
Werner Lembergd6a213f2011-01-31 18:51:07 +01005054 R = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00005055 }
5056 else
5057 {
5058 if ( CUR.opcode & 1 )
David Turner72a0dd22007-02-12 15:24:51 +00005059 R = CUR_fast_dualproj( &CUR.zp2.org[L] );
David Turnerd2b1f351999-12-16 23:11:37 +00005060 else
David Turner72a0dd22007-02-12 15:24:51 +00005061 R = CUR_fast_project( &CUR.zp2.cur[L] );
David Turnerd2b1f351999-12-16 23:11:37 +00005062 }
5063
5064 args[0] = R;
5065 }
5066
5067
5068 /*************************************************************************/
5069 /* */
5070 /* SCFS[]: Set Coordinate From Stack */
5071 /* Opcode range: 0x48 */
5072 /* Stack: f26.6 uint32 --> */
5073 /* */
5074 /* Formula: */
5075 /* */
5076 /* OA := OA + ( value - OA.p )/( f.p ) * f */
5077 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005078 static void
5079 Ins_SCFS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005080 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005081 FT_Long K;
5082 FT_UShort L;
David Turnerd2b1f351999-12-16 23:11:37 +00005083
5084
David Turnerf9b8dec2000-06-16 19:34:52 +00005085 L = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005086
5087 if ( BOUNDS( L, CUR.zp2.n_points ) )
5088 {
5089 if ( CUR.pedantic_hinting )
5090 CUR.error = TT_Err_Invalid_Reference;
5091 return;
5092 }
5093
David Turner72a0dd22007-02-12 15:24:51 +00005094 K = CUR_fast_project( &CUR.zp2.cur[L] );
David Turnerd2b1f351999-12-16 23:11:37 +00005095
5096 CUR_Func_move( &CUR.zp2, L, args[1] - K );
5097
5098 /* not part of the specs, but here for safety */
5099
5100 if ( CUR.GS.gep2 == 0 )
5101 CUR.zp2.org[L] = CUR.zp2.cur[L];
5102 }
5103
5104
5105 /*************************************************************************/
5106 /* */
5107 /* MD[a]: Measure Distance */
5108 /* Opcode range: 0x49-0x4A */
5109 /* Stack: uint32 uint32 --> f26.6 */
5110 /* */
5111 /* BULLSHIT: Measure taken in the original glyph must be along the dual */
5112 /* projection vector. */
5113 /* */
5114 /* Second BULLSHIT: Flag attributes are inverted! */
5115 /* 0 => measure distance in original outline */
5116 /* 1 => measure distance in grid-fitted outline */
5117 /* */
5118 /* Third one: `zp0 - zp1', and not `zp2 - zp1! */
5119 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005120 static void
5121 Ins_MD( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005122 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005123 FT_UShort K, L;
5124 FT_F26Dot6 D;
David Turnerd2b1f351999-12-16 23:11:37 +00005125
5126
David Turnerf9b8dec2000-06-16 19:34:52 +00005127 K = (FT_UShort)args[1];
5128 L = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005129
Werner Lemberg346f1862010-08-06 00:47:57 +02005130 if ( BOUNDS( L, CUR.zp0.n_points ) ||
5131 BOUNDS( K, CUR.zp1.n_points ) )
David Turnerd2b1f351999-12-16 23:11:37 +00005132 {
5133 if ( CUR.pedantic_hinting )
David Turnerd2b1f351999-12-16 23:11:37 +00005134 CUR.error = TT_Err_Invalid_Reference;
David Turnerd2b1f351999-12-16 23:11:37 +00005135 D = 0;
5136 }
5137 else
5138 {
5139 if ( CUR.opcode & 1 )
5140 D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
5141 else
Werner Lembergc94fa662008-05-27 23:24:07 +00005142 {
5143 FT_Vector* vec1 = CUR.zp0.orus + L;
5144 FT_Vector* vec2 = CUR.zp1.orus + K;
5145
5146
5147 if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
5148 {
5149 /* this should be faster */
5150 D = CUR_Func_dualproj( vec1, vec2 );
5151 D = TT_MULFIX( D, CUR.metrics.x_scale );
5152 }
5153 else
5154 {
5155 FT_Vector vec;
5156
5157
5158 vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
5159 vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
5160
5161 D = CUR_fast_dualproj( &vec );
5162 }
5163 }
David Turnerd2b1f351999-12-16 23:11:37 +00005164 }
5165
5166 args[0] = D;
5167 }
5168
5169
5170 /*************************************************************************/
5171 /* */
5172 /* SDPVTL[a]: Set Dual PVector to Line */
5173 /* Opcode range: 0x86-0x87 */
5174 /* Stack: uint32 uint32 --> */
5175 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005176 static void
5177 Ins_SDPVTL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005178 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005179 FT_Long A, B, C;
5180 FT_UShort p1, p2; /* was FT_Int in pas type ERROR */
David Turnerd2b1f351999-12-16 23:11:37 +00005181
5182
David Turnerf9b8dec2000-06-16 19:34:52 +00005183 p1 = (FT_UShort)args[1];
5184 p2 = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005185
5186 if ( BOUNDS( p2, CUR.zp1.n_points ) ||
5187 BOUNDS( p1, CUR.zp2.n_points ) )
5188 {
5189 if ( CUR.pedantic_hinting )
5190 CUR.error = TT_Err_Invalid_Reference;
5191 return;
5192 }
5193
5194 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005195 FT_Vector* v1 = CUR.zp1.org + p2;
5196 FT_Vector* v2 = CUR.zp2.org + p1;
David Turnerd2b1f351999-12-16 23:11:37 +00005197
5198
5199 A = v1->x - v2->x;
5200 B = v1->y - v2->y;
5201 }
5202
Werner Lemberg78575dc2000-06-12 19:36:41 +00005203 if ( ( CUR.opcode & 1 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00005204 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00005205 C = B; /* counter clockwise rotation */
David Turnerd2b1f351999-12-16 23:11:37 +00005206 B = A;
5207 A = -C;
5208 }
5209
5210 NORMalize( A, B, &CUR.GS.dualVector );
5211
5212 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005213 FT_Vector* v1 = CUR.zp1.cur + p2;
5214 FT_Vector* v2 = CUR.zp2.cur + p1;
David Turnerd2b1f351999-12-16 23:11:37 +00005215
5216
5217 A = v1->x - v2->x;
5218 B = v1->y - v2->y;
5219 }
5220
Werner Lemberg78575dc2000-06-12 19:36:41 +00005221 if ( ( CUR.opcode & 1 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00005222 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00005223 C = B; /* counter clockwise rotation */
David Turnerd2b1f351999-12-16 23:11:37 +00005224 B = A;
5225 A = -C;
5226 }
5227
5228 NORMalize( A, B, &CUR.GS.projVector );
5229
Graham Asher3ea859f2003-04-25 11:40:46 +00005230 GUESS_VECTOR( freeVector );
5231
David Turnerd2b1f351999-12-16 23:11:37 +00005232 COMPUTE_Funcs();
5233 }
5234
5235
5236 /*************************************************************************/
5237 /* */
5238 /* SZP0[]: Set Zone Pointer 0 */
5239 /* Opcode range: 0x13 */
5240 /* Stack: uint32 --> */
5241 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005242 static void
5243 Ins_SZP0( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005244 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005245 switch ( (FT_Int)args[0] )
David Turnerd2b1f351999-12-16 23:11:37 +00005246 {
5247 case 0:
5248 CUR.zp0 = CUR.twilight;
5249 break;
5250
5251 case 1:
5252 CUR.zp0 = CUR.pts;
5253 break;
5254
5255 default:
5256 if ( CUR.pedantic_hinting )
5257 CUR.error = TT_Err_Invalid_Reference;
5258 return;
5259 }
5260
David Turnerf9b8dec2000-06-16 19:34:52 +00005261 CUR.GS.gep0 = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005262 }
5263
5264
5265 /*************************************************************************/
5266 /* */
5267 /* SZP1[]: Set Zone Pointer 1 */
5268 /* Opcode range: 0x14 */
5269 /* Stack: uint32 --> */
5270 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005271 static void
5272 Ins_SZP1( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005273 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005274 switch ( (FT_Int)args[0] )
David Turnerd2b1f351999-12-16 23:11:37 +00005275 {
5276 case 0:
5277 CUR.zp1 = CUR.twilight;
5278 break;
5279
5280 case 1:
5281 CUR.zp1 = CUR.pts;
5282 break;
5283
5284 default:
5285 if ( CUR.pedantic_hinting )
5286 CUR.error = TT_Err_Invalid_Reference;
5287 return;
5288 }
5289
David Turnerf9b8dec2000-06-16 19:34:52 +00005290 CUR.GS.gep1 = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005291 }
5292
5293
5294 /*************************************************************************/
5295 /* */
5296 /* SZP2[]: Set Zone Pointer 2 */
5297 /* Opcode range: 0x15 */
5298 /* Stack: uint32 --> */
5299 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005300 static void
5301 Ins_SZP2( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005302 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005303 switch ( (FT_Int)args[0] )
David Turnerd2b1f351999-12-16 23:11:37 +00005304 {
5305 case 0:
5306 CUR.zp2 = CUR.twilight;
5307 break;
5308
5309 case 1:
5310 CUR.zp2 = CUR.pts;
5311 break;
5312
5313 default:
5314 if ( CUR.pedantic_hinting )
5315 CUR.error = TT_Err_Invalid_Reference;
5316 return;
5317 }
5318
David Turnerf9b8dec2000-06-16 19:34:52 +00005319 CUR.GS.gep2 = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005320 }
5321
5322
5323 /*************************************************************************/
5324 /* */
5325 /* SZPS[]: Set Zone PointerS */
5326 /* Opcode range: 0x16 */
5327 /* Stack: uint32 --> */
5328 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005329 static void
5330 Ins_SZPS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005331 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005332 switch ( (FT_Int)args[0] )
David Turnerd2b1f351999-12-16 23:11:37 +00005333 {
5334 case 0:
5335 CUR.zp0 = CUR.twilight;
5336 break;
5337
5338 case 1:
5339 CUR.zp0 = CUR.pts;
5340 break;
5341
5342 default:
5343 if ( CUR.pedantic_hinting )
5344 CUR.error = TT_Err_Invalid_Reference;
5345 return;
5346 }
5347
5348 CUR.zp1 = CUR.zp0;
5349 CUR.zp2 = CUR.zp0;
5350
David Turnerf9b8dec2000-06-16 19:34:52 +00005351 CUR.GS.gep0 = (FT_UShort)args[0];
5352 CUR.GS.gep1 = (FT_UShort)args[0];
5353 CUR.GS.gep2 = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005354 }
5355
5356
5357 /*************************************************************************/
5358 /* */
5359 /* INSTCTRL[]: INSTruction ConTRoL */
5360 /* Opcode range: 0x8e */
5361 /* Stack: int32 int32 --> */
5362 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005363 static void
5364 Ins_INSTCTRL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005365 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005366 FT_Long K, L;
David Turnerd2b1f351999-12-16 23:11:37 +00005367
5368
5369 K = args[1];
5370 L = args[0];
5371
5372 if ( K < 1 || K > 2 )
5373 {
5374 if ( CUR.pedantic_hinting )
5375 CUR.error = TT_Err_Invalid_Reference;
5376 return;
5377 }
5378
5379 if ( L != 0 )
5380 L = K;
5381
David Turner3b7049f2001-07-07 16:12:14 +00005382 CUR.GS.instruct_control = FT_BOOL(
5383 ( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );
David Turnerd2b1f351999-12-16 23:11:37 +00005384 }
5385
5386
5387 /*************************************************************************/
5388 /* */
5389 /* SCANCTRL[]: SCAN ConTRoL */
5390 /* Opcode range: 0x85 */
5391 /* Stack: uint32? --> */
5392 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005393 static void
5394 Ins_SCANCTRL( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005395 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005396 FT_Int A;
David Turnerd2b1f351999-12-16 23:11:37 +00005397
5398
5399 /* Get Threshold */
David Turnerf9b8dec2000-06-16 19:34:52 +00005400 A = (FT_Int)( args[0] & 0xFF );
David Turnerd2b1f351999-12-16 23:11:37 +00005401
5402 if ( A == 0xFF )
5403 {
5404 CUR.GS.scan_control = TRUE;
5405 return;
5406 }
5407 else if ( A == 0 )
5408 {
5409 CUR.GS.scan_control = FALSE;
5410 return;
5411 }
5412
Werner Lemberg1e5e7aa2009-01-25 16:27:04 +00005413 if ( ( args[0] & 0x100 ) != 0 && CUR.tt_metrics.ppem <= A )
David Turnerd2b1f351999-12-16 23:11:37 +00005414 CUR.GS.scan_control = TRUE;
David Turnerd2b1f351999-12-16 23:11:37 +00005415
Werner Lembergc9f6c662007-03-21 13:30:14 +00005416 if ( ( args[0] & 0x200 ) != 0 && CUR.tt_metrics.rotated )
David Turnerd2b1f351999-12-16 23:11:37 +00005417 CUR.GS.scan_control = TRUE;
5418
Werner Lembergc9f6c662007-03-21 13:30:14 +00005419 if ( ( args[0] & 0x400 ) != 0 && CUR.tt_metrics.stretched )
David Turnerd2b1f351999-12-16 23:11:37 +00005420 CUR.GS.scan_control = TRUE;
5421
Werner Lemberg1e5e7aa2009-01-25 16:27:04 +00005422 if ( ( args[0] & 0x800 ) != 0 && CUR.tt_metrics.ppem > A )
David Turnerd2b1f351999-12-16 23:11:37 +00005423 CUR.GS.scan_control = FALSE;
David Turnerd2b1f351999-12-16 23:11:37 +00005424
Werner Lembergc9f6c662007-03-21 13:30:14 +00005425 if ( ( args[0] & 0x1000 ) != 0 && CUR.tt_metrics.rotated )
David Turnerd2b1f351999-12-16 23:11:37 +00005426 CUR.GS.scan_control = FALSE;
5427
Werner Lembergc9f6c662007-03-21 13:30:14 +00005428 if ( ( args[0] & 0x2000 ) != 0 && CUR.tt_metrics.stretched )
David Turnerd2b1f351999-12-16 23:11:37 +00005429 CUR.GS.scan_control = FALSE;
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005430 }
David Turnerd2b1f351999-12-16 23:11:37 +00005431
5432
5433 /*************************************************************************/
5434 /* */
5435 /* SCANTYPE[]: SCAN TYPE */
5436 /* Opcode range: 0x8D */
5437 /* Stack: uint32? --> */
5438 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005439 static void
5440 Ins_SCANTYPE( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005441 {
Werner Lembergce8853a2008-06-24 11:19:03 +00005442 if ( args[0] >= 0 )
David Turnerf9b8dec2000-06-16 19:34:52 +00005443 CUR.GS.scan_type = (FT_Int)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005444 }
5445
5446
5447 /*************************************************************************/
5448 /* */
5449 /* MANAGING OUTLINES */
5450 /* */
Werner Lemberg5811c7c2000-07-02 13:53:16 +00005451 /* Instructions appear in the specification's order. */
David Turnerd2b1f351999-12-16 23:11:37 +00005452 /* */
5453 /*************************************************************************/
5454
5455
5456 /*************************************************************************/
5457 /* */
5458 /* FLIPPT[]: FLIP PoinT */
5459 /* Opcode range: 0x80 */
5460 /* Stack: uint32... --> */
5461 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005462 static void
5463 Ins_FLIPPT( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005464 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005465 FT_UShort point;
David Turnerd2b1f351999-12-16 23:11:37 +00005466
David Turnerc6a92202000-07-04 18:12:13 +00005467 FT_UNUSED_ARG;
David Turnerd2b1f351999-12-16 23:11:37 +00005468
Werner Lemberg5811c7c2000-07-02 13:53:16 +00005469
David Turnerd2b1f351999-12-16 23:11:37 +00005470 if ( CUR.top < CUR.GS.loop )
5471 {
Werner Lemberg96f04562011-01-31 10:24:32 +01005472 if ( CUR.pedantic_hinting )
Werner Lemberg96f04562011-01-31 10:24:32 +01005473 CUR.error = TT_Err_Too_Few_Arguments;
Werner Lembergd6a213f2011-01-31 18:51:07 +01005474 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00005475 }
5476
5477 while ( CUR.GS.loop > 0 )
5478 {
5479 CUR.args--;
5480
David Turnerf9b8dec2000-06-16 19:34:52 +00005481 point = (FT_UShort)CUR.stack[CUR.args];
David Turnerd2b1f351999-12-16 23:11:37 +00005482
5483 if ( BOUNDS( point, CUR.pts.n_points ) )
5484 {
5485 if ( CUR.pedantic_hinting )
5486 {
5487 CUR.error = TT_Err_Invalid_Reference;
5488 return;
5489 }
5490 }
5491 else
David Turnerb08fe2d2002-08-27 20:20:29 +00005492 CUR.pts.tags[point] ^= FT_CURVE_TAG_ON;
David Turnerd2b1f351999-12-16 23:11:37 +00005493
5494 CUR.GS.loop--;
5495 }
5496
Werner Lembergd6a213f2011-01-31 18:51:07 +01005497 Fail:
David Turnerd2b1f351999-12-16 23:11:37 +00005498 CUR.GS.loop = 1;
5499 CUR.new_top = CUR.args;
5500 }
5501
5502
5503 /*************************************************************************/
5504 /* */
5505 /* FLIPRGON[]: FLIP RanGe ON */
5506 /* Opcode range: 0x81 */
5507 /* Stack: uint32 uint32 --> */
5508 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005509 static void
5510 Ins_FLIPRGON( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005511 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005512 FT_UShort I, K, L;
David Turnerd2b1f351999-12-16 23:11:37 +00005513
5514
David Turnerf9b8dec2000-06-16 19:34:52 +00005515 K = (FT_UShort)args[1];
5516 L = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005517
5518 if ( BOUNDS( K, CUR.pts.n_points ) ||
5519 BOUNDS( L, CUR.pts.n_points ) )
5520 {
5521 if ( CUR.pedantic_hinting )
5522 CUR.error = TT_Err_Invalid_Reference;
5523 return;
5524 }
5525
5526 for ( I = L; I <= K; I++ )
David Turnerb08fe2d2002-08-27 20:20:29 +00005527 CUR.pts.tags[I] |= FT_CURVE_TAG_ON;
David Turnerd2b1f351999-12-16 23:11:37 +00005528 }
5529
5530
5531 /*************************************************************************/
5532 /* */
5533 /* FLIPRGOFF: FLIP RanGe OFF */
5534 /* Opcode range: 0x82 */
5535 /* Stack: uint32 uint32 --> */
5536 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005537 static void
5538 Ins_FLIPRGOFF( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005539 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005540 FT_UShort I, K, L;
David Turnerd2b1f351999-12-16 23:11:37 +00005541
5542
David Turnerf9b8dec2000-06-16 19:34:52 +00005543 K = (FT_UShort)args[1];
5544 L = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005545
5546 if ( BOUNDS( K, CUR.pts.n_points ) ||
5547 BOUNDS( L, CUR.pts.n_points ) )
5548 {
5549 if ( CUR.pedantic_hinting )
5550 CUR.error = TT_Err_Invalid_Reference;
5551 return;
5552 }
5553
5554 for ( I = L; I <= K; I++ )
David Turnerb08fe2d2002-08-27 20:20:29 +00005555 CUR.pts.tags[I] &= ~FT_CURVE_TAG_ON;
David Turnerd2b1f351999-12-16 23:11:37 +00005556 }
5557
5558
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005559 static FT_Bool
Werner Lemberg91db04c2002-04-01 14:25:28 +00005560 Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6* x,
5561 FT_F26Dot6* y,
5562 TT_GlyphZone zone,
5563 FT_UShort* refp )
David Turnerd2b1f351999-12-16 23:11:37 +00005564 {
David Turnerb5713c52002-03-14 11:26:29 +00005565 TT_GlyphZoneRec zp;
Werner Lemberg91db04c2002-04-01 14:25:28 +00005566 FT_UShort p;
5567 FT_F26Dot6 d;
David Turnerd2b1f351999-12-16 23:11:37 +00005568
5569
5570 if ( CUR.opcode & 1 )
5571 {
5572 zp = CUR.zp0;
5573 p = CUR.GS.rp1;
5574 }
5575 else
5576 {
5577 zp = CUR.zp1;
5578 p = CUR.GS.rp2;
5579 }
5580
5581 if ( BOUNDS( p, zp.n_points ) )
5582 {
5583 if ( CUR.pedantic_hinting )
5584 CUR.error = TT_Err_Invalid_Reference;
Werner Lemberg8c4120d2007-01-15 06:42:40 +00005585 *refp = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00005586 return FAILURE;
5587 }
5588
5589 *zone = zp;
5590 *refp = p;
5591
5592 d = CUR_Func_project( zp.cur + p, zp.org + p );
5593
David Turner8b6db862003-08-17 22:09:14 +00005594#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Graham Asher3ea859f2003-04-25 11:40:46 +00005595 if ( CUR.face->unpatented_hinting )
5596 {
5597 if ( CUR.GS.both_x_axis )
5598 {
5599 *x = d;
5600 *y = 0;
5601 }
5602 else
5603 {
5604 *x = 0;
5605 *y = d;
David Turner87c0d302003-12-24 01:10:46 +00005606 }
Graham Asher3ea859f2003-04-25 11:40:46 +00005607 }
5608 else
5609#endif
5610 {
5611 *x = TT_MULDIV( d,
5612 (FT_Long)CUR.GS.freeVector.x * 0x10000L,
5613 CUR.F_dot_P );
5614 *y = TT_MULDIV( d,
5615 (FT_Long)CUR.GS.freeVector.y * 0x10000L,
5616 CUR.F_dot_P );
5617 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00005618
David Turnerd2b1f351999-12-16 23:11:37 +00005619 return SUCCESS;
5620 }
5621
5622
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005623 static void
5624 Move_Zp2_Point( EXEC_OP_ FT_UShort point,
5625 FT_F26Dot6 dx,
5626 FT_F26Dot6 dy,
5627 FT_Bool touch )
David Turnerd2b1f351999-12-16 23:11:37 +00005628 {
David Turner8b6db862003-08-17 22:09:14 +00005629#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Werner Lemberga3f4da82003-04-29 13:23:47 +00005630 if ( CUR.face->unpatented_hinting )
Graham Asher3ea859f2003-04-25 11:40:46 +00005631 {
5632 if ( CUR.GS.both_x_axis )
5633 {
5634 CUR.zp2.cur[point].x += dx;
5635 if ( touch )
5636 CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
5637 }
5638 else
5639 {
5640 CUR.zp2.cur[point].y += dy;
5641 if ( touch )
5642 CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
5643 }
5644 return;
5645 }
5646#endif
5647
David Turnerd2b1f351999-12-16 23:11:37 +00005648 if ( CUR.GS.freeVector.x != 0 )
5649 {
5650 CUR.zp2.cur[point].x += dx;
5651 if ( touch )
David Turnerb08fe2d2002-08-27 20:20:29 +00005652 CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
David Turnerd2b1f351999-12-16 23:11:37 +00005653 }
5654
5655 if ( CUR.GS.freeVector.y != 0 )
5656 {
5657 CUR.zp2.cur[point].y += dy;
5658 if ( touch )
David Turnerb08fe2d2002-08-27 20:20:29 +00005659 CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
David Turnerd2b1f351999-12-16 23:11:37 +00005660 }
5661 }
5662
5663
5664 /*************************************************************************/
5665 /* */
5666 /* SHP[a]: SHift Point by the last point */
5667 /* Opcode range: 0x32-0x33 */
5668 /* Stack: uint32... --> */
5669 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005670 static void
5671 Ins_SHP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005672 {
David Turnerb5713c52002-03-14 11:26:29 +00005673 TT_GlyphZoneRec zp;
Werner Lemberg91db04c2002-04-01 14:25:28 +00005674 FT_UShort refp;
David Turnerd2b1f351999-12-16 23:11:37 +00005675
Werner Lemberg91db04c2002-04-01 14:25:28 +00005676 FT_F26Dot6 dx,
5677 dy;
5678 FT_UShort point;
David Turnerd2b1f351999-12-16 23:11:37 +00005679
David Turnerc6a92202000-07-04 18:12:13 +00005680 FT_UNUSED_ARG;
David Turnerd2b1f351999-12-16 23:11:37 +00005681
Werner Lemberg78575dc2000-06-12 19:36:41 +00005682
David Turnerd2b1f351999-12-16 23:11:37 +00005683 if ( CUR.top < CUR.GS.loop )
5684 {
Werner Lembergd6a213f2011-01-31 18:51:07 +01005685 if ( CUR.pedantic_hinting )
5686 CUR.error = TT_Err_Invalid_Reference;
5687 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00005688 }
5689
5690 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
5691 return;
5692
5693 while ( CUR.GS.loop > 0 )
5694 {
5695 CUR.args--;
David Turnerf9b8dec2000-06-16 19:34:52 +00005696 point = (FT_UShort)CUR.stack[CUR.args];
David Turnerd2b1f351999-12-16 23:11:37 +00005697
5698 if ( BOUNDS( point, CUR.zp2.n_points ) )
5699 {
5700 if ( CUR.pedantic_hinting )
5701 {
5702 CUR.error = TT_Err_Invalid_Reference;
5703 return;
5704 }
5705 }
5706 else
5707 /* XXX: UNDOCUMENTED! SHP touches the points */
5708 MOVE_Zp2_Point( point, dx, dy, TRUE );
5709
5710 CUR.GS.loop--;
5711 }
5712
Werner Lembergd6a213f2011-01-31 18:51:07 +01005713 Fail:
David Turnerd2b1f351999-12-16 23:11:37 +00005714 CUR.GS.loop = 1;
5715 CUR.new_top = CUR.args;
5716 }
5717
5718
5719 /*************************************************************************/
5720 /* */
5721 /* SHC[a]: SHift Contour */
5722 /* Opcode range: 0x34-35 */
5723 /* Stack: uint32 --> */
5724 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005725 static void
5726 Ins_SHC( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005727 {
David Turnerb5713c52002-03-14 11:26:29 +00005728 TT_GlyphZoneRec zp;
Werner Lemberg91db04c2002-04-01 14:25:28 +00005729 FT_UShort refp;
5730 FT_F26Dot6 dx,
5731 dy;
David Turnerd2b1f351999-12-16 23:11:37 +00005732
Werner Lemberg91db04c2002-04-01 14:25:28 +00005733 FT_Short contour;
5734 FT_UShort first_point, last_point, i;
David Turnerd2b1f351999-12-16 23:11:37 +00005735
5736
David Turnerf9b8dec2000-06-16 19:34:52 +00005737 contour = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005738
5739 if ( BOUNDS( contour, CUR.pts.n_contours ) )
5740 {
5741 if ( CUR.pedantic_hinting )
5742 CUR.error = TT_Err_Invalid_Reference;
5743 return;
5744 }
5745
5746 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
5747 return;
5748
5749 if ( contour == 0 )
5750 first_point = 0;
5751 else
Werner Lemberga2da05c2006-06-25 06:27:27 +00005752 first_point = (FT_UShort)( CUR.pts.contours[contour - 1] + 1 -
5753 CUR.pts.first_point );
David Turnerd2b1f351999-12-16 23:11:37 +00005754
Werner Lembergb4142d52007-01-17 12:45:26 +00005755 last_point = (FT_UShort)( CUR.pts.contours[contour] -
5756 CUR.pts.first_point );
David Turnerd2b1f351999-12-16 23:11:37 +00005757
5758 /* XXX: this is probably wrong... at least it prevents memory */
5759 /* corruption when zp2 is the twilight zone */
Werner Lemberg7cb9ec02008-06-09 20:49:29 +00005760 if ( BOUNDS( last_point, CUR.zp2.n_points ) )
David Turnerd2b1f351999-12-16 23:11:37 +00005761 {
5762 if ( CUR.zp2.n_points > 0 )
David Turner3b7049f2001-07-07 16:12:14 +00005763 last_point = (FT_UShort)(CUR.zp2.n_points - 1);
David Turnerd2b1f351999-12-16 23:11:37 +00005764 else
5765 last_point = 0;
5766 }
5767
Werner Lemberg555258f2007-01-21 09:46:37 +00005768 /* XXX: UNDOCUMENTED! SHC touches the points */
David Turnerd2b1f351999-12-16 23:11:37 +00005769 for ( i = first_point; i <= last_point; i++ )
5770 {
5771 if ( zp.cur != CUR.zp2.cur || refp != i )
Werner Lembergbe67c4e2003-11-24 22:54:58 +00005772 MOVE_Zp2_Point( i, dx, dy, TRUE );
David Turnerd2b1f351999-12-16 23:11:37 +00005773 }
5774 }
5775
5776
5777 /*************************************************************************/
5778 /* */
5779 /* SHZ[a]: SHift Zone */
5780 /* Opcode range: 0x36-37 */
5781 /* Stack: uint32 --> */
5782 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005783 static void
5784 Ins_SHZ( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005785 {
Werner Lemberg346f1862010-08-06 00:47:57 +02005786 TT_GlyphZoneRec zp;
5787 FT_UShort refp;
5788 FT_F26Dot6 dx,
5789 dy;
David Turnerd2b1f351999-12-16 23:11:37 +00005790
Werner Lemberg346f1862010-08-06 00:47:57 +02005791 FT_UShort last_point, i;
David Turnerd2b1f351999-12-16 23:11:37 +00005792
5793
5794 if ( BOUNDS( args[0], 2 ) )
5795 {
5796 if ( CUR.pedantic_hinting )
5797 CUR.error = TT_Err_Invalid_Reference;
5798 return;
5799 }
5800
5801 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
5802 return;
5803
Werner Lemberg555258f2007-01-21 09:46:37 +00005804 /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points. */
5805 /* Twilight zone has no contours, so use `n_points'. */
5806 /* Normal zone's `n_points' includes phantoms, so must */
5807 /* use end of last contour. */
5808 if ( CUR.GS.gep2 == 0 && CUR.zp2.n_points > 0 )
5809 last_point = (FT_UShort)( CUR.zp2.n_points - 1 );
5810 else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 )
Werner Lemberg0edf0982010-10-06 11:52:27 +02005811 {
Werner Lemberg555258f2007-01-21 09:46:37 +00005812 last_point = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] );
Werner Lemberg0edf0982010-10-06 11:52:27 +02005813
5814 if ( BOUNDS( last_point, CUR.zp2.n_points ) )
5815 {
5816 if ( CUR.pedantic_hinting )
5817 CUR.error = TT_Err_Invalid_Reference;
5818 return;
5819 }
5820 }
David Turnerd2b1f351999-12-16 23:11:37 +00005821 else
5822 last_point = 0;
5823
5824 /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
5825 for ( i = 0; i <= last_point; i++ )
5826 {
5827 if ( zp.cur != CUR.zp2.cur || refp != i )
5828 MOVE_Zp2_Point( i, dx, dy, FALSE );
5829 }
5830 }
5831
5832
5833 /*************************************************************************/
5834 /* */
5835 /* SHPIX[]: SHift points by a PIXel amount */
5836 /* Opcode range: 0x38 */
5837 /* Stack: f26.6 uint32... --> */
5838 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005839 static void
5840 Ins_SHPIX( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005841 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005842 FT_F26Dot6 dx, dy;
5843 FT_UShort point;
David Turnerd2b1f351999-12-16 23:11:37 +00005844
5845
5846 if ( CUR.top < CUR.GS.loop + 1 )
5847 {
Werner Lembergd6a213f2011-01-31 18:51:07 +01005848 if ( CUR.pedantic_hinting )
5849 CUR.error = TT_Err_Invalid_Reference;
5850 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00005851 }
5852
David Turner8b6db862003-08-17 22:09:14 +00005853#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Werner Lemberga3f4da82003-04-29 13:23:47 +00005854 if ( CUR.face->unpatented_hinting )
Graham Asher3ea859f2003-04-25 11:40:46 +00005855 {
5856 if ( CUR.GS.both_x_axis )
5857 {
suzuki toshiya6dc27522009-08-01 00:32:15 +09005858 dx = TT_MulFix14( (FT_UInt32)args[0], 0x4000 );
Werner Lemberga3f4da82003-04-29 13:23:47 +00005859 dy = 0;
Graham Asher3ea859f2003-04-25 11:40:46 +00005860 }
5861 else
5862 {
Werner Lemberga3f4da82003-04-29 13:23:47 +00005863 dx = 0;
suzuki toshiya6dc27522009-08-01 00:32:15 +09005864 dy = TT_MulFix14( (FT_UInt32)args[0], 0x4000 );
Graham Asher3ea859f2003-04-25 11:40:46 +00005865 }
5866 }
5867 else
5868#endif
5869 {
suzuki toshiya6dc27522009-08-01 00:32:15 +09005870 dx = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.x );
5871 dy = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.y );
Graham Asher3ea859f2003-04-25 11:40:46 +00005872 }
David Turnerd2b1f351999-12-16 23:11:37 +00005873
5874 while ( CUR.GS.loop > 0 )
5875 {
5876 CUR.args--;
5877
David Turnerf9b8dec2000-06-16 19:34:52 +00005878 point = (FT_UShort)CUR.stack[CUR.args];
David Turnerd2b1f351999-12-16 23:11:37 +00005879
5880 if ( BOUNDS( point, CUR.zp2.n_points ) )
5881 {
5882 if ( CUR.pedantic_hinting )
5883 {
5884 CUR.error = TT_Err_Invalid_Reference;
5885 return;
5886 }
5887 }
5888 else
5889 MOVE_Zp2_Point( point, dx, dy, TRUE );
5890
5891 CUR.GS.loop--;
5892 }
5893
Werner Lembergd6a213f2011-01-31 18:51:07 +01005894 Fail:
David Turnerd2b1f351999-12-16 23:11:37 +00005895 CUR.GS.loop = 1;
5896 CUR.new_top = CUR.args;
5897 }
5898
5899
5900 /*************************************************************************/
5901 /* */
5902 /* MSIRP[a]: Move Stack Indirect Relative Position */
5903 /* Opcode range: 0x3A-0x3B */
5904 /* Stack: f26.6 uint32 --> */
5905 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005906 static void
5907 Ins_MSIRP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005908 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005909 FT_UShort point;
5910 FT_F26Dot6 distance;
David Turnerd2b1f351999-12-16 23:11:37 +00005911
5912
David Turnerf9b8dec2000-06-16 19:34:52 +00005913 point = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005914
5915 if ( BOUNDS( point, CUR.zp1.n_points ) ||
5916 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
5917 {
5918 if ( CUR.pedantic_hinting )
5919 CUR.error = TT_Err_Invalid_Reference;
5920 return;
5921 }
5922
5923 /* XXX: UNDOCUMENTED! behaviour */
Werner Lembergbe67c4e2003-11-24 22:54:58 +00005924 if ( CUR.GS.gep1 == 0 ) /* if the point that is to be moved */
5925 /* is in twilight zone */
David Turnerd2b1f351999-12-16 23:11:37 +00005926 {
5927 CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
Werner Lembergbe67c4e2003-11-24 22:54:58 +00005928 CUR_Func_move_orig( &CUR.zp1, point, args[1] );
David Turnerd2b1f351999-12-16 23:11:37 +00005929 CUR.zp1.cur[point] = CUR.zp1.org[point];
5930 }
5931
5932 distance = CUR_Func_project( CUR.zp1.cur + point,
5933 CUR.zp0.cur + CUR.GS.rp0 );
5934
5935 CUR_Func_move( &CUR.zp1, point, args[1] - distance );
5936
5937 CUR.GS.rp1 = CUR.GS.rp0;
5938 CUR.GS.rp2 = point;
5939
Werner Lembergc9f6c662007-03-21 13:30:14 +00005940 if ( ( CUR.opcode & 1 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00005941 CUR.GS.rp0 = point;
5942 }
5943
5944
5945 /*************************************************************************/
5946 /* */
5947 /* MDAP[a]: Move Direct Absolute Point */
5948 /* Opcode range: 0x2E-0x2F */
5949 /* Stack: uint32 --> */
5950 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005951 static void
5952 Ins_MDAP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005953 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005954 FT_UShort point;
5955 FT_F26Dot6 cur_dist,
David Turnerd2b1f351999-12-16 23:11:37 +00005956 distance;
5957
5958
David Turnerf9b8dec2000-06-16 19:34:52 +00005959 point = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00005960
5961 if ( BOUNDS( point, CUR.zp0.n_points ) )
5962 {
5963 if ( CUR.pedantic_hinting )
5964 CUR.error = TT_Err_Invalid_Reference;
5965 return;
5966 }
5967
5968 /* XXX: Is there some undocumented feature while in the */
5969 /* twilight zone? ? */
Werner Lemberg78575dc2000-06-12 19:36:41 +00005970 if ( ( CUR.opcode & 1 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00005971 {
David Turner72a0dd22007-02-12 15:24:51 +00005972 cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
David Turnerd2b1f351999-12-16 23:11:37 +00005973 distance = CUR_Func_round( cur_dist,
5974 CUR.tt_metrics.compensations[0] ) - cur_dist;
5975 }
5976 else
5977 distance = 0;
5978
5979 CUR_Func_move( &CUR.zp0, point, distance );
5980
5981 CUR.GS.rp0 = point;
5982 CUR.GS.rp1 = point;
5983 }
5984
5985
5986 /*************************************************************************/
5987 /* */
5988 /* MIAP[a]: Move Indirect Absolute Point */
5989 /* Opcode range: 0x3E-0x3F */
5990 /* Stack: uint32 uint32 --> */
5991 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00005992 static void
5993 Ins_MIAP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00005994 {
David Turnerf9b8dec2000-06-16 19:34:52 +00005995 FT_ULong cvtEntry;
5996 FT_UShort point;
5997 FT_F26Dot6 distance,
David Turnerd2b1f351999-12-16 23:11:37 +00005998 org_dist;
5999
6000
David Turnerf9b8dec2000-06-16 19:34:52 +00006001 cvtEntry = (FT_ULong)args[1];
6002 point = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00006003
Werner Lemberg346f1862010-08-06 00:47:57 +02006004 if ( BOUNDS( point, CUR.zp0.n_points ) ||
6005 BOUNDSL( cvtEntry, CUR.cvtSize ) )
David Turnerd2b1f351999-12-16 23:11:37 +00006006 {
6007 if ( CUR.pedantic_hinting )
6008 CUR.error = TT_Err_Invalid_Reference;
LIU Sun-Liangc61b3592011-01-30 16:29:45 +01006009 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00006010 }
6011
Werner Lembergc9f6c662007-03-21 13:30:14 +00006012 /* XXX: UNDOCUMENTED! */
David Turnerd2b1f351999-12-16 23:11:37 +00006013 /* */
6014 /* The behaviour of an MIAP instruction is quite */
6015 /* different when used in the twilight zone. */
6016 /* */
Werner Lemberg406d25f2007-02-12 22:01:18 +00006017 /* First, no control value cut-in test is performed */
David Turnerd2b1f351999-12-16 23:11:37 +00006018 /* as it would fail anyway. Second, the original */
6019 /* point, i.e. (org_x,org_y) of zp0.point, is set */
6020 /* to the absolute, unrounded distance found in */
6021 /* the CVT. */
6022 /* */
6023 /* This is used in the CVT programs of the Microsoft */
6024 /* fonts Arial, Times, etc., in order to re-adjust */
6025 /* some key font heights. It allows the use of the */
6026 /* IP instruction in the twilight zone, which */
6027 /* otherwise would be `illegal' according to the */
Werner Lemberg78575dc2000-06-12 19:36:41 +00006028 /* specification. */
David Turnerd2b1f351999-12-16 23:11:37 +00006029 /* */
6030 /* We implement it with a special sequence for the */
6031 /* twilight zone. This is a bad hack, but it seems */
6032 /* to work. */
6033
6034 distance = CUR_Func_read_cvt( cvtEntry );
6035
6036 if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */
6037 {
suzuki toshiya6dc27522009-08-01 00:32:15 +09006038 CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance, CUR.GS.freeVector.x );
6039 CUR.zp0.org[point].y = TT_MulFix14( (FT_UInt32)distance, CUR.GS.freeVector.y ),
David Turner4b29d582002-03-25 17:02:26 +00006040 CUR.zp0.cur[point] = CUR.zp0.org[point];
David Turnerd2b1f351999-12-16 23:11:37 +00006041 }
6042
David Turner72a0dd22007-02-12 15:24:51 +00006043 org_dist = CUR_fast_project( &CUR.zp0.cur[point] );
David Turnerd2b1f351999-12-16 23:11:37 +00006044
Werner Lemberg78575dc2000-06-12 19:36:41 +00006045 if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cutin flag */
David Turnerd2b1f351999-12-16 23:11:37 +00006046 {
Werner Lembergdfa46192004-03-05 09:26:24 +00006047 if ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin )
David Turnerd2b1f351999-12-16 23:11:37 +00006048 distance = org_dist;
6049
6050 distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );
6051 }
6052
6053 CUR_Func_move( &CUR.zp0, point, distance - org_dist );
6054
LIU Sun-Liangc61b3592011-01-30 16:29:45 +01006055 Fail:
David Turnerd2b1f351999-12-16 23:11:37 +00006056 CUR.GS.rp0 = point;
6057 CUR.GS.rp1 = point;
6058 }
6059
6060
6061 /*************************************************************************/
6062 /* */
6063 /* MDRP[abcde]: Move Direct Relative Point */
6064 /* Opcode range: 0xC0-0xDF */
6065 /* Stack: uint32 --> */
6066 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006067 static void
6068 Ins_MDRP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00006069 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006070 FT_UShort point;
6071 FT_F26Dot6 org_dist, distance;
David Turnerd2b1f351999-12-16 23:11:37 +00006072
6073
David Turnerf9b8dec2000-06-16 19:34:52 +00006074 point = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00006075
6076 if ( BOUNDS( point, CUR.zp1.n_points ) ||
6077 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
6078 {
6079 if ( CUR.pedantic_hinting )
6080 CUR.error = TT_Err_Invalid_Reference;
Werner Lembergd6a213f2011-01-31 18:51:07 +01006081 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00006082 }
6083
6084 /* XXX: Is there some undocumented feature while in the */
6085 /* twilight zone? */
6086
Werner Lembergc9f6c662007-03-21 13:30:14 +00006087 /* XXX: UNDOCUMENTED: twilight zone special case */
David Turner74c34eb2007-03-18 07:19:31 +00006088
6089 if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )
6090 {
6091 FT_Vector* vec1 = &CUR.zp1.org[point];
6092 FT_Vector* vec2 = &CUR.zp0.org[CUR.GS.rp0];
6093
Werner Lembergc9f6c662007-03-21 13:30:14 +00006094
David Turner74c34eb2007-03-18 07:19:31 +00006095 org_dist = CUR_Func_dualproj( vec1, vec2 );
6096 }
6097 else
David Turner33f5f242006-08-16 16:50:55 +00006098 {
David Turner2c4500e2007-02-14 15:08:47 +00006099 FT_Vector* vec1 = &CUR.zp1.orus[point];
6100 FT_Vector* vec2 = &CUR.zp0.orus[CUR.GS.rp0];
David Turner33f5f242006-08-16 16:50:55 +00006101
Werner Lemberg12342992006-08-19 11:18:09 +00006102
David Turner89020d92007-03-17 17:48:57 +00006103 if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
David Turner2c4500e2007-02-14 15:08:47 +00006104 {
6105 /* this should be faster */
6106 org_dist = CUR_Func_dualproj( vec1, vec2 );
6107 org_dist = TT_MULFIX( org_dist, CUR.metrics.x_scale );
6108 }
David Turner89020d92007-03-17 17:48:57 +00006109 else
David Turner2c4500e2007-02-14 15:08:47 +00006110 {
6111 FT_Vector vec;
David Turner33f5f242006-08-16 16:50:55 +00006112
Werner Lembergc9f6c662007-03-21 13:30:14 +00006113
David Turner2c4500e2007-02-14 15:08:47 +00006114 vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
6115 vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
David Turner33f5f242006-08-16 16:50:55 +00006116
David Turner2c4500e2007-02-14 15:08:47 +00006117 org_dist = CUR_fast_dualproj( &vec );
6118 }
David Turner33f5f242006-08-16 16:50:55 +00006119 }
Werner Lemberg12342992006-08-19 11:18:09 +00006120
Werner Lemberg12342992006-08-19 11:18:09 +00006121 /* single width cut-in test */
David Turnerd2b1f351999-12-16 23:11:37 +00006122
Werner Lembergdfa46192004-03-05 09:26:24 +00006123 if ( FT_ABS( org_dist - CUR.GS.single_width_value ) <
Werner Lemberg6e9b3182003-06-10 10:54:33 +00006124 CUR.GS.single_width_cutin )
David Turnerd2b1f351999-12-16 23:11:37 +00006125 {
6126 if ( org_dist >= 0 )
6127 org_dist = CUR.GS.single_width_value;
6128 else
6129 org_dist = -CUR.GS.single_width_value;
6130 }
6131
6132 /* round flag */
6133
Werner Lemberg78575dc2000-06-12 19:36:41 +00006134 if ( ( CUR.opcode & 4 ) != 0 )
6135 distance = CUR_Func_round(
6136 org_dist,
6137 CUR.tt_metrics.compensations[CUR.opcode & 3] );
David Turnerd2b1f351999-12-16 23:11:37 +00006138 else
Werner Lemberg78575dc2000-06-12 19:36:41 +00006139 distance = ROUND_None(
6140 org_dist,
6141 CUR.tt_metrics.compensations[CUR.opcode & 3] );
David Turnerd2b1f351999-12-16 23:11:37 +00006142
6143 /* minimum distance flag */
6144
Werner Lemberg78575dc2000-06-12 19:36:41 +00006145 if ( ( CUR.opcode & 8 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00006146 {
6147 if ( org_dist >= 0 )
6148 {
6149 if ( distance < CUR.GS.minimum_distance )
6150 distance = CUR.GS.minimum_distance;
6151 }
6152 else
6153 {
6154 if ( distance > -CUR.GS.minimum_distance )
6155 distance = -CUR.GS.minimum_distance;
6156 }
6157 }
6158
6159 /* now move the point */
6160
6161 org_dist = CUR_Func_project( CUR.zp1.cur + point,
6162 CUR.zp0.cur + CUR.GS.rp0 );
6163
6164 CUR_Func_move( &CUR.zp1, point, distance - org_dist );
6165
Werner Lembergd6a213f2011-01-31 18:51:07 +01006166 Fail:
David Turnerd2b1f351999-12-16 23:11:37 +00006167 CUR.GS.rp1 = CUR.GS.rp0;
6168 CUR.GS.rp2 = point;
6169
Werner Lemberg78575dc2000-06-12 19:36:41 +00006170 if ( ( CUR.opcode & 16 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00006171 CUR.GS.rp0 = point;
6172 }
6173
6174
6175 /*************************************************************************/
6176 /* */
6177 /* MIRP[abcde]: Move Indirect Relative Point */
6178 /* Opcode range: 0xE0-0xFF */
6179 /* Stack: int32? uint32 --> */
6180 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006181 static void
6182 Ins_MIRP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00006183 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006184 FT_UShort point;
6185 FT_ULong cvtEntry;
David Turnerd2b1f351999-12-16 23:11:37 +00006186
David Turnerf9b8dec2000-06-16 19:34:52 +00006187 FT_F26Dot6 cvt_dist,
David Turnerd2b1f351999-12-16 23:11:37 +00006188 distance,
6189 cur_dist,
6190 org_dist;
6191
6192
David Turnerf9b8dec2000-06-16 19:34:52 +00006193 point = (FT_UShort)args[0];
6194 cvtEntry = (FT_ULong)( args[1] + 1 );
David Turnerd2b1f351999-12-16 23:11:37 +00006195
6196 /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
6197
6198 if ( BOUNDS( point, CUR.zp1.n_points ) ||
Werner Lemberg346f1862010-08-06 00:47:57 +02006199 BOUNDSL( cvtEntry, CUR.cvtSize + 1 ) ||
David Turnerd2b1f351999-12-16 23:11:37 +00006200 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
6201 {
6202 if ( CUR.pedantic_hinting )
6203 CUR.error = TT_Err_Invalid_Reference;
Werner Lembergd6a213f2011-01-31 18:51:07 +01006204 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00006205 }
6206
6207 if ( !cvtEntry )
6208 cvt_dist = 0;
6209 else
6210 cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
6211
6212 /* single width test */
6213
Werner Lembergdfa46192004-03-05 09:26:24 +00006214 if ( FT_ABS( cvt_dist - CUR.GS.single_width_value ) <
Werner Lemberg6e9b3182003-06-10 10:54:33 +00006215 CUR.GS.single_width_cutin )
David Turnerd2b1f351999-12-16 23:11:37 +00006216 {
6217 if ( cvt_dist >= 0 )
6218 cvt_dist = CUR.GS.single_width_value;
6219 else
6220 cvt_dist = -CUR.GS.single_width_value;
6221 }
6222
6223 /* XXX: UNDOCUMENTED! -- twilight zone */
6224
6225 if ( CUR.GS.gep1 == 0 )
6226 {
6227 CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
suzuki toshiya6dc27522009-08-01 00:32:15 +09006228 TT_MulFix14( (FT_UInt32)cvt_dist,
6229 CUR.GS.freeVector.x );
David Turnerd2b1f351999-12-16 23:11:37 +00006230
6231 CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +
suzuki toshiya6dc27522009-08-01 00:32:15 +09006232 TT_MulFix14( (FT_UInt32)cvt_dist,
6233 CUR.GS.freeVector.y );
David Turnerd2b1f351999-12-16 23:11:37 +00006234
David Turner2c4500e2007-02-14 15:08:47 +00006235 CUR.zp1.cur[point] = CUR.zp0.cur[point];
David Turnerd2b1f351999-12-16 23:11:37 +00006236 }
6237
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00006238 org_dist = CUR_Func_dualproj( &CUR.zp1.org[point],
6239 &CUR.zp0.org[CUR.GS.rp0] );
6240 cur_dist = CUR_Func_project ( &CUR.zp1.cur[point],
6241 &CUR.zp0.cur[CUR.GS.rp0] );
David Turnerd2b1f351999-12-16 23:11:37 +00006242
6243 /* auto-flip test */
6244
6245 if ( CUR.GS.auto_flip )
6246 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00006247 if ( ( org_dist ^ cvt_dist ) < 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00006248 cvt_dist = -cvt_dist;
6249 }
6250
6251 /* control value cutin and round */
6252
Werner Lemberg78575dc2000-06-12 19:36:41 +00006253 if ( ( CUR.opcode & 4 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00006254 {
6255 /* XXX: UNDOCUMENTED! Only perform cut-in test when both points */
6256 /* refer to the same zone. */
6257
6258 if ( CUR.GS.gep0 == CUR.GS.gep1 )
Werner Lembergdcdb3162011-01-18 07:35:26 +01006259 {
6260 /* XXX: According to Greg Hitchcock, the following wording is */
6261 /* the right one: */
6262 /* */
6263 /* When the absolute difference between the value in */
6264 /* the table [CVT] and the measurement directly from */
6265 /* the outline is _greater_ than the cut_in value, the */
6266 /* outline measurement is used. */
6267 /* */
6268 /* This is from `instgly.doc'. The description in */
6269 /* `ttinst2.doc', version 1.66, is thus incorrect since */
6270 /* it implies `>=' instead of `>'. */
6271
6272 if ( FT_ABS( cvt_dist - org_dist ) > CUR.GS.control_value_cutin )
David Turnerd2b1f351999-12-16 23:11:37 +00006273 cvt_dist = org_dist;
Werner Lembergdcdb3162011-01-18 07:35:26 +01006274 }
David Turnerd2b1f351999-12-16 23:11:37 +00006275
Werner Lemberg78575dc2000-06-12 19:36:41 +00006276 distance = CUR_Func_round(
6277 cvt_dist,
6278 CUR.tt_metrics.compensations[CUR.opcode & 3] );
David Turnerd2b1f351999-12-16 23:11:37 +00006279 }
6280 else
Werner Lemberg78575dc2000-06-12 19:36:41 +00006281 distance = ROUND_None(
6282 cvt_dist,
6283 CUR.tt_metrics.compensations[CUR.opcode & 3] );
David Turnerd2b1f351999-12-16 23:11:37 +00006284
6285 /* minimum distance test */
6286
Werner Lemberg78575dc2000-06-12 19:36:41 +00006287 if ( ( CUR.opcode & 8 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00006288 {
6289 if ( org_dist >= 0 )
6290 {
6291 if ( distance < CUR.GS.minimum_distance )
6292 distance = CUR.GS.minimum_distance;
6293 }
6294 else
6295 {
6296 if ( distance > -CUR.GS.minimum_distance )
6297 distance = -CUR.GS.minimum_distance;
6298 }
6299 }
6300
6301 CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
6302
Werner Lembergd6a213f2011-01-31 18:51:07 +01006303 Fail:
David Turnerd2b1f351999-12-16 23:11:37 +00006304 CUR.GS.rp1 = CUR.GS.rp0;
6305
Werner Lemberg78575dc2000-06-12 19:36:41 +00006306 if ( ( CUR.opcode & 16 ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00006307 CUR.GS.rp0 = point;
6308
6309 /* XXX: UNDOCUMENTED! */
David Turnerd2b1f351999-12-16 23:11:37 +00006310 CUR.GS.rp2 = point;
6311 }
6312
6313
6314 /*************************************************************************/
6315 /* */
6316 /* ALIGNRP[]: ALIGN Relative Point */
6317 /* Opcode range: 0x3C */
6318 /* Stack: uint32 uint32... --> */
6319 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006320 static void
6321 Ins_ALIGNRP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00006322 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006323 FT_UShort point;
6324 FT_F26Dot6 distance;
David Turnerd2b1f351999-12-16 23:11:37 +00006325
David Turnerc6a92202000-07-04 18:12:13 +00006326 FT_UNUSED_ARG;
David Turnerd2b1f351999-12-16 23:11:37 +00006327
Werner Lemberg78575dc2000-06-12 19:36:41 +00006328
David Turnerd2b1f351999-12-16 23:11:37 +00006329 if ( CUR.top < CUR.GS.loop ||
6330 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
6331 {
6332 if ( CUR.pedantic_hinting )
6333 CUR.error = TT_Err_Invalid_Reference;
Werner Lembergd6a213f2011-01-31 18:51:07 +01006334 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00006335 }
6336
6337 while ( CUR.GS.loop > 0 )
6338 {
6339 CUR.args--;
6340
David Turnerf9b8dec2000-06-16 19:34:52 +00006341 point = (FT_UShort)CUR.stack[CUR.args];
David Turnerd2b1f351999-12-16 23:11:37 +00006342
6343 if ( BOUNDS( point, CUR.zp1.n_points ) )
6344 {
6345 if ( CUR.pedantic_hinting )
6346 {
6347 CUR.error = TT_Err_Invalid_Reference;
6348 return;
6349 }
6350 }
6351 else
6352 {
6353 distance = CUR_Func_project( CUR.zp1.cur + point,
6354 CUR.zp0.cur + CUR.GS.rp0 );
6355
6356 CUR_Func_move( &CUR.zp1, point, -distance );
6357 }
6358
6359 CUR.GS.loop--;
6360 }
6361
Werner Lembergd6a213f2011-01-31 18:51:07 +01006362 Fail:
David Turnerd2b1f351999-12-16 23:11:37 +00006363 CUR.GS.loop = 1;
6364 CUR.new_top = CUR.args;
6365 }
6366
6367
6368 /*************************************************************************/
6369 /* */
6370 /* ISECT[]: moves point to InterSECTion */
6371 /* Opcode range: 0x0F */
6372 /* Stack: 5 * uint32 --> */
6373 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006374 static void
6375 Ins_ISECT( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00006376 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006377 FT_UShort point,
David Turnerd2b1f351999-12-16 23:11:37 +00006378 a0, a1,
6379 b0, b1;
6380
David Turnerf9b8dec2000-06-16 19:34:52 +00006381 FT_F26Dot6 discriminant;
David Turnerd2b1f351999-12-16 23:11:37 +00006382
David Turnerf9b8dec2000-06-16 19:34:52 +00006383 FT_F26Dot6 dx, dy,
David Turnerd2b1f351999-12-16 23:11:37 +00006384 dax, day,
6385 dbx, dby;
6386
David Turnerf9b8dec2000-06-16 19:34:52 +00006387 FT_F26Dot6 val;
David Turnerd2b1f351999-12-16 23:11:37 +00006388
David Turnerf9b8dec2000-06-16 19:34:52 +00006389 FT_Vector R;
David Turnerd2b1f351999-12-16 23:11:37 +00006390
6391
David Turnerf9b8dec2000-06-16 19:34:52 +00006392 point = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00006393
David Turnerf9b8dec2000-06-16 19:34:52 +00006394 a0 = (FT_UShort)args[1];
6395 a1 = (FT_UShort)args[2];
6396 b0 = (FT_UShort)args[3];
6397 b1 = (FT_UShort)args[4];
David Turnerd2b1f351999-12-16 23:11:37 +00006398
6399 if ( BOUNDS( b0, CUR.zp0.n_points ) ||
6400 BOUNDS( b1, CUR.zp0.n_points ) ||
6401 BOUNDS( a0, CUR.zp1.n_points ) ||
6402 BOUNDS( a1, CUR.zp1.n_points ) ||
6403 BOUNDS( point, CUR.zp2.n_points ) )
6404 {
6405 if ( CUR.pedantic_hinting )
6406 CUR.error = TT_Err_Invalid_Reference;
6407 return;
6408 }
6409
6410 dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
6411 dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
6412
6413 dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x;
6414 day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y;
6415
6416 dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x;
6417 dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y;
6418
David Turnerb08fe2d2002-08-27 20:20:29 +00006419 CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
David Turnerd2b1f351999-12-16 23:11:37 +00006420
6421 discriminant = TT_MULDIV( dax, -dby, 0x40 ) +
6422 TT_MULDIV( day, dbx, 0x40 );
6423
Werner Lembergdfa46192004-03-05 09:26:24 +00006424 if ( FT_ABS( discriminant ) >= 0x40 )
David Turnerd2b1f351999-12-16 23:11:37 +00006425 {
6426 val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );
6427
6428 R.x = TT_MULDIV( val, dax, discriminant );
6429 R.y = TT_MULDIV( val, day, discriminant );
6430
6431 CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;
6432 CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
6433 }
6434 else
6435 {
6436 /* else, take the middle of the middles of A and B */
6437
6438 CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x +
6439 CUR.zp1.cur[a1].x +
6440 CUR.zp0.cur[b0].x +
6441 CUR.zp0.cur[b1].x ) / 4;
6442 CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y +
6443 CUR.zp1.cur[a1].y +
6444 CUR.zp0.cur[b0].y +
6445 CUR.zp0.cur[b1].y ) / 4;
6446 }
6447 }
6448
6449
6450 /*************************************************************************/
6451 /* */
6452 /* ALIGNPTS[]: ALIGN PoinTS */
6453 /* Opcode range: 0x27 */
6454 /* Stack: uint32 uint32 --> */
6455 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006456 static void
6457 Ins_ALIGNPTS( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00006458 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006459 FT_UShort p1, p2;
6460 FT_F26Dot6 distance;
David Turnerd2b1f351999-12-16 23:11:37 +00006461
6462
David Turnerf9b8dec2000-06-16 19:34:52 +00006463 p1 = (FT_UShort)args[0];
6464 p2 = (FT_UShort)args[1];
David Turnerd2b1f351999-12-16 23:11:37 +00006465
Werner Lemberg346f1862010-08-06 00:47:57 +02006466 if ( BOUNDS( p1, CUR.zp1.n_points ) ||
6467 BOUNDS( p2, CUR.zp0.n_points ) )
David Turnerd2b1f351999-12-16 23:11:37 +00006468 {
6469 if ( CUR.pedantic_hinting )
6470 CUR.error = TT_Err_Invalid_Reference;
6471 return;
6472 }
6473
6474 distance = CUR_Func_project( CUR.zp0.cur + p2,
6475 CUR.zp1.cur + p1 ) / 2;
6476
6477 CUR_Func_move( &CUR.zp1, p1, distance );
6478 CUR_Func_move( &CUR.zp0, p2, -distance );
6479 }
6480
6481
6482 /*************************************************************************/
6483 /* */
6484 /* IP[]: Interpolate Point */
6485 /* Opcode range: 0x39 */
6486 /* Stack: uint32... --> */
6487 /* */
David Turner2c4500e2007-02-14 15:08:47 +00006488
6489 /* SOMETIMES, DUMBER CODE IS BETTER CODE */
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00006490
David Turner2c4500e2007-02-14 15:08:47 +00006491 static void
6492 Ins_IP( INS_ARG )
6493 {
6494 FT_F26Dot6 old_range, cur_range;
6495 FT_Vector* orus_base;
6496 FT_Vector* cur_base;
David Turner89020d92007-03-17 17:48:57 +00006497 FT_Int twilight;
David Turner2c4500e2007-02-14 15:08:47 +00006498
6499 FT_UNUSED_ARG;
6500
6501
6502 if ( CUR.top < CUR.GS.loop )
6503 {
Werner Lembergd6a213f2011-01-31 18:51:07 +01006504 if ( CUR.pedantic_hinting )
6505 CUR.error = TT_Err_Invalid_Reference;
6506 goto Fail;
David Turner2c4500e2007-02-14 15:08:47 +00006507 }
6508
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00006509 /*
David Turner89020d92007-03-17 17:48:57 +00006510 * We need to deal in a special way with the twilight zone.
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00006511 * Otherwise, by definition, the value of CUR.twilight.orus[n] is (0,0),
David Turner89020d92007-03-17 17:48:57 +00006512 * for every n.
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00006513 */
Werner Lembergc9f6c662007-03-21 13:30:14 +00006514 twilight = CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 || CUR.GS.gep2 == 0;
David Turner2c4500e2007-02-14 15:08:47 +00006515
Werner Lemberge12ed562007-06-17 05:31:23 +00006516 if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) )
David Turner815911a2007-06-16 17:07:20 +00006517 {
6518 if ( CUR.pedantic_hinting )
6519 CUR.error = TT_Err_Invalid_Reference;
Werner Lembergd6a213f2011-01-31 18:51:07 +01006520 goto Fail;
David Turner815911a2007-06-16 17:07:20 +00006521 }
6522
Werner Lembergc9f6c662007-03-21 13:30:14 +00006523 if ( twilight )
6524 orus_base = &CUR.zp0.org[CUR.GS.rp1];
David Turner89020d92007-03-17 17:48:57 +00006525 else
Werner Lembergc9f6c662007-03-21 13:30:14 +00006526 orus_base = &CUR.zp0.orus[CUR.GS.rp1];
David Turner89020d92007-03-17 17:48:57 +00006527
6528 cur_base = &CUR.zp0.cur[CUR.GS.rp1];
David Turner2c4500e2007-02-14 15:08:47 +00006529
Werner Lembergc9f6c662007-03-21 13:30:14 +00006530 /* XXX: There are some glyphs in some braindead but popular */
6531 /* fonts out there (e.g. [aeu]grave in monotype.ttf) */
6532 /* calling IP[] with bad values of rp[12]. */
6533 /* Do something sane when this odd thing happens. */
David Turner2c4500e2007-02-14 15:08:47 +00006534 if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ||
6535 BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) )
6536 {
6537 old_range = 0;
6538 cur_range = 0;
6539 }
6540 else
6541 {
Werner Lembergc9f6c662007-03-21 13:30:14 +00006542 if ( twilight )
6543 old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2],
6544 orus_base );
David Turner89020d92007-03-17 17:48:57 +00006545 else
Werner Lembergc9f6c662007-03-21 13:30:14 +00006546 old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2],
6547 orus_base );
David Turner89020d92007-03-17 17:48:57 +00006548
Werner Lembergc9f6c662007-03-21 13:30:14 +00006549 cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base );
David Turner2c4500e2007-02-14 15:08:47 +00006550 }
6551
6552 for ( ; CUR.GS.loop > 0; --CUR.GS.loop )
6553 {
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00006554 FT_UInt point = (FT_UInt)CUR.stack[--CUR.args];
David Turner2c4500e2007-02-14 15:08:47 +00006555 FT_F26Dot6 org_dist, cur_dist, new_dist;
6556
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00006557
David Turner2c4500e2007-02-14 15:08:47 +00006558 /* check point bounds */
6559 if ( BOUNDS( point, CUR.zp2.n_points ) )
6560 {
6561 if ( CUR.pedantic_hinting )
6562 {
6563 CUR.error = TT_Err_Invalid_Reference;
6564 return;
6565 }
6566 continue;
6567 }
6568
Werner Lembergc9f6c662007-03-21 13:30:14 +00006569 if ( twilight )
David Turner89020d92007-03-17 17:48:57 +00006570 org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base );
6571 else
6572 org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base );
6573
David Turner2c4500e2007-02-14 15:08:47 +00006574 cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base );
Werner Lembergd77e7222008-06-05 22:07:19 +00006575
6576 if ( org_dist )
6577 new_dist = ( old_range != 0 )
6578 ? TT_MULDIV( org_dist, cur_range, old_range )
6579 : cur_dist;
6580 else
6581 new_dist = 0;
David Turner2c4500e2007-02-14 15:08:47 +00006582
Werner Lemberg94be20e2007-05-09 20:02:55 +00006583 CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
David Turner2c4500e2007-02-14 15:08:47 +00006584 }
Werner Lembergd6a213f2011-01-31 18:51:07 +01006585
6586 Fail:
David Turner2c4500e2007-02-14 15:08:47 +00006587 CUR.GS.loop = 1;
6588 CUR.new_top = CUR.args;
6589 }
Werner Lemberg3cd6cc22007-02-16 08:10:17 +00006590
David Turnerd2b1f351999-12-16 23:11:37 +00006591
6592 /*************************************************************************/
6593 /* */
6594 /* UTP[a]: UnTouch Point */
6595 /* Opcode range: 0x29 */
6596 /* Stack: uint32 --> */
6597 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006598 static void
6599 Ins_UTP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00006600 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006601 FT_UShort point;
6602 FT_Byte mask;
David Turnerd2b1f351999-12-16 23:11:37 +00006603
6604
David Turnerf9b8dec2000-06-16 19:34:52 +00006605 point = (FT_UShort)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00006606
6607 if ( BOUNDS( point, CUR.zp0.n_points ) )
6608 {
6609 if ( CUR.pedantic_hinting )
6610 CUR.error = TT_Err_Invalid_Reference;
6611 return;
6612 }
6613
6614 mask = 0xFF;
6615
6616 if ( CUR.GS.freeVector.x != 0 )
David Turnerb08fe2d2002-08-27 20:20:29 +00006617 mask &= ~FT_CURVE_TAG_TOUCH_X;
David Turnerd2b1f351999-12-16 23:11:37 +00006618
6619 if ( CUR.GS.freeVector.y != 0 )
David Turnerb08fe2d2002-08-27 20:20:29 +00006620 mask &= ~FT_CURVE_TAG_TOUCH_Y;
David Turnerd2b1f351999-12-16 23:11:37 +00006621
David Turner41dbcbf2000-03-09 11:46:25 +00006622 CUR.zp0.tags[point] &= mask;
David Turnerd2b1f351999-12-16 23:11:37 +00006623 }
6624
6625
6626 /* Local variables for Ins_IUP: */
Werner Lemberg2b0b4222008-05-28 22:17:28 +00006627 typedef struct IUP_WorkerRec_
David Turnerd2b1f351999-12-16 23:11:37 +00006628 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006629 FT_Vector* orgs; /* original and current coordinate */
6630 FT_Vector* curs; /* arrays */
David Turner33f5f242006-08-16 16:50:55 +00006631 FT_Vector* orus;
David Turner815911a2007-06-16 17:07:20 +00006632 FT_UInt max_points;
David Turner33f5f242006-08-16 16:50:55 +00006633
6634 } IUP_WorkerRec, *IUP_Worker;
David Turnerd2b1f351999-12-16 23:11:37 +00006635
6636
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006637 static void
David Turner33f5f242006-08-16 16:50:55 +00006638 _iup_worker_shift( IUP_Worker worker,
6639 FT_UInt p1,
6640 FT_UInt p2,
6641 FT_UInt p )
David Turnerd2b1f351999-12-16 23:11:37 +00006642 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006643 FT_UInt i;
David Turner33f5f242006-08-16 16:50:55 +00006644 FT_F26Dot6 dx;
David Turnerd2b1f351999-12-16 23:11:37 +00006645
Werner Lemberg78575dc2000-06-12 19:36:41 +00006646
David Turner33f5f242006-08-16 16:50:55 +00006647 dx = worker->curs[p].x - worker->orgs[p].x;
6648 if ( dx != 0 )
6649 {
6650 for ( i = p1; i < p; i++ )
6651 worker->curs[i].x += dx;
David Turnerd2b1f351999-12-16 23:11:37 +00006652
David Turner33f5f242006-08-16 16:50:55 +00006653 for ( i = p + 1; i <= p2; i++ )
6654 worker->curs[i].x += dx;
6655 }
David Turnerd2b1f351999-12-16 23:11:37 +00006656 }
6657
6658
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006659 static void
David Turner33f5f242006-08-16 16:50:55 +00006660 _iup_worker_interpolate( IUP_Worker worker,
6661 FT_UInt p1,
6662 FT_UInt p2,
6663 FT_UInt ref1,
6664 FT_UInt ref2 )
David Turnerd2b1f351999-12-16 23:11:37 +00006665 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006666 FT_UInt i;
David Turner33f5f242006-08-16 16:50:55 +00006667 FT_F26Dot6 orus1, orus2, org1, org2, delta1, delta2;
David Turnerd2b1f351999-12-16 23:11:37 +00006668
Werner Lemberg78575dc2000-06-12 19:36:41 +00006669
David Turnerd2b1f351999-12-16 23:11:37 +00006670 if ( p1 > p2 )
6671 return;
6672
Werner Lemberge12ed562007-06-17 05:31:23 +00006673 if ( BOUNDS( ref1, worker->max_points ) ||
6674 BOUNDS( ref2, worker->max_points ) )
David Turner815911a2007-06-16 17:07:20 +00006675 return;
6676
David Turner33f5f242006-08-16 16:50:55 +00006677 orus1 = worker->orus[ref1].x;
6678 orus2 = worker->orus[ref2].x;
David Turnerd2b1f351999-12-16 23:11:37 +00006679
Werner Lemberg12342992006-08-19 11:18:09 +00006680 if ( orus1 > orus2 )
David Turnerd2b1f351999-12-16 23:11:37 +00006681 {
David Turner33f5f242006-08-16 16:50:55 +00006682 FT_F26Dot6 tmp_o;
6683 FT_UInt tmp_r;
David Turnerd2b1f351999-12-16 23:11:37 +00006684
Werner Lemberg12342992006-08-19 11:18:09 +00006685
6686 tmp_o = orus1;
6687 orus1 = orus2;
6688 orus2 = tmp_o;
6689
6690 tmp_r = ref1;
6691 ref1 = ref2;
6692 ref2 = tmp_r;
David Turnerd2b1f351999-12-16 23:11:37 +00006693 }
6694
David Turner33f5f242006-08-16 16:50:55 +00006695 org1 = worker->orgs[ref1].x;
6696 org2 = worker->orgs[ref2].x;
6697 delta1 = worker->curs[ref1].x - org1;
6698 delta2 = worker->curs[ref2].x - org2;
6699
6700 if ( orus1 == orus2 )
David Turnerd2b1f351999-12-16 23:11:37 +00006701 {
David Turner33f5f242006-08-16 16:50:55 +00006702 /* simple shift of untouched points */
David Turnerd2b1f351999-12-16 23:11:37 +00006703 for ( i = p1; i <= p2; i++ )
6704 {
David Turner33f5f242006-08-16 16:50:55 +00006705 FT_F26Dot6 x = worker->orgs[i].x;
David Turnerd2b1f351999-12-16 23:11:37 +00006706
Werner Lemberg12342992006-08-19 11:18:09 +00006707
David Turner33f5f242006-08-16 16:50:55 +00006708 if ( x <= org1 )
6709 x += delta1;
6710 else
6711 x += delta2;
6712
6713 worker->curs[i].x = x;
6714 }
6715 }
6716 else
6717 {
6718 FT_Fixed scale = 0;
6719 FT_Bool scale_valid = 0;
6720
Werner Lemberg12342992006-08-19 11:18:09 +00006721
David Turner33f5f242006-08-16 16:50:55 +00006722 /* interpolation */
6723 for ( i = p1; i <= p2; i++ )
6724 {
6725 FT_F26Dot6 x = worker->orgs[i].x;
6726
Werner Lemberg12342992006-08-19 11:18:09 +00006727
David Turner33f5f242006-08-16 16:50:55 +00006728 if ( x <= org1 )
6729 x += delta1;
6730
6731 else if ( x >= org2 )
6732 x += delta2;
6733
David Turnerd2b1f351999-12-16 23:11:37 +00006734 else
6735 {
David Turner33f5f242006-08-16 16:50:55 +00006736 if ( !scale_valid )
6737 {
6738 scale_valid = 1;
Werner Lemberg12342992006-08-19 11:18:09 +00006739 scale = TT_MULDIV( org2 + delta2 - ( org1 + delta1 ),
Werner Lemberg1a5d5612008-11-29 22:50:24 +00006740 0x10000L, orus2 - orus1 );
David Turner33f5f242006-08-16 16:50:55 +00006741 }
6742
Werner Lemberg12342992006-08-19 11:18:09 +00006743 x = ( org1 + delta1 ) +
6744 TT_MULFIX( worker->orus[i].x - orus1, scale );
David Turnerd2b1f351999-12-16 23:11:37 +00006745 }
David Turner33f5f242006-08-16 16:50:55 +00006746 worker->curs[i].x = x;
David Turnerd2b1f351999-12-16 23:11:37 +00006747 }
David Turnerd2b1f351999-12-16 23:11:37 +00006748 }
6749 }
6750
6751
6752 /*************************************************************************/
6753 /* */
6754 /* IUP[a]: Interpolate Untouched Points */
6755 /* Opcode range: 0x30-0x31 */
6756 /* Stack: --> */
6757 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006758 static void
6759 Ins_IUP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00006760 {
David Turner33f5f242006-08-16 16:50:55 +00006761 IUP_WorkerRec V;
6762 FT_Byte mask;
David Turnerd2b1f351999-12-16 23:11:37 +00006763
David Turnerf9b8dec2000-06-16 19:34:52 +00006764 FT_UInt first_point; /* first point of contour */
6765 FT_UInt end_point; /* end point (last+1) of contour */
David Turnerd2b1f351999-12-16 23:11:37 +00006766
David Turnerf9b8dec2000-06-16 19:34:52 +00006767 FT_UInt first_touched; /* first touched point in contour */
6768 FT_UInt cur_touched; /* current touched point in contour */
David Turnerd2b1f351999-12-16 23:11:37 +00006769
David Turnerf9b8dec2000-06-16 19:34:52 +00006770 FT_UInt point; /* current point */
6771 FT_Short contour; /* current contour */
David Turnerd2b1f351999-12-16 23:11:37 +00006772
David Turnerc6a92202000-07-04 18:12:13 +00006773 FT_UNUSED_ARG;
David Turnerd2b1f351999-12-16 23:11:37 +00006774
Werner Lemberge12ed562007-06-17 05:31:23 +00006775
David Turner815911a2007-06-16 17:07:20 +00006776 /* ignore empty outlines */
6777 if ( CUR.pts.n_contours == 0 )
6778 return;
Werner Lemberg78575dc2000-06-12 19:36:41 +00006779
David Turnerd2b1f351999-12-16 23:11:37 +00006780 if ( CUR.opcode & 1 )
6781 {
David Turnerb08fe2d2002-08-27 20:20:29 +00006782 mask = FT_CURVE_TAG_TOUCH_X;
David Turnerd2b1f351999-12-16 23:11:37 +00006783 V.orgs = CUR.pts.org;
6784 V.curs = CUR.pts.cur;
David Turner33f5f242006-08-16 16:50:55 +00006785 V.orus = CUR.pts.orus;
David Turnerd2b1f351999-12-16 23:11:37 +00006786 }
6787 else
6788 {
David Turnerb08fe2d2002-08-27 20:20:29 +00006789 mask = FT_CURVE_TAG_TOUCH_Y;
David Turner43a2f652000-07-05 18:23:38 +00006790 V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
6791 V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
David Turner33f5f242006-08-16 16:50:55 +00006792 V.orus = (FT_Vector*)( (FT_Pos*)CUR.pts.orus + 1 );
David Turnerd2b1f351999-12-16 23:11:37 +00006793 }
David Turner74cc0e92007-06-30 22:54:12 +00006794 V.max_points = CUR.pts.n_points;
David Turnerd2b1f351999-12-16 23:11:37 +00006795
6796 contour = 0;
6797 point = 0;
6798
6799 do
6800 {
Werner Lemberga2da05c2006-06-25 06:27:27 +00006801 end_point = CUR.pts.contours[contour] - CUR.pts.first_point;
David Turnerd2b1f351999-12-16 23:11:37 +00006802 first_point = point;
6803
Werner Lemberg888cd182010-07-08 07:29:42 +02006804 if ( BOUNDS ( end_point, CUR.pts.n_points ) )
6805 end_point = CUR.pts.n_points - 1;
Werner Lemberg28464c42008-02-18 20:34:42 +00006806
Werner Lembergc9f6c662007-03-21 13:30:14 +00006807 while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00006808 point++;
6809
6810 if ( point <= end_point )
6811 {
6812 first_touched = point;
6813 cur_touched = point;
6814
6815 point++;
6816
6817 while ( point <= end_point )
6818 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00006819 if ( ( CUR.pts.tags[point] & mask ) != 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00006820 {
Werner Lemberg5220ef52010-09-13 07:32:22 +02006821 _iup_worker_interpolate( &V,
6822 cur_touched + 1,
6823 point - 1,
6824 cur_touched,
6825 point );
David Turnerd2b1f351999-12-16 23:11:37 +00006826 cur_touched = point;
6827 }
6828
6829 point++;
6830 }
6831
6832 if ( cur_touched == first_touched )
David Turner33f5f242006-08-16 16:50:55 +00006833 _iup_worker_shift( &V, first_point, end_point, cur_touched );
David Turnerd2b1f351999-12-16 23:11:37 +00006834 else
6835 {
David Turner33f5f242006-08-16 16:50:55 +00006836 _iup_worker_interpolate( &V,
6837 (FT_UShort)( cur_touched + 1 ),
6838 end_point,
6839 cur_touched,
6840 first_touched );
David Turnerd2b1f351999-12-16 23:11:37 +00006841
6842 if ( first_touched > 0 )
David Turner33f5f242006-08-16 16:50:55 +00006843 _iup_worker_interpolate( &V,
6844 first_point,
6845 first_touched - 1,
6846 cur_touched,
6847 first_touched );
David Turnerd2b1f351999-12-16 23:11:37 +00006848 }
6849 }
6850 contour++;
6851 } while ( contour < CUR.pts.n_contours );
6852 }
6853
6854
6855 /*************************************************************************/
6856 /* */
6857 /* DELTAPn[]: DELTA exceptions P1, P2, P3 */
6858 /* Opcode range: 0x5D,0x71,0x72 */
6859 /* Stack: uint32 (2 * uint32)... --> */
6860 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006861 static void
6862 Ins_DELTAP( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00006863 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006864 FT_ULong k, nump;
6865 FT_UShort A;
6866 FT_ULong C;
6867 FT_Long B;
David Turnerd2b1f351999-12-16 23:11:37 +00006868
Werner Lemberg82ee38e2006-11-20 09:19:26 +00006869
David Turner8b6db862003-08-17 22:09:14 +00006870#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Graham Asher3ea859f2003-04-25 11:40:46 +00006871 /* Delta hinting is covered by US Patent 5159668. */
6872 if ( CUR.face->unpatented_hinting )
Werner Lemberg82ee38e2006-11-20 09:19:26 +00006873 {
6874 FT_Long n = args[0] * 2;
6875
6876
Graham Asher3ea859f2003-04-25 11:40:46 +00006877 if ( CUR.args < n )
6878 {
Werner Lemberg96f04562011-01-31 10:24:32 +01006879 if ( CUR.pedantic_hinting )
6880 CUR.error = TT_Err_Too_Few_Arguments;
6881 n = CUR.args;
Graham Asher3ea859f2003-04-25 11:40:46 +00006882 }
6883
Werner Lemberga3f4da82003-04-29 13:23:47 +00006884 CUR.args -= n;
Graham Asher3ea859f2003-04-25 11:40:46 +00006885 CUR.new_top = CUR.args;
6886 return;
6887 }
6888#endif
David Turnerd2b1f351999-12-16 23:11:37 +00006889
David Turnerf9b8dec2000-06-16 19:34:52 +00006890 nump = (FT_ULong)args[0]; /* some points theoretically may occur more
David Turnerd2b1f351999-12-16 23:11:37 +00006891 than once, thus UShort isn't enough */
6892
6893 for ( k = 1; k <= nump; k++ )
6894 {
6895 if ( CUR.args < 2 )
6896 {
Werner Lemberg96f04562011-01-31 10:24:32 +01006897 if ( CUR.pedantic_hinting )
6898 CUR.error = TT_Err_Too_Few_Arguments;
6899 CUR.args = 0;
6900 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00006901 }
6902
6903 CUR.args -= 2;
6904
David Turnerf9b8dec2000-06-16 19:34:52 +00006905 A = (FT_UShort)CUR.stack[CUR.args + 1];
David Turnerd2b1f351999-12-16 23:11:37 +00006906 B = CUR.stack[CUR.args];
6907
Werner Lemberg78575dc2000-06-12 19:36:41 +00006908 /* XXX: Because some popular fonts contain some invalid DeltaP */
6909 /* instructions, we simply ignore them when the stacked */
6910 /* point reference is off limit, rather than returning an */
6911 /* error. As a delta instruction doesn't change a glyph */
6912 /* in great ways, this shouldn't be a problem. */
David Turnerd2b1f351999-12-16 23:11:37 +00006913
6914 if ( !BOUNDS( A, CUR.zp0.n_points ) )
6915 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006916 C = ( (FT_ULong)B & 0xF0 ) >> 4;
David Turnerd2b1f351999-12-16 23:11:37 +00006917
6918 switch ( CUR.opcode )
6919 {
6920 case 0x5D:
6921 break;
6922
6923 case 0x71:
6924 C += 16;
6925 break;
6926
6927 case 0x72:
6928 C += 32;
6929 break;
6930 }
6931
6932 C += CUR.GS.delta_base;
6933
David Turnerf9b8dec2000-06-16 19:34:52 +00006934 if ( CURRENT_Ppem() == (FT_Long)C )
David Turnerd2b1f351999-12-16 23:11:37 +00006935 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006936 B = ( (FT_ULong)B & 0xF ) - 8;
David Turnerd2b1f351999-12-16 23:11:37 +00006937 if ( B >= 0 )
6938 B++;
Werner Lemberg78575dc2000-06-12 19:36:41 +00006939 B = B * 64 / ( 1L << CUR.GS.delta_shift );
David Turnerd2b1f351999-12-16 23:11:37 +00006940
6941 CUR_Func_move( &CUR.zp0, A, B );
6942 }
6943 }
6944 else
6945 if ( CUR.pedantic_hinting )
6946 CUR.error = TT_Err_Invalid_Reference;
6947 }
6948
Werner Lemberg96f04562011-01-31 10:24:32 +01006949 Fail:
David Turnerd2b1f351999-12-16 23:11:37 +00006950 CUR.new_top = CUR.args;
6951 }
6952
6953
6954 /*************************************************************************/
6955 /* */
6956 /* DELTACn[]: DELTA exceptions C1, C2, C3 */
6957 /* Opcode range: 0x73,0x74,0x75 */
6958 /* Stack: uint32 (2 * uint32)... --> */
6959 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00006960 static void
6961 Ins_DELTAC( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00006962 {
David Turnerf9b8dec2000-06-16 19:34:52 +00006963 FT_ULong nump, k;
6964 FT_ULong A, C;
6965 FT_Long B;
David Turnerd2b1f351999-12-16 23:11:37 +00006966
Werner Lemberga3f4da82003-04-29 13:23:47 +00006967
David Turner8b6db862003-08-17 22:09:14 +00006968#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
Graham Asher3ea859f2003-04-25 11:40:46 +00006969 /* Delta hinting is covered by US Patent 5159668. */
6970 if ( CUR.face->unpatented_hinting )
Werner Lemberga3f4da82003-04-29 13:23:47 +00006971 {
6972 FT_Long n = args[0] * 2;
6973
6974
Graham Asher3ea859f2003-04-25 11:40:46 +00006975 if ( CUR.args < n )
6976 {
Werner Lemberg96f04562011-01-31 10:24:32 +01006977 if ( CUR.pedantic_hinting )
6978 CUR.error = TT_Err_Too_Few_Arguments;
6979 n = CUR.args;
Graham Asher3ea859f2003-04-25 11:40:46 +00006980 }
6981
Werner Lemberga3f4da82003-04-29 13:23:47 +00006982 CUR.args -= n;
Graham Asher3ea859f2003-04-25 11:40:46 +00006983 CUR.new_top = CUR.args;
6984 return;
6985 }
6986#endif
David Turnerd2b1f351999-12-16 23:11:37 +00006987
David Turnerf9b8dec2000-06-16 19:34:52 +00006988 nump = (FT_ULong)args[0];
David Turnerd2b1f351999-12-16 23:11:37 +00006989
6990 for ( k = 1; k <= nump; k++ )
6991 {
6992 if ( CUR.args < 2 )
6993 {
Werner Lemberg96f04562011-01-31 10:24:32 +01006994 if ( CUR.pedantic_hinting )
6995 CUR.error = TT_Err_Too_Few_Arguments;
6996 CUR.args = 0;
6997 goto Fail;
David Turnerd2b1f351999-12-16 23:11:37 +00006998 }
6999
7000 CUR.args -= 2;
7001
David Turnerf9b8dec2000-06-16 19:34:52 +00007002 A = (FT_ULong)CUR.stack[CUR.args + 1];
David Turnerd2b1f351999-12-16 23:11:37 +00007003 B = CUR.stack[CUR.args];
7004
Werner Lemberg346f1862010-08-06 00:47:57 +02007005 if ( BOUNDSL( A, CUR.cvtSize ) )
David Turnerd2b1f351999-12-16 23:11:37 +00007006 {
Werner Lemberg78575dc2000-06-12 19:36:41 +00007007 if ( CUR.pedantic_hinting )
David Turnerd2b1f351999-12-16 23:11:37 +00007008 {
7009 CUR.error = TT_Err_Invalid_Reference;
7010 return;
7011 }
7012 }
7013 else
7014 {
David Turnerf9b8dec2000-06-16 19:34:52 +00007015 C = ( (FT_ULong)B & 0xF0 ) >> 4;
David Turnerd2b1f351999-12-16 23:11:37 +00007016
7017 switch ( CUR.opcode )
7018 {
7019 case 0x73:
7020 break;
7021
7022 case 0x74:
7023 C += 16;
7024 break;
7025
7026 case 0x75:
7027 C += 32;
7028 break;
7029 }
7030
7031 C += CUR.GS.delta_base;
7032
David Turnerf9b8dec2000-06-16 19:34:52 +00007033 if ( CURRENT_Ppem() == (FT_Long)C )
David Turnerd2b1f351999-12-16 23:11:37 +00007034 {
David Turnerf9b8dec2000-06-16 19:34:52 +00007035 B = ( (FT_ULong)B & 0xF ) - 8;
David Turnerd2b1f351999-12-16 23:11:37 +00007036 if ( B >= 0 )
7037 B++;
Werner Lemberg78575dc2000-06-12 19:36:41 +00007038 B = B * 64 / ( 1L << CUR.GS.delta_shift );
David Turnerd2b1f351999-12-16 23:11:37 +00007039
7040 CUR_Func_move_cvt( A, B );
7041 }
7042 }
7043 }
7044
Werner Lemberg96f04562011-01-31 10:24:32 +01007045 Fail:
David Turnerd2b1f351999-12-16 23:11:37 +00007046 CUR.new_top = CUR.args;
7047 }
7048
7049
7050 /*************************************************************************/
7051 /* */
7052 /* MISC. INSTRUCTIONS */
7053 /* */
7054 /*************************************************************************/
7055
7056
7057 /*************************************************************************/
7058 /* */
7059 /* GETINFO[]: GET INFOrmation */
7060 /* Opcode range: 0x88 */
7061 /* Stack: uint32 --> uint32 */
7062 /* */
Werner Lemberg4a2305c2001-06-28 07:17:51 +00007063 static void
7064 Ins_GETINFO( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00007065 {
David Turnerf9b8dec2000-06-16 19:34:52 +00007066 FT_Long K;
David Turnerd2b1f351999-12-16 23:11:37 +00007067
7068
7069 K = 0;
7070
Werner Lembergdea712b2004-08-07 15:08:33 +00007071 /* We return MS rasterizer version 1.7 for the font scaler. */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007072 if ( ( args[0] & 1 ) != 0 )
Werner Lembergdea712b2004-08-07 15:08:33 +00007073 K = 35;
David Turnerd2b1f351999-12-16 23:11:37 +00007074
Werner Lembergdea712b2004-08-07 15:08:33 +00007075 /* Has the glyph been rotated? */
7076 if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated )
David Turnerd2b1f351999-12-16 23:11:37 +00007077 K |= 0x80;
7078
Werner Lembergdea712b2004-08-07 15:08:33 +00007079 /* Has the glyph been stretched? */
7080 if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched )
7081 K |= 1 << 8;
7082
7083 /* Are we hinting for grayscale? */
7084 if ( ( args[0] & 32 ) != 0 && CUR.grayscale )
Werner Lemberg2bad8ff2006-11-22 09:37:03 +00007085 K |= 1 << 12;
David Turnerd2b1f351999-12-16 23:11:37 +00007086
7087 args[0] = K;
7088 }
7089
7090
Werner Lemberg4a2305c2001-06-28 07:17:51 +00007091 static void
7092 Ins_UNKNOWN( INS_ARG )
David Turnerd2b1f351999-12-16 23:11:37 +00007093 {
7094 TT_DefRecord* def = CUR.IDefs;
7095 TT_DefRecord* limit = def + CUR.numIDefs;
David Turnere49ab252000-05-16 23:44:38 +00007096
David Turnerc6a92202000-07-04 18:12:13 +00007097 FT_UNUSED_ARG;
David Turnere49ab252000-05-16 23:44:38 +00007098
Werner Lemberg78575dc2000-06-12 19:36:41 +00007099
David Turnerd2b1f351999-12-16 23:11:37 +00007100 for ( ; def < limit; def++ )
7101 {
David Turnerb1aabf42000-11-30 23:48:22 +00007102 if ( (FT_Byte)def->opc == CUR.opcode && def->active )
David Turnerd2b1f351999-12-16 23:11:37 +00007103 {
7104 TT_CallRec* call;
David Turnere49ab252000-05-16 23:44:38 +00007105
Werner Lemberg78575dc2000-06-12 19:36:41 +00007106
David Turnerd2b1f351999-12-16 23:11:37 +00007107 if ( CUR.callTop >= CUR.callSize )
7108 {
7109 CUR.error = TT_Err_Stack_Overflow;
7110 return;
7111 }
David Turnere49ab252000-05-16 23:44:38 +00007112
David Turnerd2b1f351999-12-16 23:11:37 +00007113 call = CUR.callStack + CUR.callTop++;
7114
7115 call->Caller_Range = CUR.curRange;
Werner Lemberg462ddb42010-07-01 11:28:43 +02007116 call->Caller_IP = CUR.IP + 1;
David Turnerd2b1f351999-12-16 23:11:37 +00007117 call->Cur_Count = 1;
7118 call->Cur_Restart = def->start;
David Turnere49ab252000-05-16 23:44:38 +00007119
David Turnerd2b1f351999-12-16 23:11:37 +00007120 INS_Goto_CodeRange( def->range, def->start );
David Turnere49ab252000-05-16 23:44:38 +00007121
David Turnerd2b1f351999-12-16 23:11:37 +00007122 CUR.step_ins = FALSE;
7123 return;
7124 }
7125 }
7126
7127 CUR.error = TT_Err_Invalid_Opcode;
7128 }
7129
7130
7131#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
Werner Lemberg78575dc2000-06-12 19:36:41 +00007132
7133
David Turnerd2b1f351999-12-16 23:11:37 +00007134 static
7135 TInstruction_Function Instruct_Dispatch[256] =
7136 {
7137 /* Opcodes are gathered in groups of 16. */
7138 /* Please keep the spaces as they are. */
7139
7140 /* SVTCA y */ Ins_SVTCA,
7141 /* SVTCA x */ Ins_SVTCA,
7142 /* SPvTCA y */ Ins_SPVTCA,
7143 /* SPvTCA x */ Ins_SPVTCA,
7144 /* SFvTCA y */ Ins_SFVTCA,
7145 /* SFvTCA x */ Ins_SFVTCA,
7146 /* SPvTL // */ Ins_SPVTL,
7147 /* SPvTL + */ Ins_SPVTL,
7148 /* SFvTL // */ Ins_SFVTL,
7149 /* SFvTL + */ Ins_SFVTL,
7150 /* SPvFS */ Ins_SPVFS,
7151 /* SFvFS */ Ins_SFVFS,
7152 /* GPV */ Ins_GPV,
7153 /* GFV */ Ins_GFV,
7154 /* SFvTPv */ Ins_SFVTPV,
7155 /* ISECT */ Ins_ISECT,
7156
7157 /* SRP0 */ Ins_SRP0,
7158 /* SRP1 */ Ins_SRP1,
7159 /* SRP2 */ Ins_SRP2,
7160 /* SZP0 */ Ins_SZP0,
7161 /* SZP1 */ Ins_SZP1,
7162 /* SZP2 */ Ins_SZP2,
7163 /* SZPS */ Ins_SZPS,
7164 /* SLOOP */ Ins_SLOOP,
7165 /* RTG */ Ins_RTG,
7166 /* RTHG */ Ins_RTHG,
7167 /* SMD */ Ins_SMD,
7168 /* ELSE */ Ins_ELSE,
7169 /* JMPR */ Ins_JMPR,
7170 /* SCvTCi */ Ins_SCVTCI,
7171 /* SSwCi */ Ins_SSWCI,
7172 /* SSW */ Ins_SSW,
7173
7174 /* DUP */ Ins_DUP,
7175 /* POP */ Ins_POP,
7176 /* CLEAR */ Ins_CLEAR,
7177 /* SWAP */ Ins_SWAP,
7178 /* DEPTH */ Ins_DEPTH,
7179 /* CINDEX */ Ins_CINDEX,
7180 /* MINDEX */ Ins_MINDEX,
7181 /* AlignPTS */ Ins_ALIGNPTS,
7182 /* INS_0x28 */ Ins_UNKNOWN,
7183 /* UTP */ Ins_UTP,
7184 /* LOOPCALL */ Ins_LOOPCALL,
7185 /* CALL */ Ins_CALL,
7186 /* FDEF */ Ins_FDEF,
7187 /* ENDF */ Ins_ENDF,
7188 /* MDAP[0] */ Ins_MDAP,
7189 /* MDAP[1] */ Ins_MDAP,
7190
7191 /* IUP[0] */ Ins_IUP,
7192 /* IUP[1] */ Ins_IUP,
7193 /* SHP[0] */ Ins_SHP,
7194 /* SHP[1] */ Ins_SHP,
7195 /* SHC[0] */ Ins_SHC,
7196 /* SHC[1] */ Ins_SHC,
7197 /* SHZ[0] */ Ins_SHZ,
7198 /* SHZ[1] */ Ins_SHZ,
7199 /* SHPIX */ Ins_SHPIX,
7200 /* IP */ Ins_IP,
7201 /* MSIRP[0] */ Ins_MSIRP,
7202 /* MSIRP[1] */ Ins_MSIRP,
7203 /* AlignRP */ Ins_ALIGNRP,
7204 /* RTDG */ Ins_RTDG,
7205 /* MIAP[0] */ Ins_MIAP,
7206 /* MIAP[1] */ Ins_MIAP,
7207
7208 /* NPushB */ Ins_NPUSHB,
7209 /* NPushW */ Ins_NPUSHW,
7210 /* WS */ Ins_WS,
7211 /* RS */ Ins_RS,
7212 /* WCvtP */ Ins_WCVTP,
7213 /* RCvt */ Ins_RCVT,
7214 /* GC[0] */ Ins_GC,
7215 /* GC[1] */ Ins_GC,
7216 /* SCFS */ Ins_SCFS,
7217 /* MD[0] */ Ins_MD,
7218 /* MD[1] */ Ins_MD,
7219 /* MPPEM */ Ins_MPPEM,
7220 /* MPS */ Ins_MPS,
7221 /* FlipON */ Ins_FLIPON,
7222 /* FlipOFF */ Ins_FLIPOFF,
7223 /* DEBUG */ Ins_DEBUG,
7224
7225 /* LT */ Ins_LT,
7226 /* LTEQ */ Ins_LTEQ,
7227 /* GT */ Ins_GT,
7228 /* GTEQ */ Ins_GTEQ,
7229 /* EQ */ Ins_EQ,
7230 /* NEQ */ Ins_NEQ,
7231 /* ODD */ Ins_ODD,
7232 /* EVEN */ Ins_EVEN,
7233 /* IF */ Ins_IF,
7234 /* EIF */ Ins_EIF,
7235 /* AND */ Ins_AND,
7236 /* OR */ Ins_OR,
7237 /* NOT */ Ins_NOT,
7238 /* DeltaP1 */ Ins_DELTAP,
7239 /* SDB */ Ins_SDB,
7240 /* SDS */ Ins_SDS,
7241
7242 /* ADD */ Ins_ADD,
7243 /* SUB */ Ins_SUB,
7244 /* DIV */ Ins_DIV,
7245 /* MUL */ Ins_MUL,
7246 /* ABS */ Ins_ABS,
7247 /* NEG */ Ins_NEG,
7248 /* FLOOR */ Ins_FLOOR,
7249 /* CEILING */ Ins_CEILING,
7250 /* ROUND[0] */ Ins_ROUND,
7251 /* ROUND[1] */ Ins_ROUND,
7252 /* ROUND[2] */ Ins_ROUND,
7253 /* ROUND[3] */ Ins_ROUND,
7254 /* NROUND[0] */ Ins_NROUND,
7255 /* NROUND[1] */ Ins_NROUND,
7256 /* NROUND[2] */ Ins_NROUND,
7257 /* NROUND[3] */ Ins_NROUND,
7258
7259 /* WCvtF */ Ins_WCVTF,
7260 /* DeltaP2 */ Ins_DELTAP,
7261 /* DeltaP3 */ Ins_DELTAP,
7262 /* DeltaCn[0] */ Ins_DELTAC,
7263 /* DeltaCn[1] */ Ins_DELTAC,
7264 /* DeltaCn[2] */ Ins_DELTAC,
7265 /* SROUND */ Ins_SROUND,
7266 /* S45Round */ Ins_S45ROUND,
7267 /* JROT */ Ins_JROT,
7268 /* JROF */ Ins_JROF,
7269 /* ROFF */ Ins_ROFF,
7270 /* INS_0x7B */ Ins_UNKNOWN,
7271 /* RUTG */ Ins_RUTG,
7272 /* RDTG */ Ins_RDTG,
7273 /* SANGW */ Ins_SANGW,
7274 /* AA */ Ins_AA,
7275
7276 /* FlipPT */ Ins_FLIPPT,
7277 /* FlipRgON */ Ins_FLIPRGON,
7278 /* FlipRgOFF */ Ins_FLIPRGOFF,
7279 /* INS_0x83 */ Ins_UNKNOWN,
7280 /* INS_0x84 */ Ins_UNKNOWN,
7281 /* ScanCTRL */ Ins_SCANCTRL,
7282 /* SDPVTL[0] */ Ins_SDPVTL,
7283 /* SDPVTL[1] */ Ins_SDPVTL,
7284 /* GetINFO */ Ins_GETINFO,
7285 /* IDEF */ Ins_IDEF,
7286 /* ROLL */ Ins_ROLL,
7287 /* MAX */ Ins_MAX,
7288 /* MIN */ Ins_MIN,
7289 /* ScanTYPE */ Ins_SCANTYPE,
7290 /* InstCTRL */ Ins_INSTCTRL,
7291 /* INS_0x8F */ Ins_UNKNOWN,
7292
7293 /* INS_0x90 */ Ins_UNKNOWN,
7294 /* INS_0x91 */ Ins_UNKNOWN,
7295 /* INS_0x92 */ Ins_UNKNOWN,
7296 /* INS_0x93 */ Ins_UNKNOWN,
7297 /* INS_0x94 */ Ins_UNKNOWN,
7298 /* INS_0x95 */ Ins_UNKNOWN,
7299 /* INS_0x96 */ Ins_UNKNOWN,
7300 /* INS_0x97 */ Ins_UNKNOWN,
7301 /* INS_0x98 */ Ins_UNKNOWN,
7302 /* INS_0x99 */ Ins_UNKNOWN,
7303 /* INS_0x9A */ Ins_UNKNOWN,
7304 /* INS_0x9B */ Ins_UNKNOWN,
7305 /* INS_0x9C */ Ins_UNKNOWN,
7306 /* INS_0x9D */ Ins_UNKNOWN,
7307 /* INS_0x9E */ Ins_UNKNOWN,
7308 /* INS_0x9F */ Ins_UNKNOWN,
7309
7310 /* INS_0xA0 */ Ins_UNKNOWN,
7311 /* INS_0xA1 */ Ins_UNKNOWN,
7312 /* INS_0xA2 */ Ins_UNKNOWN,
7313 /* INS_0xA3 */ Ins_UNKNOWN,
7314 /* INS_0xA4 */ Ins_UNKNOWN,
7315 /* INS_0xA5 */ Ins_UNKNOWN,
7316 /* INS_0xA6 */ Ins_UNKNOWN,
7317 /* INS_0xA7 */ Ins_UNKNOWN,
7318 /* INS_0xA8 */ Ins_UNKNOWN,
7319 /* INS_0xA9 */ Ins_UNKNOWN,
7320 /* INS_0xAA */ Ins_UNKNOWN,
7321 /* INS_0xAB */ Ins_UNKNOWN,
7322 /* INS_0xAC */ Ins_UNKNOWN,
7323 /* INS_0xAD */ Ins_UNKNOWN,
7324 /* INS_0xAE */ Ins_UNKNOWN,
7325 /* INS_0xAF */ Ins_UNKNOWN,
7326
7327 /* PushB[0] */ Ins_PUSHB,
7328 /* PushB[1] */ Ins_PUSHB,
7329 /* PushB[2] */ Ins_PUSHB,
7330 /* PushB[3] */ Ins_PUSHB,
7331 /* PushB[4] */ Ins_PUSHB,
7332 /* PushB[5] */ Ins_PUSHB,
7333 /* PushB[6] */ Ins_PUSHB,
7334 /* PushB[7] */ Ins_PUSHB,
7335 /* PushW[0] */ Ins_PUSHW,
7336 /* PushW[1] */ Ins_PUSHW,
7337 /* PushW[2] */ Ins_PUSHW,
7338 /* PushW[3] */ Ins_PUSHW,
7339 /* PushW[4] */ Ins_PUSHW,
7340 /* PushW[5] */ Ins_PUSHW,
7341 /* PushW[6] */ Ins_PUSHW,
7342 /* PushW[7] */ Ins_PUSHW,
7343
7344 /* MDRP[00] */ Ins_MDRP,
7345 /* MDRP[01] */ Ins_MDRP,
7346 /* MDRP[02] */ Ins_MDRP,
7347 /* MDRP[03] */ Ins_MDRP,
7348 /* MDRP[04] */ Ins_MDRP,
7349 /* MDRP[05] */ Ins_MDRP,
7350 /* MDRP[06] */ Ins_MDRP,
7351 /* MDRP[07] */ Ins_MDRP,
7352 /* MDRP[08] */ Ins_MDRP,
7353 /* MDRP[09] */ Ins_MDRP,
7354 /* MDRP[10] */ Ins_MDRP,
7355 /* MDRP[11] */ Ins_MDRP,
7356 /* MDRP[12] */ Ins_MDRP,
7357 /* MDRP[13] */ Ins_MDRP,
7358 /* MDRP[14] */ Ins_MDRP,
7359 /* MDRP[15] */ Ins_MDRP,
7360
7361 /* MDRP[16] */ Ins_MDRP,
7362 /* MDRP[17] */ Ins_MDRP,
7363 /* MDRP[18] */ Ins_MDRP,
7364 /* MDRP[19] */ Ins_MDRP,
7365 /* MDRP[20] */ Ins_MDRP,
7366 /* MDRP[21] */ Ins_MDRP,
7367 /* MDRP[22] */ Ins_MDRP,
7368 /* MDRP[23] */ Ins_MDRP,
7369 /* MDRP[24] */ Ins_MDRP,
7370 /* MDRP[25] */ Ins_MDRP,
7371 /* MDRP[26] */ Ins_MDRP,
7372 /* MDRP[27] */ Ins_MDRP,
7373 /* MDRP[28] */ Ins_MDRP,
7374 /* MDRP[29] */ Ins_MDRP,
7375 /* MDRP[30] */ Ins_MDRP,
7376 /* MDRP[31] */ Ins_MDRP,
7377
7378 /* MIRP[00] */ Ins_MIRP,
7379 /* MIRP[01] */ Ins_MIRP,
7380 /* MIRP[02] */ Ins_MIRP,
7381 /* MIRP[03] */ Ins_MIRP,
7382 /* MIRP[04] */ Ins_MIRP,
7383 /* MIRP[05] */ Ins_MIRP,
7384 /* MIRP[06] */ Ins_MIRP,
7385 /* MIRP[07] */ Ins_MIRP,
7386 /* MIRP[08] */ Ins_MIRP,
7387 /* MIRP[09] */ Ins_MIRP,
7388 /* MIRP[10] */ Ins_MIRP,
7389 /* MIRP[11] */ Ins_MIRP,
7390 /* MIRP[12] */ Ins_MIRP,
7391 /* MIRP[13] */ Ins_MIRP,
7392 /* MIRP[14] */ Ins_MIRP,
7393 /* MIRP[15] */ Ins_MIRP,
7394
7395 /* MIRP[16] */ Ins_MIRP,
7396 /* MIRP[17] */ Ins_MIRP,
7397 /* MIRP[18] */ Ins_MIRP,
7398 /* MIRP[19] */ Ins_MIRP,
7399 /* MIRP[20] */ Ins_MIRP,
7400 /* MIRP[21] */ Ins_MIRP,
7401 /* MIRP[22] */ Ins_MIRP,
7402 /* MIRP[23] */ Ins_MIRP,
7403 /* MIRP[24] */ Ins_MIRP,
7404 /* MIRP[25] */ Ins_MIRP,
7405 /* MIRP[26] */ Ins_MIRP,
7406 /* MIRP[27] */ Ins_MIRP,
7407 /* MIRP[28] */ Ins_MIRP,
7408 /* MIRP[29] */ Ins_MIRP,
7409 /* MIRP[30] */ Ins_MIRP,
7410 /* MIRP[31] */ Ins_MIRP
7411 };
Werner Lemberg78575dc2000-06-12 19:36:41 +00007412
7413
David Turnerd2b1f351999-12-16 23:11:37 +00007414#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
7415
7416
7417 /*************************************************************************/
7418 /* */
7419 /* RUN */
7420 /* */
7421 /* This function executes a run of opcodes. It will exit in the */
7422 /* following cases: */
7423 /* */
7424 /* - Errors (in which case it returns FALSE). */
7425 /* */
7426 /* - Reaching the end of the main code range (returns TRUE). */
7427 /* Reaching the end of a code range within a function call is an */
7428 /* error. */
7429 /* */
7430 /* - After executing one single opcode, if the flag `Instruction_Trap' */
7431 /* is set to TRUE (returns TRUE). */
7432 /* */
Werner Lemberg6e87ed92007-01-26 22:18:56 +00007433 /* On exit with TRUE, test IP < CodeSize to know whether it comes from */
David Turnerd2b1f351999-12-16 23:11:37 +00007434 /* an instruction trap or a normal termination. */
7435 /* */
7436 /* */
7437 /* Note: The documented DEBUG opcode pops a value from the stack. This */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007438 /* behaviour is unsupported; here a DEBUG opcode is always an */
David Turnerd2b1f351999-12-16 23:11:37 +00007439 /* error. */
7440 /* */
7441 /* */
7442 /* THIS IS THE INTERPRETER'S MAIN LOOP. */
7443 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007444 /* Instructions appear in the specification's order. */
David Turnerd2b1f351999-12-16 23:11:37 +00007445 /* */
7446 /*************************************************************************/
7447
7448
Werner Lemberg90a03302000-11-07 17:21:11 +00007449 /* documentation is in ttinterp.h */
7450
Werner Lemberg4a2305c2001-06-28 07:17:51 +00007451 FT_EXPORT_DEF( FT_Error )
7452 TT_RunIns( TT_ExecContext exc )
David Turnerd2b1f351999-12-16 23:11:37 +00007453 {
David Turnerf9b8dec2000-06-16 19:34:52 +00007454 FT_Long ins_counter = 0; /* executed instructions counter */
David Turnerd2b1f351999-12-16 23:11:37 +00007455
Werner Lemberg78575dc2000-06-12 19:36:41 +00007456
7457#ifdef TT_CONFIG_OPTION_STATIC_RASTER
David Turnerd2b1f351999-12-16 23:11:37 +00007458 cur = *exc;
Werner Lemberg78575dc2000-06-12 19:36:41 +00007459#endif
David Turnerd2b1f351999-12-16 23:11:37 +00007460
7461 /* set CVT functions */
7462 CUR.tt_metrics.ratio = 0;
7463 if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
7464 {
7465 /* non-square pixels, use the stretched routines */
7466 CUR.func_read_cvt = Read_CVT_Stretched;
7467 CUR.func_write_cvt = Write_CVT_Stretched;
7468 CUR.func_move_cvt = Move_CVT_Stretched;
7469 }
7470 else
7471 {
7472 /* square pixels, use normal routines */
7473 CUR.func_read_cvt = Read_CVT;
7474 CUR.func_write_cvt = Write_CVT;
7475 CUR.func_move_cvt = Move_CVT;
7476 }
7477
7478 COMPUTE_Funcs();
David Turnerf9b8dec2000-06-16 19:34:52 +00007479 COMPUTE_Round( (FT_Byte)exc->GS.round_state );
David Turnerd2b1f351999-12-16 23:11:37 +00007480
7481 do
7482 {
7483 CUR.opcode = CUR.code[CUR.IP];
7484
Werner Lemberg462ddb42010-07-01 11:28:43 +02007485 FT_TRACE7(( " " ));
7486 FT_TRACE7(( opcode_name[CUR.opcode] ));
7487 FT_TRACE7(( "\n" ));
7488
David Turnerd2b1f351999-12-16 23:11:37 +00007489 if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
7490 {
7491 if ( CUR.IP + 1 > CUR.codeSize )
7492 goto LErrorCodeOverflow_;
7493
Werner Lemberg33febc02004-10-09 07:07:43 +00007494 CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
David Turnerd2b1f351999-12-16 23:11:37 +00007495 }
7496
7497 if ( CUR.IP + CUR.length > CUR.codeSize )
7498 goto LErrorCodeOverflow_;
7499
7500 /* First, let's check for empty stack and overflow */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007501 CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );
David Turnerd2b1f351999-12-16 23:11:37 +00007502
7503 /* `args' is the top of the stack once arguments have been popped. */
7504 /* One can also interpret it as the index of the last argument. */
7505 if ( CUR.args < 0 )
7506 {
Werner Lemberg96f04562011-01-31 10:24:32 +01007507 FT_UShort i;
7508
7509
7510 if ( CUR.pedantic_hinting )
7511 {
7512 CUR.error = TT_Err_Too_Few_Arguments;
7513 goto LErrorLabel_;
7514 }
7515
7516 /* push zeroes onto the stack */
7517 for ( i = 0; i < Pop_Push_Count[CUR.opcode] >> 4; i++ )
7518 CUR.stack[i] = 0;
7519 CUR.args = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00007520 }
7521
Werner Lemberg78575dc2000-06-12 19:36:41 +00007522 CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
David Turnerd2b1f351999-12-16 23:11:37 +00007523
7524 /* `new_top' is the new top of the stack, after the instruction's */
7525 /* execution. `top' will be set to `new_top' after the `switch' */
7526 /* statement. */
7527 if ( CUR.new_top > CUR.stackSize )
7528 {
7529 CUR.error = TT_Err_Stack_Overflow;
7530 goto LErrorLabel_;
7531 }
7532
7533 CUR.step_ins = TRUE;
7534 CUR.error = TT_Err_Ok;
7535
7536#ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
Werner Lemberg78575dc2000-06-12 19:36:41 +00007537
David Turnerd2b1f351999-12-16 23:11:37 +00007538 {
David Turnerf9b8dec2000-06-16 19:34:52 +00007539 FT_Long* args = CUR.stack + CUR.args;
7540 FT_Byte opcode = CUR.opcode;
David Turnerd2b1f351999-12-16 23:11:37 +00007541
7542
Werner Lemberg63408a12000-12-13 23:44:37 +00007543#undef ARRAY_BOUND_ERROR
7544#define ARRAY_BOUND_ERROR goto Set_Invalid_Ref
David Turnerd2b1f351999-12-16 23:11:37 +00007545
7546
7547 switch ( opcode )
7548 {
7549 case 0x00: /* SVTCA y */
7550 case 0x01: /* SVTCA x */
7551 case 0x02: /* SPvTCA y */
7552 case 0x03: /* SPvTCA x */
7553 case 0x04: /* SFvTCA y */
7554 case 0x05: /* SFvTCA x */
7555 {
Werner Lemberg96f04562011-01-31 10:24:32 +01007556 FT_Short AA, BB;
David Turnerd2b1f351999-12-16 23:11:37 +00007557
7558
Werner Lemberg2b6248b2001-07-07 23:24:02 +00007559 AA = (FT_Short)( ( opcode & 1 ) << 14 );
David Turner3b7049f2001-07-07 16:12:14 +00007560 BB = (FT_Short)( AA ^ 0x4000 );
David Turnerd2b1f351999-12-16 23:11:37 +00007561
7562 if ( opcode < 4 )
7563 {
7564 CUR.GS.projVector.x = AA;
7565 CUR.GS.projVector.y = BB;
7566
7567 CUR.GS.dualVector.x = AA;
7568 CUR.GS.dualVector.y = BB;
7569 }
Graham Asher3ea859f2003-04-25 11:40:46 +00007570 else
7571 {
7572 GUESS_VECTOR( projVector );
7573 }
David Turnerd2b1f351999-12-16 23:11:37 +00007574
Werner Lemberg78575dc2000-06-12 19:36:41 +00007575 if ( ( opcode & 2 ) == 0 )
David Turnerd2b1f351999-12-16 23:11:37 +00007576 {
7577 CUR.GS.freeVector.x = AA;
7578 CUR.GS.freeVector.y = BB;
7579 }
Graham Asher3ea859f2003-04-25 11:40:46 +00007580 else
7581 {
7582 GUESS_VECTOR( freeVector );
7583 }
David Turnerd2b1f351999-12-16 23:11:37 +00007584
7585 COMPUTE_Funcs();
7586 }
7587 break;
7588
7589 case 0x06: /* SPvTL // */
7590 case 0x07: /* SPvTL + */
7591 DO_SPVTL
7592 break;
7593
7594 case 0x08: /* SFvTL // */
7595 case 0x09: /* SFvTL + */
7596 DO_SFVTL
7597 break;
7598
7599 case 0x0A: /* SPvFS */
7600 DO_SPVFS
7601 break;
7602
7603 case 0x0B: /* SFvFS */
7604 DO_SFVFS
7605 break;
7606
7607 case 0x0C: /* GPV */
7608 DO_GPV
7609 break;
7610
7611 case 0x0D: /* GFV */
7612 DO_GFV
7613 break;
7614
7615 case 0x0E: /* SFvTPv */
7616 DO_SFVTPV
7617 break;
7618
7619 case 0x0F: /* ISECT */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007620 Ins_ISECT( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007621 break;
7622
7623 case 0x10: /* SRP0 */
7624 DO_SRP0
7625 break;
7626
7627 case 0x11: /* SRP1 */
7628 DO_SRP1
7629 break;
7630
7631 case 0x12: /* SRP2 */
7632 DO_SRP2
7633 break;
7634
7635 case 0x13: /* SZP0 */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007636 Ins_SZP0( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007637 break;
7638
7639 case 0x14: /* SZP1 */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007640 Ins_SZP1( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007641 break;
7642
7643 case 0x15: /* SZP2 */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007644 Ins_SZP2( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007645 break;
7646
7647 case 0x16: /* SZPS */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007648 Ins_SZPS( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007649 break;
7650
7651 case 0x17: /* SLOOP */
7652 DO_SLOOP
7653 break;
7654
7655 case 0x18: /* RTG */
7656 DO_RTG
7657 break;
7658
7659 case 0x19: /* RTHG */
7660 DO_RTHG
7661 break;
7662
7663 case 0x1A: /* SMD */
7664 DO_SMD
7665 break;
7666
7667 case 0x1B: /* ELSE */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007668 Ins_ELSE( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007669 break;
7670
7671 case 0x1C: /* JMPR */
7672 DO_JMPR
7673 break;
7674
7675 case 0x1D: /* SCVTCI */
7676 DO_SCVTCI
7677 break;
7678
7679 case 0x1E: /* SSWCI */
7680 DO_SSWCI
7681 break;
7682
7683 case 0x1F: /* SSW */
7684 DO_SSW
7685 break;
7686
7687 case 0x20: /* DUP */
7688 DO_DUP
7689 break;
7690
7691 case 0x21: /* POP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007692 /* nothing :-) */
David Turnerd2b1f351999-12-16 23:11:37 +00007693 break;
7694
7695 case 0x22: /* CLEAR */
7696 DO_CLEAR
7697 break;
7698
7699 case 0x23: /* SWAP */
7700 DO_SWAP
7701 break;
7702
7703 case 0x24: /* DEPTH */
7704 DO_DEPTH
7705 break;
7706
7707 case 0x25: /* CINDEX */
7708 DO_CINDEX
7709 break;
7710
7711 case 0x26: /* MINDEX */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007712 Ins_MINDEX( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007713 break;
7714
7715 case 0x27: /* ALIGNPTS */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007716 Ins_ALIGNPTS( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007717 break;
7718
7719 case 0x28: /* ???? */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007720 Ins_UNKNOWN( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007721 break;
7722
7723 case 0x29: /* UTP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007724 Ins_UTP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007725 break;
7726
7727 case 0x2A: /* LOOPCALL */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007728 Ins_LOOPCALL( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007729 break;
7730
7731 case 0x2B: /* CALL */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007732 Ins_CALL( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007733 break;
7734
7735 case 0x2C: /* FDEF */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007736 Ins_FDEF( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007737 break;
7738
7739 case 0x2D: /* ENDF */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007740 Ins_ENDF( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007741 break;
7742
7743 case 0x2E: /* MDAP */
7744 case 0x2F: /* MDAP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007745 Ins_MDAP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007746 break;
7747
7748
7749 case 0x30: /* IUP */
7750 case 0x31: /* IUP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007751 Ins_IUP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007752 break;
7753
7754 case 0x32: /* SHP */
7755 case 0x33: /* SHP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007756 Ins_SHP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007757 break;
7758
7759 case 0x34: /* SHC */
7760 case 0x35: /* SHC */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007761 Ins_SHC( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007762 break;
7763
7764 case 0x36: /* SHZ */
7765 case 0x37: /* SHZ */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007766 Ins_SHZ( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007767 break;
7768
7769 case 0x38: /* SHPIX */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007770 Ins_SHPIX( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007771 break;
7772
7773 case 0x39: /* IP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007774 Ins_IP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007775 break;
7776
7777 case 0x3A: /* MSIRP */
7778 case 0x3B: /* MSIRP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007779 Ins_MSIRP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007780 break;
7781
7782 case 0x3C: /* AlignRP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007783 Ins_ALIGNRP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007784 break;
7785
7786 case 0x3D: /* RTDG */
7787 DO_RTDG
7788 break;
7789
7790 case 0x3E: /* MIAP */
7791 case 0x3F: /* MIAP */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007792 Ins_MIAP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007793 break;
7794
7795 case 0x40: /* NPUSHB */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007796 Ins_NPUSHB( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007797 break;
7798
7799 case 0x41: /* NPUSHW */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007800 Ins_NPUSHW( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007801 break;
7802
7803 case 0x42: /* WS */
7804 DO_WS
7805 break;
7806
Werner Lemberg78575dc2000-06-12 19:36:41 +00007807 Set_Invalid_Ref:
David Turnerd2b1f351999-12-16 23:11:37 +00007808 CUR.error = TT_Err_Invalid_Reference;
7809 break;
7810
7811 case 0x43: /* RS */
7812 DO_RS
7813 break;
7814
7815 case 0x44: /* WCVTP */
7816 DO_WCVTP
7817 break;
7818
7819 case 0x45: /* RCVT */
7820 DO_RCVT
7821 break;
7822
7823 case 0x46: /* GC */
7824 case 0x47: /* GC */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007825 Ins_GC( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007826 break;
7827
7828 case 0x48: /* SCFS */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007829 Ins_SCFS( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007830 break;
7831
7832 case 0x49: /* MD */
7833 case 0x4A: /* MD */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007834 Ins_MD( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007835 break;
7836
7837 case 0x4B: /* MPPEM */
7838 DO_MPPEM
7839 break;
7840
7841 case 0x4C: /* MPS */
7842 DO_MPS
7843 break;
7844
7845 case 0x4D: /* FLIPON */
7846 DO_FLIPON
7847 break;
7848
7849 case 0x4E: /* FLIPOFF */
7850 DO_FLIPOFF
7851 break;
7852
7853 case 0x4F: /* DEBUG */
7854 DO_DEBUG
7855 break;
7856
7857 case 0x50: /* LT */
7858 DO_LT
7859 break;
7860
7861 case 0x51: /* LTEQ */
7862 DO_LTEQ
7863 break;
7864
7865 case 0x52: /* GT */
7866 DO_GT
7867 break;
7868
7869 case 0x53: /* GTEQ */
7870 DO_GTEQ
7871 break;
7872
7873 case 0x54: /* EQ */
7874 DO_EQ
7875 break;
7876
7877 case 0x55: /* NEQ */
7878 DO_NEQ
7879 break;
7880
7881 case 0x56: /* ODD */
7882 DO_ODD
7883 break;
7884
7885 case 0x57: /* EVEN */
7886 DO_EVEN
7887 break;
7888
7889 case 0x58: /* IF */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007890 Ins_IF( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007891 break;
7892
7893 case 0x59: /* EIF */
7894 /* do nothing */
7895 break;
7896
7897 case 0x5A: /* AND */
7898 DO_AND
7899 break;
7900
7901 case 0x5B: /* OR */
7902 DO_OR
7903 break;
7904
7905 case 0x5C: /* NOT */
7906 DO_NOT
7907 break;
7908
7909 case 0x5D: /* DELTAP1 */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007910 Ins_DELTAP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007911 break;
7912
7913 case 0x5E: /* SDB */
7914 DO_SDB
7915 break;
7916
7917 case 0x5F: /* SDS */
7918 DO_SDS
7919 break;
7920
7921 case 0x60: /* ADD */
7922 DO_ADD
7923 break;
7924
7925 case 0x61: /* SUB */
7926 DO_SUB
7927 break;
7928
7929 case 0x62: /* DIV */
7930 DO_DIV
7931 break;
7932
7933 case 0x63: /* MUL */
7934 DO_MUL
7935 break;
7936
7937 case 0x64: /* ABS */
7938 DO_ABS
7939 break;
7940
7941 case 0x65: /* NEG */
7942 DO_NEG
7943 break;
7944
7945 case 0x66: /* FLOOR */
7946 DO_FLOOR
7947 break;
7948
7949 case 0x67: /* CEILING */
7950 DO_CEILING
7951 break;
7952
7953 case 0x68: /* ROUND */
7954 case 0x69: /* ROUND */
7955 case 0x6A: /* ROUND */
7956 case 0x6B: /* ROUND */
7957 DO_ROUND
7958 break;
7959
7960 case 0x6C: /* NROUND */
7961 case 0x6D: /* NROUND */
7962 case 0x6E: /* NRRUND */
7963 case 0x6F: /* NROUND */
7964 DO_NROUND
7965 break;
7966
7967 case 0x70: /* WCVTF */
7968 DO_WCVTF
7969 break;
7970
7971 case 0x71: /* DELTAP2 */
7972 case 0x72: /* DELTAP3 */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007973 Ins_DELTAP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007974 break;
7975
7976 case 0x73: /* DELTAC0 */
7977 case 0x74: /* DELTAC1 */
7978 case 0x75: /* DELTAC2 */
Werner Lemberg78575dc2000-06-12 19:36:41 +00007979 Ins_DELTAC( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00007980 break;
7981
7982 case 0x76: /* SROUND */
7983 DO_SROUND
7984 break;
7985
7986 case 0x77: /* S45Round */
7987 DO_S45ROUND
7988 break;
7989
7990 case 0x78: /* JROT */
7991 DO_JROT
7992 break;
7993
7994 case 0x79: /* JROF */
7995 DO_JROF
7996 break;
7997
7998 case 0x7A: /* ROFF */
7999 DO_ROFF
8000 break;
8001
8002 case 0x7B: /* ???? */
Werner Lemberg78575dc2000-06-12 19:36:41 +00008003 Ins_UNKNOWN( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008004 break;
8005
8006 case 0x7C: /* RUTG */
8007 DO_RUTG
8008 break;
8009
8010 case 0x7D: /* RDTG */
8011 DO_RDTG
8012 break;
8013
8014 case 0x7E: /* SANGW */
8015 case 0x7F: /* AA */
8016 /* nothing - obsolete */
8017 break;
8018
8019 case 0x80: /* FLIPPT */
Werner Lemberg78575dc2000-06-12 19:36:41 +00008020 Ins_FLIPPT( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008021 break;
8022
8023 case 0x81: /* FLIPRGON */
Werner Lemberg78575dc2000-06-12 19:36:41 +00008024 Ins_FLIPRGON( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008025 break;
8026
8027 case 0x82: /* FLIPRGOFF */
Werner Lemberg78575dc2000-06-12 19:36:41 +00008028 Ins_FLIPRGOFF( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008029 break;
8030
8031 case 0x83: /* UNKNOWN */
8032 case 0x84: /* UNKNOWN */
Werner Lemberg78575dc2000-06-12 19:36:41 +00008033 Ins_UNKNOWN( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008034 break;
8035
8036 case 0x85: /* SCANCTRL */
Werner Lemberg78575dc2000-06-12 19:36:41 +00008037 Ins_SCANCTRL( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008038 break;
8039
8040 case 0x86: /* SDPVTL */
8041 case 0x87: /* SDPVTL */
Werner Lemberg78575dc2000-06-12 19:36:41 +00008042 Ins_SDPVTL( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008043 break;
8044
8045 case 0x88: /* GETINFO */
Werner Lemberg78575dc2000-06-12 19:36:41 +00008046 Ins_GETINFO( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008047 break;
8048
8049 case 0x89: /* IDEF */
Werner Lemberg78575dc2000-06-12 19:36:41 +00008050 Ins_IDEF( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008051 break;
8052
8053 case 0x8A: /* ROLL */
Werner Lemberg78575dc2000-06-12 19:36:41 +00008054 Ins_ROLL( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008055 break;
8056
8057 case 0x8B: /* MAX */
8058 DO_MAX
8059 break;
8060
8061 case 0x8C: /* MIN */
8062 DO_MIN
8063 break;
8064
8065 case 0x8D: /* SCANTYPE */
Werner Lemberg78575dc2000-06-12 19:36:41 +00008066 Ins_SCANTYPE( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008067 break;
8068
8069 case 0x8E: /* INSTCTRL */
Werner Lemberg78575dc2000-06-12 19:36:41 +00008070 Ins_INSTCTRL( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008071 break;
8072
8073 case 0x8F:
Werner Lemberg78575dc2000-06-12 19:36:41 +00008074 Ins_UNKNOWN( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008075 break;
8076
8077 default:
8078 if ( opcode >= 0xE0 )
Werner Lemberg78575dc2000-06-12 19:36:41 +00008079 Ins_MIRP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008080 else if ( opcode >= 0xC0 )
Werner Lemberg78575dc2000-06-12 19:36:41 +00008081 Ins_MDRP( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008082 else if ( opcode >= 0xB8 )
Werner Lemberg78575dc2000-06-12 19:36:41 +00008083 Ins_PUSHW( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008084 else if ( opcode >= 0xB0 )
Werner Lemberg78575dc2000-06-12 19:36:41 +00008085 Ins_PUSHB( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008086 else
Werner Lemberg78575dc2000-06-12 19:36:41 +00008087 Ins_UNKNOWN( EXEC_ARG_ args );
David Turnerd2b1f351999-12-16 23:11:37 +00008088 }
8089
8090 }
Werner Lemberg78575dc2000-06-12 19:36:41 +00008091
David Turnerd2b1f351999-12-16 23:11:37 +00008092#else
Werner Lemberg78575dc2000-06-12 19:36:41 +00008093
David Turnerd2b1f351999-12-16 23:11:37 +00008094 Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );
Werner Lemberg78575dc2000-06-12 19:36:41 +00008095
8096#endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
8097
Werner Lemberg79860702001-06-08 21:17:29 +00008098 if ( CUR.error != TT_Err_Ok )
David Turnerd2b1f351999-12-16 23:11:37 +00008099 {
8100 switch ( CUR.error )
8101 {
8102 case TT_Err_Invalid_Opcode: /* looking for redefined instructions */
8103 {
8104 TT_DefRecord* def = CUR.IDefs;
8105 TT_DefRecord* limit = def + CUR.numIDefs;
David Turnere49ab252000-05-16 23:44:38 +00008106
Werner Lemberg78575dc2000-06-12 19:36:41 +00008107
David Turnerd2b1f351999-12-16 23:11:37 +00008108 for ( ; def < limit; def++ )
8109 {
David Turnerb1aabf42000-11-30 23:48:22 +00008110 if ( def->active && CUR.opcode == (FT_Byte)def->opc )
David Turnerd2b1f351999-12-16 23:11:37 +00008111 {
8112 TT_CallRec* callrec;
David Turnere49ab252000-05-16 23:44:38 +00008113
Werner Lemberg78575dc2000-06-12 19:36:41 +00008114
David Turnerd2b1f351999-12-16 23:11:37 +00008115 if ( CUR.callTop >= CUR.callSize )
8116 {
8117 CUR.error = TT_Err_Invalid_Reference;
8118 goto LErrorLabel_;
8119 }
David Turnere49ab252000-05-16 23:44:38 +00008120
David Turnerd2b1f351999-12-16 23:11:37 +00008121 callrec = &CUR.callStack[CUR.callTop];
David Turnere49ab252000-05-16 23:44:38 +00008122
David Turnerd2b1f351999-12-16 23:11:37 +00008123 callrec->Caller_Range = CUR.curRange;
8124 callrec->Caller_IP = CUR.IP + 1;
8125 callrec->Cur_Count = 1;
8126 callrec->Cur_Restart = def->start;
David Turnere49ab252000-05-16 23:44:38 +00008127
David Turnerd2b1f351999-12-16 23:11:37 +00008128 if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
8129 goto LErrorLabel_;
David Turnere49ab252000-05-16 23:44:38 +00008130
David Turnerd2b1f351999-12-16 23:11:37 +00008131 goto LSuiteLabel_;
8132 }
8133 }
8134 }
8135
8136 CUR.error = TT_Err_Invalid_Opcode;
8137 goto LErrorLabel_;
Werner Lemberg78575dc2000-06-12 19:36:41 +00008138
8139#if 0
8140 break; /* Unreachable code warning suppression. */
8141 /* Leave to remind in case a later change the editor */
8142 /* to consider break; */
8143#endif
David Turnerd2b1f351999-12-16 23:11:37 +00008144
8145 default:
8146 goto LErrorLabel_;
Werner Lemberg78575dc2000-06-12 19:36:41 +00008147
8148#if 0
8149 break;
8150#endif
David Turnerd2b1f351999-12-16 23:11:37 +00008151 }
8152 }
8153
8154 CUR.top = CUR.new_top;
8155
8156 if ( CUR.step_ins )
8157 CUR.IP += CUR.length;
8158
Werner Lemberg78575dc2000-06-12 19:36:41 +00008159 /* increment instruction counter and check if we didn't */
8160 /* run this program for too long (e.g. infinite loops). */
David Turnerd2b1f351999-12-16 23:11:37 +00008161 if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
8162 return TT_Err_Execution_Too_Long;
8163
Werner Lemberg78575dc2000-06-12 19:36:41 +00008164 LSuiteLabel_:
David Turnerd2b1f351999-12-16 23:11:37 +00008165 if ( CUR.IP >= CUR.codeSize )
8166 {
8167 if ( CUR.callTop > 0 )
8168 {
8169 CUR.error = TT_Err_Code_Overflow;
8170 goto LErrorLabel_;
8171 }
8172 else
8173 goto LNo_Error_;
8174 }
8175 } while ( !CUR.instruction_trap );
8176
8177 LNo_Error_:
Werner Lemberg78575dc2000-06-12 19:36:41 +00008178
8179#ifdef TT_CONFIG_OPTION_STATIC_RASTER
David Turnerd2b1f351999-12-16 23:11:37 +00008180 *exc = cur;
Werner Lemberg78575dc2000-06-12 19:36:41 +00008181#endif
8182
David Turnerd2b1f351999-12-16 23:11:37 +00008183 return TT_Err_Ok;
8184
8185 LErrorCodeOverflow_:
8186 CUR.error = TT_Err_Code_Overflow;
8187
8188 LErrorLabel_:
Werner Lemberg78575dc2000-06-12 19:36:41 +00008189
8190#ifdef TT_CONFIG_OPTION_STATIC_RASTER
David Turnerd2b1f351999-12-16 23:11:37 +00008191 *exc = cur;
Werner Lemberg78575dc2000-06-12 19:36:41 +00008192#endif
8193
Werner Lembergafd89d32010-09-15 13:02:35 +02008194 /* If any errors have occurred, function tables may be broken. */
8195 /* Force a re-execution of `prep' and `fpgm' tables if no */
8196 /* bytecode debugger is run. */
8197 if ( CUR.error && !CUR.instruction_trap )
suzuki toshiya29e044a2010-08-31 01:23:30 +09008198 {
Werner Lemberg6abb9232010-09-14 09:02:10 +02008199 FT_TRACE1(( " The interpreter returned error 0x%x\n", CUR.error ));
Werner Lembergafd89d32010-09-15 13:02:35 +02008200 exc->size->cvt_ready = FALSE;
suzuki toshiya29e044a2010-08-31 01:23:30 +09008201 }
8202
David Turnerd2b1f351999-12-16 23:11:37 +00008203 return CUR.error;
8204 }
8205
8206
David Turner6aa260c2006-08-25 22:45:13 +00008207#endif /* TT_USE_BYTECODE_INTERPRETER */
David Turnerd2b1f351999-12-16 23:11:37 +00008208
Werner Lemberg78575dc2000-06-12 19:36:41 +00008209
David Turnerd2b1f351999-12-16 23:11:37 +00008210/* END */