| Index: src/truetype/ttinterp.c
|
| diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
|
| index 3acb24a2f6f6dc513a2eb4963f77ca36ec5fc79f..798d4a9b3d1be3bc72168f8b2f2f6b7144f7ce0f 100644
|
| --- a/src/truetype/ttinterp.c
|
| +++ b/src/truetype/ttinterp.c
|
| @@ -4,7 +4,7 @@
|
| /* */
|
| /* TrueType bytecode interpreter (body). */
|
| /* */
|
| -/* Copyright 1996-2012 */
|
| +/* Copyright 1996-2013 */
|
| /* by David Turner, Robert Wilhelm, and Werner Lemberg. */
|
| /* */
|
| /* This file is part of the FreeType project, and may only be used, */
|
| @@ -25,20 +25,16 @@
|
| #include FT_INTERNAL_CALC_H
|
| #include FT_TRIGONOMETRY_H
|
| #include FT_SYSTEM_H
|
| +#include FT_TRUETYPE_DRIVER_H
|
|
|
| #include "ttinterp.h"
|
| -
|
| #include "tterrors.h"
|
| +#include "ttsubpix.h"
|
|
|
|
|
| #ifdef TT_USE_BYTECODE_INTERPRETER
|
|
|
|
|
| -#define TT_MULFIX FT_MulFix
|
| -#define TT_MULDIV FT_MulDiv
|
| -#define TT_MULDIV_NO_ROUND FT_MulDiv_No_Round
|
| -
|
| -
|
| /*************************************************************************/
|
| /* */
|
| /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
| @@ -52,7 +48,7 @@
|
| /* */
|
| /* In order to detect infinite loops in the code, we set up a counter */
|
| /* within the run loop. A single stroke of interpretation is now */
|
| - /* limited to a maximal number of opcodes defined below. */
|
| + /* limited to a maximum number of opcodes defined below. */
|
| /* */
|
| #define MAX_RUNNABLE_OPCODES 1000000L
|
|
|
| @@ -136,6 +132,11 @@
|
| #define FT_UNUSED_ARG FT_UNUSED_EXEC; FT_UNUSED( args )
|
|
|
|
|
| +#define SUBPIXEL_HINTING \
|
| + ( ((TT_Driver)FT_FACE_DRIVER( CUR.face ))->interpreter_version == \
|
| + TT_INTERPRETER_VERSION_38 )
|
| +
|
| +
|
| /*************************************************************************/
|
| /* */
|
| /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to */
|
| @@ -232,6 +233,14 @@
|
| #define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) )
|
| #define BOUNDSL( x, n ) ( (FT_ULong)(x) >= (FT_ULong)(n) )
|
|
|
| + /*************************************************************************/
|
| + /* */
|
| + /* This macro computes (a*2^14)/b and complements TT_MulFix14. */
|
| + /* */
|
| +#define TT_DivFix14( a, b ) \
|
| + FT_DivFix( a, (b) << 2 )
|
| +
|
| +
|
| #undef SUCCESS
|
| #define SUCCESS 0
|
|
|
| @@ -301,7 +310,7 @@
|
| exec->IP = IP;
|
| exec->curRange = range;
|
|
|
| - return TT_Err_Ok;
|
| + return FT_Err_Ok;
|
| }
|
|
|
|
|
| @@ -337,7 +346,7 @@
|
| exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
|
| exec->codeRangeTable[range - 1].size = length;
|
|
|
| - return TT_Err_Ok;
|
| + return FT_Err_Ok;
|
| }
|
|
|
|
|
| @@ -370,7 +379,7 @@
|
| exec->codeRangeTable[range - 1].base = NULL;
|
| exec->codeRangeTable[range - 1].size = 0;
|
|
|
| - return TT_Err_Ok;
|
| + return FT_Err_Ok;
|
| }
|
|
|
|
|
| @@ -428,7 +437,7 @@
|
|
|
| FT_FREE( exec );
|
|
|
| - return TT_Err_Ok;
|
| + return FT_Err_Ok;
|
| }
|
|
|
|
|
| @@ -478,7 +487,7 @@
|
| exec->face = NULL;
|
| exec->size = NULL;
|
|
|
| - return TT_Err_Ok;
|
| + return FT_Err_Ok;
|
|
|
| Fail_Memory:
|
| FT_ERROR(( "Init_Context: not enough memory for %p\n", exec ));
|
| @@ -530,7 +539,7 @@
|
| *size = new_max;
|
| }
|
|
|
| - return TT_Err_Ok;
|
| + return FT_Err_Ok;
|
| }
|
|
|
|
|
| @@ -637,7 +646,7 @@
|
|
|
| exec->instruction_trap = FALSE;
|
|
|
| - return TT_Err_Ok;
|
| + return FT_Err_Ok;
|
| }
|
|
|
|
|
| @@ -680,7 +689,7 @@
|
| for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
|
| size->codeRangeTable[i] = exec->codeRangeTable[i];
|
|
|
| - return TT_Err_Ok;
|
| + return FT_Err_Ok;
|
| }
|
|
|
|
|
| @@ -716,7 +725,7 @@
|
|
|
|
|
| if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) )
|
| - != TT_Err_Ok )
|
| + != FT_Err_Ok )
|
| return error;
|
|
|
| exec->zp0 = exec->pts;
|
| @@ -753,7 +762,7 @@
|
| if ( !debug )
|
| return TT_RunIns( exec );
|
| else
|
| - return TT_Err_Ok;
|
| + return FT_Err_Ok;
|
| #endif
|
| }
|
|
|
| @@ -1463,7 +1472,7 @@
|
|
|
| #else
|
|
|
| - /* compute (a*b)/2^14 with maximal accuracy and rounding */
|
| + /* compute (a*b)/2^14 with maximum accuracy and rounding */
|
| static FT_Int32
|
| TT_MulFix14( FT_Int32 a,
|
| FT_Int b )
|
| @@ -1476,7 +1485,7 @@
|
| l = (FT_UInt32)( ( a & 0xFFFFU ) * b );
|
| m = ( a >> 16 ) * b;
|
|
|
| - lo = l + (FT_UInt32)( m << 16 );
|
| + lo = l + ( (FT_UInt32)m << 16 );
|
| hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l );
|
|
|
| /* divide the result by 2^14 with rounding */
|
| @@ -1488,12 +1497,12 @@
|
| l = lo + 0x2000U;
|
| hi += l < lo;
|
|
|
| - return ( hi << 18 ) | ( l >> 14 );
|
| + return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) );
|
| }
|
| #endif
|
|
|
|
|
| - /* compute (ax*bx+ay*by)/2^14 with maximal accuracy and rounding */
|
| + /* compute (ax*bx+ay*by)/2^14 with maximum accuracy and rounding */
|
| static FT_Int32
|
| TT_DotFix14( FT_Int32 ax,
|
| FT_Int32 ay,
|
| @@ -1508,14 +1517,14 @@
|
| l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx );
|
| m = ( ax >> 16 ) * bx;
|
|
|
| - lo1 = l + (FT_UInt32)( m << 16 );
|
| + lo1 = l + ( (FT_UInt32)m << 16 );
|
| hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l );
|
|
|
| /* compute ay*by as 64-bit value */
|
| l = (FT_UInt32)( ( ay & 0xFFFFU ) * by );
|
| m = ( ay >> 16 ) * by;
|
|
|
| - lo2 = l + (FT_UInt32)( m << 16 );
|
| + lo2 = l + ( (FT_UInt32)m << 16 );
|
| hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l );
|
|
|
| /* add them */
|
| @@ -1531,100 +1540,10 @@
|
| l = lo + 0x2000U;
|
| hi += ( l < lo );
|
|
|
| - return ( hi << 18 ) | ( l >> 14 );
|
| + return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) );
|
| }
|
|
|
|
|
| - /* return length of given vector */
|
| -
|
| -#if 0
|
| -
|
| - static FT_Int32
|
| - TT_VecLen( FT_Int32 x,
|
| - FT_Int32 y )
|
| - {
|
| - FT_Int32 m, hi1, hi2, hi;
|
| - FT_UInt32 l, lo1, lo2, lo;
|
| -
|
| -
|
| - /* compute x*x as 64-bit value */
|
| - lo = (FT_UInt32)( x & 0xFFFFU );
|
| - hi = x >> 16;
|
| -
|
| - l = lo * lo;
|
| - m = hi * lo;
|
| - hi = hi * hi;
|
| -
|
| - lo1 = l + (FT_UInt32)( m << 17 );
|
| - hi1 = hi + ( m >> 15 ) + ( lo1 < l );
|
| -
|
| - /* compute y*y as 64-bit value */
|
| - lo = (FT_UInt32)( y & 0xFFFFU );
|
| - hi = y >> 16;
|
| -
|
| - l = lo * lo;
|
| - m = hi * lo;
|
| - hi = hi * hi;
|
| -
|
| - lo2 = l + (FT_UInt32)( m << 17 );
|
| - hi2 = hi + ( m >> 15 ) + ( lo2 < l );
|
| -
|
| - /* add them to get 'x*x+y*y' as 64-bit value */
|
| - lo = lo1 + lo2;
|
| - hi = hi1 + hi2 + ( lo < lo1 );
|
| -
|
| - /* compute the square root of this value */
|
| - {
|
| - FT_UInt32 root, rem, test_div;
|
| - FT_Int count;
|
| -
|
| -
|
| - root = 0;
|
| -
|
| - {
|
| - rem = 0;
|
| - count = 32;
|
| - do
|
| - {
|
| - rem = ( rem << 2 ) | ( (FT_UInt32)hi >> 30 );
|
| - hi = ( hi << 2 ) | ( lo >> 30 );
|
| - lo <<= 2;
|
| - root <<= 1;
|
| - test_div = ( root << 1 ) + 1;
|
| -
|
| - if ( rem >= test_div )
|
| - {
|
| - rem -= test_div;
|
| - root += 1;
|
| - }
|
| - } while ( --count );
|
| - }
|
| -
|
| - return (FT_Int32)root;
|
| - }
|
| - }
|
| -
|
| -#else
|
| -
|
| - /* this version uses FT_Vector_Length which computes the same value */
|
| - /* much, much faster.. */
|
| - /* */
|
| - static FT_F26Dot6
|
| - TT_VecLen( FT_F26Dot6 X,
|
| - FT_F26Dot6 Y )
|
| - {
|
| - FT_Vector v;
|
| -
|
| -
|
| - v.x = X;
|
| - v.y = Y;
|
| -
|
| - return FT_Vector_Length( &v );
|
| - }
|
| -
|
| -#endif
|
| -
|
| -
|
| /*************************************************************************/
|
| /* */
|
| /* <Function> */
|
| @@ -1661,14 +1580,14 @@
|
|
|
| else
|
| {
|
| - FT_Long x, y;
|
| + FT_F26Dot6 x, y;
|
|
|
|
|
| - x = TT_MULDIV( CUR.GS.projVector.x,
|
| - CUR.tt_metrics.x_ratio, 0x4000 );
|
| - y = TT_MULDIV( CUR.GS.projVector.y,
|
| - CUR.tt_metrics.y_ratio, 0x4000 );
|
| - CUR.tt_metrics.ratio = TT_VecLen( x, y );
|
| + x = TT_MulFix14( CUR.tt_metrics.x_ratio,
|
| + CUR.GS.projVector.x );
|
| + y = TT_MulFix14( CUR.tt_metrics.y_ratio,
|
| + CUR.GS.projVector.y );
|
| + CUR.tt_metrics.ratio = FT_Hypot( x, y );
|
| }
|
| }
|
| }
|
| @@ -1679,7 +1598,7 @@
|
| static FT_Long
|
| Current_Ppem( EXEC_OP )
|
| {
|
| - return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() );
|
| + return FT_MulFix( CUR.tt_metrics.ppem, CURRENT_Ratio() );
|
| }
|
|
|
|
|
| @@ -1700,7 +1619,7 @@
|
| FT_CALLBACK_DEF( FT_F26Dot6 )
|
| Read_CVT_Stretched( EXEC_OP_ FT_ULong idx )
|
| {
|
| - return TT_MULFIX( CUR.cvt[idx], CURRENT_Ratio() );
|
| + return FT_MulFix( CUR.cvt[idx], CURRENT_Ratio() );
|
| }
|
|
|
|
|
| @@ -1786,7 +1705,7 @@
|
|
|
| if ( aRange < 1 || aRange > 3 )
|
| {
|
| - CUR.error = TT_Err_Bad_Argument;
|
| + CUR.error = FT_THROW( Bad_Argument );
|
| return FAILURE;
|
| }
|
|
|
| @@ -1794,7 +1713,7 @@
|
|
|
| if ( range->base == NULL ) /* invalid coderange */
|
| {
|
| - CUR.error = TT_Err_Invalid_CodeRange;
|
| + CUR.error = FT_THROW( Invalid_CodeRange );
|
| return FAILURE;
|
| }
|
|
|
| @@ -1804,7 +1723,7 @@
|
|
|
| if ( aIP > range->size )
|
| {
|
| - CUR.error = TT_Err_Code_Overflow;
|
| + CUR.error = FT_THROW( Code_Overflow );
|
| return FAILURE;
|
| }
|
|
|
| @@ -1850,9 +1769,12 @@
|
|
|
| if ( v != 0 )
|
| {
|
| - zone->cur[point].x += TT_MULDIV( distance,
|
| - v * 0x10000L,
|
| - CUR.F_dot_P );
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + if ( !SUBPIXEL_HINTING ||
|
| + ( !CUR.ignore_x_mode ||
|
| + ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| + zone->cur[point].x += FT_MulDiv( distance, v, CUR.F_dot_P );
|
|
|
| zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
|
| }
|
| @@ -1861,9 +1783,7 @@
|
|
|
| if ( v != 0 )
|
| {
|
| - zone->cur[point].y += TT_MULDIV( distance,
|
| - v * 0x10000L,
|
| - CUR.F_dot_P );
|
| + zone->cur[point].y += FT_MulDiv( distance, v, CUR.F_dot_P );
|
|
|
| zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
|
| }
|
| @@ -1902,16 +1822,12 @@
|
| v = CUR.GS.freeVector.x;
|
|
|
| if ( v != 0 )
|
| - zone->org[point].x += TT_MULDIV( distance,
|
| - v * 0x10000L,
|
| - CUR.F_dot_P );
|
| + zone->org[point].x += FT_MulDiv( distance, v, CUR.F_dot_P );
|
|
|
| v = CUR.GS.freeVector.y;
|
|
|
| if ( v != 0 )
|
| - zone->org[point].y += TT_MULDIV( distance,
|
| - v * 0x10000L,
|
| - CUR.F_dot_P );
|
| + zone->org[point].y += FT_MulDiv( distance, v, CUR.F_dot_P );
|
| }
|
|
|
|
|
| @@ -1932,7 +1848,12 @@
|
| {
|
| FT_UNUSED_EXEC;
|
|
|
| - zone->cur[point].x += distance;
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + if ( !SUBPIXEL_HINTING ||
|
| + !CUR.ignore_x_mode )
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| + zone->cur[point].x += distance;
|
| +
|
| zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
|
| }
|
|
|
| @@ -2193,7 +2114,7 @@
|
| }
|
| else
|
| {
|
| - val = - FT_PIX_CEIL( compensation - distance );
|
| + val = -FT_PIX_CEIL( compensation - distance );
|
| if ( val > 0 )
|
| val = 0;
|
| }
|
| @@ -2404,8 +2325,9 @@
|
| /* Sets Super Round parameters. */
|
| /* */
|
| /* <Input> */
|
| - /* GridPeriod :: Grid period */
|
| - /* selector :: SROUND opcode */
|
| + /* GridPeriod :: The grid period. */
|
| + /* */
|
| + /* selector :: The SROUND opcode. */
|
| /* */
|
| static void
|
| SetSuperRound( EXEC_OP_ FT_F26Dot6 GridPeriod,
|
| @@ -2617,13 +2539,10 @@
|
|
|
| if ( CUR.GS.dualVector.x == 0x4000 )
|
| CUR.func_dualproj = Project_x;
|
| + else if ( CUR.GS.dualVector.y == 0x4000 )
|
| + CUR.func_dualproj = Project_y;
|
| else
|
| - {
|
| - if ( CUR.GS.dualVector.y == 0x4000 )
|
| - CUR.func_dualproj = Project_y;
|
| - else
|
| - CUR.func_dualproj = Dual_Project;
|
| - }
|
| + CUR.func_dualproj = Dual_Project;
|
|
|
| /* Force recalculation of cached aspect ratio */
|
| CUR.tt_metrics.ratio = 0;
|
| @@ -2633,61 +2552,50 @@
|
| #endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */
|
|
|
| if ( CUR.GS.freeVector.x == 0x4000 )
|
| - CUR.F_dot_P = CUR.GS.projVector.x * 0x10000L;
|
| + CUR.F_dot_P = CUR.GS.projVector.x;
|
| + else if ( CUR.GS.freeVector.y == 0x4000 )
|
| + CUR.F_dot_P = CUR.GS.projVector.y;
|
| else
|
| - {
|
| - if ( CUR.GS.freeVector.y == 0x4000 )
|
| - CUR.F_dot_P = CUR.GS.projVector.y * 0x10000L;
|
| - else
|
| - CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 +
|
| - (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4;
|
| - }
|
| + CUR.F_dot_P = ( (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x +
|
| + (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y ) >>
|
| + 14;
|
|
|
| if ( CUR.GS.projVector.x == 0x4000 )
|
| CUR.func_project = (TT_Project_Func)Project_x;
|
| + else if ( CUR.GS.projVector.y == 0x4000 )
|
| + CUR.func_project = (TT_Project_Func)Project_y;
|
| else
|
| - {
|
| - if ( CUR.GS.projVector.y == 0x4000 )
|
| - CUR.func_project = (TT_Project_Func)Project_y;
|
| - else
|
| - CUR.func_project = (TT_Project_Func)Project;
|
| - }
|
| + CUR.func_project = (TT_Project_Func)Project;
|
|
|
| if ( CUR.GS.dualVector.x == 0x4000 )
|
| CUR.func_dualproj = (TT_Project_Func)Project_x;
|
| + else if ( CUR.GS.dualVector.y == 0x4000 )
|
| + CUR.func_dualproj = (TT_Project_Func)Project_y;
|
| else
|
| - {
|
| - if ( CUR.GS.dualVector.y == 0x4000 )
|
| - CUR.func_dualproj = (TT_Project_Func)Project_y;
|
| - else
|
| - CUR.func_dualproj = (TT_Project_Func)Dual_Project;
|
| - }
|
| + CUR.func_dualproj = (TT_Project_Func)Dual_Project;
|
|
|
| CUR.func_move = (TT_Move_Func)Direct_Move;
|
| CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig;
|
|
|
| - if ( CUR.F_dot_P == 0x40000000L )
|
| + if ( CUR.F_dot_P == 0x4000L )
|
| {
|
| if ( CUR.GS.freeVector.x == 0x4000 )
|
| {
|
| CUR.func_move = (TT_Move_Func)Direct_Move_X;
|
| CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
|
| }
|
| - else
|
| + else if ( CUR.GS.freeVector.y == 0x4000 )
|
| {
|
| - if ( CUR.GS.freeVector.y == 0x4000 )
|
| - {
|
| - CUR.func_move = (TT_Move_Func)Direct_Move_Y;
|
| - CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
|
| - }
|
| + CUR.func_move = (TT_Move_Func)Direct_Move_Y;
|
| + CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
|
| }
|
| }
|
|
|
| /* at small sizes, F_dot_P can become too small, resulting */
|
| /* in overflows and `spikes' in a number of glyphs like `w'. */
|
|
|
| - if ( FT_ABS( CUR.F_dot_P ) < 0x4000000L )
|
| - CUR.F_dot_P = 0x40000000L;
|
| + if ( FT_ABS( CUR.F_dot_P ) < 0x400L )
|
| + CUR.F_dot_P = 0x4000L;
|
|
|
| /* Disable cached aspect ratio */
|
| CUR.tt_metrics.ratio = 0;
|
| @@ -2716,98 +2624,33 @@
|
| /* In case Vx and Vy are both zero, Normalize() returns SUCCESS, and */
|
| /* R is undefined. */
|
| /* */
|
| -
|
| -
|
| static FT_Bool
|
| Normalize( EXEC_OP_ FT_F26Dot6 Vx,
|
| FT_F26Dot6 Vy,
|
| FT_UnitVector* R )
|
| {
|
| FT_F26Dot6 W;
|
| - FT_Bool S1, S2;
|
|
|
| FT_UNUSED_EXEC;
|
|
|
|
|
| - if ( FT_ABS( Vx ) < 0x10000L && FT_ABS( Vy ) < 0x10000L )
|
| + if ( FT_ABS( Vx ) < 0x4000L && FT_ABS( Vy ) < 0x4000L )
|
| {
|
| - Vx *= 0x100;
|
| - Vy *= 0x100;
|
| -
|
| - W = TT_VecLen( Vx, Vy );
|
| -
|
| - if ( W == 0 )
|
| + if ( Vx == 0 && Vy == 0 )
|
| {
|
| /* XXX: UNDOCUMENTED! It seems that it is possible to try */
|
| /* to normalize the vector (0,0). Return immediately. */
|
| return SUCCESS;
|
| }
|
|
|
| - R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W );
|
| - R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W );
|
| -
|
| - return SUCCESS;
|
| + Vx *= 0x4000;
|
| + Vy *= 0x4000;
|
| }
|
|
|
| - W = TT_VecLen( Vx, Vy );
|
| -
|
| - Vx = FT_MulDiv( Vx, 0x4000L, W );
|
| - Vy = FT_MulDiv( Vy, 0x4000L, W );
|
| -
|
| - W = Vx * Vx + Vy * Vy;
|
| -
|
| - /* Now, we want that Sqrt( W ) = 0x4000 */
|
| - /* Or 0x10000000 <= W < 0x10004000 */
|
| -
|
| - if ( Vx < 0 )
|
| - {
|
| - Vx = -Vx;
|
| - S1 = TRUE;
|
| - }
|
| - else
|
| - S1 = FALSE;
|
| + W = FT_Hypot( Vx, Vy );
|
|
|
| - if ( Vy < 0 )
|
| - {
|
| - Vy = -Vy;
|
| - S2 = TRUE;
|
| - }
|
| - else
|
| - S2 = FALSE;
|
| -
|
| - while ( W < 0x10000000L )
|
| - {
|
| - /* We need to increase W by a minimal amount */
|
| - if ( Vx < Vy )
|
| - Vx++;
|
| - else
|
| - Vy++;
|
| -
|
| - W = Vx * Vx + Vy * Vy;
|
| - }
|
| -
|
| - while ( W >= 0x10004000L )
|
| - {
|
| - /* We need to decrease W by a minimal amount */
|
| - if ( Vx < Vy )
|
| - Vx--;
|
| - else
|
| - Vy--;
|
| -
|
| - W = Vx * Vx + Vy * Vy;
|
| - }
|
| -
|
| - /* Note that in various cases, we can only */
|
| - /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */
|
| -
|
| - if ( S1 )
|
| - Vx = -Vx;
|
| -
|
| - if ( S2 )
|
| - Vy = -Vy;
|
| -
|
| - R->x = (FT_F2Dot14)Vx; /* Type conversion */
|
| - R->y = (FT_F2Dot14)Vy; /* Type conversion */
|
| + R->x = (FT_F2Dot14)TT_DivFix14( Vx, W );
|
| + R->y = (FT_F2Dot14)TT_DivFix14( Vy, W );
|
|
|
| return SUCCESS;
|
| }
|
| @@ -2835,7 +2678,7 @@
|
| BOUNDS( aIdx2, CUR.zp1.n_points ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return FAILURE;
|
| }
|
|
|
| @@ -3091,10 +2934,10 @@
|
| CUR.func_round = (TT_Round_Func)Round_Super_45;
|
|
|
|
|
| -#define DO_SLOOP \
|
| - if ( args[0] < 0 ) \
|
| - CUR.error = TT_Err_Bad_Argument; \
|
| - else \
|
| +#define DO_SLOOP \
|
| + if ( args[0] < 0 ) \
|
| + CUR.error = FT_THROW( Bad_Argument ); \
|
| + else \
|
| CUR.GS.loop = args[0];
|
|
|
|
|
| @@ -3110,14 +2953,9 @@
|
| CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];
|
|
|
|
|
| - /* XXX: UNDOCUMENTED! or bug in the Windows engine? */
|
| - /* */
|
| - /* It seems that the value that is read here is */
|
| - /* expressed in 16.16 format rather than in font */
|
| - /* units. */
|
| - /* */
|
| -#define DO_SSW \
|
| - CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 );
|
| +#define DO_SSW \
|
| + CUR.GS.single_width_value = FT_MulFix( args[0], \
|
| + CUR.tt_metrics.scale );
|
|
|
|
|
| #define DO_FLIPON \
|
| @@ -3181,21 +3019,21 @@
|
| args[0] = CUR.top;
|
|
|
|
|
| -#define DO_CINDEX \
|
| - { \
|
| - FT_Long L; \
|
| - \
|
| - \
|
| - L = args[0]; \
|
| - \
|
| - if ( L <= 0 || L > CUR.args ) \
|
| - { \
|
| - if ( CUR.pedantic_hinting ) \
|
| - CUR.error = TT_Err_Invalid_Reference; \
|
| - args[0] = 0; \
|
| - } \
|
| - else \
|
| - args[0] = CUR.stack[CUR.args - L]; \
|
| +#define DO_CINDEX \
|
| + { \
|
| + FT_Long L; \
|
| + \
|
| + \
|
| + L = args[0]; \
|
| + \
|
| + if ( L <= 0 || L > CUR.args ) \
|
| + { \
|
| + if ( CUR.pedantic_hinting ) \
|
| + CUR.error = FT_THROW( Invalid_Reference ); \
|
| + args[0] = 0; \
|
| + } \
|
| + else \
|
| + args[0] = CUR.stack[CUR.args - L]; \
|
| }
|
|
|
|
|
| @@ -3203,24 +3041,24 @@
|
| if ( args[1] != 0 ) \
|
| { \
|
| if ( args[0] == 0 && CUR.args == 0 ) \
|
| - CUR.error = TT_Err_Bad_Argument; \
|
| + CUR.error = FT_THROW( Bad_Argument ); \
|
| CUR.IP += args[0]; \
|
| if ( CUR.IP < 0 || \
|
| ( CUR.callTop > 0 && \
|
| CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \
|
| - CUR.error = TT_Err_Bad_Argument; \
|
| + CUR.error = FT_THROW( Bad_Argument ); \
|
| CUR.step_ins = FALSE; \
|
| }
|
|
|
|
|
| #define DO_JMPR \
|
| if ( args[0] == 0 && CUR.args == 0 ) \
|
| - CUR.error = TT_Err_Bad_Argument; \
|
| + CUR.error = FT_THROW( Bad_Argument ); \
|
| CUR.IP += args[0]; \
|
| if ( CUR.IP < 0 || \
|
| ( CUR.callTop > 0 && \
|
| CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \
|
| - CUR.error = TT_Err_Bad_Argument; \
|
| + CUR.error = FT_THROW( Bad_Argument ); \
|
| CUR.step_ins = FALSE;
|
|
|
|
|
| @@ -3228,12 +3066,12 @@
|
| if ( args[1] == 0 ) \
|
| { \
|
| if ( args[0] == 0 && CUR.args == 0 ) \
|
| - CUR.error = TT_Err_Bad_Argument; \
|
| + CUR.error = FT_THROW( Bad_Argument ); \
|
| CUR.IP += args[0]; \
|
| if ( CUR.IP < 0 || \
|
| ( CUR.callTop > 0 && \
|
| CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \
|
| - CUR.error = TT_Err_Bad_Argument; \
|
| + CUR.error = FT_THROW( Bad_Argument ); \
|
| CUR.step_ins = FALSE; \
|
| }
|
|
|
| @@ -3292,13 +3130,13 @@
|
|
|
| #define DO_DIV \
|
| if ( args[1] == 0 ) \
|
| - CUR.error = TT_Err_Divide_By_Zero; \
|
| + CUR.error = FT_THROW( Divide_By_Zero ); \
|
| else \
|
| - args[0] = TT_MULDIV_NO_ROUND( args[0], 64L, args[1] );
|
| + args[0] = FT_MulDiv_No_Round( args[0], 64L, args[1] );
|
|
|
|
|
| #define DO_MUL \
|
| - args[0] = TT_MULDIV( args[0], args[1], 64L );
|
| + args[0] = FT_MulDiv( args[0], args[1], 64L );
|
|
|
|
|
| #define DO_ABS \
|
| @@ -3316,6 +3154,45 @@
|
| #define DO_CEILING \
|
| args[0] = FT_PIX_CEIL( args[0] );
|
|
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| +
|
| +#define DO_RS \
|
| + { \
|
| + FT_ULong I = (FT_ULong)args[0]; \
|
| + \
|
| + \
|
| + if ( BOUNDSL( I, CUR.storeSize ) ) \
|
| + { \
|
| + if ( CUR.pedantic_hinting ) \
|
| + ARRAY_BOUND_ERROR; \
|
| + else \
|
| + args[0] = 0; \
|
| + } \
|
| + else \
|
| + { \
|
| + /* subpixel hinting - avoid Typeman Dstroke and */ \
|
| + /* IStroke and Vacuform rounds */ \
|
| + \
|
| + if ( SUBPIXEL_HINTING && \
|
| + CUR.ignore_x_mode && \
|
| + ( ( I == 24 && \
|
| + ( CUR.face->sph_found_func_flags & \
|
| + ( SPH_FDEF_SPACING_1 | \
|
| + SPH_FDEF_SPACING_2 ) ) ) || \
|
| + ( I == 22 && \
|
| + ( CUR.sph_in_func_flags & \
|
| + SPH_FDEF_TYPEMAN_STROKES ) ) || \
|
| + ( I == 8 && \
|
| + ( CUR.face->sph_found_func_flags & \
|
| + SPH_FDEF_VACUFORM_ROUND_1 ) && \
|
| + CUR.iup_called ) ) ) \
|
| + args[0] = 0; \
|
| + else \
|
| + args[0] = CUR.storage[I]; \
|
| + } \
|
| + }
|
| +
|
| +#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
|
|
| #define DO_RS \
|
| { \
|
| @@ -3335,6 +3212,8 @@
|
| args[0] = CUR.storage[I]; \
|
| }
|
|
|
| +#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
|
|
| #define DO_WS \
|
| { \
|
| @@ -3402,12 +3281,12 @@
|
| } \
|
| } \
|
| else \
|
| - CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \
|
| + CUR.cvt[I] = FT_MulFix( args[1], CUR.tt_metrics.scale ); \
|
| }
|
|
|
|
|
| -#define DO_DEBUG \
|
| - CUR.error = TT_Err_Debug_OpCode;
|
| +#define DO_DEBUG \
|
| + CUR.error = FT_THROW( Debug_OpCode );
|
|
|
|
|
| #define DO_ROUND \
|
| @@ -3435,10 +3314,10 @@
|
|
|
|
|
| #undef ARRAY_BOUND_ERROR
|
| -#define ARRAY_BOUND_ERROR \
|
| - { \
|
| - CUR.error = TT_Err_Invalid_Reference; \
|
| - return; \
|
| +#define ARRAY_BOUND_ERROR \
|
| + { \
|
| + CUR.error = FT_THROW( Invalid_Reference ); \
|
| + return; \
|
| }
|
|
|
|
|
| @@ -4417,7 +4296,7 @@
|
| if ( L <= 0 || L > CUR.args )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| }
|
| else
|
| {
|
| @@ -4487,7 +4366,7 @@
|
| }
|
|
|
| Fail_Overflow:
|
| - CUR.error = TT_Err_Code_Overflow;
|
| + CUR.error = FT_THROW( Code_Overflow );
|
| return FAILURE;
|
| }
|
|
|
| @@ -4592,6 +4471,106 @@
|
| TT_DefRecord* rec;
|
| TT_DefRecord* limit;
|
|
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + /* arguments to opcodes are skipped by `SKIP_Code' */
|
| + FT_Byte opcode_pattern[9][12] = {
|
| + /* #0 inline delta function 1 */
|
| + {
|
| + 0x4B, /* PPEM */
|
| + 0x53, /* GTEQ */
|
| + 0x23, /* SWAP */
|
| + 0x4B, /* PPEM */
|
| + 0x51, /* LTEQ */
|
| + 0x5A, /* AND */
|
| + 0x58, /* IF */
|
| + 0x38, /* SHPIX */
|
| + 0x1B, /* ELSE */
|
| + 0x21, /* POP */
|
| + 0x21, /* POP */
|
| + 0x59 /* EIF */
|
| + },
|
| + /* #1 inline delta function 2 */
|
| + {
|
| + 0x4B, /* PPEM */
|
| + 0x54, /* EQ */
|
| + 0x58, /* IF */
|
| + 0x38, /* SHPIX */
|
| + 0x1B, /* ELSE */
|
| + 0x21, /* POP */
|
| + 0x21, /* POP */
|
| + 0x59 /* EIF */
|
| + },
|
| + /* #2 diagonal stroke function */
|
| + {
|
| + 0x20, /* DUP */
|
| + 0x20, /* DUP */
|
| + 0xB0, /* PUSHB_1 */
|
| + /* 1 */
|
| + 0x60, /* ADD */
|
| + 0x46, /* GC_cur */
|
| + 0xB0, /* PUSHB_1 */
|
| + /* 64 */
|
| + 0x23, /* SWAP */
|
| + 0x42 /* WS */
|
| + },
|
| + /* #3 VacuFormRound function */
|
| + {
|
| + 0x45, /* RCVT */
|
| + 0x23, /* SWAP */
|
| + 0x46, /* GC_cur */
|
| + 0x60, /* ADD */
|
| + 0x20, /* DUP */
|
| + 0xB0 /* PUSHB_1 */
|
| + /* 38 */
|
| + },
|
| + /* #4 TTFautohint bytecode (old) */
|
| + {
|
| + 0x20, /* DUP */
|
| + 0x64, /* ABS */
|
| + 0xB0, /* PUSHB_1 */
|
| + /* 32 */
|
| + 0x60, /* ADD */
|
| + 0x66, /* FLOOR */
|
| + 0x23, /* SWAP */
|
| + 0xB0 /* PUSHB_1 */
|
| + },
|
| + /* #5 spacing function 1 */
|
| + {
|
| + 0x01, /* SVTCA_x */
|
| + 0xB0, /* PUSHB_1 */
|
| + /* 24 */
|
| + 0x43, /* RS */
|
| + 0x58 /* IF */
|
| + },
|
| + /* #6 spacing function 2 */
|
| + {
|
| + 0x01, /* SVTCA_x */
|
| + 0x18, /* RTG */
|
| + 0xB0, /* PUSHB_1 */
|
| + /* 24 */
|
| + 0x43, /* RS */
|
| + 0x58 /* IF */
|
| + },
|
| + /* #7 TypeMan Talk DiagEndCtrl function */
|
| + {
|
| + 0x01, /* SVTCA_x */
|
| + 0x20, /* DUP */
|
| + 0xB0, /* PUSHB_1 */
|
| + /* 3 */
|
| + 0x25, /* CINDEX */
|
| + },
|
| + /* #8 TypeMan Talk Align */
|
| + {
|
| + 0x06, /* SPVTL */
|
| + 0x7D, /* RDTG */
|
| + },
|
| + };
|
| + FT_UShort opcode_patterns = 9;
|
| + FT_UShort opcode_pointer[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
| + FT_UShort opcode_size[9] = { 12, 8, 8, 6, 7, 4, 5, 4, 2 };
|
| + FT_UShort i;
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
|
|
| /* some font programs are broken enough to redefine functions! */
|
| /* We will then parse the current table. */
|
| @@ -4611,7 +4590,7 @@
|
| /* check that there is enough room for new functions */
|
| if ( CUR.numFDefs >= CUR.maxFDefs )
|
| {
|
| - CUR.error = TT_Err_Too_Many_Function_Defs;
|
| + CUR.error = FT_THROW( Too_Many_Function_Defs );
|
| return;
|
| }
|
| CUR.numFDefs++;
|
| @@ -4621,28 +4600,149 @@
|
| /* func # must be within unsigned 16-bit integer */
|
| if ( n > 0xFFFFU )
|
| {
|
| - CUR.error = TT_Err_Too_Many_Function_Defs;
|
| + CUR.error = FT_THROW( Too_Many_Function_Defs );
|
| return;
|
| }
|
|
|
| - rec->range = CUR.curRange;
|
| - rec->opc = (FT_UInt16)n;
|
| - rec->start = CUR.IP + 1;
|
| - rec->active = TRUE;
|
| + rec->range = CUR.curRange;
|
| + rec->opc = (FT_UInt16)n;
|
| + rec->start = CUR.IP + 1;
|
| + rec->active = TRUE;
|
| + rec->inline_delta = FALSE;
|
| + rec->sph_fdef_flags = 0x0000;
|
|
|
| if ( n > CUR.maxFunc )
|
| CUR.maxFunc = (FT_UInt16)n;
|
|
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + /* We don't know for sure these are typeman functions, */
|
| + /* however they are only active when RS 22 is called */
|
| + if ( n >= 64 && n <= 66 )
|
| + rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_STROKES;
|
| +#endif
|
| +
|
| /* Now skip the whole function definition. */
|
| /* We don't allow nested IDEFS & FDEFs. */
|
|
|
| while ( SKIP_Code() == SUCCESS )
|
| {
|
| +
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| +
|
| + if ( SUBPIXEL_HINTING )
|
| + {
|
| + for ( i = 0; i < opcode_patterns; i++ )
|
| + {
|
| + if ( opcode_pointer[i] < opcode_size[i] &&
|
| + CUR.opcode == opcode_pattern[i][opcode_pointer[i]] )
|
| + {
|
| + opcode_pointer[i] += 1;
|
| +
|
| + if ( opcode_pointer[i] == opcode_size[i] )
|
| + {
|
| + FT_TRACE7(( "sph: Function %d, opcode ptrn: %d, %s %s\n",
|
| + i, n,
|
| + CUR.face->root.family_name,
|
| + CUR.face->root.style_name ));
|
| +
|
| + switch ( i )
|
| + {
|
| + case 0:
|
| + rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_1;
|
| + CUR.face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_1;
|
| + break;
|
| +
|
| + case 1:
|
| + rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_2;
|
| + CUR.face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_2;
|
| + break;
|
| +
|
| + case 2:
|
| + switch ( n )
|
| + {
|
| + /* needs to be implemented still */
|
| + case 58:
|
| + rec->sph_fdef_flags |= SPH_FDEF_DIAGONAL_STROKE;
|
| + CUR.face->sph_found_func_flags |= SPH_FDEF_DIAGONAL_STROKE;
|
| + }
|
| + break;
|
| +
|
| + case 3:
|
| + switch ( n )
|
| + {
|
| + case 0:
|
| + rec->sph_fdef_flags |= SPH_FDEF_VACUFORM_ROUND_1;
|
| + CUR.face->sph_found_func_flags |= SPH_FDEF_VACUFORM_ROUND_1;
|
| + }
|
| + break;
|
| +
|
| + case 4:
|
| + /* probably not necessary to detect anymore */
|
| + rec->sph_fdef_flags |= SPH_FDEF_TTFAUTOHINT_1;
|
| + CUR.face->sph_found_func_flags |= SPH_FDEF_TTFAUTOHINT_1;
|
| + break;
|
| +
|
| + case 5:
|
| + switch ( n )
|
| + {
|
| + case 0:
|
| + case 1:
|
| + case 2:
|
| + case 4:
|
| + case 7:
|
| + case 8:
|
| + rec->sph_fdef_flags |= SPH_FDEF_SPACING_1;
|
| + CUR.face->sph_found_func_flags |= SPH_FDEF_SPACING_1;
|
| + }
|
| + break;
|
| +
|
| + case 6:
|
| + switch ( n )
|
| + {
|
| + case 0:
|
| + case 1:
|
| + case 2:
|
| + case 4:
|
| + case 7:
|
| + case 8:
|
| + rec->sph_fdef_flags |= SPH_FDEF_SPACING_2;
|
| + CUR.face->sph_found_func_flags |= SPH_FDEF_SPACING_2;
|
| + }
|
| + break;
|
| +
|
| + case 7:
|
| + rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
|
| + CUR.face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
|
| + break;
|
| +
|
| + case 8:
|
| +#if 0
|
| + rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
|
| + CUR.face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
|
| +#endif
|
| + break;
|
| + }
|
| + opcode_pointer[i] = 0;
|
| + }
|
| + }
|
| +
|
| + else
|
| + opcode_pointer[i] = 0;
|
| + }
|
| +
|
| + /* Set sph_compatibility_mode only when deltas are detected */
|
| + CUR.face->sph_compatibility_mode =
|
| + ( ( CUR.face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_1 ) |
|
| + ( CUR.face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) );
|
| + }
|
| +
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| switch ( CUR.opcode )
|
| {
|
| case 0x89: /* IDEF */
|
| case 0x2C: /* FDEF */
|
| - CUR.error = TT_Err_Nested_DEFS;
|
| + CUR.error = FT_THROW( Nested_DEFS );
|
| return;
|
|
|
| case 0x2D: /* ENDF */
|
| @@ -4667,9 +4767,13 @@
|
| FT_UNUSED_ARG;
|
|
|
|
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + CUR.sph_in_func_flags = 0x0000;
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| if ( CUR.callTop <= 0 ) /* We encountered an ENDF without a call */
|
| {
|
| - CUR.error = TT_Err_ENDF_In_Exec_Stream;
|
| + CUR.error = FT_THROW( ENDF_In_Exec_Stream );
|
| return;
|
| }
|
|
|
| @@ -4751,10 +4855,21 @@
|
| if ( !def->active )
|
| goto Fail;
|
|
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode &&
|
| + ( ( CUR.iup_called &&
|
| + ( CUR.sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) ||
|
| + ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) )
|
| + goto Fail;
|
| + else
|
| + CUR.sph_in_func_flags = def->sph_fdef_flags;
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| /* check the call stack */
|
| if ( CUR.callTop >= CUR.callSize )
|
| {
|
| - CUR.error = TT_Err_Stack_Overflow;
|
| + CUR.error = FT_THROW( Stack_Overflow );
|
| return;
|
| }
|
|
|
| @@ -4772,10 +4887,11 @@
|
| def->start );
|
|
|
| CUR.step_ins = FALSE;
|
| +
|
| return;
|
|
|
| Fail:
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| }
|
|
|
|
|
| @@ -4828,10 +4944,19 @@
|
| if ( !def->active )
|
| goto Fail;
|
|
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode &&
|
| + ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) )
|
| + goto Fail;
|
| + else
|
| + CUR.sph_in_func_flags = def->sph_fdef_flags;
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| /* check stack */
|
| if ( CUR.callTop >= CUR.callSize )
|
| {
|
| - CUR.error = TT_Err_Stack_Overflow;
|
| + CUR.error = FT_THROW( Stack_Overflow );
|
| return;
|
| }
|
|
|
| @@ -4851,10 +4976,11 @@
|
|
|
| CUR.step_ins = FALSE;
|
| }
|
| +
|
| return;
|
|
|
| Fail:
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| }
|
|
|
|
|
| @@ -4885,7 +5011,7 @@
|
| /* check that there is enough room for a new instruction */
|
| if ( CUR.numIDefs >= CUR.maxIDefs )
|
| {
|
| - CUR.error = TT_Err_Too_Many_Instruction_Defs;
|
| + CUR.error = FT_THROW( Too_Many_Instruction_Defs );
|
| return;
|
| }
|
| CUR.numIDefs++;
|
| @@ -4894,7 +5020,7 @@
|
| /* opcode must be unsigned 8-bit integer */
|
| if ( 0 > args[0] || args[0] > 0x00FF )
|
| {
|
| - CUR.error = TT_Err_Too_Many_Instruction_Defs;
|
| + CUR.error = FT_THROW( Too_Many_Instruction_Defs );
|
| return;
|
| }
|
|
|
| @@ -4915,7 +5041,7 @@
|
| {
|
| case 0x89: /* IDEF */
|
| case 0x2C: /* FDEF */
|
| - CUR.error = TT_Err_Nested_DEFS;
|
| + CUR.error = FT_THROW( Nested_DEFS );
|
| return;
|
| case 0x2D: /* ENDF */
|
| return;
|
| @@ -4949,7 +5075,7 @@
|
|
|
| if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
|
| {
|
| - CUR.error = TT_Err_Stack_Overflow;
|
| + CUR.error = FT_THROW( Stack_Overflow );
|
| return;
|
| }
|
|
|
| @@ -4976,7 +5102,7 @@
|
|
|
| if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
|
| {
|
| - CUR.error = TT_Err_Stack_Overflow;
|
| + CUR.error = FT_THROW( Stack_Overflow );
|
| return;
|
| }
|
|
|
| @@ -5006,7 +5132,7 @@
|
|
|
| if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
|
| {
|
| - CUR.error = TT_Err_Stack_Overflow;
|
| + CUR.error = FT_THROW( Stack_Overflow );
|
| return;
|
| }
|
|
|
| @@ -5031,7 +5157,7 @@
|
|
|
| if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
|
| {
|
| - CUR.error = TT_Err_Stack_Overflow;
|
| + CUR.error = FT_THROW( Stack_Overflow );
|
| return;
|
| }
|
|
|
| @@ -5074,7 +5200,7 @@
|
| if ( BOUNDSL( L, CUR.zp2.n_points ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| R = 0;
|
| }
|
| else
|
| @@ -5111,7 +5237,7 @@
|
| if ( BOUNDS( L, CUR.zp2.n_points ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
|
|
| @@ -5155,7 +5281,7 @@
|
| BOUNDS( K, CUR.zp1.n_points ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| D = 0;
|
| }
|
| else
|
| @@ -5184,15 +5310,15 @@
|
| {
|
| /* this should be faster */
|
| D = CUR_Func_dualproj( vec1, vec2 );
|
| - D = TT_MULFIX( D, CUR.metrics.x_scale );
|
| + D = FT_MulFix( D, CUR.metrics.x_scale );
|
| }
|
| else
|
| {
|
| FT_Vector vec;
|
|
|
|
|
| - vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
|
| - vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
|
| + vec.x = FT_MulFix( vec1->x - vec2->x, CUR.metrics.x_scale );
|
| + vec.y = FT_MulFix( vec1->y - vec2->y, CUR.metrics.y_scale );
|
|
|
| D = CUR_fast_dualproj( &vec );
|
| }
|
| @@ -5200,6 +5326,13 @@
|
| }
|
| }
|
|
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode && FT_ABS( D ) == 64 )
|
| + D += 1;
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| args[0] = D;
|
| }
|
|
|
| @@ -5225,7 +5358,7 @@
|
| BOUNDS( p1, CUR.zp2.n_points ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
|
|
| @@ -5265,6 +5398,12 @@
|
|
|
| A = v1->x - v2->x;
|
| B = v1->y - v2->y;
|
| +
|
| + if ( A == 0 && B == 0 )
|
| + {
|
| + A = 0x4000;
|
| + aOpc = 0;
|
| + }
|
| }
|
|
|
| if ( ( aOpc & 1 ) != 0 )
|
| @@ -5303,7 +5442,7 @@
|
|
|
| default:
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
|
|
| @@ -5332,7 +5471,7 @@
|
|
|
| default:
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
|
|
| @@ -5361,7 +5500,7 @@
|
|
|
| default:
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
|
|
| @@ -5390,7 +5529,7 @@
|
|
|
| default:
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
|
|
| @@ -5421,7 +5560,7 @@
|
| if ( K < 1 || K > 2 )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
|
|
| @@ -5519,7 +5658,7 @@
|
| if ( CUR.top < CUR.GS.loop )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Too_Few_Arguments;
|
| + CUR.error = FT_THROW( Too_Few_Arguments );
|
| goto Fail;
|
| }
|
|
|
| @@ -5533,7 +5672,7 @@
|
| {
|
| if ( CUR.pedantic_hinting )
|
| {
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
| }
|
| @@ -5568,7 +5707,7 @@
|
| BOUNDS( L, CUR.pts.n_points ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
|
|
| @@ -5596,7 +5735,7 @@
|
| BOUNDS( L, CUR.pts.n_points ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
|
|
| @@ -5630,7 +5769,7 @@
|
| if ( BOUNDS( p, zp.n_points ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| *refp = 0;
|
| return FAILURE;
|
| }
|
| @@ -5657,12 +5796,8 @@
|
| else
|
| #endif
|
| {
|
| - *x = TT_MULDIV( d,
|
| - (FT_Long)CUR.GS.freeVector.x * 0x10000L,
|
| - CUR.F_dot_P );
|
| - *y = TT_MULDIV( d,
|
| - (FT_Long)CUR.GS.freeVector.y * 0x10000L,
|
| - CUR.F_dot_P );
|
| + *x = FT_MulDiv( d, (FT_Long)CUR.GS.freeVector.x, CUR.F_dot_P );
|
| + *y = FT_MulDiv( d, (FT_Long)CUR.GS.freeVector.y, CUR.F_dot_P );
|
| }
|
|
|
| return SUCCESS;
|
| @@ -5732,7 +5867,7 @@
|
| if ( CUR.top < CUR.GS.loop )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| goto Fail;
|
| }
|
|
|
| @@ -5748,11 +5883,18 @@
|
| {
|
| if ( CUR.pedantic_hinting )
|
| {
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
| }
|
| else
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + /* doesn't follow Cleartype spec but produces better result */
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode )
|
| + MOVE_Zp2_Point( point, 0, dy, TRUE );
|
| + else
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| MOVE_Zp2_Point( point, dx, dy, TRUE );
|
|
|
| CUR.GS.loop--;
|
| @@ -5772,7 +5914,7 @@
|
| /* */
|
| /* UNDOCUMENTED: According to Greg Hitchcock, there is one (virtual) */
|
| /* contour in the twilight zone, namely contour number */
|
| - /* zero. */
|
| + /* zero which includes all points of it. */
|
| /* */
|
| static void
|
| Ins_SHC( INS_ARG )
|
| @@ -5791,7 +5933,7 @@
|
| if ( BOUNDS( contour, bounds ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
|
|
| @@ -5839,7 +5981,7 @@
|
| if ( BOUNDS( args[0], 2 ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
|
|
| @@ -5877,12 +6019,15 @@
|
| {
|
| FT_F26Dot6 dx, dy;
|
| FT_UShort point;
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + FT_Int B1, B2;
|
| +#endif
|
|
|
|
|
| if ( CUR.top < CUR.GS.loop + 1 )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| goto Fail;
|
| }
|
|
|
| @@ -5891,13 +6036,13 @@
|
| {
|
| if ( CUR.GS.both_x_axis )
|
| {
|
| - dx = TT_MulFix14( (FT_UInt32)args[0], 0x4000 );
|
| + dx = (FT_UInt32)args[0];
|
| dy = 0;
|
| }
|
| else
|
| {
|
| dx = 0;
|
| - dy = TT_MulFix14( (FT_UInt32)args[0], 0x4000 );
|
| + dy = (FT_UInt32)args[0];
|
| }
|
| }
|
| else
|
| @@ -5917,13 +6062,95 @@
|
| {
|
| if ( CUR.pedantic_hinting )
|
| {
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
| }
|
| else
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + {
|
| + /* If not using ignore_x_mode rendering, allow ZP2 move. */
|
| + /* If inline deltas aren't allowed, skip ZP2 move. */
|
| + /* If using ignore_x_mode rendering, allow ZP2 point move if: */
|
| + /* - freedom vector is y and sph_compatibility_mode is off */
|
| + /* - the glyph is composite and the move is in the Y direction */
|
| + /* - the glyph is specifically set to allow SHPIX moves */
|
| + /* - the move is on a previously Y-touched point */
|
| +
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode )
|
| + {
|
| + /* save point for later comparison */
|
| + if ( CUR.GS.freeVector.y != 0 )
|
| + B1 = CUR.zp2.cur[point].y;
|
| + else
|
| + B1 = CUR.zp2.cur[point].x;
|
| +
|
| + if ( !CUR.face->sph_compatibility_mode &&
|
| + CUR.GS.freeVector.y != 0 )
|
| + {
|
| + MOVE_Zp2_Point( point, dx, dy, TRUE );
|
| +
|
| + /* save new point */
|
| + if ( CUR.GS.freeVector.y != 0 )
|
| + {
|
| + B2 = CUR.zp2.cur[point].y;
|
| +
|
| + /* reverse any disallowed moves */
|
| + if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
|
| + ( B1 & 63 ) != 0 &&
|
| + ( B2 & 63 ) != 0 &&
|
| + B1 != B2 )
|
| + MOVE_Zp2_Point( point, -dx, -dy, TRUE );
|
| + }
|
| + }
|
| + else if ( CUR.face->sph_compatibility_mode )
|
| + {
|
| + if ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
|
| + {
|
| + dx = FT_PIX_ROUND( B1 + dx ) - B1;
|
| + dy = FT_PIX_ROUND( B1 + dy ) - B1;
|
| + }
|
| +
|
| + /* skip post-iup deltas */
|
| + if ( CUR.iup_called &&
|
| + ( ( CUR.sph_in_func_flags & SPH_FDEF_INLINE_DELTA_1 ) ||
|
| + ( CUR.sph_in_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ) )
|
| + goto Skip;
|
| +
|
| + if ( !( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) &&
|
| + ( ( CUR.is_composite && CUR.GS.freeVector.y != 0 ) ||
|
| + ( CUR.zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y ) ||
|
| + ( CUR.sph_tweak_flags & SPH_TWEAK_DO_SHPIX ) ) )
|
| + MOVE_Zp2_Point( point, 0, dy, TRUE );
|
| +
|
| + /* save new point */
|
| + if ( CUR.GS.freeVector.y != 0 )
|
| + {
|
| + B2 = CUR.zp2.cur[point].y;
|
| +
|
| + /* reverse any disallowed moves */
|
| + if ( ( B1 & 63 ) == 0 &&
|
| + ( B2 & 63 ) != 0 &&
|
| + B1 != B2 )
|
| + MOVE_Zp2_Point( point, 0, -dy, TRUE );
|
| + }
|
| + }
|
| + else if ( CUR.sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL )
|
| + MOVE_Zp2_Point( point, dx, dy, TRUE );
|
| + }
|
| + else
|
| + MOVE_Zp2_Point( point, dx, dy, TRUE );
|
| + }
|
| +
|
| + Skip:
|
| +
|
| +#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| MOVE_Zp2_Point( point, dx, dy, TRUE );
|
|
|
| +#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| CUR.GS.loop--;
|
| }
|
|
|
| @@ -5945,6 +6172,21 @@
|
| FT_UShort point;
|
| FT_F26Dot6 distance;
|
|
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + FT_F26Dot6 control_value_cutin;
|
| +
|
| +
|
| + if ( SUBPIXEL_HINTING )
|
| + {
|
| + control_value_cutin = CUR.GS.control_value_cutin;
|
| +
|
| + if ( CUR.ignore_x_mode &&
|
| + CUR.GS.freeVector.x != 0 &&
|
| + !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
|
| + control_value_cutin = 0;
|
| + }
|
| +
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
|
|
| point = (FT_UShort)args[0];
|
|
|
| @@ -5952,7 +6194,7 @@
|
| BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
|
|
| @@ -5968,6 +6210,15 @@
|
| distance = CUR_Func_project( CUR.zp1.cur + point,
|
| CUR.zp0.cur + CUR.GS.rp0 );
|
|
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + /* subpixel hinting - make MSIRP respect CVT cut-in; */
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode &&
|
| + CUR.GS.freeVector.x != 0 &&
|
| + FT_ABS( distance - args[1] ) >= control_value_cutin )
|
| + distance = args[1];
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| CUR_Func_move( &CUR.zp1, point, args[1] - distance );
|
|
|
| CUR.GS.rp1 = CUR.GS.rp0;
|
| @@ -5988,8 +6239,8 @@
|
| Ins_MDAP( INS_ARG )
|
| {
|
| FT_UShort point;
|
| - FT_F26Dot6 cur_dist,
|
| - distance;
|
| + FT_F26Dot6 cur_dist;
|
| + FT_F26Dot6 distance;
|
|
|
|
|
| point = (FT_UShort)args[0];
|
| @@ -5997,15 +6248,25 @@
|
| if ( BOUNDS( point, CUR.zp0.n_points ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
|
|
| if ( ( CUR.opcode & 1 ) != 0 )
|
| {
|
| cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
|
| - distance = CUR_Func_round( cur_dist,
|
| - CUR.tt_metrics.compensations[0] ) - cur_dist;
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode &&
|
| + CUR.GS.freeVector.x != 0 )
|
| + distance = ROUND_None(
|
| + cur_dist,
|
| + CUR.tt_metrics.compensations[0] ) - cur_dist;
|
| + else
|
| +#endif
|
| + distance = CUR_Func_round(
|
| + cur_dist,
|
| + CUR.tt_metrics.compensations[0] ) - cur_dist;
|
| }
|
| else
|
| distance = 0;
|
| @@ -6028,18 +6289,29 @@
|
| {
|
| FT_ULong cvtEntry;
|
| FT_UShort point;
|
| - FT_F26Dot6 distance,
|
| - org_dist;
|
| + FT_F26Dot6 distance;
|
| + FT_F26Dot6 org_dist;
|
| + FT_F26Dot6 control_value_cutin;
|
|
|
|
|
| - cvtEntry = (FT_ULong)args[1];
|
| - point = (FT_UShort)args[0];
|
| + control_value_cutin = CUR.GS.control_value_cutin;
|
| + cvtEntry = (FT_ULong)args[1];
|
| + point = (FT_UShort)args[0];
|
| +
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode &&
|
| + CUR.GS.freeVector.x != 0 &&
|
| + CUR.GS.freeVector.y == 0 &&
|
| + !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
|
| + control_value_cutin = 0;
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
|
|
| if ( BOUNDS( point, CUR.zp0.n_points ) ||
|
| BOUNDSL( cvtEntry, CUR.cvtSize ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| goto Fail;
|
| }
|
|
|
| @@ -6067,21 +6339,45 @@
|
|
|
| if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */
|
| {
|
| - CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance,
|
| - CUR.GS.freeVector.x );
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + /* Only adjust if not in sph_compatibility_mode or ignore_x_mode. */
|
| + /* Determined via experimentation and may be incorrect... */
|
| + if ( !SUBPIXEL_HINTING ||
|
| + ( !CUR.ignore_x_mode ||
|
| + !CUR.face->sph_compatibility_mode ) )
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| + CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance,
|
| + CUR.GS.freeVector.x );
|
| CUR.zp0.org[point].y = TT_MulFix14( (FT_UInt32)distance,
|
| CUR.GS.freeVector.y ),
|
| CUR.zp0.cur[point] = CUR.zp0.org[point];
|
| }
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode &&
|
| + ( CUR.sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) &&
|
| + distance > 0 &&
|
| + CUR.GS.freeVector.y != 0 )
|
| + distance = 0;
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
|
|
| org_dist = CUR_fast_project( &CUR.zp0.cur[point] );
|
|
|
| - if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cutin flag */
|
| + if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cut-in flag */
|
| {
|
| - if ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin )
|
| + if ( FT_ABS( distance - org_dist ) > control_value_cutin )
|
| distance = org_dist;
|
|
|
| - distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode &&
|
| + CUR.GS.freeVector.x != 0 )
|
| + distance = ROUND_None( distance,
|
| + CUR.tt_metrics.compensations[0] );
|
| + else
|
| +#endif
|
| + distance = CUR_Func_round( distance,
|
| + CUR.tt_metrics.compensations[0] );
|
| }
|
|
|
| CUR_Func_move( &CUR.zp0, point, distance - org_dist );
|
| @@ -6102,16 +6398,26 @@
|
| Ins_MDRP( INS_ARG )
|
| {
|
| FT_UShort point;
|
| - FT_F26Dot6 org_dist, distance;
|
| + FT_F26Dot6 org_dist, distance, minimum_distance;
|
|
|
|
|
| + minimum_distance = CUR.GS.minimum_distance;
|
| +
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode &&
|
| + CUR.GS.freeVector.x != 0 &&
|
| + !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
|
| + minimum_distance = 0;
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| point = (FT_UShort)args[0];
|
|
|
| if ( BOUNDS( point, CUR.zp1.n_points ) ||
|
| BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| goto Fail;
|
| }
|
|
|
| @@ -6138,15 +6444,15 @@
|
| {
|
| /* this should be faster */
|
| org_dist = CUR_Func_dualproj( vec1, vec2 );
|
| - org_dist = TT_MULFIX( org_dist, CUR.metrics.x_scale );
|
| + org_dist = FT_MulFix( org_dist, CUR.metrics.x_scale );
|
| }
|
| else
|
| {
|
| FT_Vector vec;
|
|
|
|
|
| - vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
|
| - vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
|
| + vec.x = FT_MulFix( vec1->x - vec2->x, CUR.metrics.x_scale );
|
| + vec.y = FT_MulFix( vec1->y - vec2->y, CUR.metrics.y_scale );
|
|
|
| org_dist = CUR_fast_dualproj( &vec );
|
| }
|
| @@ -6166,9 +6472,20 @@
|
| /* round flag */
|
|
|
| if ( ( CUR.opcode & 4 ) != 0 )
|
| + {
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode &&
|
| + CUR.GS.freeVector.x != 0 )
|
| + distance = ROUND_None(
|
| + org_dist,
|
| + CUR.tt_metrics.compensations[CUR.opcode & 3] );
|
| + else
|
| +#endif
|
| distance = CUR_Func_round(
|
| org_dist,
|
| CUR.tt_metrics.compensations[CUR.opcode & 3] );
|
| + }
|
| else
|
| distance = ROUND_None(
|
| org_dist,
|
| @@ -6180,13 +6497,13 @@
|
| {
|
| if ( org_dist >= 0 )
|
| {
|
| - if ( distance < CUR.GS.minimum_distance )
|
| - distance = CUR.GS.minimum_distance;
|
| + if ( distance < minimum_distance )
|
| + distance = minimum_distance;
|
| }
|
| else
|
| {
|
| - if ( distance > -CUR.GS.minimum_distance )
|
| - distance = -CUR.GS.minimum_distance;
|
| + if ( distance > -minimum_distance )
|
| + distance = -minimum_distance;
|
| }
|
| }
|
|
|
| @@ -6221,11 +6538,28 @@
|
| FT_F26Dot6 cvt_dist,
|
| distance,
|
| cur_dist,
|
| - org_dist;
|
| -
|
| -
|
| - point = (FT_UShort)args[0];
|
| - cvtEntry = (FT_ULong)( args[1] + 1 );
|
| + org_dist,
|
| + control_value_cutin,
|
| + minimum_distance;
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + FT_Int B1;
|
| + FT_Int B2;
|
| + FT_Bool reverse_move = FALSE;
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| +
|
| + minimum_distance = CUR.GS.minimum_distance;
|
| + control_value_cutin = CUR.GS.control_value_cutin;
|
| + point = (FT_UShort)args[0];
|
| + cvtEntry = (FT_ULong)( args[1] + 1 );
|
| +
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode &&
|
| + CUR.GS.freeVector.x != 0 &&
|
| + !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
|
| + control_value_cutin = minimum_distance = 0;
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
|
|
| /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
|
|
|
| @@ -6234,7 +6568,7 @@
|
| BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| goto Fail;
|
| }
|
|
|
| @@ -6280,7 +6614,20 @@
|
| cvt_dist = -cvt_dist;
|
| }
|
|
|
| - /* control value cutin and round */
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode &&
|
| + CUR.GS.freeVector.y != 0 &&
|
| + ( CUR.sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) )
|
| + {
|
| + if ( cur_dist < -64 )
|
| + cvt_dist -= 16;
|
| + else if ( cur_dist > 64 && cur_dist < 84 )
|
| + cvt_dist += 32;
|
| + }
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| + /* control value cut-in and round */
|
|
|
| if ( ( CUR.opcode & 4 ) != 0 )
|
| {
|
| @@ -6301,7 +6648,7 @@
|
| /* `ttinst2.doc', version 1.66, is thus incorrect since */
|
| /* it implies `>=' instead of `>'. */
|
|
|
| - if ( FT_ABS( cvt_dist - org_dist ) > CUR.GS.control_value_cutin )
|
| + if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
|
| cvt_dist = org_dist;
|
| }
|
|
|
| @@ -6310,9 +6657,23 @@
|
| CUR.tt_metrics.compensations[CUR.opcode & 3] );
|
| }
|
| else
|
| + {
|
| +
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + /* do cvt cut-in always in MIRP for sph */
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode &&
|
| + CUR.GS.gep0 == CUR.GS.gep1 )
|
| + {
|
| + if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
|
| + cvt_dist = org_dist;
|
| + }
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| distance = ROUND_None(
|
| cvt_dist,
|
| CUR.tt_metrics.compensations[CUR.opcode & 3] );
|
| + }
|
|
|
| /* minimum distance test */
|
|
|
| @@ -6320,18 +6681,65 @@
|
| {
|
| if ( org_dist >= 0 )
|
| {
|
| - if ( distance < CUR.GS.minimum_distance )
|
| - distance = CUR.GS.minimum_distance;
|
| + if ( distance < minimum_distance )
|
| + distance = minimum_distance;
|
| }
|
| else
|
| {
|
| - if ( distance > -CUR.GS.minimum_distance )
|
| - distance = -CUR.GS.minimum_distance;
|
| + if ( distance > -minimum_distance )
|
| + distance = -minimum_distance;
|
| }
|
| }
|
|
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + if ( SUBPIXEL_HINTING )
|
| + {
|
| + B1 = CUR.zp1.cur[point].y;
|
| +
|
| + /* Round moves if necessary */
|
| + if ( CUR.ignore_x_mode &&
|
| + CUR.GS.freeVector.y != 0 &&
|
| + ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) )
|
| + distance = FT_PIX_ROUND( B1 + distance - cur_dist ) - B1 + cur_dist;
|
| +
|
| + if ( CUR.ignore_x_mode &&
|
| + CUR.GS.freeVector.y != 0 &&
|
| + ( CUR.opcode & 16 ) == 0 &&
|
| + ( CUR.opcode & 8 ) == 0 &&
|
| + ( CUR.sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) )
|
| + distance += 64;
|
| + }
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
|
|
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + if ( SUBPIXEL_HINTING )
|
| + {
|
| + B2 = CUR.zp1.cur[point].y;
|
| +
|
| + /* Reverse move if necessary */
|
| + if ( CUR.ignore_x_mode )
|
| + {
|
| + if ( CUR.face->sph_compatibility_mode &&
|
| + CUR.GS.freeVector.y != 0 &&
|
| + ( B1 & 63 ) == 0 &&
|
| + ( B2 & 63 ) != 0 )
|
| + reverse_move = TRUE;
|
| +
|
| + if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
|
| + CUR.GS.freeVector.y != 0 &&
|
| + ( B2 & 63 ) != 0 &&
|
| + ( B1 & 63 ) != 0 )
|
| + reverse_move = TRUE;
|
| + }
|
| +
|
| + if ( reverse_move )
|
| + CUR_Func_move( &CUR.zp1, point, -( distance - cur_dist ) );
|
| + }
|
| +
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| Fail:
|
| CUR.GS.rp1 = CUR.GS.rp0;
|
|
|
| @@ -6357,11 +6765,22 @@
|
| FT_UNUSED_ARG;
|
|
|
|
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode &&
|
| + CUR.iup_called &&
|
| + ( CUR.sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) )
|
| + {
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| + goto Fail;
|
| + }
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| if ( CUR.top < CUR.GS.loop ||
|
| BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| goto Fail;
|
| }
|
|
|
| @@ -6375,7 +6794,7 @@
|
| {
|
| if ( CUR.pedantic_hinting )
|
| {
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
| }
|
| @@ -6409,7 +6828,7 @@
|
| a0, a1,
|
| b0, b1;
|
|
|
| - FT_F26Dot6 discriminant;
|
| + FT_F26Dot6 discriminant, dotproduct;
|
|
|
| FT_F26Dot6 dx, dy,
|
| dax, day,
|
| @@ -6434,10 +6853,12 @@
|
| BOUNDS( point, CUR.zp2.n_points ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
|
|
| + /* Cramer's rule */
|
| +
|
| dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
|
| dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
|
|
|
| @@ -6449,15 +6870,25 @@
|
|
|
| CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
|
|
|
| - discriminant = TT_MULDIV( dax, -dby, 0x40 ) +
|
| - TT_MULDIV( day, dbx, 0x40 );
|
| + discriminant = FT_MulDiv( dax, -dby, 0x40 ) +
|
| + FT_MulDiv( day, dbx, 0x40 );
|
| + dotproduct = FT_MulDiv( dax, dbx, 0x40 ) +
|
| + FT_MulDiv( day, dby, 0x40 );
|
|
|
| - if ( FT_ABS( discriminant ) >= 0x40 )
|
| + /* The discriminant above is actually a cross product of vectors */
|
| + /* da and db. Together with the dot product, they can be used as */
|
| + /* surrogates for sine and cosine of the angle between the vectors. */
|
| + /* Indeed, */
|
| + /* dotproduct = |da||db|cos(angle) */
|
| + /* discriminant = |da||db|sin(angle) . */
|
| + /* We use these equations to reject grazing intersections by */
|
| + /* thresholding abs(tan(angle)) at 1/19, corresponding to 3 degrees. */
|
| + if ( 19 * FT_ABS( discriminant ) > FT_ABS( dotproduct ) )
|
| {
|
| - val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );
|
| + val = FT_MulDiv( dx, -dby, 0x40 ) + FT_MulDiv( dy, dbx, 0x40 );
|
|
|
| - R.x = TT_MULDIV( val, dax, discriminant );
|
| - R.y = TT_MULDIV( val, day, discriminant );
|
| + R.x = FT_MulDiv( val, dax, discriminant );
|
| + R.y = FT_MulDiv( val, day, discriminant );
|
|
|
| CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;
|
| CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
|
| @@ -6498,7 +6929,7 @@
|
| BOUNDS( p2, CUR.zp0.n_points ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
|
|
| @@ -6533,7 +6964,7 @@
|
| if ( CUR.top < CUR.GS.loop )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| goto Fail;
|
| }
|
|
|
| @@ -6547,7 +6978,7 @@
|
| if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| goto Fail;
|
| }
|
|
|
| @@ -6581,9 +7012,9 @@
|
| FT_Vector vec;
|
|
|
|
|
| - vec.x = TT_MULFIX( CUR.zp1.orus[CUR.GS.rp2].x - orus_base->x,
|
| + vec.x = FT_MulFix( CUR.zp1.orus[CUR.GS.rp2].x - orus_base->x,
|
| CUR.metrics.x_scale );
|
| - vec.y = TT_MULFIX( CUR.zp1.orus[CUR.GS.rp2].y - orus_base->y,
|
| + vec.y = FT_MulFix( CUR.zp1.orus[CUR.GS.rp2].y - orus_base->y,
|
| CUR.metrics.y_scale );
|
|
|
| old_range = CUR_fast_dualproj( &vec );
|
| @@ -6603,7 +7034,7 @@
|
| {
|
| if ( CUR.pedantic_hinting )
|
| {
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
| continue;
|
| @@ -6618,9 +7049,9 @@
|
| FT_Vector vec;
|
|
|
|
|
| - vec.x = TT_MULFIX( CUR.zp2.orus[point].x - orus_base->x,
|
| + vec.x = FT_MulFix( CUR.zp2.orus[point].x - orus_base->x,
|
| CUR.metrics.x_scale );
|
| - vec.y = TT_MULFIX( CUR.zp2.orus[point].y - orus_base->y,
|
| + vec.y = FT_MulFix( CUR.zp2.orus[point].y - orus_base->y,
|
| CUR.metrics.y_scale );
|
|
|
| org_dist = CUR_fast_dualproj( &vec );
|
| @@ -6629,9 +7060,24 @@
|
| cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base );
|
|
|
| if ( org_dist )
|
| - new_dist = ( old_range != 0 )
|
| - ? TT_MULDIV( org_dist, cur_range, old_range )
|
| - : cur_dist;
|
| + {
|
| + if ( old_range )
|
| + new_dist = FT_MulDiv( org_dist, cur_range, old_range );
|
| + else
|
| + {
|
| + /* This is the same as what MS does for the invalid case: */
|
| + /* */
|
| + /* delta = (Original_Pt - Original_RP1) - */
|
| + /* (Current_Pt - Current_RP1) */
|
| + /* */
|
| + /* In FreeType speak: */
|
| + /* */
|
| + /* new_dist = cur_dist - */
|
| + /* org_dist - cur_dist; */
|
| +
|
| + new_dist = -org_dist;
|
| + }
|
| + }
|
| else
|
| new_dist = 0;
|
|
|
| @@ -6662,7 +7108,7 @@
|
| if ( BOUNDS( point, CUR.zp0.n_points ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
|
|
| @@ -6791,12 +7237,12 @@
|
| if ( !scale_valid )
|
| {
|
| scale_valid = 1;
|
| - scale = TT_MULDIV( org2 + delta2 - ( org1 + delta1 ),
|
| - 0x10000L, orus2 - orus1 );
|
| + scale = FT_DivFix( org2 + delta2 - ( org1 + delta1 ),
|
| + orus2 - orus1 );
|
| }
|
|
|
| x = ( org1 + delta1 ) +
|
| - TT_MULFIX( worker->orus[i].x - orus1, scale );
|
| + FT_MulFix( worker->orus[i].x - orus1, scale );
|
| }
|
| worker->curs[i].x = x;
|
| }
|
| @@ -6851,6 +7297,16 @@
|
| contour = 0;
|
| point = 0;
|
|
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode )
|
| + {
|
| + CUR.iup_called = TRUE;
|
| + if ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_IUP )
|
| + return;
|
| + }
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| do
|
| {
|
| end_point = CUR.pts.contours[contour] - CUR.pts.first_point;
|
| @@ -6920,6 +7376,16 @@
|
| FT_UShort A;
|
| FT_ULong C;
|
| FT_Long B;
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + FT_UShort B1, B2;
|
| +
|
| +
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode &&
|
| + CUR.iup_called &&
|
| + ( CUR.sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) )
|
| + goto Fail;
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
|
|
|
|
| #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
|
| @@ -6932,7 +7398,7 @@
|
| if ( CUR.args < n )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Too_Few_Arguments;
|
| + CUR.error = FT_THROW( Too_Few_Arguments );
|
| n = CUR.args;
|
| }
|
|
|
| @@ -6950,7 +7416,7 @@
|
| if ( CUR.args < 2 )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Too_Few_Arguments;
|
| + CUR.error = FT_THROW( Too_Few_Arguments );
|
| CUR.args = 0;
|
| goto Fail;
|
| }
|
| @@ -6993,12 +7459,82 @@
|
| B++;
|
| B = B * 64 / ( 1L << CUR.GS.delta_shift );
|
|
|
| - CUR_Func_move( &CUR.zp0, A, B );
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| +
|
| + if ( SUBPIXEL_HINTING )
|
| + {
|
| + /*
|
| + * Allow delta move if
|
| + *
|
| + * - not using ignore_x_mode rendering
|
| + * - glyph is specifically set to allow it
|
| + * - glyph is composite and freedom vector is not subpixel
|
| + * vector
|
| + */
|
| + if ( !CUR.ignore_x_mode ||
|
| + ( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_DO_DELTAP ) ||
|
| + ( CUR.is_composite && CUR.GS.freeVector.y != 0 ) )
|
| + CUR_Func_move( &CUR.zp0, A, B );
|
| +
|
| + /* Otherwise apply subpixel hinting and */
|
| + /* compatibility mode rules */
|
| + else if ( CUR.ignore_x_mode )
|
| + {
|
| + if ( CUR.GS.freeVector.y != 0 )
|
| + B1 = CUR.zp0.cur[A].y;
|
| + else
|
| + B1 = CUR.zp0.cur[A].x;
|
| +
|
| +#if 0
|
| + /* Standard Subpixel Hinting: Allow y move. */
|
| + /* This messes up dejavu and may not be needed... */
|
| + if ( !CUR.face->sph_compatibility_mode &&
|
| + CUR.GS.freeVector.y != 0 )
|
| + CUR_Func_move( &CUR.zp0, A, B );
|
| + else
|
| +#endif /* 0 */
|
| +
|
| + /* Compatibility Mode: Allow x or y move if point touched in */
|
| + /* Y direction. */
|
| + if ( CUR.face->sph_compatibility_mode &&
|
| + !( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) )
|
| + {
|
| + /* save the y value of the point now; compare after move */
|
| + B1 = CUR.zp0.cur[A].y;
|
| +
|
| + if ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
|
| + B = FT_PIX_ROUND( B1 + B ) - B1;
|
| +
|
| + /* Allow delta move if using sph_compatibility_mode, */
|
| + /* IUP has not been called, and point is touched on Y. */
|
| + if ( !CUR.iup_called &&
|
| + ( CUR.zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) )
|
| + CUR_Func_move( &CUR.zp0, A, B );
|
| + }
|
| +
|
| + B2 = CUR.zp0.cur[A].y;
|
| +
|
| + /* Reverse this move if it results in a disallowed move */
|
| + if ( CUR.GS.freeVector.y != 0 &&
|
| + ( ( CUR.face->sph_compatibility_mode &&
|
| + ( B1 & 63 ) == 0 &&
|
| + ( B2 & 63 ) != 0 ) ||
|
| + ( ( CUR.sph_tweak_flags &
|
| + SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP ) &&
|
| + ( B1 & 63 ) != 0 &&
|
| + ( B2 & 63 ) != 0 ) ) )
|
| + CUR_Func_move( &CUR.zp0, A, -B );
|
| + }
|
| + }
|
| + else
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| + CUR_Func_move( &CUR.zp0, A, B );
|
| }
|
| }
|
| else
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| }
|
|
|
| Fail:
|
| @@ -7030,7 +7566,7 @@
|
| if ( CUR.args < n )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Too_Few_Arguments;
|
| + CUR.error = FT_THROW( Too_Few_Arguments );
|
| n = CUR.args;
|
| }
|
|
|
| @@ -7047,7 +7583,7 @@
|
| if ( CUR.args < 2 )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Too_Few_Arguments;
|
| + CUR.error = FT_THROW( Too_Few_Arguments );
|
| CUR.args = 0;
|
| goto Fail;
|
| }
|
| @@ -7061,7 +7597,7 @@
|
| {
|
| if ( CUR.pedantic_hinting )
|
| {
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| return;
|
| }
|
| }
|
| @@ -7123,22 +7659,119 @@
|
|
|
| K = 0;
|
|
|
| - /* We return MS rasterizer version 1.7 for the font scaler. */
|
| - if ( ( args[0] & 1 ) != 0 )
|
| - K = 35;
|
| -
|
| - /* Has the glyph been rotated? */
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + /********************************/
|
| + /* RASTERIZER VERSION */
|
| + /* Selector Bit: 0 */
|
| + /* Return Bit(s): 0-7 */
|
| + /* */
|
| + if ( SUBPIXEL_HINTING &&
|
| + ( args[0] & 1 ) != 0 &&
|
| + CUR.ignore_x_mode )
|
| + {
|
| + K = CUR.rasterizer_version;
|
| + FT_TRACE7(( "Setting rasterizer version %d\n",
|
| + CUR.rasterizer_version ));
|
| + }
|
| + else
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| + if ( ( args[0] & 1 ) != 0 )
|
| + K = TT_INTERPRETER_VERSION_35;
|
| +
|
| + /********************************/
|
| + /* GLYPH ROTATED */
|
| + /* Selector Bit: 1 */
|
| + /* Return Bit(s): 8 */
|
| + /* */
|
| if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated )
|
| K |= 0x80;
|
|
|
| - /* Has the glyph been stretched? */
|
| + /********************************/
|
| + /* GLYPH STRETCHED */
|
| + /* Selector Bit: 2 */
|
| + /* Return Bit(s): 9 */
|
| + /* */
|
| if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched )
|
| K |= 1 << 8;
|
|
|
| - /* Are we hinting for grayscale? */
|
| + /********************************/
|
| + /* HINTING FOR GRAYSCALE */
|
| + /* Selector Bit: 5 */
|
| + /* Return Bit(s): 12 */
|
| + /* */
|
| if ( ( args[0] & 32 ) != 0 && CUR.grayscale )
|
| K |= 1 << 12;
|
|
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| +
|
| + if ( SUBPIXEL_HINTING &&
|
| + CUR.ignore_x_mode &&
|
| + CUR.rasterizer_version >= TT_INTERPRETER_VERSION_35 )
|
| + {
|
| + /********************************/
|
| + /* HINTING FOR GRAYSCALE */
|
| + /* Selector Bit: 5 */
|
| + /* Return Bit(s): 12 */
|
| + /* */
|
| + if ( ( args[0] & 32 ) != 0 && CUR.grayscale_hinting )
|
| + K |= 1 << 12;
|
| +
|
| + /********************************/
|
| + /* HINTING FOR SUBPIXEL */
|
| + /* Selector Bit: 6 */
|
| + /* Return Bit(s): 13 */
|
| + /* */
|
| + if ( ( args[0] & 64 ) != 0 &&
|
| + CUR.subpixel_hinting &&
|
| + CUR.rasterizer_version >= 37 )
|
| + {
|
| + K |= 1 << 13;
|
| +
|
| + /* the stuff below is irrelevant if subpixel_hinting is not set */
|
| +
|
| + /********************************/
|
| + /* COMPATIBLE WIDTHS ENABLED */
|
| + /* Selector Bit: 7 */
|
| + /* Return Bit(s): 14 */
|
| + /* */
|
| + /* Functionality still needs to be added */
|
| + if ( ( args[0] & 128 ) != 0 && CUR.compatible_widths )
|
| + K |= 1 << 14;
|
| +
|
| + /********************************/
|
| + /* SYMMETRICAL SMOOTHING */
|
| + /* Selector Bit: 8 */
|
| + /* Return Bit(s): 15 */
|
| + /* */
|
| + /* Functionality still needs to be added */
|
| + if ( ( args[0] & 256 ) != 0 && CUR.symmetrical_smoothing )
|
| + K |= 1 << 15;
|
| +
|
| + /********************************/
|
| + /* HINTING FOR BGR? */
|
| + /* Selector Bit: 9 */
|
| + /* Return Bit(s): 16 */
|
| + /* */
|
| + /* Functionality still needs to be added */
|
| + if ( ( args[0] & 512 ) != 0 && CUR.bgr )
|
| + K |= 1 << 16;
|
| +
|
| + if ( CUR.rasterizer_version >= 38 )
|
| + {
|
| + /********************************/
|
| + /* SUBPIXEL POSITIONED? */
|
| + /* Selector Bit: 10 */
|
| + /* Return Bit(s): 17 */
|
| + /* */
|
| + /* Functionality still needs to be added */
|
| + if ( ( args[0] & 1024 ) != 0 && CUR.subpixel_positioned )
|
| + K |= 1 << 17;
|
| + }
|
| + }
|
| + }
|
| +
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| args[0] = K;
|
| }
|
|
|
| @@ -7161,7 +7794,7 @@
|
|
|
| if ( CUR.callTop >= CUR.callSize )
|
| {
|
| - CUR.error = TT_Err_Stack_Overflow;
|
| + CUR.error = FT_THROW( Stack_Overflow );
|
| return;
|
| }
|
|
|
| @@ -7180,7 +7813,7 @@
|
| }
|
| }
|
|
|
| - CUR.error = TT_Err_Invalid_Opcode;
|
| + CUR.error = FT_THROW( Invalid_Opcode );
|
| }
|
|
|
|
|
| @@ -7507,13 +8140,31 @@
|
| FT_EXPORT_DEF( FT_Error )
|
| TT_RunIns( TT_ExecContext exc )
|
| {
|
| - FT_Long ins_counter = 0; /* executed instructions counter */
|
| + FT_Long ins_counter = 0; /* executed instructions counter */
|
| + FT_UShort i;
|
| +
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + FT_Byte opcode_pattern[1][2] = {
|
| + /* #8 TypeMan Talk Align */
|
| + {
|
| + 0x06, /* SPVTL */
|
| + 0x7D, /* RDTG */
|
| + },
|
| + };
|
| + FT_UShort opcode_patterns = 1;
|
| + FT_UShort opcode_pointer[1] = { 0 };
|
| + FT_UShort opcode_size[1] = { 1 };
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
|
|
|
|
| #ifdef TT_CONFIG_OPTION_STATIC_RASTER
|
| cur = *exc;
|
| #endif
|
|
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| + CUR.iup_called = FALSE;
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
| +
|
| /* set CVT functions */
|
| CUR.tt_metrics.ratio = 0;
|
| if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
|
| @@ -7560,12 +8211,9 @@
|
| /* One can also interpret it as the index of the last argument. */
|
| if ( CUR.args < 0 )
|
| {
|
| - FT_UShort i;
|
| -
|
| -
|
| if ( CUR.pedantic_hinting )
|
| {
|
| - CUR.error = TT_Err_Too_Few_Arguments;
|
| + CUR.error = FT_THROW( Too_Few_Arguments );
|
| goto LErrorLabel_;
|
| }
|
|
|
| @@ -7582,12 +8230,45 @@
|
| /* statement. */
|
| if ( CUR.new_top > CUR.stackSize )
|
| {
|
| - CUR.error = TT_Err_Stack_Overflow;
|
| + CUR.error = FT_THROW( Stack_Overflow );
|
| goto LErrorLabel_;
|
| }
|
|
|
| CUR.step_ins = TRUE;
|
| - CUR.error = TT_Err_Ok;
|
| + CUR.error = FT_Err_Ok;
|
| +
|
| +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
| +
|
| + if ( SUBPIXEL_HINTING )
|
| + {
|
| + for ( i = 0; i < opcode_patterns; i++ )
|
| + {
|
| + if ( opcode_pointer[i] < opcode_size[i] &&
|
| + CUR.opcode == opcode_pattern[i][opcode_pointer[i]] )
|
| + {
|
| + opcode_pointer[i] += 1;
|
| +
|
| + if ( opcode_pointer[i] == opcode_size[i] )
|
| + {
|
| + FT_TRACE7(( "sph: opcode ptrn: %d, %s %s\n",
|
| + i,
|
| + CUR.face->root.family_name,
|
| + CUR.face->root.style_name ));
|
| +
|
| + switch ( i )
|
| + {
|
| + case 0:
|
| + break;
|
| + }
|
| + opcode_pointer[i] = 0;
|
| + }
|
| + }
|
| + else
|
| + opcode_pointer[i] = 0;
|
| + }
|
| + }
|
| +
|
| +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
|
|
| #ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
|
|
|
| @@ -7801,7 +8482,6 @@
|
| Ins_MDAP( EXEC_ARG_ args );
|
| break;
|
|
|
| -
|
| case 0x30: /* IUP */
|
| case 0x31: /* IUP */
|
| Ins_IUP( EXEC_ARG_ args );
|
| @@ -7861,7 +8541,7 @@
|
| break;
|
|
|
| Set_Invalid_Ref:
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| break;
|
|
|
| case 0x43: /* RS */
|
| @@ -8151,11 +8831,12 @@
|
|
|
| #endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
|
|
|
| - if ( CUR.error != TT_Err_Ok )
|
| + if ( CUR.error )
|
| {
|
| switch ( CUR.error )
|
| {
|
| - case TT_Err_Invalid_Opcode: /* looking for redefined instructions */
|
| + /* looking for redefined instructions */
|
| + case FT_ERR( Invalid_Opcode ):
|
| {
|
| TT_DefRecord* def = CUR.IDefs;
|
| TT_DefRecord* limit = def + CUR.numIDefs;
|
| @@ -8170,7 +8851,7 @@
|
|
|
| if ( CUR.callTop >= CUR.callSize )
|
| {
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| + CUR.error = FT_THROW( Invalid_Reference );
|
| goto LErrorLabel_;
|
| }
|
|
|
| @@ -8190,7 +8871,7 @@
|
| }
|
| }
|
|
|
| - CUR.error = TT_Err_Invalid_Opcode;
|
| + CUR.error = FT_THROW( Invalid_Opcode );
|
| goto LErrorLabel_;
|
|
|
| #if 0
|
| @@ -8216,14 +8897,14 @@
|
| /* increment instruction counter and check if we didn't */
|
| /* run this program for too long (e.g. infinite loops). */
|
| if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
|
| - return TT_Err_Execution_Too_Long;
|
| + return FT_THROW( Execution_Too_Long );
|
|
|
| LSuiteLabel_:
|
| if ( CUR.IP >= CUR.codeSize )
|
| {
|
| if ( CUR.callTop > 0 )
|
| {
|
| - CUR.error = TT_Err_Code_Overflow;
|
| + CUR.error = FT_THROW( Code_Overflow );
|
| goto LErrorLabel_;
|
| }
|
| else
|
| @@ -8237,10 +8918,10 @@
|
| *exc = cur;
|
| #endif
|
|
|
| - return TT_Err_Ok;
|
| + return FT_Err_Ok;
|
|
|
| LErrorCodeOverflow_:
|
| - CUR.error = TT_Err_Code_Overflow;
|
| + CUR.error = FT_THROW( Code_Overflow );
|
|
|
| LErrorLabel_:
|
|
|
|
|