~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/freetype/src/truetype/ttinterp.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************/
 
2
/*                                                                         */
 
3
/*  ttinterp.c                                                             */
 
4
/*                                                                         */
 
5
/*    TrueType bytecode interpreter (body).                                */
 
6
/*                                                                         */
 
7
/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
 
8
/*            2010                                                         */
 
9
/*  by David Turner, Robert Wilhelm, and Werner Lemberg.                   */
 
10
/*                                                                         */
 
11
/*  This file is part of the FreeType project, and may only be used,       */
 
12
/*  modified, and distributed under the terms of the FreeType project      */
 
13
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
 
14
/*  this file you indicate that you have read the license and              */
 
15
/*  understand and accept it fully.                                        */
 
16
/*                                                                         */
 
17
/***************************************************************************/
 
18
 
 
19
 
 
20
#include <ft2build.h>
 
21
#include FT_INTERNAL_DEBUG_H
 
22
#include FT_INTERNAL_CALC_H
 
23
#include FT_TRIGONOMETRY_H
 
24
#include FT_SYSTEM_H
 
25
 
 
26
#include "ttinterp.h"
 
27
 
 
28
#include "tterrors.h"
 
29
 
 
30
 
 
31
#ifdef TT_USE_BYTECODE_INTERPRETER
 
32
 
 
33
 
 
34
#define TT_MULFIX           FT_MulFix
 
35
#define TT_MULDIV           FT_MulDiv
 
36
#define TT_MULDIV_NO_ROUND  FT_MulDiv_No_Round
 
37
 
 
38
 
 
39
  /*************************************************************************/
 
40
  /*                                                                       */
 
41
  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
 
42
  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
 
43
  /* messages during execution.                                            */
 
44
  /*                                                                       */
 
45
#undef  FT_COMPONENT
 
46
#define FT_COMPONENT  trace_ttinterp
 
47
 
 
48
  /*************************************************************************/
 
49
  /*                                                                       */
 
50
  /* In order to detect infinite loops in the code, we set up a counter    */
 
51
  /* within the run loop.  A single stroke of interpretation is now        */
 
52
  /* limited to a maximal number of opcodes defined below.                 */
 
53
  /*                                                                       */
 
54
#define MAX_RUNNABLE_OPCODES  1000000L
 
55
 
 
56
 
 
57
  /*************************************************************************/
 
58
  /*                                                                       */
 
59
  /* There are two kinds of implementations:                               */
 
60
  /*                                                                       */
 
61
  /* a. static implementation                                              */
 
62
  /*                                                                       */
 
63
  /*    The current execution context is a static variable, which fields   */
 
64
  /*    are accessed directly by the interpreter during execution.  The    */
 
65
  /*    context is named `cur'.                                            */
 
66
  /*                                                                       */
 
67
  /*    This version is non-reentrant, of course.                          */
 
68
  /*                                                                       */
 
69
  /* b. indirect implementation                                            */
 
70
  /*                                                                       */
 
71
  /*    The current execution context is passed to _each_ function as its  */
 
72
  /*    first argument, and each field is thus accessed indirectly.        */
 
73
  /*                                                                       */
 
74
  /*    This version is fully re-entrant.                                  */
 
75
  /*                                                                       */
 
76
  /* The idea is that an indirect implementation may be slower to execute  */
 
77
  /* on low-end processors that are used in some systems (like 386s or     */
 
78
  /* even 486s).                                                           */
 
79
  /*                                                                       */
 
80
  /* As a consequence, the indirect implementation is now the default, as  */
 
81
  /* its performance costs can be considered negligible in our context.    */
 
82
  /* Note, however, that we kept the same source with macros because:      */
 
83
  /*                                                                       */
 
84
  /* - The code is kept very close in design to the Pascal code used for   */
 
85
  /*   development.                                                        */
 
86
  /*                                                                       */
 
87
  /* - It's much more readable that way!                                   */
 
88
  /*                                                                       */
 
89
  /* - It's still open to experimentation and tuning.                      */
 
90
  /*                                                                       */
 
91
  /*************************************************************************/
 
92
 
 
93
 
 
94
#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER     /* indirect implementation */
 
95
 
 
96
#define CUR  (*exc)                             /* see ttobjs.h */
 
97
 
 
98
  /*************************************************************************/
 
99
  /*                                                                       */
 
100
  /* This macro is used whenever `exec' is unused in a function, to avoid  */
 
101
  /* stupid warnings from pedantic compilers.                              */
 
102
  /*                                                                       */
 
103
#define FT_UNUSED_EXEC  FT_UNUSED( exc )
 
104
 
 
105
#else                                           /* static implementation */
 
106
 
 
107
#define CUR  cur
 
108
 
 
109
#define FT_UNUSED_EXEC  int  __dummy = __dummy
 
110
 
 
111
  static
 
112
  TT_ExecContextRec  cur;   /* static exec. context variable */
 
113
 
 
114
  /* apparently, we have a _lot_ of direct indexing when accessing  */
 
115
  /* the static `cur', which makes the code bigger (due to all the  */
 
116
  /* four bytes addresses).                                         */
 
117
 
 
118
#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
 
119
 
 
120
 
 
121
  /*************************************************************************/
 
122
  /*                                                                       */
 
123
  /* The instruction argument stack.                                       */
 
124
  /*                                                                       */
 
125
#define INS_ARG  EXEC_OP_ FT_Long*  args    /* see ttobjs.h for EXEC_OP_ */
 
126
 
 
127
 
 
128
  /*************************************************************************/
 
129
  /*                                                                       */
 
130
  /* This macro is used whenever `args' is unused in a function, to avoid  */
 
131
  /* stupid warnings from pedantic compilers.                              */
 
132
  /*                                                                       */
 
133
#define FT_UNUSED_ARG  FT_UNUSED_EXEC; FT_UNUSED( args )
 
134
 
 
135
 
 
136
  /*************************************************************************/
 
137
  /*                                                                       */
 
138
  /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to        */
 
139
  /* increase readability of the code.                                     */
 
140
  /*                                                                       */
 
141
  /*************************************************************************/
 
142
 
 
143
 
 
144
#define SKIP_Code() \
 
145
          SkipCode( EXEC_ARG )
 
146
 
 
147
#define GET_ShortIns() \
 
148
          GetShortIns( EXEC_ARG )
 
149
 
 
150
#define NORMalize( x, y, v ) \
 
151
          Normalize( EXEC_ARG_ x, y, v )
 
152
 
 
153
#define SET_SuperRound( scale, flags ) \
 
154
          SetSuperRound( EXEC_ARG_ scale, flags )
 
155
 
 
156
#define ROUND_None( d, c ) \
 
157
          Round_None( EXEC_ARG_ d, c )
 
158
 
 
159
#define INS_Goto_CodeRange( range, ip ) \
 
160
          Ins_Goto_CodeRange( EXEC_ARG_ range, ip )
 
161
 
 
162
#define CUR_Func_move( z, p, d ) \
 
163
          CUR.func_move( EXEC_ARG_ z, p, d )
 
164
 
 
165
#define CUR_Func_move_orig( z, p, d ) \
 
166
          CUR.func_move_orig( EXEC_ARG_ z, p, d )
 
167
 
 
168
#define CUR_Func_round( d, c ) \
 
169
          CUR.func_round( EXEC_ARG_ d, c )
 
170
 
 
171
#define CUR_Func_read_cvt( index ) \
 
172
          CUR.func_read_cvt( EXEC_ARG_ index )
 
173
 
 
174
#define CUR_Func_write_cvt( index, val ) \
 
175
          CUR.func_write_cvt( EXEC_ARG_ index, val )
 
176
 
 
177
#define CUR_Func_move_cvt( index, val ) \
 
178
          CUR.func_move_cvt( EXEC_ARG_ index, val )
 
179
 
 
180
#define CURRENT_Ratio() \
 
181
          Current_Ratio( EXEC_ARG )
 
182
 
 
183
#define CURRENT_Ppem() \
 
184
          Current_Ppem( EXEC_ARG )
 
185
 
 
186
#define CUR_Ppem() \
 
187
          Cur_PPEM( EXEC_ARG )
 
188
 
 
189
#define INS_SxVTL( a, b, c, d ) \
 
190
          Ins_SxVTL( EXEC_ARG_ a, b, c, d )
 
191
 
 
192
#define COMPUTE_Funcs() \
 
193
          Compute_Funcs( EXEC_ARG )
 
194
 
 
195
#define COMPUTE_Round( a ) \
 
196
          Compute_Round( EXEC_ARG_ a )
 
197
 
 
198
#define COMPUTE_Point_Displacement( a, b, c, d ) \
 
199
          Compute_Point_Displacement( EXEC_ARG_ a, b, c, d )
 
200
 
 
201
#define MOVE_Zp2_Point( a, b, c, t ) \
 
202
          Move_Zp2_Point( EXEC_ARG_ a, b, c, t )
 
203
 
 
204
 
 
205
#define CUR_Func_project( v1, v2 )  \
 
206
          CUR.func_project( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
 
207
 
 
208
#define CUR_Func_dualproj( v1, v2 )  \
 
209
          CUR.func_dualproj( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
 
210
 
 
211
#define CUR_fast_project( v ) \
 
212
          CUR.func_project( EXEC_ARG_ (v)->x, (v)->y )
 
213
 
 
214
#define CUR_fast_dualproj( v ) \
 
215
          CUR.func_dualproj( EXEC_ARG_ (v)->x, (v)->y )
 
216
 
 
217
 
 
218
  /*************************************************************************/
 
219
  /*                                                                       */
 
220
  /* Instruction dispatch function, as used by the interpreter.            */
 
221
  /*                                                                       */
 
222
  typedef void  (*TInstruction_Function)( INS_ARG );
 
223
 
 
224
 
 
225
  /*************************************************************************/
 
226
  /*                                                                       */
 
227
  /* Two simple bounds-checking macros.                                    */
 
228
  /*                                                                       */
 
229
#define BOUNDS( x, n )   ( (FT_UInt)(x)  >= (FT_UInt)(n)  )
 
230
#define BOUNDSL( x, n )  ( (FT_ULong)(x) >= (FT_ULong)(n) )
 
231
 
 
232
#undef  SUCCESS
 
233
#define SUCCESS  0
 
234
 
 
235
#undef  FAILURE
 
236
#define FAILURE  1
 
237
 
 
238
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
 
239
#define GUESS_VECTOR( V )                                         \
 
240
  if ( CUR.face->unpatented_hinting )                             \
 
241
  {                                                               \
 
242
    CUR.GS.V.x = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0x4000 : 0 ); \
 
243
    CUR.GS.V.y = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0 : 0x4000 ); \
 
244
  }
 
245
#else
 
246
#define GUESS_VECTOR( V )
 
247
#endif
 
248
 
 
249
  /*************************************************************************/
 
250
  /*                                                                       */
 
251
  /*                        CODERANGE FUNCTIONS                            */
 
252
  /*                                                                       */
 
253
  /*************************************************************************/
 
254
 
 
255
 
 
256
  /*************************************************************************/
 
257
  /*                                                                       */
 
258
  /* <Function>                                                            */
 
259
  /*    TT_Goto_CodeRange                                                  */
 
260
  /*                                                                       */
 
261
  /* <Description>                                                         */
 
262
  /*    Switches to a new code range (updates the code related elements in */
 
263
  /*    `exec', and `IP').                                                 */
 
264
  /*                                                                       */
 
265
  /* <Input>                                                               */
 
266
  /*    range :: The new execution code range.                             */
 
267
  /*                                                                       */
 
268
  /*    IP    :: The new IP in the new code range.                         */
 
269
  /*                                                                       */
 
270
  /* <InOut>                                                               */
 
271
  /*    exec  :: The target execution context.                             */
 
272
  /*                                                                       */
 
273
  /* <Return>                                                              */
 
274
  /*    FreeType error code.  0 means success.                             */
 
275
  /*                                                                       */
 
276
  FT_LOCAL_DEF( FT_Error )
 
277
  TT_Goto_CodeRange( TT_ExecContext  exec,
 
278
                     FT_Int          range,
 
279
                     FT_Long         IP )
 
280
  {
 
281
    TT_CodeRange*  coderange;
 
282
 
 
283
 
 
284
    FT_ASSERT( range >= 1 && range <= 3 );
 
285
 
 
286
    coderange = &exec->codeRangeTable[range - 1];
 
287
 
 
288
    FT_ASSERT( coderange->base != NULL );
 
289
 
 
290
    /* NOTE: Because the last instruction of a program may be a CALL */
 
291
    /*       which will return to the first byte *after* the code    */
 
292
    /*       range, we test for IP <= Size instead of IP < Size.     */
 
293
    /*                                                               */
 
294
    FT_ASSERT( (FT_ULong)IP <= coderange->size );
 
295
 
 
296
    exec->code     = coderange->base;
 
297
    exec->codeSize = coderange->size;
 
298
    exec->IP       = IP;
 
299
    exec->curRange = range;
 
300
 
 
301
    return TT_Err_Ok;
 
302
  }
 
303
 
 
304
 
 
305
  /*************************************************************************/
 
306
  /*                                                                       */
 
307
  /* <Function>                                                            */
 
308
  /*    TT_Set_CodeRange                                                   */
 
309
  /*                                                                       */
 
310
  /* <Description>                                                         */
 
311
  /*    Sets a code range.                                                 */
 
312
  /*                                                                       */
 
313
  /* <Input>                                                               */
 
314
  /*    range  :: The code range index.                                    */
 
315
  /*                                                                       */
 
316
  /*    base   :: The new code base.                                       */
 
317
  /*                                                                       */
 
318
  /*    length :: The range size in bytes.                                 */
 
319
  /*                                                                       */
 
320
  /* <InOut>                                                               */
 
321
  /*    exec   :: The target execution context.                            */
 
322
  /*                                                                       */
 
323
  /* <Return>                                                              */
 
324
  /*    FreeType error code.  0 means success.                             */
 
325
  /*                                                                       */
 
326
  FT_LOCAL_DEF( FT_Error )
 
327
  TT_Set_CodeRange( TT_ExecContext  exec,
 
328
                    FT_Int          range,
 
329
                    void*           base,
 
330
                    FT_Long         length )
 
331
  {
 
332
    FT_ASSERT( range >= 1 && range <= 3 );
 
333
 
 
334
    exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
 
335
    exec->codeRangeTable[range - 1].size = length;
 
336
 
 
337
    return TT_Err_Ok;
 
338
  }
 
339
 
 
340
 
 
341
  /*************************************************************************/
 
342
  /*                                                                       */
 
343
  /* <Function>                                                            */
 
344
  /*    TT_Clear_CodeRange                                                 */
 
345
  /*                                                                       */
 
346
  /* <Description>                                                         */
 
347
  /*    Clears a code range.                                               */
 
348
  /*                                                                       */
 
349
  /* <Input>                                                               */
 
350
  /*    range :: The code range index.                                     */
 
351
  /*                                                                       */
 
352
  /* <InOut>                                                               */
 
353
  /*    exec  :: The target execution context.                             */
 
354
  /*                                                                       */
 
355
  /* <Return>                                                              */
 
356
  /*    FreeType error code.  0 means success.                             */
 
357
  /*                                                                       */
 
358
  /* <Note>                                                                */
 
359
  /*    Does not set the Error variable.                                   */
 
360
  /*                                                                       */
 
361
  FT_LOCAL_DEF( FT_Error )
 
362
  TT_Clear_CodeRange( TT_ExecContext  exec,
 
363
                      FT_Int          range )
 
364
  {
 
365
    FT_ASSERT( range >= 1 && range <= 3 );
 
366
 
 
367
    exec->codeRangeTable[range - 1].base = NULL;
 
368
    exec->codeRangeTable[range - 1].size = 0;
 
369
 
 
370
    return TT_Err_Ok;
 
371
  }
 
372
 
 
373
 
 
374
  /*************************************************************************/
 
375
  /*                                                                       */
 
376
  /*                   EXECUTION CONTEXT ROUTINES                          */
 
377
  /*                                                                       */
 
378
  /*************************************************************************/
 
379
 
 
380
 
 
381
  /*************************************************************************/
 
382
  /*                                                                       */
 
383
  /* <Function>                                                            */
 
384
  /*    TT_Done_Context                                                    */
 
385
  /*                                                                       */
 
386
  /* <Description>                                                         */
 
387
  /*    Destroys a given context.                                          */
 
388
  /*                                                                       */
 
389
  /* <Input>                                                               */
 
390
  /*    exec   :: A handle to the target execution context.                */
 
391
  /*                                                                       */
 
392
  /*    memory :: A handle to the parent memory object.                    */
 
393
  /*                                                                       */
 
394
  /* <Return>                                                              */
 
395
  /*    FreeType error code.  0 means success.                             */
 
396
  /*                                                                       */
 
397
  /* <Note>                                                                */
 
398
  /*    Only the glyph loader and debugger should call this function.      */
 
399
  /*                                                                       */
 
400
  FT_LOCAL_DEF( FT_Error )
 
401
  TT_Done_Context( TT_ExecContext  exec )
 
402
  {
 
403
    FT_Memory  memory = exec->memory;
 
404
 
 
405
 
 
406
    /* points zone */
 
407
    exec->maxPoints   = 0;
 
408
    exec->maxContours = 0;
 
409
 
 
410
    /* free stack */
 
411
    FT_FREE( exec->stack );
 
412
    exec->stackSize = 0;
 
413
 
 
414
    /* free call stack */
 
415
    FT_FREE( exec->callStack );
 
416
    exec->callSize = 0;
 
417
    exec->callTop  = 0;
 
418
 
 
419
    /* free glyph code range */
 
420
    FT_FREE( exec->glyphIns );
 
421
    exec->glyphSize = 0;
 
422
 
 
423
    exec->size = NULL;
 
424
    exec->face = NULL;
 
425
 
 
426
    FT_FREE( exec );
 
427
 
 
428
    return TT_Err_Ok;
 
429
  }
 
430
 
 
431
 
 
432
  /*************************************************************************/
 
433
  /*                                                                       */
 
434
  /* <Function>                                                            */
 
435
  /*    Init_Context                                                       */
 
436
  /*                                                                       */
 
437
  /* <Description>                                                         */
 
438
  /*    Initializes a context object.                                      */
 
439
  /*                                                                       */
 
440
  /* <Input>                                                               */
 
441
  /*    memory :: A handle to the parent memory object.                    */
 
442
  /*                                                                       */
 
443
  /* <InOut>                                                               */
 
444
  /*    exec   :: A handle to the target execution context.                */
 
445
  /*                                                                       */
 
446
  /* <Return>                                                              */
 
447
  /*    FreeType error code.  0 means success.                             */
 
448
  /*                                                                       */
 
449
  static FT_Error
 
450
  Init_Context( TT_ExecContext  exec,
 
451
                FT_Memory       memory )
 
452
  {
 
453
    FT_Error  error;
 
454
 
 
455
 
 
456
    FT_TRACE1(( "Init_Context: new object at 0x%08p\n", exec ));
 
457
 
 
458
    exec->memory   = memory;
 
459
    exec->callSize = 32;
 
460
 
 
461
    if ( FT_NEW_ARRAY( exec->callStack, exec->callSize ) )
 
462
      goto Fail_Memory;
 
463
 
 
464
    /* all values in the context are set to 0 already, but this is */
 
465
    /* here as a remainder                                         */
 
466
    exec->maxPoints   = 0;
 
467
    exec->maxContours = 0;
 
468
 
 
469
    exec->stackSize = 0;
 
470
    exec->glyphSize = 0;
 
471
 
 
472
    exec->stack     = NULL;
 
473
    exec->glyphIns  = NULL;
 
474
 
 
475
    exec->face = NULL;
 
476
    exec->size = NULL;
 
477
 
 
478
    return TT_Err_Ok;
 
479
 
 
480
  Fail_Memory:
 
481
    FT_ERROR(( "Init_Context: not enough memory for %p\n", exec ));
 
482
    TT_Done_Context( exec );
 
483
 
 
484
    return error;
 
485
 }
 
486
 
 
487
 
 
488
  /*************************************************************************/
 
489
  /*                                                                       */
 
490
  /* <Function>                                                            */
 
491
  /*    Update_Max                                                         */
 
492
  /*                                                                       */
 
493
  /* <Description>                                                         */
 
494
  /*    Checks the size of a buffer and reallocates it if necessary.       */
 
495
  /*                                                                       */
 
496
  /* <Input>                                                               */
 
497
  /*    memory     :: A handle to the parent memory object.                */
 
498
  /*                                                                       */
 
499
  /*    multiplier :: The size in bytes of each element in the buffer.     */
 
500
  /*                                                                       */
 
501
  /*    new_max    :: The new capacity (size) of the buffer.               */
 
502
  /*                                                                       */
 
503
  /* <InOut>                                                               */
 
504
  /*    size       :: The address of the buffer's current size expressed   */
 
505
  /*                  in elements.                                         */
 
506
  /*                                                                       */
 
507
  /*    buff       :: The address of the buffer base pointer.              */
 
508
  /*                                                                       */
 
509
  /* <Return>                                                              */
 
510
  /*    FreeType error code.  0 means success.                             */
 
511
  /*                                                                       */
 
512
  FT_LOCAL_DEF( FT_Error )
 
513
  Update_Max( FT_Memory  memory,
 
514
              FT_ULong*  size,
 
515
              FT_Long    multiplier,
 
516
              void*      _pbuff,
 
517
              FT_ULong   new_max )
 
518
  {
 
519
    FT_Error  error;
 
520
    void**    pbuff = (void**)_pbuff;
 
521
 
 
522
 
 
523
    if ( *size < new_max )
 
524
    {
 
525
      if ( FT_REALLOC( *pbuff, *size * multiplier, new_max * multiplier ) )
 
526
        return error;
 
527
      *size = new_max;
 
528
    }
 
529
 
 
530
    return TT_Err_Ok;
 
531
  }
 
532
 
 
533
 
 
534
  /*************************************************************************/
 
535
  /*                                                                       */
 
536
  /* <Function>                                                            */
 
537
  /*    TT_Load_Context                                                    */
 
538
  /*                                                                       */
 
539
  /* <Description>                                                         */
 
540
  /*    Prepare an execution context for glyph hinting.                    */
 
541
  /*                                                                       */
 
542
  /* <Input>                                                               */
 
543
  /*    face :: A handle to the source face object.                        */
 
544
  /*                                                                       */
 
545
  /*    size :: A handle to the source size object.                        */
 
546
  /*                                                                       */
 
547
  /* <InOut>                                                               */
 
548
  /*    exec :: A handle to the target execution context.                  */
 
549
  /*                                                                       */
 
550
  /* <Return>                                                              */
 
551
  /*    FreeType error code.  0 means success.                             */
 
552
  /*                                                                       */
 
553
  /* <Note>                                                                */
 
554
  /*    Only the glyph loader and debugger should call this function.      */
 
555
  /*                                                                       */
 
556
  FT_LOCAL_DEF( FT_Error )
 
557
  TT_Load_Context( TT_ExecContext  exec,
 
558
                   TT_Face         face,
 
559
                   TT_Size         size )
 
560
  {
 
561
    FT_Int          i;
 
562
    FT_ULong        tmp;
 
563
    TT_MaxProfile*  maxp;
 
564
    FT_Error        error;
 
565
 
 
566
 
 
567
    exec->face = face;
 
568
    maxp       = &face->max_profile;
 
569
    exec->size = size;
 
570
 
 
571
    if ( size )
 
572
    {
 
573
      exec->numFDefs   = size->num_function_defs;
 
574
      exec->maxFDefs   = size->max_function_defs;
 
575
      exec->numIDefs   = size->num_instruction_defs;
 
576
      exec->maxIDefs   = size->max_instruction_defs;
 
577
      exec->FDefs      = size->function_defs;
 
578
      exec->IDefs      = size->instruction_defs;
 
579
      exec->tt_metrics = size->ttmetrics;
 
580
      exec->metrics    = size->metrics;
 
581
 
 
582
      exec->maxFunc    = size->max_func;
 
583
      exec->maxIns     = size->max_ins;
 
584
 
 
585
      for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
 
586
        exec->codeRangeTable[i] = size->codeRangeTable[i];
 
587
 
 
588
      /* set graphics state */
 
589
      exec->GS = size->GS;
 
590
 
 
591
      exec->cvtSize = size->cvt_size;
 
592
      exec->cvt     = size->cvt;
 
593
 
 
594
      exec->storeSize = size->storage_size;
 
595
      exec->storage   = size->storage;
 
596
 
 
597
      exec->twilight  = size->twilight;
 
598
 
 
599
      /* In case of multi-threading it can happen that the old size object */
 
600
      /* no longer exists, thus we must clear all glyph zone references.   */
 
601
      ft_memset( &exec->zp0, 0, sizeof ( exec->zp0 ) );
 
602
      exec->zp1 = exec->zp0;
 
603
      exec->zp2 = exec->zp0;
 
604
    }
 
605
 
 
606
    /* XXX: We reserve a little more elements on the stack to deal safely */
 
607
    /*      with broken fonts like arialbs, courbs, timesbs, etc.         */
 
608
    tmp = exec->stackSize;
 
609
    error = Update_Max( exec->memory,
 
610
                        &tmp,
 
611
                        sizeof ( FT_F26Dot6 ),
 
612
                        (void*)&exec->stack,
 
613
                        maxp->maxStackElements + 32 );
 
614
    exec->stackSize = (FT_UInt)tmp;
 
615
    if ( error )
 
616
      return error;
 
617
 
 
618
    tmp = exec->glyphSize;
 
619
    error = Update_Max( exec->memory,
 
620
                        &tmp,
 
621
                        sizeof ( FT_Byte ),
 
622
                        (void*)&exec->glyphIns,
 
623
                        maxp->maxSizeOfInstructions );
 
624
    exec->glyphSize = (FT_UShort)tmp;
 
625
    if ( error )
 
626
      return error;
 
627
 
 
628
    exec->pts.n_points   = 0;
 
629
    exec->pts.n_contours = 0;
 
630
 
 
631
    exec->zp1 = exec->pts;
 
632
    exec->zp2 = exec->pts;
 
633
    exec->zp0 = exec->pts;
 
634
 
 
635
    exec->instruction_trap = FALSE;
 
636
 
 
637
    return TT_Err_Ok;
 
638
  }
 
639
 
 
640
 
 
641
  /*************************************************************************/
 
642
  /*                                                                       */
 
643
  /* <Function>                                                            */
 
644
  /*    TT_Save_Context                                                    */
 
645
  /*                                                                       */
 
646
  /* <Description>                                                         */
 
647
  /*    Saves the code ranges in a `size' object.                          */
 
648
  /*                                                                       */
 
649
  /* <Input>                                                               */
 
650
  /*    exec :: A handle to the source execution context.                  */
 
651
  /*                                                                       */
 
652
  /* <InOut>                                                               */
 
653
  /*    size :: A handle to the target size object.                        */
 
654
  /*                                                                       */
 
655
  /* <Return>                                                              */
 
656
  /*    FreeType error code.  0 means success.                             */
 
657
  /*                                                                       */
 
658
  /* <Note>                                                                */
 
659
  /*    Only the glyph loader and debugger should call this function.      */
 
660
  /*                                                                       */
 
661
  FT_LOCAL_DEF( FT_Error )
 
662
  TT_Save_Context( TT_ExecContext  exec,
 
663
                   TT_Size         size )
 
664
  {
 
665
    FT_Int  i;
 
666
 
 
667
 
 
668
    /* XXXX: Will probably disappear soon with all the code range */
 
669
    /*       management, which is now rather obsolete.            */
 
670
    /*                                                            */
 
671
    size->num_function_defs    = exec->numFDefs;
 
672
    size->num_instruction_defs = exec->numIDefs;
 
673
 
 
674
    size->max_func = exec->maxFunc;
 
675
    size->max_ins  = exec->maxIns;
 
676
 
 
677
    for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
 
678
      size->codeRangeTable[i] = exec->codeRangeTable[i];
 
679
 
 
680
    return TT_Err_Ok;
 
681
  }
 
682
 
 
683
 
 
684
  /*************************************************************************/
 
685
  /*                                                                       */
 
686
  /* <Function>                                                            */
 
687
  /*    TT_Run_Context                                                     */
 
688
  /*                                                                       */
 
689
  /* <Description>                                                         */
 
690
  /*    Executes one or more instructions in the execution context.        */
 
691
  /*                                                                       */
 
692
  /* <Input>                                                               */
 
693
  /*    debug :: A Boolean flag.  If set, the function sets some internal  */
 
694
  /*             variables and returns immediately, otherwise TT_RunIns()  */
 
695
  /*             is called.                                                */
 
696
  /*                                                                       */
 
697
  /*             This is commented out currently.                          */
 
698
  /*                                                                       */
 
699
  /* <Input>                                                               */
 
700
  /*    exec  :: A handle to the target execution context.                 */
 
701
  /*                                                                       */
 
702
  /* <Return>                                                              */
 
703
  /*    TrueType error code.  0 means success.                             */
 
704
  /*                                                                       */
 
705
  /* <Note>                                                                */
 
706
  /*    Only the glyph loader and debugger should call this function.      */
 
707
  /*                                                                       */
 
708
  FT_LOCAL_DEF( FT_Error )
 
709
  TT_Run_Context( TT_ExecContext  exec,
 
710
                  FT_Bool         debug )
 
711
  {
 
712
    FT_Error  error;
 
713
 
 
714
 
 
715
    if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0  ) )
 
716
           != TT_Err_Ok )
 
717
      return error;
 
718
 
 
719
    exec->zp0 = exec->pts;
 
720
    exec->zp1 = exec->pts;
 
721
    exec->zp2 = exec->pts;
 
722
 
 
723
    exec->GS.gep0 = 1;
 
724
    exec->GS.gep1 = 1;
 
725
    exec->GS.gep2 = 1;
 
726
 
 
727
    exec->GS.projVector.x = 0x4000;
 
728
    exec->GS.projVector.y = 0x0000;
 
729
 
 
730
    exec->GS.freeVector = exec->GS.projVector;
 
731
    exec->GS.dualVector = exec->GS.projVector;
 
732
 
 
733
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
 
734
    exec->GS.both_x_axis = TRUE;
 
735
#endif
 
736
 
 
737
    exec->GS.round_state = 1;
 
738
    exec->GS.loop        = 1;
 
739
 
 
740
    /* some glyphs leave something on the stack. so we clean it */
 
741
    /* before a new execution.                                  */
 
742
    exec->top     = 0;
 
743
    exec->callTop = 0;
 
744
 
 
745
#if 1
 
746
    FT_UNUSED( debug );
 
747
 
 
748
    return exec->face->interpreter( exec );
 
749
#else
 
750
    if ( !debug )
 
751
      return TT_RunIns( exec );
 
752
    else
 
753
      return TT_Err_Ok;
 
754
#endif
 
755
  }
 
756
 
 
757
 
 
758
  /* The default value for `scan_control' is documented as FALSE in the */
 
759
  /* TrueType specification.  This is confusing since it implies a      */
 
760
  /* Boolean value.  However, this is not the case, thus both the       */
 
761
  /* default values of our `scan_type' and `scan_control' fields (which */
 
762
  /* the documentation's `scan_control' variable is split into) are     */
 
763
  /* zero.                                                              */
 
764
 
 
765
  const TT_GraphicsState  tt_default_graphics_state =
 
766
  {
 
767
    0, 0, 0,
 
768
    { 0x4000, 0 },
 
769
    { 0x4000, 0 },
 
770
    { 0x4000, 0 },
 
771
 
 
772
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
 
773
    TRUE,
 
774
#endif
 
775
 
 
776
    1, 64, 1,
 
777
    TRUE, 68, 0, 0, 9, 3,
 
778
    0, FALSE, 0, 1, 1, 1
 
779
  };
 
780
 
 
781
 
 
782
  /* documentation is in ttinterp.h */
 
783
 
 
784
  FT_EXPORT_DEF( TT_ExecContext )
 
785
  TT_New_Context( TT_Driver  driver )
 
786
  {
 
787
    TT_ExecContext  exec;
 
788
    FT_Memory       memory;
 
789
 
 
790
 
 
791
    memory = driver->root.root.memory;
 
792
    exec   = driver->context;
 
793
 
 
794
    if ( !driver->context )
 
795
    {
 
796
      FT_Error  error;
 
797
 
 
798
 
 
799
      /* allocate object */
 
800
      if ( FT_NEW( exec ) )
 
801
        goto Fail;
 
802
 
 
803
      /* initialize it; in case of error this deallocates `exec' too */
 
804
      error = Init_Context( exec, memory );
 
805
      if ( error )
 
806
        goto Fail;
 
807
 
 
808
      /* store it into the driver */
 
809
      driver->context = exec;
 
810
    }
 
811
 
 
812
    return driver->context;
 
813
 
 
814
  Fail:
 
815
    return NULL;
 
816
  }
 
817
 
 
818
 
 
819
  /*************************************************************************/
 
820
  /*                                                                       */
 
821
  /* Before an opcode is executed, the interpreter verifies that there are */
 
822
  /* enough arguments on the stack, with the help of the `Pop_Push_Count'  */
 
823
  /* table.                                                                */
 
824
  /*                                                                       */
 
825
  /* For each opcode, the first column gives the number of arguments that  */
 
826
  /* are popped from the stack; the second one gives the number of those   */
 
827
  /* that are pushed in result.                                            */
 
828
  /*                                                                       */
 
829
  /* Opcodes which have a varying number of parameters in the data stream  */
 
830
  /* (NPUSHB, NPUSHW) are handled specially; they have a negative value in */
 
831
  /* the `opcode_length' table, and the value in `Pop_Push_Count' is set   */
 
832
  /* to zero.                                                              */
 
833
  /*                                                                       */
 
834
  /*************************************************************************/
 
835
 
 
836
 
 
837
#undef  PACK
 
838
#define PACK( x, y )  ( ( x << 4 ) | y )
 
839
 
 
840
 
 
841
  static
 
842
  const FT_Byte  Pop_Push_Count[256] =
 
843
  {
 
844
    /* opcodes are gathered in groups of 16 */
 
845
    /* please keep the spaces as they are   */
 
846
 
 
847
    /*  SVTCA  y  */  PACK( 0, 0 ),
 
848
    /*  SVTCA  x  */  PACK( 0, 0 ),
 
849
    /*  SPvTCA y  */  PACK( 0, 0 ),
 
850
    /*  SPvTCA x  */  PACK( 0, 0 ),
 
851
    /*  SFvTCA y  */  PACK( 0, 0 ),
 
852
    /*  SFvTCA x  */  PACK( 0, 0 ),
 
853
    /*  SPvTL //  */  PACK( 2, 0 ),
 
854
    /*  SPvTL +   */  PACK( 2, 0 ),
 
855
    /*  SFvTL //  */  PACK( 2, 0 ),
 
856
    /*  SFvTL +   */  PACK( 2, 0 ),
 
857
    /*  SPvFS     */  PACK( 2, 0 ),
 
858
    /*  SFvFS     */  PACK( 2, 0 ),
 
859
    /*  GPV       */  PACK( 0, 2 ),
 
860
    /*  GFV       */  PACK( 0, 2 ),
 
861
    /*  SFvTPv    */  PACK( 0, 0 ),
 
862
    /*  ISECT     */  PACK( 5, 0 ),
 
863
 
 
864
    /*  SRP0      */  PACK( 1, 0 ),
 
865
    /*  SRP1      */  PACK( 1, 0 ),
 
866
    /*  SRP2      */  PACK( 1, 0 ),
 
867
    /*  SZP0      */  PACK( 1, 0 ),
 
868
    /*  SZP1      */  PACK( 1, 0 ),
 
869
    /*  SZP2      */  PACK( 1, 0 ),
 
870
    /*  SZPS      */  PACK( 1, 0 ),
 
871
    /*  SLOOP     */  PACK( 1, 0 ),
 
872
    /*  RTG       */  PACK( 0, 0 ),
 
873
    /*  RTHG      */  PACK( 0, 0 ),
 
874
    /*  SMD       */  PACK( 1, 0 ),
 
875
    /*  ELSE      */  PACK( 0, 0 ),
 
876
    /*  JMPR      */  PACK( 1, 0 ),
 
877
    /*  SCvTCi    */  PACK( 1, 0 ),
 
878
    /*  SSwCi     */  PACK( 1, 0 ),
 
879
    /*  SSW       */  PACK( 1, 0 ),
 
880
 
 
881
    /*  DUP       */  PACK( 1, 2 ),
 
882
    /*  POP       */  PACK( 1, 0 ),
 
883
    /*  CLEAR     */  PACK( 0, 0 ),
 
884
    /*  SWAP      */  PACK( 2, 2 ),
 
885
    /*  DEPTH     */  PACK( 0, 1 ),
 
886
    /*  CINDEX    */  PACK( 1, 1 ),
 
887
    /*  MINDEX    */  PACK( 1, 0 ),
 
888
    /*  AlignPTS  */  PACK( 2, 0 ),
 
889
    /*  INS_$28   */  PACK( 0, 0 ),
 
890
    /*  UTP       */  PACK( 1, 0 ),
 
891
    /*  LOOPCALL  */  PACK( 2, 0 ),
 
892
    /*  CALL      */  PACK( 1, 0 ),
 
893
    /*  FDEF      */  PACK( 1, 0 ),
 
894
    /*  ENDF      */  PACK( 0, 0 ),
 
895
    /*  MDAP[0]   */  PACK( 1, 0 ),
 
896
    /*  MDAP[1]   */  PACK( 1, 0 ),
 
897
 
 
898
    /*  IUP[0]    */  PACK( 0, 0 ),
 
899
    /*  IUP[1]    */  PACK( 0, 0 ),
 
900
    /*  SHP[0]    */  PACK( 0, 0 ),
 
901
    /*  SHP[1]    */  PACK( 0, 0 ),
 
902
    /*  SHC[0]    */  PACK( 1, 0 ),
 
903
    /*  SHC[1]    */  PACK( 1, 0 ),
 
904
    /*  SHZ[0]    */  PACK( 1, 0 ),
 
905
    /*  SHZ[1]    */  PACK( 1, 0 ),
 
906
    /*  SHPIX     */  PACK( 1, 0 ),
 
907
    /*  IP        */  PACK( 0, 0 ),
 
908
    /*  MSIRP[0]  */  PACK( 2, 0 ),
 
909
    /*  MSIRP[1]  */  PACK( 2, 0 ),
 
910
    /*  AlignRP   */  PACK( 0, 0 ),
 
911
    /*  RTDG      */  PACK( 0, 0 ),
 
912
    /*  MIAP[0]   */  PACK( 2, 0 ),
 
913
    /*  MIAP[1]   */  PACK( 2, 0 ),
 
914
 
 
915
    /*  NPushB    */  PACK( 0, 0 ),
 
916
    /*  NPushW    */  PACK( 0, 0 ),
 
917
    /*  WS        */  PACK( 2, 0 ),
 
918
    /*  RS        */  PACK( 1, 1 ),
 
919
    /*  WCvtP     */  PACK( 2, 0 ),
 
920
    /*  RCvt      */  PACK( 1, 1 ),
 
921
    /*  GC[0]     */  PACK( 1, 1 ),
 
922
    /*  GC[1]     */  PACK( 1, 1 ),
 
923
    /*  SCFS      */  PACK( 2, 0 ),
 
924
    /*  MD[0]     */  PACK( 2, 1 ),
 
925
    /*  MD[1]     */  PACK( 2, 1 ),
 
926
    /*  MPPEM     */  PACK( 0, 1 ),
 
927
    /*  MPS       */  PACK( 0, 1 ),
 
928
    /*  FlipON    */  PACK( 0, 0 ),
 
929
    /*  FlipOFF   */  PACK( 0, 0 ),
 
930
    /*  DEBUG     */  PACK( 1, 0 ),
 
931
 
 
932
    /*  LT        */  PACK( 2, 1 ),
 
933
    /*  LTEQ      */  PACK( 2, 1 ),
 
934
    /*  GT        */  PACK( 2, 1 ),
 
935
    /*  GTEQ      */  PACK( 2, 1 ),
 
936
    /*  EQ        */  PACK( 2, 1 ),
 
937
    /*  NEQ       */  PACK( 2, 1 ),
 
938
    /*  ODD       */  PACK( 1, 1 ),
 
939
    /*  EVEN      */  PACK( 1, 1 ),
 
940
    /*  IF        */  PACK( 1, 0 ),
 
941
    /*  EIF       */  PACK( 0, 0 ),
 
942
    /*  AND       */  PACK( 2, 1 ),
 
943
    /*  OR        */  PACK( 2, 1 ),
 
944
    /*  NOT       */  PACK( 1, 1 ),
 
945
    /*  DeltaP1   */  PACK( 1, 0 ),
 
946
    /*  SDB       */  PACK( 1, 0 ),
 
947
    /*  SDS       */  PACK( 1, 0 ),
 
948
 
 
949
    /*  ADD       */  PACK( 2, 1 ),
 
950
    /*  SUB       */  PACK( 2, 1 ),
 
951
    /*  DIV       */  PACK( 2, 1 ),
 
952
    /*  MUL       */  PACK( 2, 1 ),
 
953
    /*  ABS       */  PACK( 1, 1 ),
 
954
    /*  NEG       */  PACK( 1, 1 ),
 
955
    /*  FLOOR     */  PACK( 1, 1 ),
 
956
    /*  CEILING   */  PACK( 1, 1 ),
 
957
    /*  ROUND[0]  */  PACK( 1, 1 ),
 
958
    /*  ROUND[1]  */  PACK( 1, 1 ),
 
959
    /*  ROUND[2]  */  PACK( 1, 1 ),
 
960
    /*  ROUND[3]  */  PACK( 1, 1 ),
 
961
    /*  NROUND[0] */  PACK( 1, 1 ),
 
962
    /*  NROUND[1] */  PACK( 1, 1 ),
 
963
    /*  NROUND[2] */  PACK( 1, 1 ),
 
964
    /*  NROUND[3] */  PACK( 1, 1 ),
 
965
 
 
966
    /*  WCvtF     */  PACK( 2, 0 ),
 
967
    /*  DeltaP2   */  PACK( 1, 0 ),
 
968
    /*  DeltaP3   */  PACK( 1, 0 ),
 
969
    /*  DeltaCn[0] */ PACK( 1, 0 ),
 
970
    /*  DeltaCn[1] */ PACK( 1, 0 ),
 
971
    /*  DeltaCn[2] */ PACK( 1, 0 ),
 
972
    /*  SROUND    */  PACK( 1, 0 ),
 
973
    /*  S45Round  */  PACK( 1, 0 ),
 
974
    /*  JROT      */  PACK( 2, 0 ),
 
975
    /*  JROF      */  PACK( 2, 0 ),
 
976
    /*  ROFF      */  PACK( 0, 0 ),
 
977
    /*  INS_$7B   */  PACK( 0, 0 ),
 
978
    /*  RUTG      */  PACK( 0, 0 ),
 
979
    /*  RDTG      */  PACK( 0, 0 ),
 
980
    /*  SANGW     */  PACK( 1, 0 ),
 
981
    /*  AA        */  PACK( 1, 0 ),
 
982
 
 
983
    /*  FlipPT    */  PACK( 0, 0 ),
 
984
    /*  FlipRgON  */  PACK( 2, 0 ),
 
985
    /*  FlipRgOFF */  PACK( 2, 0 ),
 
986
    /*  INS_$83   */  PACK( 0, 0 ),
 
987
    /*  INS_$84   */  PACK( 0, 0 ),
 
988
    /*  ScanCTRL  */  PACK( 1, 0 ),
 
989
    /*  SDVPTL[0] */  PACK( 2, 0 ),
 
990
    /*  SDVPTL[1] */  PACK( 2, 0 ),
 
991
    /*  GetINFO   */  PACK( 1, 1 ),
 
992
    /*  IDEF      */  PACK( 1, 0 ),
 
993
    /*  ROLL      */  PACK( 3, 3 ),
 
994
    /*  MAX       */  PACK( 2, 1 ),
 
995
    /*  MIN       */  PACK( 2, 1 ),
 
996
    /*  ScanTYPE  */  PACK( 1, 0 ),
 
997
    /*  InstCTRL  */  PACK( 2, 0 ),
 
998
    /*  INS_$8F   */  PACK( 0, 0 ),
 
999
 
 
1000
    /*  INS_$90  */   PACK( 0, 0 ),
 
1001
    /*  INS_$91  */   PACK( 0, 0 ),
 
1002
    /*  INS_$92  */   PACK( 0, 0 ),
 
1003
    /*  INS_$93  */   PACK( 0, 0 ),
 
1004
    /*  INS_$94  */   PACK( 0, 0 ),
 
1005
    /*  INS_$95  */   PACK( 0, 0 ),
 
1006
    /*  INS_$96  */   PACK( 0, 0 ),
 
1007
    /*  INS_$97  */   PACK( 0, 0 ),
 
1008
    /*  INS_$98  */   PACK( 0, 0 ),
 
1009
    /*  INS_$99  */   PACK( 0, 0 ),
 
1010
    /*  INS_$9A  */   PACK( 0, 0 ),
 
1011
    /*  INS_$9B  */   PACK( 0, 0 ),
 
1012
    /*  INS_$9C  */   PACK( 0, 0 ),
 
1013
    /*  INS_$9D  */   PACK( 0, 0 ),
 
1014
    /*  INS_$9E  */   PACK( 0, 0 ),
 
1015
    /*  INS_$9F  */   PACK( 0, 0 ),
 
1016
 
 
1017
    /*  INS_$A0  */   PACK( 0, 0 ),
 
1018
    /*  INS_$A1  */   PACK( 0, 0 ),
 
1019
    /*  INS_$A2  */   PACK( 0, 0 ),
 
1020
    /*  INS_$A3  */   PACK( 0, 0 ),
 
1021
    /*  INS_$A4  */   PACK( 0, 0 ),
 
1022
    /*  INS_$A5  */   PACK( 0, 0 ),
 
1023
    /*  INS_$A6  */   PACK( 0, 0 ),
 
1024
    /*  INS_$A7  */   PACK( 0, 0 ),
 
1025
    /*  INS_$A8  */   PACK( 0, 0 ),
 
1026
    /*  INS_$A9  */   PACK( 0, 0 ),
 
1027
    /*  INS_$AA  */   PACK( 0, 0 ),
 
1028
    /*  INS_$AB  */   PACK( 0, 0 ),
 
1029
    /*  INS_$AC  */   PACK( 0, 0 ),
 
1030
    /*  INS_$AD  */   PACK( 0, 0 ),
 
1031
    /*  INS_$AE  */   PACK( 0, 0 ),
 
1032
    /*  INS_$AF  */   PACK( 0, 0 ),
 
1033
 
 
1034
    /*  PushB[0]  */  PACK( 0, 1 ),
 
1035
    /*  PushB[1]  */  PACK( 0, 2 ),
 
1036
    /*  PushB[2]  */  PACK( 0, 3 ),
 
1037
    /*  PushB[3]  */  PACK( 0, 4 ),
 
1038
    /*  PushB[4]  */  PACK( 0, 5 ),
 
1039
    /*  PushB[5]  */  PACK( 0, 6 ),
 
1040
    /*  PushB[6]  */  PACK( 0, 7 ),
 
1041
    /*  PushB[7]  */  PACK( 0, 8 ),
 
1042
    /*  PushW[0]  */  PACK( 0, 1 ),
 
1043
    /*  PushW[1]  */  PACK( 0, 2 ),
 
1044
    /*  PushW[2]  */  PACK( 0, 3 ),
 
1045
    /*  PushW[3]  */  PACK( 0, 4 ),
 
1046
    /*  PushW[4]  */  PACK( 0, 5 ),
 
1047
    /*  PushW[5]  */  PACK( 0, 6 ),
 
1048
    /*  PushW[6]  */  PACK( 0, 7 ),
 
1049
    /*  PushW[7]  */  PACK( 0, 8 ),
 
1050
 
 
1051
    /*  MDRP[00]  */  PACK( 1, 0 ),
 
1052
    /*  MDRP[01]  */  PACK( 1, 0 ),
 
1053
    /*  MDRP[02]  */  PACK( 1, 0 ),
 
1054
    /*  MDRP[03]  */  PACK( 1, 0 ),
 
1055
    /*  MDRP[04]  */  PACK( 1, 0 ),
 
1056
    /*  MDRP[05]  */  PACK( 1, 0 ),
 
1057
    /*  MDRP[06]  */  PACK( 1, 0 ),
 
1058
    /*  MDRP[07]  */  PACK( 1, 0 ),
 
1059
    /*  MDRP[08]  */  PACK( 1, 0 ),
 
1060
    /*  MDRP[09]  */  PACK( 1, 0 ),
 
1061
    /*  MDRP[10]  */  PACK( 1, 0 ),
 
1062
    /*  MDRP[11]  */  PACK( 1, 0 ),
 
1063
    /*  MDRP[12]  */  PACK( 1, 0 ),
 
1064
    /*  MDRP[13]  */  PACK( 1, 0 ),
 
1065
    /*  MDRP[14]  */  PACK( 1, 0 ),
 
1066
    /*  MDRP[15]  */  PACK( 1, 0 ),
 
1067
 
 
1068
    /*  MDRP[16]  */  PACK( 1, 0 ),
 
1069
    /*  MDRP[17]  */  PACK( 1, 0 ),
 
1070
    /*  MDRP[18]  */  PACK( 1, 0 ),
 
1071
    /*  MDRP[19]  */  PACK( 1, 0 ),
 
1072
    /*  MDRP[20]  */  PACK( 1, 0 ),
 
1073
    /*  MDRP[21]  */  PACK( 1, 0 ),
 
1074
    /*  MDRP[22]  */  PACK( 1, 0 ),
 
1075
    /*  MDRP[23]  */  PACK( 1, 0 ),
 
1076
    /*  MDRP[24]  */  PACK( 1, 0 ),
 
1077
    /*  MDRP[25]  */  PACK( 1, 0 ),
 
1078
    /*  MDRP[26]  */  PACK( 1, 0 ),
 
1079
    /*  MDRP[27]  */  PACK( 1, 0 ),
 
1080
    /*  MDRP[28]  */  PACK( 1, 0 ),
 
1081
    /*  MDRP[29]  */  PACK( 1, 0 ),
 
1082
    /*  MDRP[30]  */  PACK( 1, 0 ),
 
1083
    /*  MDRP[31]  */  PACK( 1, 0 ),
 
1084
 
 
1085
    /*  MIRP[00]  */  PACK( 2, 0 ),
 
1086
    /*  MIRP[01]  */  PACK( 2, 0 ),
 
1087
    /*  MIRP[02]  */  PACK( 2, 0 ),
 
1088
    /*  MIRP[03]  */  PACK( 2, 0 ),
 
1089
    /*  MIRP[04]  */  PACK( 2, 0 ),
 
1090
    /*  MIRP[05]  */  PACK( 2, 0 ),
 
1091
    /*  MIRP[06]  */  PACK( 2, 0 ),
 
1092
    /*  MIRP[07]  */  PACK( 2, 0 ),
 
1093
    /*  MIRP[08]  */  PACK( 2, 0 ),
 
1094
    /*  MIRP[09]  */  PACK( 2, 0 ),
 
1095
    /*  MIRP[10]  */  PACK( 2, 0 ),
 
1096
    /*  MIRP[11]  */  PACK( 2, 0 ),
 
1097
    /*  MIRP[12]  */  PACK( 2, 0 ),
 
1098
    /*  MIRP[13]  */  PACK( 2, 0 ),
 
1099
    /*  MIRP[14]  */  PACK( 2, 0 ),
 
1100
    /*  MIRP[15]  */  PACK( 2, 0 ),
 
1101
 
 
1102
    /*  MIRP[16]  */  PACK( 2, 0 ),
 
1103
    /*  MIRP[17]  */  PACK( 2, 0 ),
 
1104
    /*  MIRP[18]  */  PACK( 2, 0 ),
 
1105
    /*  MIRP[19]  */  PACK( 2, 0 ),
 
1106
    /*  MIRP[20]  */  PACK( 2, 0 ),
 
1107
    /*  MIRP[21]  */  PACK( 2, 0 ),
 
1108
    /*  MIRP[22]  */  PACK( 2, 0 ),
 
1109
    /*  MIRP[23]  */  PACK( 2, 0 ),
 
1110
    /*  MIRP[24]  */  PACK( 2, 0 ),
 
1111
    /*  MIRP[25]  */  PACK( 2, 0 ),
 
1112
    /*  MIRP[26]  */  PACK( 2, 0 ),
 
1113
    /*  MIRP[27]  */  PACK( 2, 0 ),
 
1114
    /*  MIRP[28]  */  PACK( 2, 0 ),
 
1115
    /*  MIRP[29]  */  PACK( 2, 0 ),
 
1116
    /*  MIRP[30]  */  PACK( 2, 0 ),
 
1117
    /*  MIRP[31]  */  PACK( 2, 0 )
 
1118
  };
 
1119
 
 
1120
 
 
1121
#ifdef FT_DEBUG_LEVEL_TRACE
 
1122
 
 
1123
  static
 
1124
  const char*  const opcode_name[256] =
 
1125
  {
 
1126
    "SVTCA y",
 
1127
    "SVTCA x",
 
1128
    "SPvTCA y",
 
1129
    "SPvTCA x",
 
1130
    "SFvTCA y",
 
1131
    "SFvTCA x",
 
1132
    "SPvTL ||",
 
1133
    "SPvTL +",
 
1134
    "SFvTL ||",
 
1135
    "SFvTL +",
 
1136
    "SPvFS",
 
1137
    "SFvFS",
 
1138
    "GPV",
 
1139
    "GFV",
 
1140
    "SFvTPv",
 
1141
    "ISECT",
 
1142
 
 
1143
    "SRP0",
 
1144
    "SRP1",
 
1145
    "SRP2",
 
1146
    "SZP0",
 
1147
    "SZP1",
 
1148
    "SZP2",
 
1149
    "SZPS",
 
1150
    "SLOOP",
 
1151
    "RTG",
 
1152
    "RTHG",
 
1153
    "SMD",
 
1154
    "ELSE",
 
1155
    "JMPR",
 
1156
    "SCvTCi",
 
1157
    "SSwCi",
 
1158
    "SSW",
 
1159
 
 
1160
    "DUP",
 
1161
    "POP",
 
1162
    "CLEAR",
 
1163
    "SWAP",
 
1164
    "DEPTH",
 
1165
    "CINDEX",
 
1166
    "MINDEX",
 
1167
    "AlignPTS",
 
1168
    "INS_$28",
 
1169
    "UTP",
 
1170
    "LOOPCALL",
 
1171
    "CALL",
 
1172
    "FDEF",
 
1173
    "ENDF",
 
1174
    "MDAP[0]",
 
1175
    "MDAP[1]",
 
1176
 
 
1177
    "IUP[0]",
 
1178
    "IUP[1]",
 
1179
    "SHP[0]",
 
1180
    "SHP[1]",
 
1181
    "SHC[0]",
 
1182
    "SHC[1]",
 
1183
    "SHZ[0]",
 
1184
    "SHZ[1]",
 
1185
    "SHPIX",
 
1186
    "IP",
 
1187
    "MSIRP[0]",
 
1188
    "MSIRP[1]",
 
1189
    "AlignRP",
 
1190
    "RTDG",
 
1191
    "MIAP[0]",
 
1192
    "MIAP[1]",
 
1193
 
 
1194
    "NPushB",
 
1195
    "NPushW",
 
1196
    "WS",
 
1197
    "RS",
 
1198
    "WCvtP",
 
1199
    "RCvt",
 
1200
    "GC[0]",
 
1201
    "GC[1]",
 
1202
    "SCFS",
 
1203
    "MD[0]",
 
1204
    "MD[1]",
 
1205
    "MPPEM",
 
1206
    "MPS",
 
1207
    "FlipON",
 
1208
    "FlipOFF",
 
1209
    "DEBUG",
 
1210
 
 
1211
    "LT",
 
1212
    "LTEQ",
 
1213
    "GT",
 
1214
    "GTEQ",
 
1215
    "EQ",
 
1216
    "NEQ",
 
1217
    "ODD",
 
1218
    "EVEN",
 
1219
    "IF",
 
1220
    "EIF",
 
1221
    "AND",
 
1222
    "OR",
 
1223
    "NOT",
 
1224
    "DeltaP1",
 
1225
    "SDB",
 
1226
    "SDS",
 
1227
 
 
1228
    "ADD",
 
1229
    "SUB",
 
1230
    "DIV",
 
1231
    "MUL",
 
1232
    "ABS",
 
1233
    "NEG",
 
1234
    "FLOOR",
 
1235
    "CEILING",
 
1236
    "ROUND[0]",
 
1237
    "ROUND[1]",
 
1238
    "ROUND[2]",
 
1239
    "ROUND[3]",
 
1240
    "NROUND[0]",
 
1241
    "NROUND[1]",
 
1242
    "NROUND[2]",
 
1243
    "NROUND[3]",
 
1244
 
 
1245
    "WCvtF",
 
1246
    "DeltaP2",
 
1247
    "DeltaP3",
 
1248
    "DeltaCn[0]",
 
1249
    "DeltaCn[1]",
 
1250
    "DeltaCn[2]",
 
1251
    "SROUND",
 
1252
    "S45Round",
 
1253
    "JROT",
 
1254
    "JROF",
 
1255
    "ROFF",
 
1256
    "INS_$7B",
 
1257
    "RUTG",
 
1258
    "RDTG",
 
1259
    "SANGW",
 
1260
    "AA",
 
1261
 
 
1262
    "FlipPT",
 
1263
    "FlipRgON",
 
1264
    "FlipRgOFF",
 
1265
    "INS_$83",
 
1266
    "INS_$84",
 
1267
    "ScanCTRL",
 
1268
    "SDVPTL[0]",
 
1269
    "SDVPTL[1]",
 
1270
    "GetINFO",
 
1271
    "IDEF",
 
1272
    "ROLL",
 
1273
    "MAX",
 
1274
    "MIN",
 
1275
    "ScanTYPE",
 
1276
    "InstCTRL",
 
1277
    "INS_$8F",
 
1278
 
 
1279
    "INS_$90",
 
1280
    "INS_$91",
 
1281
    "INS_$92",
 
1282
    "INS_$93",
 
1283
    "INS_$94",
 
1284
    "INS_$95",
 
1285
    "INS_$96",
 
1286
    "INS_$97",
 
1287
    "INS_$98",
 
1288
    "INS_$99",
 
1289
    "INS_$9A",
 
1290
    "INS_$9B",
 
1291
    "INS_$9C",
 
1292
    "INS_$9D",
 
1293
    "INS_$9E",
 
1294
    "INS_$9F",
 
1295
 
 
1296
    "INS_$A0",
 
1297
    "INS_$A1",
 
1298
    "INS_$A2",
 
1299
    "INS_$A3",
 
1300
    "INS_$A4",
 
1301
    "INS_$A5",
 
1302
    "INS_$A6",
 
1303
    "INS_$A7",
 
1304
    "INS_$A8",
 
1305
    "INS_$A9",
 
1306
    "INS_$AA",
 
1307
    "INS_$AB",
 
1308
    "INS_$AC",
 
1309
    "INS_$AD",
 
1310
    "INS_$AE",
 
1311
    "INS_$AF",
 
1312
 
 
1313
    "PushB[0]",
 
1314
    "PushB[1]",
 
1315
    "PushB[2]",
 
1316
    "PushB[3]",
 
1317
    "PushB[4]",
 
1318
    "PushB[5]",
 
1319
    "PushB[6]",
 
1320
    "PushB[7]",
 
1321
    "PushW[0]",
 
1322
    "PushW[1]",
 
1323
    "PushW[2]",
 
1324
    "PushW[3]",
 
1325
    "PushW[4]",
 
1326
    "PushW[5]",
 
1327
    "PushW[6]",
 
1328
    "PushW[7]",
 
1329
 
 
1330
    "MDRP[00]",
 
1331
    "MDRP[01]",
 
1332
    "MDRP[02]",
 
1333
    "MDRP[03]",
 
1334
    "MDRP[04]",
 
1335
    "MDRP[05]",
 
1336
    "MDRP[06]",
 
1337
    "MDRP[07]",
 
1338
    "MDRP[08]",
 
1339
    "MDRP[09]",
 
1340
    "MDRP[10]",
 
1341
    "MDRP[11]",
 
1342
    "MDRP[12]",
 
1343
    "MDRP[13]",
 
1344
    "MDRP[14]",
 
1345
    "MDRP[15]",
 
1346
 
 
1347
    "MDRP[16]",
 
1348
    "MDRP[17]",
 
1349
    "MDRP[18]",
 
1350
    "MDRP[19]",
 
1351
    "MDRP[20]",
 
1352
    "MDRP[21]",
 
1353
    "MDRP[22]",
 
1354
    "MDRP[23]",
 
1355
    "MDRP[24]",
 
1356
    "MDRP[25]",
 
1357
    "MDRP[26]",
 
1358
    "MDRP[27]",
 
1359
    "MDRP[28]",
 
1360
    "MDRP[29]",
 
1361
    "MDRP[30]",
 
1362
    "MDRP[31]",
 
1363
 
 
1364
    "MIRP[00]",
 
1365
    "MIRP[01]",
 
1366
    "MIRP[02]",
 
1367
    "MIRP[03]",
 
1368
    "MIRP[04]",
 
1369
    "MIRP[05]",
 
1370
    "MIRP[06]",
 
1371
    "MIRP[07]",
 
1372
    "MIRP[08]",
 
1373
    "MIRP[09]",
 
1374
    "MIRP[10]",
 
1375
    "MIRP[11]",
 
1376
    "MIRP[12]",
 
1377
    "MIRP[13]",
 
1378
    "MIRP[14]",
 
1379
    "MIRP[15]",
 
1380
 
 
1381
    "MIRP[16]",
 
1382
    "MIRP[17]",
 
1383
    "MIRP[18]",
 
1384
    "MIRP[19]",
 
1385
    "MIRP[20]",
 
1386
    "MIRP[21]",
 
1387
    "MIRP[22]",
 
1388
    "MIRP[23]",
 
1389
    "MIRP[24]",
 
1390
    "MIRP[25]",
 
1391
    "MIRP[26]",
 
1392
    "MIRP[27]",
 
1393
    "MIRP[28]",
 
1394
    "MIRP[29]",
 
1395
    "MIRP[30]",
 
1396
    "MIRP[31]"
 
1397
  };
 
1398
 
 
1399
#endif /* FT_DEBUG_LEVEL_TRACE */
 
1400
 
 
1401
 
 
1402
  static
 
1403
  const FT_Char  opcode_length[256] =
 
1404
  {
 
1405
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
 
1406
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
 
1407
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
 
1408
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
 
1409
 
 
1410
   -1,-2, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
 
1411
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
 
1412
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
 
1413
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
 
1414
 
 
1415
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
 
1416
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
 
1417
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
 
1418
    2, 3, 4, 5,  6, 7, 8, 9,  3, 5, 7, 9, 11,13,15,17,
 
1419
 
 
1420
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
 
1421
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
 
1422
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
 
1423
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1
 
1424
  };
 
1425
 
 
1426
#undef PACK
 
1427
 
 
1428
#if 1
 
1429
 
 
1430
  static FT_Int32
 
1431
  TT_MulFix14( FT_Int32  a,
 
1432
               FT_Int    b )
 
1433
  {
 
1434
    FT_Int32   sign;
 
1435
    FT_UInt32  ah, al, mid, lo, hi;
 
1436
 
 
1437
 
 
1438
    sign = a ^ b;
 
1439
 
 
1440
    if ( a < 0 )
 
1441
      a = -a;
 
1442
    if ( b < 0 )
 
1443
      b = -b;
 
1444
 
 
1445
    ah = (FT_UInt32)( ( a >> 16 ) & 0xFFFFU );
 
1446
    al = (FT_UInt32)( a & 0xFFFFU );
 
1447
 
 
1448
    lo    = al * b;
 
1449
    mid   = ah * b;
 
1450
    hi    = mid >> 16;
 
1451
    mid   = ( mid << 16 ) + ( 1 << 13 ); /* rounding */
 
1452
    lo   += mid;
 
1453
    if ( lo < mid )
 
1454
      hi += 1;
 
1455
 
 
1456
    mid = ( lo >> 14 ) | ( hi << 18 );
 
1457
 
 
1458
    return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid;
 
1459
  }
 
1460
 
 
1461
#else
 
1462
 
 
1463
  /* compute (a*b)/2^14 with maximal accuracy and rounding */
 
1464
  static FT_Int32
 
1465
  TT_MulFix14( FT_Int32  a,
 
1466
               FT_Int    b )
 
1467
  {
 
1468
    FT_Int32   m, s, hi;
 
1469
    FT_UInt32  l, lo;
 
1470
 
 
1471
 
 
1472
    /* compute ax*bx as 64-bit value */
 
1473
    l  = (FT_UInt32)( ( a & 0xFFFFU ) * b );
 
1474
    m  = ( a >> 16 ) * b;
 
1475
 
 
1476
    lo = l + (FT_UInt32)( m << 16 );
 
1477
    hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l );
 
1478
 
 
1479
    /* divide the result by 2^14 with rounding */
 
1480
    s   = hi >> 31;
 
1481
    l   = lo + (FT_UInt32)s;
 
1482
    hi += s + ( l < lo );
 
1483
    lo  = l;
 
1484
 
 
1485
    l   = lo + 0x2000U;
 
1486
    hi += l < lo;
 
1487
 
 
1488
    return ( hi << 18 ) | ( l >> 14 );
 
1489
  }
 
1490
#endif
 
1491
 
 
1492
 
 
1493
  /* compute (ax*bx+ay*by)/2^14 with maximal accuracy and rounding */
 
1494
  static FT_Int32
 
1495
  TT_DotFix14( FT_Int32  ax,
 
1496
               FT_Int32  ay,
 
1497
               FT_Int    bx,
 
1498
               FT_Int    by )
 
1499
  {
 
1500
    FT_Int32   m, s, hi1, hi2, hi;
 
1501
    FT_UInt32  l, lo1, lo2, lo;
 
1502
 
 
1503
 
 
1504
    /* compute ax*bx as 64-bit value */
 
1505
    l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx );
 
1506
    m = ( ax >> 16 ) * bx;
 
1507
 
 
1508
    lo1 = l + (FT_UInt32)( m << 16 );
 
1509
    hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l );
 
1510
 
 
1511
    /* compute ay*by as 64-bit value */
 
1512
    l = (FT_UInt32)( ( ay & 0xFFFFU ) * by );
 
1513
    m = ( ay >> 16 ) * by;
 
1514
 
 
1515
    lo2 = l + (FT_UInt32)( m << 16 );
 
1516
    hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l );
 
1517
 
 
1518
    /* add them */
 
1519
    lo = lo1 + lo2;
 
1520
    hi = hi1 + hi2 + ( lo < lo1 );
 
1521
 
 
1522
    /* divide the result by 2^14 with rounding */
 
1523
    s   = hi >> 31;
 
1524
    l   = lo + (FT_UInt32)s;
 
1525
    hi += s + ( l < lo );
 
1526
    lo  = l;
 
1527
 
 
1528
    l   = lo + 0x2000U;
 
1529
    hi += ( l < lo );
 
1530
 
 
1531
    return ( hi << 18 ) | ( l >> 14 );
 
1532
  }
 
1533
 
 
1534
 
 
1535
  /* return length of given vector */
 
1536
 
 
1537
#if 0
 
1538
 
 
1539
  static FT_Int32
 
1540
  TT_VecLen( FT_Int32  x,
 
1541
             FT_Int32  y )
 
1542
  {
 
1543
    FT_Int32   m, hi1, hi2, hi;
 
1544
    FT_UInt32  l, lo1, lo2, lo;
 
1545
 
 
1546
 
 
1547
    /* compute x*x as 64-bit value */
 
1548
    lo = (FT_UInt32)( x & 0xFFFFU );
 
1549
    hi = x >> 16;
 
1550
 
 
1551
    l  = lo * lo;
 
1552
    m  = hi * lo;
 
1553
    hi = hi * hi;
 
1554
 
 
1555
    lo1 = l + (FT_UInt32)( m << 17 );
 
1556
    hi1 = hi + ( m >> 15 ) + ( lo1 < l );
 
1557
 
 
1558
    /* compute y*y as 64-bit value */
 
1559
    lo = (FT_UInt32)( y & 0xFFFFU );
 
1560
    hi = y >> 16;
 
1561
 
 
1562
    l  = lo * lo;
 
1563
    m  = hi * lo;
 
1564
    hi = hi * hi;
 
1565
 
 
1566
    lo2 = l + (FT_UInt32)( m << 17 );
 
1567
    hi2 = hi + ( m >> 15 ) + ( lo2 < l );
 
1568
 
 
1569
    /* add them to get 'x*x+y*y' as 64-bit value */
 
1570
    lo = lo1 + lo2;
 
1571
    hi = hi1 + hi2 + ( lo < lo1 );
 
1572
 
 
1573
    /* compute the square root of this value */
 
1574
    {
 
1575
      FT_UInt32  root, rem, test_div;
 
1576
      FT_Int     count;
 
1577
 
 
1578
 
 
1579
      root = 0;
 
1580
 
 
1581
      {
 
1582
        rem   = 0;
 
1583
        count = 32;
 
1584
        do
 
1585
        {
 
1586
          rem      = ( rem << 2 ) | ( (FT_UInt32)hi >> 30 );
 
1587
          hi       = (  hi << 2 ) | (            lo >> 30 );
 
1588
          lo     <<= 2;
 
1589
          root   <<= 1;
 
1590
          test_div = ( root << 1 ) + 1;
 
1591
 
 
1592
          if ( rem >= test_div )
 
1593
          {
 
1594
            rem  -= test_div;
 
1595
            root += 1;
 
1596
          }
 
1597
        } while ( --count );
 
1598
      }
 
1599
 
 
1600
      return (FT_Int32)root;
 
1601
    }
 
1602
  }
 
1603
 
 
1604
#else
 
1605
 
 
1606
  /* this version uses FT_Vector_Length which computes the same value */
 
1607
  /* much, much faster..                                              */
 
1608
  /*                                                                  */
 
1609
  static FT_F26Dot6
 
1610
  TT_VecLen( FT_F26Dot6  X,
 
1611
             FT_F26Dot6  Y )
 
1612
  {
 
1613
    FT_Vector  v;
 
1614
 
 
1615
 
 
1616
    v.x = X;
 
1617
    v.y = Y;
 
1618
 
 
1619
    return FT_Vector_Length( &v );
 
1620
  }
 
1621
 
 
1622
#endif
 
1623
 
 
1624
 
 
1625
  /*************************************************************************/
 
1626
  /*                                                                       */
 
1627
  /* <Function>                                                            */
 
1628
  /*    Current_Ratio                                                      */
 
1629
  /*                                                                       */
 
1630
  /* <Description>                                                         */
 
1631
  /*    Returns the current aspect ratio scaling factor depending on the   */
 
1632
  /*    projection vector's state and device resolutions.                  */
 
1633
  /*                                                                       */
 
1634
  /* <Return>                                                              */
 
1635
  /*    The aspect ratio in 16.16 format, always <= 1.0 .                  */
 
1636
  /*                                                                       */
 
1637
  static FT_Long
 
1638
  Current_Ratio( EXEC_OP )
 
1639
  {
 
1640
    if ( !CUR.tt_metrics.ratio )
 
1641
    {
 
1642
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
 
1643
      if ( CUR.face->unpatented_hinting )
 
1644
      {
 
1645
        if ( CUR.GS.both_x_axis )
 
1646
          CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
 
1647
        else
 
1648
          CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
 
1649
      }
 
1650
      else
 
1651
#endif
 
1652
      {
 
1653
        if ( CUR.GS.projVector.y == 0 )
 
1654
          CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
 
1655
 
 
1656
        else if ( CUR.GS.projVector.x == 0 )
 
1657
          CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
 
1658
 
 
1659
        else
 
1660
        {
 
1661
          FT_Long  x, y;
 
1662
 
 
1663
 
 
1664
          x = TT_MULDIV( CUR.GS.projVector.x,
 
1665
                         CUR.tt_metrics.x_ratio, 0x4000 );
 
1666
          y = TT_MULDIV( CUR.GS.projVector.y,
 
1667
                         CUR.tt_metrics.y_ratio, 0x4000 );
 
1668
          CUR.tt_metrics.ratio = TT_VecLen( x, y );
 
1669
        }
 
1670
      }
 
1671
    }
 
1672
    return CUR.tt_metrics.ratio;
 
1673
  }
 
1674
 
 
1675
 
 
1676
  static FT_Long
 
1677
  Current_Ppem( EXEC_OP )
 
1678
  {
 
1679
    return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() );
 
1680
  }
 
1681
 
 
1682
 
 
1683
  /*************************************************************************/
 
1684
  /*                                                                       */
 
1685
  /* Functions related to the control value table (CVT).                   */
 
1686
  /*                                                                       */
 
1687
  /*************************************************************************/
 
1688
 
 
1689
 
 
1690
  FT_CALLBACK_DEF( FT_F26Dot6 )
 
1691
  Read_CVT( EXEC_OP_ FT_ULong  idx )
 
1692
  {
 
1693
    return CUR.cvt[idx];
 
1694
  }
 
1695
 
 
1696
 
 
1697
  FT_CALLBACK_DEF( FT_F26Dot6 )
 
1698
  Read_CVT_Stretched( EXEC_OP_ FT_ULong  idx )
 
1699
  {
 
1700
    return TT_MULFIX( CUR.cvt[idx], CURRENT_Ratio() );
 
1701
  }
 
1702
 
 
1703
 
 
1704
  FT_CALLBACK_DEF( void )
 
1705
  Write_CVT( EXEC_OP_ FT_ULong    idx,
 
1706
                      FT_F26Dot6  value )
 
1707
  {
 
1708
    CUR.cvt[idx] = value;
 
1709
  }
 
1710
 
 
1711
 
 
1712
  FT_CALLBACK_DEF( void )
 
1713
  Write_CVT_Stretched( EXEC_OP_ FT_ULong    idx,
 
1714
                                FT_F26Dot6  value )
 
1715
  {
 
1716
    CUR.cvt[idx] = FT_DivFix( value, CURRENT_Ratio() );
 
1717
  }
 
1718
 
 
1719
 
 
1720
  FT_CALLBACK_DEF( void )
 
1721
  Move_CVT( EXEC_OP_ FT_ULong    idx,
 
1722
                     FT_F26Dot6  value )
 
1723
  {
 
1724
    CUR.cvt[idx] += value;
 
1725
  }
 
1726
 
 
1727
 
 
1728
  FT_CALLBACK_DEF( void )
 
1729
  Move_CVT_Stretched( EXEC_OP_ FT_ULong    idx,
 
1730
                               FT_F26Dot6  value )
 
1731
  {
 
1732
    CUR.cvt[idx] += FT_DivFix( value, CURRENT_Ratio() );
 
1733
  }
 
1734
 
 
1735
 
 
1736
  /*************************************************************************/
 
1737
  /*                                                                       */
 
1738
  /* <Function>                                                            */
 
1739
  /*    GetShortIns                                                        */
 
1740
  /*                                                                       */
 
1741
  /* <Description>                                                         */
 
1742
  /*    Returns a short integer taken from the instruction stream at       */
 
1743
  /*    address IP.                                                        */
 
1744
  /*                                                                       */
 
1745
  /* <Return>                                                              */
 
1746
  /*    Short read at code[IP].                                            */
 
1747
  /*                                                                       */
 
1748
  /* <Note>                                                                */
 
1749
  /*    This one could become a macro.                                     */
 
1750
  /*                                                                       */
 
1751
  static FT_Short
 
1752
  GetShortIns( EXEC_OP )
 
1753
  {
 
1754
    /* Reading a byte stream so there is no endianess (DaveP) */
 
1755
    CUR.IP += 2;
 
1756
    return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) +
 
1757
                         CUR.code[CUR.IP - 1]      );
 
1758
  }
 
1759
 
 
1760
 
 
1761
  /*************************************************************************/
 
1762
  /*                                                                       */
 
1763
  /* <Function>                                                            */
 
1764
  /*    Ins_Goto_CodeRange                                                 */
 
1765
  /*                                                                       */
 
1766
  /* <Description>                                                         */
 
1767
  /*    Goes to a certain code range in the instruction stream.            */
 
1768
  /*                                                                       */
 
1769
  /* <Input>                                                               */
 
1770
  /*    aRange :: The index of the code range.                             */
 
1771
  /*                                                                       */
 
1772
  /*    aIP    :: The new IP address in the code range.                    */
 
1773
  /*                                                                       */
 
1774
  /* <Return>                                                              */
 
1775
  /*    SUCCESS or FAILURE.                                                */
 
1776
  /*                                                                       */
 
1777
  static FT_Bool
 
1778
  Ins_Goto_CodeRange( EXEC_OP_ FT_Int    aRange,
 
1779
                               FT_ULong  aIP )
 
1780
  {
 
1781
    TT_CodeRange*  range;
 
1782
 
 
1783
 
 
1784
    if ( aRange < 1 || aRange > 3 )
 
1785
    {
 
1786
      CUR.error = TT_Err_Bad_Argument;
 
1787
      return FAILURE;
 
1788
    }
 
1789
 
 
1790
    range = &CUR.codeRangeTable[aRange - 1];
 
1791
 
 
1792
    if ( range->base == NULL )     /* invalid coderange */
 
1793
    {
 
1794
      CUR.error = TT_Err_Invalid_CodeRange;
 
1795
      return FAILURE;
 
1796
    }
 
1797
 
 
1798
    /* NOTE: Because the last instruction of a program may be a CALL */
 
1799
    /*       which will return to the first byte *after* the code    */
 
1800
    /*       range, we test for AIP <= Size, instead of AIP < Size.  */
 
1801
 
 
1802
    if ( aIP > range->size )
 
1803
    {
 
1804
      CUR.error = TT_Err_Code_Overflow;
 
1805
      return FAILURE;
 
1806
    }
 
1807
 
 
1808
    CUR.code     = range->base;
 
1809
    CUR.codeSize = range->size;
 
1810
    CUR.IP       = aIP;
 
1811
    CUR.curRange = aRange;
 
1812
 
 
1813
    return SUCCESS;
 
1814
  }
 
1815
 
 
1816
 
 
1817
  /*************************************************************************/
 
1818
  /*                                                                       */
 
1819
  /* <Function>                                                            */
 
1820
  /*    Direct_Move                                                        */
 
1821
  /*                                                                       */
 
1822
  /* <Description>                                                         */
 
1823
  /*    Moves a point by a given distance along the freedom vector.  The   */
 
1824
  /*    point will be `touched'.                                           */
 
1825
  /*                                                                       */
 
1826
  /* <Input>                                                               */
 
1827
  /*    point    :: The index of the point to move.                        */
 
1828
  /*                                                                       */
 
1829
  /*    distance :: The distance to apply.                                 */
 
1830
  /*                                                                       */
 
1831
  /* <InOut>                                                               */
 
1832
  /*    zone     :: The affected glyph zone.                               */
 
1833
  /*                                                                       */
 
1834
  static void
 
1835
  Direct_Move( EXEC_OP_ TT_GlyphZone  zone,
 
1836
                        FT_UShort     point,
 
1837
                        FT_F26Dot6    distance )
 
1838
  {
 
1839
    FT_F26Dot6  v;
 
1840
 
 
1841
 
 
1842
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
 
1843
    FT_ASSERT( !CUR.face->unpatented_hinting );
 
1844
#endif
 
1845
 
 
1846
    v = CUR.GS.freeVector.x;
 
1847
 
 
1848
    if ( v != 0 )
 
1849
    {
 
1850
      zone->cur[point].x += TT_MULDIV( distance,
 
1851
                                       v * 0x10000L,
 
1852
                                       CUR.F_dot_P );
 
1853
 
 
1854
      zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
 
1855
    }
 
1856
 
 
1857
    v = CUR.GS.freeVector.y;
 
1858
 
 
1859
    if ( v != 0 )
 
1860
    {
 
1861
      zone->cur[point].y += TT_MULDIV( distance,
 
1862
                                       v * 0x10000L,
 
1863
                                       CUR.F_dot_P );
 
1864
 
 
1865
      zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
 
1866
    }
 
1867
  }
 
1868
 
 
1869
 
 
1870
  /*************************************************************************/
 
1871
  /*                                                                       */
 
1872
  /* <Function>                                                            */
 
1873
  /*    Direct_Move_Orig                                                   */
 
1874
  /*                                                                       */
 
1875
  /* <Description>                                                         */
 
1876
  /*    Moves the *original* position of a point by a given distance along */
 
1877
  /*    the freedom vector.  Obviously, the point will not be `touched'.   */
 
1878
  /*                                                                       */
 
1879
  /* <Input>                                                               */
 
1880
  /*    point    :: The index of the point to move.                        */
 
1881
  /*                                                                       */
 
1882
  /*    distance :: The distance to apply.                                 */
 
1883
  /*                                                                       */
 
1884
  /* <InOut>                                                               */
 
1885
  /*    zone     :: The affected glyph zone.                               */
 
1886
  /*                                                                       */
 
1887
  static void
 
1888
  Direct_Move_Orig( EXEC_OP_ TT_GlyphZone  zone,
 
1889
                             FT_UShort     point,
 
1890
                             FT_F26Dot6    distance )
 
1891
  {
 
1892
    FT_F26Dot6  v;
 
1893
 
 
1894
 
 
1895
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
 
1896
    FT_ASSERT( !CUR.face->unpatented_hinting );
 
1897
#endif
 
1898
 
 
1899
    v = CUR.GS.freeVector.x;
 
1900
 
 
1901
    if ( v != 0 )
 
1902
      zone->org[point].x += TT_MULDIV( distance,
 
1903
                                       v * 0x10000L,
 
1904
                                       CUR.F_dot_P );
 
1905
 
 
1906
    v = CUR.GS.freeVector.y;
 
1907
 
 
1908
    if ( v != 0 )
 
1909
      zone->org[point].y += TT_MULDIV( distance,
 
1910
                                       v * 0x10000L,
 
1911
                                       CUR.F_dot_P );
 
1912
  }
 
1913
 
 
1914
 
 
1915
  /*************************************************************************/
 
1916
  /*                                                                       */
 
1917
  /* Special versions of Direct_Move()                                     */
 
1918
  /*                                                                       */
 
1919
  /*   The following versions are used whenever both vectors are both      */
 
1920
  /*   along one of the coordinate unit vectors, i.e. in 90% of the cases. */
 
1921
  /*                                                                       */
 
1922
  /*************************************************************************/
 
1923
 
 
1924
 
 
1925
  static void
 
1926
  Direct_Move_X( EXEC_OP_ TT_GlyphZone  zone,
 
1927
                          FT_UShort     point,
 
1928
                          FT_F26Dot6    distance )
 
1929
  {
 
1930
    FT_UNUSED_EXEC;
 
1931
 
 
1932
    zone->cur[point].x += distance;
 
1933
    zone->tags[point]  |= FT_CURVE_TAG_TOUCH_X;
 
1934
  }
 
1935
 
 
1936
 
 
1937
  static void
 
1938
  Direct_Move_Y( EXEC_OP_ TT_GlyphZone  zone,
 
1939
                          FT_UShort     point,
 
1940
                          FT_F26Dot6    distance )
 
1941
  {
 
1942
    FT_UNUSED_EXEC;
 
1943
 
 
1944
    zone->cur[point].y += distance;
 
1945
    zone->tags[point]  |= FT_CURVE_TAG_TOUCH_Y;
 
1946
  }
 
1947
 
 
1948
 
 
1949
  /*************************************************************************/
 
1950
  /*                                                                       */
 
1951
  /* Special versions of Direct_Move_Orig()                                */
 
1952
  /*                                                                       */
 
1953
  /*   The following versions are used whenever both vectors are both      */
 
1954
  /*   along one of the coordinate unit vectors, i.e. in 90% of the cases. */
 
1955
  /*                                                                       */
 
1956
  /*************************************************************************/
 
1957
 
 
1958
 
 
1959
  static void
 
1960
  Direct_Move_Orig_X( EXEC_OP_ TT_GlyphZone  zone,
 
1961
                               FT_UShort     point,
 
1962
                               FT_F26Dot6    distance )
 
1963
  {
 
1964
    FT_UNUSED_EXEC;
 
1965
 
 
1966
    zone->org[point].x += distance;
 
1967
  }
 
1968
 
 
1969
 
 
1970
  static void
 
1971
  Direct_Move_Orig_Y( EXEC_OP_ TT_GlyphZone  zone,
 
1972
                               FT_UShort     point,
 
1973
                               FT_F26Dot6    distance )
 
1974
  {
 
1975
    FT_UNUSED_EXEC;
 
1976
 
 
1977
    zone->org[point].y += distance;
 
1978
  }
 
1979
 
 
1980
 
 
1981
  /*************************************************************************/
 
1982
  /*                                                                       */
 
1983
  /* <Function>                                                            */
 
1984
  /*    Round_None                                                         */
 
1985
  /*                                                                       */
 
1986
  /* <Description>                                                         */
 
1987
  /*    Does not round, but adds engine compensation.                      */
 
1988
  /*                                                                       */
 
1989
  /* <Input>                                                               */
 
1990
  /*    distance     :: The distance (not) to round.                       */
 
1991
  /*                                                                       */
 
1992
  /*    compensation :: The engine compensation.                           */
 
1993
  /*                                                                       */
 
1994
  /* <Return>                                                              */
 
1995
  /*    The compensated distance.                                          */
 
1996
  /*                                                                       */
 
1997
  /* <Note>                                                                */
 
1998
  /*    The TrueType specification says very few about the relationship    */
 
1999
  /*    between rounding and engine compensation.  However, it seems from  */
 
2000
  /*    the description of super round that we should add the compensation */
 
2001
  /*    before rounding.                                                   */
 
2002
  /*                                                                       */
 
2003
  static FT_F26Dot6
 
2004
  Round_None( EXEC_OP_ FT_F26Dot6  distance,
 
2005
                       FT_F26Dot6  compensation )
 
2006
  {
 
2007
    FT_F26Dot6  val;
 
2008
 
 
2009
    FT_UNUSED_EXEC;
 
2010
 
 
2011
 
 
2012
    if ( distance >= 0 )
 
2013
    {
 
2014
      val = distance + compensation;
 
2015
      if ( distance && val < 0 )
 
2016
        val = 0;
 
2017
    }
 
2018
    else
 
2019
    {
 
2020
      val = distance - compensation;
 
2021
      if ( val > 0 )
 
2022
        val = 0;
 
2023
    }
 
2024
    return val;
 
2025
  }
 
2026
 
 
2027
 
 
2028
  /*************************************************************************/
 
2029
  /*                                                                       */
 
2030
  /* <Function>                                                            */
 
2031
  /*    Round_To_Grid                                                      */
 
2032
  /*                                                                       */
 
2033
  /* <Description>                                                         */
 
2034
  /*    Rounds value to grid after adding engine compensation.             */
 
2035
  /*                                                                       */
 
2036
  /* <Input>                                                               */
 
2037
  /*    distance     :: The distance to round.                             */
 
2038
  /*                                                                       */
 
2039
  /*    compensation :: The engine compensation.                           */
 
2040
  /*                                                                       */
 
2041
  /* <Return>                                                              */
 
2042
  /*    Rounded distance.                                                  */
 
2043
  /*                                                                       */
 
2044
  static FT_F26Dot6
 
2045
  Round_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
 
2046
                          FT_F26Dot6  compensation )
 
2047
  {
 
2048
    FT_F26Dot6  val;
 
2049
 
 
2050
    FT_UNUSED_EXEC;
 
2051
 
 
2052
 
 
2053
    if ( distance >= 0 )
 
2054
    {
 
2055
      val = distance + compensation + 32;
 
2056
      if ( distance && val > 0 )
 
2057
        val &= ~63;
 
2058
      else
 
2059
        val = 0;
 
2060
    }
 
2061
    else
 
2062
    {
 
2063
      val = -FT_PIX_ROUND( compensation - distance );
 
2064
      if ( val > 0 )
 
2065
        val = 0;
 
2066
    }
 
2067
 
 
2068
    return  val;
 
2069
  }
 
2070
 
 
2071
 
 
2072
  /*************************************************************************/
 
2073
  /*                                                                       */
 
2074
  /* <Function>                                                            */
 
2075
  /*    Round_To_Half_Grid                                                 */
 
2076
  /*                                                                       */
 
2077
  /* <Description>                                                         */
 
2078
  /*    Rounds value to half grid after adding engine compensation.        */
 
2079
  /*                                                                       */
 
2080
  /* <Input>                                                               */
 
2081
  /*    distance     :: The distance to round.                             */
 
2082
  /*                                                                       */
 
2083
  /*    compensation :: The engine compensation.                           */
 
2084
  /*                                                                       */
 
2085
  /* <Return>                                                              */
 
2086
  /*    Rounded distance.                                                  */
 
2087
  /*                                                                       */
 
2088
  static FT_F26Dot6
 
2089
  Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6  distance,
 
2090
                               FT_F26Dot6  compensation )
 
2091
  {
 
2092
    FT_F26Dot6  val;
 
2093
 
 
2094
    FT_UNUSED_EXEC;
 
2095
 
 
2096
 
 
2097
    if ( distance >= 0 )
 
2098
    {
 
2099
      val = FT_PIX_FLOOR( distance + compensation ) + 32;
 
2100
      if ( distance && val < 0 )
 
2101
        val = 0;
 
2102
    }
 
2103
    else
 
2104
    {
 
2105
      val = -( FT_PIX_FLOOR( compensation - distance ) + 32 );
 
2106
      if ( val > 0 )
 
2107
        val = 0;
 
2108
    }
 
2109
 
 
2110
    return val;
 
2111
  }
 
2112
 
 
2113
 
 
2114
  /*************************************************************************/
 
2115
  /*                                                                       */
 
2116
  /* <Function>                                                            */
 
2117
  /*    Round_Down_To_Grid                                                 */
 
2118
  /*                                                                       */
 
2119
  /* <Description>                                                         */
 
2120
  /*    Rounds value down to grid after adding engine compensation.        */
 
2121
  /*                                                                       */
 
2122
  /* <Input>                                                               */
 
2123
  /*    distance     :: The distance to round.                             */
 
2124
  /*                                                                       */
 
2125
  /*    compensation :: The engine compensation.                           */
 
2126
  /*                                                                       */
 
2127
  /* <Return>                                                              */
 
2128
  /*    Rounded distance.                                                  */
 
2129
  /*                                                                       */
 
2130
  static FT_F26Dot6
 
2131
  Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
 
2132
                               FT_F26Dot6  compensation )
 
2133
  {
 
2134
    FT_F26Dot6  val;
 
2135
 
 
2136
    FT_UNUSED_EXEC;
 
2137
 
 
2138
 
 
2139
    if ( distance >= 0 )
 
2140
    {
 
2141
      val = distance + compensation;
 
2142
      if ( distance && val > 0 )
 
2143
        val &= ~63;
 
2144
      else
 
2145
        val = 0;
 
2146
    }
 
2147
    else
 
2148
    {
 
2149
      val = -( ( compensation - distance ) & -64 );
 
2150
      if ( val > 0 )
 
2151
        val = 0;
 
2152
    }
 
2153
 
 
2154
    return val;
 
2155
  }
 
2156
 
 
2157
 
 
2158
  /*************************************************************************/
 
2159
  /*                                                                       */
 
2160
  /* <Function>                                                            */
 
2161
  /*    Round_Up_To_Grid                                                   */
 
2162
  /*                                                                       */
 
2163
  /* <Description>                                                         */
 
2164
  /*    Rounds value up to grid after adding engine compensation.          */
 
2165
  /*                                                                       */
 
2166
  /* <Input>                                                               */
 
2167
  /*    distance     :: The distance to round.                             */
 
2168
  /*                                                                       */
 
2169
  /*    compensation :: The engine compensation.                           */
 
2170
  /*                                                                       */
 
2171
  /* <Return>                                                              */
 
2172
  /*    Rounded distance.                                                  */
 
2173
  /*                                                                       */
 
2174
  static FT_F26Dot6
 
2175
  Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
 
2176
                             FT_F26Dot6  compensation )
 
2177
  {
 
2178
    FT_F26Dot6  val;
 
2179
 
 
2180
    FT_UNUSED_EXEC;
 
2181
 
 
2182
 
 
2183
    if ( distance >= 0 )
 
2184
    {
 
2185
      val = distance + compensation + 63;
 
2186
      if ( distance && val > 0 )
 
2187
        val &= ~63;
 
2188
      else
 
2189
        val = 0;
 
2190
    }
 
2191
    else
 
2192
    {
 
2193
      val = - FT_PIX_CEIL( compensation - distance );
 
2194
      if ( val > 0 )
 
2195
        val = 0;
 
2196
    }
 
2197
 
 
2198
    return val;
 
2199
  }
 
2200
 
 
2201
 
 
2202
  /*************************************************************************/
 
2203
  /*                                                                       */
 
2204
  /* <Function>                                                            */
 
2205
  /*    Round_To_Double_Grid                                               */
 
2206
  /*                                                                       */
 
2207
  /* <Description>                                                         */
 
2208
  /*    Rounds value to double grid after adding engine compensation.      */
 
2209
  /*                                                                       */
 
2210
  /* <Input>                                                               */
 
2211
  /*    distance     :: The distance to round.                             */
 
2212
  /*                                                                       */
 
2213
  /*    compensation :: The engine compensation.                           */
 
2214
  /*                                                                       */
 
2215
  /* <Return>                                                              */
 
2216
  /*    Rounded distance.                                                  */
 
2217
  /*                                                                       */
 
2218
  static FT_F26Dot6
 
2219
  Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6  distance,
 
2220
                                 FT_F26Dot6  compensation )
 
2221
  {
 
2222
    FT_F26Dot6 val;
 
2223
 
 
2224
    FT_UNUSED_EXEC;
 
2225
 
 
2226
 
 
2227
    if ( distance >= 0 )
 
2228
    {
 
2229
      val = distance + compensation + 16;
 
2230
      if ( distance && val > 0 )
 
2231
        val &= ~31;
 
2232
      else
 
2233
        val = 0;
 
2234
    }
 
2235
    else
 
2236
    {
 
2237
      val = -FT_PAD_ROUND( compensation - distance, 32 );
 
2238
      if ( val > 0 )
 
2239
        val = 0;
 
2240
    }
 
2241
 
 
2242
    return val;
 
2243
  }
 
2244
 
 
2245
 
 
2246
  /*************************************************************************/
 
2247
  /*                                                                       */
 
2248
  /* <Function>                                                            */
 
2249
  /*    Round_Super                                                        */
 
2250
  /*                                                                       */
 
2251
  /* <Description>                                                         */
 
2252
  /*    Super-rounds value to grid after adding engine compensation.       */
 
2253
  /*                                                                       */
 
2254
  /* <Input>                                                               */
 
2255
  /*    distance     :: The distance to round.                             */
 
2256
  /*                                                                       */
 
2257
  /*    compensation :: The engine compensation.                           */
 
2258
  /*                                                                       */
 
2259
  /* <Return>                                                              */
 
2260
  /*    Rounded distance.                                                  */
 
2261
  /*                                                                       */
 
2262
  /* <Note>                                                                */
 
2263
  /*    The TrueType specification says very few about the relationship    */
 
2264
  /*    between rounding and engine compensation.  However, it seems from  */
 
2265
  /*    the description of super round that we should add the compensation */
 
2266
  /*    before rounding.                                                   */
 
2267
  /*                                                                       */
 
2268
  static FT_F26Dot6
 
2269
  Round_Super( EXEC_OP_ FT_F26Dot6  distance,
 
2270
                        FT_F26Dot6  compensation )
 
2271
  {
 
2272
    FT_F26Dot6  val;
 
2273
 
 
2274
 
 
2275
    if ( distance >= 0 )
 
2276
    {
 
2277
      val = ( distance - CUR.phase + CUR.threshold + compensation ) &
 
2278
              -CUR.period;
 
2279
      if ( distance && val < 0 )
 
2280
        val = 0;
 
2281
      val += CUR.phase;
 
2282
    }
 
2283
    else
 
2284
    {
 
2285
      val = -( ( CUR.threshold - CUR.phase - distance + compensation ) &
 
2286
               -CUR.period );
 
2287
      if ( val > 0 )
 
2288
        val = 0;
 
2289
      val -= CUR.phase;
 
2290
    }
 
2291
 
 
2292
    return val;
 
2293
  }
 
2294
 
 
2295
 
 
2296
  /*************************************************************************/
 
2297
  /*                                                                       */
 
2298
  /* <Function>                                                            */
 
2299
  /*    Round_Super_45                                                     */
 
2300
  /*                                                                       */
 
2301
  /* <Description>                                                         */
 
2302
  /*    Super-rounds value to grid after adding engine compensation.       */
 
2303
  /*                                                                       */
 
2304
  /* <Input>                                                               */
 
2305
  /*    distance     :: The distance to round.                             */
 
2306
  /*                                                                       */
 
2307
  /*    compensation :: The engine compensation.                           */
 
2308
  /*                                                                       */
 
2309
  /* <Return>                                                              */
 
2310
  /*    Rounded distance.                                                  */
 
2311
  /*                                                                       */
 
2312
  /* <Note>                                                                */
 
2313
  /*    There is a separate function for Round_Super_45() as we may need   */
 
2314
  /*    greater precision.                                                 */
 
2315
  /*                                                                       */
 
2316
  static FT_F26Dot6
 
2317
  Round_Super_45( EXEC_OP_ FT_F26Dot6  distance,
 
2318
                           FT_F26Dot6  compensation )
 
2319
  {
 
2320
    FT_F26Dot6  val;
 
2321
 
 
2322
 
 
2323
    if ( distance >= 0 )
 
2324
    {
 
2325
      val = ( ( distance - CUR.phase + CUR.threshold + compensation ) /
 
2326
                CUR.period ) * CUR.period;
 
2327
      if ( distance && val < 0 )
 
2328
        val = 0;
 
2329
      val += CUR.phase;
 
2330
    }
 
2331
    else
 
2332
    {
 
2333
      val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) /
 
2334
                   CUR.period ) * CUR.period );
 
2335
      if ( val > 0 )
 
2336
        val = 0;
 
2337
      val -= CUR.phase;
 
2338
    }
 
2339
 
 
2340
    return val;
 
2341
  }
 
2342
 
 
2343
 
 
2344
  /*************************************************************************/
 
2345
  /*                                                                       */
 
2346
  /* <Function>                                                            */
 
2347
  /*    Compute_Round                                                      */
 
2348
  /*                                                                       */
 
2349
  /* <Description>                                                         */
 
2350
  /*    Sets the rounding mode.                                            */
 
2351
  /*                                                                       */
 
2352
  /* <Input>                                                               */
 
2353
  /*    round_mode :: The rounding mode to be used.                        */
 
2354
  /*                                                                       */
 
2355
  static void
 
2356
  Compute_Round( EXEC_OP_ FT_Byte  round_mode )
 
2357
  {
 
2358
    switch ( round_mode )
 
2359
    {
 
2360
    case TT_Round_Off:
 
2361
      CUR.func_round = (TT_Round_Func)Round_None;
 
2362
      break;
 
2363
 
 
2364
    case TT_Round_To_Grid:
 
2365
      CUR.func_round = (TT_Round_Func)Round_To_Grid;
 
2366
      break;
 
2367
 
 
2368
    case TT_Round_Up_To_Grid:
 
2369
      CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
 
2370
      break;
 
2371
 
 
2372
    case TT_Round_Down_To_Grid:
 
2373
      CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
 
2374
      break;
 
2375
 
 
2376
    case TT_Round_To_Half_Grid:
 
2377
      CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
 
2378
      break;
 
2379
 
 
2380
    case TT_Round_To_Double_Grid:
 
2381
      CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
 
2382
      break;
 
2383
 
 
2384
    case TT_Round_Super:
 
2385
      CUR.func_round = (TT_Round_Func)Round_Super;
 
2386
      break;
 
2387
 
 
2388
    case TT_Round_Super_45:
 
2389
      CUR.func_round = (TT_Round_Func)Round_Super_45;
 
2390
      break;
 
2391
    }
 
2392
  }
 
2393
 
 
2394
 
 
2395
  /*************************************************************************/
 
2396
  /*                                                                       */
 
2397
  /* <Function>                                                            */
 
2398
  /*    SetSuperRound                                                      */
 
2399
  /*                                                                       */
 
2400
  /* <Description>                                                         */
 
2401
  /*    Sets Super Round parameters.                                       */
 
2402
  /*                                                                       */
 
2403
  /* <Input>                                                               */
 
2404
  /*    GridPeriod :: Grid period                                          */
 
2405
  /*    selector   :: SROUND opcode                                        */
 
2406
  /*                                                                       */
 
2407
  static void
 
2408
  SetSuperRound( EXEC_OP_ FT_F26Dot6  GridPeriod,
 
2409
                          FT_Long     selector )
 
2410
  {
 
2411
    switch ( (FT_Int)( selector & 0xC0 ) )
 
2412
    {
 
2413
      case 0:
 
2414
        CUR.period = GridPeriod / 2;
 
2415
        break;
 
2416
 
 
2417
      case 0x40:
 
2418
        CUR.period = GridPeriod;
 
2419
        break;
 
2420
 
 
2421
      case 0x80:
 
2422
        CUR.period = GridPeriod * 2;
 
2423
        break;
 
2424
 
 
2425
      /* This opcode is reserved, but... */
 
2426
 
 
2427
      case 0xC0:
 
2428
        CUR.period = GridPeriod;
 
2429
        break;
 
2430
    }
 
2431
 
 
2432
    switch ( (FT_Int)( selector & 0x30 ) )
 
2433
    {
 
2434
    case 0:
 
2435
      CUR.phase = 0;
 
2436
      break;
 
2437
 
 
2438
    case 0x10:
 
2439
      CUR.phase = CUR.period / 4;
 
2440
      break;
 
2441
 
 
2442
    case 0x20:
 
2443
      CUR.phase = CUR.period / 2;
 
2444
      break;
 
2445
 
 
2446
    case 0x30:
 
2447
      CUR.phase = CUR.period * 3 / 4;
 
2448
      break;
 
2449
    }
 
2450
 
 
2451
    if ( ( selector & 0x0F ) == 0 )
 
2452
      CUR.threshold = CUR.period - 1;
 
2453
    else
 
2454
      CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8;
 
2455
 
 
2456
    CUR.period    /= 256;
 
2457
    CUR.phase     /= 256;
 
2458
    CUR.threshold /= 256;
 
2459
  }
 
2460
 
 
2461
 
 
2462
  /*************************************************************************/
 
2463
  /*                                                                       */
 
2464
  /* <Function>                                                            */
 
2465
  /*    Project                                                            */
 
2466
  /*                                                                       */
 
2467
  /* <Description>                                                         */
 
2468
  /*    Computes the projection of vector given by (v2-v1) along the       */
 
2469
  /*    current projection vector.                                         */
 
2470
  /*                                                                       */
 
2471
  /* <Input>                                                               */
 
2472
  /*    v1 :: First input vector.                                          */
 
2473
  /*    v2 :: Second input vector.                                         */
 
2474
  /*                                                                       */
 
2475
  /* <Return>                                                              */
 
2476
  /*    The distance in F26dot6 format.                                    */
 
2477
  /*                                                                       */
 
2478
  static FT_F26Dot6
 
2479
  Project( EXEC_OP_ FT_Pos  dx,
 
2480
                    FT_Pos  dy )
 
2481
  {
 
2482
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
 
2483
    FT_ASSERT( !CUR.face->unpatented_hinting );
 
2484
#endif
 
2485
 
 
2486
    return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,
 
2487
                        CUR.GS.projVector.x,
 
2488
                        CUR.GS.projVector.y );
 
2489
  }
 
2490
 
 
2491
 
 
2492
  /*************************************************************************/
 
2493
  /*                                                                       */
 
2494
  /* <Function>                                                            */
 
2495
  /*    Dual_Project                                                       */
 
2496
  /*                                                                       */
 
2497
  /* <Description>                                                         */
 
2498
  /*    Computes the projection of the vector given by (v2-v1) along the   */
 
2499
  /*    current dual vector.                                               */
 
2500
  /*                                                                       */
 
2501
  /* <Input>                                                               */
 
2502
  /*    v1 :: First input vector.                                          */
 
2503
  /*    v2 :: Second input vector.                                         */
 
2504
  /*                                                                       */
 
2505
  /* <Return>                                                              */
 
2506
  /*    The distance in F26dot6 format.                                    */
 
2507
  /*                                                                       */
 
2508
  static FT_F26Dot6
 
2509
  Dual_Project( EXEC_OP_ FT_Pos  dx,
 
2510
                         FT_Pos  dy )
 
2511
  {
 
2512
    return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,
 
2513
                        CUR.GS.dualVector.x,
 
2514
                        CUR.GS.dualVector.y );
 
2515
  }
 
2516
 
 
2517
 
 
2518
  /*************************************************************************/
 
2519
  /*                                                                       */
 
2520
  /* <Function>                                                            */
 
2521
  /*    Project_x                                                          */
 
2522
  /*                                                                       */
 
2523
  /* <Description>                                                         */
 
2524
  /*    Computes the projection of the vector given by (v2-v1) along the   */
 
2525
  /*    horizontal axis.                                                   */
 
2526
  /*                                                                       */
 
2527
  /* <Input>                                                               */
 
2528
  /*    v1 :: First input vector.                                          */
 
2529
  /*    v2 :: Second input vector.                                         */
 
2530
  /*                                                                       */
 
2531
  /* <Return>                                                              */
 
2532
  /*    The distance in F26dot6 format.                                    */
 
2533
  /*                                                                       */
 
2534
  static FT_F26Dot6
 
2535
  Project_x( EXEC_OP_ FT_Pos  dx,
 
2536
                      FT_Pos  dy )
 
2537
  {
 
2538
    FT_UNUSED_EXEC;
 
2539
    FT_UNUSED( dy );
 
2540
 
 
2541
    return dx;
 
2542
  }
 
2543
 
 
2544
 
 
2545
  /*************************************************************************/
 
2546
  /*                                                                       */
 
2547
  /* <Function>                                                            */
 
2548
  /*    Project_y                                                          */
 
2549
  /*                                                                       */
 
2550
  /* <Description>                                                         */
 
2551
  /*    Computes the projection of the vector given by (v2-v1) along the   */
 
2552
  /*    vertical axis.                                                     */
 
2553
  /*                                                                       */
 
2554
  /* <Input>                                                               */
 
2555
  /*    v1 :: First input vector.                                          */
 
2556
  /*    v2 :: Second input vector.                                         */
 
2557
  /*                                                                       */
 
2558
  /* <Return>                                                              */
 
2559
  /*    The distance in F26dot6 format.                                    */
 
2560
  /*                                                                       */
 
2561
  static FT_F26Dot6
 
2562
  Project_y( EXEC_OP_ FT_Pos  dx,
 
2563
                      FT_Pos  dy )
 
2564
  {
 
2565
    FT_UNUSED_EXEC;
 
2566
    FT_UNUSED( dx );
 
2567
 
 
2568
    return dy;
 
2569
  }
 
2570
 
 
2571
 
 
2572
  /*************************************************************************/
 
2573
  /*                                                                       */
 
2574
  /* <Function>                                                            */
 
2575
  /*    Compute_Funcs                                                      */
 
2576
  /*                                                                       */
 
2577
  /* <Description>                                                         */
 
2578
  /*    Computes the projection and movement function pointers according   */
 
2579
  /*    to the current graphics state.                                     */
 
2580
  /*                                                                       */
 
2581
  static void
 
2582
  Compute_Funcs( EXEC_OP )
 
2583
  {
 
2584
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
 
2585
    if ( CUR.face->unpatented_hinting )
 
2586
    {
 
2587
      /* If both vectors point rightwards along the x axis, set             */
 
2588
      /* `both-x-axis' true, otherwise set it false.  The x values only     */
 
2589
      /* need be tested because the vector has been normalised to a unit    */
 
2590
      /* vector of length 0x4000 = unity.                                   */
 
2591
      CUR.GS.both_x_axis = (FT_Bool)( CUR.GS.projVector.x == 0x4000 &&
 
2592
                                      CUR.GS.freeVector.x == 0x4000 );
 
2593
 
 
2594
      /* Throw away projection and freedom vector information */
 
2595
      /* because the patents don't allow them to be stored.   */
 
2596
      /* The relevant US Patents are 5155805 and 5325479.     */
 
2597
      CUR.GS.projVector.x = 0;
 
2598
      CUR.GS.projVector.y = 0;
 
2599
      CUR.GS.freeVector.x = 0;
 
2600
      CUR.GS.freeVector.y = 0;
 
2601
 
 
2602
      if ( CUR.GS.both_x_axis )
 
2603
      {
 
2604
        CUR.func_project   = Project_x;
 
2605
        CUR.func_move      = Direct_Move_X;
 
2606
        CUR.func_move_orig = Direct_Move_Orig_X;
 
2607
      }
 
2608
      else
 
2609
      {
 
2610
        CUR.func_project   = Project_y;
 
2611
        CUR.func_move      = Direct_Move_Y;
 
2612
        CUR.func_move_orig = Direct_Move_Orig_Y;
 
2613
      }
 
2614
 
 
2615
      if ( CUR.GS.dualVector.x == 0x4000 )
 
2616
        CUR.func_dualproj = Project_x;
 
2617
      else
 
2618
      {
 
2619
        if ( CUR.GS.dualVector.y == 0x4000 )
 
2620
          CUR.func_dualproj = Project_y;
 
2621
        else
 
2622
          CUR.func_dualproj = Dual_Project;
 
2623
      }
 
2624
 
 
2625
      /* Force recalculation of cached aspect ratio */
 
2626
      CUR.tt_metrics.ratio = 0;
 
2627
 
 
2628
      return;
 
2629
    }
 
2630
#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */
 
2631
 
 
2632
    if ( CUR.GS.freeVector.x == 0x4000 )
 
2633
      CUR.F_dot_P       = CUR.GS.projVector.x * 0x10000L;
 
2634
    else
 
2635
    {
 
2636
      if ( CUR.GS.freeVector.y == 0x4000 )
 
2637
        CUR.F_dot_P       = CUR.GS.projVector.y * 0x10000L;
 
2638
      else
 
2639
        CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 +
 
2640
                      (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4;
 
2641
    }
 
2642
 
 
2643
    if ( CUR.GS.projVector.x == 0x4000 )
 
2644
      CUR.func_project = (TT_Project_Func)Project_x;
 
2645
    else
 
2646
    {
 
2647
      if ( CUR.GS.projVector.y == 0x4000 )
 
2648
        CUR.func_project = (TT_Project_Func)Project_y;
 
2649
      else
 
2650
        CUR.func_project = (TT_Project_Func)Project;
 
2651
    }
 
2652
 
 
2653
    if ( CUR.GS.dualVector.x == 0x4000 )
 
2654
      CUR.func_dualproj = (TT_Project_Func)Project_x;
 
2655
    else
 
2656
    {
 
2657
      if ( CUR.GS.dualVector.y == 0x4000 )
 
2658
        CUR.func_dualproj = (TT_Project_Func)Project_y;
 
2659
      else
 
2660
        CUR.func_dualproj = (TT_Project_Func)Dual_Project;
 
2661
    }
 
2662
 
 
2663
    CUR.func_move      = (TT_Move_Func)Direct_Move;
 
2664
    CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig;
 
2665
 
 
2666
    if ( CUR.F_dot_P == 0x40000000L )
 
2667
    {
 
2668
      if ( CUR.GS.freeVector.x == 0x4000 )
 
2669
      {
 
2670
        CUR.func_move      = (TT_Move_Func)Direct_Move_X;
 
2671
        CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
 
2672
      }
 
2673
      else
 
2674
      {
 
2675
        if ( CUR.GS.freeVector.y == 0x4000 )
 
2676
        {
 
2677
          CUR.func_move      = (TT_Move_Func)Direct_Move_Y;
 
2678
          CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
 
2679
        }
 
2680
      }
 
2681
    }
 
2682
 
 
2683
    /* at small sizes, F_dot_P can become too small, resulting   */
 
2684
    /* in overflows and `spikes' in a number of glyphs like `w'. */
 
2685
 
 
2686
    if ( FT_ABS( CUR.F_dot_P ) < 0x4000000L )
 
2687
      CUR.F_dot_P = 0x40000000L;
 
2688
 
 
2689
    /* Disable cached aspect ratio */
 
2690
    CUR.tt_metrics.ratio = 0;
 
2691
  }
 
2692
 
 
2693
 
 
2694
  /*************************************************************************/
 
2695
  /*                                                                       */
 
2696
  /* <Function>                                                            */
 
2697
  /*    Normalize                                                          */
 
2698
  /*                                                                       */
 
2699
  /* <Description>                                                         */
 
2700
  /*    Norms a vector.                                                    */
 
2701
  /*                                                                       */
 
2702
  /* <Input>                                                               */
 
2703
  /*    Vx :: The horizontal input vector coordinate.                      */
 
2704
  /*    Vy :: The vertical input vector coordinate.                        */
 
2705
  /*                                                                       */
 
2706
  /* <Output>                                                              */
 
2707
  /*    R  :: The normed unit vector.                                      */
 
2708
  /*                                                                       */
 
2709
  /* <Return>                                                              */
 
2710
  /*    Returns FAILURE if a vector parameter is zero.                     */
 
2711
  /*                                                                       */
 
2712
  /* <Note>                                                                */
 
2713
  /*    In case Vx and Vy are both zero, Normalize() returns SUCCESS, and  */
 
2714
  /*    R is undefined.                                                    */
 
2715
  /*                                                                       */
 
2716
 
 
2717
 
 
2718
  static FT_Bool
 
2719
  Normalize( EXEC_OP_ FT_F26Dot6      Vx,
 
2720
                      FT_F26Dot6      Vy,
 
2721
                      FT_UnitVector*  R )
 
2722
  {
 
2723
    FT_F26Dot6  W;
 
2724
    FT_Bool     S1, S2;
 
2725
 
 
2726
    FT_UNUSED_EXEC;
 
2727
 
 
2728
 
 
2729
    if ( FT_ABS( Vx ) < 0x10000L && FT_ABS( Vy ) < 0x10000L )
 
2730
    {
 
2731
      Vx *= 0x100;
 
2732
      Vy *= 0x100;
 
2733
 
 
2734
      W = TT_VecLen( Vx, Vy );
 
2735
 
 
2736
      if ( W == 0 )
 
2737
      {
 
2738
        /* XXX: UNDOCUMENTED! It seems that it is possible to try   */
 
2739
        /*      to normalize the vector (0,0).  Return immediately. */
 
2740
        return SUCCESS;
 
2741
      }
 
2742
 
 
2743
      R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W );
 
2744
      R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W );
 
2745
 
 
2746
      return SUCCESS;
 
2747
    }
 
2748
 
 
2749
    W = TT_VecLen( Vx, Vy );
 
2750
 
 
2751
    Vx = FT_MulDiv( Vx, 0x4000L, W );
 
2752
    Vy = FT_MulDiv( Vy, 0x4000L, W );
 
2753
 
 
2754
    W = Vx * Vx + Vy * Vy;
 
2755
 
 
2756
    /* Now, we want that Sqrt( W ) = 0x4000 */
 
2757
    /* Or 0x10000000 <= W < 0x10004000        */
 
2758
 
 
2759
    if ( Vx < 0 )
 
2760
    {
 
2761
      Vx = -Vx;
 
2762
      S1 = TRUE;
 
2763
    }
 
2764
    else
 
2765
      S1 = FALSE;
 
2766
 
 
2767
    if ( Vy < 0 )
 
2768
    {
 
2769
      Vy = -Vy;
 
2770
      S2 = TRUE;
 
2771
    }
 
2772
    else
 
2773
      S2 = FALSE;
 
2774
 
 
2775
    while ( W < 0x10000000L )
 
2776
    {
 
2777
      /* We need to increase W by a minimal amount */
 
2778
      if ( Vx < Vy )
 
2779
        Vx++;
 
2780
      else
 
2781
        Vy++;
 
2782
 
 
2783
      W = Vx * Vx + Vy * Vy;
 
2784
    }
 
2785
 
 
2786
    while ( W >= 0x10004000L )
 
2787
    {
 
2788
      /* We need to decrease W by a minimal amount */
 
2789
      if ( Vx < Vy )
 
2790
        Vx--;
 
2791
      else
 
2792
        Vy--;
 
2793
 
 
2794
      W = Vx * Vx + Vy * Vy;
 
2795
    }
 
2796
 
 
2797
    /* Note that in various cases, we can only  */
 
2798
    /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */
 
2799
 
 
2800
    if ( S1 )
 
2801
      Vx = -Vx;
 
2802
 
 
2803
    if ( S2 )
 
2804
      Vy = -Vy;
 
2805
 
 
2806
    R->x = (FT_F2Dot14)Vx;   /* Type conversion */
 
2807
    R->y = (FT_F2Dot14)Vy;   /* Type conversion */
 
2808
 
 
2809
    return SUCCESS;
 
2810
  }
 
2811
 
 
2812
 
 
2813
  /*************************************************************************/
 
2814
  /*                                                                       */
 
2815
  /* Here we start with the implementation of the various opcodes.         */
 
2816
  /*                                                                       */
 
2817
  /*************************************************************************/
 
2818
 
 
2819
 
 
2820
  static FT_Bool
 
2821
  Ins_SxVTL( EXEC_OP_ FT_UShort       aIdx1,
 
2822
                      FT_UShort       aIdx2,
 
2823
                      FT_Int          aOpc,
 
2824
                      FT_UnitVector*  Vec )
 
2825
  {
 
2826
    FT_Long     A, B, C;
 
2827
    FT_Vector*  p1;
 
2828
    FT_Vector*  p2;
 
2829
 
 
2830
 
 
2831
    if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||
 
2832
         BOUNDS( aIdx2, CUR.zp1.n_points ) )
 
2833
    {
 
2834
      if ( CUR.pedantic_hinting )
 
2835
        CUR.error = TT_Err_Invalid_Reference;
 
2836
      return FAILURE;
 
2837
    }
 
2838
 
 
2839
    p1 = CUR.zp1.cur + aIdx2;
 
2840
    p2 = CUR.zp2.cur + aIdx1;
 
2841
 
 
2842
    A = p1->x - p2->x;
 
2843
    B = p1->y - p2->y;
 
2844
 
 
2845
    if ( ( aOpc & 1 ) != 0 )
 
2846
    {
 
2847
      C =  B;   /* counter clockwise rotation */
 
2848
      B =  A;
 
2849
      A = -C;
 
2850
    }
 
2851
 
 
2852
    NORMalize( A, B, Vec );
 
2853
 
 
2854
    return SUCCESS;
 
2855
  }
 
2856
 
 
2857
 
 
2858
  /* When not using the big switch statements, the interpreter uses a */
 
2859
  /* call table defined later below in this source.  Each opcode must */
 
2860
  /* thus have a corresponding function, even trivial ones.           */
 
2861
  /*                                                                  */
 
2862
  /* They are all defined there.                                      */
 
2863
 
 
2864
#define DO_SVTCA                            \
 
2865
  {                                         \
 
2866
    FT_Short  A, B;                         \
 
2867
                                            \
 
2868
                                            \
 
2869
    A = (FT_Short)( CUR.opcode & 1 ) << 14; \
 
2870
    B = A ^ (FT_Short)0x4000;               \
 
2871
                                            \
 
2872
    CUR.GS.freeVector.x = A;                \
 
2873
    CUR.GS.projVector.x = A;                \
 
2874
    CUR.GS.dualVector.x = A;                \
 
2875
                                            \
 
2876
    CUR.GS.freeVector.y = B;                \
 
2877
    CUR.GS.projVector.y = B;                \
 
2878
    CUR.GS.dualVector.y = B;                \
 
2879
                                            \
 
2880
    COMPUTE_Funcs();                        \
 
2881
  }
 
2882
 
 
2883
 
 
2884
#define DO_SPVTCA                           \
 
2885
  {                                         \
 
2886
    FT_Short  A, B;                         \
 
2887
                                            \
 
2888
                                            \
 
2889
    A = (FT_Short)( CUR.opcode & 1 ) << 14; \
 
2890
    B = A ^ (FT_Short)0x4000;               \
 
2891
                                            \
 
2892
    CUR.GS.projVector.x = A;                \
 
2893
    CUR.GS.dualVector.x = A;                \
 
2894
                                            \
 
2895
    CUR.GS.projVector.y = B;                \
 
2896
    CUR.GS.dualVector.y = B;                \
 
2897
                                            \
 
2898
    GUESS_VECTOR( freeVector );             \
 
2899
                                            \
 
2900
    COMPUTE_Funcs();                        \
 
2901
  }
 
2902
 
 
2903
 
 
2904
#define DO_SFVTCA                           \
 
2905
  {                                         \
 
2906
    FT_Short  A, B;                         \
 
2907
                                            \
 
2908
                                            \
 
2909
    A = (FT_Short)( CUR.opcode & 1 ) << 14; \
 
2910
    B = A ^ (FT_Short)0x4000;               \
 
2911
                                            \
 
2912
    CUR.GS.freeVector.x = A;                \
 
2913
    CUR.GS.freeVector.y = B;                \
 
2914
                                            \
 
2915
    GUESS_VECTOR( projVector );             \
 
2916
                                            \
 
2917
    COMPUTE_Funcs();                        \
 
2918
  }
 
2919
 
 
2920
 
 
2921
#define DO_SPVTL                                      \
 
2922
    if ( INS_SxVTL( (FT_UShort)args[1],               \
 
2923
                    (FT_UShort)args[0],               \
 
2924
                    CUR.opcode,                       \
 
2925
                    &CUR.GS.projVector ) == SUCCESS ) \
 
2926
    {                                                 \
 
2927
      CUR.GS.dualVector = CUR.GS.projVector;          \
 
2928
      GUESS_VECTOR( freeVector );                     \
 
2929
      COMPUTE_Funcs();                                \
 
2930
    }
 
2931
 
 
2932
 
 
2933
#define DO_SFVTL                                      \
 
2934
    if ( INS_SxVTL( (FT_UShort)args[1],               \
 
2935
                    (FT_UShort)args[0],               \
 
2936
                    CUR.opcode,                       \
 
2937
                    &CUR.GS.freeVector ) == SUCCESS ) \
 
2938
    {                                                 \
 
2939
      GUESS_VECTOR( projVector );                     \
 
2940
      COMPUTE_Funcs();                                \
 
2941
    }
 
2942
 
 
2943
 
 
2944
#define DO_SFVTPV                          \
 
2945
    GUESS_VECTOR( projVector );            \
 
2946
    CUR.GS.freeVector = CUR.GS.projVector; \
 
2947
    COMPUTE_Funcs();
 
2948
 
 
2949
 
 
2950
#define DO_SPVFS                                \
 
2951
  {                                             \
 
2952
    FT_Short  S;                                \
 
2953
    FT_Long   X, Y;                             \
 
2954
                                                \
 
2955
                                                \
 
2956
    /* Only use low 16bits, then sign extend */ \
 
2957
    S = (FT_Short)args[1];                      \
 
2958
    Y = (FT_Long)S;                             \
 
2959
    S = (FT_Short)args[0];                      \
 
2960
    X = (FT_Long)S;                             \
 
2961
                                                \
 
2962
    NORMalize( X, Y, &CUR.GS.projVector );      \
 
2963
                                                \
 
2964
    CUR.GS.dualVector = CUR.GS.projVector;      \
 
2965
    GUESS_VECTOR( freeVector );                 \
 
2966
    COMPUTE_Funcs();                            \
 
2967
  }
 
2968
 
 
2969
 
 
2970
#define DO_SFVFS                                \
 
2971
  {                                             \
 
2972
    FT_Short  S;                                \
 
2973
    FT_Long   X, Y;                             \
 
2974
                                                \
 
2975
                                                \
 
2976
    /* Only use low 16bits, then sign extend */ \
 
2977
    S = (FT_Short)args[1];                      \
 
2978
    Y = (FT_Long)S;                             \
 
2979
    S = (FT_Short)args[0];                      \
 
2980
    X = S;                                      \
 
2981
                                                \
 
2982
    NORMalize( X, Y, &CUR.GS.freeVector );      \
 
2983
    GUESS_VECTOR( projVector );                 \
 
2984
    COMPUTE_Funcs();                            \
 
2985
  }
 
2986
 
 
2987
 
 
2988
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
 
2989
#define DO_GPV                                   \
 
2990
    if ( CUR.face->unpatented_hinting )          \
 
2991
    {                                            \
 
2992
      args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
 
2993
      args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
 
2994
    }                                            \
 
2995
    else                                         \
 
2996
    {                                            \
 
2997
      args[0] = CUR.GS.projVector.x;             \
 
2998
      args[1] = CUR.GS.projVector.y;             \
 
2999
    }
 
3000
#else
 
3001
#define DO_GPV                                   \
 
3002
    args[0] = CUR.GS.projVector.x;               \
 
3003
    args[1] = CUR.GS.projVector.y;
 
3004
#endif
 
3005
 
 
3006
 
 
3007
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
 
3008
#define DO_GFV                                   \
 
3009
    if ( CUR.face->unpatented_hinting )          \
 
3010
    {                                            \
 
3011
      args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
 
3012
      args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
 
3013
    }                                            \
 
3014
    else                                         \
 
3015
    {                                            \
 
3016
      args[0] = CUR.GS.freeVector.x;             \
 
3017
      args[1] = CUR.GS.freeVector.y;             \
 
3018
    }
 
3019
#else
 
3020
#define DO_GFV                                   \
 
3021
    args[0] = CUR.GS.freeVector.x;               \
 
3022
    args[1] = CUR.GS.freeVector.y;
 
3023
#endif
 
3024
 
 
3025
 
 
3026
#define DO_SRP0                      \
 
3027
    CUR.GS.rp0 = (FT_UShort)args[0];
 
3028
 
 
3029
 
 
3030
#define DO_SRP1                      \
 
3031
    CUR.GS.rp1 = (FT_UShort)args[0];
 
3032
 
 
3033
 
 
3034
#define DO_SRP2                      \
 
3035
    CUR.GS.rp2 = (FT_UShort)args[0];
 
3036
 
 
3037
 
 
3038
#define DO_RTHG                                         \
 
3039
    CUR.GS.round_state = TT_Round_To_Half_Grid;         \
 
3040
    CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
 
3041
 
 
3042
 
 
3043
#define DO_RTG                                     \
 
3044
    CUR.GS.round_state = TT_Round_To_Grid;         \
 
3045
    CUR.func_round = (TT_Round_Func)Round_To_Grid;
 
3046
 
 
3047
 
 
3048
#define DO_RTDG                                           \
 
3049
    CUR.GS.round_state = TT_Round_To_Double_Grid;         \
 
3050
    CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
 
3051
 
 
3052
 
 
3053
#define DO_RUTG                                       \
 
3054
    CUR.GS.round_state = TT_Round_Up_To_Grid;         \
 
3055
    CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
 
3056
 
 
3057
 
 
3058
#define DO_RDTG                                         \
 
3059
    CUR.GS.round_state = TT_Round_Down_To_Grid;         \
 
3060
    CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
 
3061
 
 
3062
 
 
3063
#define DO_ROFF                                 \
 
3064
    CUR.GS.round_state = TT_Round_Off;          \
 
3065
    CUR.func_round = (TT_Round_Func)Round_None;
 
3066
 
 
3067
 
 
3068
#define DO_SROUND                                \
 
3069
    SET_SuperRound( 0x4000, args[0] );           \
 
3070
    CUR.GS.round_state = TT_Round_Super;         \
 
3071
    CUR.func_round = (TT_Round_Func)Round_Super;
 
3072
 
 
3073
 
 
3074
#define DO_S45ROUND                                 \
 
3075
    SET_SuperRound( 0x2D41, args[0] );              \
 
3076
    CUR.GS.round_state = TT_Round_Super_45;         \
 
3077
    CUR.func_round = (TT_Round_Func)Round_Super_45;
 
3078
 
 
3079
 
 
3080
#define DO_SLOOP                       \
 
3081
    if ( args[0] < 0 )                 \
 
3082
      CUR.error = TT_Err_Bad_Argument; \
 
3083
    else                               \
 
3084
      CUR.GS.loop = args[0];
 
3085
 
 
3086
 
 
3087
#define DO_SMD                         \
 
3088
    CUR.GS.minimum_distance = args[0];
 
3089
 
 
3090
 
 
3091
#define DO_SCVTCI                                     \
 
3092
    CUR.GS.control_value_cutin = (FT_F26Dot6)args[0];
 
3093
 
 
3094
 
 
3095
#define DO_SSWCI                                     \
 
3096
    CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];
 
3097
 
 
3098
 
 
3099
    /* XXX: UNDOCUMENTED! or bug in the Windows engine?   */
 
3100
    /*                                                    */
 
3101
    /*      It seems that the value that is read here is  */
 
3102
    /*      expressed in 16.16 format rather than in font */
 
3103
    /*      units.                                        */
 
3104
    /*                                                    */
 
3105
#define DO_SSW                                                 \
 
3106
    CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 );
 
3107
 
 
3108
 
 
3109
#define DO_FLIPON            \
 
3110
    CUR.GS.auto_flip = TRUE;
 
3111
 
 
3112
 
 
3113
#define DO_FLIPOFF            \
 
3114
    CUR.GS.auto_flip = FALSE;
 
3115
 
 
3116
 
 
3117
#define DO_SDB                             \
 
3118
    CUR.GS.delta_base = (FT_Short)args[0];
 
3119
 
 
3120
 
 
3121
#define DO_SDS                              \
 
3122
    CUR.GS.delta_shift = (FT_Short)args[0];
 
3123
 
 
3124
 
 
3125
#define DO_MD  /* nothing */
 
3126
 
 
3127
 
 
3128
#define DO_MPPEM              \
 
3129
    args[0] = CURRENT_Ppem();
 
3130
 
 
3131
 
 
3132
  /* Note: The pointSize should be irrelevant in a given font program; */
 
3133
  /*       we thus decide to return only the ppem.                     */
 
3134
#if 0
 
3135
 
 
3136
#define DO_MPS                       \
 
3137
    args[0] = CUR.metrics.pointSize;
 
3138
 
 
3139
#else
 
3140
 
 
3141
#define DO_MPS                \
 
3142
    args[0] = CURRENT_Ppem();
 
3143
 
 
3144
#endif /* 0 */
 
3145
 
 
3146
 
 
3147
#define DO_DUP         \
 
3148
    args[1] = args[0];
 
3149
 
 
3150
 
 
3151
#define DO_CLEAR     \
 
3152
    CUR.new_top = 0;
 
3153
 
 
3154
 
 
3155
#define DO_SWAP        \
 
3156
  {                    \
 
3157
    FT_Long  L;        \
 
3158
                       \
 
3159
                       \
 
3160
    L       = args[0]; \
 
3161
    args[0] = args[1]; \
 
3162
    args[1] = L;       \
 
3163
  }
 
3164
 
 
3165
 
 
3166
#define DO_DEPTH       \
 
3167
    args[0] = CUR.top;
 
3168
 
 
3169
 
 
3170
#define DO_CINDEX                           \
 
3171
  {                                         \
 
3172
    FT_Long  L;                             \
 
3173
                                            \
 
3174
                                            \
 
3175
    L = args[0];                            \
 
3176
                                            \
 
3177
    if ( L <= 0 || L > CUR.args )           \
 
3178
      CUR.error = TT_Err_Invalid_Reference; \
 
3179
    else                                    \
 
3180
      args[0] = CUR.stack[CUR.args - L];    \
 
3181
  }
 
3182
 
 
3183
 
 
3184
#define DO_JROT                          \
 
3185
    if ( args[1] != 0 )                  \
 
3186
    {                                    \
 
3187
      CUR.IP      += args[0];            \
 
3188
      if ( CUR.IP < 0 )                  \
 
3189
        CUR.error = TT_Err_Bad_Argument; \
 
3190
      CUR.step_ins = FALSE;              \
 
3191
    }
 
3192
 
 
3193
 
 
3194
#define DO_JMPR                        \
 
3195
    CUR.IP      += args[0];            \
 
3196
    if ( CUR.IP < 0 )                  \
 
3197
      CUR.error = TT_Err_Bad_Argument; \
 
3198
    CUR.step_ins = FALSE;
 
3199
 
 
3200
 
 
3201
#define DO_JROF                          \
 
3202
    if ( args[1] == 0 )                  \
 
3203
    {                                    \
 
3204
      CUR.IP      += args[0];            \
 
3205
      if ( CUR.IP < 0 )                  \
 
3206
        CUR.error = TT_Err_Bad_Argument; \
 
3207
      CUR.step_ins = FALSE;              \
 
3208
    }
 
3209
 
 
3210
 
 
3211
#define DO_LT                        \
 
3212
    args[0] = ( args[0] < args[1] );
 
3213
 
 
3214
 
 
3215
#define DO_LTEQ                       \
 
3216
    args[0] = ( args[0] <= args[1] );
 
3217
 
 
3218
 
 
3219
#define DO_GT                        \
 
3220
    args[0] = ( args[0] > args[1] );
 
3221
 
 
3222
 
 
3223
#define DO_GTEQ                       \
 
3224
    args[0] = ( args[0] >= args[1] );
 
3225
 
 
3226
 
 
3227
#define DO_EQ                         \
 
3228
    args[0] = ( args[0] == args[1] );
 
3229
 
 
3230
 
 
3231
#define DO_NEQ                        \
 
3232
    args[0] = ( args[0] != args[1] );
 
3233
 
 
3234
 
 
3235
#define DO_ODD                                                  \
 
3236
    args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 );
 
3237
 
 
3238
 
 
3239
#define DO_EVEN                                                \
 
3240
    args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 );
 
3241
 
 
3242
 
 
3243
#define DO_AND                        \
 
3244
    args[0] = ( args[0] && args[1] );
 
3245
 
 
3246
 
 
3247
#define DO_OR                         \
 
3248
    args[0] = ( args[0] || args[1] );
 
3249
 
 
3250
 
 
3251
#define DO_NOT          \
 
3252
    args[0] = !args[0];
 
3253
 
 
3254
 
 
3255
#define DO_ADD          \
 
3256
    args[0] += args[1];
 
3257
 
 
3258
 
 
3259
#define DO_SUB          \
 
3260
    args[0] -= args[1];
 
3261
 
 
3262
 
 
3263
#define DO_DIV                                               \
 
3264
    if ( args[1] == 0 )                                      \
 
3265
      CUR.error = TT_Err_Divide_By_Zero;                     \
 
3266
    else                                                     \
 
3267
      args[0] = TT_MULDIV_NO_ROUND( args[0], 64L, args[1] );
 
3268
 
 
3269
 
 
3270
#define DO_MUL                                    \
 
3271
    args[0] = TT_MULDIV( args[0], args[1], 64L );
 
3272
 
 
3273
 
 
3274
#define DO_ABS                   \
 
3275
    args[0] = FT_ABS( args[0] );
 
3276
 
 
3277
 
 
3278
#define DO_NEG          \
 
3279
    args[0] = -args[0];
 
3280
 
 
3281
 
 
3282
#define DO_FLOOR    \
 
3283
    args[0] = FT_PIX_FLOOR( args[0] );
 
3284
 
 
3285
 
 
3286
#define DO_CEILING                    \
 
3287
    args[0] = FT_PIX_CEIL( args[0] );
 
3288
 
 
3289
 
 
3290
#define DO_RS                           \
 
3291
   {                                    \
 
3292
     FT_ULong  I = (FT_ULong)args[0];   \
 
3293
                                        \
 
3294
                                        \
 
3295
     if ( BOUNDSL( I, CUR.storeSize ) ) \
 
3296
     {                                  \
 
3297
       if ( CUR.pedantic_hinting )      \
 
3298
       {                                \
 
3299
         ARRAY_BOUND_ERROR;             \
 
3300
       }                                \
 
3301
       else                             \
 
3302
         args[0] = 0;                   \
 
3303
     }                                  \
 
3304
     else                               \
 
3305
       args[0] = CUR.storage[I];        \
 
3306
   }
 
3307
 
 
3308
 
 
3309
#define DO_WS                           \
 
3310
   {                                    \
 
3311
     FT_ULong  I = (FT_ULong)args[0];   \
 
3312
                                        \
 
3313
                                        \
 
3314
     if ( BOUNDSL( I, CUR.storeSize ) ) \
 
3315
     {                                  \
 
3316
       if ( CUR.pedantic_hinting )      \
 
3317
       {                                \
 
3318
         ARRAY_BOUND_ERROR;             \
 
3319
       }                                \
 
3320
     }                                  \
 
3321
     else                               \
 
3322
       CUR.storage[I] = args[1];        \
 
3323
   }
 
3324
 
 
3325
 
 
3326
#define DO_RCVT                          \
 
3327
   {                                     \
 
3328
     FT_ULong  I = (FT_ULong)args[0];    \
 
3329
                                         \
 
3330
                                         \
 
3331
     if ( BOUNDSL( I, CUR.cvtSize ) )    \
 
3332
     {                                   \
 
3333
       if ( CUR.pedantic_hinting )       \
 
3334
       {                                 \
 
3335
         ARRAY_BOUND_ERROR;              \
 
3336
       }                                 \
 
3337
       else                              \
 
3338
         args[0] = 0;                    \
 
3339
     }                                   \
 
3340
     else                                \
 
3341
       args[0] = CUR_Func_read_cvt( I ); \
 
3342
   }
 
3343
 
 
3344
 
 
3345
#define DO_WCVTP                         \
 
3346
   {                                     \
 
3347
     FT_ULong  I = (FT_ULong)args[0];    \
 
3348
                                         \
 
3349
                                         \
 
3350
     if ( BOUNDSL( I, CUR.cvtSize ) )    \
 
3351
     {                                   \
 
3352
       if ( CUR.pedantic_hinting )       \
 
3353
       {                                 \
 
3354
         ARRAY_BOUND_ERROR;              \
 
3355
       }                                 \
 
3356
     }                                   \
 
3357
     else                                \
 
3358
       CUR_Func_write_cvt( I, args[1] ); \
 
3359
   }
 
3360
 
 
3361
 
 
3362
#define DO_WCVTF                                                \
 
3363
   {                                                            \
 
3364
     FT_ULong  I = (FT_ULong)args[0];                           \
 
3365
                                                                \
 
3366
                                                                \
 
3367
     if ( BOUNDSL( I, CUR.cvtSize ) )                           \
 
3368
     {                                                          \
 
3369
       if ( CUR.pedantic_hinting )                              \
 
3370
       {                                                        \
 
3371
         ARRAY_BOUND_ERROR;                                     \
 
3372
       }                                                        \
 
3373
     }                                                          \
 
3374
     else                                                       \
 
3375
       CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \
 
3376
   }
 
3377
 
 
3378
 
 
3379
#define DO_DEBUG                     \
 
3380
    CUR.error = TT_Err_Debug_OpCode;
 
3381
 
 
3382
 
 
3383
#define DO_ROUND                                                   \
 
3384
    args[0] = CUR_Func_round(                                      \
 
3385
                args[0],                                           \
 
3386
                CUR.tt_metrics.compensations[CUR.opcode - 0x68] );
 
3387
 
 
3388
 
 
3389
#define DO_NROUND                                                            \
 
3390
    args[0] = ROUND_None( args[0],                                           \
 
3391
                          CUR.tt_metrics.compensations[CUR.opcode - 0x6C] );
 
3392
 
 
3393
 
 
3394
#define DO_MAX               \
 
3395
    if ( args[1] > args[0] ) \
 
3396
      args[0] = args[1];
 
3397
 
 
3398
 
 
3399
#define DO_MIN               \
 
3400
    if ( args[1] < args[0] ) \
 
3401
      args[0] = args[1];
 
3402
 
 
3403
 
 
3404
#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
 
3405
 
 
3406
 
 
3407
#undef  ARRAY_BOUND_ERROR
 
3408
#define ARRAY_BOUND_ERROR                   \
 
3409
    {                                       \
 
3410
      CUR.error = TT_Err_Invalid_Reference; \
 
3411
      return;                               \
 
3412
    }
 
3413
 
 
3414
 
 
3415
  /*************************************************************************/
 
3416
  /*                                                                       */
 
3417
  /* SVTCA[a]:     Set (F and P) Vectors to Coordinate Axis                */
 
3418
  /* Opcode range: 0x00-0x01                                               */
 
3419
  /* Stack:        -->                                                     */
 
3420
  /*                                                                       */
 
3421
  static void
 
3422
  Ins_SVTCA( INS_ARG )
 
3423
  {
 
3424
    DO_SVTCA
 
3425
  }
 
3426
 
 
3427
 
 
3428
  /*************************************************************************/
 
3429
  /*                                                                       */
 
3430
  /* SPVTCA[a]:    Set PVector to Coordinate Axis                          */
 
3431
  /* Opcode range: 0x02-0x03                                               */
 
3432
  /* Stack:        -->                                                     */
 
3433
  /*                                                                       */
 
3434
  static void
 
3435
  Ins_SPVTCA( INS_ARG )
 
3436
  {
 
3437
    DO_SPVTCA
 
3438
  }
 
3439
 
 
3440
 
 
3441
  /*************************************************************************/
 
3442
  /*                                                                       */
 
3443
  /* SFVTCA[a]:    Set FVector to Coordinate Axis                          */
 
3444
  /* Opcode range: 0x04-0x05                                               */
 
3445
  /* Stack:        -->                                                     */
 
3446
  /*                                                                       */
 
3447
  static void
 
3448
  Ins_SFVTCA( INS_ARG )
 
3449
  {
 
3450
    DO_SFVTCA
 
3451
  }
 
3452
 
 
3453
 
 
3454
  /*************************************************************************/
 
3455
  /*                                                                       */
 
3456
  /* SPVTL[a]:     Set PVector To Line                                     */
 
3457
  /* Opcode range: 0x06-0x07                                               */
 
3458
  /* Stack:        uint32 uint32 -->                                       */
 
3459
  /*                                                                       */
 
3460
  static void
 
3461
  Ins_SPVTL( INS_ARG )
 
3462
  {
 
3463
    DO_SPVTL
 
3464
  }
 
3465
 
 
3466
 
 
3467
  /*************************************************************************/
 
3468
  /*                                                                       */
 
3469
  /* SFVTL[a]:     Set FVector To Line                                     */
 
3470
  /* Opcode range: 0x08-0x09                                               */
 
3471
  /* Stack:        uint32 uint32 -->                                       */
 
3472
  /*                                                                       */
 
3473
  static void
 
3474
  Ins_SFVTL( INS_ARG )
 
3475
  {
 
3476
    DO_SFVTL
 
3477
  }
 
3478
 
 
3479
 
 
3480
  /*************************************************************************/
 
3481
  /*                                                                       */
 
3482
  /* SFVTPV[]:     Set FVector To PVector                                  */
 
3483
  /* Opcode range: 0x0E                                                    */
 
3484
  /* Stack:        -->                                                     */
 
3485
  /*                                                                       */
 
3486
  static void
 
3487
  Ins_SFVTPV( INS_ARG )
 
3488
  {
 
3489
    DO_SFVTPV
 
3490
  }
 
3491
 
 
3492
 
 
3493
  /*************************************************************************/
 
3494
  /*                                                                       */
 
3495
  /* SPVFS[]:      Set PVector From Stack                                  */
 
3496
  /* Opcode range: 0x0A                                                    */
 
3497
  /* Stack:        f2.14 f2.14 -->                                         */
 
3498
  /*                                                                       */
 
3499
  static void
 
3500
  Ins_SPVFS( INS_ARG )
 
3501
  {
 
3502
    DO_SPVFS
 
3503
  }
 
3504
 
 
3505
 
 
3506
  /*************************************************************************/
 
3507
  /*                                                                       */
 
3508
  /* SFVFS[]:      Set FVector From Stack                                  */
 
3509
  /* Opcode range: 0x0B                                                    */
 
3510
  /* Stack:        f2.14 f2.14 -->                                         */
 
3511
  /*                                                                       */
 
3512
  static void
 
3513
  Ins_SFVFS( INS_ARG )
 
3514
  {
 
3515
    DO_SFVFS
 
3516
  }
 
3517
 
 
3518
 
 
3519
  /*************************************************************************/
 
3520
  /*                                                                       */
 
3521
  /* GPV[]:        Get Projection Vector                                   */
 
3522
  /* Opcode range: 0x0C                                                    */
 
3523
  /* Stack:        ef2.14 --> ef2.14                                       */
 
3524
  /*                                                                       */
 
3525
  static void
 
3526
  Ins_GPV( INS_ARG )
 
3527
  {
 
3528
    DO_GPV
 
3529
  }
 
3530
 
 
3531
 
 
3532
  /*************************************************************************/
 
3533
  /* GFV[]:        Get Freedom Vector                                      */
 
3534
  /* Opcode range: 0x0D                                                    */
 
3535
  /* Stack:        ef2.14 --> ef2.14                                       */
 
3536
  /*                                                                       */
 
3537
  static void
 
3538
  Ins_GFV( INS_ARG )
 
3539
  {
 
3540
    DO_GFV
 
3541
  }
 
3542
 
 
3543
 
 
3544
  /*************************************************************************/
 
3545
  /*                                                                       */
 
3546
  /* SRP0[]:       Set Reference Point 0                                   */
 
3547
  /* Opcode range: 0x10                                                    */
 
3548
  /* Stack:        uint32 -->                                              */
 
3549
  /*                                                                       */
 
3550
  static void
 
3551
  Ins_SRP0( INS_ARG )
 
3552
  {
 
3553
    DO_SRP0
 
3554
  }
 
3555
 
 
3556
 
 
3557
  /*************************************************************************/
 
3558
  /*                                                                       */
 
3559
  /* SRP1[]:       Set Reference Point 1                                   */
 
3560
  /* Opcode range: 0x11                                                    */
 
3561
  /* Stack:        uint32 -->                                              */
 
3562
  /*                                                                       */
 
3563
  static void
 
3564
  Ins_SRP1( INS_ARG )
 
3565
  {
 
3566
    DO_SRP1
 
3567
  }
 
3568
 
 
3569
 
 
3570
  /*************************************************************************/
 
3571
  /*                                                                       */
 
3572
  /* SRP2[]:       Set Reference Point 2                                   */
 
3573
  /* Opcode range: 0x12                                                    */
 
3574
  /* Stack:        uint32 -->                                              */
 
3575
  /*                                                                       */
 
3576
  static void
 
3577
  Ins_SRP2( INS_ARG )
 
3578
  {
 
3579
    DO_SRP2
 
3580
  }
 
3581
 
 
3582
 
 
3583
  /*************************************************************************/
 
3584
  /*                                                                       */
 
3585
  /* RTHG[]:       Round To Half Grid                                      */
 
3586
  /* Opcode range: 0x19                                                    */
 
3587
  /* Stack:        -->                                                     */
 
3588
  /*                                                                       */
 
3589
  static void
 
3590
  Ins_RTHG( INS_ARG )
 
3591
  {
 
3592
    DO_RTHG
 
3593
  }
 
3594
 
 
3595
 
 
3596
  /*************************************************************************/
 
3597
  /*                                                                       */
 
3598
  /* RTG[]:        Round To Grid                                           */
 
3599
  /* Opcode range: 0x18                                                    */
 
3600
  /* Stack:        -->                                                     */
 
3601
  /*                                                                       */
 
3602
  static void
 
3603
  Ins_RTG( INS_ARG )
 
3604
  {
 
3605
    DO_RTG
 
3606
  }
 
3607
 
 
3608
 
 
3609
  /*************************************************************************/
 
3610
  /* RTDG[]:       Round To Double Grid                                    */
 
3611
  /* Opcode range: 0x3D                                                    */
 
3612
  /* Stack:        -->                                                     */
 
3613
  /*                                                                       */
 
3614
  static void
 
3615
  Ins_RTDG( INS_ARG )
 
3616
  {
 
3617
    DO_RTDG
 
3618
  }
 
3619
 
 
3620
 
 
3621
  /*************************************************************************/
 
3622
  /* RUTG[]:       Round Up To Grid                                        */
 
3623
  /* Opcode range: 0x7C                                                    */
 
3624
  /* Stack:        -->                                                     */
 
3625
  /*                                                                       */
 
3626
  static void
 
3627
  Ins_RUTG( INS_ARG )
 
3628
  {
 
3629
    DO_RUTG
 
3630
  }
 
3631
 
 
3632
 
 
3633
  /*************************************************************************/
 
3634
  /*                                                                       */
 
3635
  /* RDTG[]:       Round Down To Grid                                      */
 
3636
  /* Opcode range: 0x7D                                                    */
 
3637
  /* Stack:        -->                                                     */
 
3638
  /*                                                                       */
 
3639
  static void
 
3640
  Ins_RDTG( INS_ARG )
 
3641
  {
 
3642
    DO_RDTG
 
3643
  }
 
3644
 
 
3645
 
 
3646
  /*************************************************************************/
 
3647
  /*                                                                       */
 
3648
  /* ROFF[]:       Round OFF                                               */
 
3649
  /* Opcode range: 0x7A                                                    */
 
3650
  /* Stack:        -->                                                     */
 
3651
  /*                                                                       */
 
3652
  static void
 
3653
  Ins_ROFF( INS_ARG )
 
3654
  {
 
3655
    DO_ROFF
 
3656
  }
 
3657
 
 
3658
 
 
3659
  /*************************************************************************/
 
3660
  /*                                                                       */
 
3661
  /* SROUND[]:     Super ROUND                                             */
 
3662
  /* Opcode range: 0x76                                                    */
 
3663
  /* Stack:        Eint8 -->                                               */
 
3664
  /*                                                                       */
 
3665
  static void
 
3666
  Ins_SROUND( INS_ARG )
 
3667
  {
 
3668
    DO_SROUND
 
3669
  }
 
3670
 
 
3671
 
 
3672
  /*************************************************************************/
 
3673
  /*                                                                       */
 
3674
  /* S45ROUND[]:   Super ROUND 45 degrees                                  */
 
3675
  /* Opcode range: 0x77                                                    */
 
3676
  /* Stack:        uint32 -->                                              */
 
3677
  /*                                                                       */
 
3678
  static void
 
3679
  Ins_S45ROUND( INS_ARG )
 
3680
  {
 
3681
    DO_S45ROUND
 
3682
  }
 
3683
 
 
3684
 
 
3685
  /*************************************************************************/
 
3686
  /*                                                                       */
 
3687
  /* SLOOP[]:      Set LOOP variable                                       */
 
3688
  /* Opcode range: 0x17                                                    */
 
3689
  /* Stack:        int32? -->                                              */
 
3690
  /*                                                                       */
 
3691
  static void
 
3692
  Ins_SLOOP( INS_ARG )
 
3693
  {
 
3694
    DO_SLOOP
 
3695
  }
 
3696
 
 
3697
 
 
3698
  /*************************************************************************/
 
3699
  /*                                                                       */
 
3700
  /* SMD[]:        Set Minimum Distance                                    */
 
3701
  /* Opcode range: 0x1A                                                    */
 
3702
  /* Stack:        f26.6 -->                                               */
 
3703
  /*                                                                       */
 
3704
  static void
 
3705
  Ins_SMD( INS_ARG )
 
3706
  {
 
3707
    DO_SMD
 
3708
  }
 
3709
 
 
3710
 
 
3711
  /*************************************************************************/
 
3712
  /*                                                                       */
 
3713
  /* SCVTCI[]:     Set Control Value Table Cut In                          */
 
3714
  /* Opcode range: 0x1D                                                    */
 
3715
  /* Stack:        f26.6 -->                                               */
 
3716
  /*                                                                       */
 
3717
  static void
 
3718
  Ins_SCVTCI( INS_ARG )
 
3719
  {
 
3720
    DO_SCVTCI
 
3721
  }
 
3722
 
 
3723
 
 
3724
  /*************************************************************************/
 
3725
  /*                                                                       */
 
3726
  /* SSWCI[]:      Set Single Width Cut In                                 */
 
3727
  /* Opcode range: 0x1E                                                    */
 
3728
  /* Stack:        f26.6 -->                                               */
 
3729
  /*                                                                       */
 
3730
  static void
 
3731
  Ins_SSWCI( INS_ARG )
 
3732
  {
 
3733
    DO_SSWCI
 
3734
  }
 
3735
 
 
3736
 
 
3737
  /*************************************************************************/
 
3738
  /*                                                                       */
 
3739
  /* SSW[]:        Set Single Width                                        */
 
3740
  /* Opcode range: 0x1F                                                    */
 
3741
  /* Stack:        int32? -->                                              */
 
3742
  /*                                                                       */
 
3743
  static void
 
3744
  Ins_SSW( INS_ARG )
 
3745
  {
 
3746
    DO_SSW
 
3747
  }
 
3748
 
 
3749
 
 
3750
  /*************************************************************************/
 
3751
  /*                                                                       */
 
3752
  /* FLIPON[]:     Set auto-FLIP to ON                                     */
 
3753
  /* Opcode range: 0x4D                                                    */
 
3754
  /* Stack:        -->                                                     */
 
3755
  /*                                                                       */
 
3756
  static void
 
3757
  Ins_FLIPON( INS_ARG )
 
3758
  {
 
3759
    DO_FLIPON
 
3760
  }
 
3761
 
 
3762
 
 
3763
  /*************************************************************************/
 
3764
  /*                                                                       */
 
3765
  /* FLIPOFF[]:    Set auto-FLIP to OFF                                    */
 
3766
  /* Opcode range: 0x4E                                                    */
 
3767
  /* Stack: -->                                                            */
 
3768
  /*                                                                       */
 
3769
  static void
 
3770
  Ins_FLIPOFF( INS_ARG )
 
3771
  {
 
3772
    DO_FLIPOFF
 
3773
  }
 
3774
 
 
3775
 
 
3776
  /*************************************************************************/
 
3777
  /*                                                                       */
 
3778
  /* SANGW[]:      Set ANGle Weight                                        */
 
3779
  /* Opcode range: 0x7E                                                    */
 
3780
  /* Stack:        uint32 -->                                              */
 
3781
  /*                                                                       */
 
3782
  static void
 
3783
  Ins_SANGW( INS_ARG )
 
3784
  {
 
3785
    /* instruction not supported anymore */
 
3786
  }
 
3787
 
 
3788
 
 
3789
  /*************************************************************************/
 
3790
  /*                                                                       */
 
3791
  /* SDB[]:        Set Delta Base                                          */
 
3792
  /* Opcode range: 0x5E                                                    */
 
3793
  /* Stack:        uint32 -->                                              */
 
3794
  /*                                                                       */
 
3795
  static void
 
3796
  Ins_SDB( INS_ARG )
 
3797
  {
 
3798
    DO_SDB
 
3799
  }
 
3800
 
 
3801
 
 
3802
  /*************************************************************************/
 
3803
  /*                                                                       */
 
3804
  /* SDS[]:        Set Delta Shift                                         */
 
3805
  /* Opcode range: 0x5F                                                    */
 
3806
  /* Stack:        uint32 -->                                              */
 
3807
  /*                                                                       */
 
3808
  static void
 
3809
  Ins_SDS( INS_ARG )
 
3810
  {
 
3811
    DO_SDS
 
3812
  }
 
3813
 
 
3814
 
 
3815
  /*************************************************************************/
 
3816
  /*                                                                       */
 
3817
  /* MPPEM[]:      Measure Pixel Per EM                                    */
 
3818
  /* Opcode range: 0x4B                                                    */
 
3819
  /* Stack:        --> Euint16                                             */
 
3820
  /*                                                                       */
 
3821
  static void
 
3822
  Ins_MPPEM( INS_ARG )
 
3823
  {
 
3824
    DO_MPPEM
 
3825
  }
 
3826
 
 
3827
 
 
3828
  /*************************************************************************/
 
3829
  /*                                                                       */
 
3830
  /* MPS[]:        Measure Point Size                                      */
 
3831
  /* Opcode range: 0x4C                                                    */
 
3832
  /* Stack:        --> Euint16                                             */
 
3833
  /*                                                                       */
 
3834
  static void
 
3835
  Ins_MPS( INS_ARG )
 
3836
  {
 
3837
    DO_MPS
 
3838
  }
 
3839
 
 
3840
 
 
3841
  /*************************************************************************/
 
3842
  /*                                                                       */
 
3843
  /* DUP[]:        DUPlicate the top stack's element                       */
 
3844
  /* Opcode range: 0x20                                                    */
 
3845
  /* Stack:        StkElt --> StkElt StkElt                                */
 
3846
  /*                                                                       */
 
3847
  static void
 
3848
  Ins_DUP( INS_ARG )
 
3849
  {
 
3850
    DO_DUP
 
3851
  }
 
3852
 
 
3853
 
 
3854
  /*************************************************************************/
 
3855
  /*                                                                       */
 
3856
  /* POP[]:        POP the stack's top element                             */
 
3857
  /* Opcode range: 0x21                                                    */
 
3858
  /* Stack:        StkElt -->                                              */
 
3859
  /*                                                                       */
 
3860
  static void
 
3861
  Ins_POP( INS_ARG )
 
3862
  {
 
3863
    /* nothing to do */
 
3864
  }
 
3865
 
 
3866
 
 
3867
  /*************************************************************************/
 
3868
  /*                                                                       */
 
3869
  /* CLEAR[]:      CLEAR the entire stack                                  */
 
3870
  /* Opcode range: 0x22                                                    */
 
3871
  /* Stack:        StkElt... -->                                           */
 
3872
  /*                                                                       */
 
3873
  static void
 
3874
  Ins_CLEAR( INS_ARG )
 
3875
  {
 
3876
    DO_CLEAR
 
3877
  }
 
3878
 
 
3879
 
 
3880
  /*************************************************************************/
 
3881
  /*                                                                       */
 
3882
  /* SWAP[]:       SWAP the stack's top two elements                       */
 
3883
  /* Opcode range: 0x23                                                    */
 
3884
  /* Stack:        2 * StkElt --> 2 * StkElt                               */
 
3885
  /*                                                                       */
 
3886
  static void
 
3887
  Ins_SWAP( INS_ARG )
 
3888
  {
 
3889
    DO_SWAP
 
3890
  }
 
3891
 
 
3892
 
 
3893
  /*************************************************************************/
 
3894
  /*                                                                       */
 
3895
  /* DEPTH[]:      return the stack DEPTH                                  */
 
3896
  /* Opcode range: 0x24                                                    */
 
3897
  /* Stack:        --> uint32                                              */
 
3898
  /*                                                                       */
 
3899
  static void
 
3900
  Ins_DEPTH( INS_ARG )
 
3901
  {
 
3902
    DO_DEPTH
 
3903
  }
 
3904
 
 
3905
 
 
3906
  /*************************************************************************/
 
3907
  /*                                                                       */
 
3908
  /* CINDEX[]:     Copy INDEXed element                                    */
 
3909
  /* Opcode range: 0x25                                                    */
 
3910
  /* Stack:        int32 --> StkElt                                        */
 
3911
  /*                                                                       */
 
3912
  static void
 
3913
  Ins_CINDEX( INS_ARG )
 
3914
  {
 
3915
    DO_CINDEX
 
3916
  }
 
3917
 
 
3918
 
 
3919
  /*************************************************************************/
 
3920
  /*                                                                       */
 
3921
  /* EIF[]:        End IF                                                  */
 
3922
  /* Opcode range: 0x59                                                    */
 
3923
  /* Stack:        -->                                                     */
 
3924
  /*                                                                       */
 
3925
  static void
 
3926
  Ins_EIF( INS_ARG )
 
3927
  {
 
3928
    /* nothing to do */
 
3929
  }
 
3930
 
 
3931
 
 
3932
  /*************************************************************************/
 
3933
  /*                                                                       */
 
3934
  /* JROT[]:       Jump Relative On True                                   */
 
3935
  /* Opcode range: 0x78                                                    */
 
3936
  /* Stack:        StkElt int32 -->                                        */
 
3937
  /*                                                                       */
 
3938
  static void
 
3939
  Ins_JROT( INS_ARG )
 
3940
  {
 
3941
    DO_JROT
 
3942
  }
 
3943
 
 
3944
 
 
3945
  /*************************************************************************/
 
3946
  /*                                                                       */
 
3947
  /* JMPR[]:       JuMP Relative                                           */
 
3948
  /* Opcode range: 0x1C                                                    */
 
3949
  /* Stack:        int32 -->                                               */
 
3950
  /*                                                                       */
 
3951
  static void
 
3952
  Ins_JMPR( INS_ARG )
 
3953
  {
 
3954
    DO_JMPR
 
3955
  }
 
3956
 
 
3957
 
 
3958
  /*************************************************************************/
 
3959
  /*                                                                       */
 
3960
  /* JROF[]:       Jump Relative On False                                  */
 
3961
  /* Opcode range: 0x79                                                    */
 
3962
  /* Stack:        StkElt int32 -->                                        */
 
3963
  /*                                                                       */
 
3964
  static void
 
3965
  Ins_JROF( INS_ARG )
 
3966
  {
 
3967
    DO_JROF
 
3968
  }
 
3969
 
 
3970
 
 
3971
  /*************************************************************************/
 
3972
  /*                                                                       */
 
3973
  /* LT[]:         Less Than                                               */
 
3974
  /* Opcode range: 0x50                                                    */
 
3975
  /* Stack:        int32? int32? --> bool                                  */
 
3976
  /*                                                                       */
 
3977
  static void
 
3978
  Ins_LT( INS_ARG )
 
3979
  {
 
3980
    DO_LT
 
3981
  }
 
3982
 
 
3983
 
 
3984
  /*************************************************************************/
 
3985
  /*                                                                       */
 
3986
  /* LTEQ[]:       Less Than or EQual                                      */
 
3987
  /* Opcode range: 0x51                                                    */
 
3988
  /* Stack:        int32? int32? --> bool                                  */
 
3989
  /*                                                                       */
 
3990
  static void
 
3991
  Ins_LTEQ( INS_ARG )
 
3992
  {
 
3993
    DO_LTEQ
 
3994
  }
 
3995
 
 
3996
 
 
3997
  /*************************************************************************/
 
3998
  /*                                                                       */
 
3999
  /* GT[]:         Greater Than                                            */
 
4000
  /* Opcode range: 0x52                                                    */
 
4001
  /* Stack:        int32? int32? --> bool                                  */
 
4002
  /*                                                                       */
 
4003
  static void
 
4004
  Ins_GT( INS_ARG )
 
4005
  {
 
4006
    DO_GT
 
4007
  }
 
4008
 
 
4009
 
 
4010
  /*************************************************************************/
 
4011
  /*                                                                       */
 
4012
  /* GTEQ[]:       Greater Than or EQual                                   */
 
4013
  /* Opcode range: 0x53                                                    */
 
4014
  /* Stack:        int32? int32? --> bool                                  */
 
4015
  /*                                                                       */
 
4016
  static void
 
4017
  Ins_GTEQ( INS_ARG )
 
4018
  {
 
4019
    DO_GTEQ
 
4020
  }
 
4021
 
 
4022
 
 
4023
  /*************************************************************************/
 
4024
  /*                                                                       */
 
4025
  /* EQ[]:         EQual                                                   */
 
4026
  /* Opcode range: 0x54                                                    */
 
4027
  /* Stack:        StkElt StkElt --> bool                                  */
 
4028
  /*                                                                       */
 
4029
  static void
 
4030
  Ins_EQ( INS_ARG )
 
4031
  {
 
4032
    DO_EQ
 
4033
  }
 
4034
 
 
4035
 
 
4036
  /*************************************************************************/
 
4037
  /*                                                                       */
 
4038
  /* NEQ[]:        Not EQual                                               */
 
4039
  /* Opcode range: 0x55                                                    */
 
4040
  /* Stack:        StkElt StkElt --> bool                                  */
 
4041
  /*                                                                       */
 
4042
  static void
 
4043
  Ins_NEQ( INS_ARG )
 
4044
  {
 
4045
    DO_NEQ
 
4046
  }
 
4047
 
 
4048
 
 
4049
  /*************************************************************************/
 
4050
  /*                                                                       */
 
4051
  /* ODD[]:        Is ODD                                                  */
 
4052
  /* Opcode range: 0x56                                                    */
 
4053
  /* Stack:        f26.6 --> bool                                          */
 
4054
  /*                                                                       */
 
4055
  static void
 
4056
  Ins_ODD( INS_ARG )
 
4057
  {
 
4058
    DO_ODD
 
4059
  }
 
4060
 
 
4061
 
 
4062
  /*************************************************************************/
 
4063
  /*                                                                       */
 
4064
  /* EVEN[]:       Is EVEN                                                 */
 
4065
  /* Opcode range: 0x57                                                    */
 
4066
  /* Stack:        f26.6 --> bool                                          */
 
4067
  /*                                                                       */
 
4068
  static void
 
4069
  Ins_EVEN( INS_ARG )
 
4070
  {
 
4071
    DO_EVEN
 
4072
  }
 
4073
 
 
4074
 
 
4075
  /*************************************************************************/
 
4076
  /*                                                                       */
 
4077
  /* AND[]:        logical AND                                             */
 
4078
  /* Opcode range: 0x5A                                                    */
 
4079
  /* Stack:        uint32 uint32 --> uint32                                */
 
4080
  /*                                                                       */
 
4081
  static void
 
4082
  Ins_AND( INS_ARG )
 
4083
  {
 
4084
    DO_AND
 
4085
  }
 
4086
 
 
4087
 
 
4088
  /*************************************************************************/
 
4089
  /*                                                                       */
 
4090
  /* OR[]:         logical OR                                              */
 
4091
  /* Opcode range: 0x5B                                                    */
 
4092
  /* Stack:        uint32 uint32 --> uint32                                */
 
4093
  /*                                                                       */
 
4094
  static void
 
4095
  Ins_OR( INS_ARG )
 
4096
  {
 
4097
    DO_OR
 
4098
  }
 
4099
 
 
4100
 
 
4101
  /*************************************************************************/
 
4102
  /*                                                                       */
 
4103
  /* NOT[]:        logical NOT                                             */
 
4104
  /* Opcode range: 0x5C                                                    */
 
4105
  /* Stack:        StkElt --> uint32                                       */
 
4106
  /*                                                                       */
 
4107
  static void
 
4108
  Ins_NOT( INS_ARG )
 
4109
  {
 
4110
    DO_NOT
 
4111
  }
 
4112
 
 
4113
 
 
4114
  /*************************************************************************/
 
4115
  /*                                                                       */
 
4116
  /* ADD[]:        ADD                                                     */
 
4117
  /* Opcode range: 0x60                                                    */
 
4118
  /* Stack:        f26.6 f26.6 --> f26.6                                   */
 
4119
  /*                                                                       */
 
4120
  static void
 
4121
  Ins_ADD( INS_ARG )
 
4122
  {
 
4123
    DO_ADD
 
4124
  }
 
4125
 
 
4126
 
 
4127
  /*************************************************************************/
 
4128
  /*                                                                       */
 
4129
  /* SUB[]:        SUBtract                                                */
 
4130
  /* Opcode range: 0x61                                                    */
 
4131
  /* Stack:        f26.6 f26.6 --> f26.6                                   */
 
4132
  /*                                                                       */
 
4133
  static void
 
4134
  Ins_SUB( INS_ARG )
 
4135
  {
 
4136
    DO_SUB
 
4137
  }
 
4138
 
 
4139
 
 
4140
  /*************************************************************************/
 
4141
  /*                                                                       */
 
4142
  /* DIV[]:        DIVide                                                  */
 
4143
  /* Opcode range: 0x62                                                    */
 
4144
  /* Stack:        f26.6 f26.6 --> f26.6                                   */
 
4145
  /*                                                                       */
 
4146
  static void
 
4147
  Ins_DIV( INS_ARG )
 
4148
  {
 
4149
    DO_DIV
 
4150
  }
 
4151
 
 
4152
 
 
4153
  /*************************************************************************/
 
4154
  /*                                                                       */
 
4155
  /* MUL[]:        MULtiply                                                */
 
4156
  /* Opcode range: 0x63                                                    */
 
4157
  /* Stack:        f26.6 f26.6 --> f26.6                                   */
 
4158
  /*                                                                       */
 
4159
  static void
 
4160
  Ins_MUL( INS_ARG )
 
4161
  {
 
4162
    DO_MUL
 
4163
  }
 
4164
 
 
4165
 
 
4166
  /*************************************************************************/
 
4167
  /*                                                                       */
 
4168
  /* ABS[]:        ABSolute value                                          */
 
4169
  /* Opcode range: 0x64                                                    */
 
4170
  /* Stack:        f26.6 --> f26.6                                         */
 
4171
  /*                                                                       */
 
4172
  static void
 
4173
  Ins_ABS( INS_ARG )
 
4174
  {
 
4175
    DO_ABS
 
4176
  }
 
4177
 
 
4178
 
 
4179
  /*************************************************************************/
 
4180
  /*                                                                       */
 
4181
  /* NEG[]:        NEGate                                                  */
 
4182
  /* Opcode range: 0x65                                                    */
 
4183
  /* Stack: f26.6 --> f26.6                                                */
 
4184
  /*                                                                       */
 
4185
  static void
 
4186
  Ins_NEG( INS_ARG )
 
4187
  {
 
4188
    DO_NEG
 
4189
  }
 
4190
 
 
4191
 
 
4192
  /*************************************************************************/
 
4193
  /*                                                                       */
 
4194
  /* FLOOR[]:      FLOOR                                                   */
 
4195
  /* Opcode range: 0x66                                                    */
 
4196
  /* Stack:        f26.6 --> f26.6                                         */
 
4197
  /*                                                                       */
 
4198
  static void
 
4199
  Ins_FLOOR( INS_ARG )
 
4200
  {
 
4201
    DO_FLOOR
 
4202
  }
 
4203
 
 
4204
 
 
4205
  /*************************************************************************/
 
4206
  /*                                                                       */
 
4207
  /* CEILING[]:    CEILING                                                 */
 
4208
  /* Opcode range: 0x67                                                    */
 
4209
  /* Stack:        f26.6 --> f26.6                                         */
 
4210
  /*                                                                       */
 
4211
  static void
 
4212
  Ins_CEILING( INS_ARG )
 
4213
  {
 
4214
    DO_CEILING
 
4215
  }
 
4216
 
 
4217
 
 
4218
  /*************************************************************************/
 
4219
  /*                                                                       */
 
4220
  /* RS[]:         Read Store                                              */
 
4221
  /* Opcode range: 0x43                                                    */
 
4222
  /* Stack:        uint32 --> uint32                                       */
 
4223
  /*                                                                       */
 
4224
  static void
 
4225
  Ins_RS( INS_ARG )
 
4226
  {
 
4227
    DO_RS
 
4228
  }
 
4229
 
 
4230
 
 
4231
  /*************************************************************************/
 
4232
  /*                                                                       */
 
4233
  /* WS[]:         Write Store                                             */
 
4234
  /* Opcode range: 0x42                                                    */
 
4235
  /* Stack:        uint32 uint32 -->                                       */
 
4236
  /*                                                                       */
 
4237
  static void
 
4238
  Ins_WS( INS_ARG )
 
4239
  {
 
4240
    DO_WS
 
4241
  }
 
4242
 
 
4243
 
 
4244
  /*************************************************************************/
 
4245
  /*                                                                       */
 
4246
  /* WCVTP[]:      Write CVT in Pixel units                                */
 
4247
  /* Opcode range: 0x44                                                    */
 
4248
  /* Stack:        f26.6 uint32 -->                                        */
 
4249
  /*                                                                       */
 
4250
  static void
 
4251
  Ins_WCVTP( INS_ARG )
 
4252
  {
 
4253
    DO_WCVTP
 
4254
  }
 
4255
 
 
4256
 
 
4257
  /*************************************************************************/
 
4258
  /*                                                                       */
 
4259
  /* WCVTF[]:      Write CVT in Funits                                     */
 
4260
  /* Opcode range: 0x70                                                    */
 
4261
  /* Stack:        uint32 uint32 -->                                       */
 
4262
  /*                                                                       */
 
4263
  static void
 
4264
  Ins_WCVTF( INS_ARG )
 
4265
  {
 
4266
    DO_WCVTF
 
4267
  }
 
4268
 
 
4269
 
 
4270
  /*************************************************************************/
 
4271
  /*                                                                       */
 
4272
  /* RCVT[]:       Read CVT                                                */
 
4273
  /* Opcode range: 0x45                                                    */
 
4274
  /* Stack:        uint32 --> f26.6                                        */
 
4275
  /*                                                                       */
 
4276
  static void
 
4277
  Ins_RCVT( INS_ARG )
 
4278
  {
 
4279
    DO_RCVT
 
4280
  }
 
4281
 
 
4282
 
 
4283
  /*************************************************************************/
 
4284
  /*                                                                       */
 
4285
  /* AA[]:         Adjust Angle                                            */
 
4286
  /* Opcode range: 0x7F                                                    */
 
4287
  /* Stack:        uint32 -->                                              */
 
4288
  /*                                                                       */
 
4289
  static void
 
4290
  Ins_AA( INS_ARG )
 
4291
  {
 
4292
    /* intentionally no longer supported */
 
4293
  }
 
4294
 
 
4295
 
 
4296
  /*************************************************************************/
 
4297
  /*                                                                       */
 
4298
  /* DEBUG[]:      DEBUG.  Unsupported.                                    */
 
4299
  /* Opcode range: 0x4F                                                    */
 
4300
  /* Stack:        uint32 -->                                              */
 
4301
  /*                                                                       */
 
4302
  /* Note: The original instruction pops a value from the stack.           */
 
4303
  /*                                                                       */
 
4304
  static void
 
4305
  Ins_DEBUG( INS_ARG )
 
4306
  {
 
4307
    DO_DEBUG
 
4308
  }
 
4309
 
 
4310
 
 
4311
  /*************************************************************************/
 
4312
  /*                                                                       */
 
4313
  /* ROUND[ab]:    ROUND value                                             */
 
4314
  /* Opcode range: 0x68-0x6B                                               */
 
4315
  /* Stack:        f26.6 --> f26.6                                         */
 
4316
  /*                                                                       */
 
4317
  static void
 
4318
  Ins_ROUND( INS_ARG )
 
4319
  {
 
4320
    DO_ROUND
 
4321
  }
 
4322
 
 
4323
 
 
4324
  /*************************************************************************/
 
4325
  /*                                                                       */
 
4326
  /* NROUND[ab]:   No ROUNDing of value                                    */
 
4327
  /* Opcode range: 0x6C-0x6F                                               */
 
4328
  /* Stack:        f26.6 --> f26.6                                         */
 
4329
  /*                                                                       */
 
4330
  static void
 
4331
  Ins_NROUND( INS_ARG )
 
4332
  {
 
4333
    DO_NROUND
 
4334
  }
 
4335
 
 
4336
 
 
4337
  /*************************************************************************/
 
4338
  /*                                                                       */
 
4339
  /* MAX[]:        MAXimum                                                 */
 
4340
  /* Opcode range: 0x68                                                    */
 
4341
  /* Stack:        int32? int32? --> int32                                 */
 
4342
  /*                                                                       */
 
4343
  static void
 
4344
  Ins_MAX( INS_ARG )
 
4345
  {
 
4346
    DO_MAX
 
4347
  }
 
4348
 
 
4349
 
 
4350
  /*************************************************************************/
 
4351
  /*                                                                       */
 
4352
  /* MIN[]:        MINimum                                                 */
 
4353
  /* Opcode range: 0x69                                                    */
 
4354
  /* Stack:        int32? int32? --> int32                                 */
 
4355
  /*                                                                       */
 
4356
  static void
 
4357
  Ins_MIN( INS_ARG )
 
4358
  {
 
4359
    DO_MIN
 
4360
  }
 
4361
 
 
4362
 
 
4363
#endif  /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
 
4364
 
 
4365
 
 
4366
  /*************************************************************************/
 
4367
  /*                                                                       */
 
4368
  /* The following functions are called as is within the switch statement. */
 
4369
  /*                                                                       */
 
4370
  /*************************************************************************/
 
4371
 
 
4372
 
 
4373
  /*************************************************************************/
 
4374
  /*                                                                       */
 
4375
  /* MINDEX[]:     Move INDEXed element                                    */
 
4376
  /* Opcode range: 0x26                                                    */
 
4377
  /* Stack:        int32? --> StkElt                                       */
 
4378
  /*                                                                       */
 
4379
  static void
 
4380
  Ins_MINDEX( INS_ARG )
 
4381
  {
 
4382
    FT_Long  L, K;
 
4383
 
 
4384
 
 
4385
    L = args[0];
 
4386
 
 
4387
    if ( L <= 0 || L > CUR.args )
 
4388
    {
 
4389
      CUR.error = TT_Err_Invalid_Reference;
 
4390
      return;
 
4391
    }
 
4392
 
 
4393
    K = CUR.stack[CUR.args - L];
 
4394
 
 
4395
    FT_ARRAY_MOVE( &CUR.stack[CUR.args - L    ],
 
4396
                   &CUR.stack[CUR.args - L + 1],
 
4397
                   ( L - 1 ) );
 
4398
 
 
4399
    CUR.stack[CUR.args - 1] = K;
 
4400
  }
 
4401
 
 
4402
 
 
4403
  /*************************************************************************/
 
4404
  /*                                                                       */
 
4405
  /* ROLL[]:       ROLL top three elements                                 */
 
4406
  /* Opcode range: 0x8A                                                    */
 
4407
  /* Stack:        3 * StkElt --> 3 * StkElt                               */
 
4408
  /*                                                                       */
 
4409
  static void
 
4410
  Ins_ROLL( INS_ARG )
 
4411
  {
 
4412
    FT_Long  A, B, C;
 
4413
 
 
4414
    FT_UNUSED_EXEC;
 
4415
 
 
4416
 
 
4417
    A = args[2];
 
4418
    B = args[1];
 
4419
    C = args[0];
 
4420
 
 
4421
    args[2] = C;
 
4422
    args[1] = A;
 
4423
    args[0] = B;
 
4424
  }
 
4425
 
 
4426
 
 
4427
  /*************************************************************************/
 
4428
  /*                                                                       */
 
4429
  /* MANAGING THE FLOW OF CONTROL                                          */
 
4430
  /*                                                                       */
 
4431
  /*   Instructions appear in the specification's order.                   */
 
4432
  /*                                                                       */
 
4433
  /*************************************************************************/
 
4434
 
 
4435
 
 
4436
  static FT_Bool
 
4437
  SkipCode( EXEC_OP )
 
4438
  {
 
4439
    CUR.IP += CUR.length;
 
4440
 
 
4441
    if ( CUR.IP < CUR.codeSize )
 
4442
    {
 
4443
      CUR.opcode = CUR.code[CUR.IP];
 
4444
 
 
4445
      CUR.length = opcode_length[CUR.opcode];
 
4446
      if ( CUR.length < 0 )
 
4447
      {
 
4448
        if ( CUR.IP + 1 > CUR.codeSize )
 
4449
          goto Fail_Overflow;
 
4450
        CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
 
4451
      }
 
4452
 
 
4453
      if ( CUR.IP + CUR.length <= CUR.codeSize )
 
4454
        return SUCCESS;
 
4455
    }
 
4456
 
 
4457
  Fail_Overflow:
 
4458
    CUR.error = TT_Err_Code_Overflow;
 
4459
    return FAILURE;
 
4460
  }
 
4461
 
 
4462
 
 
4463
  /*************************************************************************/
 
4464
  /*                                                                       */
 
4465
  /* IF[]:         IF test                                                 */
 
4466
  /* Opcode range: 0x58                                                    */
 
4467
  /* Stack:        StkElt -->                                              */
 
4468
  /*                                                                       */
 
4469
  static void
 
4470
  Ins_IF( INS_ARG )
 
4471
  {
 
4472
    FT_Int   nIfs;
 
4473
    FT_Bool  Out;
 
4474
 
 
4475
 
 
4476
    if ( args[0] != 0 )
 
4477
      return;
 
4478
 
 
4479
    nIfs = 1;
 
4480
    Out = 0;
 
4481
 
 
4482
    do
 
4483
    {
 
4484
      if ( SKIP_Code() == FAILURE )
 
4485
        return;
 
4486
 
 
4487
      switch ( CUR.opcode )
 
4488
      {
 
4489
      case 0x58:      /* IF */
 
4490
        nIfs++;
 
4491
        break;
 
4492
 
 
4493
      case 0x1B:      /* ELSE */
 
4494
        Out = FT_BOOL( nIfs == 1 );
 
4495
        break;
 
4496
 
 
4497
      case 0x59:      /* EIF */
 
4498
        nIfs--;
 
4499
        Out = FT_BOOL( nIfs == 0 );
 
4500
        break;
 
4501
      }
 
4502
    } while ( Out == 0 );
 
4503
  }
 
4504
 
 
4505
 
 
4506
  /*************************************************************************/
 
4507
  /*                                                                       */
 
4508
  /* ELSE[]:       ELSE                                                    */
 
4509
  /* Opcode range: 0x1B                                                    */
 
4510
  /* Stack:        -->                                                     */
 
4511
  /*                                                                       */
 
4512
  static void
 
4513
  Ins_ELSE( INS_ARG )
 
4514
  {
 
4515
    FT_Int  nIfs;
 
4516
 
 
4517
    FT_UNUSED_ARG;
 
4518
 
 
4519
 
 
4520
    nIfs = 1;
 
4521
 
 
4522
    do
 
4523
    {
 
4524
      if ( SKIP_Code() == FAILURE )
 
4525
        return;
 
4526
 
 
4527
      switch ( CUR.opcode )
 
4528
      {
 
4529
      case 0x58:    /* IF */
 
4530
        nIfs++;
 
4531
        break;
 
4532
 
 
4533
      case 0x59:    /* EIF */
 
4534
        nIfs--;
 
4535
        break;
 
4536
      }
 
4537
    } while ( nIfs != 0 );
 
4538
  }
 
4539
 
 
4540
 
 
4541
  /*************************************************************************/
 
4542
  /*                                                                       */
 
4543
  /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS                         */
 
4544
  /*                                                                       */
 
4545
  /*   Instructions appear in the specification's order.                   */
 
4546
  /*                                                                       */
 
4547
  /*************************************************************************/
 
4548
 
 
4549
 
 
4550
  /*************************************************************************/
 
4551
  /*                                                                       */
 
4552
  /* FDEF[]:       Function DEFinition                                     */
 
4553
  /* Opcode range: 0x2C                                                    */
 
4554
  /* Stack:        uint32 -->                                              */
 
4555
  /*                                                                       */
 
4556
  static void
 
4557
  Ins_FDEF( INS_ARG )
 
4558
  {
 
4559
    FT_ULong       n;
 
4560
    TT_DefRecord*  rec;
 
4561
    TT_DefRecord*  limit;
 
4562
 
 
4563
 
 
4564
    /* some font programs are broken enough to redefine functions! */
 
4565
    /* We will then parse the current table.                       */
 
4566
 
 
4567
    rec   = CUR.FDefs;
 
4568
    limit = rec + CUR.numFDefs;
 
4569
    n     = args[0];
 
4570
 
 
4571
    for ( ; rec < limit; rec++ )
 
4572
    {
 
4573
      if ( rec->opc == n )
 
4574
        break;
 
4575
    }
 
4576
 
 
4577
    if ( rec == limit )
 
4578
    {
 
4579
      /* check that there is enough room for new functions */
 
4580
      if ( CUR.numFDefs >= CUR.maxFDefs )
 
4581
      {
 
4582
        CUR.error = TT_Err_Too_Many_Function_Defs;
 
4583
        return;
 
4584
      }
 
4585
      CUR.numFDefs++;
 
4586
    }
 
4587
 
 
4588
    /* Although FDEF takes unsigned 32-bit integer,  */
 
4589
    /* func # must be within unsigned 16-bit integer */
 
4590
    if ( n > 0xFFFFU )
 
4591
    {
 
4592
      CUR.error = TT_Err_Too_Many_Function_Defs;
 
4593
      return;
 
4594
    }
 
4595
 
 
4596
    rec->range  = CUR.curRange;
 
4597
    rec->opc    = (FT_UInt16)n;
 
4598
    rec->start  = CUR.IP + 1;
 
4599
    rec->active = TRUE;
 
4600
 
 
4601
    if ( n > CUR.maxFunc )
 
4602
      CUR.maxFunc = (FT_UInt16)n;
 
4603
 
 
4604
    /* Now skip the whole function definition. */
 
4605
    /* We don't allow nested IDEFS & FDEFs.    */
 
4606
 
 
4607
    while ( SKIP_Code() == SUCCESS )
 
4608
    {
 
4609
      switch ( CUR.opcode )
 
4610
      {
 
4611
      case 0x89:    /* IDEF */
 
4612
      case 0x2C:    /* FDEF */
 
4613
        CUR.error = TT_Err_Nested_DEFS;
 
4614
        return;
 
4615
 
 
4616
      case 0x2D:   /* ENDF */
 
4617
        return;
 
4618
      }
 
4619
    }
 
4620
  }
 
4621
 
 
4622
 
 
4623
  /*************************************************************************/
 
4624
  /*                                                                       */
 
4625
  /* ENDF[]:       END Function definition                                 */
 
4626
  /* Opcode range: 0x2D                                                    */
 
4627
  /* Stack:        -->                                                     */
 
4628
  /*                                                                       */
 
4629
  static void
 
4630
  Ins_ENDF( INS_ARG )
 
4631
  {
 
4632
    TT_CallRec*  pRec;
 
4633
 
 
4634
    FT_UNUSED_ARG;
 
4635
 
 
4636
 
 
4637
    if ( CUR.callTop <= 0 )     /* We encountered an ENDF without a call */
 
4638
    {
 
4639
      CUR.error = TT_Err_ENDF_In_Exec_Stream;
 
4640
      return;
 
4641
    }
 
4642
 
 
4643
    CUR.callTop--;
 
4644
 
 
4645
    pRec = &CUR.callStack[CUR.callTop];
 
4646
 
 
4647
    pRec->Cur_Count--;
 
4648
 
 
4649
    CUR.step_ins = FALSE;
 
4650
 
 
4651
    if ( pRec->Cur_Count > 0 )
 
4652
    {
 
4653
      CUR.callTop++;
 
4654
      CUR.IP = pRec->Cur_Restart;
 
4655
    }
 
4656
    else
 
4657
      /* Loop through the current function */
 
4658
      INS_Goto_CodeRange( pRec->Caller_Range,
 
4659
                          pRec->Caller_IP );
 
4660
 
 
4661
    /* Exit the current call frame.                      */
 
4662
 
 
4663
    /* NOTE: If the last instruction of a program is a   */
 
4664
    /*       CALL or LOOPCALL, the return address is     */
 
4665
    /*       always out of the code range.  This is a    */
 
4666
    /*       valid address, and it is why we do not test */
 
4667
    /*       the result of Ins_Goto_CodeRange() here!    */
 
4668
  }
 
4669
 
 
4670
 
 
4671
  /*************************************************************************/
 
4672
  /*                                                                       */
 
4673
  /* CALL[]:       CALL function                                           */
 
4674
  /* Opcode range: 0x2B                                                    */
 
4675
  /* Stack:        uint32? -->                                             */
 
4676
  /*                                                                       */
 
4677
  static void
 
4678
  Ins_CALL( INS_ARG )
 
4679
  {
 
4680
    FT_ULong       F;
 
4681
    TT_CallRec*    pCrec;
 
4682
    TT_DefRecord*  def;
 
4683
 
 
4684
 
 
4685
    /* first of all, check the index */
 
4686
 
 
4687
    F = args[0];
 
4688
    if ( BOUNDSL( F, CUR.maxFunc + 1 ) )
 
4689
      goto Fail;
 
4690
 
 
4691
    /* Except for some old Apple fonts, all functions in a TrueType */
 
4692
    /* font are defined in increasing order, starting from 0.  This */
 
4693
    /* means that we normally have                                  */
 
4694
    /*                                                              */
 
4695
    /*    CUR.maxFunc+1 == CUR.numFDefs                             */
 
4696
    /*    CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc             */
 
4697
    /*                                                              */
 
4698
    /* If this isn't true, we need to look up the function table.   */
 
4699
 
 
4700
    def = CUR.FDefs + F;
 
4701
    if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
 
4702
    {
 
4703
      /* look up the FDefs table */
 
4704
      TT_DefRecord*  limit;
 
4705
 
 
4706
 
 
4707
      def   = CUR.FDefs;
 
4708
      limit = def + CUR.numFDefs;
 
4709
 
 
4710
      while ( def < limit && def->opc != F )
 
4711
        def++;
 
4712
 
 
4713
      if ( def == limit )
 
4714
        goto Fail;
 
4715
    }
 
4716
 
 
4717
    /* check that the function is active */
 
4718
    if ( !def->active )
 
4719
      goto Fail;
 
4720
 
 
4721
    /* check the call stack */
 
4722
    if ( CUR.callTop >= CUR.callSize )
 
4723
    {
 
4724
      CUR.error = TT_Err_Stack_Overflow;
 
4725
      return;
 
4726
    }
 
4727
 
 
4728
    pCrec = CUR.callStack + CUR.callTop;
 
4729
 
 
4730
    pCrec->Caller_Range = CUR.curRange;
 
4731
    pCrec->Caller_IP    = CUR.IP + 1;
 
4732
    pCrec->Cur_Count    = 1;
 
4733
    pCrec->Cur_Restart  = def->start;
 
4734
 
 
4735
    CUR.callTop++;
 
4736
 
 
4737
    INS_Goto_CodeRange( def->range,
 
4738
                        def->start );
 
4739
 
 
4740
    CUR.step_ins = FALSE;
 
4741
    return;
 
4742
 
 
4743
  Fail:
 
4744
    CUR.error = TT_Err_Invalid_Reference;
 
4745
  }
 
4746
 
 
4747
 
 
4748
  /*************************************************************************/
 
4749
  /*                                                                       */
 
4750
  /* LOOPCALL[]:   LOOP and CALL function                                  */
 
4751
  /* Opcode range: 0x2A                                                    */
 
4752
  /* Stack:        uint32? Eint16? -->                                     */
 
4753
  /*                                                                       */
 
4754
  static void
 
4755
  Ins_LOOPCALL( INS_ARG )
 
4756
  {
 
4757
    FT_ULong       F;
 
4758
    TT_CallRec*    pCrec;
 
4759
    TT_DefRecord*  def;
 
4760
 
 
4761
 
 
4762
    /* first of all, check the index */
 
4763
    F = args[1];
 
4764
    if ( BOUNDSL( F, CUR.maxFunc + 1 ) )
 
4765
      goto Fail;
 
4766
 
 
4767
    /* Except for some old Apple fonts, all functions in a TrueType */
 
4768
    /* font are defined in increasing order, starting from 0.  This */
 
4769
    /* means that we normally have                                  */
 
4770
    /*                                                              */
 
4771
    /*    CUR.maxFunc+1 == CUR.numFDefs                             */
 
4772
    /*    CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc             */
 
4773
    /*                                                              */
 
4774
    /* If this isn't true, we need to look up the function table.   */
 
4775
 
 
4776
    def = CUR.FDefs + F;
 
4777
    if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
 
4778
    {
 
4779
      /* look up the FDefs table */
 
4780
      TT_DefRecord*  limit;
 
4781
 
 
4782
 
 
4783
      def   = CUR.FDefs;
 
4784
      limit = def + CUR.numFDefs;
 
4785
 
 
4786
      while ( def < limit && def->opc != F )
 
4787
        def++;
 
4788
 
 
4789
      if ( def == limit )
 
4790
        goto Fail;
 
4791
    }
 
4792
 
 
4793
    /* check that the function is active */
 
4794
    if ( !def->active )
 
4795
      goto Fail;
 
4796
 
 
4797
    /* check stack */
 
4798
    if ( CUR.callTop >= CUR.callSize )
 
4799
    {
 
4800
      CUR.error = TT_Err_Stack_Overflow;
 
4801
      return;
 
4802
    }
 
4803
 
 
4804
    if ( args[0] > 0 )
 
4805
    {
 
4806
      pCrec = CUR.callStack + CUR.callTop;
 
4807
 
 
4808
      pCrec->Caller_Range = CUR.curRange;
 
4809
      pCrec->Caller_IP    = CUR.IP + 1;
 
4810
      pCrec->Cur_Count    = (FT_Int)args[0];
 
4811
      pCrec->Cur_Restart  = def->start;
 
4812
 
 
4813
      CUR.callTop++;
 
4814
 
 
4815
      INS_Goto_CodeRange( def->range, def->start );
 
4816
 
 
4817
      CUR.step_ins = FALSE;
 
4818
    }
 
4819
    return;
 
4820
 
 
4821
  Fail:
 
4822
    CUR.error = TT_Err_Invalid_Reference;
 
4823
  }
 
4824
 
 
4825
 
 
4826
  /*************************************************************************/
 
4827
  /*                                                                       */
 
4828
  /* IDEF[]:       Instruction DEFinition                                  */
 
4829
  /* Opcode range: 0x89                                                    */
 
4830
  /* Stack:        Eint8 -->                                               */
 
4831
  /*                                                                       */
 
4832
  static void
 
4833
  Ins_IDEF( INS_ARG )
 
4834
  {
 
4835
    TT_DefRecord*  def;
 
4836
    TT_DefRecord*  limit;
 
4837
 
 
4838
 
 
4839
    /*  First of all, look for the same function in our table */
 
4840
 
 
4841
    def   = CUR.IDefs;
 
4842
    limit = def + CUR.numIDefs;
 
4843
 
 
4844
    for ( ; def < limit; def++ )
 
4845
      if ( def->opc == (FT_ULong)args[0] )
 
4846
        break;
 
4847
 
 
4848
    if ( def == limit )
 
4849
    {
 
4850
      /* check that there is enough room for a new instruction */
 
4851
      if ( CUR.numIDefs >= CUR.maxIDefs )
 
4852
      {
 
4853
        CUR.error = TT_Err_Too_Many_Instruction_Defs;
 
4854
        return;
 
4855
      }
 
4856
      CUR.numIDefs++;
 
4857
    }
 
4858
 
 
4859
    /* opcode must be unsigned 8-bit integer */
 
4860
    if ( 0 > args[0] || args[0] > 0x00FF )
 
4861
    {
 
4862
      CUR.error = TT_Err_Too_Many_Instruction_Defs;
 
4863
      return;
 
4864
    }
 
4865
 
 
4866
    def->opc    = (FT_Byte)args[0];
 
4867
    def->start  = CUR.IP + 1;
 
4868
    def->range  = CUR.curRange;
 
4869
    def->active = TRUE;
 
4870
 
 
4871
    if ( (FT_ULong)args[0] > CUR.maxIns )
 
4872
      CUR.maxIns = (FT_Byte)args[0];
 
4873
 
 
4874
    /* Now skip the whole function definition. */
 
4875
    /* We don't allow nested IDEFs & FDEFs.    */
 
4876
 
 
4877
    while ( SKIP_Code() == SUCCESS )
 
4878
    {
 
4879
      switch ( CUR.opcode )
 
4880
      {
 
4881
      case 0x89:   /* IDEF */
 
4882
      case 0x2C:   /* FDEF */
 
4883
        CUR.error = TT_Err_Nested_DEFS;
 
4884
        return;
 
4885
      case 0x2D:   /* ENDF */
 
4886
        return;
 
4887
      }
 
4888
    }
 
4889
  }
 
4890
 
 
4891
 
 
4892
  /*************************************************************************/
 
4893
  /*                                                                       */
 
4894
  /* PUSHING DATA ONTO THE INTERPRETER STACK                               */
 
4895
  /*                                                                       */
 
4896
  /*   Instructions appear in the specification's order.                   */
 
4897
  /*                                                                       */
 
4898
  /*************************************************************************/
 
4899
 
 
4900
 
 
4901
  /*************************************************************************/
 
4902
  /*                                                                       */
 
4903
  /* NPUSHB[]:     PUSH N Bytes                                            */
 
4904
  /* Opcode range: 0x40                                                    */
 
4905
  /* Stack:        --> uint32...                                           */
 
4906
  /*                                                                       */
 
4907
  static void
 
4908
  Ins_NPUSHB( INS_ARG )
 
4909
  {
 
4910
    FT_UShort  L, K;
 
4911
 
 
4912
 
 
4913
    L = (FT_UShort)CUR.code[CUR.IP + 1];
 
4914
 
 
4915
    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
 
4916
    {
 
4917
      CUR.error = TT_Err_Stack_Overflow;
 
4918
      return;
 
4919
    }
 
4920
 
 
4921
    for ( K = 1; K <= L; K++ )
 
4922
      args[K - 1] = CUR.code[CUR.IP + K + 1];
 
4923
 
 
4924
    CUR.new_top += L;
 
4925
  }
 
4926
 
 
4927
 
 
4928
  /*************************************************************************/
 
4929
  /*                                                                       */
 
4930
  /* NPUSHW[]:     PUSH N Words                                            */
 
4931
  /* Opcode range: 0x41                                                    */
 
4932
  /* Stack:        --> int32...                                            */
 
4933
  /*                                                                       */
 
4934
  static void
 
4935
  Ins_NPUSHW( INS_ARG )
 
4936
  {
 
4937
    FT_UShort  L, K;
 
4938
 
 
4939
 
 
4940
    L = (FT_UShort)CUR.code[CUR.IP + 1];
 
4941
 
 
4942
    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
 
4943
    {
 
4944
      CUR.error = TT_Err_Stack_Overflow;
 
4945
      return;
 
4946
    }
 
4947
 
 
4948
    CUR.IP += 2;
 
4949
 
 
4950
    for ( K = 0; K < L; K++ )
 
4951
      args[K] = GET_ShortIns();
 
4952
 
 
4953
    CUR.step_ins = FALSE;
 
4954
    CUR.new_top += L;
 
4955
  }
 
4956
 
 
4957
 
 
4958
  /*************************************************************************/
 
4959
  /*                                                                       */
 
4960
  /* PUSHB[abc]:   PUSH Bytes                                              */
 
4961
  /* Opcode range: 0xB0-0xB7                                               */
 
4962
  /* Stack:        --> uint32...                                           */
 
4963
  /*                                                                       */
 
4964
  static void
 
4965
  Ins_PUSHB( INS_ARG )
 
4966
  {
 
4967
    FT_UShort  L, K;
 
4968
 
 
4969
 
 
4970
    L = (FT_UShort)( CUR.opcode - 0xB0 + 1 );
 
4971
 
 
4972
    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
 
4973
    {
 
4974
      CUR.error = TT_Err_Stack_Overflow;
 
4975
      return;
 
4976
    }
 
4977
 
 
4978
    for ( K = 1; K <= L; K++ )
 
4979
      args[K - 1] = CUR.code[CUR.IP + K];
 
4980
  }
 
4981
 
 
4982
 
 
4983
  /*************************************************************************/
 
4984
  /*                                                                       */
 
4985
  /* PUSHW[abc]:   PUSH Words                                              */
 
4986
  /* Opcode range: 0xB8-0xBF                                               */
 
4987
  /* Stack:        --> int32...                                            */
 
4988
  /*                                                                       */
 
4989
  static void
 
4990
  Ins_PUSHW( INS_ARG )
 
4991
  {
 
4992
    FT_UShort  L, K;
 
4993
 
 
4994
 
 
4995
    L = (FT_UShort)( CUR.opcode - 0xB8 + 1 );
 
4996
 
 
4997
    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
 
4998
    {
 
4999
      CUR.error = TT_Err_Stack_Overflow;
 
5000
      return;
 
5001
    }
 
5002
 
 
5003
    CUR.IP++;
 
5004
 
 
5005
    for ( K = 0; K < L; K++ )
 
5006
      args[K] = GET_ShortIns();
 
5007
 
 
5008
    CUR.step_ins = FALSE;
 
5009
  }
 
5010
 
 
5011
 
 
5012
  /*************************************************************************/
 
5013
  /*                                                                       */
 
5014
  /* MANAGING THE GRAPHICS STATE                                           */
 
5015
  /*                                                                       */
 
5016
  /*  Instructions appear in the specs' order.                             */
 
5017
  /*                                                                       */
 
5018
  /*************************************************************************/
 
5019
 
 
5020
 
 
5021
  /*************************************************************************/
 
5022
  /*                                                                       */
 
5023
  /* GC[a]:        Get Coordinate projected onto                           */
 
5024
  /* Opcode range: 0x46-0x47                                               */
 
5025
  /* Stack:        uint32 --> f26.6                                        */
 
5026
  /*                                                                       */
 
5027
  /* BULLSHIT: Measures from the original glyph must be taken along the    */
 
5028
  /*           dual projection vector!                                     */
 
5029
  /*                                                                       */
 
5030
  static void
 
5031
  Ins_GC( INS_ARG )
 
5032
  {
 
5033
    FT_ULong    L;
 
5034
    FT_F26Dot6  R;
 
5035
 
 
5036
 
 
5037
    L = (FT_ULong)args[0];
 
5038
 
 
5039
    if ( BOUNDSL( L, CUR.zp2.n_points ) )
 
5040
    {
 
5041
      if ( CUR.pedantic_hinting )
 
5042
      {
 
5043
        CUR.error = TT_Err_Invalid_Reference;
 
5044
        return;
 
5045
      }
 
5046
      else
 
5047
        R = 0;
 
5048
    }
 
5049
    else
 
5050
    {
 
5051
      if ( CUR.opcode & 1 )
 
5052
        R = CUR_fast_dualproj( &CUR.zp2.org[L] );
 
5053
      else
 
5054
        R = CUR_fast_project( &CUR.zp2.cur[L] );
 
5055
    }
 
5056
 
 
5057
    args[0] = R;
 
5058
  }
 
5059
 
 
5060
 
 
5061
  /*************************************************************************/
 
5062
  /*                                                                       */
 
5063
  /* SCFS[]:       Set Coordinate From Stack                               */
 
5064
  /* Opcode range: 0x48                                                    */
 
5065
  /* Stack:        f26.6 uint32 -->                                        */
 
5066
  /*                                                                       */
 
5067
  /* Formula:                                                              */
 
5068
  /*                                                                       */
 
5069
  /*   OA := OA + ( value - OA.p )/( f.p ) * f                             */
 
5070
  /*                                                                       */
 
5071
  static void
 
5072
  Ins_SCFS( INS_ARG )
 
5073
  {
 
5074
    FT_Long    K;
 
5075
    FT_UShort  L;
 
5076
 
 
5077
 
 
5078
    L = (FT_UShort)args[0];
 
5079
 
 
5080
    if ( BOUNDS( L, CUR.zp2.n_points ) )
 
5081
    {
 
5082
      if ( CUR.pedantic_hinting )
 
5083
        CUR.error = TT_Err_Invalid_Reference;
 
5084
      return;
 
5085
    }
 
5086
 
 
5087
    K = CUR_fast_project( &CUR.zp2.cur[L] );
 
5088
 
 
5089
    CUR_Func_move( &CUR.zp2, L, args[1] - K );
 
5090
 
 
5091
    /* not part of the specs, but here for safety */
 
5092
 
 
5093
    if ( CUR.GS.gep2 == 0 )
 
5094
      CUR.zp2.org[L] = CUR.zp2.cur[L];
 
5095
  }
 
5096
 
 
5097
 
 
5098
  /*************************************************************************/
 
5099
  /*                                                                       */
 
5100
  /* MD[a]:        Measure Distance                                        */
 
5101
  /* Opcode range: 0x49-0x4A                                               */
 
5102
  /* Stack:        uint32 uint32 --> f26.6                                 */
 
5103
  /*                                                                       */
 
5104
  /* BULLSHIT: Measure taken in the original glyph must be along the dual  */
 
5105
  /*           projection vector.                                          */
 
5106
  /*                                                                       */
 
5107
  /* Second BULLSHIT: Flag attributes are inverted!                        */
 
5108
  /*                  0 => measure distance in original outline            */
 
5109
  /*                  1 => measure distance in grid-fitted outline         */
 
5110
  /*                                                                       */
 
5111
  /* Third one: `zp0 - zp1', and not `zp2 - zp1!                           */
 
5112
  /*                                                                       */
 
5113
  static void
 
5114
  Ins_MD( INS_ARG )
 
5115
  {
 
5116
    FT_UShort   K, L;
 
5117
    FT_F26Dot6  D;
 
5118
 
 
5119
 
 
5120
    K = (FT_UShort)args[1];
 
5121
    L = (FT_UShort)args[0];
 
5122
 
 
5123
    if ( BOUNDS( L, CUR.zp0.n_points ) ||
 
5124
         BOUNDS( K, CUR.zp1.n_points ) )
 
5125
    {
 
5126
      if ( CUR.pedantic_hinting )
 
5127
      {
 
5128
        CUR.error = TT_Err_Invalid_Reference;
 
5129
        return;
 
5130
      }
 
5131
      D = 0;
 
5132
    }
 
5133
    else
 
5134
    {
 
5135
      if ( CUR.opcode & 1 )
 
5136
        D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
 
5137
      else
 
5138
      {
 
5139
        FT_Vector*  vec1 = CUR.zp0.orus + L;
 
5140
        FT_Vector*  vec2 = CUR.zp1.orus + K;
 
5141
 
 
5142
 
 
5143
        if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
 
5144
        {
 
5145
          /* this should be faster */
 
5146
          D = CUR_Func_dualproj( vec1, vec2 );
 
5147
          D = TT_MULFIX( D, CUR.metrics.x_scale );
 
5148
        }
 
5149
        else
 
5150
        {
 
5151
          FT_Vector  vec;
 
5152
 
 
5153
 
 
5154
          vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
 
5155
          vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
 
5156
 
 
5157
          D = CUR_fast_dualproj( &vec );
 
5158
        }
 
5159
      }
 
5160
    }
 
5161
 
 
5162
    args[0] = D;
 
5163
  }
 
5164
 
 
5165
 
 
5166
  /*************************************************************************/
 
5167
  /*                                                                       */
 
5168
  /* SDPVTL[a]:    Set Dual PVector to Line                                */
 
5169
  /* Opcode range: 0x86-0x87                                               */
 
5170
  /* Stack:        uint32 uint32 -->                                       */
 
5171
  /*                                                                       */
 
5172
  static void
 
5173
  Ins_SDPVTL( INS_ARG )
 
5174
  {
 
5175
    FT_Long    A, B, C;
 
5176
    FT_UShort  p1, p2;   /* was FT_Int in pas type ERROR */
 
5177
 
 
5178
 
 
5179
    p1 = (FT_UShort)args[1];
 
5180
    p2 = (FT_UShort)args[0];
 
5181
 
 
5182
    if ( BOUNDS( p2, CUR.zp1.n_points ) ||
 
5183
         BOUNDS( p1, CUR.zp2.n_points ) )
 
5184
    {
 
5185
      if ( CUR.pedantic_hinting )
 
5186
        CUR.error = TT_Err_Invalid_Reference;
 
5187
      return;
 
5188
    }
 
5189
 
 
5190
    {
 
5191
      FT_Vector* v1 = CUR.zp1.org + p2;
 
5192
      FT_Vector* v2 = CUR.zp2.org + p1;
 
5193
 
 
5194
 
 
5195
      A = v1->x - v2->x;
 
5196
      B = v1->y - v2->y;
 
5197
    }
 
5198
 
 
5199
    if ( ( CUR.opcode & 1 ) != 0 )
 
5200
    {
 
5201
      C =  B;   /* counter clockwise rotation */
 
5202
      B =  A;
 
5203
      A = -C;
 
5204
    }
 
5205
 
 
5206
    NORMalize( A, B, &CUR.GS.dualVector );
 
5207
 
 
5208
    {
 
5209
      FT_Vector*  v1 = CUR.zp1.cur + p2;
 
5210
      FT_Vector*  v2 = CUR.zp2.cur + p1;
 
5211
 
 
5212
 
 
5213
      A = v1->x - v2->x;
 
5214
      B = v1->y - v2->y;
 
5215
    }
 
5216
 
 
5217
    if ( ( CUR.opcode & 1 ) != 0 )
 
5218
    {
 
5219
      C =  B;   /* counter clockwise rotation */
 
5220
      B =  A;
 
5221
      A = -C;
 
5222
    }
 
5223
 
 
5224
    NORMalize( A, B, &CUR.GS.projVector );
 
5225
 
 
5226
    GUESS_VECTOR( freeVector );
 
5227
 
 
5228
    COMPUTE_Funcs();
 
5229
  }
 
5230
 
 
5231
 
 
5232
  /*************************************************************************/
 
5233
  /*                                                                       */
 
5234
  /* SZP0[]:       Set Zone Pointer 0                                      */
 
5235
  /* Opcode range: 0x13                                                    */
 
5236
  /* Stack:        uint32 -->                                              */
 
5237
  /*                                                                       */
 
5238
  static void
 
5239
  Ins_SZP0( INS_ARG )
 
5240
  {
 
5241
    switch ( (FT_Int)args[0] )
 
5242
    {
 
5243
    case 0:
 
5244
      CUR.zp0 = CUR.twilight;
 
5245
      break;
 
5246
 
 
5247
    case 1:
 
5248
      CUR.zp0 = CUR.pts;
 
5249
      break;
 
5250
 
 
5251
    default:
 
5252
      if ( CUR.pedantic_hinting )
 
5253
        CUR.error = TT_Err_Invalid_Reference;
 
5254
      return;
 
5255
    }
 
5256
 
 
5257
    CUR.GS.gep0 = (FT_UShort)args[0];
 
5258
  }
 
5259
 
 
5260
 
 
5261
  /*************************************************************************/
 
5262
  /*                                                                       */
 
5263
  /* SZP1[]:       Set Zone Pointer 1                                      */
 
5264
  /* Opcode range: 0x14                                                    */
 
5265
  /* Stack:        uint32 -->                                              */
 
5266
  /*                                                                       */
 
5267
  static void
 
5268
  Ins_SZP1( INS_ARG )
 
5269
  {
 
5270
    switch ( (FT_Int)args[0] )
 
5271
    {
 
5272
    case 0:
 
5273
      CUR.zp1 = CUR.twilight;
 
5274
      break;
 
5275
 
 
5276
    case 1:
 
5277
      CUR.zp1 = CUR.pts;
 
5278
      break;
 
5279
 
 
5280
    default:
 
5281
      if ( CUR.pedantic_hinting )
 
5282
        CUR.error = TT_Err_Invalid_Reference;
 
5283
      return;
 
5284
    }
 
5285
 
 
5286
    CUR.GS.gep1 = (FT_UShort)args[0];
 
5287
  }
 
5288
 
 
5289
 
 
5290
  /*************************************************************************/
 
5291
  /*                                                                       */
 
5292
  /* SZP2[]:       Set Zone Pointer 2                                      */
 
5293
  /* Opcode range: 0x15                                                    */
 
5294
  /* Stack:        uint32 -->                                              */
 
5295
  /*                                                                       */
 
5296
  static void
 
5297
  Ins_SZP2( INS_ARG )
 
5298
  {
 
5299
    switch ( (FT_Int)args[0] )
 
5300
    {
 
5301
    case 0:
 
5302
      CUR.zp2 = CUR.twilight;
 
5303
      break;
 
5304
 
 
5305
    case 1:
 
5306
      CUR.zp2 = CUR.pts;
 
5307
      break;
 
5308
 
 
5309
    default:
 
5310
      if ( CUR.pedantic_hinting )
 
5311
        CUR.error = TT_Err_Invalid_Reference;
 
5312
      return;
 
5313
    }
 
5314
 
 
5315
    CUR.GS.gep2 = (FT_UShort)args[0];
 
5316
  }
 
5317
 
 
5318
 
 
5319
  /*************************************************************************/
 
5320
  /*                                                                       */
 
5321
  /* SZPS[]:       Set Zone PointerS                                       */
 
5322
  /* Opcode range: 0x16                                                    */
 
5323
  /* Stack:        uint32 -->                                              */
 
5324
  /*                                                                       */
 
5325
  static void
 
5326
  Ins_SZPS( INS_ARG )
 
5327
  {
 
5328
    switch ( (FT_Int)args[0] )
 
5329
    {
 
5330
    case 0:
 
5331
      CUR.zp0 = CUR.twilight;
 
5332
      break;
 
5333
 
 
5334
    case 1:
 
5335
      CUR.zp0 = CUR.pts;
 
5336
      break;
 
5337
 
 
5338
    default:
 
5339
      if ( CUR.pedantic_hinting )
 
5340
        CUR.error = TT_Err_Invalid_Reference;
 
5341
      return;
 
5342
    }
 
5343
 
 
5344
    CUR.zp1 = CUR.zp0;
 
5345
    CUR.zp2 = CUR.zp0;
 
5346
 
 
5347
    CUR.GS.gep0 = (FT_UShort)args[0];
 
5348
    CUR.GS.gep1 = (FT_UShort)args[0];
 
5349
    CUR.GS.gep2 = (FT_UShort)args[0];
 
5350
  }
 
5351
 
 
5352
 
 
5353
  /*************************************************************************/
 
5354
  /*                                                                       */
 
5355
  /* INSTCTRL[]:   INSTruction ConTRoL                                     */
 
5356
  /* Opcode range: 0x8e                                                    */
 
5357
  /* Stack:        int32 int32 -->                                         */
 
5358
  /*                                                                       */
 
5359
  static void
 
5360
  Ins_INSTCTRL( INS_ARG )
 
5361
  {
 
5362
    FT_Long  K, L;
 
5363
 
 
5364
 
 
5365
    K = args[1];
 
5366
    L = args[0];
 
5367
 
 
5368
    if ( K < 1 || K > 2 )
 
5369
    {
 
5370
      if ( CUR.pedantic_hinting )
 
5371
        CUR.error = TT_Err_Invalid_Reference;
 
5372
      return;
 
5373
    }
 
5374
 
 
5375
    if ( L != 0 )
 
5376
        L = K;
 
5377
 
 
5378
    CUR.GS.instruct_control = FT_BOOL(
 
5379
      ( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );
 
5380
  }
 
5381
 
 
5382
 
 
5383
  /*************************************************************************/
 
5384
  /*                                                                       */
 
5385
  /* SCANCTRL[]:   SCAN ConTRoL                                            */
 
5386
  /* Opcode range: 0x85                                                    */
 
5387
  /* Stack:        uint32? -->                                             */
 
5388
  /*                                                                       */
 
5389
  static void
 
5390
  Ins_SCANCTRL( INS_ARG )
 
5391
  {
 
5392
    FT_Int  A;
 
5393
 
 
5394
 
 
5395
    /* Get Threshold */
 
5396
    A = (FT_Int)( args[0] & 0xFF );
 
5397
 
 
5398
    if ( A == 0xFF )
 
5399
    {
 
5400
      CUR.GS.scan_control = TRUE;
 
5401
      return;
 
5402
    }
 
5403
    else if ( A == 0 )
 
5404
    {
 
5405
      CUR.GS.scan_control = FALSE;
 
5406
      return;
 
5407
    }
 
5408
 
 
5409
    if ( ( args[0] & 0x100 ) != 0 && CUR.tt_metrics.ppem <= A )
 
5410
      CUR.GS.scan_control = TRUE;
 
5411
 
 
5412
    if ( ( args[0] & 0x200 ) != 0 && CUR.tt_metrics.rotated )
 
5413
      CUR.GS.scan_control = TRUE;
 
5414
 
 
5415
    if ( ( args[0] & 0x400 ) != 0 && CUR.tt_metrics.stretched )
 
5416
      CUR.GS.scan_control = TRUE;
 
5417
 
 
5418
    if ( ( args[0] & 0x800 ) != 0 && CUR.tt_metrics.ppem > A )
 
5419
      CUR.GS.scan_control = FALSE;
 
5420
 
 
5421
    if ( ( args[0] & 0x1000 ) != 0 && CUR.tt_metrics.rotated )
 
5422
      CUR.GS.scan_control = FALSE;
 
5423
 
 
5424
    if ( ( args[0] & 0x2000 ) != 0 && CUR.tt_metrics.stretched )
 
5425
      CUR.GS.scan_control = FALSE;
 
5426
  }
 
5427
 
 
5428
 
 
5429
  /*************************************************************************/
 
5430
  /*                                                                       */
 
5431
  /* SCANTYPE[]:   SCAN TYPE                                               */
 
5432
  /* Opcode range: 0x8D                                                    */
 
5433
  /* Stack:        uint32? -->                                             */
 
5434
  /*                                                                       */
 
5435
  static void
 
5436
  Ins_SCANTYPE( INS_ARG )
 
5437
  {
 
5438
    if ( args[0] >= 0 )
 
5439
      CUR.GS.scan_type = (FT_Int)args[0];
 
5440
  }
 
5441
 
 
5442
 
 
5443
  /*************************************************************************/
 
5444
  /*                                                                       */
 
5445
  /* MANAGING OUTLINES                                                     */
 
5446
  /*                                                                       */
 
5447
  /*   Instructions appear in the specification's order.                   */
 
5448
  /*                                                                       */
 
5449
  /*************************************************************************/
 
5450
 
 
5451
 
 
5452
  /*************************************************************************/
 
5453
  /*                                                                       */
 
5454
  /* FLIPPT[]:     FLIP PoinT                                              */
 
5455
  /* Opcode range: 0x80                                                    */
 
5456
  /* Stack:        uint32... -->                                           */
 
5457
  /*                                                                       */
 
5458
  static void
 
5459
  Ins_FLIPPT( INS_ARG )
 
5460
  {
 
5461
    FT_UShort  point;
 
5462
 
 
5463
    FT_UNUSED_ARG;
 
5464
 
 
5465
 
 
5466
    if ( CUR.top < CUR.GS.loop )
 
5467
    {
 
5468
      CUR.error = TT_Err_Too_Few_Arguments;
 
5469
      return;
 
5470
    }
 
5471
 
 
5472
    while ( CUR.GS.loop > 0 )
 
5473
    {
 
5474
      CUR.args--;
 
5475
 
 
5476
      point = (FT_UShort)CUR.stack[CUR.args];
 
5477
 
 
5478
      if ( BOUNDS( point, CUR.pts.n_points ) )
 
5479
      {
 
5480
        if ( CUR.pedantic_hinting )
 
5481
        {
 
5482
          CUR.error = TT_Err_Invalid_Reference;
 
5483
          return;
 
5484
        }
 
5485
      }
 
5486
      else
 
5487
        CUR.pts.tags[point] ^= FT_CURVE_TAG_ON;
 
5488
 
 
5489
      CUR.GS.loop--;
 
5490
    }
 
5491
 
 
5492
    CUR.GS.loop = 1;
 
5493
    CUR.new_top = CUR.args;
 
5494
  }
 
5495
 
 
5496
 
 
5497
  /*************************************************************************/
 
5498
  /*                                                                       */
 
5499
  /* FLIPRGON[]:   FLIP RanGe ON                                           */
 
5500
  /* Opcode range: 0x81                                                    */
 
5501
  /* Stack:        uint32 uint32 -->                                       */
 
5502
  /*                                                                       */
 
5503
  static void
 
5504
  Ins_FLIPRGON( INS_ARG )
 
5505
  {
 
5506
    FT_UShort  I, K, L;
 
5507
 
 
5508
 
 
5509
    K = (FT_UShort)args[1];
 
5510
    L = (FT_UShort)args[0];
 
5511
 
 
5512
    if ( BOUNDS( K, CUR.pts.n_points ) ||
 
5513
         BOUNDS( L, CUR.pts.n_points ) )
 
5514
    {
 
5515
      if ( CUR.pedantic_hinting )
 
5516
        CUR.error = TT_Err_Invalid_Reference;
 
5517
      return;
 
5518
    }
 
5519
 
 
5520
    for ( I = L; I <= K; I++ )
 
5521
      CUR.pts.tags[I] |= FT_CURVE_TAG_ON;
 
5522
  }
 
5523
 
 
5524
 
 
5525
  /*************************************************************************/
 
5526
  /*                                                                       */
 
5527
  /* FLIPRGOFF:    FLIP RanGe OFF                                          */
 
5528
  /* Opcode range: 0x82                                                    */
 
5529
  /* Stack:        uint32 uint32 -->                                       */
 
5530
  /*                                                                       */
 
5531
  static void
 
5532
  Ins_FLIPRGOFF( INS_ARG )
 
5533
  {
 
5534
    FT_UShort  I, K, L;
 
5535
 
 
5536
 
 
5537
    K = (FT_UShort)args[1];
 
5538
    L = (FT_UShort)args[0];
 
5539
 
 
5540
    if ( BOUNDS( K, CUR.pts.n_points ) ||
 
5541
         BOUNDS( L, CUR.pts.n_points ) )
 
5542
    {
 
5543
      if ( CUR.pedantic_hinting )
 
5544
        CUR.error = TT_Err_Invalid_Reference;
 
5545
      return;
 
5546
    }
 
5547
 
 
5548
    for ( I = L; I <= K; I++ )
 
5549
      CUR.pts.tags[I] &= ~FT_CURVE_TAG_ON;
 
5550
  }
 
5551
 
 
5552
 
 
5553
  static FT_Bool
 
5554
  Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6*   x,
 
5555
                                       FT_F26Dot6*   y,
 
5556
                                       TT_GlyphZone  zone,
 
5557
                                       FT_UShort*    refp )
 
5558
  {
 
5559
    TT_GlyphZoneRec  zp;
 
5560
    FT_UShort        p;
 
5561
    FT_F26Dot6       d;
 
5562
 
 
5563
 
 
5564
    if ( CUR.opcode & 1 )
 
5565
    {
 
5566
      zp = CUR.zp0;
 
5567
      p  = CUR.GS.rp1;
 
5568
    }
 
5569
    else
 
5570
    {
 
5571
      zp = CUR.zp1;
 
5572
      p  = CUR.GS.rp2;
 
5573
    }
 
5574
 
 
5575
    if ( BOUNDS( p, zp.n_points ) )
 
5576
    {
 
5577
      if ( CUR.pedantic_hinting )
 
5578
        CUR.error = TT_Err_Invalid_Reference;
 
5579
      *refp = 0;
 
5580
      return FAILURE;
 
5581
    }
 
5582
 
 
5583
    *zone = zp;
 
5584
    *refp = p;
 
5585
 
 
5586
    d = CUR_Func_project( zp.cur + p, zp.org + p );
 
5587
 
 
5588
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
 
5589
    if ( CUR.face->unpatented_hinting )
 
5590
    {
 
5591
      if ( CUR.GS.both_x_axis )
 
5592
      {
 
5593
        *x = d;
 
5594
        *y = 0;
 
5595
      }
 
5596
      else
 
5597
      {
 
5598
        *x = 0;
 
5599
        *y = d;
 
5600
      }
 
5601
    }
 
5602
    else
 
5603
#endif
 
5604
    {
 
5605
      *x = TT_MULDIV( d,
 
5606
                      (FT_Long)CUR.GS.freeVector.x * 0x10000L,
 
5607
                      CUR.F_dot_P );
 
5608
      *y = TT_MULDIV( d,
 
5609
                      (FT_Long)CUR.GS.freeVector.y * 0x10000L,
 
5610
                      CUR.F_dot_P );
 
5611
    }
 
5612
 
 
5613
    return SUCCESS;
 
5614
  }
 
5615
 
 
5616
 
 
5617
  static void
 
5618
  Move_Zp2_Point( EXEC_OP_ FT_UShort   point,
 
5619
                           FT_F26Dot6  dx,
 
5620
                           FT_F26Dot6  dy,
 
5621
                           FT_Bool     touch )
 
5622
  {
 
5623
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
 
5624
    if ( CUR.face->unpatented_hinting )
 
5625
    {
 
5626
      if ( CUR.GS.both_x_axis )
 
5627
      {
 
5628
        CUR.zp2.cur[point].x += dx;
 
5629
        if ( touch )
 
5630
          CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
 
5631
      }
 
5632
      else
 
5633
      {
 
5634
        CUR.zp2.cur[point].y += dy;
 
5635
        if ( touch )
 
5636
          CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
 
5637
      }
 
5638
      return;
 
5639
    }
 
5640
#endif
 
5641
 
 
5642
    if ( CUR.GS.freeVector.x != 0 )
 
5643
    {
 
5644
      CUR.zp2.cur[point].x += dx;
 
5645
      if ( touch )
 
5646
        CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
 
5647
    }
 
5648
 
 
5649
    if ( CUR.GS.freeVector.y != 0 )
 
5650
    {
 
5651
      CUR.zp2.cur[point].y += dy;
 
5652
      if ( touch )
 
5653
        CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
 
5654
    }
 
5655
  }
 
5656
 
 
5657
 
 
5658
  /*************************************************************************/
 
5659
  /*                                                                       */
 
5660
  /* SHP[a]:       SHift Point by the last point                           */
 
5661
  /* Opcode range: 0x32-0x33                                               */
 
5662
  /* Stack:        uint32... -->                                           */
 
5663
  /*                                                                       */
 
5664
  static void
 
5665
  Ins_SHP( INS_ARG )
 
5666
  {
 
5667
    TT_GlyphZoneRec  zp;
 
5668
    FT_UShort        refp;
 
5669
 
 
5670
    FT_F26Dot6       dx,
 
5671
                     dy;
 
5672
    FT_UShort        point;
 
5673
 
 
5674
    FT_UNUSED_ARG;
 
5675
 
 
5676
 
 
5677
    if ( CUR.top < CUR.GS.loop )
 
5678
    {
 
5679
      CUR.error = TT_Err_Invalid_Reference;
 
5680
      return;
 
5681
    }
 
5682
 
 
5683
    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
 
5684
      return;
 
5685
 
 
5686
    while ( CUR.GS.loop > 0 )
 
5687
    {
 
5688
      CUR.args--;
 
5689
      point = (FT_UShort)CUR.stack[CUR.args];
 
5690
 
 
5691
      if ( BOUNDS( point, CUR.zp2.n_points ) )
 
5692
      {
 
5693
        if ( CUR.pedantic_hinting )
 
5694
        {
 
5695
          CUR.error = TT_Err_Invalid_Reference;
 
5696
          return;
 
5697
        }
 
5698
      }
 
5699
      else
 
5700
        /* XXX: UNDOCUMENTED! SHP touches the points */
 
5701
        MOVE_Zp2_Point( point, dx, dy, TRUE );
 
5702
 
 
5703
      CUR.GS.loop--;
 
5704
    }
 
5705
 
 
5706
    CUR.GS.loop = 1;
 
5707
    CUR.new_top = CUR.args;
 
5708
  }
 
5709
 
 
5710
 
 
5711
  /*************************************************************************/
 
5712
  /*                                                                       */
 
5713
  /* SHC[a]:       SHift Contour                                           */
 
5714
  /* Opcode range: 0x34-35                                                 */
 
5715
  /* Stack:        uint32 -->                                              */
 
5716
  /*                                                                       */
 
5717
  static void
 
5718
  Ins_SHC( INS_ARG )
 
5719
  {
 
5720
    TT_GlyphZoneRec zp;
 
5721
    FT_UShort       refp;
 
5722
    FT_F26Dot6      dx,
 
5723
                    dy;
 
5724
 
 
5725
    FT_Short        contour;
 
5726
    FT_UShort       first_point, last_point, i;
 
5727
 
 
5728
 
 
5729
    contour = (FT_UShort)args[0];
 
5730
 
 
5731
    if ( BOUNDS( contour, CUR.pts.n_contours ) )
 
5732
    {
 
5733
      if ( CUR.pedantic_hinting )
 
5734
        CUR.error = TT_Err_Invalid_Reference;
 
5735
      return;
 
5736
    }
 
5737
 
 
5738
    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
 
5739
      return;
 
5740
 
 
5741
    if ( contour == 0 )
 
5742
      first_point = 0;
 
5743
    else
 
5744
      first_point = (FT_UShort)( CUR.pts.contours[contour - 1] + 1 -
 
5745
                                 CUR.pts.first_point );
 
5746
 
 
5747
    last_point = (FT_UShort)( CUR.pts.contours[contour] -
 
5748
                              CUR.pts.first_point );
 
5749
 
 
5750
    /* XXX: this is probably wrong... at least it prevents memory */
 
5751
    /*      corruption when zp2 is the twilight zone              */
 
5752
    if ( BOUNDS( last_point, CUR.zp2.n_points ) )
 
5753
    {
 
5754
      if ( CUR.zp2.n_points > 0 )
 
5755
        last_point = (FT_UShort)(CUR.zp2.n_points - 1);
 
5756
      else
 
5757
        last_point = 0;
 
5758
    }
 
5759
 
 
5760
    /* XXX: UNDOCUMENTED! SHC touches the points */
 
5761
    for ( i = first_point; i <= last_point; i++ )
 
5762
    {
 
5763
      if ( zp.cur != CUR.zp2.cur || refp != i )
 
5764
        MOVE_Zp2_Point( i, dx, dy, TRUE );
 
5765
    }
 
5766
  }
 
5767
 
 
5768
 
 
5769
  /*************************************************************************/
 
5770
  /*                                                                       */
 
5771
  /* SHZ[a]:       SHift Zone                                              */
 
5772
  /* Opcode range: 0x36-37                                                 */
 
5773
  /* Stack:        uint32 -->                                              */
 
5774
  /*                                                                       */
 
5775
  static void
 
5776
  Ins_SHZ( INS_ARG )
 
5777
  {
 
5778
    TT_GlyphZoneRec  zp;
 
5779
    FT_UShort        refp;
 
5780
    FT_F26Dot6       dx,
 
5781
                     dy;
 
5782
 
 
5783
    FT_UShort        last_point, i;
 
5784
 
 
5785
 
 
5786
    if ( BOUNDS( args[0], 2 ) )
 
5787
    {
 
5788
      if ( CUR.pedantic_hinting )
 
5789
        CUR.error = TT_Err_Invalid_Reference;
 
5790
      return;
 
5791
    }
 
5792
 
 
5793
    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
 
5794
      return;
 
5795
 
 
5796
    /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points.  */
 
5797
    /*      Twilight zone has no contours, so use `n_points'.   */
 
5798
    /*      Normal zone's `n_points' includes phantoms, so must */
 
5799
    /*      use end of last contour.                            */
 
5800
    if ( CUR.GS.gep2 == 0 && CUR.zp2.n_points > 0 )
 
5801
      last_point = (FT_UShort)( CUR.zp2.n_points - 1 );
 
5802
    else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 )
 
5803
    {
 
5804
      last_point = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] );
 
5805
 
 
5806
      if ( BOUNDS( last_point, CUR.zp2.n_points ) )
 
5807
      {
 
5808
        if ( CUR.pedantic_hinting )
 
5809
          CUR.error = TT_Err_Invalid_Reference;
 
5810
        return;
 
5811
      }
 
5812
    }
 
5813
    else
 
5814
      last_point = 0;
 
5815
 
 
5816
    /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
 
5817
    for ( i = 0; i <= last_point; i++ )
 
5818
    {
 
5819
      if ( zp.cur != CUR.zp2.cur || refp != i )
 
5820
        MOVE_Zp2_Point( i, dx, dy, FALSE );
 
5821
    }
 
5822
  }
 
5823
 
 
5824
 
 
5825
  /*************************************************************************/
 
5826
  /*                                                                       */
 
5827
  /* SHPIX[]:      SHift points by a PIXel amount                          */
 
5828
  /* Opcode range: 0x38                                                    */
 
5829
  /* Stack:        f26.6 uint32... -->                                     */
 
5830
  /*                                                                       */
 
5831
  static void
 
5832
  Ins_SHPIX( INS_ARG )
 
5833
  {
 
5834
    FT_F26Dot6  dx, dy;
 
5835
    FT_UShort   point;
 
5836
 
 
5837
 
 
5838
    if ( CUR.top < CUR.GS.loop + 1 )
 
5839
    {
 
5840
      CUR.error = TT_Err_Invalid_Reference;
 
5841
      return;
 
5842
    }
 
5843
 
 
5844
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
 
5845
    if ( CUR.face->unpatented_hinting )
 
5846
    {
 
5847
      if ( CUR.GS.both_x_axis )
 
5848
      {
 
5849
        dx = TT_MulFix14( (FT_UInt32)args[0], 0x4000 );
 
5850
        dy = 0;
 
5851
      }
 
5852
      else
 
5853
      {
 
5854
        dx = 0;
 
5855
        dy = TT_MulFix14( (FT_UInt32)args[0], 0x4000 );
 
5856
      }
 
5857
    }
 
5858
    else
 
5859
#endif
 
5860
    {
 
5861
      dx = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.x );
 
5862
      dy = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.y );
 
5863
    }
 
5864
 
 
5865
    while ( CUR.GS.loop > 0 )
 
5866
    {
 
5867
      CUR.args--;
 
5868
 
 
5869
      point = (FT_UShort)CUR.stack[CUR.args];
 
5870
 
 
5871
      if ( BOUNDS( point, CUR.zp2.n_points ) )
 
5872
      {
 
5873
        if ( CUR.pedantic_hinting )
 
5874
        {
 
5875
          CUR.error = TT_Err_Invalid_Reference;
 
5876
          return;
 
5877
        }
 
5878
      }
 
5879
      else
 
5880
        MOVE_Zp2_Point( point, dx, dy, TRUE );
 
5881
 
 
5882
      CUR.GS.loop--;
 
5883
    }
 
5884
 
 
5885
    CUR.GS.loop = 1;
 
5886
    CUR.new_top = CUR.args;
 
5887
  }
 
5888
 
 
5889
 
 
5890
  /*************************************************************************/
 
5891
  /*                                                                       */
 
5892
  /* MSIRP[a]:     Move Stack Indirect Relative Position                   */
 
5893
  /* Opcode range: 0x3A-0x3B                                               */
 
5894
  /* Stack:        f26.6 uint32 -->                                        */
 
5895
  /*                                                                       */
 
5896
  static void
 
5897
  Ins_MSIRP( INS_ARG )
 
5898
  {
 
5899
    FT_UShort   point;
 
5900
    FT_F26Dot6  distance;
 
5901
 
 
5902
 
 
5903
    point = (FT_UShort)args[0];
 
5904
 
 
5905
    if ( BOUNDS( point,      CUR.zp1.n_points ) ||
 
5906
         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
 
5907
    {
 
5908
      if ( CUR.pedantic_hinting )
 
5909
        CUR.error = TT_Err_Invalid_Reference;
 
5910
      return;
 
5911
    }
 
5912
 
 
5913
    /* XXX: UNDOCUMENTED! behaviour */
 
5914
    if ( CUR.GS.gep1 == 0 )   /* if the point that is to be moved */
 
5915
                              /* is in twilight zone              */
 
5916
    {
 
5917
      CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
 
5918
      CUR_Func_move_orig( &CUR.zp1, point, args[1] );
 
5919
      CUR.zp1.cur[point] = CUR.zp1.org[point];
 
5920
    }
 
5921
 
 
5922
    distance = CUR_Func_project( CUR.zp1.cur + point,
 
5923
                                 CUR.zp0.cur + CUR.GS.rp0 );
 
5924
 
 
5925
    CUR_Func_move( &CUR.zp1, point, args[1] - distance );
 
5926
 
 
5927
    CUR.GS.rp1 = CUR.GS.rp0;
 
5928
    CUR.GS.rp2 = point;
 
5929
 
 
5930
    if ( ( CUR.opcode & 1 ) != 0 )
 
5931
      CUR.GS.rp0 = point;
 
5932
  }
 
5933
 
 
5934
 
 
5935
  /*************************************************************************/
 
5936
  /*                                                                       */
 
5937
  /* MDAP[a]:      Move Direct Absolute Point                              */
 
5938
  /* Opcode range: 0x2E-0x2F                                               */
 
5939
  /* Stack:        uint32 -->                                              */
 
5940
  /*                                                                       */
 
5941
  static void
 
5942
  Ins_MDAP( INS_ARG )
 
5943
  {
 
5944
    FT_UShort   point;
 
5945
    FT_F26Dot6  cur_dist,
 
5946
                distance;
 
5947
 
 
5948
 
 
5949
    point = (FT_UShort)args[0];
 
5950
 
 
5951
    if ( BOUNDS( point, CUR.zp0.n_points ) )
 
5952
    {
 
5953
      if ( CUR.pedantic_hinting )
 
5954
        CUR.error = TT_Err_Invalid_Reference;
 
5955
      return;
 
5956
    }
 
5957
 
 
5958
    /* XXX: Is there some undocumented feature while in the */
 
5959
    /*      twilight zone? ?                                */
 
5960
    if ( ( CUR.opcode & 1 ) != 0 )
 
5961
    {
 
5962
      cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
 
5963
      distance = CUR_Func_round( cur_dist,
 
5964
                                 CUR.tt_metrics.compensations[0] ) - cur_dist;
 
5965
    }
 
5966
    else
 
5967
      distance = 0;
 
5968
 
 
5969
    CUR_Func_move( &CUR.zp0, point, distance );
 
5970
 
 
5971
    CUR.GS.rp0 = point;
 
5972
    CUR.GS.rp1 = point;
 
5973
  }
 
5974
 
 
5975
 
 
5976
  /*************************************************************************/
 
5977
  /*                                                                       */
 
5978
  /* MIAP[a]:      Move Indirect Absolute Point                            */
 
5979
  /* Opcode range: 0x3E-0x3F                                               */
 
5980
  /* Stack:        uint32 uint32 -->                                       */
 
5981
  /*                                                                       */
 
5982
  static void
 
5983
  Ins_MIAP( INS_ARG )
 
5984
  {
 
5985
    FT_ULong    cvtEntry;
 
5986
    FT_UShort   point;
 
5987
    FT_F26Dot6  distance,
 
5988
                org_dist;
 
5989
 
 
5990
 
 
5991
    cvtEntry = (FT_ULong)args[1];
 
5992
    point    = (FT_UShort)args[0];
 
5993
 
 
5994
    if ( BOUNDS( point,     CUR.zp0.n_points ) ||
 
5995
         BOUNDSL( cvtEntry, CUR.cvtSize )      )
 
5996
    {
 
5997
      if ( CUR.pedantic_hinting )
 
5998
        CUR.error = TT_Err_Invalid_Reference;
 
5999
      return;
 
6000
    }
 
6001
 
 
6002
    /* XXX: UNDOCUMENTED!                                */
 
6003
    /*                                                   */
 
6004
    /* The behaviour of an MIAP instruction is quite     */
 
6005
    /* different when used in the twilight zone.         */
 
6006
    /*                                                   */
 
6007
    /* First, no control value cut-in test is performed  */
 
6008
    /* as it would fail anyway.  Second, the original    */
 
6009
    /* point, i.e. (org_x,org_y) of zp0.point, is set    */
 
6010
    /* to the absolute, unrounded distance found in      */
 
6011
    /* the CVT.                                          */
 
6012
    /*                                                   */
 
6013
    /* This is used in the CVT programs of the Microsoft */
 
6014
    /* fonts Arial, Times, etc., in order to re-adjust   */
 
6015
    /* some key font heights.  It allows the use of the  */
 
6016
    /* IP instruction in the twilight zone, which        */
 
6017
    /* otherwise would be `illegal' according to the     */
 
6018
    /* specification.                                    */
 
6019
    /*                                                   */
 
6020
    /* We implement it with a special sequence for the   */
 
6021
    /* twilight zone.  This is a bad hack, but it seems  */
 
6022
    /* to work.                                          */
 
6023
 
 
6024
    distance = CUR_Func_read_cvt( cvtEntry );
 
6025
 
 
6026
    if ( CUR.GS.gep0 == 0 )   /* If in twilight zone */
 
6027
    {
 
6028
      CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance, CUR.GS.freeVector.x );
 
6029
      CUR.zp0.org[point].y = TT_MulFix14( (FT_UInt32)distance, CUR.GS.freeVector.y ),
 
6030
      CUR.zp0.cur[point]   = CUR.zp0.org[point];
 
6031
    }
 
6032
 
 
6033
    org_dist = CUR_fast_project( &CUR.zp0.cur[point] );
 
6034
 
 
6035
    if ( ( CUR.opcode & 1 ) != 0 )   /* rounding and control cutin flag */
 
6036
    {
 
6037
      if ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin )
 
6038
        distance = org_dist;
 
6039
 
 
6040
      distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );
 
6041
    }
 
6042
 
 
6043
    CUR_Func_move( &CUR.zp0, point, distance - org_dist );
 
6044
 
 
6045
    CUR.GS.rp0 = point;
 
6046
    CUR.GS.rp1 = point;
 
6047
  }
 
6048
 
 
6049
 
 
6050
  /*************************************************************************/
 
6051
  /*                                                                       */
 
6052
  /* MDRP[abcde]:  Move Direct Relative Point                              */
 
6053
  /* Opcode range: 0xC0-0xDF                                               */
 
6054
  /* Stack:        uint32 -->                                              */
 
6055
  /*                                                                       */
 
6056
  static void
 
6057
  Ins_MDRP( INS_ARG )
 
6058
  {
 
6059
    FT_UShort   point;
 
6060
    FT_F26Dot6  org_dist, distance;
 
6061
 
 
6062
 
 
6063
    point = (FT_UShort)args[0];
 
6064
 
 
6065
    if ( BOUNDS( point,      CUR.zp1.n_points ) ||
 
6066
         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
 
6067
    {
 
6068
      if ( CUR.pedantic_hinting )
 
6069
        CUR.error = TT_Err_Invalid_Reference;
 
6070
      return;
 
6071
    }
 
6072
 
 
6073
    /* XXX: Is there some undocumented feature while in the */
 
6074
    /*      twilight zone?                                  */
 
6075
 
 
6076
    /* XXX: UNDOCUMENTED: twilight zone special case */
 
6077
 
 
6078
    if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )
 
6079
    {
 
6080
      FT_Vector*  vec1 = &CUR.zp1.org[point];
 
6081
      FT_Vector*  vec2 = &CUR.zp0.org[CUR.GS.rp0];
 
6082
 
 
6083
 
 
6084
      org_dist = CUR_Func_dualproj( vec1, vec2 );
 
6085
    }
 
6086
    else
 
6087
    {
 
6088
      FT_Vector*  vec1 = &CUR.zp1.orus[point];
 
6089
      FT_Vector*  vec2 = &CUR.zp0.orus[CUR.GS.rp0];
 
6090
 
 
6091
 
 
6092
      if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
 
6093
      {
 
6094
        /* this should be faster */
 
6095
        org_dist = CUR_Func_dualproj( vec1, vec2 );
 
6096
        org_dist = TT_MULFIX( org_dist, CUR.metrics.x_scale );
 
6097
      }
 
6098
      else
 
6099
      {
 
6100
        FT_Vector  vec;
 
6101
 
 
6102
 
 
6103
        vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
 
6104
        vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
 
6105
 
 
6106
        org_dist = CUR_fast_dualproj( &vec );
 
6107
      }
 
6108
    }
 
6109
 
 
6110
    /* single width cut-in test */
 
6111
 
 
6112
    if ( FT_ABS( org_dist - CUR.GS.single_width_value ) <
 
6113
         CUR.GS.single_width_cutin )
 
6114
    {
 
6115
      if ( org_dist >= 0 )
 
6116
        org_dist = CUR.GS.single_width_value;
 
6117
      else
 
6118
        org_dist = -CUR.GS.single_width_value;
 
6119
    }
 
6120
 
 
6121
    /* round flag */
 
6122
 
 
6123
    if ( ( CUR.opcode & 4 ) != 0 )
 
6124
      distance = CUR_Func_round(
 
6125
                   org_dist,
 
6126
                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
 
6127
    else
 
6128
      distance = ROUND_None(
 
6129
                   org_dist,
 
6130
                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
 
6131
 
 
6132
    /* minimum distance flag */
 
6133
 
 
6134
    if ( ( CUR.opcode & 8 ) != 0 )
 
6135
    {
 
6136
      if ( org_dist >= 0 )
 
6137
      {
 
6138
        if ( distance < CUR.GS.minimum_distance )
 
6139
          distance = CUR.GS.minimum_distance;
 
6140
      }
 
6141
      else
 
6142
      {
 
6143
        if ( distance > -CUR.GS.minimum_distance )
 
6144
          distance = -CUR.GS.minimum_distance;
 
6145
      }
 
6146
    }
 
6147
 
 
6148
    /* now move the point */
 
6149
 
 
6150
    org_dist = CUR_Func_project( CUR.zp1.cur + point,
 
6151
                                 CUR.zp0.cur + CUR.GS.rp0 );
 
6152
 
 
6153
    CUR_Func_move( &CUR.zp1, point, distance - org_dist );
 
6154
 
 
6155
    CUR.GS.rp1 = CUR.GS.rp0;
 
6156
    CUR.GS.rp2 = point;
 
6157
 
 
6158
    if ( ( CUR.opcode & 16 ) != 0 )
 
6159
      CUR.GS.rp0 = point;
 
6160
  }
 
6161
 
 
6162
 
 
6163
  /*************************************************************************/
 
6164
  /*                                                                       */
 
6165
  /* MIRP[abcde]:  Move Indirect Relative Point                            */
 
6166
  /* Opcode range: 0xE0-0xFF                                               */
 
6167
  /* Stack:        int32? uint32 -->                                       */
 
6168
  /*                                                                       */
 
6169
  static void
 
6170
  Ins_MIRP( INS_ARG )
 
6171
  {
 
6172
    FT_UShort   point;
 
6173
    FT_ULong    cvtEntry;
 
6174
 
 
6175
    FT_F26Dot6  cvt_dist,
 
6176
                distance,
 
6177
                cur_dist,
 
6178
                org_dist;
 
6179
 
 
6180
 
 
6181
    point    = (FT_UShort)args[0];
 
6182
    cvtEntry = (FT_ULong)( args[1] + 1 );
 
6183
 
 
6184
    /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
 
6185
 
 
6186
    if ( BOUNDS( point,      CUR.zp1.n_points ) ||
 
6187
         BOUNDSL( cvtEntry,  CUR.cvtSize + 1 )  ||
 
6188
         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
 
6189
    {
 
6190
      if ( CUR.pedantic_hinting )
 
6191
        CUR.error = TT_Err_Invalid_Reference;
 
6192
      return;
 
6193
    }
 
6194
 
 
6195
    if ( !cvtEntry )
 
6196
      cvt_dist = 0;
 
6197
    else
 
6198
      cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
 
6199
 
 
6200
    /* single width test */
 
6201
 
 
6202
    if ( FT_ABS( cvt_dist - CUR.GS.single_width_value ) <
 
6203
         CUR.GS.single_width_cutin )
 
6204
    {
 
6205
      if ( cvt_dist >= 0 )
 
6206
        cvt_dist =  CUR.GS.single_width_value;
 
6207
      else
 
6208
        cvt_dist = -CUR.GS.single_width_value;
 
6209
    }
 
6210
 
 
6211
    /* XXX: UNDOCUMENTED! -- twilight zone */
 
6212
 
 
6213
    if ( CUR.GS.gep1 == 0 )
 
6214
    {
 
6215
      CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
 
6216
                             TT_MulFix14( (FT_UInt32)cvt_dist,
 
6217
                                          CUR.GS.freeVector.x );
 
6218
 
 
6219
      CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +
 
6220
                             TT_MulFix14( (FT_UInt32)cvt_dist,
 
6221
                                          CUR.GS.freeVector.y );
 
6222
 
 
6223
      CUR.zp1.cur[point] = CUR.zp0.cur[point];
 
6224
    }
 
6225
 
 
6226
    org_dist = CUR_Func_dualproj( &CUR.zp1.org[point],
 
6227
                                  &CUR.zp0.org[CUR.GS.rp0] );
 
6228
    cur_dist = CUR_Func_project ( &CUR.zp1.cur[point],
 
6229
                                  &CUR.zp0.cur[CUR.GS.rp0] );
 
6230
 
 
6231
    /* auto-flip test */
 
6232
 
 
6233
    if ( CUR.GS.auto_flip )
 
6234
    {
 
6235
      if ( ( org_dist ^ cvt_dist ) < 0 )
 
6236
        cvt_dist = -cvt_dist;
 
6237
    }
 
6238
 
 
6239
    /* control value cutin and round */
 
6240
 
 
6241
    if ( ( CUR.opcode & 4 ) != 0 )
 
6242
    {
 
6243
      /* XXX: UNDOCUMENTED!  Only perform cut-in test when both points */
 
6244
      /*      refer to the same zone.                                  */
 
6245
 
 
6246
      if ( CUR.GS.gep0 == CUR.GS.gep1 )
 
6247
        if ( FT_ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )
 
6248
          cvt_dist = org_dist;
 
6249
 
 
6250
      distance = CUR_Func_round(
 
6251
                   cvt_dist,
 
6252
                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
 
6253
    }
 
6254
    else
 
6255
      distance = ROUND_None(
 
6256
                   cvt_dist,
 
6257
                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
 
6258
 
 
6259
    /* minimum distance test */
 
6260
 
 
6261
    if ( ( CUR.opcode & 8 ) != 0 )
 
6262
    {
 
6263
      if ( org_dist >= 0 )
 
6264
      {
 
6265
        if ( distance < CUR.GS.minimum_distance )
 
6266
          distance = CUR.GS.minimum_distance;
 
6267
      }
 
6268
      else
 
6269
      {
 
6270
        if ( distance > -CUR.GS.minimum_distance )
 
6271
          distance = -CUR.GS.minimum_distance;
 
6272
      }
 
6273
    }
 
6274
 
 
6275
    CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
 
6276
 
 
6277
    CUR.GS.rp1 = CUR.GS.rp0;
 
6278
 
 
6279
    if ( ( CUR.opcode & 16 ) != 0 )
 
6280
      CUR.GS.rp0 = point;
 
6281
 
 
6282
    /* XXX: UNDOCUMENTED! */
 
6283
    CUR.GS.rp2 = point;
 
6284
  }
 
6285
 
 
6286
 
 
6287
  /*************************************************************************/
 
6288
  /*                                                                       */
 
6289
  /* ALIGNRP[]:    ALIGN Relative Point                                    */
 
6290
  /* Opcode range: 0x3C                                                    */
 
6291
  /* Stack:        uint32 uint32... -->                                    */
 
6292
  /*                                                                       */
 
6293
  static void
 
6294
  Ins_ALIGNRP( INS_ARG )
 
6295
  {
 
6296
    FT_UShort   point;
 
6297
    FT_F26Dot6  distance;
 
6298
 
 
6299
    FT_UNUSED_ARG;
 
6300
 
 
6301
 
 
6302
    if ( CUR.top < CUR.GS.loop ||
 
6303
         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
 
6304
    {
 
6305
      if ( CUR.pedantic_hinting )
 
6306
        CUR.error = TT_Err_Invalid_Reference;
 
6307
      return;
 
6308
    }
 
6309
 
 
6310
    while ( CUR.GS.loop > 0 )
 
6311
    {
 
6312
      CUR.args--;
 
6313
 
 
6314
      point = (FT_UShort)CUR.stack[CUR.args];
 
6315
 
 
6316
      if ( BOUNDS( point, CUR.zp1.n_points ) )
 
6317
      {
 
6318
        if ( CUR.pedantic_hinting )
 
6319
        {
 
6320
          CUR.error = TT_Err_Invalid_Reference;
 
6321
          return;
 
6322
        }
 
6323
      }
 
6324
      else
 
6325
      {
 
6326
        distance = CUR_Func_project( CUR.zp1.cur + point,
 
6327
                                     CUR.zp0.cur + CUR.GS.rp0 );
 
6328
 
 
6329
        CUR_Func_move( &CUR.zp1, point, -distance );
 
6330
      }
 
6331
 
 
6332
      CUR.GS.loop--;
 
6333
    }
 
6334
 
 
6335
    CUR.GS.loop = 1;
 
6336
    CUR.new_top = CUR.args;
 
6337
  }
 
6338
 
 
6339
 
 
6340
  /*************************************************************************/
 
6341
  /*                                                                       */
 
6342
  /* ISECT[]:      moves point to InterSECTion                             */
 
6343
  /* Opcode range: 0x0F                                                    */
 
6344
  /* Stack:        5 * uint32 -->                                          */
 
6345
  /*                                                                       */
 
6346
  static void
 
6347
  Ins_ISECT( INS_ARG )
 
6348
  {
 
6349
    FT_UShort   point,
 
6350
                a0, a1,
 
6351
                b0, b1;
 
6352
 
 
6353
    FT_F26Dot6  discriminant;
 
6354
 
 
6355
    FT_F26Dot6  dx,  dy,
 
6356
                dax, day,
 
6357
                dbx, dby;
 
6358
 
 
6359
    FT_F26Dot6  val;
 
6360
 
 
6361
    FT_Vector   R;
 
6362
 
 
6363
 
 
6364
    point = (FT_UShort)args[0];
 
6365
 
 
6366
    a0 = (FT_UShort)args[1];
 
6367
    a1 = (FT_UShort)args[2];
 
6368
    b0 = (FT_UShort)args[3];
 
6369
    b1 = (FT_UShort)args[4];
 
6370
 
 
6371
    if ( BOUNDS( b0, CUR.zp0.n_points )  ||
 
6372
         BOUNDS( b1, CUR.zp0.n_points )  ||
 
6373
         BOUNDS( a0, CUR.zp1.n_points )  ||
 
6374
         BOUNDS( a1, CUR.zp1.n_points )  ||
 
6375
         BOUNDS( point, CUR.zp2.n_points ) )
 
6376
    {
 
6377
      if ( CUR.pedantic_hinting )
 
6378
        CUR.error = TT_Err_Invalid_Reference;
 
6379
      return;
 
6380
    }
 
6381
 
 
6382
    dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
 
6383
    dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
 
6384
 
 
6385
    dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x;
 
6386
    day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y;
 
6387
 
 
6388
    dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x;
 
6389
    dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y;
 
6390
 
 
6391
    CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
 
6392
 
 
6393
    discriminant = TT_MULDIV( dax, -dby, 0x40 ) +
 
6394
                   TT_MULDIV( day, dbx, 0x40 );
 
6395
 
 
6396
    if ( FT_ABS( discriminant ) >= 0x40 )
 
6397
    {
 
6398
      val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );
 
6399
 
 
6400
      R.x = TT_MULDIV( val, dax, discriminant );
 
6401
      R.y = TT_MULDIV( val, day, discriminant );
 
6402
 
 
6403
      CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;
 
6404
      CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
 
6405
    }
 
6406
    else
 
6407
    {
 
6408
      /* else, take the middle of the middles of A and B */
 
6409
 
 
6410
      CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x +
 
6411
                               CUR.zp1.cur[a1].x +
 
6412
                               CUR.zp0.cur[b0].x +
 
6413
                               CUR.zp0.cur[b1].x ) / 4;
 
6414
      CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y +
 
6415
                               CUR.zp1.cur[a1].y +
 
6416
                               CUR.zp0.cur[b0].y +
 
6417
                               CUR.zp0.cur[b1].y ) / 4;
 
6418
    }
 
6419
  }
 
6420
 
 
6421
 
 
6422
  /*************************************************************************/
 
6423
  /*                                                                       */
 
6424
  /* ALIGNPTS[]:   ALIGN PoinTS                                            */
 
6425
  /* Opcode range: 0x27                                                    */
 
6426
  /* Stack:        uint32 uint32 -->                                       */
 
6427
  /*                                                                       */
 
6428
  static void
 
6429
  Ins_ALIGNPTS( INS_ARG )
 
6430
  {
 
6431
    FT_UShort   p1, p2;
 
6432
    FT_F26Dot6  distance;
 
6433
 
 
6434
 
 
6435
    p1 = (FT_UShort)args[0];
 
6436
    p2 = (FT_UShort)args[1];
 
6437
 
 
6438
    if ( BOUNDS( p1, CUR.zp1.n_points ) ||
 
6439
         BOUNDS( p2, CUR.zp0.n_points ) )
 
6440
    {
 
6441
      if ( CUR.pedantic_hinting )
 
6442
        CUR.error = TT_Err_Invalid_Reference;
 
6443
      return;
 
6444
    }
 
6445
 
 
6446
    distance = CUR_Func_project( CUR.zp0.cur + p2,
 
6447
                                 CUR.zp1.cur + p1 ) / 2;
 
6448
 
 
6449
    CUR_Func_move( &CUR.zp1, p1, distance );
 
6450
    CUR_Func_move( &CUR.zp0, p2, -distance );
 
6451
  }
 
6452
 
 
6453
 
 
6454
  /*************************************************************************/
 
6455
  /*                                                                       */
 
6456
  /* IP[]:         Interpolate Point                                       */
 
6457
  /* Opcode range: 0x39                                                    */
 
6458
  /* Stack:        uint32... -->                                           */
 
6459
  /*                                                                       */
 
6460
 
 
6461
  /* SOMETIMES, DUMBER CODE IS BETTER CODE */
 
6462
 
 
6463
  static void
 
6464
  Ins_IP( INS_ARG )
 
6465
  {
 
6466
    FT_F26Dot6  old_range, cur_range;
 
6467
    FT_Vector*  orus_base;
 
6468
    FT_Vector*  cur_base;
 
6469
    FT_Int      twilight;
 
6470
 
 
6471
    FT_UNUSED_ARG;
 
6472
 
 
6473
 
 
6474
    if ( CUR.top < CUR.GS.loop )
 
6475
    {
 
6476
      CUR.error = TT_Err_Invalid_Reference;
 
6477
      return;
 
6478
    }
 
6479
 
 
6480
    /*
 
6481
     * We need to deal in a special way with the twilight zone.
 
6482
     * Otherwise, by definition, the value of CUR.twilight.orus[n] is (0,0),
 
6483
     * for every n.
 
6484
     */
 
6485
    twilight = CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 || CUR.GS.gep2 == 0;
 
6486
 
 
6487
    if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) )
 
6488
    {
 
6489
      if ( CUR.pedantic_hinting )
 
6490
        CUR.error = TT_Err_Invalid_Reference;
 
6491
      return;
 
6492
    }
 
6493
 
 
6494
    if ( twilight )
 
6495
      orus_base = &CUR.zp0.org[CUR.GS.rp1];
 
6496
    else
 
6497
      orus_base = &CUR.zp0.orus[CUR.GS.rp1];
 
6498
 
 
6499
    cur_base = &CUR.zp0.cur[CUR.GS.rp1];
 
6500
 
 
6501
    /* XXX: There are some glyphs in some braindead but popular */
 
6502
    /*      fonts out there (e.g. [aeu]grave in monotype.ttf)   */
 
6503
    /*      calling IP[] with bad values of rp[12].             */
 
6504
    /*      Do something sane when this odd thing happens.      */
 
6505
    if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ||
 
6506
         BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) )
 
6507
    {
 
6508
      old_range = 0;
 
6509
      cur_range = 0;
 
6510
    }
 
6511
    else
 
6512
    {
 
6513
      if ( twilight )
 
6514
        old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2],
 
6515
                                       orus_base );
 
6516
      else
 
6517
        old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2],
 
6518
                                       orus_base );
 
6519
 
 
6520
      cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base );
 
6521
    }
 
6522
 
 
6523
    for ( ; CUR.GS.loop > 0; --CUR.GS.loop )
 
6524
    {
 
6525
      FT_UInt     point = (FT_UInt)CUR.stack[--CUR.args];
 
6526
      FT_F26Dot6  org_dist, cur_dist, new_dist;
 
6527
 
 
6528
 
 
6529
      /* check point bounds */
 
6530
      if ( BOUNDS( point, CUR.zp2.n_points ) )
 
6531
      {
 
6532
        if ( CUR.pedantic_hinting )
 
6533
        {
 
6534
          CUR.error = TT_Err_Invalid_Reference;
 
6535
          return;
 
6536
        }
 
6537
        continue;
 
6538
      }
 
6539
 
 
6540
      if ( twilight )
 
6541
        org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base );
 
6542
      else
 
6543
        org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base );
 
6544
 
 
6545
      cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base );
 
6546
 
 
6547
      if ( org_dist )
 
6548
        new_dist = ( old_range != 0 )
 
6549
                     ? TT_MULDIV( org_dist, cur_range, old_range )
 
6550
                     : cur_dist;
 
6551
      else
 
6552
        new_dist = 0;
 
6553
 
 
6554
      CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
 
6555
    }
 
6556
    CUR.GS.loop = 1;
 
6557
    CUR.new_top = CUR.args;
 
6558
  }
 
6559
 
 
6560
 
 
6561
  /*************************************************************************/
 
6562
  /*                                                                       */
 
6563
  /* UTP[a]:       UnTouch Point                                           */
 
6564
  /* Opcode range: 0x29                                                    */
 
6565
  /* Stack:        uint32 -->                                              */
 
6566
  /*                                                                       */
 
6567
  static void
 
6568
  Ins_UTP( INS_ARG )
 
6569
  {
 
6570
    FT_UShort  point;
 
6571
    FT_Byte    mask;
 
6572
 
 
6573
 
 
6574
    point = (FT_UShort)args[0];
 
6575
 
 
6576
    if ( BOUNDS( point, CUR.zp0.n_points ) )
 
6577
    {
 
6578
      if ( CUR.pedantic_hinting )
 
6579
        CUR.error = TT_Err_Invalid_Reference;
 
6580
      return;
 
6581
    }
 
6582
 
 
6583
    mask = 0xFF;
 
6584
 
 
6585
    if ( CUR.GS.freeVector.x != 0 )
 
6586
      mask &= ~FT_CURVE_TAG_TOUCH_X;
 
6587
 
 
6588
    if ( CUR.GS.freeVector.y != 0 )
 
6589
      mask &= ~FT_CURVE_TAG_TOUCH_Y;
 
6590
 
 
6591
    CUR.zp0.tags[point] &= mask;
 
6592
  }
 
6593
 
 
6594
 
 
6595
  /* Local variables for Ins_IUP: */
 
6596
  typedef struct  IUP_WorkerRec_
 
6597
  {
 
6598
    FT_Vector*  orgs;   /* original and current coordinate */
 
6599
    FT_Vector*  curs;   /* arrays                          */
 
6600
    FT_Vector*  orus;
 
6601
    FT_UInt     max_points;
 
6602
 
 
6603
  } IUP_WorkerRec, *IUP_Worker;
 
6604
 
 
6605
 
 
6606
  static void
 
6607
  _iup_worker_shift( IUP_Worker  worker,
 
6608
                     FT_UInt     p1,
 
6609
                     FT_UInt     p2,
 
6610
                     FT_UInt     p )
 
6611
  {
 
6612
    FT_UInt     i;
 
6613
    FT_F26Dot6  dx;
 
6614
 
 
6615
 
 
6616
    dx = worker->curs[p].x - worker->orgs[p].x;
 
6617
    if ( dx != 0 )
 
6618
    {
 
6619
      for ( i = p1; i < p; i++ )
 
6620
        worker->curs[i].x += dx;
 
6621
 
 
6622
      for ( i = p + 1; i <= p2; i++ )
 
6623
        worker->curs[i].x += dx;
 
6624
    }
 
6625
  }
 
6626
 
 
6627
 
 
6628
  static void
 
6629
  _iup_worker_interpolate( IUP_Worker  worker,
 
6630
                           FT_UInt     p1,
 
6631
                           FT_UInt     p2,
 
6632
                           FT_UInt     ref1,
 
6633
                           FT_UInt     ref2 )
 
6634
  {
 
6635
    FT_UInt     i;
 
6636
    FT_F26Dot6  orus1, orus2, org1, org2, delta1, delta2;
 
6637
 
 
6638
 
 
6639
    if ( p1 > p2 )
 
6640
      return;
 
6641
 
 
6642
    if ( BOUNDS( ref1, worker->max_points ) ||
 
6643
         BOUNDS( ref2, worker->max_points ) )
 
6644
      return;
 
6645
 
 
6646
    orus1 = worker->orus[ref1].x;
 
6647
    orus2 = worker->orus[ref2].x;
 
6648
 
 
6649
    if ( orus1 > orus2 )
 
6650
    {
 
6651
      FT_F26Dot6  tmp_o;
 
6652
      FT_UInt     tmp_r;
 
6653
 
 
6654
 
 
6655
      tmp_o = orus1;
 
6656
      orus1 = orus2;
 
6657
      orus2 = tmp_o;
 
6658
 
 
6659
      tmp_r = ref1;
 
6660
      ref1  = ref2;
 
6661
      ref2  = tmp_r;
 
6662
    }
 
6663
 
 
6664
    org1   = worker->orgs[ref1].x;
 
6665
    org2   = worker->orgs[ref2].x;
 
6666
    delta1 = worker->curs[ref1].x - org1;
 
6667
    delta2 = worker->curs[ref2].x - org2;
 
6668
 
 
6669
    if ( orus1 == orus2 )
 
6670
    {
 
6671
      /* simple shift of untouched points */
 
6672
      for ( i = p1; i <= p2; i++ )
 
6673
      {
 
6674
        FT_F26Dot6  x = worker->orgs[i].x;
 
6675
 
 
6676
 
 
6677
        if ( x <= org1 )
 
6678
          x += delta1;
 
6679
        else
 
6680
          x += delta2;
 
6681
 
 
6682
        worker->curs[i].x = x;
 
6683
      }
 
6684
    }
 
6685
    else
 
6686
    {
 
6687
      FT_Fixed  scale       = 0;
 
6688
      FT_Bool   scale_valid = 0;
 
6689
 
 
6690
 
 
6691
      /* interpolation */
 
6692
      for ( i = p1; i <= p2; i++ )
 
6693
      {
 
6694
        FT_F26Dot6  x = worker->orgs[i].x;
 
6695
 
 
6696
 
 
6697
        if ( x <= org1 )
 
6698
          x += delta1;
 
6699
 
 
6700
        else if ( x >= org2 )
 
6701
          x += delta2;
 
6702
 
 
6703
        else
 
6704
        {
 
6705
          if ( !scale_valid )
 
6706
          {
 
6707
            scale_valid = 1;
 
6708
            scale       = TT_MULDIV( org2 + delta2 - ( org1 + delta1 ),
 
6709
                                     0x10000L, orus2 - orus1 );
 
6710
          }
 
6711
 
 
6712
          x = ( org1 + delta1 ) +
 
6713
              TT_MULFIX( worker->orus[i].x - orus1, scale );
 
6714
        }
 
6715
        worker->curs[i].x = x;
 
6716
      }
 
6717
    }
 
6718
  }
 
6719
 
 
6720
 
 
6721
  /*************************************************************************/
 
6722
  /*                                                                       */
 
6723
  /* IUP[a]:       Interpolate Untouched Points                            */
 
6724
  /* Opcode range: 0x30-0x31                                               */
 
6725
  /* Stack:        -->                                                     */
 
6726
  /*                                                                       */
 
6727
  static void
 
6728
  Ins_IUP( INS_ARG )
 
6729
  {
 
6730
    IUP_WorkerRec  V;
 
6731
    FT_Byte        mask;
 
6732
 
 
6733
    FT_UInt   first_point;   /* first point of contour        */
 
6734
    FT_UInt   end_point;     /* end point (last+1) of contour */
 
6735
 
 
6736
    FT_UInt   first_touched; /* first touched point in contour   */
 
6737
    FT_UInt   cur_touched;   /* current touched point in contour */
 
6738
 
 
6739
    FT_UInt   point;         /* current point   */
 
6740
    FT_Short  contour;       /* current contour */
 
6741
 
 
6742
    FT_UNUSED_ARG;
 
6743
 
 
6744
 
 
6745
    /* ignore empty outlines */
 
6746
    if ( CUR.pts.n_contours == 0 )
 
6747
      return;
 
6748
 
 
6749
    if ( CUR.opcode & 1 )
 
6750
    {
 
6751
      mask   = FT_CURVE_TAG_TOUCH_X;
 
6752
      V.orgs = CUR.pts.org;
 
6753
      V.curs = CUR.pts.cur;
 
6754
      V.orus = CUR.pts.orus;
 
6755
    }
 
6756
    else
 
6757
    {
 
6758
      mask   = FT_CURVE_TAG_TOUCH_Y;
 
6759
      V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
 
6760
      V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
 
6761
      V.orus = (FT_Vector*)( (FT_Pos*)CUR.pts.orus + 1 );
 
6762
    }
 
6763
    V.max_points = CUR.pts.n_points;
 
6764
 
 
6765
    contour = 0;
 
6766
    point   = 0;
 
6767
 
 
6768
    do
 
6769
    {
 
6770
      end_point   = CUR.pts.contours[contour] - CUR.pts.first_point;
 
6771
      first_point = point;
 
6772
 
 
6773
      if ( BOUNDS ( end_point, CUR.pts.n_points ) )
 
6774
        end_point = CUR.pts.n_points - 1;
 
6775
 
 
6776
      while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 )
 
6777
        point++;
 
6778
 
 
6779
      if ( point <= end_point )
 
6780
      {
 
6781
        first_touched = point;
 
6782
        cur_touched   = point;
 
6783
 
 
6784
        point++;
 
6785
 
 
6786
        while ( point <= end_point )
 
6787
        {
 
6788
          if ( ( CUR.pts.tags[point] & mask ) != 0 )
 
6789
          {
 
6790
            _iup_worker_interpolate( &V,
 
6791
                                     cur_touched + 1,
 
6792
                                     point - 1,
 
6793
                                     cur_touched,
 
6794
                                     point );
 
6795
            cur_touched = point;
 
6796
          }
 
6797
 
 
6798
          point++;
 
6799
        }
 
6800
 
 
6801
        if ( cur_touched == first_touched )
 
6802
          _iup_worker_shift( &V, first_point, end_point, cur_touched );
 
6803
        else
 
6804
        {
 
6805
          _iup_worker_interpolate( &V,
 
6806
                                   (FT_UShort)( cur_touched + 1 ),
 
6807
                                   end_point,
 
6808
                                   cur_touched,
 
6809
                                   first_touched );
 
6810
 
 
6811
          if ( first_touched > 0 )
 
6812
            _iup_worker_interpolate( &V,
 
6813
                                     first_point,
 
6814
                                     first_touched - 1,
 
6815
                                     cur_touched,
 
6816
                                     first_touched );
 
6817
        }
 
6818
      }
 
6819
      contour++;
 
6820
    } while ( contour < CUR.pts.n_contours );
 
6821
  }
 
6822
 
 
6823
 
 
6824
  /*************************************************************************/
 
6825
  /*                                                                       */
 
6826
  /* DELTAPn[]:    DELTA exceptions P1, P2, P3                             */
 
6827
  /* Opcode range: 0x5D,0x71,0x72                                          */
 
6828
  /* Stack:        uint32 (2 * uint32)... -->                              */
 
6829
  /*                                                                       */
 
6830
  static void
 
6831
  Ins_DELTAP( INS_ARG )
 
6832
  {
 
6833
    FT_ULong   k, nump;
 
6834
    FT_UShort  A;
 
6835
    FT_ULong   C;
 
6836
    FT_Long    B;
 
6837
 
 
6838
 
 
6839
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
 
6840
    /* Delta hinting is covered by US Patent 5159668. */
 
6841
    if ( CUR.face->unpatented_hinting )
 
6842
    {
 
6843
      FT_Long  n = args[0] * 2;
 
6844
 
 
6845
 
 
6846
      if ( CUR.args < n )
 
6847
      {
 
6848
        CUR.error = TT_Err_Too_Few_Arguments;
 
6849
        return;
 
6850
      }
 
6851
 
 
6852
      CUR.args -= n;
 
6853
      CUR.new_top = CUR.args;
 
6854
      return;
 
6855
    }
 
6856
#endif
 
6857
 
 
6858
    nump = (FT_ULong)args[0];   /* some points theoretically may occur more
 
6859
                                   than once, thus UShort isn't enough */
 
6860
 
 
6861
    for ( k = 1; k <= nump; k++ )
 
6862
    {
 
6863
      if ( CUR.args < 2 )
 
6864
      {
 
6865
        CUR.error = TT_Err_Too_Few_Arguments;
 
6866
        return;
 
6867
      }
 
6868
 
 
6869
      CUR.args -= 2;
 
6870
 
 
6871
      A = (FT_UShort)CUR.stack[CUR.args + 1];
 
6872
      B = CUR.stack[CUR.args];
 
6873
 
 
6874
      /* XXX: Because some popular fonts contain some invalid DeltaP */
 
6875
      /*      instructions, we simply ignore them when the stacked   */
 
6876
      /*      point reference is off limit, rather than returning an */
 
6877
      /*      error.  As a delta instruction doesn't change a glyph  */
 
6878
      /*      in great ways, this shouldn't be a problem.            */
 
6879
 
 
6880
      if ( !BOUNDS( A, CUR.zp0.n_points ) )
 
6881
      {
 
6882
        C = ( (FT_ULong)B & 0xF0 ) >> 4;
 
6883
 
 
6884
        switch ( CUR.opcode )
 
6885
        {
 
6886
        case 0x5D:
 
6887
          break;
 
6888
 
 
6889
        case 0x71:
 
6890
          C += 16;
 
6891
          break;
 
6892
 
 
6893
        case 0x72:
 
6894
          C += 32;
 
6895
          break;
 
6896
        }
 
6897
 
 
6898
        C += CUR.GS.delta_base;
 
6899
 
 
6900
        if ( CURRENT_Ppem() == (FT_Long)C )
 
6901
        {
 
6902
          B = ( (FT_ULong)B & 0xF ) - 8;
 
6903
          if ( B >= 0 )
 
6904
            B++;
 
6905
          B = B * 64 / ( 1L << CUR.GS.delta_shift );
 
6906
 
 
6907
          CUR_Func_move( &CUR.zp0, A, B );
 
6908
        }
 
6909
      }
 
6910
      else
 
6911
        if ( CUR.pedantic_hinting )
 
6912
          CUR.error = TT_Err_Invalid_Reference;
 
6913
    }
 
6914
 
 
6915
    CUR.new_top = CUR.args;
 
6916
  }
 
6917
 
 
6918
 
 
6919
  /*************************************************************************/
 
6920
  /*                                                                       */
 
6921
  /* DELTACn[]:    DELTA exceptions C1, C2, C3                             */
 
6922
  /* Opcode range: 0x73,0x74,0x75                                          */
 
6923
  /* Stack:        uint32 (2 * uint32)... -->                              */
 
6924
  /*                                                                       */
 
6925
  static void
 
6926
  Ins_DELTAC( INS_ARG )
 
6927
  {
 
6928
    FT_ULong  nump, k;
 
6929
    FT_ULong  A, C;
 
6930
    FT_Long   B;
 
6931
 
 
6932
 
 
6933
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
 
6934
    /* Delta hinting is covered by US Patent 5159668. */
 
6935
    if ( CUR.face->unpatented_hinting )
 
6936
    {
 
6937
      FT_Long  n = args[0] * 2;
 
6938
 
 
6939
 
 
6940
      if ( CUR.args < n )
 
6941
      {
 
6942
        CUR.error = TT_Err_Too_Few_Arguments;
 
6943
        return;
 
6944
      }
 
6945
 
 
6946
      CUR.args -= n;
 
6947
      CUR.new_top = CUR.args;
 
6948
      return;
 
6949
    }
 
6950
#endif
 
6951
 
 
6952
    nump = (FT_ULong)args[0];
 
6953
 
 
6954
    for ( k = 1; k <= nump; k++ )
 
6955
    {
 
6956
      if ( CUR.args < 2 )
 
6957
      {
 
6958
        CUR.error = TT_Err_Too_Few_Arguments;
 
6959
        return;
 
6960
      }
 
6961
 
 
6962
      CUR.args -= 2;
 
6963
 
 
6964
      A = (FT_ULong)CUR.stack[CUR.args + 1];
 
6965
      B = CUR.stack[CUR.args];
 
6966
 
 
6967
      if ( BOUNDSL( A, CUR.cvtSize ) )
 
6968
      {
 
6969
        if ( CUR.pedantic_hinting )
 
6970
        {
 
6971
          CUR.error = TT_Err_Invalid_Reference;
 
6972
          return;
 
6973
        }
 
6974
      }
 
6975
      else
 
6976
      {
 
6977
        C = ( (FT_ULong)B & 0xF0 ) >> 4;
 
6978
 
 
6979
        switch ( CUR.opcode )
 
6980
        {
 
6981
        case 0x73:
 
6982
          break;
 
6983
 
 
6984
        case 0x74:
 
6985
          C += 16;
 
6986
          break;
 
6987
 
 
6988
        case 0x75:
 
6989
          C += 32;
 
6990
          break;
 
6991
        }
 
6992
 
 
6993
        C += CUR.GS.delta_base;
 
6994
 
 
6995
        if ( CURRENT_Ppem() == (FT_Long)C )
 
6996
        {
 
6997
          B = ( (FT_ULong)B & 0xF ) - 8;
 
6998
          if ( B >= 0 )
 
6999
            B++;
 
7000
          B = B * 64 / ( 1L << CUR.GS.delta_shift );
 
7001
 
 
7002
          CUR_Func_move_cvt( A, B );
 
7003
        }
 
7004
      }
 
7005
    }
 
7006
 
 
7007
    CUR.new_top = CUR.args;
 
7008
  }
 
7009
 
 
7010
 
 
7011
  /*************************************************************************/
 
7012
  /*                                                                       */
 
7013
  /* MISC. INSTRUCTIONS                                                    */
 
7014
  /*                                                                       */
 
7015
  /*************************************************************************/
 
7016
 
 
7017
 
 
7018
  /*************************************************************************/
 
7019
  /*                                                                       */
 
7020
  /* GETINFO[]:    GET INFOrmation                                         */
 
7021
  /* Opcode range: 0x88                                                    */
 
7022
  /* Stack:        uint32 --> uint32                                       */
 
7023
  /*                                                                       */
 
7024
  static void
 
7025
  Ins_GETINFO( INS_ARG )
 
7026
  {
 
7027
    FT_Long  K;
 
7028
 
 
7029
 
 
7030
    K = 0;
 
7031
 
 
7032
    /* We return MS rasterizer version 1.7 for the font scaler. */
 
7033
    if ( ( args[0] & 1 ) != 0 )
 
7034
      K = 35;
 
7035
 
 
7036
    /* Has the glyph been rotated? */
 
7037
    if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated )
 
7038
      K |= 0x80;
 
7039
 
 
7040
    /* Has the glyph been stretched? */
 
7041
    if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched )
 
7042
      K |= 1 << 8;
 
7043
 
 
7044
    /* Are we hinting for grayscale? */
 
7045
    if ( ( args[0] & 32 ) != 0 && CUR.grayscale )
 
7046
      K |= 1 << 12;
 
7047
 
 
7048
    args[0] = K;
 
7049
  }
 
7050
 
 
7051
 
 
7052
  static void
 
7053
  Ins_UNKNOWN( INS_ARG )
 
7054
  {
 
7055
    TT_DefRecord*  def   = CUR.IDefs;
 
7056
    TT_DefRecord*  limit = def + CUR.numIDefs;
 
7057
 
 
7058
    FT_UNUSED_ARG;
 
7059
 
 
7060
 
 
7061
    for ( ; def < limit; def++ )
 
7062
    {
 
7063
      if ( (FT_Byte)def->opc == CUR.opcode && def->active )
 
7064
      {
 
7065
        TT_CallRec*  call;
 
7066
 
 
7067
 
 
7068
        if ( CUR.callTop >= CUR.callSize )
 
7069
        {
 
7070
          CUR.error = TT_Err_Stack_Overflow;
 
7071
          return;
 
7072
        }
 
7073
 
 
7074
        call = CUR.callStack + CUR.callTop++;
 
7075
 
 
7076
        call->Caller_Range = CUR.curRange;
 
7077
        call->Caller_IP    = CUR.IP + 1;
 
7078
        call->Cur_Count    = 1;
 
7079
        call->Cur_Restart  = def->start;
 
7080
 
 
7081
        INS_Goto_CodeRange( def->range, def->start );
 
7082
 
 
7083
        CUR.step_ins = FALSE;
 
7084
        return;
 
7085
      }
 
7086
    }
 
7087
 
 
7088
    CUR.error = TT_Err_Invalid_Opcode;
 
7089
  }
 
7090
 
 
7091
 
 
7092
#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
 
7093
 
 
7094
 
 
7095
  static
 
7096
  TInstruction_Function  Instruct_Dispatch[256] =
 
7097
  {
 
7098
    /* Opcodes are gathered in groups of 16. */
 
7099
    /* Please keep the spaces as they are.   */
 
7100
 
 
7101
    /*  SVTCA  y  */  Ins_SVTCA,
 
7102
    /*  SVTCA  x  */  Ins_SVTCA,
 
7103
    /*  SPvTCA y  */  Ins_SPVTCA,
 
7104
    /*  SPvTCA x  */  Ins_SPVTCA,
 
7105
    /*  SFvTCA y  */  Ins_SFVTCA,
 
7106
    /*  SFvTCA x  */  Ins_SFVTCA,
 
7107
    /*  SPvTL //  */  Ins_SPVTL,
 
7108
    /*  SPvTL +   */  Ins_SPVTL,
 
7109
    /*  SFvTL //  */  Ins_SFVTL,
 
7110
    /*  SFvTL +   */  Ins_SFVTL,
 
7111
    /*  SPvFS     */  Ins_SPVFS,
 
7112
    /*  SFvFS     */  Ins_SFVFS,
 
7113
    /*  GPV       */  Ins_GPV,
 
7114
    /*  GFV       */  Ins_GFV,
 
7115
    /*  SFvTPv    */  Ins_SFVTPV,
 
7116
    /*  ISECT     */  Ins_ISECT,
 
7117
 
 
7118
    /*  SRP0      */  Ins_SRP0,
 
7119
    /*  SRP1      */  Ins_SRP1,
 
7120
    /*  SRP2      */  Ins_SRP2,
 
7121
    /*  SZP0      */  Ins_SZP0,
 
7122
    /*  SZP1      */  Ins_SZP1,
 
7123
    /*  SZP2      */  Ins_SZP2,
 
7124
    /*  SZPS      */  Ins_SZPS,
 
7125
    /*  SLOOP     */  Ins_SLOOP,
 
7126
    /*  RTG       */  Ins_RTG,
 
7127
    /*  RTHG      */  Ins_RTHG,
 
7128
    /*  SMD       */  Ins_SMD,
 
7129
    /*  ELSE      */  Ins_ELSE,
 
7130
    /*  JMPR      */  Ins_JMPR,
 
7131
    /*  SCvTCi    */  Ins_SCVTCI,
 
7132
    /*  SSwCi     */  Ins_SSWCI,
 
7133
    /*  SSW       */  Ins_SSW,
 
7134
 
 
7135
    /*  DUP       */  Ins_DUP,
 
7136
    /*  POP       */  Ins_POP,
 
7137
    /*  CLEAR     */  Ins_CLEAR,
 
7138
    /*  SWAP      */  Ins_SWAP,
 
7139
    /*  DEPTH     */  Ins_DEPTH,
 
7140
    /*  CINDEX    */  Ins_CINDEX,
 
7141
    /*  MINDEX    */  Ins_MINDEX,
 
7142
    /*  AlignPTS  */  Ins_ALIGNPTS,
 
7143
    /*  INS_0x28  */  Ins_UNKNOWN,
 
7144
    /*  UTP       */  Ins_UTP,
 
7145
    /*  LOOPCALL  */  Ins_LOOPCALL,
 
7146
    /*  CALL      */  Ins_CALL,
 
7147
    /*  FDEF      */  Ins_FDEF,
 
7148
    /*  ENDF      */  Ins_ENDF,
 
7149
    /*  MDAP[0]   */  Ins_MDAP,
 
7150
    /*  MDAP[1]   */  Ins_MDAP,
 
7151
 
 
7152
    /*  IUP[0]    */  Ins_IUP,
 
7153
    /*  IUP[1]    */  Ins_IUP,
 
7154
    /*  SHP[0]    */  Ins_SHP,
 
7155
    /*  SHP[1]    */  Ins_SHP,
 
7156
    /*  SHC[0]    */  Ins_SHC,
 
7157
    /*  SHC[1]    */  Ins_SHC,
 
7158
    /*  SHZ[0]    */  Ins_SHZ,
 
7159
    /*  SHZ[1]    */  Ins_SHZ,
 
7160
    /*  SHPIX     */  Ins_SHPIX,
 
7161
    /*  IP        */  Ins_IP,
 
7162
    /*  MSIRP[0]  */  Ins_MSIRP,
 
7163
    /*  MSIRP[1]  */  Ins_MSIRP,
 
7164
    /*  AlignRP   */  Ins_ALIGNRP,
 
7165
    /*  RTDG      */  Ins_RTDG,
 
7166
    /*  MIAP[0]   */  Ins_MIAP,
 
7167
    /*  MIAP[1]   */  Ins_MIAP,
 
7168
 
 
7169
    /*  NPushB    */  Ins_NPUSHB,
 
7170
    /*  NPushW    */  Ins_NPUSHW,
 
7171
    /*  WS        */  Ins_WS,
 
7172
    /*  RS        */  Ins_RS,
 
7173
    /*  WCvtP     */  Ins_WCVTP,
 
7174
    /*  RCvt      */  Ins_RCVT,
 
7175
    /*  GC[0]     */  Ins_GC,
 
7176
    /*  GC[1]     */  Ins_GC,
 
7177
    /*  SCFS      */  Ins_SCFS,
 
7178
    /*  MD[0]     */  Ins_MD,
 
7179
    /*  MD[1]     */  Ins_MD,
 
7180
    /*  MPPEM     */  Ins_MPPEM,
 
7181
    /*  MPS       */  Ins_MPS,
 
7182
    /*  FlipON    */  Ins_FLIPON,
 
7183
    /*  FlipOFF   */  Ins_FLIPOFF,
 
7184
    /*  DEBUG     */  Ins_DEBUG,
 
7185
 
 
7186
    /*  LT        */  Ins_LT,
 
7187
    /*  LTEQ      */  Ins_LTEQ,
 
7188
    /*  GT        */  Ins_GT,
 
7189
    /*  GTEQ      */  Ins_GTEQ,
 
7190
    /*  EQ        */  Ins_EQ,
 
7191
    /*  NEQ       */  Ins_NEQ,
 
7192
    /*  ODD       */  Ins_ODD,
 
7193
    /*  EVEN      */  Ins_EVEN,
 
7194
    /*  IF        */  Ins_IF,
 
7195
    /*  EIF       */  Ins_EIF,
 
7196
    /*  AND       */  Ins_AND,
 
7197
    /*  OR        */  Ins_OR,
 
7198
    /*  NOT       */  Ins_NOT,
 
7199
    /*  DeltaP1   */  Ins_DELTAP,
 
7200
    /*  SDB       */  Ins_SDB,
 
7201
    /*  SDS       */  Ins_SDS,
 
7202
 
 
7203
    /*  ADD       */  Ins_ADD,
 
7204
    /*  SUB       */  Ins_SUB,
 
7205
    /*  DIV       */  Ins_DIV,
 
7206
    /*  MUL       */  Ins_MUL,
 
7207
    /*  ABS       */  Ins_ABS,
 
7208
    /*  NEG       */  Ins_NEG,
 
7209
    /*  FLOOR     */  Ins_FLOOR,
 
7210
    /*  CEILING   */  Ins_CEILING,
 
7211
    /*  ROUND[0]  */  Ins_ROUND,
 
7212
    /*  ROUND[1]  */  Ins_ROUND,
 
7213
    /*  ROUND[2]  */  Ins_ROUND,
 
7214
    /*  ROUND[3]  */  Ins_ROUND,
 
7215
    /*  NROUND[0] */  Ins_NROUND,
 
7216
    /*  NROUND[1] */  Ins_NROUND,
 
7217
    /*  NROUND[2] */  Ins_NROUND,
 
7218
    /*  NROUND[3] */  Ins_NROUND,
 
7219
 
 
7220
    /*  WCvtF     */  Ins_WCVTF,
 
7221
    /*  DeltaP2   */  Ins_DELTAP,
 
7222
    /*  DeltaP3   */  Ins_DELTAP,
 
7223
    /*  DeltaCn[0] */ Ins_DELTAC,
 
7224
    /*  DeltaCn[1] */ Ins_DELTAC,
 
7225
    /*  DeltaCn[2] */ Ins_DELTAC,
 
7226
    /*  SROUND    */  Ins_SROUND,
 
7227
    /*  S45Round  */  Ins_S45ROUND,
 
7228
    /*  JROT      */  Ins_JROT,
 
7229
    /*  JROF      */  Ins_JROF,
 
7230
    /*  ROFF      */  Ins_ROFF,
 
7231
    /*  INS_0x7B  */  Ins_UNKNOWN,
 
7232
    /*  RUTG      */  Ins_RUTG,
 
7233
    /*  RDTG      */  Ins_RDTG,
 
7234
    /*  SANGW     */  Ins_SANGW,
 
7235
    /*  AA        */  Ins_AA,
 
7236
 
 
7237
    /*  FlipPT    */  Ins_FLIPPT,
 
7238
    /*  FlipRgON  */  Ins_FLIPRGON,
 
7239
    /*  FlipRgOFF */  Ins_FLIPRGOFF,
 
7240
    /*  INS_0x83  */  Ins_UNKNOWN,
 
7241
    /*  INS_0x84  */  Ins_UNKNOWN,
 
7242
    /*  ScanCTRL  */  Ins_SCANCTRL,
 
7243
    /*  SDPVTL[0] */  Ins_SDPVTL,
 
7244
    /*  SDPVTL[1] */  Ins_SDPVTL,
 
7245
    /*  GetINFO   */  Ins_GETINFO,
 
7246
    /*  IDEF      */  Ins_IDEF,
 
7247
    /*  ROLL      */  Ins_ROLL,
 
7248
    /*  MAX       */  Ins_MAX,
 
7249
    /*  MIN       */  Ins_MIN,
 
7250
    /*  ScanTYPE  */  Ins_SCANTYPE,
 
7251
    /*  InstCTRL  */  Ins_INSTCTRL,
 
7252
    /*  INS_0x8F  */  Ins_UNKNOWN,
 
7253
 
 
7254
    /*  INS_0x90  */   Ins_UNKNOWN,
 
7255
    /*  INS_0x91  */   Ins_UNKNOWN,
 
7256
    /*  INS_0x92  */   Ins_UNKNOWN,
 
7257
    /*  INS_0x93  */   Ins_UNKNOWN,
 
7258
    /*  INS_0x94  */   Ins_UNKNOWN,
 
7259
    /*  INS_0x95  */   Ins_UNKNOWN,
 
7260
    /*  INS_0x96  */   Ins_UNKNOWN,
 
7261
    /*  INS_0x97  */   Ins_UNKNOWN,
 
7262
    /*  INS_0x98  */   Ins_UNKNOWN,
 
7263
    /*  INS_0x99  */   Ins_UNKNOWN,
 
7264
    /*  INS_0x9A  */   Ins_UNKNOWN,
 
7265
    /*  INS_0x9B  */   Ins_UNKNOWN,
 
7266
    /*  INS_0x9C  */   Ins_UNKNOWN,
 
7267
    /*  INS_0x9D  */   Ins_UNKNOWN,
 
7268
    /*  INS_0x9E  */   Ins_UNKNOWN,
 
7269
    /*  INS_0x9F  */   Ins_UNKNOWN,
 
7270
 
 
7271
    /*  INS_0xA0  */   Ins_UNKNOWN,
 
7272
    /*  INS_0xA1  */   Ins_UNKNOWN,
 
7273
    /*  INS_0xA2  */   Ins_UNKNOWN,
 
7274
    /*  INS_0xA3  */   Ins_UNKNOWN,
 
7275
    /*  INS_0xA4  */   Ins_UNKNOWN,
 
7276
    /*  INS_0xA5  */   Ins_UNKNOWN,
 
7277
    /*  INS_0xA6  */   Ins_UNKNOWN,
 
7278
    /*  INS_0xA7  */   Ins_UNKNOWN,
 
7279
    /*  INS_0xA8  */   Ins_UNKNOWN,
 
7280
    /*  INS_0xA9  */   Ins_UNKNOWN,
 
7281
    /*  INS_0xAA  */   Ins_UNKNOWN,
 
7282
    /*  INS_0xAB  */   Ins_UNKNOWN,
 
7283
    /*  INS_0xAC  */   Ins_UNKNOWN,
 
7284
    /*  INS_0xAD  */   Ins_UNKNOWN,
 
7285
    /*  INS_0xAE  */   Ins_UNKNOWN,
 
7286
    /*  INS_0xAF  */   Ins_UNKNOWN,
 
7287
 
 
7288
    /*  PushB[0]  */  Ins_PUSHB,
 
7289
    /*  PushB[1]  */  Ins_PUSHB,
 
7290
    /*  PushB[2]  */  Ins_PUSHB,
 
7291
    /*  PushB[3]  */  Ins_PUSHB,
 
7292
    /*  PushB[4]  */  Ins_PUSHB,
 
7293
    /*  PushB[5]  */  Ins_PUSHB,
 
7294
    /*  PushB[6]  */  Ins_PUSHB,
 
7295
    /*  PushB[7]  */  Ins_PUSHB,
 
7296
    /*  PushW[0]  */  Ins_PUSHW,
 
7297
    /*  PushW[1]  */  Ins_PUSHW,
 
7298
    /*  PushW[2]  */  Ins_PUSHW,
 
7299
    /*  PushW[3]  */  Ins_PUSHW,
 
7300
    /*  PushW[4]  */  Ins_PUSHW,
 
7301
    /*  PushW[5]  */  Ins_PUSHW,
 
7302
    /*  PushW[6]  */  Ins_PUSHW,
 
7303
    /*  PushW[7]  */  Ins_PUSHW,
 
7304
 
 
7305
    /*  MDRP[00]  */  Ins_MDRP,
 
7306
    /*  MDRP[01]  */  Ins_MDRP,
 
7307
    /*  MDRP[02]  */  Ins_MDRP,
 
7308
    /*  MDRP[03]  */  Ins_MDRP,
 
7309
    /*  MDRP[04]  */  Ins_MDRP,
 
7310
    /*  MDRP[05]  */  Ins_MDRP,
 
7311
    /*  MDRP[06]  */  Ins_MDRP,
 
7312
    /*  MDRP[07]  */  Ins_MDRP,
 
7313
    /*  MDRP[08]  */  Ins_MDRP,
 
7314
    /*  MDRP[09]  */  Ins_MDRP,
 
7315
    /*  MDRP[10]  */  Ins_MDRP,
 
7316
    /*  MDRP[11]  */  Ins_MDRP,
 
7317
    /*  MDRP[12]  */  Ins_MDRP,
 
7318
    /*  MDRP[13]  */  Ins_MDRP,
 
7319
    /*  MDRP[14]  */  Ins_MDRP,
 
7320
    /*  MDRP[15]  */  Ins_MDRP,
 
7321
 
 
7322
    /*  MDRP[16]  */  Ins_MDRP,
 
7323
    /*  MDRP[17]  */  Ins_MDRP,
 
7324
    /*  MDRP[18]  */  Ins_MDRP,
 
7325
    /*  MDRP[19]  */  Ins_MDRP,
 
7326
    /*  MDRP[20]  */  Ins_MDRP,
 
7327
    /*  MDRP[21]  */  Ins_MDRP,
 
7328
    /*  MDRP[22]  */  Ins_MDRP,
 
7329
    /*  MDRP[23]  */  Ins_MDRP,
 
7330
    /*  MDRP[24]  */  Ins_MDRP,
 
7331
    /*  MDRP[25]  */  Ins_MDRP,
 
7332
    /*  MDRP[26]  */  Ins_MDRP,
 
7333
    /*  MDRP[27]  */  Ins_MDRP,
 
7334
    /*  MDRP[28]  */  Ins_MDRP,
 
7335
    /*  MDRP[29]  */  Ins_MDRP,
 
7336
    /*  MDRP[30]  */  Ins_MDRP,
 
7337
    /*  MDRP[31]  */  Ins_MDRP,
 
7338
 
 
7339
    /*  MIRP[00]  */  Ins_MIRP,
 
7340
    /*  MIRP[01]  */  Ins_MIRP,
 
7341
    /*  MIRP[02]  */  Ins_MIRP,
 
7342
    /*  MIRP[03]  */  Ins_MIRP,
 
7343
    /*  MIRP[04]  */  Ins_MIRP,
 
7344
    /*  MIRP[05]  */  Ins_MIRP,
 
7345
    /*  MIRP[06]  */  Ins_MIRP,
 
7346
    /*  MIRP[07]  */  Ins_MIRP,
 
7347
    /*  MIRP[08]  */  Ins_MIRP,
 
7348
    /*  MIRP[09]  */  Ins_MIRP,
 
7349
    /*  MIRP[10]  */  Ins_MIRP,
 
7350
    /*  MIRP[11]  */  Ins_MIRP,
 
7351
    /*  MIRP[12]  */  Ins_MIRP,
 
7352
    /*  MIRP[13]  */  Ins_MIRP,
 
7353
    /*  MIRP[14]  */  Ins_MIRP,
 
7354
    /*  MIRP[15]  */  Ins_MIRP,
 
7355
 
 
7356
    /*  MIRP[16]  */  Ins_MIRP,
 
7357
    /*  MIRP[17]  */  Ins_MIRP,
 
7358
    /*  MIRP[18]  */  Ins_MIRP,
 
7359
    /*  MIRP[19]  */  Ins_MIRP,
 
7360
    /*  MIRP[20]  */  Ins_MIRP,
 
7361
    /*  MIRP[21]  */  Ins_MIRP,
 
7362
    /*  MIRP[22]  */  Ins_MIRP,
 
7363
    /*  MIRP[23]  */  Ins_MIRP,
 
7364
    /*  MIRP[24]  */  Ins_MIRP,
 
7365
    /*  MIRP[25]  */  Ins_MIRP,
 
7366
    /*  MIRP[26]  */  Ins_MIRP,
 
7367
    /*  MIRP[27]  */  Ins_MIRP,
 
7368
    /*  MIRP[28]  */  Ins_MIRP,
 
7369
    /*  MIRP[29]  */  Ins_MIRP,
 
7370
    /*  MIRP[30]  */  Ins_MIRP,
 
7371
    /*  MIRP[31]  */  Ins_MIRP
 
7372
  };
 
7373
 
 
7374
 
 
7375
#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
 
7376
 
 
7377
 
 
7378
  /*************************************************************************/
 
7379
  /*                                                                       */
 
7380
  /* RUN                                                                   */
 
7381
  /*                                                                       */
 
7382
  /*  This function executes a run of opcodes.  It will exit in the        */
 
7383
  /*  following cases:                                                     */
 
7384
  /*                                                                       */
 
7385
  /*  - Errors (in which case it returns FALSE).                           */
 
7386
  /*                                                                       */
 
7387
  /*  - Reaching the end of the main code range (returns TRUE).            */
 
7388
  /*    Reaching the end of a code range within a function call is an      */
 
7389
  /*    error.                                                             */
 
7390
  /*                                                                       */
 
7391
  /*  - After executing one single opcode, if the flag `Instruction_Trap'  */
 
7392
  /*    is set to TRUE (returns TRUE).                                     */
 
7393
  /*                                                                       */
 
7394
  /*  On exit with TRUE, test IP < CodeSize to know whether it comes from  */
 
7395
  /*  an instruction trap or a normal termination.                         */
 
7396
  /*                                                                       */
 
7397
  /*                                                                       */
 
7398
  /*  Note: The documented DEBUG opcode pops a value from the stack.  This */
 
7399
  /*        behaviour is unsupported; here a DEBUG opcode is always an     */
 
7400
  /*        error.                                                         */
 
7401
  /*                                                                       */
 
7402
  /*                                                                       */
 
7403
  /* THIS IS THE INTERPRETER'S MAIN LOOP.                                  */
 
7404
  /*                                                                       */
 
7405
  /*  Instructions appear in the specification's order.                    */
 
7406
  /*                                                                       */
 
7407
  /*************************************************************************/
 
7408
 
 
7409
 
 
7410
  /* documentation is in ttinterp.h */
 
7411
 
 
7412
  FT_EXPORT_DEF( FT_Error )
 
7413
  TT_RunIns( TT_ExecContext  exc )
 
7414
  {
 
7415
    FT_Long  ins_counter = 0;  /* executed instructions counter */
 
7416
 
 
7417
 
 
7418
#ifdef TT_CONFIG_OPTION_STATIC_RASTER
 
7419
    cur = *exc;
 
7420
#endif
 
7421
 
 
7422
    /* set CVT functions */
 
7423
    CUR.tt_metrics.ratio = 0;
 
7424
    if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
 
7425
    {
 
7426
      /* non-square pixels, use the stretched routines */
 
7427
      CUR.func_read_cvt  = Read_CVT_Stretched;
 
7428
      CUR.func_write_cvt = Write_CVT_Stretched;
 
7429
      CUR.func_move_cvt  = Move_CVT_Stretched;
 
7430
    }
 
7431
    else
 
7432
    {
 
7433
      /* square pixels, use normal routines */
 
7434
      CUR.func_read_cvt  = Read_CVT;
 
7435
      CUR.func_write_cvt = Write_CVT;
 
7436
      CUR.func_move_cvt  = Move_CVT;
 
7437
    }
 
7438
 
 
7439
    COMPUTE_Funcs();
 
7440
    COMPUTE_Round( (FT_Byte)exc->GS.round_state );
 
7441
 
 
7442
    do
 
7443
    {
 
7444
      CUR.opcode = CUR.code[CUR.IP];
 
7445
 
 
7446
      FT_TRACE7(( "  " ));
 
7447
      FT_TRACE7(( opcode_name[CUR.opcode] ));
 
7448
      FT_TRACE7(( "\n" ));
 
7449
 
 
7450
      if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
 
7451
      {
 
7452
        if ( CUR.IP + 1 > CUR.codeSize )
 
7453
          goto LErrorCodeOverflow_;
 
7454
 
 
7455
        CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
 
7456
      }
 
7457
 
 
7458
      if ( CUR.IP + CUR.length > CUR.codeSize )
 
7459
        goto LErrorCodeOverflow_;
 
7460
 
 
7461
      /* First, let's check for empty stack and overflow */
 
7462
      CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );
 
7463
 
 
7464
      /* `args' is the top of the stack once arguments have been popped. */
 
7465
      /* One can also interpret it as the index of the last argument.    */
 
7466
      if ( CUR.args < 0 )
 
7467
      {
 
7468
        CUR.error = TT_Err_Too_Few_Arguments;
 
7469
        goto LErrorLabel_;
 
7470
      }
 
7471
 
 
7472
      CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
 
7473
 
 
7474
      /* `new_top' is the new top of the stack, after the instruction's */
 
7475
      /* execution.  `top' will be set to `new_top' after the `switch'  */
 
7476
      /* statement.                                                     */
 
7477
      if ( CUR.new_top > CUR.stackSize )
 
7478
      {
 
7479
        CUR.error = TT_Err_Stack_Overflow;
 
7480
        goto LErrorLabel_;
 
7481
      }
 
7482
 
 
7483
      CUR.step_ins = TRUE;
 
7484
      CUR.error    = TT_Err_Ok;
 
7485
 
 
7486
#ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
 
7487
 
 
7488
      {
 
7489
        FT_Long*  args   = CUR.stack + CUR.args;
 
7490
        FT_Byte   opcode = CUR.opcode;
 
7491
 
 
7492
 
 
7493
#undef  ARRAY_BOUND_ERROR
 
7494
#define ARRAY_BOUND_ERROR  goto Set_Invalid_Ref
 
7495
 
 
7496
 
 
7497
        switch ( opcode )
 
7498
        {
 
7499
        case 0x00:  /* SVTCA y  */
 
7500
        case 0x01:  /* SVTCA x  */
 
7501
        case 0x02:  /* SPvTCA y */
 
7502
        case 0x03:  /* SPvTCA x */
 
7503
        case 0x04:  /* SFvTCA y */
 
7504
        case 0x05:  /* SFvTCA x */
 
7505
          {
 
7506
            FT_Short AA, BB;
 
7507
 
 
7508
 
 
7509
            AA = (FT_Short)( ( opcode & 1 ) << 14 );
 
7510
            BB = (FT_Short)( AA ^ 0x4000 );
 
7511
 
 
7512
            if ( opcode < 4 )
 
7513
            {
 
7514
              CUR.GS.projVector.x = AA;
 
7515
              CUR.GS.projVector.y = BB;
 
7516
 
 
7517
              CUR.GS.dualVector.x = AA;
 
7518
              CUR.GS.dualVector.y = BB;
 
7519
            }
 
7520
            else
 
7521
            {
 
7522
              GUESS_VECTOR( projVector );
 
7523
            }
 
7524
 
 
7525
            if ( ( opcode & 2 ) == 0 )
 
7526
            {
 
7527
              CUR.GS.freeVector.x = AA;
 
7528
              CUR.GS.freeVector.y = BB;
 
7529
            }
 
7530
            else
 
7531
            {
 
7532
              GUESS_VECTOR( freeVector );
 
7533
            }
 
7534
 
 
7535
            COMPUTE_Funcs();
 
7536
          }
 
7537
          break;
 
7538
 
 
7539
        case 0x06:  /* SPvTL // */
 
7540
        case 0x07:  /* SPvTL +  */
 
7541
          DO_SPVTL
 
7542
          break;
 
7543
 
 
7544
        case 0x08:  /* SFvTL // */
 
7545
        case 0x09:  /* SFvTL +  */
 
7546
          DO_SFVTL
 
7547
          break;
 
7548
 
 
7549
        case 0x0A:  /* SPvFS */
 
7550
          DO_SPVFS
 
7551
          break;
 
7552
 
 
7553
        case 0x0B:  /* SFvFS */
 
7554
          DO_SFVFS
 
7555
          break;
 
7556
 
 
7557
        case 0x0C:  /* GPV */
 
7558
          DO_GPV
 
7559
          break;
 
7560
 
 
7561
        case 0x0D:  /* GFV */
 
7562
          DO_GFV
 
7563
          break;
 
7564
 
 
7565
        case 0x0E:  /* SFvTPv */
 
7566
          DO_SFVTPV
 
7567
          break;
 
7568
 
 
7569
        case 0x0F:  /* ISECT  */
 
7570
          Ins_ISECT( EXEC_ARG_ args );
 
7571
          break;
 
7572
 
 
7573
        case 0x10:  /* SRP0 */
 
7574
          DO_SRP0
 
7575
          break;
 
7576
 
 
7577
        case 0x11:  /* SRP1 */
 
7578
          DO_SRP1
 
7579
          break;
 
7580
 
 
7581
        case 0x12:  /* SRP2 */
 
7582
          DO_SRP2
 
7583
          break;
 
7584
 
 
7585
        case 0x13:  /* SZP0 */
 
7586
          Ins_SZP0( EXEC_ARG_ args );
 
7587
          break;
 
7588
 
 
7589
        case 0x14:  /* SZP1 */
 
7590
          Ins_SZP1( EXEC_ARG_ args );
 
7591
          break;
 
7592
 
 
7593
        case 0x15:  /* SZP2 */
 
7594
          Ins_SZP2( EXEC_ARG_ args );
 
7595
          break;
 
7596
 
 
7597
        case 0x16:  /* SZPS */
 
7598
          Ins_SZPS( EXEC_ARG_ args );
 
7599
          break;
 
7600
 
 
7601
        case 0x17:  /* SLOOP */
 
7602
          DO_SLOOP
 
7603
          break;
 
7604
 
 
7605
        case 0x18:  /* RTG */
 
7606
          DO_RTG
 
7607
          break;
 
7608
 
 
7609
        case 0x19:  /* RTHG */
 
7610
          DO_RTHG
 
7611
          break;
 
7612
 
 
7613
        case 0x1A:  /* SMD */
 
7614
          DO_SMD
 
7615
          break;
 
7616
 
 
7617
        case 0x1B:  /* ELSE */
 
7618
          Ins_ELSE( EXEC_ARG_ args );
 
7619
          break;
 
7620
 
 
7621
        case 0x1C:  /* JMPR */
 
7622
          DO_JMPR
 
7623
          break;
 
7624
 
 
7625
        case 0x1D:  /* SCVTCI */
 
7626
          DO_SCVTCI
 
7627
          break;
 
7628
 
 
7629
        case 0x1E:  /* SSWCI */
 
7630
          DO_SSWCI
 
7631
          break;
 
7632
 
 
7633
        case 0x1F:  /* SSW */
 
7634
          DO_SSW
 
7635
          break;
 
7636
 
 
7637
        case 0x20:  /* DUP */
 
7638
          DO_DUP
 
7639
          break;
 
7640
 
 
7641
        case 0x21:  /* POP */
 
7642
          /* nothing :-) */
 
7643
          break;
 
7644
 
 
7645
        case 0x22:  /* CLEAR */
 
7646
          DO_CLEAR
 
7647
          break;
 
7648
 
 
7649
        case 0x23:  /* SWAP */
 
7650
          DO_SWAP
 
7651
          break;
 
7652
 
 
7653
        case 0x24:  /* DEPTH */
 
7654
          DO_DEPTH
 
7655
          break;
 
7656
 
 
7657
        case 0x25:  /* CINDEX */
 
7658
          DO_CINDEX
 
7659
          break;
 
7660
 
 
7661
        case 0x26:  /* MINDEX */
 
7662
          Ins_MINDEX( EXEC_ARG_ args );
 
7663
          break;
 
7664
 
 
7665
        case 0x27:  /* ALIGNPTS */
 
7666
          Ins_ALIGNPTS( EXEC_ARG_ args );
 
7667
          break;
 
7668
 
 
7669
        case 0x28:  /* ???? */
 
7670
          Ins_UNKNOWN( EXEC_ARG_ args );
 
7671
          break;
 
7672
 
 
7673
        case 0x29:  /* UTP */
 
7674
          Ins_UTP( EXEC_ARG_ args );
 
7675
          break;
 
7676
 
 
7677
        case 0x2A:  /* LOOPCALL */
 
7678
          Ins_LOOPCALL( EXEC_ARG_ args );
 
7679
          break;
 
7680
 
 
7681
        case 0x2B:  /* CALL */
 
7682
          Ins_CALL( EXEC_ARG_ args );
 
7683
          break;
 
7684
 
 
7685
        case 0x2C:  /* FDEF */
 
7686
          Ins_FDEF( EXEC_ARG_ args );
 
7687
          break;
 
7688
 
 
7689
        case 0x2D:  /* ENDF */
 
7690
          Ins_ENDF( EXEC_ARG_ args );
 
7691
          break;
 
7692
 
 
7693
        case 0x2E:  /* MDAP */
 
7694
        case 0x2F:  /* MDAP */
 
7695
          Ins_MDAP( EXEC_ARG_ args );
 
7696
          break;
 
7697
 
 
7698
 
 
7699
        case 0x30:  /* IUP */
 
7700
        case 0x31:  /* IUP */
 
7701
          Ins_IUP( EXEC_ARG_ args );
 
7702
          break;
 
7703
 
 
7704
        case 0x32:  /* SHP */
 
7705
        case 0x33:  /* SHP */
 
7706
          Ins_SHP( EXEC_ARG_ args );
 
7707
          break;
 
7708
 
 
7709
        case 0x34:  /* SHC */
 
7710
        case 0x35:  /* SHC */
 
7711
          Ins_SHC( EXEC_ARG_ args );
 
7712
          break;
 
7713
 
 
7714
        case 0x36:  /* SHZ */
 
7715
        case 0x37:  /* SHZ */
 
7716
          Ins_SHZ( EXEC_ARG_ args );
 
7717
          break;
 
7718
 
 
7719
        case 0x38:  /* SHPIX */
 
7720
          Ins_SHPIX( EXEC_ARG_ args );
 
7721
          break;
 
7722
 
 
7723
        case 0x39:  /* IP    */
 
7724
          Ins_IP( EXEC_ARG_ args );
 
7725
          break;
 
7726
 
 
7727
        case 0x3A:  /* MSIRP */
 
7728
        case 0x3B:  /* MSIRP */
 
7729
          Ins_MSIRP( EXEC_ARG_ args );
 
7730
          break;
 
7731
 
 
7732
        case 0x3C:  /* AlignRP */
 
7733
          Ins_ALIGNRP( EXEC_ARG_ args );
 
7734
          break;
 
7735
 
 
7736
        case 0x3D:  /* RTDG */
 
7737
          DO_RTDG
 
7738
          break;
 
7739
 
 
7740
        case 0x3E:  /* MIAP */
 
7741
        case 0x3F:  /* MIAP */
 
7742
          Ins_MIAP( EXEC_ARG_ args );
 
7743
          break;
 
7744
 
 
7745
        case 0x40:  /* NPUSHB */
 
7746
          Ins_NPUSHB( EXEC_ARG_ args );
 
7747
          break;
 
7748
 
 
7749
        case 0x41:  /* NPUSHW */
 
7750
          Ins_NPUSHW( EXEC_ARG_ args );
 
7751
          break;
 
7752
 
 
7753
        case 0x42:  /* WS */
 
7754
          DO_WS
 
7755
          break;
 
7756
 
 
7757
      Set_Invalid_Ref:
 
7758
            CUR.error = TT_Err_Invalid_Reference;
 
7759
          break;
 
7760
 
 
7761
        case 0x43:  /* RS */
 
7762
          DO_RS
 
7763
          break;
 
7764
 
 
7765
        case 0x44:  /* WCVTP */
 
7766
          DO_WCVTP
 
7767
          break;
 
7768
 
 
7769
        case 0x45:  /* RCVT */
 
7770
          DO_RCVT
 
7771
          break;
 
7772
 
 
7773
        case 0x46:  /* GC */
 
7774
        case 0x47:  /* GC */
 
7775
          Ins_GC( EXEC_ARG_ args );
 
7776
          break;
 
7777
 
 
7778
        case 0x48:  /* SCFS */
 
7779
          Ins_SCFS( EXEC_ARG_ args );
 
7780
          break;
 
7781
 
 
7782
        case 0x49:  /* MD */
 
7783
        case 0x4A:  /* MD */
 
7784
          Ins_MD( EXEC_ARG_ args );
 
7785
          break;
 
7786
 
 
7787
        case 0x4B:  /* MPPEM */
 
7788
          DO_MPPEM
 
7789
          break;
 
7790
 
 
7791
        case 0x4C:  /* MPS */
 
7792
          DO_MPS
 
7793
          break;
 
7794
 
 
7795
        case 0x4D:  /* FLIPON */
 
7796
          DO_FLIPON
 
7797
          break;
 
7798
 
 
7799
        case 0x4E:  /* FLIPOFF */
 
7800
          DO_FLIPOFF
 
7801
          break;
 
7802
 
 
7803
        case 0x4F:  /* DEBUG */
 
7804
          DO_DEBUG
 
7805
          break;
 
7806
 
 
7807
        case 0x50:  /* LT */
 
7808
          DO_LT
 
7809
          break;
 
7810
 
 
7811
        case 0x51:  /* LTEQ */
 
7812
          DO_LTEQ
 
7813
          break;
 
7814
 
 
7815
        case 0x52:  /* GT */
 
7816
          DO_GT
 
7817
          break;
 
7818
 
 
7819
        case 0x53:  /* GTEQ */
 
7820
          DO_GTEQ
 
7821
          break;
 
7822
 
 
7823
        case 0x54:  /* EQ */
 
7824
          DO_EQ
 
7825
          break;
 
7826
 
 
7827
        case 0x55:  /* NEQ */
 
7828
          DO_NEQ
 
7829
          break;
 
7830
 
 
7831
        case 0x56:  /* ODD */
 
7832
          DO_ODD
 
7833
          break;
 
7834
 
 
7835
        case 0x57:  /* EVEN */
 
7836
          DO_EVEN
 
7837
          break;
 
7838
 
 
7839
        case 0x58:  /* IF */
 
7840
          Ins_IF( EXEC_ARG_ args );
 
7841
          break;
 
7842
 
 
7843
        case 0x59:  /* EIF */
 
7844
          /* do nothing */
 
7845
          break;
 
7846
 
 
7847
        case 0x5A:  /* AND */
 
7848
          DO_AND
 
7849
          break;
 
7850
 
 
7851
        case 0x5B:  /* OR */
 
7852
          DO_OR
 
7853
          break;
 
7854
 
 
7855
        case 0x5C:  /* NOT */
 
7856
          DO_NOT
 
7857
          break;
 
7858
 
 
7859
        case 0x5D:  /* DELTAP1 */
 
7860
          Ins_DELTAP( EXEC_ARG_ args );
 
7861
          break;
 
7862
 
 
7863
        case 0x5E:  /* SDB */
 
7864
          DO_SDB
 
7865
          break;
 
7866
 
 
7867
        case 0x5F:  /* SDS */
 
7868
          DO_SDS
 
7869
          break;
 
7870
 
 
7871
        case 0x60:  /* ADD */
 
7872
          DO_ADD
 
7873
          break;
 
7874
 
 
7875
        case 0x61:  /* SUB */
 
7876
          DO_SUB
 
7877
          break;
 
7878
 
 
7879
        case 0x62:  /* DIV */
 
7880
          DO_DIV
 
7881
          break;
 
7882
 
 
7883
        case 0x63:  /* MUL */
 
7884
          DO_MUL
 
7885
          break;
 
7886
 
 
7887
        case 0x64:  /* ABS */
 
7888
          DO_ABS
 
7889
          break;
 
7890
 
 
7891
        case 0x65:  /* NEG */
 
7892
          DO_NEG
 
7893
          break;
 
7894
 
 
7895
        case 0x66:  /* FLOOR */
 
7896
          DO_FLOOR
 
7897
          break;
 
7898
 
 
7899
        case 0x67:  /* CEILING */
 
7900
          DO_CEILING
 
7901
          break;
 
7902
 
 
7903
        case 0x68:  /* ROUND */
 
7904
        case 0x69:  /* ROUND */
 
7905
        case 0x6A:  /* ROUND */
 
7906
        case 0x6B:  /* ROUND */
 
7907
          DO_ROUND
 
7908
          break;
 
7909
 
 
7910
        case 0x6C:  /* NROUND */
 
7911
        case 0x6D:  /* NROUND */
 
7912
        case 0x6E:  /* NRRUND */
 
7913
        case 0x6F:  /* NROUND */
 
7914
          DO_NROUND
 
7915
          break;
 
7916
 
 
7917
        case 0x70:  /* WCVTF */
 
7918
          DO_WCVTF
 
7919
          break;
 
7920
 
 
7921
        case 0x71:  /* DELTAP2 */
 
7922
        case 0x72:  /* DELTAP3 */
 
7923
          Ins_DELTAP( EXEC_ARG_ args );
 
7924
          break;
 
7925
 
 
7926
        case 0x73:  /* DELTAC0 */
 
7927
        case 0x74:  /* DELTAC1 */
 
7928
        case 0x75:  /* DELTAC2 */
 
7929
          Ins_DELTAC( EXEC_ARG_ args );
 
7930
          break;
 
7931
 
 
7932
        case 0x76:  /* SROUND */
 
7933
          DO_SROUND
 
7934
          break;
 
7935
 
 
7936
        case 0x77:  /* S45Round */
 
7937
          DO_S45ROUND
 
7938
          break;
 
7939
 
 
7940
        case 0x78:  /* JROT */
 
7941
          DO_JROT
 
7942
          break;
 
7943
 
 
7944
        case 0x79:  /* JROF */
 
7945
          DO_JROF
 
7946
          break;
 
7947
 
 
7948
        case 0x7A:  /* ROFF */
 
7949
          DO_ROFF
 
7950
          break;
 
7951
 
 
7952
        case 0x7B:  /* ???? */
 
7953
          Ins_UNKNOWN( EXEC_ARG_ args );
 
7954
          break;
 
7955
 
 
7956
        case 0x7C:  /* RUTG */
 
7957
          DO_RUTG
 
7958
          break;
 
7959
 
 
7960
        case 0x7D:  /* RDTG */
 
7961
          DO_RDTG
 
7962
          break;
 
7963
 
 
7964
        case 0x7E:  /* SANGW */
 
7965
        case 0x7F:  /* AA    */
 
7966
          /* nothing - obsolete */
 
7967
          break;
 
7968
 
 
7969
        case 0x80:  /* FLIPPT */
 
7970
          Ins_FLIPPT( EXEC_ARG_ args );
 
7971
          break;
 
7972
 
 
7973
        case 0x81:  /* FLIPRGON */
 
7974
          Ins_FLIPRGON( EXEC_ARG_ args );
 
7975
          break;
 
7976
 
 
7977
        case 0x82:  /* FLIPRGOFF */
 
7978
          Ins_FLIPRGOFF( EXEC_ARG_ args );
 
7979
          break;
 
7980
 
 
7981
        case 0x83:  /* UNKNOWN */
 
7982
        case 0x84:  /* UNKNOWN */
 
7983
          Ins_UNKNOWN( EXEC_ARG_ args );
 
7984
          break;
 
7985
 
 
7986
        case 0x85:  /* SCANCTRL */
 
7987
          Ins_SCANCTRL( EXEC_ARG_ args );
 
7988
          break;
 
7989
 
 
7990
        case 0x86:  /* SDPVTL */
 
7991
        case 0x87:  /* SDPVTL */
 
7992
          Ins_SDPVTL( EXEC_ARG_ args );
 
7993
          break;
 
7994
 
 
7995
        case 0x88:  /* GETINFO */
 
7996
          Ins_GETINFO( EXEC_ARG_ args );
 
7997
          break;
 
7998
 
 
7999
        case 0x89:  /* IDEF */
 
8000
          Ins_IDEF( EXEC_ARG_ args );
 
8001
          break;
 
8002
 
 
8003
        case 0x8A:  /* ROLL */
 
8004
          Ins_ROLL( EXEC_ARG_ args );
 
8005
          break;
 
8006
 
 
8007
        case 0x8B:  /* MAX */
 
8008
          DO_MAX
 
8009
          break;
 
8010
 
 
8011
        case 0x8C:  /* MIN */
 
8012
          DO_MIN
 
8013
          break;
 
8014
 
 
8015
        case 0x8D:  /* SCANTYPE */
 
8016
          Ins_SCANTYPE( EXEC_ARG_ args );
 
8017
          break;
 
8018
 
 
8019
        case 0x8E:  /* INSTCTRL */
 
8020
          Ins_INSTCTRL( EXEC_ARG_ args );
 
8021
          break;
 
8022
 
 
8023
        case 0x8F:
 
8024
          Ins_UNKNOWN( EXEC_ARG_ args );
 
8025
          break;
 
8026
 
 
8027
        default:
 
8028
          if ( opcode >= 0xE0 )
 
8029
            Ins_MIRP( EXEC_ARG_ args );
 
8030
          else if ( opcode >= 0xC0 )
 
8031
            Ins_MDRP( EXEC_ARG_ args );
 
8032
          else if ( opcode >= 0xB8 )
 
8033
            Ins_PUSHW( EXEC_ARG_ args );
 
8034
          else if ( opcode >= 0xB0 )
 
8035
            Ins_PUSHB( EXEC_ARG_ args );
 
8036
          else
 
8037
            Ins_UNKNOWN( EXEC_ARG_ args );
 
8038
        }
 
8039
 
 
8040
      }
 
8041
 
 
8042
#else
 
8043
 
 
8044
      Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );
 
8045
 
 
8046
#endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
 
8047
 
 
8048
      if ( CUR.error != TT_Err_Ok )
 
8049
      {
 
8050
        switch ( CUR.error )
 
8051
        {
 
8052
        case TT_Err_Invalid_Opcode: /* looking for redefined instructions */
 
8053
          {
 
8054
            TT_DefRecord*  def   = CUR.IDefs;
 
8055
            TT_DefRecord*  limit = def + CUR.numIDefs;
 
8056
 
 
8057
 
 
8058
            for ( ; def < limit; def++ )
 
8059
            {
 
8060
              if ( def->active && CUR.opcode == (FT_Byte)def->opc )
 
8061
              {
 
8062
                TT_CallRec*  callrec;
 
8063
 
 
8064
 
 
8065
                if ( CUR.callTop >= CUR.callSize )
 
8066
                {
 
8067
                  CUR.error = TT_Err_Invalid_Reference;
 
8068
                  goto LErrorLabel_;
 
8069
                }
 
8070
 
 
8071
                callrec = &CUR.callStack[CUR.callTop];
 
8072
 
 
8073
                callrec->Caller_Range = CUR.curRange;
 
8074
                callrec->Caller_IP    = CUR.IP + 1;
 
8075
                callrec->Cur_Count    = 1;
 
8076
                callrec->Cur_Restart  = def->start;
 
8077
 
 
8078
                if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
 
8079
                  goto LErrorLabel_;
 
8080
 
 
8081
                goto LSuiteLabel_;
 
8082
              }
 
8083
            }
 
8084
          }
 
8085
 
 
8086
          CUR.error = TT_Err_Invalid_Opcode;
 
8087
          goto LErrorLabel_;
 
8088
 
 
8089
#if 0
 
8090
          break;   /* Unreachable code warning suppression.             */
 
8091
                   /* Leave to remind in case a later change the editor */
 
8092
                   /* to consider break;                                */
 
8093
#endif
 
8094
 
 
8095
        default:
 
8096
          goto LErrorLabel_;
 
8097
 
 
8098
#if 0
 
8099
        break;
 
8100
#endif
 
8101
        }
 
8102
      }
 
8103
 
 
8104
      CUR.top = CUR.new_top;
 
8105
 
 
8106
      if ( CUR.step_ins )
 
8107
        CUR.IP += CUR.length;
 
8108
 
 
8109
      /* increment instruction counter and check if we didn't */
 
8110
      /* run this program for too long (e.g. infinite loops). */
 
8111
      if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
 
8112
        return TT_Err_Execution_Too_Long;
 
8113
 
 
8114
    LSuiteLabel_:
 
8115
      if ( CUR.IP >= CUR.codeSize )
 
8116
      {
 
8117
        if ( CUR.callTop > 0 )
 
8118
        {
 
8119
          CUR.error = TT_Err_Code_Overflow;
 
8120
          goto LErrorLabel_;
 
8121
        }
 
8122
        else
 
8123
          goto LNo_Error_;
 
8124
      }
 
8125
    } while ( !CUR.instruction_trap );
 
8126
 
 
8127
  LNo_Error_:
 
8128
 
 
8129
#ifdef TT_CONFIG_OPTION_STATIC_RASTER
 
8130
    *exc = cur;
 
8131
#endif
 
8132
 
 
8133
    return TT_Err_Ok;
 
8134
 
 
8135
  LErrorCodeOverflow_:
 
8136
    CUR.error = TT_Err_Code_Overflow;
 
8137
 
 
8138
  LErrorLabel_:
 
8139
 
 
8140
#ifdef TT_CONFIG_OPTION_STATIC_RASTER
 
8141
    *exc = cur;
 
8142
#endif
 
8143
 
 
8144
    /* If any errors have occurred, function tables may be broken. */
 
8145
    /* Force a re-execution of `prep' and `fpgm' tables if no      */
 
8146
    /* bytecode debugger is run.                                   */
 
8147
    if ( CUR.error && !CUR.instruction_trap )
 
8148
    {
 
8149
      FT_TRACE1(( "  The interpreter returned error 0x%x\n", CUR.error ));
 
8150
      exc->size->cvt_ready      = FALSE;  
 
8151
    }
 
8152
 
 
8153
    return CUR.error;
 
8154
  }
 
8155
 
 
8156
 
 
8157
#endif /* TT_USE_BYTECODE_INTERPRETER */
 
8158
 
 
8159
 
 
8160
/* END */