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_: |