00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <ft2build.h>
00020 #include FT_INTERNAL_DEBUG_H
00021 #include FT_INTERNAL_CALC_H
00022 #include FT_TRIGONOMETRY_H
00023 #include FT_SYSTEM_H
00024
00025 #include "ttinterp.h"
00026
00027 #include "tterrors.h"
00028
00029
00030 #ifdef TT_USE_BYTECODE_INTERPRETER
00031
00032
00033 #define TT_MULFIX FT_MulFix
00034 #define TT_MULDIV FT_MulDiv
00035 #define TT_MULDIV_NO_ROUND FT_MulDiv_No_Round
00036
00037
00038
00039
00040
00041
00042
00043
00044 #undef FT_COMPONENT
00045 #define FT_COMPONENT trace_ttinterp
00046
00047
00048
00049
00050
00051
00052
00053 #define MAX_RUNNABLE_OPCODES 1000000L
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 #ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER
00094
00095 #define CUR (*exc)
00096
00097
00098
00099
00100
00101
00102 #define FT_UNUSED_EXEC FT_UNUSED( exc )
00103
00104 #else
00105
00106 #define CUR cur
00107
00108 #define FT_UNUSED_EXEC int __dummy = __dummy
00109
00110 static
00111 TT_ExecContextRec cur;
00112
00113
00114
00115
00116
00117 #endif
00118
00119
00120
00121
00122
00123
00124 #define INS_ARG EXEC_OP_ FT_Long* args
00125
00126
00127
00128
00129
00130
00131
00132 #define FT_UNUSED_ARG FT_UNUSED_EXEC; FT_UNUSED( args )
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 #define SKIP_Code() \
00144 SkipCode( EXEC_ARG )
00145
00146 #define GET_ShortIns() \
00147 GetShortIns( EXEC_ARG )
00148
00149 #define NORMalize( x, y, v ) \
00150 Normalize( EXEC_ARG_ x, y, v )
00151
00152 #define SET_SuperRound( scale, flags ) \
00153 SetSuperRound( EXEC_ARG_ scale, flags )
00154
00155 #define ROUND_None( d, c ) \
00156 Round_None( EXEC_ARG_ d, c )
00157
00158 #define INS_Goto_CodeRange( range, ip ) \
00159 Ins_Goto_CodeRange( EXEC_ARG_ range, ip )
00160
00161 #define CUR_Func_move( z, p, d ) \
00162 CUR.func_move( EXEC_ARG_ z, p, d )
00163
00164 #define CUR_Func_move_orig( z, p, d ) \
00165 CUR.func_move_orig( EXEC_ARG_ z, p, d )
00166
00167 #define CUR_Func_round( d, c ) \
00168 CUR.func_round( EXEC_ARG_ d, c )
00169
00170 #define CUR_Func_read_cvt( index ) \
00171 CUR.func_read_cvt( EXEC_ARG_ index )
00172
00173 #define CUR_Func_write_cvt( index, val ) \
00174 CUR.func_write_cvt( EXEC_ARG_ index, val )
00175
00176 #define CUR_Func_move_cvt( index, val ) \
00177 CUR.func_move_cvt( EXEC_ARG_ index, val )
00178
00179 #define CURRENT_Ratio() \
00180 Current_Ratio( EXEC_ARG )
00181
00182 #define CURRENT_Ppem() \
00183 Current_Ppem( EXEC_ARG )
00184
00185 #define CUR_Ppem() \
00186 Cur_PPEM( EXEC_ARG )
00187
00188 #define INS_SxVTL( a, b, c, d ) \
00189 Ins_SxVTL( EXEC_ARG_ a, b, c, d )
00190
00191 #define COMPUTE_Funcs() \
00192 Compute_Funcs( EXEC_ARG )
00193
00194 #define COMPUTE_Round( a ) \
00195 Compute_Round( EXEC_ARG_ a )
00196
00197 #define COMPUTE_Point_Displacement( a, b, c, d ) \
00198 Compute_Point_Displacement( EXEC_ARG_ a, b, c, d )
00199
00200 #define MOVE_Zp2_Point( a, b, c, t ) \
00201 Move_Zp2_Point( EXEC_ARG_ a, b, c, t )
00202
00203
00204 #define CUR_Func_project( v1, v2 ) \
00205 CUR.func_project( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
00206
00207 #define CUR_Func_dualproj( v1, v2 ) \
00208 CUR.func_dualproj( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
00209
00210 #define CUR_fast_project( v ) \
00211 CUR.func_project( EXEC_ARG_ (v)->x, (v)->y )
00212
00213 #define CUR_fast_dualproj( v ) \
00214 CUR.func_dualproj( EXEC_ARG_ (v)->x, (v)->y )
00215
00216
00217
00218
00219
00220
00221 typedef void (*TInstruction_Function)( INS_ARG );
00222
00223
00224
00225
00226
00227
00228 #define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) )
00229
00230 #undef SUCCESS
00231 #define SUCCESS 0
00232
00233 #undef FAILURE
00234 #define FAILURE 1
00235
00236 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
00237 #define GUESS_VECTOR( V ) \
00238 if ( CUR.face->unpatented_hinting ) \
00239 { \
00240 CUR.GS.V.x = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0x4000 : 0 ); \
00241 CUR.GS.V.y = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0 : 0x4000 ); \
00242 }
00243 #else
00244 #define GUESS_VECTOR( V )
00245 #endif
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 FT_LOCAL_DEF( FT_Error )
00275 TT_Goto_CodeRange( TT_ExecContext exec,
00276 FT_Int range,
00277 FT_Long IP )
00278 {
00279 TT_CodeRange* coderange;
00280
00281
00282 FT_ASSERT( range >= 1 && range <= 3 );
00283
00284 coderange = &exec->codeRangeTable[range - 1];
00285
00286 FT_ASSERT( coderange->base != NULL );
00287
00288
00289
00290
00291
00292 FT_ASSERT( (FT_ULong)IP <= coderange->size );
00293
00294 exec->code = coderange->base;
00295 exec->codeSize = coderange->size;
00296 exec->IP = IP;
00297 exec->curRange = range;
00298
00299 return TT_Err_Ok;
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 FT_LOCAL_DEF( FT_Error )
00325 TT_Set_CodeRange( TT_ExecContext exec,
00326 FT_Int range,
00327 void* base,
00328 FT_Long length )
00329 {
00330 FT_ASSERT( range >= 1 && range <= 3 );
00331
00332 exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
00333 exec->codeRangeTable[range - 1].size = length;
00334
00335 return TT_Err_Ok;
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 FT_LOCAL_DEF( FT_Error )
00360 TT_Clear_CodeRange( TT_ExecContext exec,
00361 FT_Int range )
00362 {
00363 FT_ASSERT( range >= 1 && range <= 3 );
00364
00365 exec->codeRangeTable[range - 1].base = NULL;
00366 exec->codeRangeTable[range - 1].size = 0;
00367
00368 return TT_Err_Ok;
00369 }
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398 FT_LOCAL_DEF( FT_Error )
00399 TT_Done_Context( TT_ExecContext exec )
00400 {
00401 FT_Memory memory = exec->memory;
00402
00403
00404
00405 exec->maxPoints = 0;
00406 exec->maxContours = 0;
00407
00408
00409 FT_FREE( exec->stack );
00410 exec->stackSize = 0;
00411
00412
00413 FT_FREE( exec->callStack );
00414 exec->callSize = 0;
00415 exec->callTop = 0;
00416
00417
00418 FT_FREE( exec->glyphIns );
00419 exec->glyphSize = 0;
00420
00421 exec->size = NULL;
00422 exec->face = NULL;
00423
00424 FT_FREE( exec );
00425
00426 return TT_Err_Ok;
00427 }
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447 static FT_Error
00448 Init_Context( TT_ExecContext exec,
00449 FT_Memory memory )
00450 {
00451 FT_Error error;
00452
00453
00454 FT_TRACE1(( "Init_Context: new object at 0x%08p\n", exec ));
00455
00456 exec->memory = memory;
00457 exec->callSize = 32;
00458
00459 if ( FT_NEW_ARRAY( exec->callStack, exec->callSize ) )
00460 goto Fail_Memory;
00461
00462
00463
00464 exec->maxPoints = 0;
00465 exec->maxContours = 0;
00466
00467 exec->stackSize = 0;
00468 exec->glyphSize = 0;
00469
00470 exec->stack = NULL;
00471 exec->glyphIns = NULL;
00472
00473 exec->face = NULL;
00474 exec->size = NULL;
00475
00476 return TT_Err_Ok;
00477
00478 Fail_Memory:
00479 FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n",
00480 (FT_Long)exec ));
00481 TT_Done_Context( exec );
00482
00483 return error;
00484 }
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 static FT_Error
00512 Update_Max( FT_Memory memory,
00513 FT_ULong* size,
00514 FT_Long multiplier,
00515 void* _pbuff,
00516 FT_ULong new_max )
00517 {
00518 FT_Error error;
00519 void** pbuff = (void**)_pbuff;
00520
00521
00522 if ( *size < new_max )
00523 {
00524 if ( FT_REALLOC( *pbuff, *size * multiplier, new_max * multiplier ) )
00525 return error;
00526 *size = new_max;
00527 }
00528
00529 return TT_Err_Ok;
00530 }
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 FT_LOCAL_DEF( FT_Error )
00556 TT_Load_Context( TT_ExecContext exec,
00557 TT_Face face,
00558 TT_Size size )
00559 {
00560 FT_Int i;
00561 FT_ULong tmp;
00562 TT_MaxProfile* maxp;
00563 FT_Error error;
00564
00565
00566 exec->face = face;
00567 maxp = &face->max_profile;
00568 exec->size = size;
00569
00570 if ( size )
00571 {
00572 exec->numFDefs = size->num_function_defs;
00573 exec->maxFDefs = size->max_function_defs;
00574 exec->numIDefs = size->num_instruction_defs;
00575 exec->maxIDefs = size->max_instruction_defs;
00576 exec->FDefs = size->function_defs;
00577 exec->IDefs = size->instruction_defs;
00578 exec->tt_metrics = size->ttmetrics;
00579 exec->metrics = size->metrics;
00580
00581 exec->maxFunc = size->max_func;
00582 exec->maxIns = size->max_ins;
00583
00584 for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
00585 exec->codeRangeTable[i] = size->codeRangeTable[i];
00586
00587
00588 exec->GS = size->GS;
00589
00590 exec->cvtSize = size->cvt_size;
00591 exec->cvt = size->cvt;
00592
00593 exec->storeSize = size->storage_size;
00594 exec->storage = size->storage;
00595
00596 exec->twilight = size->twilight;
00597 }
00598
00599
00600
00601 tmp = exec->stackSize;
00602 error = Update_Max( exec->memory,
00603 &tmp,
00604 sizeof ( FT_F26Dot6 ),
00605 (void*)&exec->stack,
00606 maxp->maxStackElements + 32 );
00607 exec->stackSize = (FT_UInt)tmp;
00608 if ( error )
00609 return error;
00610
00611 tmp = exec->glyphSize;
00612 error = Update_Max( exec->memory,
00613 &tmp,
00614 sizeof ( FT_Byte ),
00615 (void*)&exec->glyphIns,
00616 maxp->maxSizeOfInstructions );
00617 exec->glyphSize = (FT_UShort)tmp;
00618 if ( error )
00619 return error;
00620
00621 exec->pts.n_points = 0;
00622 exec->pts.n_contours = 0;
00623
00624 exec->zp1 = exec->pts;
00625 exec->zp2 = exec->pts;
00626 exec->zp0 = exec->pts;
00627
00628 exec->instruction_trap = FALSE;
00629
00630 return TT_Err_Ok;
00631 }
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654 FT_LOCAL_DEF( FT_Error )
00655 TT_Save_Context( TT_ExecContext exec,
00656 TT_Size size )
00657 {
00658 FT_Int i;
00659
00660
00661
00662
00663
00664 size->num_function_defs = exec->numFDefs;
00665 size->num_instruction_defs = exec->numIDefs;
00666
00667 size->max_func = exec->maxFunc;
00668 size->max_ins = exec->maxIns;
00669
00670 for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
00671 size->codeRangeTable[i] = exec->codeRangeTable[i];
00672
00673 return TT_Err_Ok;
00674 }
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701 FT_LOCAL_DEF( FT_Error )
00702 TT_Run_Context( TT_ExecContext exec,
00703 FT_Bool debug )
00704 {
00705 FT_Error error;
00706
00707
00708 if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) )
00709 != TT_Err_Ok )
00710 return error;
00711
00712 exec->zp0 = exec->pts;
00713 exec->zp1 = exec->pts;
00714 exec->zp2 = exec->pts;
00715
00716 exec->GS.gep0 = 1;
00717 exec->GS.gep1 = 1;
00718 exec->GS.gep2 = 1;
00719
00720 exec->GS.projVector.x = 0x4000;
00721 exec->GS.projVector.y = 0x0000;
00722
00723 exec->GS.freeVector = exec->GS.projVector;
00724 exec->GS.dualVector = exec->GS.projVector;
00725
00726 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
00727 exec->GS.both_x_axis = TRUE;
00728 #endif
00729
00730 exec->GS.round_state = 1;
00731 exec->GS.loop = 1;
00732
00733
00734
00735 exec->top = 0;
00736 exec->callTop = 0;
00737
00738 #if 1
00739 FT_UNUSED( debug );
00740
00741 return exec->face->interpreter( exec );
00742 #else
00743 if ( !debug )
00744 return TT_RunIns( exec );
00745 else
00746 return TT_Err_Ok;
00747 #endif
00748 }
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758 const TT_GraphicsState tt_default_graphics_state =
00759 {
00760 0, 0, 0,
00761 { 0x4000, 0 },
00762 { 0x4000, 0 },
00763 { 0x4000, 0 },
00764
00765 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
00766 TRUE,
00767 #endif
00768
00769 1, 64, 1,
00770 TRUE, 68, 0, 0, 9, 3,
00771 0, FALSE, 0, 1, 1, 1
00772 };
00773
00774
00775
00776
00777 FT_EXPORT_DEF( TT_ExecContext )
00778 TT_New_Context( TT_Driver driver )
00779 {
00780 TT_ExecContext exec;
00781 FT_Memory memory;
00782
00783
00784 memory = driver->root.root.memory;
00785 exec = driver->context;
00786
00787 if ( !driver->context )
00788 {
00789 FT_Error error;
00790
00791
00792
00793 if ( FT_NEW( exec ) )
00794 goto Fail;
00795
00796
00797 error = Init_Context( exec, memory );
00798 if ( error )
00799 goto Fail;
00800
00801
00802 driver->context = exec;
00803 }
00804
00805 return driver->context;
00806
00807 Fail:
00808 return NULL;
00809 }
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830 #undef PACK
00831 #define PACK( x, y ) ( ( x << 4 ) | y )
00832
00833
00834 static
00835 const FT_Byte Pop_Push_Count[256] =
00836 {
00837
00838
00839
00840 PACK( 0, 0 ),
00841 PACK( 0, 0 ),
00842 PACK( 0, 0 ),
00843 PACK( 0, 0 ),
00844 PACK( 0, 0 ),
00845 PACK( 0, 0 ),
00846 PACK( 2, 0 ),
00847 PACK( 2, 0 ),
00848 PACK( 2, 0 ),
00849 PACK( 2, 0 ),
00850 PACK( 2, 0 ),
00851 PACK( 2, 0 ),
00852 PACK( 0, 2 ),
00853 PACK( 0, 2 ),
00854 PACK( 0, 0 ),
00855 PACK( 5, 0 ),
00856
00857 PACK( 1, 0 ),
00858 PACK( 1, 0 ),
00859 PACK( 1, 0 ),
00860 PACK( 1, 0 ),
00861 PACK( 1, 0 ),
00862 PACK( 1, 0 ),
00863 PACK( 1, 0 ),
00864 PACK( 1, 0 ),
00865 PACK( 0, 0 ),
00866 PACK( 0, 0 ),
00867 PACK( 1, 0 ),
00868 PACK( 0, 0 ),
00869 PACK( 1, 0 ),
00870 PACK( 1, 0 ),
00871 PACK( 1, 0 ),
00872 PACK( 1, 0 ),
00873
00874 PACK( 1, 2 ),
00875 PACK( 1, 0 ),
00876 PACK( 0, 0 ),
00877 PACK( 2, 2 ),
00878 PACK( 0, 1 ),
00879 PACK( 1, 1 ),
00880 PACK( 1, 0 ),
00881 PACK( 2, 0 ),
00882 PACK( 0, 0 ),
00883 PACK( 1, 0 ),
00884 PACK( 2, 0 ),
00885 PACK( 1, 0 ),
00886 PACK( 1, 0 ),
00887 PACK( 0, 0 ),
00888 PACK( 1, 0 ),
00889 PACK( 1, 0 ),
00890
00891 PACK( 0, 0 ),
00892 PACK( 0, 0 ),
00893 PACK( 0, 0 ),
00894 PACK( 0, 0 ),
00895 PACK( 1, 0 ),
00896 PACK( 1, 0 ),
00897 PACK( 1, 0 ),
00898 PACK( 1, 0 ),
00899 PACK( 1, 0 ),
00900 PACK( 0, 0 ),
00901 PACK( 2, 0 ),
00902 PACK( 2, 0 ),
00903 PACK( 0, 0 ),
00904 PACK( 0, 0 ),
00905 PACK( 2, 0 ),
00906 PACK( 2, 0 ),
00907
00908 PACK( 0, 0 ),
00909 PACK( 0, 0 ),
00910 PACK( 2, 0 ),
00911 PACK( 1, 1 ),
00912 PACK( 2, 0 ),
00913 PACK( 1, 1 ),
00914 PACK( 1, 1 ),
00915 PACK( 1, 1 ),
00916 PACK( 2, 0 ),
00917 PACK( 2, 1 ),
00918 PACK( 2, 1 ),
00919 PACK( 0, 1 ),
00920 PACK( 0, 1 ),
00921 PACK( 0, 0 ),
00922 PACK( 0, 0 ),
00923 PACK( 1, 0 ),
00924
00925 PACK( 2, 1 ),
00926 PACK( 2, 1 ),
00927 PACK( 2, 1 ),
00928 PACK( 2, 1 ),
00929 PACK( 2, 1 ),
00930 PACK( 2, 1 ),
00931 PACK( 1, 1 ),
00932 PACK( 1, 1 ),
00933 PACK( 1, 0 ),
00934 PACK( 0, 0 ),
00935 PACK( 2, 1 ),
00936 PACK( 2, 1 ),
00937 PACK( 1, 1 ),
00938 PACK( 1, 0 ),
00939 PACK( 1, 0 ),
00940 PACK( 1, 0 ),
00941
00942 PACK( 2, 1 ),
00943 PACK( 2, 1 ),
00944 PACK( 2, 1 ),
00945 PACK( 2, 1 ),
00946 PACK( 1, 1 ),
00947 PACK( 1, 1 ),
00948 PACK( 1, 1 ),
00949 PACK( 1, 1 ),
00950 PACK( 1, 1 ),
00951 PACK( 1, 1 ),
00952 PACK( 1, 1 ),
00953 PACK( 1, 1 ),
00954 PACK( 1, 1 ),
00955 PACK( 1, 1 ),
00956 PACK( 1, 1 ),
00957 PACK( 1, 1 ),
00958
00959 PACK( 2, 0 ),
00960 PACK( 1, 0 ),
00961 PACK( 1, 0 ),
00962 PACK( 1, 0 ),
00963 PACK( 1, 0 ),
00964 PACK( 1, 0 ),
00965 PACK( 1, 0 ),
00966 PACK( 1, 0 ),
00967 PACK( 2, 0 ),
00968 PACK( 2, 0 ),
00969 PACK( 0, 0 ),
00970 PACK( 0, 0 ),
00971 PACK( 0, 0 ),
00972 PACK( 0, 0 ),
00973 PACK( 1, 0 ),
00974 PACK( 1, 0 ),
00975
00976 PACK( 0, 0 ),
00977 PACK( 2, 0 ),
00978 PACK( 2, 0 ),
00979 PACK( 0, 0 ),
00980 PACK( 0, 0 ),
00981 PACK( 1, 0 ),
00982 PACK( 2, 0 ),
00983 PACK( 2, 0 ),
00984 PACK( 1, 1 ),
00985 PACK( 1, 0 ),
00986 PACK( 3, 3 ),
00987 PACK( 2, 1 ),
00988 PACK( 2, 1 ),
00989 PACK( 1, 0 ),
00990 PACK( 2, 0 ),
00991 PACK( 0, 0 ),
00992
00993 PACK( 0, 0 ),
00994 PACK( 0, 0 ),
00995 PACK( 0, 0 ),
00996 PACK( 0, 0 ),
00997 PACK( 0, 0 ),
00998 PACK( 0, 0 ),
00999 PACK( 0, 0 ),
01000 PACK( 0, 0 ),
01001 PACK( 0, 0 ),
01002 PACK( 0, 0 ),
01003 PACK( 0, 0 ),
01004 PACK( 0, 0 ),
01005 PACK( 0, 0 ),
01006 PACK( 0, 0 ),
01007 PACK( 0, 0 ),
01008 PACK( 0, 0 ),
01009
01010 PACK( 0, 0 ),
01011 PACK( 0, 0 ),
01012 PACK( 0, 0 ),
01013 PACK( 0, 0 ),
01014 PACK( 0, 0 ),
01015 PACK( 0, 0 ),
01016 PACK( 0, 0 ),
01017 PACK( 0, 0 ),
01018 PACK( 0, 0 ),
01019 PACK( 0, 0 ),
01020 PACK( 0, 0 ),
01021 PACK( 0, 0 ),
01022 PACK( 0, 0 ),
01023 PACK( 0, 0 ),
01024 PACK( 0, 0 ),
01025 PACK( 0, 0 ),
01026
01027 PACK( 0, 1 ),
01028 PACK( 0, 2 ),
01029 PACK( 0, 3 ),
01030 PACK( 0, 4 ),
01031 PACK( 0, 5 ),
01032 PACK( 0, 6 ),
01033 PACK( 0, 7 ),
01034 PACK( 0, 8 ),
01035 PACK( 0, 1 ),
01036 PACK( 0, 2 ),
01037 PACK( 0, 3 ),
01038 PACK( 0, 4 ),
01039 PACK( 0, 5 ),
01040 PACK( 0, 6 ),
01041 PACK( 0, 7 ),
01042 PACK( 0, 8 ),
01043
01044 PACK( 1, 0 ),
01045 PACK( 1, 0 ),
01046 PACK( 1, 0 ),
01047 PACK( 1, 0 ),
01048 PACK( 1, 0 ),
01049 PACK( 1, 0 ),
01050 PACK( 1, 0 ),
01051 PACK( 1, 0 ),
01052 PACK( 1, 0 ),
01053 PACK( 1, 0 ),
01054 PACK( 1, 0 ),
01055 PACK( 1, 0 ),
01056 PACK( 1, 0 ),
01057 PACK( 1, 0 ),
01058 PACK( 1, 0 ),
01059 PACK( 1, 0 ),
01060
01061 PACK( 1, 0 ),
01062 PACK( 1, 0 ),
01063 PACK( 1, 0 ),
01064 PACK( 1, 0 ),
01065 PACK( 1, 0 ),
01066 PACK( 1, 0 ),
01067 PACK( 1, 0 ),
01068 PACK( 1, 0 ),
01069 PACK( 1, 0 ),
01070 PACK( 1, 0 ),
01071 PACK( 1, 0 ),
01072 PACK( 1, 0 ),
01073 PACK( 1, 0 ),
01074 PACK( 1, 0 ),
01075 PACK( 1, 0 ),
01076 PACK( 1, 0 ),
01077
01078 PACK( 2, 0 ),
01079 PACK( 2, 0 ),
01080 PACK( 2, 0 ),
01081 PACK( 2, 0 ),
01082 PACK( 2, 0 ),
01083 PACK( 2, 0 ),
01084 PACK( 2, 0 ),
01085 PACK( 2, 0 ),
01086 PACK( 2, 0 ),
01087 PACK( 2, 0 ),
01088 PACK( 2, 0 ),
01089 PACK( 2, 0 ),
01090 PACK( 2, 0 ),
01091 PACK( 2, 0 ),
01092 PACK( 2, 0 ),
01093 PACK( 2, 0 ),
01094
01095 PACK( 2, 0 ),
01096 PACK( 2, 0 ),
01097 PACK( 2, 0 ),
01098 PACK( 2, 0 ),
01099 PACK( 2, 0 ),
01100 PACK( 2, 0 ),
01101 PACK( 2, 0 ),
01102 PACK( 2, 0 ),
01103 PACK( 2, 0 ),
01104 PACK( 2, 0 ),
01105 PACK( 2, 0 ),
01106 PACK( 2, 0 ),
01107 PACK( 2, 0 ),
01108 PACK( 2, 0 ),
01109 PACK( 2, 0 ),
01110 PACK( 2, 0 )
01111 };
01112
01113
01114 static
01115 const FT_Char opcode_length[256] =
01116 {
01117 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
01118 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
01119 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
01120 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
01121
01122 -1,-2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
01123 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
01124 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
01125 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
01126
01127 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
01128 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
01129 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
01130 2, 3, 4, 5, 6, 7, 8, 9, 3, 5, 7, 9, 11,13,15,17,
01131
01132 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
01133 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
01134 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
01135 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
01136 };
01137
01138 #undef PACK
01139
01140 #if 1
01141
01142 static FT_Int32
01143 TT_MulFix14( FT_Int32 a,
01144 FT_Int b )
01145 {
01146 FT_Int32 sign;
01147 FT_UInt32 ah, al, mid, lo, hi;
01148
01149
01150 sign = a ^ b;
01151
01152 if ( a < 0 )
01153 a = -a;
01154 if ( b < 0 )
01155 b = -b;
01156
01157 ah = (FT_UInt32)( ( a >> 16 ) & 0xFFFFU );
01158 al = (FT_UInt32)( a & 0xFFFFU );
01159
01160 lo = al * b;
01161 mid = ah * b;
01162 hi = mid >> 16;
01163 mid = ( mid << 16 ) + ( 1 << 13 );
01164 lo += mid;
01165 if ( lo < mid )
01166 hi += 1;
01167
01168 mid = ( lo >> 14 ) | ( hi << 18 );
01169
01170 return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid;
01171 }
01172
01173 #else
01174
01175
01176 static FT_Int32
01177 TT_MulFix14( FT_Int32 a,
01178 FT_Int b )
01179 {
01180 FT_Int32 m, s, hi;
01181 FT_UInt32 l, lo;
01182
01183
01184
01185 l = (FT_UInt32)( ( a & 0xFFFFU ) * b );
01186 m = ( a >> 16 ) * b;
01187
01188 lo = l + (FT_UInt32)( m << 16 );
01189 hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l );
01190
01191
01192 s = hi >> 31;
01193 l = lo + (FT_UInt32)s;
01194 hi += s + ( l < lo );
01195 lo = l;
01196
01197 l = lo + 0x2000U;
01198 hi += l < lo;
01199
01200 return ( hi << 18 ) | ( l >> 14 );
01201 }
01202 #endif
01203
01204
01205
01206 static FT_Int32
01207 TT_DotFix14( FT_Int32 ax,
01208 FT_Int32 ay,
01209 FT_Int bx,
01210 FT_Int by )
01211 {
01212 FT_Int32 m, s, hi1, hi2, hi;
01213 FT_UInt32 l, lo1, lo2, lo;
01214
01215
01216
01217 l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx );
01218 m = ( ax >> 16 ) * bx;
01219
01220 lo1 = l + (FT_UInt32)( m << 16 );
01221 hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l );
01222
01223
01224 l = (FT_UInt32)( ( ay & 0xFFFFU ) * by );
01225 m = ( ay >> 16 ) * by;
01226
01227 lo2 = l + (FT_UInt32)( m << 16 );
01228 hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l );
01229
01230
01231 lo = lo1 + lo2;
01232 hi = hi1 + hi2 + ( lo < lo1 );
01233
01234
01235 s = hi >> 31;
01236 l = lo + (FT_UInt32)s;
01237 hi += s + ( l < lo );
01238 lo = l;
01239
01240 l = lo + 0x2000U;
01241 hi += ( l < lo );
01242
01243 return ( hi << 18 ) | ( l >> 14 );
01244 }
01245
01246
01247
01248
01249 #if 0
01250
01251 static FT_Int32
01252 TT_VecLen( FT_Int32 x,
01253 FT_Int32 y )
01254 {
01255 FT_Int32 m, hi1, hi2, hi;
01256 FT_UInt32 l, lo1, lo2, lo;
01257
01258
01259
01260 lo = (FT_UInt32)( x & 0xFFFFU );
01261 hi = x >> 16;
01262
01263 l = lo * lo;
01264 m = hi * lo;
01265 hi = hi * hi;
01266
01267 lo1 = l + (FT_UInt32)( m << 17 );
01268 hi1 = hi + ( m >> 15 ) + ( lo1 < l );
01269
01270
01271 lo = (FT_UInt32)( y & 0xFFFFU );
01272 hi = y >> 16;
01273
01274 l = lo * lo;
01275 m = hi * lo;
01276 hi = hi * hi;
01277
01278 lo2 = l + (FT_UInt32)( m << 17 );
01279 hi2 = hi + ( m >> 15 ) + ( lo2 < l );
01280
01281
01282 lo = lo1 + lo2;
01283 hi = hi1 + hi2 + ( lo < lo1 );
01284
01285
01286 {
01287 FT_UInt32 root, rem, test_div;
01288 FT_Int count;
01289
01290
01291 root = 0;
01292
01293 {
01294 rem = 0;
01295 count = 32;
01296 do
01297 {
01298 rem = ( rem << 2 ) | ( (FT_UInt32)hi >> 30 );
01299 hi = ( hi << 2 ) | ( lo >> 30 );
01300 lo <<= 2;
01301 root <<= 1;
01302 test_div = ( root << 1 ) + 1;
01303
01304 if ( rem >= test_div )
01305 {
01306 rem -= test_div;
01307 root += 1;
01308 }
01309 } while ( --count );
01310 }
01311
01312 return (FT_Int32)root;
01313 }
01314 }
01315
01316 #else
01317
01318
01319
01320
01321 static FT_F26Dot6
01322 TT_VecLen( FT_F26Dot6 X,
01323 FT_F26Dot6 Y )
01324 {
01325 FT_Vector v;
01326
01327
01328 v.x = X;
01329 v.y = Y;
01330
01331 return FT_Vector_Length( &v );
01332 }
01333
01334 #endif
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349 static FT_Long
01350 Current_Ratio( EXEC_OP )
01351 {
01352 if ( !CUR.tt_metrics.ratio )
01353 {
01354 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
01355 if ( CUR.face->unpatented_hinting )
01356 {
01357 if ( CUR.GS.both_x_axis )
01358 CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
01359 else
01360 CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
01361 }
01362 else
01363 #endif
01364 {
01365 if ( CUR.GS.projVector.y == 0 )
01366 CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
01367
01368 else if ( CUR.GS.projVector.x == 0 )
01369 CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
01370
01371 else
01372 {
01373 FT_Long x, y;
01374
01375
01376 x = TT_MULDIV( CUR.GS.projVector.x,
01377 CUR.tt_metrics.x_ratio, 0x4000 );
01378 y = TT_MULDIV( CUR.GS.projVector.y,
01379 CUR.tt_metrics.y_ratio, 0x4000 );
01380 CUR.tt_metrics.ratio = TT_VecLen( x, y );
01381 }
01382 }
01383 }
01384 return CUR.tt_metrics.ratio;
01385 }
01386
01387
01388 static FT_Long
01389 Current_Ppem( EXEC_OP )
01390 {
01391 return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() );
01392 }
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402 FT_CALLBACK_DEF( FT_F26Dot6 )
01403 Read_CVT( EXEC_OP_ FT_ULong idx )
01404 {
01405 return CUR.cvt[idx];
01406 }
01407
01408
01409 FT_CALLBACK_DEF( FT_F26Dot6 )
01410 Read_CVT_Stretched( EXEC_OP_ FT_ULong idx )
01411 {
01412 return TT_MULFIX( CUR.cvt[idx], CURRENT_Ratio() );
01413 }
01414
01415
01416 FT_CALLBACK_DEF( void )
01417 Write_CVT( EXEC_OP_ FT_ULong idx,
01418 FT_F26Dot6 value )
01419 {
01420 CUR.cvt[idx] = value;
01421 }
01422
01423
01424 FT_CALLBACK_DEF( void )
01425 Write_CVT_Stretched( EXEC_OP_ FT_ULong idx,
01426 FT_F26Dot6 value )
01427 {
01428 CUR.cvt[idx] = FT_DivFix( value, CURRENT_Ratio() );
01429 }
01430
01431
01432 FT_CALLBACK_DEF( void )
01433 Move_CVT( EXEC_OP_ FT_ULong idx,
01434 FT_F26Dot6 value )
01435 {
01436 CUR.cvt[idx] += value;
01437 }
01438
01439
01440 FT_CALLBACK_DEF( void )
01441 Move_CVT_Stretched( EXEC_OP_ FT_ULong idx,
01442 FT_F26Dot6 value )
01443 {
01444 CUR.cvt[idx] += FT_DivFix( value, CURRENT_Ratio() );
01445 }
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463 static FT_Short
01464 GetShortIns( EXEC_OP )
01465 {
01466
01467 CUR.IP += 2;
01468 return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) +
01469 CUR.code[CUR.IP - 1] );
01470 }
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489 static FT_Bool
01490 Ins_Goto_CodeRange( EXEC_OP_ FT_Int aRange,
01491 FT_ULong aIP )
01492 {
01493 TT_CodeRange* range;
01494
01495
01496 if ( aRange < 1 || aRange > 3 )
01497 {
01498 CUR.error = TT_Err_Bad_Argument;
01499 return FAILURE;
01500 }
01501
01502 range = &CUR.codeRangeTable[aRange - 1];
01503
01504 if ( range->base == NULL )
01505 {
01506 CUR.error = TT_Err_Invalid_CodeRange;
01507 return FAILURE;
01508 }
01509
01510
01511
01512
01513
01514 if ( aIP > range->size )
01515 {
01516 CUR.error = TT_Err_Code_Overflow;
01517 return FAILURE;
01518 }
01519
01520 CUR.code = range->base;
01521 CUR.codeSize = range->size;
01522 CUR.IP = aIP;
01523 CUR.curRange = aRange;
01524
01525 return SUCCESS;
01526 }
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546 static void
01547 Direct_Move( EXEC_OP_ TT_GlyphZone zone,
01548 FT_UShort point,
01549 FT_F26Dot6 distance )
01550 {
01551 FT_F26Dot6 v;
01552
01553
01554 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
01555 FT_ASSERT( !CUR.face->unpatented_hinting );
01556 #endif
01557
01558 v = CUR.GS.freeVector.x;
01559
01560 if ( v != 0 )
01561 {
01562 zone->cur[point].x += TT_MULDIV( distance,
01563 v * 0x10000L,
01564 CUR.F_dot_P );
01565
01566 zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
01567 }
01568
01569 v = CUR.GS.freeVector.y;
01570
01571 if ( v != 0 )
01572 {
01573 zone->cur[point].y += TT_MULDIV( distance,
01574 v * 0x10000L,
01575 CUR.F_dot_P );
01576
01577 zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
01578 }
01579 }
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599 static void
01600 Direct_Move_Orig( EXEC_OP_ TT_GlyphZone zone,
01601 FT_UShort point,
01602 FT_F26Dot6 distance )
01603 {
01604 FT_F26Dot6 v;
01605
01606
01607 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
01608 FT_ASSERT( !CUR.face->unpatented_hinting );
01609 #endif
01610
01611 v = CUR.GS.freeVector.x;
01612
01613 if ( v != 0 )
01614 zone->org[point].x += TT_MULDIV( distance,
01615 v * 0x10000L,
01616 CUR.F_dot_P );
01617
01618 v = CUR.GS.freeVector.y;
01619
01620 if ( v != 0 )
01621 zone->org[point].y += TT_MULDIV( distance,
01622 v * 0x10000L,
01623 CUR.F_dot_P );
01624 }
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637 static void
01638 Direct_Move_X( EXEC_OP_ TT_GlyphZone zone,
01639 FT_UShort point,
01640 FT_F26Dot6 distance )
01641 {
01642 FT_UNUSED_EXEC;
01643
01644 zone->cur[point].x += distance;
01645 zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
01646 }
01647
01648
01649 static void
01650 Direct_Move_Y( EXEC_OP_ TT_GlyphZone zone,
01651 FT_UShort point,
01652 FT_F26Dot6 distance )
01653 {
01654 FT_UNUSED_EXEC;
01655
01656 zone->cur[point].y += distance;
01657 zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
01658 }
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671 static void
01672 Direct_Move_Orig_X( EXEC_OP_ TT_GlyphZone zone,
01673 FT_UShort point,
01674 FT_F26Dot6 distance )
01675 {
01676 FT_UNUSED_EXEC;
01677
01678 zone->org[point].x += distance;
01679 }
01680
01681
01682 static void
01683 Direct_Move_Orig_Y( EXEC_OP_ TT_GlyphZone zone,
01684 FT_UShort point,
01685 FT_F26Dot6 distance )
01686 {
01687 FT_UNUSED_EXEC;
01688
01689 zone->org[point].y += distance;
01690 }
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715 static FT_F26Dot6
01716 Round_None( EXEC_OP_ FT_F26Dot6 distance,
01717 FT_F26Dot6 compensation )
01718 {
01719 FT_F26Dot6 val;
01720
01721 FT_UNUSED_EXEC;
01722
01723
01724 if ( distance >= 0 )
01725 {
01726 val = distance + compensation;
01727 if ( distance && val < 0 )
01728 val = 0;
01729 }
01730 else {
01731 val = distance - compensation;
01732 if ( val > 0 )
01733 val = 0;
01734 }
01735 return val;
01736 }
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755 static FT_F26Dot6
01756 Round_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
01757 FT_F26Dot6 compensation )
01758 {
01759 FT_F26Dot6 val;
01760
01761 FT_UNUSED_EXEC;
01762
01763
01764 if ( distance >= 0 )
01765 {
01766 val = distance + compensation + 32;
01767 if ( distance && val > 0 )
01768 val &= ~63;
01769 else
01770 val = 0;
01771 }
01772 else
01773 {
01774 val = -FT_PIX_ROUND( compensation - distance );
01775 if ( val > 0 )
01776 val = 0;
01777 }
01778
01779 return val;
01780 }
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799 static FT_F26Dot6
01800 Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6 distance,
01801 FT_F26Dot6 compensation )
01802 {
01803 FT_F26Dot6 val;
01804
01805 FT_UNUSED_EXEC;
01806
01807
01808 if ( distance >= 0 )
01809 {
01810 val = FT_PIX_FLOOR( distance + compensation ) + 32;
01811 if ( distance && val < 0 )
01812 val = 0;
01813 }
01814 else
01815 {
01816 val = -( FT_PIX_FLOOR( compensation - distance ) + 32 );
01817 if ( val > 0 )
01818 val = 0;
01819 }
01820
01821 return val;
01822 }
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841 static FT_F26Dot6
01842 Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
01843 FT_F26Dot6 compensation )
01844 {
01845 FT_F26Dot6 val;
01846
01847 FT_UNUSED_EXEC;
01848
01849
01850 if ( distance >= 0 )
01851 {
01852 val = distance + compensation;
01853 if ( distance && val > 0 )
01854 val &= ~63;
01855 else
01856 val = 0;
01857 }
01858 else
01859 {
01860 val = -( ( compensation - distance ) & -64 );
01861 if ( val > 0 )
01862 val = 0;
01863 }
01864
01865 return val;
01866 }
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885 static FT_F26Dot6
01886 Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
01887 FT_F26Dot6 compensation )
01888 {
01889 FT_F26Dot6 val;
01890
01891 FT_UNUSED_EXEC;
01892
01893
01894 if ( distance >= 0 )
01895 {
01896 val = distance + compensation + 63;
01897 if ( distance && val > 0 )
01898 val &= ~63;
01899 else
01900 val = 0;
01901 }
01902 else
01903 {
01904 val = - FT_PIX_CEIL( compensation - distance );
01905 if ( val > 0 )
01906 val = 0;
01907 }
01908
01909 return val;
01910 }
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929 static FT_F26Dot6
01930 Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6 distance,
01931 FT_F26Dot6 compensation )
01932 {
01933 FT_F26Dot6 val;
01934
01935 FT_UNUSED_EXEC;
01936
01937
01938 if ( distance >= 0 )
01939 {
01940 val = distance + compensation + 16;
01941 if ( distance && val > 0 )
01942 val &= ~31;
01943 else
01944 val = 0;
01945 }
01946 else
01947 {
01948 val = -FT_PAD_ROUND( compensation - distance, 32 );
01949 if ( val > 0 )
01950 val = 0;
01951 }
01952
01953 return val;
01954 }
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979 static FT_F26Dot6
01980 Round_Super( EXEC_OP_ FT_F26Dot6 distance,
01981 FT_F26Dot6 compensation )
01982 {
01983 FT_F26Dot6 val;
01984
01985
01986 if ( distance >= 0 )
01987 {
01988 val = ( distance - CUR.phase + CUR.threshold + compensation ) &
01989 -CUR.period;
01990 if ( distance && val < 0 )
01991 val = 0;
01992 val += CUR.phase;
01993 }
01994 else
01995 {
01996 val = -( ( CUR.threshold - CUR.phase - distance + compensation ) &
01997 -CUR.period );
01998 if ( val > 0 )
01999 val = 0;
02000 val -= CUR.phase;
02001 }
02002
02003 return val;
02004 }
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027 static FT_F26Dot6
02028 Round_Super_45( EXEC_OP_ FT_F26Dot6 distance,
02029 FT_F26Dot6 compensation )
02030 {
02031 FT_F26Dot6 val;
02032
02033
02034 if ( distance >= 0 )
02035 {
02036 val = ( ( distance - CUR.phase + CUR.threshold + compensation ) /
02037 CUR.period ) * CUR.period;
02038 if ( distance && val < 0 )
02039 val = 0;
02040 val += CUR.phase;
02041 }
02042 else
02043 {
02044 val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) /
02045 CUR.period ) * CUR.period );
02046 if ( val > 0 )
02047 val = 0;
02048 val -= CUR.phase;
02049 }
02050
02051 return val;
02052 }
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066 static void
02067 Compute_Round( EXEC_OP_ FT_Byte round_mode )
02068 {
02069 switch ( round_mode )
02070 {
02071 case TT_Round_Off:
02072 CUR.func_round = (TT_Round_Func)Round_None;
02073 break;
02074
02075 case TT_Round_To_Grid:
02076 CUR.func_round = (TT_Round_Func)Round_To_Grid;
02077 break;
02078
02079 case TT_Round_Up_To_Grid:
02080 CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
02081 break;
02082
02083 case TT_Round_Down_To_Grid:
02084 CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
02085 break;
02086
02087 case TT_Round_To_Half_Grid:
02088 CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
02089 break;
02090
02091 case TT_Round_To_Double_Grid:
02092 CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
02093 break;
02094
02095 case TT_Round_Super:
02096 CUR.func_round = (TT_Round_Func)Round_Super;
02097 break;
02098
02099 case TT_Round_Super_45:
02100 CUR.func_round = (TT_Round_Func)Round_Super_45;
02101 break;
02102 }
02103 }
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118 static void
02119 SetSuperRound( EXEC_OP_ FT_F26Dot6 GridPeriod,
02120 FT_Long selector )
02121 {
02122 switch ( (FT_Int)( selector & 0xC0 ) )
02123 {
02124 case 0:
02125 CUR.period = GridPeriod / 2;
02126 break;
02127
02128 case 0x40:
02129 CUR.period = GridPeriod;
02130 break;
02131
02132 case 0x80:
02133 CUR.period = GridPeriod * 2;
02134 break;
02135
02136
02137
02138 case 0xC0:
02139 CUR.period = GridPeriod;
02140 break;
02141 }
02142
02143 switch ( (FT_Int)( selector & 0x30 ) )
02144 {
02145 case 0:
02146 CUR.phase = 0;
02147 break;
02148
02149 case 0x10:
02150 CUR.phase = CUR.period / 4;
02151 break;
02152
02153 case 0x20:
02154 CUR.phase = CUR.period / 2;
02155 break;
02156
02157 case 0x30:
02158 CUR.phase = CUR.period * 3 / 4;
02159 break;
02160 }
02161
02162 if ( ( selector & 0x0F ) == 0 )
02163 CUR.threshold = CUR.period - 1;
02164 else
02165 CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8;
02166
02167 CUR.period /= 256;
02168 CUR.phase /= 256;
02169 CUR.threshold /= 256;
02170 }
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189 static FT_F26Dot6
02190 Project( EXEC_OP_ FT_Pos dx,
02191 FT_Pos dy )
02192 {
02193 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
02194 FT_ASSERT( !CUR.face->unpatented_hinting );
02195 #endif
02196
02197 return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,
02198 CUR.GS.projVector.x,
02199 CUR.GS.projVector.y );
02200 }
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219 static FT_F26Dot6
02220 Dual_Project( EXEC_OP_ FT_Pos dx,
02221 FT_Pos dy )
02222 {
02223 return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,
02224 CUR.GS.dualVector.x,
02225 CUR.GS.dualVector.y );
02226 }
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245 static FT_F26Dot6
02246 Project_x( EXEC_OP_ FT_Pos dx,
02247 FT_Pos dy )
02248 {
02249 FT_UNUSED_EXEC;
02250 FT_UNUSED( dy );
02251
02252 return dx;
02253 }
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272 static FT_F26Dot6
02273 Project_y( EXEC_OP_ FT_Pos dx,
02274 FT_Pos dy )
02275 {
02276 FT_UNUSED_EXEC;
02277 FT_UNUSED( dx );
02278
02279 return dy;
02280 }
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292 static void
02293 Compute_Funcs( EXEC_OP )
02294 {
02295 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
02296 if ( CUR.face->unpatented_hinting )
02297 {
02298
02299
02300
02301
02302 CUR.GS.both_x_axis = (FT_Bool)( CUR.GS.projVector.x == 0x4000 &&
02303 CUR.GS.freeVector.x == 0x4000 );
02304
02305
02306
02307
02308 CUR.GS.projVector.x = 0;
02309 CUR.GS.projVector.y = 0;
02310 CUR.GS.freeVector.x = 0;
02311 CUR.GS.freeVector.y = 0;
02312
02313 if ( CUR.GS.both_x_axis )
02314 {
02315 CUR.func_project = Project_x;
02316 CUR.func_move = Direct_Move_X;
02317 CUR.func_move_orig = Direct_Move_Orig_X;
02318 }
02319 else
02320 {
02321 CUR.func_project = Project_y;
02322 CUR.func_move = Direct_Move_Y;
02323 CUR.func_move_orig = Direct_Move_Orig_Y;
02324 }
02325
02326 if ( CUR.GS.dualVector.x == 0x4000 )
02327 CUR.func_dualproj = Project_x;
02328 else
02329 {
02330 if ( CUR.GS.dualVector.y == 0x4000 )
02331 CUR.func_dualproj = Project_y;
02332 else
02333 CUR.func_dualproj = Dual_Project;
02334 }
02335
02336
02337 CUR.tt_metrics.ratio = 0;
02338
02339 return;
02340 }
02341 #endif
02342
02343 if ( CUR.GS.freeVector.x == 0x4000 )
02344 CUR.F_dot_P = CUR.GS.projVector.x * 0x10000L;
02345 else
02346 {
02347 if ( CUR.GS.freeVector.y == 0x4000 )
02348 CUR.F_dot_P = CUR.GS.projVector.y * 0x10000L;
02349 else
02350 CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 +
02351 (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4;
02352 }
02353
02354 if ( CUR.GS.projVector.x == 0x4000 )
02355 CUR.func_project = (TT_Project_Func)Project_x;
02356 else
02357 {
02358 if ( CUR.GS.projVector.y == 0x4000 )
02359 CUR.func_project = (TT_Project_Func)Project_y;
02360 else
02361 CUR.func_project = (TT_Project_Func)Project;
02362 }
02363
02364 if ( CUR.GS.dualVector.x == 0x4000 )
02365 CUR.func_dualproj = (TT_Project_Func)Project_x;
02366 else
02367 {
02368 if ( CUR.GS.dualVector.y == 0x4000 )
02369 CUR.func_dualproj = (TT_Project_Func)Project_y;
02370 else
02371 CUR.func_dualproj = (TT_Project_Func)Dual_Project;
02372 }
02373
02374 CUR.func_move = (TT_Move_Func)Direct_Move;
02375 CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig;
02376
02377 if ( CUR.F_dot_P == 0x40000000L )
02378 {
02379 if ( CUR.GS.freeVector.x == 0x4000 )
02380 {
02381 CUR.func_move = (TT_Move_Func)Direct_Move_X;
02382 CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
02383 }
02384 else
02385 {
02386 if ( CUR.GS.freeVector.y == 0x4000 )
02387 {
02388 CUR.func_move = (TT_Move_Func)Direct_Move_Y;
02389 CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
02390 }
02391 }
02392 }
02393
02394
02395
02396
02397 if ( FT_ABS( CUR.F_dot_P ) < 0x4000000L )
02398 CUR.F_dot_P = 0x40000000L;
02399
02400
02401 CUR.tt_metrics.ratio = 0;
02402 }
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429 static FT_Bool
02430 Normalize( EXEC_OP_ FT_F26Dot6 Vx,
02431 FT_F26Dot6 Vy,
02432 FT_UnitVector* R )
02433 {
02434 FT_F26Dot6 W;
02435 FT_Bool S1, S2;
02436
02437 FT_UNUSED_EXEC;
02438
02439
02440 if ( FT_ABS( Vx ) < 0x10000L && FT_ABS( Vy ) < 0x10000L )
02441 {
02442 Vx *= 0x100;
02443 Vy *= 0x100;
02444
02445 W = TT_VecLen( Vx, Vy );
02446
02447 if ( W == 0 )
02448 {
02449
02450
02451 return SUCCESS;
02452 }
02453
02454 R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W );
02455 R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W );
02456
02457 return SUCCESS;
02458 }
02459
02460 W = TT_VecLen( Vx, Vy );
02461
02462 Vx = FT_MulDiv( Vx, 0x4000L, W );
02463 Vy = FT_MulDiv( Vy, 0x4000L, W );
02464
02465 W = Vx * Vx + Vy * Vy;
02466
02467
02468
02469
02470 if ( Vx < 0 )
02471 {
02472 Vx = -Vx;
02473 S1 = TRUE;
02474 }
02475 else
02476 S1 = FALSE;
02477
02478 if ( Vy < 0 )
02479 {
02480 Vy = -Vy;
02481 S2 = TRUE;
02482 }
02483 else
02484 S2 = FALSE;
02485
02486 while ( W < 0x10000000L )
02487 {
02488
02489 if ( Vx < Vy )
02490 Vx++;
02491 else
02492 Vy++;
02493
02494 W = Vx * Vx + Vy * Vy;
02495 }
02496
02497 while ( W >= 0x10004000L )
02498 {
02499
02500 if ( Vx < Vy )
02501 Vx--;
02502 else
02503 Vy--;
02504
02505 W = Vx * Vx + Vy * Vy;
02506 }
02507
02508
02509
02510
02511 if ( S1 )
02512 Vx = -Vx;
02513
02514 if ( S2 )
02515 Vy = -Vy;
02516
02517 R->x = (FT_F2Dot14)Vx;
02518 R->y = (FT_F2Dot14)Vy;
02519
02520 return SUCCESS;
02521 }
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531 static FT_Bool
02532 Ins_SxVTL( EXEC_OP_ FT_UShort aIdx1,
02533 FT_UShort aIdx2,
02534 FT_Int aOpc,
02535 FT_UnitVector* Vec )
02536 {
02537 FT_Long A, B, C;
02538 FT_Vector* p1;
02539 FT_Vector* p2;
02540
02541
02542 if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||
02543 BOUNDS( aIdx2, CUR.zp1.n_points ) )
02544 {
02545 if ( CUR.pedantic_hinting )
02546 CUR.error = TT_Err_Invalid_Reference;
02547 return FAILURE;
02548 }
02549
02550 p1 = CUR.zp1.cur + aIdx2;
02551 p2 = CUR.zp2.cur + aIdx1;
02552
02553 A = p1->x - p2->x;
02554 B = p1->y - p2->y;
02555
02556 if ( ( aOpc & 1 ) != 0 )
02557 {
02558 C = B;
02559 B = A;
02560 A = -C;
02561 }
02562
02563 NORMalize( A, B, Vec );
02564
02565 return SUCCESS;
02566 }
02567
02568
02569
02570
02571
02572
02573
02574
02575 #define DO_SVTCA \
02576 { \
02577 FT_Short A, B; \
02578 \
02579 \
02580 A = (FT_Short)( CUR.opcode & 1 ) << 14; \
02581 B = A ^ (FT_Short)0x4000; \
02582 \
02583 CUR.GS.freeVector.x = A; \
02584 CUR.GS.projVector.x = A; \
02585 CUR.GS.dualVector.x = A; \
02586 \
02587 CUR.GS.freeVector.y = B; \
02588 CUR.GS.projVector.y = B; \
02589 CUR.GS.dualVector.y = B; \
02590 \
02591 COMPUTE_Funcs(); \
02592 }
02593
02594
02595 #define DO_SPVTCA \
02596 { \
02597 FT_Short A, B; \
02598 \
02599 \
02600 A = (FT_Short)( CUR.opcode & 1 ) << 14; \
02601 B = A ^ (FT_Short)0x4000; \
02602 \
02603 CUR.GS.projVector.x = A; \
02604 CUR.GS.dualVector.x = A; \
02605 \
02606 CUR.GS.projVector.y = B; \
02607 CUR.GS.dualVector.y = B; \
02608 \
02609 GUESS_VECTOR( freeVector ); \
02610 \
02611 COMPUTE_Funcs(); \
02612 }
02613
02614
02615 #define DO_SFVTCA \
02616 { \
02617 FT_Short A, B; \
02618 \
02619 \
02620 A = (FT_Short)( CUR.opcode & 1 ) << 14; \
02621 B = A ^ (FT_Short)0x4000; \
02622 \
02623 CUR.GS.freeVector.x = A; \
02624 CUR.GS.freeVector.y = B; \
02625 \
02626 GUESS_VECTOR( projVector ); \
02627 \
02628 COMPUTE_Funcs(); \
02629 }
02630
02631
02632 #define DO_SPVTL \
02633 if ( INS_SxVTL( (FT_UShort)args[1], \
02634 (FT_UShort)args[0], \
02635 CUR.opcode, \
02636 &CUR.GS.projVector ) == SUCCESS ) \
02637 { \
02638 CUR.GS.dualVector = CUR.GS.projVector; \
02639 GUESS_VECTOR( freeVector ); \
02640 COMPUTE_Funcs(); \
02641 }
02642
02643
02644 #define DO_SFVTL \
02645 if ( INS_SxVTL( (FT_UShort)args[1], \
02646 (FT_UShort)args[0], \
02647 CUR.opcode, \
02648 &CUR.GS.freeVector ) == SUCCESS ) \
02649 { \
02650 GUESS_VECTOR( projVector ); \
02651 COMPUTE_Funcs(); \
02652 }
02653
02654
02655 #define DO_SFVTPV \
02656 GUESS_VECTOR( projVector ); \
02657 CUR.GS.freeVector = CUR.GS.projVector; \
02658 COMPUTE_Funcs();
02659
02660
02661 #define DO_SPVFS \
02662 { \
02663 FT_Short S; \
02664 FT_Long X, Y; \
02665 \
02666 \
02667 \
02668 S = (FT_Short)args[1]; \
02669 Y = (FT_Long)S; \
02670 S = (FT_Short)args[0]; \
02671 X = (FT_Long)S; \
02672 \
02673 NORMalize( X, Y, &CUR.GS.projVector ); \
02674 \
02675 CUR.GS.dualVector = CUR.GS.projVector; \
02676 GUESS_VECTOR( freeVector ); \
02677 COMPUTE_Funcs(); \
02678 }
02679
02680
02681 #define DO_SFVFS \
02682 { \
02683 FT_Short S; \
02684 FT_Long X, Y; \
02685 \
02686 \
02687 \
02688 S = (FT_Short)args[1]; \
02689 Y = (FT_Long)S; \
02690 S = (FT_Short)args[0]; \
02691 X = S; \
02692 \
02693 NORMalize( X, Y, &CUR.GS.freeVector ); \
02694 GUESS_VECTOR( projVector ); \
02695 COMPUTE_Funcs(); \
02696 }
02697
02698
02699 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
02700 #define DO_GPV \
02701 if ( CUR.face->unpatented_hinting ) \
02702 { \
02703 args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
02704 args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
02705 } \
02706 else \
02707 { \
02708 args[0] = CUR.GS.projVector.x; \
02709 args[1] = CUR.GS.projVector.y; \
02710 }
02711 #else
02712 #define DO_GPV \
02713 args[0] = CUR.GS.projVector.x; \
02714 args[1] = CUR.GS.projVector.y;
02715 #endif
02716
02717
02718 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
02719 #define DO_GFV \
02720 if ( CUR.face->unpatented_hinting ) \
02721 { \
02722 args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
02723 args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
02724 } \
02725 else \
02726 { \
02727 args[0] = CUR.GS.freeVector.x; \
02728 args[1] = CUR.GS.freeVector.y; \
02729 }
02730 #else
02731 #define DO_GFV \
02732 args[0] = CUR.GS.freeVector.x; \
02733 args[1] = CUR.GS.freeVector.y;
02734 #endif
02735
02736
02737 #define DO_SRP0 \
02738 CUR.GS.rp0 = (FT_UShort)args[0];
02739
02740
02741 #define DO_SRP1 \
02742 CUR.GS.rp1 = (FT_UShort)args[0];
02743
02744
02745 #define DO_SRP2 \
02746 CUR.GS.rp2 = (FT_UShort)args[0];
02747
02748
02749 #define DO_RTHG \
02750 CUR.GS.round_state = TT_Round_To_Half_Grid; \
02751 CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
02752
02753
02754 #define DO_RTG \
02755 CUR.GS.round_state = TT_Round_To_Grid; \
02756 CUR.func_round = (TT_Round_Func)Round_To_Grid;
02757
02758
02759 #define DO_RTDG \
02760 CUR.GS.round_state = TT_Round_To_Double_Grid; \
02761 CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
02762
02763
02764 #define DO_RUTG \
02765 CUR.GS.round_state = TT_Round_Up_To_Grid; \
02766 CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
02767
02768
02769 #define DO_RDTG \
02770 CUR.GS.round_state = TT_Round_Down_To_Grid; \
02771 CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
02772
02773
02774 #define DO_ROFF \
02775 CUR.GS.round_state = TT_Round_Off; \
02776 CUR.func_round = (TT_Round_Func)Round_None;
02777
02778
02779 #define DO_SROUND \
02780 SET_SuperRound( 0x4000, args[0] ); \
02781 CUR.GS.round_state = TT_Round_Super; \
02782 CUR.func_round = (TT_Round_Func)Round_Super;
02783
02784
02785 #define DO_S45ROUND \
02786 SET_SuperRound( 0x2D41, args[0] ); \
02787 CUR.GS.round_state = TT_Round_Super_45; \
02788 CUR.func_round = (TT_Round_Func)Round_Super_45;
02789
02790
02791 #define DO_SLOOP \
02792 if ( args[0] < 0 ) \
02793 CUR.error = TT_Err_Bad_Argument; \
02794 else \
02795 CUR.GS.loop = args[0];
02796
02797
02798 #define DO_SMD \
02799 CUR.GS.minimum_distance = args[0];
02800
02801
02802 #define DO_SCVTCI \
02803 CUR.GS.control_value_cutin = (FT_F26Dot6)args[0];
02804
02805
02806 #define DO_SSWCI \
02807 CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];
02808
02809
02810
02811
02812
02813
02814
02815
02816 #define DO_SSW \
02817 CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 );
02818
02819
02820 #define DO_FLIPON \
02821 CUR.GS.auto_flip = TRUE;
02822
02823
02824 #define DO_FLIPOFF \
02825 CUR.GS.auto_flip = FALSE;
02826
02827
02828 #define DO_SDB \
02829 CUR.GS.delta_base = (FT_Short)args[0];
02830
02831
02832 #define DO_SDS \
02833 CUR.GS.delta_shift = (FT_Short)args[0];
02834
02835
02836 #define DO_MD
02837
02838
02839 #define DO_MPPEM \
02840 args[0] = CURRENT_Ppem();
02841
02842
02843
02844
02845 #if 0
02846
02847 #define DO_MPS \
02848 args[0] = CUR.metrics.pointSize;
02849
02850 #else
02851
02852 #define DO_MPS \
02853 args[0] = CURRENT_Ppem();
02854
02855 #endif
02856
02857
02858 #define DO_DUP \
02859 args[1] = args[0];
02860
02861
02862 #define DO_CLEAR \
02863 CUR.new_top = 0;
02864
02865
02866 #define DO_SWAP \
02867 { \
02868 FT_Long L; \
02869 \
02870 \
02871 L = args[0]; \
02872 args[0] = args[1]; \
02873 args[1] = L; \
02874 }
02875
02876
02877 #define DO_DEPTH \
02878 args[0] = CUR.top;
02879
02880
02881 #define DO_CINDEX \
02882 { \
02883 FT_Long L; \
02884 \
02885 \
02886 L = args[0]; \
02887 \
02888 if ( L <= 0 || L > CUR.args ) \
02889 CUR.error = TT_Err_Invalid_Reference; \
02890 else \
02891 args[0] = CUR.stack[CUR.args - L]; \
02892 }
02893
02894
02895 #define DO_JROT \
02896 if ( args[1] != 0 ) \
02897 { \
02898 CUR.IP += args[0]; \
02899 CUR.step_ins = FALSE; \
02900 }
02901
02902
02903 #define DO_JMPR \
02904 CUR.IP += args[0]; \
02905 CUR.step_ins = FALSE;
02906
02907
02908 #define DO_JROF \
02909 if ( args[1] == 0 ) \
02910 { \
02911 CUR.IP += args[0]; \
02912 CUR.step_ins = FALSE; \
02913 }
02914
02915
02916 #define DO_LT \
02917 args[0] = ( args[0] < args[1] );
02918
02919
02920 #define DO_LTEQ \
02921 args[0] = ( args[0] <= args[1] );
02922
02923
02924 #define DO_GT \
02925 args[0] = ( args[0] > args[1] );
02926
02927
02928 #define DO_GTEQ \
02929 args[0] = ( args[0] >= args[1] );
02930
02931
02932 #define DO_EQ \
02933 args[0] = ( args[0] == args[1] );
02934
02935
02936 #define DO_NEQ \
02937 args[0] = ( args[0] != args[1] );
02938
02939
02940 #define DO_ODD \
02941 args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 );
02942
02943
02944 #define DO_EVEN \
02945 args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 );
02946
02947
02948 #define DO_AND \
02949 args[0] = ( args[0] && args[1] );
02950
02951
02952 #define DO_OR \
02953 args[0] = ( args[0] || args[1] );
02954
02955
02956 #define DO_NOT \
02957 args[0] = !args[0];
02958
02959
02960 #define DO_ADD \
02961 args[0] += args[1];
02962
02963
02964 #define DO_SUB \
02965 args[0] -= args[1];
02966
02967
02968 #define DO_DIV \
02969 if ( args[1] == 0 ) \
02970 CUR.error = TT_Err_Divide_By_Zero; \
02971 else \
02972 args[0] = TT_MULDIV_NO_ROUND( args[0], 64L, args[1] );
02973
02974
02975 #define DO_MUL \
02976 args[0] = TT_MULDIV( args[0], args[1], 64L );
02977
02978
02979 #define DO_ABS \
02980 args[0] = FT_ABS( args[0] );
02981
02982
02983 #define DO_NEG \
02984 args[0] = -args[0];
02985
02986
02987 #define DO_FLOOR \
02988 args[0] = FT_PIX_FLOOR( args[0] );
02989
02990
02991 #define DO_CEILING \
02992 args[0] = FT_PIX_CEIL( args[0] );
02993
02994
02995 #define DO_RS \
02996 { \
02997 FT_ULong I = (FT_ULong)args[0]; \
02998 \
02999 \
03000 if ( BOUNDS( I, CUR.storeSize ) ) \
03001 { \
03002 if ( CUR.pedantic_hinting ) \
03003 { \
03004 ARRAY_BOUND_ERROR; \
03005 } \
03006 else \
03007 args[0] = 0; \
03008 } \
03009 else \
03010 args[0] = CUR.storage[I]; \
03011 }
03012
03013
03014 #define DO_WS \
03015 { \
03016 FT_ULong I = (FT_ULong)args[0]; \
03017 \
03018 \
03019 if ( BOUNDS( I, CUR.storeSize ) ) \
03020 { \
03021 if ( CUR.pedantic_hinting ) \
03022 { \
03023 ARRAY_BOUND_ERROR; \
03024 } \
03025 } \
03026 else \
03027 CUR.storage[I] = args[1]; \
03028 }
03029
03030
03031 #define DO_RCVT \
03032 { \
03033 FT_ULong I = (FT_ULong)args[0]; \
03034 \
03035 \
03036 if ( BOUNDS( I, CUR.cvtSize ) ) \
03037 { \
03038 if ( CUR.pedantic_hinting ) \
03039 { \
03040 ARRAY_BOUND_ERROR; \
03041 } \
03042 else \
03043 args[0] = 0; \
03044 } \
03045 else \
03046 args[0] = CUR_Func_read_cvt( I ); \
03047 }
03048
03049
03050 #define DO_WCVTP \
03051 { \
03052 FT_ULong I = (FT_ULong)args[0]; \
03053 \
03054 \
03055 if ( BOUNDS( I, CUR.cvtSize ) ) \
03056 { \
03057 if ( CUR.pedantic_hinting ) \
03058 { \
03059 ARRAY_BOUND_ERROR; \
03060 } \
03061 } \
03062 else \
03063 CUR_Func_write_cvt( I, args[1] ); \
03064 }
03065
03066
03067 #define DO_WCVTF \
03068 { \
03069 FT_ULong I = (FT_ULong)args[0]; \
03070 \
03071 \
03072 if ( BOUNDS( I, CUR.cvtSize ) ) \
03073 { \
03074 if ( CUR.pedantic_hinting ) \
03075 { \
03076 ARRAY_BOUND_ERROR; \
03077 } \
03078 } \
03079 else \
03080 CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \
03081 }
03082
03083
03084 #define DO_DEBUG \
03085 CUR.error = TT_Err_Debug_OpCode;
03086
03087
03088 #define DO_ROUND \
03089 args[0] = CUR_Func_round( \
03090 args[0], \
03091 CUR.tt_metrics.compensations[CUR.opcode - 0x68] );
03092
03093
03094 #define DO_NROUND \
03095 args[0] = ROUND_None( args[0], \
03096 CUR.tt_metrics.compensations[CUR.opcode - 0x6C] );
03097
03098
03099 #define DO_MAX \
03100 if ( args[1] > args[0] ) \
03101 args[0] = args[1];
03102
03103
03104 #define DO_MIN \
03105 if ( args[1] < args[0] ) \
03106 args[0] = args[1];
03107
03108
03109 #ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
03110
03111
03112 #undef ARRAY_BOUND_ERROR
03113 #define ARRAY_BOUND_ERROR \
03114 { \
03115 CUR.error = TT_Err_Invalid_Reference; \
03116 return; \
03117 }
03118
03119
03120
03121
03122
03123
03124
03125
03126 static void
03127 Ins_SVTCA( INS_ARG )
03128 {
03129 DO_SVTCA
03130 }
03131
03132
03133
03134
03135
03136
03137
03138
03139 static void
03140 Ins_SPVTCA( INS_ARG )
03141 {
03142 DO_SPVTCA
03143 }
03144
03145
03146
03147
03148
03149
03150
03151
03152 static void
03153 Ins_SFVTCA( INS_ARG )
03154 {
03155 DO_SFVTCA
03156 }
03157
03158
03159
03160
03161
03162
03163
03164
03165 static void
03166 Ins_SPVTL( INS_ARG )
03167 {
03168 DO_SPVTL
03169 }
03170
03171
03172
03173
03174
03175
03176
03177
03178 static void
03179 Ins_SFVTL( INS_ARG )
03180 {
03181 DO_SFVTL
03182 }
03183
03184
03185
03186
03187
03188
03189
03190
03191 static void
03192 Ins_SFVTPV( INS_ARG )
03193 {
03194 DO_SFVTPV
03195 }
03196
03197
03198
03199
03200
03201
03202
03203
03204 static void
03205 Ins_SPVFS( INS_ARG )
03206 {
03207 DO_SPVFS
03208 }
03209
03210
03211
03212
03213
03214
03215
03216
03217 static void
03218 Ins_SFVFS( INS_ARG )
03219 {
03220 DO_SFVFS
03221 }
03222
03223
03224
03225
03226
03227
03228
03229
03230 static void
03231 Ins_GPV( INS_ARG )
03232 {
03233 DO_GPV
03234 }
03235
03236
03237
03238
03239
03240
03241
03242 static void
03243 Ins_GFV( INS_ARG )
03244 {
03245 DO_GFV
03246 }
03247
03248
03249
03250
03251
03252
03253
03254
03255 static void
03256 Ins_SRP0( INS_ARG )
03257 {
03258 DO_SRP0
03259 }
03260
03261
03262
03263
03264
03265
03266
03267
03268 static void
03269 Ins_SRP1( INS_ARG )
03270 {
03271 DO_SRP1
03272 }
03273
03274
03275
03276
03277
03278
03279
03280
03281 static void
03282 Ins_SRP2( INS_ARG )
03283 {
03284 DO_SRP2
03285 }
03286
03287
03288
03289
03290
03291
03292
03293
03294 static void
03295 Ins_RTHG( INS_ARG )
03296 {
03297 DO_RTHG
03298 }
03299
03300
03301
03302
03303
03304
03305
03306
03307 static void
03308 Ins_RTG( INS_ARG )
03309 {
03310 DO_RTG
03311 }
03312
03313
03314
03315
03316
03317
03318
03319 static void
03320 Ins_RTDG( INS_ARG )
03321 {
03322 DO_RTDG
03323 }
03324
03325
03326
03327
03328
03329
03330
03331 static void
03332 Ins_RUTG( INS_ARG )
03333 {
03334 DO_RUTG
03335 }
03336
03337
03338
03339
03340
03341
03342
03343
03344 static void
03345 Ins_RDTG( INS_ARG )
03346 {
03347 DO_RDTG
03348 }
03349
03350
03351
03352
03353
03354
03355
03356
03357 static void
03358 Ins_ROFF( INS_ARG )
03359 {
03360 DO_ROFF
03361 }
03362
03363
03364
03365
03366
03367
03368
03369
03370 static void
03371 Ins_SROUND( INS_ARG )
03372 {
03373 DO_SROUND
03374 }
03375
03376
03377
03378
03379
03380
03381
03382
03383 static void
03384 Ins_S45ROUND( INS_ARG )
03385 {
03386 DO_S45ROUND
03387 }
03388
03389
03390
03391
03392
03393
03394
03395
03396 static void
03397 Ins_SLOOP( INS_ARG )
03398 {
03399 DO_SLOOP
03400 }
03401
03402
03403
03404
03405
03406
03407
03408
03409 static void
03410 Ins_SMD( INS_ARG )
03411 {
03412 DO_SMD
03413 }
03414
03415
03416
03417
03418
03419
03420
03421
03422 static void
03423 Ins_SCVTCI( INS_ARG )
03424 {
03425 DO_SCVTCI
03426 }
03427
03428
03429
03430
03431
03432
03433
03434
03435 static void
03436 Ins_SSWCI( INS_ARG )
03437 {
03438 DO_SSWCI
03439 }
03440
03441
03442
03443
03444
03445
03446
03447
03448 static void
03449 Ins_SSW( INS_ARG )
03450 {
03451 DO_SSW
03452 }
03453
03454
03455
03456
03457
03458
03459
03460
03461 static void
03462 Ins_FLIPON( INS_ARG )
03463 {
03464 DO_FLIPON
03465 }
03466
03467
03468
03469
03470
03471
03472
03473
03474 static void
03475 Ins_FLIPOFF( INS_ARG )
03476 {
03477 DO_FLIPOFF
03478 }
03479
03480
03481
03482
03483
03484
03485
03486
03487 static void
03488 Ins_SANGW( INS_ARG )
03489 {
03490
03491 }
03492
03493
03494
03495
03496
03497
03498
03499
03500 static void
03501 Ins_SDB( INS_ARG )
03502 {
03503 DO_SDB
03504 }
03505
03506
03507
03508
03509
03510
03511
03512
03513 static void
03514 Ins_SDS( INS_ARG )
03515 {
03516 DO_SDS
03517 }
03518
03519
03520
03521
03522
03523
03524
03525
03526 static void
03527 Ins_MPPEM( INS_ARG )
03528 {
03529 DO_MPPEM
03530 }
03531
03532
03533
03534
03535
03536
03537
03538
03539 static void
03540 Ins_MPS( INS_ARG )
03541 {
03542 DO_MPS
03543 }
03544
03545
03546
03547
03548
03549
03550
03551
03552 static void
03553 Ins_DUP( INS_ARG )
03554 {
03555 DO_DUP
03556 }
03557
03558
03559
03560
03561
03562
03563
03564
03565 static void
03566 Ins_POP( INS_ARG )
03567 {
03568
03569 }
03570
03571
03572
03573
03574
03575
03576
03577
03578 static void
03579 Ins_CLEAR( INS_ARG )
03580 {
03581 DO_CLEAR
03582 }
03583
03584
03585
03586
03587
03588
03589
03590
03591 static void
03592 Ins_SWAP( INS_ARG )
03593 {
03594 DO_SWAP
03595 }
03596
03597
03598
03599
03600
03601
03602
03603
03604 static void
03605 Ins_DEPTH( INS_ARG )
03606 {
03607 DO_DEPTH
03608 }
03609
03610
03611
03612
03613
03614
03615
03616
03617 static void
03618 Ins_CINDEX( INS_ARG )
03619 {
03620 DO_CINDEX
03621 }
03622
03623
03624
03625
03626
03627
03628
03629
03630 static void
03631 Ins_EIF( INS_ARG )
03632 {
03633
03634 }
03635
03636
03637
03638
03639
03640
03641
03642
03643 static void
03644 Ins_JROT( INS_ARG )
03645 {
03646 DO_JROT
03647 }
03648
03649
03650
03651
03652
03653
03654
03655
03656 static void
03657 Ins_JMPR( INS_ARG )
03658 {
03659 DO_JMPR
03660 }
03661
03662
03663
03664
03665
03666
03667
03668
03669 static void
03670 Ins_JROF( INS_ARG )
03671 {
03672 DO_JROF
03673 }
03674
03675
03676
03677
03678
03679
03680
03681
03682 static void
03683 Ins_LT( INS_ARG )
03684 {
03685 DO_LT
03686 }
03687
03688
03689
03690
03691
03692
03693
03694
03695 static void
03696 Ins_LTEQ( INS_ARG )
03697 {
03698 DO_LTEQ
03699 }
03700
03701
03702
03703
03704
03705
03706
03707
03708 static void
03709 Ins_GT( INS_ARG )
03710 {
03711 DO_GT
03712 }
03713
03714
03715
03716
03717
03718
03719
03720
03721 static void
03722 Ins_GTEQ( INS_ARG )
03723 {
03724 DO_GTEQ
03725 }
03726
03727
03728
03729
03730
03731
03732
03733
03734 static void
03735 Ins_EQ( INS_ARG )
03736 {
03737 DO_EQ
03738 }
03739
03740
03741
03742
03743
03744
03745
03746
03747 static void
03748 Ins_NEQ( INS_ARG )
03749 {
03750 DO_NEQ
03751 }
03752
03753
03754
03755
03756
03757
03758
03759
03760 static void
03761 Ins_ODD( INS_ARG )
03762 {
03763 DO_ODD
03764 }
03765
03766
03767
03768
03769
03770
03771
03772
03773 static void
03774 Ins_EVEN( INS_ARG )
03775 {
03776 DO_EVEN
03777 }
03778
03779
03780
03781
03782
03783
03784
03785
03786 static void
03787 Ins_AND( INS_ARG )
03788 {
03789 DO_AND
03790 }
03791
03792
03793
03794
03795
03796
03797
03798
03799 static void
03800 Ins_OR( INS_ARG )
03801 {
03802 DO_OR
03803 }
03804
03805
03806
03807
03808
03809
03810
03811
03812 static void
03813 Ins_NOT( INS_ARG )
03814 {
03815 DO_NOT
03816 }
03817
03818
03819
03820
03821
03822
03823
03824
03825 static void
03826 Ins_ADD( INS_ARG )
03827 {
03828 DO_ADD
03829 }
03830
03831
03832
03833
03834
03835
03836
03837
03838 static void
03839 Ins_SUB( INS_ARG )
03840 {
03841 DO_SUB
03842 }
03843
03844
03845
03846
03847
03848
03849
03850
03851 static void
03852 Ins_DIV( INS_ARG )
03853 {
03854 DO_DIV
03855 }
03856
03857
03858
03859
03860
03861
03862
03863
03864 static void
03865 Ins_MUL( INS_ARG )
03866 {
03867 DO_MUL
03868 }
03869
03870
03871
03872
03873
03874
03875
03876
03877 static void
03878 Ins_ABS( INS_ARG )
03879 {
03880 DO_ABS
03881 }
03882
03883
03884
03885
03886
03887
03888
03889
03890 static void
03891 Ins_NEG( INS_ARG )
03892 {
03893 DO_NEG
03894 }
03895
03896
03897
03898
03899
03900
03901
03902
03903 static void
03904 Ins_FLOOR( INS_ARG )
03905 {
03906 DO_FLOOR
03907 }
03908
03909
03910
03911
03912
03913
03914
03915
03916 static void
03917 Ins_CEILING( INS_ARG )
03918 {
03919 DO_CEILING
03920 }
03921
03922
03923
03924
03925
03926
03927
03928
03929 static void
03930 Ins_RS( INS_ARG )
03931 {
03932 DO_RS
03933 }
03934
03935
03936
03937
03938
03939
03940
03941
03942 static void
03943 Ins_WS( INS_ARG )
03944 {
03945 DO_WS
03946 }
03947
03948
03949
03950
03951
03952
03953
03954
03955 static void
03956 Ins_WCVTP( INS_ARG )
03957 {
03958 DO_WCVTP
03959 }
03960
03961
03962
03963
03964
03965
03966
03967
03968 static void
03969 Ins_WCVTF( INS_ARG )
03970 {
03971 DO_WCVTF
03972 }
03973
03974
03975
03976
03977
03978
03979
03980
03981 static void
03982 Ins_RCVT( INS_ARG )
03983 {
03984 DO_RCVT
03985 }
03986
03987
03988
03989
03990
03991
03992
03993
03994 static void
03995 Ins_AA( INS_ARG )
03996 {
03997
03998 }
03999
04000
04001
04002
04003
04004
04005
04006
04007
04008
04009 static void
04010 Ins_DEBUG( INS_ARG )
04011 {
04012 DO_DEBUG
04013 }
04014
04015
04016
04017
04018
04019
04020
04021
04022 static void
04023 Ins_ROUND( INS_ARG )
04024 {
04025 DO_ROUND
04026 }
04027
04028
04029
04030
04031
04032
04033
04034
04035 static void
04036 Ins_NROUND( INS_ARG )
04037 {
04038 DO_NROUND
04039 }
04040
04041
04042
04043
04044
04045
04046
04047
04048 static void
04049 Ins_MAX( INS_ARG )
04050 {
04051 DO_MAX
04052 }
04053
04054
04055
04056
04057
04058
04059
04060
04061 static void
04062 Ins_MIN( INS_ARG )
04063 {
04064 DO_MIN
04065 }
04066
04067
04068 #endif
04069
04070
04071
04072
04073
04074
04075
04076
04077
04078
04079
04080
04081
04082
04083
04084 static void
04085 Ins_MINDEX( INS_ARG )
04086 {
04087 FT_Long L, K;
04088
04089
04090 L = args[0];
04091
04092 if ( L <= 0 || L > CUR.args )
04093 {
04094 CUR.error = TT_Err_Invalid_Reference;
04095 return;
04096 }
04097
04098 K = CUR.stack[CUR.args - L];
04099
04100 FT_ARRAY_MOVE( &CUR.stack[CUR.args - L ],
04101 &CUR.stack[CUR.args - L + 1],
04102 ( L - 1 ) );
04103
04104 CUR.stack[CUR.args - 1] = K;
04105 }
04106
04107
04108
04109
04110
04111
04112
04113
04114 static void
04115 Ins_ROLL( INS_ARG )
04116 {
04117 FT_Long A, B, C;
04118
04119 FT_UNUSED_EXEC;
04120
04121
04122 A = args[2];
04123 B = args[1];
04124 C = args[0];
04125
04126 args[2] = C;
04127 args[1] = A;
04128 args[0] = B;
04129 }
04130
04131
04132
04133
04134
04135
04136
04137
04138
04139
04140
04141 static FT_Bool
04142 SkipCode( EXEC_OP )
04143 {
04144 CUR.IP += CUR.length;
04145
04146 if ( CUR.IP < CUR.codeSize )
04147 {
04148 CUR.opcode = CUR.code[CUR.IP];
04149
04150 CUR.length = opcode_length[CUR.opcode];
04151 if ( CUR.length < 0 )
04152 {
04153 if ( CUR.IP + 1 > CUR.codeSize )
04154 goto Fail_Overflow;
04155 CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
04156 }
04157
04158 if ( CUR.IP + CUR.length <= CUR.codeSize )
04159 return SUCCESS;
04160 }
04161
04162 Fail_Overflow:
04163 CUR.error = TT_Err_Code_Overflow;
04164 return FAILURE;
04165 }
04166
04167
04168
04169
04170
04171
04172
04173
04174 static void
04175 Ins_IF( INS_ARG )
04176 {
04177 FT_Int nIfs;
04178 FT_Bool Out;
04179
04180
04181 if ( args[0] != 0 )
04182 return;
04183
04184 nIfs = 1;
04185 Out = 0;
04186
04187 do
04188 {
04189 if ( SKIP_Code() == FAILURE )
04190 return;
04191
04192 switch ( CUR.opcode )
04193 {
04194 case 0x58:
04195 nIfs++;
04196 break;
04197
04198 case 0x1B:
04199 Out = FT_BOOL( nIfs == 1 );
04200 break;
04201
04202 case 0x59:
04203 nIfs--;
04204 Out = FT_BOOL( nIfs == 0 );
04205 break;
04206 }
04207 } while ( Out == 0 );
04208 }
04209
04210
04211
04212
04213
04214
04215
04216
04217 static void
04218 Ins_ELSE( INS_ARG )
04219 {
04220 FT_Int nIfs;
04221
04222 FT_UNUSED_ARG;
04223
04224
04225 nIfs = 1;
04226
04227 do
04228 {
04229 if ( SKIP_Code() == FAILURE )
04230 return;
04231
04232 switch ( CUR.opcode )
04233 {
04234 case 0x58:
04235 nIfs++;
04236 break;
04237
04238 case 0x59:
04239 nIfs--;
04240 break;
04241 }
04242 } while ( nIfs != 0 );
04243 }
04244
04245
04246
04247
04248
04249
04250
04251
04252
04253
04254
04255
04256
04257
04258
04259
04260
04261 static void
04262 Ins_FDEF( INS_ARG )
04263 {
04264 FT_ULong n;
04265 TT_DefRecord* rec;
04266 TT_DefRecord* limit;
04267
04268
04269
04270
04271
04272 rec = CUR.FDefs;
04273 limit = rec + CUR.numFDefs;
04274 n = args[0];
04275
04276 for ( ; rec < limit; rec++ )
04277 {
04278 if ( rec->opc == n )
04279 break;
04280 }
04281
04282 if ( rec == limit )
04283 {
04284
04285 if ( CUR.numFDefs >= CUR.maxFDefs )
04286 {
04287 CUR.error = TT_Err_Too_Many_Function_Defs;
04288 return;
04289 }
04290 CUR.numFDefs++;
04291 }
04292
04293
04294
04295 if ( n > 0xFFFFU )
04296 {
04297 CUR.error = TT_Err_Too_Many_Function_Defs;
04298 return;
04299 }
04300
04301 rec->range = CUR.curRange;
04302 rec->opc = (FT_UInt16)n;
04303 rec->start = CUR.IP + 1;
04304 rec->active = TRUE;
04305
04306 if ( n > CUR.maxFunc )
04307 CUR.maxFunc = (FT_UInt16)n;
04308
04309
04310
04311
04312 while ( SKIP_Code() == SUCCESS )
04313 {
04314 switch ( CUR.opcode )
04315 {
04316 case 0x89:
04317 case 0x2C:
04318 CUR.error = TT_Err_Nested_DEFS;
04319 return;
04320
04321 case 0x2D:
04322 return;
04323 }
04324 }
04325 }
04326
04327
04328
04329
04330
04331
04332
04333
04334 static void
04335 Ins_ENDF( INS_ARG )
04336 {
04337 TT_CallRec* pRec;
04338
04339 FT_UNUSED_ARG;
04340
04341
04342 if ( CUR.callTop <= 0 )
04343 {
04344 CUR.error = TT_Err_ENDF_In_Exec_Stream;
04345 return;
04346 }
04347
04348 CUR.callTop--;
04349
04350 pRec = &CUR.callStack[CUR.callTop];
04351
04352 pRec->Cur_Count--;
04353
04354 CUR.step_ins = FALSE;
04355
04356 if ( pRec->Cur_Count > 0 )
04357 {
04358 CUR.callTop++;
04359 CUR.IP = pRec->Cur_Restart;
04360 }
04361 else
04362
04363 INS_Goto_CodeRange( pRec->Caller_Range,
04364 pRec->Caller_IP );
04365
04366
04367
04368
04369
04370
04371
04372
04373 }
04374
04375
04376
04377
04378
04379
04380
04381
04382 static void
04383 Ins_CALL( INS_ARG )
04384 {
04385 FT_ULong F;
04386 TT_CallRec* pCrec;
04387 TT_DefRecord* def;
04388
04389
04390
04391
04392 F = args[0];
04393 if ( BOUNDS( F, CUR.maxFunc + 1 ) )
04394 goto Fail;
04395
04396
04397
04398
04399
04400
04401
04402
04403
04404
04405 def = CUR.FDefs + F;
04406 if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
04407 {
04408
04409 TT_DefRecord* limit;
04410
04411
04412 def = CUR.FDefs;
04413 limit = def + CUR.numFDefs;
04414
04415 while ( def < limit && def->opc != F )
04416 def++;
04417
04418 if ( def == limit )
04419 goto Fail;
04420 }
04421
04422
04423 if ( !def->active )
04424 goto Fail;
04425
04426
04427 if ( CUR.callTop >= CUR.callSize )
04428 {
04429 CUR.error = TT_Err_Stack_Overflow;
04430 return;
04431 }
04432
04433 pCrec = CUR.callStack + CUR.callTop;
04434
04435 pCrec->Caller_Range = CUR.curRange;
04436 pCrec->Caller_IP = CUR.IP + 1;
04437 pCrec->Cur_Count = 1;
04438 pCrec->Cur_Restart = def->start;
04439
04440 CUR.callTop++;
04441
04442 INS_Goto_CodeRange( def->range,
04443 def->start );
04444
04445 CUR.step_ins = FALSE;
04446 return;
04447
04448 Fail:
04449 CUR.error = TT_Err_Invalid_Reference;
04450 }
04451
04452
04453
04454
04455
04456
04457
04458
04459 static void
04460 Ins_LOOPCALL( INS_ARG )
04461 {
04462 FT_ULong F;
04463 TT_CallRec* pCrec;
04464 TT_DefRecord* def;
04465
04466
04467
04468 F = args[1];
04469 if ( BOUNDS( F, CUR.maxFunc + 1 ) )
04470 goto Fail;
04471
04472
04473
04474
04475
04476
04477
04478
04479
04480
04481 def = CUR.FDefs + F;
04482 if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
04483 {
04484
04485 TT_DefRecord* limit;
04486
04487
04488 def = CUR.FDefs;
04489 limit = def + CUR.numFDefs;
04490
04491 while ( def < limit && def->opc != F )
04492 def++;
04493
04494 if ( def == limit )
04495 goto Fail;
04496 }
04497
04498
04499 if ( !def->active )
04500 goto Fail;
04501
04502
04503 if ( CUR.callTop >= CUR.callSize )
04504 {
04505 CUR.error = TT_Err_Stack_Overflow;
04506 return;
04507 }
04508
04509 if ( args[0] > 0 )
04510 {
04511 pCrec = CUR.callStack + CUR.callTop;
04512
04513 pCrec->Caller_Range = CUR.curRange;
04514 pCrec->Caller_IP = CUR.IP + 1;
04515 pCrec->Cur_Count = (FT_Int)args[0];
04516 pCrec->Cur_Restart = def->start;
04517
04518 CUR.callTop++;
04519
04520 INS_Goto_CodeRange( def->range, def->start );
04521
04522 CUR.step_ins = FALSE;
04523 }
04524 return;
04525
04526 Fail:
04527 CUR.error = TT_Err_Invalid_Reference;
04528 }
04529
04530
04531
04532
04533
04534
04535
04536
04537 static void
04538 Ins_IDEF( INS_ARG )
04539 {
04540 TT_DefRecord* def;
04541 TT_DefRecord* limit;
04542
04543
04544
04545
04546 def = CUR.IDefs;
04547 limit = def + CUR.numIDefs;
04548
04549 for ( ; def < limit; def++ )
04550 if ( def->opc == (FT_ULong)args[0] )
04551 break;
04552
04553 if ( def == limit )
04554 {
04555
04556 if ( CUR.numIDefs >= CUR.maxIDefs )
04557 {
04558 CUR.error = TT_Err_Too_Many_Instruction_Defs;
04559 return;
04560 }
04561 CUR.numIDefs++;
04562 }
04563
04564
04565 if ( 0 > args[0] || args[0] > 0x00FF )
04566 {
04567 CUR.error = TT_Err_Too_Many_Instruction_Defs;
04568 return;
04569 }
04570
04571 def->opc = (FT_Byte)args[0];
04572 def->start = CUR.IP+1;
04573 def->range = CUR.curRange;
04574 def->active = TRUE;
04575
04576 if ( (FT_ULong)args[0] > CUR.maxIns )
04577 CUR.maxIns = (FT_Byte)args[0];
04578
04579
04580
04581
04582 while ( SKIP_Code() == SUCCESS )
04583 {
04584 switch ( CUR.opcode )
04585 {
04586 case 0x89:
04587 case 0x2C:
04588 CUR.error = TT_Err_Nested_DEFS;
04589 return;
04590 case 0x2D:
04591 return;
04592 }
04593 }
04594 }
04595
04596
04597
04598
04599
04600
04601
04602
04603
04604
04605
04606
04607
04608
04609
04610
04611
04612 static void
04613 Ins_NPUSHB( INS_ARG )
04614 {
04615 FT_UShort L, K;
04616
04617
04618 L = (FT_UShort)CUR.code[CUR.IP + 1];
04619
04620 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
04621 {
04622 CUR.error = TT_Err_Stack_Overflow;
04623 return;
04624 }
04625
04626 for ( K = 1; K <= L; K++ )
04627 args[K - 1] = CUR.code[CUR.IP + K + 1];
04628
04629 CUR.new_top += L;
04630 }
04631
04632
04633
04634
04635
04636
04637
04638
04639 static void
04640 Ins_NPUSHW( INS_ARG )
04641 {
04642 FT_UShort L, K;
04643
04644
04645 L = (FT_UShort)CUR.code[CUR.IP + 1];
04646
04647 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
04648 {
04649 CUR.error = TT_Err_Stack_Overflow;
04650 return;
04651 }
04652
04653 CUR.IP += 2;
04654
04655 for ( K = 0; K < L; K++ )
04656 args[K] = GET_ShortIns();
04657
04658 CUR.step_ins = FALSE;
04659 CUR.new_top += L;
04660 }
04661
04662
04663
04664
04665
04666
04667
04668
04669 static void
04670 Ins_PUSHB( INS_ARG )
04671 {
04672 FT_UShort L, K;
04673
04674
04675 L = (FT_UShort)( CUR.opcode - 0xB0 + 1 );
04676
04677 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
04678 {
04679 CUR.error = TT_Err_Stack_Overflow;
04680 return;
04681 }
04682
04683 for ( K = 1; K <= L; K++ )
04684 args[K - 1] = CUR.code[CUR.IP + K];
04685 }
04686
04687
04688
04689
04690
04691
04692
04693
04694 static void
04695 Ins_PUSHW( INS_ARG )
04696 {
04697 FT_UShort L, K;
04698
04699
04700 L = (FT_UShort)( CUR.opcode - 0xB8 + 1 );
04701
04702 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
04703 {
04704 CUR.error = TT_Err_Stack_Overflow;
04705 return;
04706 }
04707
04708 CUR.IP++;
04709
04710 for ( K = 0; K < L; K++ )
04711 args[K] = GET_ShortIns();
04712
04713 CUR.step_ins = FALSE;
04714 }
04715
04716
04717
04718
04719
04720
04721
04722
04723
04724
04725
04726
04727
04728
04729
04730
04731
04732
04733
04734
04735 static void
04736 Ins_GC( INS_ARG )
04737 {
04738 FT_ULong L;
04739 FT_F26Dot6 R;
04740
04741
04742 L = (FT_ULong)args[0];
04743
04744 if ( BOUNDS( L, CUR.zp2.n_points ) )
04745 {
04746 if ( CUR.pedantic_hinting )
04747 {
04748 CUR.error = TT_Err_Invalid_Reference;
04749 return;
04750 }
04751 else
04752 R = 0;
04753 }
04754 else
04755 {
04756 if ( CUR.opcode & 1 )
04757 R = CUR_fast_dualproj( &CUR.zp2.org[L] );
04758 else
04759 R = CUR_fast_project( &CUR.zp2.cur[L] );
04760 }
04761
04762 args[0] = R;
04763 }
04764
04765
04766
04767
04768
04769
04770
04771
04772
04773
04774
04775
04776 static void
04777 Ins_SCFS( INS_ARG )
04778 {
04779 FT_Long K;
04780 FT_UShort L;
04781
04782
04783 L = (FT_UShort)args[0];
04784
04785 if ( BOUNDS( L, CUR.zp2.n_points ) )
04786 {
04787 if ( CUR.pedantic_hinting )
04788 CUR.error = TT_Err_Invalid_Reference;
04789 return;
04790 }
04791
04792 K = CUR_fast_project( &CUR.zp2.cur[L] );
04793
04794 CUR_Func_move( &CUR.zp2, L, args[1] - K );
04795
04796
04797
04798 if ( CUR.GS.gep2 == 0 )
04799 CUR.zp2.org[L] = CUR.zp2.cur[L];
04800 }
04801
04802
04803
04804
04805
04806
04807
04808
04809
04810
04811
04812
04813
04814
04815
04816
04817
04818 static void
04819 Ins_MD( INS_ARG )
04820 {
04821 FT_UShort K, L;
04822 FT_F26Dot6 D;
04823
04824
04825 K = (FT_UShort)args[1];
04826 L = (FT_UShort)args[0];
04827
04828 if( BOUNDS( L, CUR.zp0.n_points ) ||
04829 BOUNDS( K, CUR.zp1.n_points ) )
04830 {
04831 if ( CUR.pedantic_hinting )
04832 {
04833 CUR.error = TT_Err_Invalid_Reference;
04834 return;
04835 }
04836 D = 0;
04837 }
04838 else
04839 {
04840 if ( CUR.opcode & 1 )
04841 D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
04842 else
04843 {
04844 FT_Vector* vec1 = CUR.zp0.orus + L;
04845 FT_Vector* vec2 = CUR.zp1.orus + K;
04846
04847
04848 if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
04849 {
04850
04851 D = CUR_Func_dualproj( vec1, vec2 );
04852 D = TT_MULFIX( D, CUR.metrics.x_scale );
04853 }
04854 else
04855 {
04856 FT_Vector vec;
04857
04858
04859 vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
04860 vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
04861
04862 D = CUR_fast_dualproj( &vec );
04863 }
04864 }
04865 }
04866
04867 args[0] = D;
04868 }
04869
04870
04871
04872
04873
04874
04875
04876
04877 static void
04878 Ins_SDPVTL( INS_ARG )
04879 {
04880 FT_Long A, B, C;
04881 FT_UShort p1, p2;
04882
04883
04884 p1 = (FT_UShort)args[1];
04885 p2 = (FT_UShort)args[0];
04886
04887 if ( BOUNDS( p2, CUR.zp1.n_points ) ||
04888 BOUNDS( p1, CUR.zp2.n_points ) )
04889 {
04890 if ( CUR.pedantic_hinting )
04891 CUR.error = TT_Err_Invalid_Reference;
04892 return;
04893 }
04894
04895 {
04896 FT_Vector* v1 = CUR.zp1.org + p2;
04897 FT_Vector* v2 = CUR.zp2.org + p1;
04898
04899
04900 A = v1->x - v2->x;
04901 B = v1->y - v2->y;
04902 }
04903
04904 if ( ( CUR.opcode & 1 ) != 0 )
04905 {
04906 C = B;
04907 B = A;
04908 A = -C;
04909 }
04910
04911 NORMalize( A, B, &CUR.GS.dualVector );
04912
04913 {
04914 FT_Vector* v1 = CUR.zp1.cur + p2;
04915 FT_Vector* v2 = CUR.zp2.cur + p1;
04916
04917
04918 A = v1->x - v2->x;
04919 B = v1->y - v2->y;
04920 }
04921
04922 if ( ( CUR.opcode & 1 ) != 0 )
04923 {
04924 C = B;
04925 B = A;
04926 A = -C;
04927 }
04928
04929 NORMalize( A, B, &CUR.GS.projVector );
04930
04931 GUESS_VECTOR( freeVector );
04932
04933 COMPUTE_Funcs();
04934 }
04935
04936
04937
04938
04939
04940
04941
04942
04943 static void
04944 Ins_SZP0( INS_ARG )
04945 {
04946 switch ( (FT_Int)args[0] )
04947 {
04948 case 0:
04949 CUR.zp0 = CUR.twilight;
04950 break;
04951
04952 case 1:
04953 CUR.zp0 = CUR.pts;
04954 break;
04955
04956 default:
04957 if ( CUR.pedantic_hinting )
04958 CUR.error = TT_Err_Invalid_Reference;
04959 return;
04960 }
04961
04962 CUR.GS.gep0 = (FT_UShort)args[0];
04963 }
04964
04965
04966
04967
04968
04969
04970
04971
04972 static void
04973 Ins_SZP1( INS_ARG )
04974 {
04975 switch ( (FT_Int)args[0] )
04976 {
04977 case 0:
04978 CUR.zp1 = CUR.twilight;
04979 break;
04980
04981 case 1:
04982 CUR.zp1 = CUR.pts;
04983 break;
04984
04985 default:
04986 if ( CUR.pedantic_hinting )
04987 CUR.error = TT_Err_Invalid_Reference;
04988 return;
04989 }
04990
04991 CUR.GS.gep1 = (FT_UShort)args[0];
04992 }
04993
04994
04995
04996
04997
04998
04999
05000
05001 static void
05002 Ins_SZP2( INS_ARG )
05003 {
05004 switch ( (FT_Int)args[0] )
05005 {
05006 case 0:
05007 CUR.zp2 = CUR.twilight;
05008 break;
05009
05010 case 1:
05011 CUR.zp2 = CUR.pts;
05012 break;
05013
05014 default:
05015 if ( CUR.pedantic_hinting )
05016 CUR.error = TT_Err_Invalid_Reference;
05017 return;
05018 }
05019
05020 CUR.GS.gep2 = (FT_UShort)args[0];
05021 }
05022
05023
05024
05025
05026
05027
05028
05029
05030 static void
05031 Ins_SZPS( INS_ARG )
05032 {
05033 switch ( (FT_Int)args[0] )
05034 {
05035 case 0:
05036 CUR.zp0 = CUR.twilight;
05037 break;
05038
05039 case 1:
05040 CUR.zp0 = CUR.pts;
05041 break;
05042
05043 default:
05044 if ( CUR.pedantic_hinting )
05045 CUR.error = TT_Err_Invalid_Reference;
05046 return;
05047 }
05048
05049 CUR.zp1 = CUR.zp0;
05050 CUR.zp2 = CUR.zp0;
05051
05052 CUR.GS.gep0 = (FT_UShort)args[0];
05053 CUR.GS.gep1 = (FT_UShort)args[0];
05054 CUR.GS.gep2 = (FT_UShort)args[0];
05055 }
05056
05057
05058
05059
05060
05061
05062
05063
05064 static void
05065 Ins_INSTCTRL( INS_ARG )
05066 {
05067 FT_Long K, L;
05068
05069
05070 K = args[1];
05071 L = args[0];
05072
05073 if ( K < 1 || K > 2 )
05074 {
05075 if ( CUR.pedantic_hinting )
05076 CUR.error = TT_Err_Invalid_Reference;
05077 return;
05078 }
05079
05080 if ( L != 0 )
05081 L = K;
05082
05083 CUR.GS.instruct_control = FT_BOOL(
05084 ( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );
05085 }
05086
05087
05088
05089
05090
05091
05092
05093
05094 static void
05095 Ins_SCANCTRL( INS_ARG )
05096 {
05097 FT_Int A;
05098
05099
05100
05101 A = (FT_Int)( args[0] & 0xFF );
05102
05103 if ( A == 0xFF )
05104 {
05105 CUR.GS.scan_control = TRUE;
05106 return;
05107 }
05108 else if ( A == 0 )
05109 {
05110 CUR.GS.scan_control = FALSE;
05111 return;
05112 }
05113
05114 if ( ( args[0] & 0x100 ) != 0 && CUR.tt_metrics.ppem <= A )
05115 CUR.GS.scan_control = TRUE;
05116
05117 if ( ( args[0] & 0x200 ) != 0 && CUR.tt_metrics.rotated )
05118 CUR.GS.scan_control = TRUE;
05119
05120 if ( ( args[0] & 0x400 ) != 0 && CUR.tt_metrics.stretched )
05121 CUR.GS.scan_control = TRUE;
05122
05123 if ( ( args[0] & 0x800 ) != 0 && CUR.tt_metrics.ppem > A )
05124 CUR.GS.scan_control = FALSE;
05125
05126 if ( ( args[0] & 0x1000 ) != 0 && CUR.tt_metrics.rotated )
05127 CUR.GS.scan_control = FALSE;
05128
05129 if ( ( args[0] & 0x2000 ) != 0 && CUR.tt_metrics.stretched )
05130 CUR.GS.scan_control = FALSE;
05131 }
05132
05133
05134
05135
05136
05137
05138
05139
05140 static void
05141 Ins_SCANTYPE( INS_ARG )
05142 {
05143 if ( args[0] >= 0 )
05144 CUR.GS.scan_type = (FT_Int)args[0];
05145 }
05146
05147
05148
05149
05150
05151
05152
05153
05154
05155
05156
05157
05158
05159
05160
05161
05162
05163 static void
05164 Ins_FLIPPT( INS_ARG )
05165 {
05166 FT_UShort point;
05167
05168 FT_UNUSED_ARG;
05169
05170
05171 if ( CUR.top < CUR.GS.loop )
05172 {
05173 CUR.error = TT_Err_Too_Few_Arguments;
05174 return;
05175 }
05176
05177 while ( CUR.GS.loop > 0 )
05178 {
05179 CUR.args--;
05180
05181 point = (FT_UShort)CUR.stack[CUR.args];
05182
05183 if ( BOUNDS( point, CUR.pts.n_points ) )
05184 {
05185 if ( CUR.pedantic_hinting )
05186 {
05187 CUR.error = TT_Err_Invalid_Reference;
05188 return;
05189 }
05190 }
05191 else
05192 CUR.pts.tags[point] ^= FT_CURVE_TAG_ON;
05193
05194 CUR.GS.loop--;
05195 }
05196
05197 CUR.GS.loop = 1;
05198 CUR.new_top = CUR.args;
05199 }
05200
05201
05202
05203
05204
05205
05206
05207
05208 static void
05209 Ins_FLIPRGON( INS_ARG )
05210 {
05211 FT_UShort I, K, L;
05212
05213
05214 K = (FT_UShort)args[1];
05215 L = (FT_UShort)args[0];
05216
05217 if ( BOUNDS( K, CUR.pts.n_points ) ||
05218 BOUNDS( L, CUR.pts.n_points ) )
05219 {
05220 if ( CUR.pedantic_hinting )
05221 CUR.error = TT_Err_Invalid_Reference;
05222 return;
05223 }
05224
05225 for ( I = L; I <= K; I++ )
05226 CUR.pts.tags[I] |= FT_CURVE_TAG_ON;
05227 }
05228
05229
05230
05231
05232
05233
05234
05235
05236 static void
05237 Ins_FLIPRGOFF( INS_ARG )
05238 {
05239 FT_UShort I, K, L;
05240
05241
05242 K = (FT_UShort)args[1];
05243 L = (FT_UShort)args[0];
05244
05245 if ( BOUNDS( K, CUR.pts.n_points ) ||
05246 BOUNDS( L, CUR.pts.n_points ) )
05247 {
05248 if ( CUR.pedantic_hinting )
05249 CUR.error = TT_Err_Invalid_Reference;
05250 return;
05251 }
05252
05253 for ( I = L; I <= K; I++ )
05254 CUR.pts.tags[I] &= ~FT_CURVE_TAG_ON;
05255 }
05256
05257
05258 static FT_Bool
05259 Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6* x,
05260 FT_F26Dot6* y,
05261 TT_GlyphZone zone,
05262 FT_UShort* refp )
05263 {
05264 TT_GlyphZoneRec zp;
05265 FT_UShort p;
05266 FT_F26Dot6 d;
05267
05268
05269 if ( CUR.opcode & 1 )
05270 {
05271 zp = CUR.zp0;
05272 p = CUR.GS.rp1;
05273 }
05274 else
05275 {
05276 zp = CUR.zp1;
05277 p = CUR.GS.rp2;
05278 }
05279
05280 if ( BOUNDS( p, zp.n_points ) )
05281 {
05282 if ( CUR.pedantic_hinting )
05283 CUR.error = TT_Err_Invalid_Reference;
05284 *refp = 0;
05285 return FAILURE;
05286 }
05287
05288 *zone = zp;
05289 *refp = p;
05290
05291 d = CUR_Func_project( zp.cur + p, zp.org + p );
05292
05293 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
05294 if ( CUR.face->unpatented_hinting )
05295 {
05296 if ( CUR.GS.both_x_axis )
05297 {
05298 *x = d;
05299 *y = 0;
05300 }
05301 else
05302 {
05303 *x = 0;
05304 *y = d;
05305 }
05306 }
05307 else
05308 #endif
05309 {
05310 *x = TT_MULDIV( d,
05311 (FT_Long)CUR.GS.freeVector.x * 0x10000L,
05312 CUR.F_dot_P );
05313 *y = TT_MULDIV( d,
05314 (FT_Long)CUR.GS.freeVector.y * 0x10000L,
05315 CUR.F_dot_P );
05316 }
05317
05318 return SUCCESS;
05319 }
05320
05321
05322 static void
05323 Move_Zp2_Point( EXEC_OP_ FT_UShort point,
05324 FT_F26Dot6 dx,
05325 FT_F26Dot6 dy,
05326 FT_Bool touch )
05327 {
05328 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
05329 if ( CUR.face->unpatented_hinting )
05330 {
05331 if ( CUR.GS.both_x_axis )
05332 {
05333 CUR.zp2.cur[point].x += dx;
05334 if ( touch )
05335 CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
05336 }
05337 else
05338 {
05339 CUR.zp2.cur[point].y += dy;
05340 if ( touch )
05341 CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
05342 }
05343 return;
05344 }
05345 #endif
05346
05347 if ( CUR.GS.freeVector.x != 0 )
05348 {
05349 CUR.zp2.cur[point].x += dx;
05350 if ( touch )
05351 CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
05352 }
05353
05354 if ( CUR.GS.freeVector.y != 0 )
05355 {
05356 CUR.zp2.cur[point].y += dy;
05357 if ( touch )
05358 CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
05359 }
05360 }
05361
05362
05363
05364
05365
05366
05367
05368
05369 static void
05370 Ins_SHP( INS_ARG )
05371 {
05372 TT_GlyphZoneRec zp;
05373 FT_UShort refp;
05374
05375 FT_F26Dot6 dx,
05376 dy;
05377 FT_UShort point;
05378
05379 FT_UNUSED_ARG;
05380
05381
05382 if ( CUR.top < CUR.GS.loop )
05383 {
05384 CUR.error = TT_Err_Invalid_Reference;
05385 return;
05386 }
05387
05388 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
05389 return;
05390
05391 while ( CUR.GS.loop > 0 )
05392 {
05393 CUR.args--;
05394 point = (FT_UShort)CUR.stack[CUR.args];
05395
05396 if ( BOUNDS( point, CUR.zp2.n_points ) )
05397 {
05398 if ( CUR.pedantic_hinting )
05399 {
05400 CUR.error = TT_Err_Invalid_Reference;
05401 return;
05402 }
05403 }
05404 else
05405
05406 MOVE_Zp2_Point( point, dx, dy, TRUE );
05407
05408 CUR.GS.loop--;
05409 }
05410
05411 CUR.GS.loop = 1;
05412 CUR.new_top = CUR.args;
05413 }
05414
05415
05416
05417
05418
05419
05420
05421
05422 static void
05423 Ins_SHC( INS_ARG )
05424 {
05425 TT_GlyphZoneRec zp;
05426 FT_UShort refp;
05427 FT_F26Dot6 dx,
05428 dy;
05429
05430 FT_Short contour;
05431 FT_UShort first_point, last_point, i;
05432
05433
05434 contour = (FT_UShort)args[0];
05435
05436 if ( BOUNDS( contour, CUR.pts.n_contours ) )
05437 {
05438 if ( CUR.pedantic_hinting )
05439 CUR.error = TT_Err_Invalid_Reference;
05440 return;
05441 }
05442
05443 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
05444 return;
05445
05446 if ( contour == 0 )
05447 first_point = 0;
05448 else
05449 first_point = (FT_UShort)( CUR.pts.contours[contour - 1] + 1 -
05450 CUR.pts.first_point );
05451
05452 last_point = (FT_UShort)( CUR.pts.contours[contour] -
05453 CUR.pts.first_point );
05454
05455
05456
05457 if ( BOUNDS( last_point, CUR.zp2.n_points ) )
05458 {
05459 if ( CUR.zp2.n_points > 0 )
05460 last_point = (FT_UShort)(CUR.zp2.n_points - 1);
05461 else
05462 last_point = 0;
05463 }
05464
05465
05466 for ( i = first_point; i <= last_point; i++ )
05467 {
05468 if ( zp.cur != CUR.zp2.cur || refp != i )
05469 MOVE_Zp2_Point( i, dx, dy, TRUE );
05470 }
05471 }
05472
05473
05474
05475
05476
05477
05478
05479
05480 static void
05481 Ins_SHZ( INS_ARG )
05482 {
05483 TT_GlyphZoneRec zp;
05484 FT_UShort refp;
05485 FT_F26Dot6 dx,
05486 dy;
05487
05488 FT_UShort last_point, i;
05489
05490
05491 if ( BOUNDS( args[0], 2 ) )
05492 {
05493 if ( CUR.pedantic_hinting )
05494 CUR.error = TT_Err_Invalid_Reference;
05495 return;
05496 }
05497
05498 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
05499 return;
05500
05501
05502
05503
05504
05505 if ( CUR.GS.gep2 == 0 && CUR.zp2.n_points > 0 )
05506 last_point = (FT_UShort)( CUR.zp2.n_points - 1 );
05507 else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 )
05508 last_point = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] );
05509 else
05510 last_point = 0;
05511
05512
05513 for ( i = 0; i <= last_point; i++ )
05514 {
05515 if ( zp.cur != CUR.zp2.cur || refp != i )
05516 MOVE_Zp2_Point( i, dx, dy, FALSE );
05517 }
05518 }
05519
05520
05521
05522
05523
05524
05525
05526
05527 static void
05528 Ins_SHPIX( INS_ARG )
05529 {
05530 FT_F26Dot6 dx, dy;
05531 FT_UShort point;
05532
05533
05534 if ( CUR.top < CUR.GS.loop + 1 )
05535 {
05536 CUR.error = TT_Err_Invalid_Reference;
05537 return;
05538 }
05539
05540 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
05541 if ( CUR.face->unpatented_hinting )
05542 {
05543 if ( CUR.GS.both_x_axis )
05544 {
05545 dx = TT_MulFix14( (FT_UInt32)args[0], 0x4000 );
05546 dy = 0;
05547 }
05548 else
05549 {
05550 dx = 0;
05551 dy = TT_MulFix14( (FT_UInt32)args[0], 0x4000 );
05552 }
05553 }
05554 else
05555 #endif
05556 {
05557 dx = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.x );
05558 dy = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.y );
05559 }
05560
05561 while ( CUR.GS.loop > 0 )
05562 {
05563 CUR.args--;
05564
05565 point = (FT_UShort)CUR.stack[CUR.args];
05566
05567 if ( BOUNDS( point, CUR.zp2.n_points ) )
05568 {
05569 if ( CUR.pedantic_hinting )
05570 {
05571 CUR.error = TT_Err_Invalid_Reference;
05572 return;
05573 }
05574 }
05575 else
05576 MOVE_Zp2_Point( point, dx, dy, TRUE );
05577
05578 CUR.GS.loop--;
05579 }
05580
05581 CUR.GS.loop = 1;
05582 CUR.new_top = CUR.args;
05583 }
05584
05585
05586
05587
05588
05589
05590
05591
05592 static void
05593 Ins_MSIRP( INS_ARG )
05594 {
05595 FT_UShort point;
05596 FT_F26Dot6 distance;
05597
05598
05599 point = (FT_UShort)args[0];
05600
05601 if ( BOUNDS( point, CUR.zp1.n_points ) ||
05602 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
05603 {
05604 if ( CUR.pedantic_hinting )
05605 CUR.error = TT_Err_Invalid_Reference;
05606 return;
05607 }
05608
05609
05610 if ( CUR.GS.gep1 == 0 )
05611
05612 {
05613 CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
05614 CUR_Func_move_orig( &CUR.zp1, point, args[1] );
05615 CUR.zp1.cur[point] = CUR.zp1.org[point];
05616 }
05617
05618 distance = CUR_Func_project( CUR.zp1.cur + point,
05619 CUR.zp0.cur + CUR.GS.rp0 );
05620
05621 CUR_Func_move( &CUR.zp1, point, args[1] - distance );
05622
05623 CUR.GS.rp1 = CUR.GS.rp0;
05624 CUR.GS.rp2 = point;
05625
05626 if ( ( CUR.opcode & 1 ) != 0 )
05627 CUR.GS.rp0 = point;
05628 }
05629
05630
05631
05632
05633
05634
05635
05636
05637 static void
05638 Ins_MDAP( INS_ARG )
05639 {
05640 FT_UShort point;
05641 FT_F26Dot6 cur_dist,
05642 distance;
05643
05644
05645 point = (FT_UShort)args[0];
05646
05647 if ( BOUNDS( point, CUR.zp0.n_points ) )
05648 {
05649 if ( CUR.pedantic_hinting )
05650 CUR.error = TT_Err_Invalid_Reference;
05651 return;
05652 }
05653
05654
05655
05656 if ( ( CUR.opcode & 1 ) != 0 )
05657 {
05658 cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
05659 distance = CUR_Func_round( cur_dist,
05660 CUR.tt_metrics.compensations[0] ) - cur_dist;
05661 }
05662 else
05663 distance = 0;
05664
05665 CUR_Func_move( &CUR.zp0, point, distance );
05666
05667 CUR.GS.rp0 = point;
05668 CUR.GS.rp1 = point;
05669 }
05670
05671
05672
05673
05674
05675
05676
05677
05678 static void
05679 Ins_MIAP( INS_ARG )
05680 {
05681 FT_ULong cvtEntry;
05682 FT_UShort point;
05683 FT_F26Dot6 distance,
05684 org_dist;
05685
05686
05687 cvtEntry = (FT_ULong)args[1];
05688 point = (FT_UShort)args[0];
05689
05690 if ( BOUNDS( point, CUR.zp0.n_points ) ||
05691 BOUNDS( cvtEntry, CUR.cvtSize ) )
05692 {
05693 if ( CUR.pedantic_hinting )
05694 CUR.error = TT_Err_Invalid_Reference;
05695 return;
05696 }
05697
05698
05699
05700
05701
05702
05703
05704
05705
05706
05707
05708
05709
05710
05711
05712
05713
05714
05715
05716
05717
05718
05719
05720 distance = CUR_Func_read_cvt( cvtEntry );
05721
05722 if ( CUR.GS.gep0 == 0 )
05723 {
05724 CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance, CUR.GS.freeVector.x );
05725 CUR.zp0.org[point].y = TT_MulFix14( (FT_UInt32)distance, CUR.GS.freeVector.y ),
05726 CUR.zp0.cur[point] = CUR.zp0.org[point];
05727 }
05728
05729 org_dist = CUR_fast_project( &CUR.zp0.cur[point] );
05730
05731 if ( ( CUR.opcode & 1 ) != 0 )
05732 {
05733 if ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin )
05734 distance = org_dist;
05735
05736 distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );
05737 }
05738
05739 CUR_Func_move( &CUR.zp0, point, distance - org_dist );
05740
05741 CUR.GS.rp0 = point;
05742 CUR.GS.rp1 = point;
05743 }
05744
05745
05746
05747
05748
05749
05750
05751
05752 static void
05753 Ins_MDRP( INS_ARG )
05754 {
05755 FT_UShort point;
05756 FT_F26Dot6 org_dist, distance;
05757
05758
05759 point = (FT_UShort)args[0];
05760
05761 if ( BOUNDS( point, CUR.zp1.n_points ) ||
05762 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
05763 {
05764 if ( CUR.pedantic_hinting )
05765 CUR.error = TT_Err_Invalid_Reference;
05766 return;
05767 }
05768
05769
05770
05771
05772
05773
05774 if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )
05775 {
05776 FT_Vector* vec1 = &CUR.zp1.org[point];
05777 FT_Vector* vec2 = &CUR.zp0.org[CUR.GS.rp0];
05778
05779
05780 org_dist = CUR_Func_dualproj( vec1, vec2 );
05781 }
05782 else
05783 {
05784 FT_Vector* vec1 = &CUR.zp1.orus[point];
05785 FT_Vector* vec2 = &CUR.zp0.orus[CUR.GS.rp0];
05786
05787
05788 if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
05789 {
05790
05791 org_dist = CUR_Func_dualproj( vec1, vec2 );
05792 org_dist = TT_MULFIX( org_dist, CUR.metrics.x_scale );
05793 }
05794 else
05795 {
05796 FT_Vector vec;
05797
05798
05799 vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
05800 vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
05801
05802 org_dist = CUR_fast_dualproj( &vec );
05803 }
05804 }
05805
05806
05807
05808 if ( FT_ABS( org_dist - CUR.GS.single_width_value ) <
05809 CUR.GS.single_width_cutin )
05810 {
05811 if ( org_dist >= 0 )
05812 org_dist = CUR.GS.single_width_value;
05813 else
05814 org_dist = -CUR.GS.single_width_value;
05815 }
05816
05817
05818
05819 if ( ( CUR.opcode & 4 ) != 0 )
05820 distance = CUR_Func_round(
05821 org_dist,
05822 CUR.tt_metrics.compensations[CUR.opcode & 3] );
05823 else
05824 distance = ROUND_None(
05825 org_dist,
05826 CUR.tt_metrics.compensations[CUR.opcode & 3] );
05827
05828
05829
05830 if ( ( CUR.opcode & 8 ) != 0 )
05831 {
05832 if ( org_dist >= 0 )
05833 {
05834 if ( distance < CUR.GS.minimum_distance )
05835 distance = CUR.GS.minimum_distance;
05836 }
05837 else
05838 {
05839 if ( distance > -CUR.GS.minimum_distance )
05840 distance = -CUR.GS.minimum_distance;
05841 }
05842 }
05843
05844
05845
05846 org_dist = CUR_Func_project( CUR.zp1.cur + point,
05847 CUR.zp0.cur + CUR.GS.rp0 );
05848
05849 CUR_Func_move( &CUR.zp1, point, distance - org_dist );
05850
05851 CUR.GS.rp1 = CUR.GS.rp0;
05852 CUR.GS.rp2 = point;
05853
05854 if ( ( CUR.opcode & 16 ) != 0 )
05855 CUR.GS.rp0 = point;
05856 }
05857
05858
05859
05860
05861
05862
05863
05864
05865 static void
05866 Ins_MIRP( INS_ARG )
05867 {
05868 FT_UShort point;
05869 FT_ULong cvtEntry;
05870
05871 FT_F26Dot6 cvt_dist,
05872 distance,
05873 cur_dist,
05874 org_dist;
05875
05876
05877 point = (FT_UShort)args[0];
05878 cvtEntry = (FT_ULong)( args[1] + 1 );
05879
05880
05881
05882 if ( BOUNDS( point, CUR.zp1.n_points ) ||
05883 BOUNDS( cvtEntry, CUR.cvtSize + 1 ) ||
05884 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
05885 {
05886 if ( CUR.pedantic_hinting )
05887 CUR.error = TT_Err_Invalid_Reference;
05888 return;
05889 }
05890
05891 if ( !cvtEntry )
05892 cvt_dist = 0;
05893 else
05894 cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
05895
05896
05897
05898 if ( FT_ABS( cvt_dist - CUR.GS.single_width_value ) <
05899 CUR.GS.single_width_cutin )
05900 {
05901 if ( cvt_dist >= 0 )
05902 cvt_dist = CUR.GS.single_width_value;
05903 else
05904 cvt_dist = -CUR.GS.single_width_value;
05905 }
05906
05907
05908
05909 if ( CUR.GS.gep1 == 0 )
05910 {
05911 CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
05912 TT_MulFix14( (FT_UInt32)cvt_dist,
05913 CUR.GS.freeVector.x );
05914
05915 CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +
05916 TT_MulFix14( (FT_UInt32)cvt_dist,
05917 CUR.GS.freeVector.y );
05918
05919 CUR.zp1.cur[point] = CUR.zp0.cur[point];
05920 }
05921
05922 org_dist = CUR_Func_dualproj( &CUR.zp1.org[point],
05923 &CUR.zp0.org[CUR.GS.rp0] );
05924 cur_dist = CUR_Func_project ( &CUR.zp1.cur[point],
05925 &CUR.zp0.cur[CUR.GS.rp0] );
05926
05927
05928
05929 if ( CUR.GS.auto_flip )
05930 {
05931 if ( ( org_dist ^ cvt_dist ) < 0 )
05932 cvt_dist = -cvt_dist;
05933 }
05934
05935
05936
05937 if ( ( CUR.opcode & 4 ) != 0 )
05938 {
05939
05940
05941
05942 if ( CUR.GS.gep0 == CUR.GS.gep1 )
05943 if ( FT_ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )
05944 cvt_dist = org_dist;
05945
05946 distance = CUR_Func_round(
05947 cvt_dist,
05948 CUR.tt_metrics.compensations[CUR.opcode & 3] );
05949 }
05950 else
05951 distance = ROUND_None(
05952 cvt_dist,
05953 CUR.tt_metrics.compensations[CUR.opcode & 3] );
05954
05955
05956
05957 if ( ( CUR.opcode & 8 ) != 0 )
05958 {
05959 if ( org_dist >= 0 )
05960 {
05961 if ( distance < CUR.GS.minimum_distance )
05962 distance = CUR.GS.minimum_distance;
05963 }
05964 else
05965 {
05966 if ( distance > -CUR.GS.minimum_distance )
05967 distance = -CUR.GS.minimum_distance;
05968 }
05969 }
05970
05971 CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
05972
05973 CUR.GS.rp1 = CUR.GS.rp0;
05974
05975 if ( ( CUR.opcode & 16 ) != 0 )
05976 CUR.GS.rp0 = point;
05977
05978
05979 CUR.GS.rp2 = point;
05980 }
05981
05982
05983
05984
05985
05986
05987
05988
05989 static void
05990 Ins_ALIGNRP( INS_ARG )
05991 {
05992 FT_UShort point;
05993 FT_F26Dot6 distance;
05994
05995 FT_UNUSED_ARG;
05996
05997
05998 if ( CUR.top < CUR.GS.loop ||
05999 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
06000 {
06001 if ( CUR.pedantic_hinting )
06002 CUR.error = TT_Err_Invalid_Reference;
06003 return;
06004 }
06005
06006 while ( CUR.GS.loop > 0 )
06007 {
06008 CUR.args--;
06009
06010 point = (FT_UShort)CUR.stack[CUR.args];
06011
06012 if ( BOUNDS( point, CUR.zp1.n_points ) )
06013 {
06014 if ( CUR.pedantic_hinting )
06015 {
06016 CUR.error = TT_Err_Invalid_Reference;
06017 return;
06018 }
06019 }
06020 else
06021 {
06022 distance = CUR_Func_project( CUR.zp1.cur + point,
06023 CUR.zp0.cur + CUR.GS.rp0 );
06024
06025 CUR_Func_move( &CUR.zp1, point, -distance );
06026 }
06027
06028 CUR.GS.loop--;
06029 }
06030
06031 CUR.GS.loop = 1;
06032 CUR.new_top = CUR.args;
06033 }
06034
06035
06036
06037
06038
06039
06040
06041
06042 static void
06043 Ins_ISECT( INS_ARG )
06044 {
06045 FT_UShort point,
06046 a0, a1,
06047 b0, b1;
06048
06049 FT_F26Dot6 discriminant;
06050
06051 FT_F26Dot6 dx, dy,
06052 dax, day,
06053 dbx, dby;
06054
06055 FT_F26Dot6 val;
06056
06057 FT_Vector R;
06058
06059
06060 point = (FT_UShort)args[0];
06061
06062 a0 = (FT_UShort)args[1];
06063 a1 = (FT_UShort)args[2];
06064 b0 = (FT_UShort)args[3];
06065 b1 = (FT_UShort)args[4];
06066
06067 if ( BOUNDS( b0, CUR.zp0.n_points ) ||
06068 BOUNDS( b1, CUR.zp0.n_points ) ||
06069 BOUNDS( a0, CUR.zp1.n_points ) ||
06070 BOUNDS( a1, CUR.zp1.n_points ) ||
06071 BOUNDS( point, CUR.zp2.n_points ) )
06072 {
06073 if ( CUR.pedantic_hinting )
06074 CUR.error = TT_Err_Invalid_Reference;
06075 return;
06076 }
06077
06078 dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
06079 dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
06080
06081 dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x;
06082 day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y;
06083
06084 dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x;
06085 dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y;
06086
06087 CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
06088
06089 discriminant = TT_MULDIV( dax, -dby, 0x40 ) +
06090 TT_MULDIV( day, dbx, 0x40 );
06091
06092 if ( FT_ABS( discriminant ) >= 0x40 )
06093 {
06094 val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );
06095
06096 R.x = TT_MULDIV( val, dax, discriminant );
06097 R.y = TT_MULDIV( val, day, discriminant );
06098
06099 CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;
06100 CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
06101 }
06102 else
06103 {
06104
06105
06106 CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x +
06107 CUR.zp1.cur[a1].x +
06108 CUR.zp0.cur[b0].x +
06109 CUR.zp0.cur[b1].x ) / 4;
06110 CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y +
06111 CUR.zp1.cur[a1].y +
06112 CUR.zp0.cur[b0].y +
06113 CUR.zp0.cur[b1].y ) / 4;
06114 }
06115 }
06116
06117
06118
06119
06120
06121
06122
06123
06124 static void
06125 Ins_ALIGNPTS( INS_ARG )
06126 {
06127 FT_UShort p1, p2;
06128 FT_F26Dot6 distance;
06129
06130
06131 p1 = (FT_UShort)args[0];
06132 p2 = (FT_UShort)args[1];
06133
06134 if ( BOUNDS( args[0], CUR.zp1.n_points ) ||
06135 BOUNDS( args[1], CUR.zp0.n_points ) )
06136 {
06137 if ( CUR.pedantic_hinting )
06138 CUR.error = TT_Err_Invalid_Reference;
06139 return;
06140 }
06141
06142 distance = CUR_Func_project( CUR.zp0.cur + p2,
06143 CUR.zp1.cur + p1 ) / 2;
06144
06145 CUR_Func_move( &CUR.zp1, p1, distance );
06146 CUR_Func_move( &CUR.zp0, p2, -distance );
06147 }
06148
06149
06150
06151
06152
06153
06154
06155
06156
06157
06158
06159 static void
06160 Ins_IP( INS_ARG )
06161 {
06162 FT_F26Dot6 old_range, cur_range;
06163 FT_Vector* orus_base;
06164 FT_Vector* cur_base;
06165 FT_Int twilight;
06166
06167 FT_UNUSED_ARG;
06168
06169
06170 if ( CUR.top < CUR.GS.loop )
06171 {
06172 CUR.error = TT_Err_Invalid_Reference;
06173 return;
06174 }
06175
06176
06177
06178
06179
06180
06181 twilight = CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 || CUR.GS.gep2 == 0;
06182
06183 if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) )
06184 {
06185 if ( CUR.pedantic_hinting )
06186 CUR.error = TT_Err_Invalid_Reference;
06187 return;
06188 }
06189
06190 if ( twilight )
06191 orus_base = &CUR.zp0.org[CUR.GS.rp1];
06192 else
06193 orus_base = &CUR.zp0.orus[CUR.GS.rp1];
06194
06195 cur_base = &CUR.zp0.cur[CUR.GS.rp1];
06196
06197
06198
06199
06200
06201 if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ||
06202 BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) )
06203 {
06204 old_range = 0;
06205 cur_range = 0;
06206 }
06207 else
06208 {
06209 if ( twilight )
06210 old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2],
06211 orus_base );
06212 else
06213 old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2],
06214 orus_base );
06215
06216 cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base );
06217 }
06218
06219 for ( ; CUR.GS.loop > 0; --CUR.GS.loop )
06220 {
06221 FT_UInt point = (FT_UInt)CUR.stack[--CUR.args];
06222 FT_F26Dot6 org_dist, cur_dist, new_dist;
06223
06224
06225
06226 if ( BOUNDS( point, CUR.zp2.n_points ) )
06227 {
06228 if ( CUR.pedantic_hinting )
06229 {
06230 CUR.error = TT_Err_Invalid_Reference;
06231 return;
06232 }
06233 continue;
06234 }
06235
06236 if ( twilight )
06237 org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base );
06238 else
06239 org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base );
06240
06241 cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base );
06242
06243 if ( org_dist )
06244 new_dist = ( old_range != 0 )
06245 ? TT_MULDIV( org_dist, cur_range, old_range )
06246 : cur_dist;
06247 else
06248 new_dist = 0;
06249
06250 CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
06251 }
06252 CUR.GS.loop = 1;
06253 CUR.new_top = CUR.args;
06254 }
06255
06256
06257
06258
06259
06260
06261
06262
06263 static void
06264 Ins_UTP( INS_ARG )
06265 {
06266 FT_UShort point;
06267 FT_Byte mask;
06268
06269
06270 point = (FT_UShort)args[0];
06271
06272 if ( BOUNDS( point, CUR.zp0.n_points ) )
06273 {
06274 if ( CUR.pedantic_hinting )
06275 CUR.error = TT_Err_Invalid_Reference;
06276 return;
06277 }
06278
06279 mask = 0xFF;
06280
06281 if ( CUR.GS.freeVector.x != 0 )
06282 mask &= ~FT_CURVE_TAG_TOUCH_X;
06283
06284 if ( CUR.GS.freeVector.y != 0 )
06285 mask &= ~FT_CURVE_TAG_TOUCH_Y;
06286
06287 CUR.zp0.tags[point] &= mask;
06288 }
06289
06290
06291
06292 typedef struct IUP_WorkerRec_
06293 {
06294 FT_Vector* orgs;
06295 FT_Vector* curs;
06296 FT_Vector* orus;
06297 FT_UInt max_points;
06298
06299 } IUP_WorkerRec, *IUP_Worker;
06300
06301
06302 static void
06303 _iup_worker_shift( IUP_Worker worker,
06304 FT_UInt p1,
06305 FT_UInt p2,
06306 FT_UInt p )
06307 {
06308 FT_UInt i;
06309 FT_F26Dot6 dx;
06310
06311
06312 dx = worker->curs[p].x - worker->orgs[p].x;
06313 if ( dx != 0 )
06314 {
06315 for ( i = p1; i < p; i++ )
06316 worker->curs[i].x += dx;
06317
06318 for ( i = p + 1; i <= p2; i++ )
06319 worker->curs[i].x += dx;
06320 }
06321 }
06322
06323
06324 static void
06325 _iup_worker_interpolate( IUP_Worker worker,
06326 FT_UInt p1,
06327 FT_UInt p2,
06328 FT_UInt ref1,
06329 FT_UInt ref2 )
06330 {
06331 FT_UInt i;
06332 FT_F26Dot6 orus1, orus2, org1, org2, delta1, delta2;
06333
06334
06335 if ( p1 > p2 )
06336 return;
06337
06338 if ( BOUNDS( ref1, worker->max_points ) ||
06339 BOUNDS( ref2, worker->max_points ) )
06340 return;
06341
06342 orus1 = worker->orus[ref1].x;
06343 orus2 = worker->orus[ref2].x;
06344
06345 if ( orus1 > orus2 )
06346 {
06347 FT_F26Dot6 tmp_o;
06348 FT_UInt tmp_r;
06349
06350
06351 tmp_o = orus1;
06352 orus1 = orus2;
06353 orus2 = tmp_o;
06354
06355 tmp_r = ref1;
06356 ref1 = ref2;
06357 ref2 = tmp_r;
06358 }
06359
06360 org1 = worker->orgs[ref1].x;
06361 org2 = worker->orgs[ref2].x;
06362 delta1 = worker->curs[ref1].x - org1;
06363 delta2 = worker->curs[ref2].x - org2;
06364
06365 if ( orus1 == orus2 )
06366 {
06367
06368 for ( i = p1; i <= p2; i++ )
06369 {
06370 FT_F26Dot6 x = worker->orgs[i].x;
06371
06372
06373 if ( x <= org1 )
06374 x += delta1;
06375 else
06376 x += delta2;
06377
06378 worker->curs[i].x = x;
06379 }
06380 }
06381 else
06382 {
06383 FT_Fixed scale = 0;
06384 FT_Bool scale_valid = 0;
06385
06386
06387
06388 for ( i = p1; i <= p2; i++ )
06389 {
06390 FT_F26Dot6 x = worker->orgs[i].x;
06391
06392
06393 if ( x <= org1 )
06394 x += delta1;
06395
06396 else if ( x >= org2 )
06397 x += delta2;
06398
06399 else
06400 {
06401 if ( !scale_valid )
06402 {
06403 scale_valid = 1;
06404 scale = TT_MULDIV( org2 + delta2 - ( org1 + delta1 ),
06405 0x10000L, orus2 - orus1 );
06406 }
06407
06408 x = ( org1 + delta1 ) +
06409 TT_MULFIX( worker->orus[i].x - orus1, scale );
06410 }
06411 worker->curs[i].x = x;
06412 }
06413 }
06414 }
06415
06416
06417
06418
06419
06420
06421
06422
06423 static void
06424 Ins_IUP( INS_ARG )
06425 {
06426 IUP_WorkerRec V;
06427 FT_Byte mask;
06428
06429 FT_UInt first_point;
06430 FT_UInt end_point;
06431
06432 FT_UInt first_touched;
06433 FT_UInt cur_touched;
06434
06435 FT_UInt point;
06436 FT_Short contour;
06437
06438 FT_UNUSED_ARG;
06439
06440
06441
06442 if ( CUR.pts.n_contours == 0 )
06443 return;
06444
06445 if ( CUR.opcode & 1 )
06446 {
06447 mask = FT_CURVE_TAG_TOUCH_X;
06448 V.orgs = CUR.pts.org;
06449 V.curs = CUR.pts.cur;
06450 V.orus = CUR.pts.orus;
06451 }
06452 else
06453 {
06454 mask = FT_CURVE_TAG_TOUCH_Y;
06455 V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
06456 V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
06457 V.orus = (FT_Vector*)( (FT_Pos*)CUR.pts.orus + 1 );
06458 }
06459 V.max_points = CUR.pts.n_points;
06460
06461 contour = 0;
06462 point = 0;
06463
06464 do
06465 {
06466 end_point = CUR.pts.contours[contour] - CUR.pts.first_point;
06467 first_point = point;
06468
06469 if ( CUR.pts.n_points <= end_point )
06470 end_point = CUR.pts.n_points;
06471
06472 while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 )
06473 point++;
06474
06475 if ( point <= end_point )
06476 {
06477 first_touched = point;
06478 cur_touched = point;
06479
06480 point++;
06481
06482 while ( point <= end_point )
06483 {
06484 if ( ( CUR.pts.tags[point] & mask ) != 0 )
06485 {
06486 if ( point > 0 )
06487 _iup_worker_interpolate( &V,
06488 cur_touched + 1,
06489 point - 1,
06490 cur_touched,
06491 point );
06492 cur_touched = point;
06493 }
06494
06495 point++;
06496 }
06497
06498 if ( cur_touched == first_touched )
06499 _iup_worker_shift( &V, first_point, end_point, cur_touched );
06500 else
06501 {
06502 _iup_worker_interpolate( &V,
06503 (FT_UShort)( cur_touched + 1 ),
06504 end_point,
06505 cur_touched,
06506 first_touched );
06507
06508 if ( first_touched > 0 )
06509 _iup_worker_interpolate( &V,
06510 first_point,
06511 first_touched - 1,
06512 cur_touched,
06513 first_touched );
06514 }
06515 }
06516 contour++;
06517 } while ( contour < CUR.pts.n_contours );
06518 }
06519
06520
06521
06522
06523
06524
06525
06526
06527 static void
06528 Ins_DELTAP( INS_ARG )
06529 {
06530 FT_ULong k, nump;
06531 FT_UShort A;
06532 FT_ULong C;
06533 FT_Long B;
06534
06535
06536 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
06537
06538 if ( CUR.face->unpatented_hinting )
06539 {
06540 FT_Long n = args[0] * 2;
06541
06542
06543 if ( CUR.args < n )
06544 {
06545 CUR.error = TT_Err_Too_Few_Arguments;
06546 return;
06547 }
06548
06549 CUR.args -= n;
06550 CUR.new_top = CUR.args;
06551 return;
06552 }
06553 #endif
06554
06555 nump = (FT_ULong)args[0];
06556
06557
06558 for ( k = 1; k <= nump; k++ )
06559 {
06560 if ( CUR.args < 2 )
06561 {
06562 CUR.error = TT_Err_Too_Few_Arguments;
06563 return;
06564 }
06565
06566 CUR.args -= 2;
06567
06568 A = (FT_UShort)CUR.stack[CUR.args + 1];
06569 B = CUR.stack[CUR.args];
06570
06571
06572
06573
06574
06575
06576
06577 if ( !BOUNDS( A, CUR.zp0.n_points ) )
06578 {
06579 C = ( (FT_ULong)B & 0xF0 ) >> 4;
06580
06581 switch ( CUR.opcode )
06582 {
06583 case 0x5D:
06584 break;
06585
06586 case 0x71:
06587 C += 16;
06588 break;
06589
06590 case 0x72:
06591 C += 32;
06592 break;
06593 }
06594
06595 C += CUR.GS.delta_base;
06596
06597 if ( CURRENT_Ppem() == (FT_Long)C )
06598 {
06599 B = ( (FT_ULong)B & 0xF ) - 8;
06600 if ( B >= 0 )
06601 B++;
06602 B = B * 64 / ( 1L << CUR.GS.delta_shift );
06603
06604 CUR_Func_move( &CUR.zp0, A, B );
06605 }
06606 }
06607 else
06608 if ( CUR.pedantic_hinting )
06609 CUR.error = TT_Err_Invalid_Reference;
06610 }
06611
06612 CUR.new_top = CUR.args;
06613 }
06614
06615
06616
06617
06618
06619
06620
06621
06622 static void
06623 Ins_DELTAC( INS_ARG )
06624 {
06625 FT_ULong nump, k;
06626 FT_ULong A, C;
06627 FT_Long B;
06628
06629
06630 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
06631
06632 if ( CUR.face->unpatented_hinting )
06633 {
06634 FT_Long n = args[0] * 2;
06635
06636
06637 if ( CUR.args < n )
06638 {
06639 CUR.error = TT_Err_Too_Few_Arguments;
06640 return;
06641 }
06642
06643 CUR.args -= n;
06644 CUR.new_top = CUR.args;
06645 return;
06646 }
06647 #endif
06648
06649 nump = (FT_ULong)args[0];
06650
06651 for ( k = 1; k <= nump; k++ )
06652 {
06653 if ( CUR.args < 2 )
06654 {
06655 CUR.error = TT_Err_Too_Few_Arguments;
06656 return;
06657 }
06658
06659 CUR.args -= 2;
06660
06661 A = (FT_ULong)CUR.stack[CUR.args + 1];
06662 B = CUR.stack[CUR.args];
06663
06664 if ( BOUNDS( A, CUR.cvtSize ) )
06665 {
06666 if ( CUR.pedantic_hinting )
06667 {
06668 CUR.error = TT_Err_Invalid_Reference;
06669 return;
06670 }
06671 }
06672 else
06673 {
06674 C = ( (FT_ULong)B & 0xF0 ) >> 4;
06675
06676 switch ( CUR.opcode )
06677 {
06678 case 0x73:
06679 break;
06680
06681 case 0x74:
06682 C += 16;
06683 break;
06684
06685 case 0x75:
06686 C += 32;
06687 break;
06688 }
06689
06690 C += CUR.GS.delta_base;
06691
06692 if ( CURRENT_Ppem() == (FT_Long)C )
06693 {
06694 B = ( (FT_ULong)B & 0xF ) - 8;
06695 if ( B >= 0 )
06696 B++;
06697 B = B * 64 / ( 1L << CUR.GS.delta_shift );
06698
06699 CUR_Func_move_cvt( A, B );
06700 }
06701 }
06702 }
06703
06704 CUR.new_top = CUR.args;
06705 }
06706
06707
06708
06709
06710
06711
06712
06713
06714
06715
06716
06717
06718
06719
06720
06721 static void
06722 Ins_GETINFO( INS_ARG )
06723 {
06724 FT_Long K;
06725
06726
06727 K = 0;
06728
06729
06730 if ( ( args[0] & 1 ) != 0 )
06731 K = 35;
06732
06733
06734 if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated )
06735 K |= 0x80;
06736
06737
06738 if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched )
06739 K |= 1 << 8;
06740
06741
06742 if ( ( args[0] & 32 ) != 0 && CUR.grayscale )
06743 K |= 1 << 12;
06744
06745 args[0] = K;
06746 }
06747
06748
06749 static void
06750 Ins_UNKNOWN( INS_ARG )
06751 {
06752 TT_DefRecord* def = CUR.IDefs;
06753 TT_DefRecord* limit = def + CUR.numIDefs;
06754
06755 FT_UNUSED_ARG;
06756
06757
06758 for ( ; def < limit; def++ )
06759 {
06760 if ( (FT_Byte)def->opc == CUR.opcode && def->active )
06761 {
06762 TT_CallRec* call;
06763
06764
06765 if ( CUR.callTop >= CUR.callSize )
06766 {
06767 CUR.error = TT_Err_Stack_Overflow;
06768 return;
06769 }
06770
06771 call = CUR.callStack + CUR.callTop++;
06772
06773 call->Caller_Range = CUR.curRange;
06774 call->Caller_IP = CUR.IP+1;
06775 call->Cur_Count = 1;
06776 call->Cur_Restart = def->start;
06777
06778 INS_Goto_CodeRange( def->range, def->start );
06779
06780 CUR.step_ins = FALSE;
06781 return;
06782 }
06783 }
06784
06785 CUR.error = TT_Err_Invalid_Opcode;
06786 }
06787
06788
06789 #ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
06790
06791
06792 static
06793 TInstruction_Function Instruct_Dispatch[256] =
06794 {
06795
06796
06797
06798 Ins_SVTCA,
06799 Ins_SVTCA,
06800 Ins_SPVTCA,
06801 Ins_SPVTCA,
06802 Ins_SFVTCA,
06803 Ins_SFVTCA,
06804 Ins_SPVTL,
06805 Ins_SPVTL,
06806 Ins_SFVTL,
06807 Ins_SFVTL,
06808 Ins_SPVFS,
06809 Ins_SFVFS,
06810 Ins_GPV,
06811 Ins_GFV,
06812 Ins_SFVTPV,
06813 Ins_ISECT,
06814
06815 Ins_SRP0,
06816 Ins_SRP1,
06817 Ins_SRP2,
06818 Ins_SZP0,
06819 Ins_SZP1,
06820 Ins_SZP2,
06821 Ins_SZPS,
06822 Ins_SLOOP,
06823 Ins_RTG,
06824 Ins_RTHG,
06825 Ins_SMD,
06826 Ins_ELSE,
06827 Ins_JMPR,
06828 Ins_SCVTCI,
06829 Ins_SSWCI,
06830 Ins_SSW,
06831
06832 Ins_DUP,
06833 Ins_POP,
06834 Ins_CLEAR,
06835 Ins_SWAP,
06836 Ins_DEPTH,
06837 Ins_CINDEX,
06838 Ins_MINDEX,
06839 Ins_ALIGNPTS,
06840 Ins_UNKNOWN,
06841 Ins_UTP,
06842 Ins_LOOPCALL,
06843 Ins_CALL,
06844 Ins_FDEF,
06845 Ins_ENDF,
06846 Ins_MDAP,
06847 Ins_MDAP,
06848
06849 Ins_IUP,
06850 Ins_IUP,
06851 Ins_SHP,
06852 Ins_SHP,
06853 Ins_SHC,
06854 Ins_SHC,
06855 Ins_SHZ,
06856 Ins_SHZ,
06857 Ins_SHPIX,
06858 Ins_IP,
06859 Ins_MSIRP,
06860 Ins_MSIRP,
06861 Ins_ALIGNRP,
06862 Ins_RTDG,
06863 Ins_MIAP,
06864 Ins_MIAP,
06865
06866 Ins_NPUSHB,
06867 Ins_NPUSHW,
06868 Ins_WS,
06869 Ins_RS,
06870 Ins_WCVTP,
06871 Ins_RCVT,
06872 Ins_GC,
06873 Ins_GC,
06874 Ins_SCFS,
06875 Ins_MD,
06876 Ins_MD,
06877 Ins_MPPEM,
06878 Ins_MPS,
06879 Ins_FLIPON,
06880 Ins_FLIPOFF,
06881 Ins_DEBUG,
06882
06883 Ins_LT,
06884 Ins_LTEQ,
06885 Ins_GT,
06886 Ins_GTEQ,
06887 Ins_EQ,
06888 Ins_NEQ,
06889 Ins_ODD,
06890 Ins_EVEN,
06891 Ins_IF,
06892 Ins_EIF,
06893 Ins_AND,
06894 Ins_OR,
06895 Ins_NOT,
06896 Ins_DELTAP,
06897 Ins_SDB,
06898 Ins_SDS,
06899
06900 Ins_ADD,
06901 Ins_SUB,
06902 Ins_DIV,
06903 Ins_MUL,
06904 Ins_ABS,
06905 Ins_NEG,
06906 Ins_FLOOR,
06907 Ins_CEILING,
06908 Ins_ROUND,
06909 Ins_ROUND,
06910 Ins_ROUND,
06911 Ins_ROUND,
06912 Ins_NROUND,
06913 Ins_NROUND,
06914 Ins_NROUND,
06915 Ins_NROUND,
06916
06917 Ins_WCVTF,
06918 Ins_DELTAP,
06919 Ins_DELTAP,
06920 Ins_DELTAC,
06921 Ins_DELTAC,
06922 Ins_DELTAC,
06923 Ins_SROUND,
06924 Ins_S45ROUND,
06925 Ins_JROT,
06926 Ins_JROF,
06927 Ins_ROFF,
06928 Ins_UNKNOWN,
06929 Ins_RUTG,
06930 Ins_RDTG,
06931 Ins_SANGW,
06932 Ins_AA,
06933
06934 Ins_FLIPPT,
06935 Ins_FLIPRGON,
06936 Ins_FLIPRGOFF,
06937 Ins_UNKNOWN,
06938 Ins_UNKNOWN,
06939 Ins_SCANCTRL,
06940 Ins_SDPVTL,
06941 Ins_SDPVTL,
06942 Ins_GETINFO,
06943 Ins_IDEF,
06944 Ins_ROLL,
06945 Ins_MAX,
06946 Ins_MIN,
06947 Ins_SCANTYPE,
06948 Ins_INSTCTRL,
06949 Ins_UNKNOWN,
06950
06951 Ins_UNKNOWN,
06952 Ins_UNKNOWN,
06953 Ins_UNKNOWN,
06954 Ins_UNKNOWN,
06955 Ins_UNKNOWN,
06956 Ins_UNKNOWN,
06957 Ins_UNKNOWN,
06958 Ins_UNKNOWN,
06959 Ins_UNKNOWN,
06960 Ins_UNKNOWN,
06961 Ins_UNKNOWN,
06962 Ins_UNKNOWN,
06963 Ins_UNKNOWN,
06964 Ins_UNKNOWN,
06965 Ins_UNKNOWN,
06966 Ins_UNKNOWN,
06967
06968 Ins_UNKNOWN,
06969 Ins_UNKNOWN,
06970 Ins_UNKNOWN,
06971 Ins_UNKNOWN,
06972 Ins_UNKNOWN,
06973 Ins_UNKNOWN,
06974 Ins_UNKNOWN,
06975 Ins_UNKNOWN,
06976 Ins_UNKNOWN,
06977 Ins_UNKNOWN,
06978 Ins_UNKNOWN,
06979 Ins_UNKNOWN,
06980 Ins_UNKNOWN,
06981 Ins_UNKNOWN,
06982 Ins_UNKNOWN,
06983 Ins_UNKNOWN,
06984
06985 Ins_PUSHB,
06986 Ins_PUSHB,
06987 Ins_PUSHB,
06988 Ins_PUSHB,
06989 Ins_PUSHB,
06990 Ins_PUSHB,
06991 Ins_PUSHB,
06992 Ins_PUSHB,
06993 Ins_PUSHW,
06994 Ins_PUSHW,
06995 Ins_PUSHW,
06996 Ins_PUSHW,
06997 Ins_PUSHW,
06998 Ins_PUSHW,
06999 Ins_PUSHW,
07000 Ins_PUSHW,
07001
07002 Ins_MDRP,
07003 Ins_MDRP,
07004 Ins_MDRP,
07005 Ins_MDRP,
07006 Ins_MDRP,
07007 Ins_MDRP,
07008 Ins_MDRP,
07009 Ins_MDRP,
07010 Ins_MDRP,
07011 Ins_MDRP,
07012 Ins_MDRP,
07013 Ins_MDRP,
07014 Ins_MDRP,
07015 Ins_MDRP,
07016 Ins_MDRP,
07017 Ins_MDRP,
07018
07019 Ins_MDRP,
07020 Ins_MDRP,
07021 Ins_MDRP,
07022 Ins_MDRP,
07023 Ins_MDRP,
07024 Ins_MDRP,
07025 Ins_MDRP,
07026 Ins_MDRP,
07027 Ins_MDRP,
07028 Ins_MDRP,
07029 Ins_MDRP,
07030 Ins_MDRP,
07031 Ins_MDRP,
07032 Ins_MDRP,
07033 Ins_MDRP,
07034 Ins_MDRP,
07035
07036 Ins_MIRP,
07037 Ins_MIRP,
07038 Ins_MIRP,
07039 Ins_MIRP,
07040 Ins_MIRP,
07041 Ins_MIRP,
07042 Ins_MIRP,
07043 Ins_MIRP,
07044 Ins_MIRP,
07045 Ins_MIRP,
07046 Ins_MIRP,
07047 Ins_MIRP,
07048 Ins_MIRP,
07049 Ins_MIRP,
07050 Ins_MIRP,
07051 Ins_MIRP,
07052
07053 Ins_MIRP,
07054 Ins_MIRP,
07055 Ins_MIRP,
07056 Ins_MIRP,
07057 Ins_MIRP,
07058 Ins_MIRP,
07059 Ins_MIRP,
07060 Ins_MIRP,
07061 Ins_MIRP,
07062 Ins_MIRP,
07063 Ins_MIRP,
07064 Ins_MIRP,
07065 Ins_MIRP,
07066 Ins_MIRP,
07067 Ins_MIRP,
07068 Ins_MIRP
07069 };
07070
07071
07072 #endif
07073
07074
07075
07076
07077
07078
07079
07080
07081
07082
07083
07084
07085
07086
07087
07088
07089
07090
07091
07092
07093
07094
07095
07096
07097
07098
07099
07100
07101
07102
07103
07104
07105
07106
07107
07108
07109 FT_EXPORT_DEF( FT_Error )
07110 TT_RunIns( TT_ExecContext exc )
07111 {
07112 FT_Long ins_counter = 0;
07113
07114
07115 #ifdef TT_CONFIG_OPTION_STATIC_RASTER
07116 cur = *exc;
07117 #endif
07118
07119
07120 CUR.tt_metrics.ratio = 0;
07121 if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
07122 {
07123
07124 CUR.func_read_cvt = Read_CVT_Stretched;
07125 CUR.func_write_cvt = Write_CVT_Stretched;
07126 CUR.func_move_cvt = Move_CVT_Stretched;
07127 }
07128 else
07129 {
07130
07131 CUR.func_read_cvt = Read_CVT;
07132 CUR.func_write_cvt = Write_CVT;
07133 CUR.func_move_cvt = Move_CVT;
07134 }
07135
07136 COMPUTE_Funcs();
07137 COMPUTE_Round( (FT_Byte)exc->GS.round_state );
07138
07139 do
07140 {
07141 CUR.opcode = CUR.code[CUR.IP];
07142
07143 if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
07144 {
07145 if ( CUR.IP + 1 > CUR.codeSize )
07146 goto LErrorCodeOverflow_;
07147
07148 CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
07149 }
07150
07151 if ( CUR.IP + CUR.length > CUR.codeSize )
07152 goto LErrorCodeOverflow_;
07153
07154
07155 CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );
07156
07157
07158
07159 if ( CUR.args < 0 )
07160 {
07161 CUR.error = TT_Err_Too_Few_Arguments;
07162 goto LErrorLabel_;
07163 }
07164
07165 CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
07166
07167
07168
07169
07170 if ( CUR.new_top > CUR.stackSize )
07171 {
07172 CUR.error = TT_Err_Stack_Overflow;
07173 goto LErrorLabel_;
07174 }
07175
07176 CUR.step_ins = TRUE;
07177 CUR.error = TT_Err_Ok;
07178
07179 #ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
07180
07181 {
07182 FT_Long* args = CUR.stack + CUR.args;
07183 FT_Byte opcode = CUR.opcode;
07184
07185
07186 #undef ARRAY_BOUND_ERROR
07187 #define ARRAY_BOUND_ERROR goto Set_Invalid_Ref
07188
07189
07190 switch ( opcode )
07191 {
07192 case 0x00:
07193 case 0x01:
07194 case 0x02:
07195 case 0x03:
07196 case 0x04:
07197 case 0x05:
07198 {
07199 FT_Short AA, BB;
07200
07201
07202 AA = (FT_Short)( ( opcode & 1 ) << 14 );
07203 BB = (FT_Short)( AA ^ 0x4000 );
07204
07205 if ( opcode < 4 )
07206 {
07207 CUR.GS.projVector.x = AA;
07208 CUR.GS.projVector.y = BB;
07209
07210 CUR.GS.dualVector.x = AA;
07211 CUR.GS.dualVector.y = BB;
07212 }
07213 else
07214 {
07215 GUESS_VECTOR( projVector );
07216 }
07217
07218 if ( ( opcode & 2 ) == 0 )
07219 {
07220 CUR.GS.freeVector.x = AA;
07221 CUR.GS.freeVector.y = BB;
07222 }
07223 else
07224 {
07225 GUESS_VECTOR( freeVector );
07226 }
07227
07228 COMPUTE_Funcs();
07229 }
07230 break;
07231
07232 case 0x06:
07233 case 0x07:
07234 DO_SPVTL
07235 break;
07236
07237 case 0x08:
07238 case 0x09:
07239 DO_SFVTL
07240 break;
07241
07242 case 0x0A:
07243 DO_SPVFS
07244 break;
07245
07246 case 0x0B:
07247 DO_SFVFS
07248 break;
07249
07250 case 0x0C:
07251 DO_GPV
07252 break;
07253
07254 case 0x0D:
07255 DO_GFV
07256 break;
07257
07258 case 0x0E:
07259 DO_SFVTPV
07260 break;
07261
07262 case 0x0F:
07263 Ins_ISECT( EXEC_ARG_ args );
07264 break;
07265
07266 case 0x10:
07267 DO_SRP0
07268 break;
07269
07270 case 0x11:
07271 DO_SRP1
07272 break;
07273
07274 case 0x12:
07275 DO_SRP2
07276 break;
07277
07278 case 0x13:
07279 Ins_SZP0( EXEC_ARG_ args );
07280 break;
07281
07282 case 0x14:
07283 Ins_SZP1( EXEC_ARG_ args );
07284 break;
07285
07286 case 0x15:
07287 Ins_SZP2( EXEC_ARG_ args );
07288 break;
07289
07290 case 0x16:
07291 Ins_SZPS( EXEC_ARG_ args );
07292 break;
07293
07294 case 0x17:
07295 DO_SLOOP
07296 break;
07297
07298 case 0x18:
07299 DO_RTG
07300 break;
07301
07302 case 0x19:
07303 DO_RTHG
07304 break;
07305
07306 case 0x1A:
07307 DO_SMD
07308 break;
07309
07310 case 0x1B:
07311 Ins_ELSE( EXEC_ARG_ args );
07312 break;
07313
07314 case 0x1C:
07315 DO_JMPR
07316 break;
07317
07318 case 0x1D:
07319 DO_SCVTCI
07320 break;
07321
07322 case 0x1E:
07323 DO_SSWCI
07324 break;
07325
07326 case 0x1F:
07327 DO_SSW
07328 break;
07329
07330 case 0x20:
07331 DO_DUP
07332 break;
07333
07334 case 0x21:
07335
07336 break;
07337
07338 case 0x22:
07339 DO_CLEAR
07340 break;
07341
07342 case 0x23:
07343 DO_SWAP
07344 break;
07345
07346 case 0x24:
07347 DO_DEPTH
07348 break;
07349
07350 case 0x25:
07351 DO_CINDEX
07352 break;
07353
07354 case 0x26:
07355 Ins_MINDEX( EXEC_ARG_ args );
07356 break;
07357
07358 case 0x27:
07359 Ins_ALIGNPTS( EXEC_ARG_ args );
07360 break;
07361
07362 case 0x28:
07363 Ins_UNKNOWN( EXEC_ARG_ args );
07364 break;
07365
07366 case 0x29:
07367 Ins_UTP( EXEC_ARG_ args );
07368 break;
07369
07370 case 0x2A:
07371 Ins_LOOPCALL( EXEC_ARG_ args );
07372 break;
07373
07374 case 0x2B:
07375 Ins_CALL( EXEC_ARG_ args );
07376 break;
07377
07378 case 0x2C:
07379 Ins_FDEF( EXEC_ARG_ args );
07380 break;
07381
07382 case 0x2D:
07383 Ins_ENDF( EXEC_ARG_ args );
07384 break;
07385
07386 case 0x2E:
07387 case 0x2F:
07388 Ins_MDAP( EXEC_ARG_ args );
07389 break;
07390
07391
07392 case 0x30:
07393 case 0x31:
07394 Ins_IUP( EXEC_ARG_ args );
07395 break;
07396
07397 case 0x32:
07398 case 0x33:
07399 Ins_SHP( EXEC_ARG_ args );
07400 break;
07401
07402 case 0x34:
07403 case 0x35:
07404 Ins_SHC( EXEC_ARG_ args );
07405 break;
07406
07407 case 0x36:
07408 case 0x37:
07409 Ins_SHZ( EXEC_ARG_ args );
07410 break;
07411
07412 case 0x38:
07413 Ins_SHPIX( EXEC_ARG_ args );
07414 break;
07415
07416 case 0x39:
07417 Ins_IP( EXEC_ARG_ args );
07418 break;
07419
07420 case 0x3A:
07421 case 0x3B:
07422 Ins_MSIRP( EXEC_ARG_ args );
07423 break;
07424
07425 case 0x3C:
07426 Ins_ALIGNRP( EXEC_ARG_ args );
07427 break;
07428
07429 case 0x3D:
07430 DO_RTDG
07431 break;
07432
07433 case 0x3E:
07434 case 0x3F:
07435 Ins_MIAP( EXEC_ARG_ args );
07436 break;
07437
07438 case 0x40:
07439 Ins_NPUSHB( EXEC_ARG_ args );
07440 break;
07441
07442 case 0x41:
07443 Ins_NPUSHW( EXEC_ARG_ args );
07444 break;
07445
07446 case 0x42:
07447 DO_WS
07448 break;
07449
07450 Set_Invalid_Ref:
07451 CUR.error = TT_Err_Invalid_Reference;
07452 break;
07453
07454 case 0x43:
07455 DO_RS
07456 break;
07457
07458 case 0x44:
07459 DO_WCVTP
07460 break;
07461
07462 case 0x45:
07463 DO_RCVT
07464 break;
07465
07466 case 0x46:
07467 case 0x47:
07468 Ins_GC( EXEC_ARG_ args );
07469 break;
07470
07471 case 0x48:
07472 Ins_SCFS( EXEC_ARG_ args );
07473 break;
07474
07475 case 0x49:
07476 case 0x4A:
07477 Ins_MD( EXEC_ARG_ args );
07478 break;
07479
07480 case 0x4B:
07481 DO_MPPEM
07482 break;
07483
07484 case 0x4C:
07485 DO_MPS
07486 break;
07487
07488 case 0x4D:
07489 DO_FLIPON
07490 break;
07491
07492 case 0x4E:
07493 DO_FLIPOFF
07494 break;
07495
07496 case 0x4F:
07497 DO_DEBUG
07498 break;
07499
07500 case 0x50:
07501 DO_LT
07502 break;
07503
07504 case 0x51:
07505 DO_LTEQ
07506 break;
07507
07508 case 0x52:
07509 DO_GT
07510 break;
07511
07512 case 0x53:
07513 DO_GTEQ
07514 break;
07515
07516 case 0x54:
07517 DO_EQ
07518 break;
07519
07520 case 0x55:
07521 DO_NEQ
07522 break;
07523
07524 case 0x56:
07525 DO_ODD
07526 break;
07527
07528 case 0x57:
07529 DO_EVEN
07530 break;
07531
07532 case 0x58:
07533 Ins_IF( EXEC_ARG_ args );
07534 break;
07535
07536 case 0x59:
07537
07538 break;
07539
07540 case 0x5A:
07541 DO_AND
07542 break;
07543
07544 case 0x5B:
07545 DO_OR
07546 break;
07547
07548 case 0x5C:
07549 DO_NOT
07550 break;
07551
07552 case 0x5D:
07553 Ins_DELTAP( EXEC_ARG_ args );
07554 break;
07555
07556 case 0x5E:
07557 DO_SDB
07558 break;
07559
07560 case 0x5F:
07561 DO_SDS
07562 break;
07563
07564 case 0x60:
07565 DO_ADD
07566 break;
07567
07568 case 0x61:
07569 DO_SUB
07570 break;
07571
07572 case 0x62:
07573 DO_DIV
07574 break;
07575
07576 case 0x63:
07577 DO_MUL
07578 break;
07579
07580 case 0x64:
07581 DO_ABS
07582 break;
07583
07584 case 0x65:
07585 DO_NEG
07586 break;
07587
07588 case 0x66:
07589 DO_FLOOR
07590 break;
07591
07592 case 0x67:
07593 DO_CEILING
07594 break;
07595
07596 case 0x68:
07597 case 0x69:
07598 case 0x6A:
07599 case 0x6B:
07600 DO_ROUND
07601 break;
07602
07603 case 0x6C:
07604 case 0x6D:
07605 case 0x6E:
07606 case 0x6F:
07607 DO_NROUND
07608 break;
07609
07610 case 0x70:
07611 DO_WCVTF
07612 break;
07613
07614 case 0x71:
07615 case 0x72:
07616 Ins_DELTAP( EXEC_ARG_ args );
07617 break;
07618
07619 case 0x73:
07620 case 0x74:
07621 case 0x75:
07622 Ins_DELTAC( EXEC_ARG_ args );
07623 break;
07624
07625 case 0x76:
07626 DO_SROUND
07627 break;
07628
07629 case 0x77:
07630 DO_S45ROUND
07631 break;
07632
07633 case 0x78:
07634 DO_JROT
07635 break;
07636
07637 case 0x79:
07638 DO_JROF
07639 break;
07640
07641 case 0x7A:
07642 DO_ROFF
07643 break;
07644
07645 case 0x7B:
07646 Ins_UNKNOWN( EXEC_ARG_ args );
07647 break;
07648
07649 case 0x7C:
07650 DO_RUTG
07651 break;
07652
07653 case 0x7D:
07654 DO_RDTG
07655 break;
07656
07657 case 0x7E:
07658 case 0x7F:
07659
07660 break;
07661
07662 case 0x80:
07663 Ins_FLIPPT( EXEC_ARG_ args );
07664 break;
07665
07666 case 0x81:
07667 Ins_FLIPRGON( EXEC_ARG_ args );
07668 break;
07669
07670 case 0x82:
07671 Ins_FLIPRGOFF( EXEC_ARG_ args );
07672 break;
07673
07674 case 0x83:
07675 case 0x84:
07676 Ins_UNKNOWN( EXEC_ARG_ args );
07677 break;
07678
07679 case 0x85:
07680 Ins_SCANCTRL( EXEC_ARG_ args );
07681 break;
07682
07683 case 0x86:
07684 case 0x87:
07685 Ins_SDPVTL( EXEC_ARG_ args );
07686 break;
07687
07688 case 0x88:
07689 Ins_GETINFO( EXEC_ARG_ args );
07690 break;
07691
07692 case 0x89:
07693 Ins_IDEF( EXEC_ARG_ args );
07694 break;
07695
07696 case 0x8A:
07697 Ins_ROLL( EXEC_ARG_ args );
07698 break;
07699
07700 case 0x8B:
07701 DO_MAX
07702 break;
07703
07704 case 0x8C:
07705 DO_MIN
07706 break;
07707
07708 case 0x8D:
07709 Ins_SCANTYPE( EXEC_ARG_ args );
07710 break;
07711
07712 case 0x8E:
07713 Ins_INSTCTRL( EXEC_ARG_ args );
07714 break;
07715
07716 case 0x8F:
07717 Ins_UNKNOWN( EXEC_ARG_ args );
07718 break;
07719
07720 default:
07721 if ( opcode >= 0xE0 )
07722 Ins_MIRP( EXEC_ARG_ args );
07723 else if ( opcode >= 0xC0 )
07724 Ins_MDRP( EXEC_ARG_ args );
07725 else if ( opcode >= 0xB8 )
07726 Ins_PUSHW( EXEC_ARG_ args );
07727 else if ( opcode >= 0xB0 )
07728 Ins_PUSHB( EXEC_ARG_ args );
07729 else
07730 Ins_UNKNOWN( EXEC_ARG_ args );
07731 }
07732
07733 }
07734
07735 #else
07736
07737 Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );
07738
07739 #endif
07740
07741 if ( CUR.error != TT_Err_Ok )
07742 {
07743 switch ( CUR.error )
07744 {
07745 case TT_Err_Invalid_Opcode:
07746 {
07747 TT_DefRecord* def = CUR.IDefs;
07748 TT_DefRecord* limit = def + CUR.numIDefs;
07749
07750
07751 for ( ; def < limit; def++ )
07752 {
07753 if ( def->active && CUR.opcode == (FT_Byte)def->opc )
07754 {
07755 TT_CallRec* callrec;
07756
07757
07758 if ( CUR.callTop >= CUR.callSize )
07759 {
07760 CUR.error = TT_Err_Invalid_Reference;
07761 goto LErrorLabel_;
07762 }
07763
07764 callrec = &CUR.callStack[CUR.callTop];
07765
07766 callrec->Caller_Range = CUR.curRange;
07767 callrec->Caller_IP = CUR.IP + 1;
07768 callrec->Cur_Count = 1;
07769 callrec->Cur_Restart = def->start;
07770
07771 if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
07772 goto LErrorLabel_;
07773
07774 goto LSuiteLabel_;
07775 }
07776 }
07777 }
07778
07779 CUR.error = TT_Err_Invalid_Opcode;
07780 goto LErrorLabel_;
07781
07782 #if 0
07783 break;
07784
07785
07786 #endif
07787
07788 default:
07789 goto LErrorLabel_;
07790
07791 #if 0
07792 break;
07793 #endif
07794 }
07795 }
07796
07797 CUR.top = CUR.new_top;
07798
07799 if ( CUR.step_ins )
07800 CUR.IP += CUR.length;
07801
07802
07803
07804 if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
07805 return TT_Err_Execution_Too_Long;
07806
07807 LSuiteLabel_:
07808 if ( CUR.IP >= CUR.codeSize )
07809 {
07810 if ( CUR.callTop > 0 )
07811 {
07812 CUR.error = TT_Err_Code_Overflow;
07813 goto LErrorLabel_;
07814 }
07815 else
07816 goto LNo_Error_;
07817 }
07818 } while ( !CUR.instruction_trap );
07819
07820 LNo_Error_:
07821
07822 #ifdef TT_CONFIG_OPTION_STATIC_RASTER
07823 *exc = cur;
07824 #endif
07825
07826 return TT_Err_Ok;
07827
07828 LErrorCodeOverflow_:
07829 CUR.error = TT_Err_Code_Overflow;
07830
07831 LErrorLabel_:
07832
07833 #ifdef TT_CONFIG_OPTION_STATIC_RASTER
07834 *exc = cur;
07835 #endif
07836
07837 return CUR.error;
07838 }
07839
07840
07841 #endif
07842
07843
07844