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