📄 ttinterp.c
字号:
/* MDRP[23] */ PACK( 1, 0 ), /* MDRP[24] */ PACK( 1, 0 ), /* MDRP[25] */ PACK( 1, 0 ), /* MDRP[26] */ PACK( 1, 0 ), /* MDRP[27] */ PACK( 1, 0 ), /* MDRP[28] */ PACK( 1, 0 ), /* MDRP[29] */ PACK( 1, 0 ), /* MDRP[30] */ PACK( 1, 0 ), /* MDRP[31] */ PACK( 1, 0 ), /* MIRP[00] */ PACK( 2, 0 ), /* MIRP[01] */ PACK( 2, 0 ), /* MIRP[02] */ PACK( 2, 0 ), /* MIRP[03] */ PACK( 2, 0 ), /* MIRP[04] */ PACK( 2, 0 ), /* MIRP[05] */ PACK( 2, 0 ), /* MIRP[06] */ PACK( 2, 0 ), /* MIRP[07] */ PACK( 2, 0 ), /* MIRP[08] */ PACK( 2, 0 ), /* MIRP[09] */ PACK( 2, 0 ), /* MIRP[10] */ PACK( 2, 0 ), /* MIRP[11] */ PACK( 2, 0 ), /* MIRP[12] */ PACK( 2, 0 ), /* MIRP[13] */ PACK( 2, 0 ), /* MIRP[14] */ PACK( 2, 0 ), /* MIRP[15] */ PACK( 2, 0 ), /* MIRP[16] */ PACK( 2, 0 ), /* MIRP[17] */ PACK( 2, 0 ), /* MIRP[18] */ PACK( 2, 0 ), /* MIRP[19] */ PACK( 2, 0 ), /* MIRP[20] */ PACK( 2, 0 ), /* MIRP[21] */ PACK( 2, 0 ), /* MIRP[22] */ PACK( 2, 0 ), /* MIRP[23] */ PACK( 2, 0 ), /* MIRP[24] */ PACK( 2, 0 ), /* MIRP[25] */ PACK( 2, 0 ), /* MIRP[26] */ PACK( 2, 0 ), /* MIRP[27] */ PACK( 2, 0 ), /* MIRP[28] */ PACK( 2, 0 ), /* MIRP[29] */ PACK( 2, 0 ), /* MIRP[30] */ PACK( 2, 0 ), /* MIRP[31] */ PACK( 2, 0 ) }; static const TT_Vector Null_Vector = {0,0};#undef NULL_Vector#define NULL_Vector (TT_Vector*)&Null_Vector/******************************************************************* * * Function : Norm * * Description : Returns the norm (length) of a vector. * * Input : X, Y vector * * Output : Returns length in F26dot6. * *****************************************************************/ static TT_F26Dot6 Norm( TT_F26Dot6 X, TT_F26Dot6 Y ) { TT_Int64 T1, T2; MUL_64( X, X, T1 ); MUL_64( Y, Y, T2 ); ADD_64( T1, T2, T1 ); return (TT_F26Dot6)SQRT_64( T1 ); }/******************************************************************* * * Function : FUnits_To_Pixels * * Description : Scale a distance in FUnits to pixel coordinates. * * Input : Distance in FUnits * * Output : Distance in 26.6 format. * *****************************************************************/ static TT_F26Dot6 FUnits_To_Pixels( EXEC_OPS Short distance ) { return TT_MulDiv( distance, CUR.metrics.scale1, CUR.metrics.scale2 ); }/******************************************************************* * * Function : Current_Ratio * * Description : Return the current aspect ratio scaling factor * depending on the projection vector's state and * device resolutions. * * Input : None * * Output : Aspect ratio in 16.16 format, always <= 1.0 . * *****************************************************************/ static Long Current_Ratio( EXEC_OP ) { if ( CUR.metrics.ratio ) return CUR.metrics.ratio; if ( CUR.GS.projVector.y == 0 ) CUR.metrics.ratio = CUR.metrics.x_ratio; else if ( CUR.GS.projVector.x == 0 ) CUR.metrics.ratio = CUR.metrics.y_ratio; else { Long x, y; x = TT_MulDiv( CUR.GS.projVector.x, CUR.metrics.x_ratio, 0x4000 ); y = TT_MulDiv( CUR.GS.projVector.y, CUR.metrics.y_ratio, 0x4000 ); CUR.metrics.ratio = Norm( x, y ); } return CUR.metrics.ratio; } static Long Current_Ppem( EXEC_OP ) { return TT_MulFix( CUR.metrics.ppem, CURRENT_Ratio() ); } static TT_F26Dot6 Read_CVT( EXEC_OPS ULong index ) { return CUR.cvt[index]; } static TT_F26Dot6 Read_CVT_Stretched( EXEC_OPS ULong index ) { return TT_MulFix( CUR.cvt[index], CURRENT_Ratio() ); } static void Write_CVT( EXEC_OPS ULong index, TT_F26Dot6 value ) { CUR.cvt[index] = value; } static void Write_CVT_Stretched( EXEC_OPS ULong index, TT_F26Dot6 value ) { CUR.cvt[index] = TT_MulDiv( value, 0x10000, CURRENT_Ratio() ); } static void Move_CVT( EXEC_OPS ULong index, TT_F26Dot6 value ) { CUR.cvt[index] += value; } static void Move_CVT_Stretched( EXEC_OPS ULong index, TT_F26Dot6 value ) { CUR.cvt[index] += TT_MulDiv( value, 0x10000, CURRENT_Ratio() ); }/****************************************************************** * * Function : Calc_Length * * Description : Computes the length in bytes of current opcode. * *****************************************************************/ static Bool Calc_Length( EXEC_OP ) { CUR.opcode = CUR.code[CUR.IP]; switch ( CUR.opcode ) { case 0x40: if ( CUR.IP + 1 >= CUR.codeSize ) return FAILURE; CUR.length = CUR.code[CUR.IP + 1] + 2; break; case 0x41: if ( CUR.IP + 1 >= CUR.codeSize ) return FAILURE; CUR.length = CUR.code[CUR.IP + 1] * 2 + 2; break; case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7: CUR.length = CUR.opcode - 0xB0 + 2; break; case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF: CUR.length = (CUR.opcode - 0xB8) * 2 + 3; break; default: CUR.length = 1; break; } /* make sure result is in range */ if ( CUR.IP + CUR.length > CUR.codeSize ) return FAILURE; return SUCCESS; }/******************************************************************* * * Function : GetShortIns * * Description : Returns a short integer taken from the instruction * stream at address IP. * * Input : None * * Output : Short read at Code^[IP..IP+1] * * Notes : This one could become a Macro in the C version. * *****************************************************************/ static Short GetShortIns( EXEC_OP ) { /* Reading a byte stream so there is no endianess (DaveP) */ CUR.IP += 2; return (Short)((CUR.code[CUR.IP - 2] << 8) + CUR.code[CUR.IP - 1]); }/******************************************************************* * * Function : Ins_Goto_CodeRange * * Description : Goes to a certain code range in the instruction * stream. * * * Input : aRange * aIP * * Output : SUCCESS or FAILURE. * *****************************************************************/ static Bool Ins_Goto_CodeRange( EXEC_OPS Int aRange, ULong aIP ) { TCodeRange* WITH; if ( aRange < 1 || aRange > 3 ) { CUR.error = TT_Err_Bad_Argument; return FAILURE; } WITH = &CUR.codeRangeTable[aRange - 1]; if ( WITH->Base == NULL ) /* invalid coderange */ { CUR.error = TT_Err_Invalid_CodeRange; return FAILURE; } /* NOTE: Because the last instruction of a program may be a CALL */ /* which will return to the first byte *after* the code */ /* range, we test for aIP <= Size, instead of aIP < Size. */ if ( aIP > WITH->Size ) { CUR.error = TT_Err_Code_Overflow; return FAILURE; } CUR.code = WITH->Base; CUR.codeSize = WITH->Size; CUR.IP = aIP; CUR.curRange = aRange; return SUCCESS; }/******************************************************************* * * Function : Direct_Move * * Description : Moves a point by a given distance along the * freedom vector. The point will be touched. * * Input : point index of point to move * distance distance to apply * zone affected glyph zone * * Output : None * *****************************************************************/ static void Direct_Move( EXEC_OPS PGlyph_Zone zone, UShort point, TT_F26Dot6 distance ) { TT_F26Dot6 v; v = CUR.GS.freeVector.x; if ( v != 0 ) { zone->cur[point].x += TT_MulDiv( distance, v * 0x10000L, CUR.F_dot_P ); zone->touch[point] |= TT_Flag_Touched_X; } v = CUR.GS.freeVector.y; if ( v != 0 ) { zone->cur[point].y += TT_MulDiv( distance, v * 0x10000L, CUR.F_dot_P ); zone->touch[point] |= TT_Flag_Touched_Y; } }/******************************************************************//* *//* The following versions are used whenever both vectors are both *//* along one of the coordinate unit vectors, i.e. in 90% cases. *//* *//******************************************************************//******************************************************************* * Direct_Move_X * *******************************************************************/ static void Direct_Move_X( EXEC_OPS PGlyph_Zone zone, UShort point, TT_F26Dot6 distance ) { zone->cur[point].x += distance; zone->touch[point] |= TT_Flag_Touched_X; }/******************************************************************* * Direct_Move_Y * *******************************************************************/ static void Direct_Move_Y( EXEC_OPS PGlyph_Zone zone, UShort point, TT_F26Dot6 distance ) { zone->cur[point].y += distance; zone->touch[point] |= TT_Flag_Touched_Y; }/******************************************************************* * * Function : Round_None * * Description : Does not round, but adds engine compensation. * * Input : distance : distance to round * compensation : engine compensation * * Output : rounded distance. * * NOTE : The spec says very few about the relationship between * rounding and engine compensation. However, it seems * from the description of super round that we should * should add the compensation before rounding. * ******************************************************************/ static TT_F26Dot6 Round_None( EXEC_OPS TT_F26Dot6 distance, TT_F26Dot6 compensation ) { TT_F26Dot6 val; if ( distance >= 0 ) { val = distance + compensation; if ( val < 0 ) val = 0; } else { val = distance - compensation; if ( val > 0 ) val = 0; } return val; }/******************************************************************* * * Function : Round_To_Grid * * Description : Rounds value to grid after adding engine * compensation * * Input : distance : distance to round * compensation : engine compensation * * Output : Rounded distance. * *****************************************************************/ static TT_F26Dot6 Round_To_Grid( EXEC_OPS TT_F26Dot6 distance, TT_F26Dot6 compensation ) { TT_F26Dot6 val; if ( distance >= 0 ) { val = distance + compensation + 32; if ( val > 0 ) val &= ~63; else val = 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -