summaryrefslogtreecommitdiffstats
path: root/src/truetype/ttinterp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/truetype/ttinterp.c')
-rw-r--r--src/truetype/ttinterp.c825
1 files changed, 748 insertions, 77 deletions
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 3a8680f..b1bc6c0 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -27,13 +27,16 @@
#include FT_SYSTEM_H
#include "ttinterp.h"
-
#include "tterrors.h"
+#include "ttsubpix.h"
#ifdef TT_USE_BYTECODE_INTERPRETER
+#define xxxSPH_DEBUG
+#define xxxSPH_DEBUG_MORE_VERBOSE
+
#define TT_MULFIX FT_MulFix
#define TT_MULDIV FT_MulDiv
#define TT_MULDIV_NO_ROUND FT_MulDiv_No_Round
@@ -153,11 +156,11 @@
#define NORMalize( x, y, v ) \
Normalize( EXEC_ARG_ x, y, v )
-#define SET_SuperRound( scale, flags ) \
- SetSuperRound( EXEC_ARG_ scale, flags )
+#define SET_SuperRound( scale, flags, res ) \
+ SetSuperRound( EXEC_ARG_ scale, flags, res )
-#define ROUND_None( d, c ) \
- Round_None( EXEC_ARG_ d, c )
+#define ROUND_None( d, c, e ) \
+ Round_None( EXEC_ARG_ d, c, e )
#define INS_Goto_CodeRange( range, ip ) \
Ins_Goto_CodeRange( EXEC_ARG_ range, ip )
@@ -168,8 +171,8 @@
#define CUR_Func_move_orig( z, p, d ) \
CUR.func_move_orig( EXEC_ARG_ z, p, d )
-#define CUR_Func_round( d, c ) \
- CUR.func_round( EXEC_ARG_ d, c )
+#define CUR_Func_round( d, c, e ) \
+ CUR.func_round( EXEC_ARG_ d, c, e )
#define CUR_Func_read_cvt( index ) \
CUR.func_read_cvt( EXEC_ARG_ index )
@@ -1850,6 +1853,10 @@
if ( v != 0 )
{
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( !CUR.ignore_x_mode ||
+ ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) )
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
zone->cur[point].x += TT_MULDIV( distance,
v * 0x10000L,
CUR.F_dot_P );
@@ -1932,6 +1939,10 @@
{
FT_UNUSED_EXEC;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( !CUR.ignore_x_mode ||
+ ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVEX ) )
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
zone->cur[point].x += distance;
zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
}
@@ -1994,6 +2005,8 @@
/* */
/* compensation :: The engine compensation. */
/* */
+ /* resolution :: The number of grid lines per pixel. */
+ /* */
/* <Return> */
/* The compensated distance. */
/* */
@@ -2005,11 +2018,13 @@
/* */
static FT_F26Dot6
Round_None( EXEC_OP_ FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
+ FT_F26Dot6 compensation,
+ FT_Int resolution )
{
FT_F26Dot6 val;
FT_UNUSED_EXEC;
+ FT_UNUSED( resolution );
if ( distance >= 0 )
@@ -2024,6 +2039,7 @@
if ( val > 0 )
val = 0;
}
+
return val;
}
@@ -2041,12 +2057,15 @@
/* */
/* compensation :: The engine compensation. */
/* */
+ /* resolution :: The number of grid lines per pixel. */
+ /* */
/* <Return> */
/* Rounded distance. */
/* */
static FT_F26Dot6
Round_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
+ FT_F26Dot6 compensation,
+ FT_Int resolution )
{
FT_F26Dot6 val;
@@ -2055,15 +2074,15 @@
if ( distance >= 0 )
{
- val = distance + compensation + 32;
+ val = distance + compensation + 32 / resolution;
if ( distance && val > 0 )
- val &= ~63;
+ val &= ~( 64 / resolution - 1 );
else
val = 0;
}
else
{
- val = -FT_PIX_ROUND( compensation - distance );
+ val = -FT_PIX_ROUND_GRID( compensation - distance, resolution );
if ( val > 0 )
val = 0;
}
@@ -2085,12 +2104,15 @@
/* */
/* compensation :: The engine compensation. */
/* */
+ /* resolution :: The number of grid lines per pixel. */
+ /* */
/* <Return> */
/* Rounded distance. */
/* */
static FT_F26Dot6
Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
+ FT_F26Dot6 compensation,
+ FT_Int resolution )
{
FT_F26Dot6 val;
@@ -2099,13 +2121,15 @@
if ( distance >= 0 )
{
- val = FT_PIX_FLOOR( distance + compensation ) + 32;
+ val = FT_PIX_FLOOR_GRID( distance + compensation, resolution ) +
+ 32 / resolution;
if ( distance && val < 0 )
val = 0;
}
else
{
- val = -( FT_PIX_FLOOR( compensation - distance ) + 32 );
+ val = -( FT_PIX_FLOOR_GRID( compensation - distance, resolution ) +
+ 32 / resolution );
if ( val > 0 )
val = 0;
}
@@ -2127,12 +2151,15 @@
/* */
/* compensation :: The engine compensation. */
/* */
+ /* resolution :: The number of grid lines per pixel. */
+ /* */
/* <Return> */
/* Rounded distance. */
/* */
static FT_F26Dot6
Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
+ FT_F26Dot6 compensation,
+ FT_Int resolution )
{
FT_F26Dot6 val;
@@ -2143,13 +2170,13 @@
{
val = distance + compensation;
if ( distance && val > 0 )
- val &= ~63;
+ val &= ~( 64 / resolution - 1 );
else
val = 0;
}
else
{
- val = -( ( compensation - distance ) & -64 );
+ val = -( ( compensation - distance ) & -( 64 / resolution ) );
if ( val > 0 )
val = 0;
}
@@ -2171,12 +2198,15 @@
/* */
/* compensation :: The engine compensation. */
/* */
+ /* resolution :: The number of grid lines per pixel. */
+ /* */
/* <Return> */
/* Rounded distance. */
/* */
static FT_F26Dot6
Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
+ FT_F26Dot6 compensation,
+ FT_Int resolution )
{
FT_F26Dot6 val;
@@ -2185,15 +2215,15 @@
if ( distance >= 0 )
{
- val = distance + compensation + 63;
+ val = distance + compensation + ( 64 / resolution - 1 );
if ( distance && val > 0 )
- val &= ~63;
+ val &= ~( 64 / resolution - 1 );
else
val = 0;
}
else
{
- val = - FT_PIX_CEIL( compensation - distance );
+ val = -FT_PIX_CEIL_GRID( compensation - distance, resolution );
if ( val > 0 )
val = 0;
}
@@ -2215,12 +2245,15 @@
/* */
/* compensation :: The engine compensation. */
/* */
+ /* resolution :: The number of grid lines per pixel. */
+ /* */
/* <Return> */
/* Rounded distance. */
/* */
static FT_F26Dot6
Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
+ FT_F26Dot6 compensation,
+ FT_Int resolution )
{
FT_F26Dot6 val;
@@ -2229,15 +2262,15 @@
if ( distance >= 0 )
{
- val = distance + compensation + 16;
+ val = distance + compensation + 16 / resolution;
if ( distance && val > 0 )
- val &= ~31;
+ val &= ~( 32 / resolution - 1 );
else
val = 0;
}
else
{
- val = -FT_PAD_ROUND( compensation - distance, 32 );
+ val = -FT_PAD_ROUND( compensation - distance, 32 / resolution );
if ( val > 0 )
val = 0;
}
@@ -2259,6 +2292,8 @@
/* */
/* compensation :: The engine compensation. */
/* */
+ /* resolution :: The number of grid lines per pixel. */
+ /* */
/* <Return> */
/* Rounded distance. */
/* */
@@ -2270,10 +2305,13 @@
/* */
static FT_F26Dot6
Round_Super( EXEC_OP_ FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
+ FT_F26Dot6 compensation,
+ FT_Int resolution )
{
FT_F26Dot6 val;
+ FT_UNUSED( resolution );
+
if ( distance >= 0 )
{
@@ -2309,6 +2347,8 @@
/* */
/* compensation :: The engine compensation. */
/* */
+ /* resolution :: The number of grid lines per pixel. */
+ /* */
/* <Return> */
/* Rounded distance. */
/* */
@@ -2318,10 +2358,13 @@
/* */
static FT_F26Dot6
Round_Super_45( EXEC_OP_ FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
+ FT_F26Dot6 compensation,
+ FT_Int resolution )
{
FT_F26Dot6 val;
+ FT_UNUSED( resolution );
+
if ( distance >= 0 )
{
@@ -2404,13 +2447,19 @@
/* Sets Super Round parameters. */
/* */
/* <Input> */
- /* GridPeriod :: Grid period */
- /* selector :: SROUND opcode */
+ /* GridPeriod :: The grid period. */
+ /* */
+ /* selector :: The SROUND opcode. */
+ /* */
+ /* resolution :: The number of grid lines per pixel. */
/* */
static void
SetSuperRound( EXEC_OP_ FT_F26Dot6 GridPeriod,
- FT_Long selector )
+ FT_Long selector,
+ FT_Int resolution )
{
+ FT_UNUSED( resolution );
+
switch ( (FT_Int)( selector & 0xC0 ) )
{
case 0:
@@ -3080,13 +3129,13 @@
#define DO_SROUND \
- SET_SuperRound( 0x4000, args[0] ); \
+ SET_SuperRound( 0x4000, args[0], 1 ); \
CUR.GS.round_state = TT_Round_Super; \
CUR.func_round = (TT_Round_Func)Round_Super;
#define DO_S45ROUND \
- SET_SuperRound( 0x2D41, args[0] ); \
+ SET_SuperRound( 0x2D41, args[0], 1 ); \
CUR.GS.round_state = TT_Round_Super_45; \
CUR.func_round = (TT_Round_Func)Round_Super_45;
@@ -3257,12 +3306,12 @@
args[0] = ( args[0] != args[1] );
-#define DO_ODD \
- args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 );
+#define DO_ODD \
+ args[0] = ( ( CUR_Func_round( args[0], 0, 1 ) & 127 ) == 64 );
-#define DO_EVEN \
- args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 );
+#define DO_EVEN \
+ args[0] = ( ( CUR_Func_round( args[0], 0, 1 ) & 127 ) == 0 );
#define DO_AND \
@@ -3311,6 +3360,34 @@
#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 ( CUR.compatibility_mode && \
+ ( I == 24 || I == 22 || I == 8 ) ) \
+ args[0] = 0; \
+ else \
+ args[0] = CUR.storage[I]; \
+ } \
+ }
+
+#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
#define DO_RS \
{ \
@@ -3330,6 +3407,8 @@
args[0] = CUR.storage[I]; \
}
+#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
#define DO_WS \
{ \
@@ -3405,15 +3484,17 @@
CUR.error = TT_Err_Debug_OpCode;
-#define DO_ROUND \
- args[0] = CUR_Func_round( \
- args[0], \
- CUR.tt_metrics.compensations[CUR.opcode - 0x68] );
+#define DO_ROUND \
+ args[0] = CUR_Func_round( \
+ args[0], \
+ CUR.tt_metrics.compensations[CUR.opcode - 0x68], \
+ 1 );
-#define DO_NROUND \
- args[0] = ROUND_None( args[0], \
- CUR.tt_metrics.compensations[CUR.opcode - 0x6C] );
+#define DO_NROUND \
+ args[0] = ROUND_None( args[0], \
+ CUR.tt_metrics.compensations[CUR.opcode - 0x6C], \
+ 1 );
#define DO_MAX \
@@ -4587,6 +4668,24 @@
TT_DefRecord* rec;
TT_DefRecord* limit;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#if 0
+ int opcode_pattern[4][12] = {
+ /* VacuFormRound function */
+ {0x45,0x23,0x46,0x60,0x20},
+ /* inline delta function 1 */
+ {0x4B,0x53,0x23,0x4B,0x51,0x5A,0x58,0x38,0x1B,0x21,0x21,0x59},
+ /* inline delta function 2 */
+ {0x4B,0x54,0x58,0x38,0x1B,0x5A,0x21,0x21,0x59},
+ /* diagonal stroke function */
+ {0x20,0x20,0x40,0x60,0x47,0x40,0x23,0x42},
+ };
+ int opcode_patterns = 4;
+ int i;
+ int opcode_pointer[4] = {0,0,0,0};
+#endif
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
/* some font programs are broken enough to redefine functions! */
/* We will then parse the current table. */
@@ -4620,10 +4719,11 @@
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;
if ( n > CUR.maxFunc )
CUR.maxFunc = (FT_UInt16)n;
@@ -4633,6 +4733,78 @@
while ( SKIP_Code() == SUCCESS )
{
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#if 0
+#ifdef SPH_DEBUG_MORE_VERBOSE
+ printf ("Opcode: %d ", CUR.opcode);
+#endif
+
+ for ( i = 0; i < opcode_patterns; i++ )
+ {
+ if ( CUR.opcode == opcode_pattern[i][opcode_pointer[i]] )
+ {
+#ifdef SPH_DEBUG_MORE_VERBOSE
+ printf( "function %d, opcode ptrn: %d"
+ " op# %d: %d FOUND \n",
+ n, i, opcode_pointer[i], CUR.opcode );
+#endif
+ opcode_pointer[i] += 1;
+
+ if ( i == 0 && opcode_pointer[0] == 5 )
+ {
+
+ CUR.inline_delta_funcs[CUR.num_delta_funcs] = n;
+ CUR.num_delta_funcs++;
+#ifdef SPH_DEBUG
+ printf( "Vacuform Round FUNCTION %d detected\n", n);
+#endif
+ /*rec->active = FALSE;*/
+ opcode_pointer[i] = 0;
+ }
+
+ if ( i == 1 && opcode_pointer[1] == 12 )
+ {
+ CUR.inline_delta_funcs[CUR.num_delta_funcs] = n;
+ CUR.num_delta_funcs++;
+#ifdef SPH_DEBUG
+ printf( "inline delta FUNCTION1 %d detected\n",
+ n, CUR.num_delta_funcs);
+#endif
+ rec->inline_delta = TRUE;
+ opcode_pointer[i] = 0;
+ }
+
+ if ( i == 2 && opcode_pointer[1] == 9 )
+ {
+ CUR.inline_delta_funcs[CUR.num_delta_funcs] = n;
+ CUR.num_delta_funcs++;
+ rec->inline_delta = TRUE;
+#ifdef SPH_DEBUG
+ printf( "inline delta2 FUNCTION2 %d detected\n",
+ n, CUR.num_delta_funcs);
+#endif
+ opcode_pointer[i] = 0;
+ }
+
+ if ( i == 4 && opcode_pointer[1] == 8 )
+ {
+ CUR.inline_delta_funcs[CUR.num_delta_funcs] = n;
+ CUR.num_delta_funcs++;
+ /*rec->active = FALSE;*/
+#ifdef SPH_DEBUG
+ printf( "diagonal stroke function %d detected\n",
+ n, CUR.num_delta_funcs);
+#endif
+ opcode_pointer[i] = 0;
+ }
+ }
+
+ else
+ opcode_pointer[i] = 0;
+ }
+#endif
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
switch ( CUR.opcode )
{
case 0x89: /* IDEF */
@@ -4676,6 +4848,15 @@
CUR.step_ins = FALSE;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ /*
+ * CUR.ignore_x_mode may be turned off prior to function calls. This
+ * ensures it is turned back on.
+ */
+ CUR.ignore_x_mode = ( CUR.subpixel_hinting || CUR.grayscale_hinting )
+ && !( CUR.sph_tweak_flags & SPH_TWEAK_PIXEL_HINTING );
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
if ( pRec->Cur_Count > 0 )
{
CUR.callTop++;
@@ -4709,6 +4890,10 @@
TT_CallRec* pCrec;
TT_DefRecord* def;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ FT_Bool oldF;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
/* first of all, check the index */
@@ -4746,6 +4931,20 @@
if ( !def->active )
goto Fail;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ /* This is test code used to detect inline delta functions */
+ oldF = def->inline_delta;
+ if ( CUR.ignore_x_mode )
+ {
+ if ( def->inline_delta )
+ CUR.in_delta_function = TRUE;
+ }
+
+#ifdef SPH_DEBUG
+ printf("Entering function %d\n", F);
+#endif
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
/* check the call stack */
if ( CUR.callTop >= CUR.callSize )
{
@@ -4767,6 +4966,13 @@
def->start );
CUR.step_ins = FALSE;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ CUR.in_delta_function = oldF;
+
+#ifdef SPH_DEBUG
+ printf("Leaving function %d\n", F);
+#endif
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
return;
Fail:
@@ -4787,6 +4993,10 @@
TT_CallRec* pCrec;
TT_DefRecord* def;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ FT_Bool oldF;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
/* first of all, check the index */
F = args[1];
@@ -4823,6 +5033,15 @@
if ( !def->active )
goto Fail;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ oldF = def->inline_delta;
+ if ( CUR.ignore_x_mode )
+ {
+ if ( def->inline_delta )
+ CUR.in_delta_function = TRUE;
+ }
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
/* check stack */
if ( CUR.callTop >= CUR.callSize )
{
@@ -4846,6 +5065,11 @@
CUR.step_ins = FALSE;
}
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ CUR.in_delta_function = oldF;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
return;
Fail:
@@ -5195,6 +5419,12 @@
}
}
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */
+ if ( CUR.ignore_x_mode && FT_ABS( D ) == 64 )
+ D += 1;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
args[0] = D;
}
@@ -5691,7 +5921,12 @@
if ( CUR.GS.freeVector.x != 0 )
{
- CUR.zp2.cur[point].x += dx;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( !CUR.ignore_x_mode ||
+ ( CUR.ignore_x_mode &&
+ ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_MOVE_ZP2 ) ) )
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ CUR.zp2.cur[point].x += dx;
if ( touch )
CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
}
@@ -5872,6 +6107,9 @@
{
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 )
@@ -5917,7 +6155,77 @@
}
}
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 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 ( 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.GS.freeVector.y != 0 &&
+ ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_INLINE_DELTAS ) )
+ goto Skip;
+
+ if ( CUR.ignore_x_mode &&
+ !CUR.compatibility_mode && CUR.GS.freeVector.y != 0 )
+ MOVE_Zp2_Point( point, dx, dy, TRUE );
+
+ else if ( CUR.ignore_x_mode && CUR.compatibility_mode )
+ {
+ if ( CUR.ignore_x_mode &&
+ ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) )
+ {
+ dx = FT_PIX_ROUND ( B1 + dx ) - B1;
+ dy = FT_PIX_ROUND ( B1 + dy ) - B1;
+ }
+
+ 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, dx, dy, TRUE );
+ }
+
+ /* save new point */
+ if ( CUR.GS.freeVector.y != 0 )
+ B2 = CUR.zp2.cur[point].y;
+ else B2 = CUR.zp2.cur[point].x;
+
+ /* reverse any disallowed moves */
+ if ( ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
+ CUR.GS.freeVector.y != 0 &&
+ B1 % 64 != 0 &&
+ B2 % 64 != 0 && B1 != B2 ) ||
+ ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES ) &&
+ CUR.GS.freeVector.y != 0 &&
+ B1 % 64 == 0 &&
+ B2 % 64 != 0 && B1 != B2 ) )
+ {
+#ifdef SPH_DEBUG
+ printf( "Reversing ZP2 move\n" );
+#endif
+ MOVE_Zp2_Point( point, -dx, -dy, TRUE );
+ }
+ }
+ else
+ MOVE_Zp2_Point( point, dx, dy, TRUE );
+ }
+ Skip:
+#else
MOVE_Zp2_Point( point, dx, dy, TRUE );
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
CUR.GS.loop--;
}
@@ -5939,7 +6247,18 @@
{
FT_UShort point;
FT_F26Dot6 distance;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ FT_Int gridlines_per_pixel = 1;
+
+ if ( CUR.ignore_x_mode )
+ {
+ if ( CUR.GS.freeVector.x != 0 )
+ gridlines_per_pixel = SPH_OPTION_GRIDLINES_PER_PIXEL_X;
+ else if ( CUR.GS.freeVector.y != 0 )
+ gridlines_per_pixel = SPH_OPTION_GRIDLINES_PER_PIXEL_Y;
+ }
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
point = (FT_UShort)args[0];
@@ -5963,6 +6282,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 ( CUR.ignore_x_mode &&
+ CUR.GS.freeVector.x != 0 &&
+ FT_ABS( distance - args[1] ) >=
+ CUR.GS.control_value_cutin / gridlines_per_pixel )
+ distance = args[1];
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
CUR_Func_move( &CUR.zp1, point, args[1] - distance );
CUR.GS.rp1 = CUR.GS.rp0;
@@ -5985,7 +6313,21 @@
FT_UShort point;
FT_F26Dot6 cur_dist,
distance;
+ FT_Int gridlines_per_pixel = 1;
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( CUR.ignore_x_mode )
+ {
+ if ( CUR.GS.freeVector.x != 0 &&
+ !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+ gridlines_per_pixel = SPH_OPTION_GRIDLINES_PER_PIXEL_X;
+
+ else if ( CUR.GS.freeVector.y != 0 &&
+ !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+ gridlines_per_pixel = SPH_OPTION_GRIDLINES_PER_PIXEL_Y;
+ }
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
point = (FT_UShort)args[0];
@@ -6000,7 +6342,8 @@
{
cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
distance = CUR_Func_round( cur_dist,
- CUR.tt_metrics.compensations[0] ) - cur_dist;
+ CUR.tt_metrics.compensations[0],
+ gridlines_per_pixel ) - cur_dist;
}
else
distance = 0;
@@ -6025,8 +6368,22 @@
FT_UShort point;
FT_F26Dot6 distance,
org_dist;
+ FT_Int gridlines_per_pixel = 1;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( CUR.ignore_x_mode )
+ {
+ if ( CUR.GS.freeVector.x != 0 &&
+ !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+ gridlines_per_pixel = SPH_OPTION_GRIDLINES_PER_PIXEL_X;
+
+ else if ( CUR.GS.freeVector.y != 0 &&
+ !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+ gridlines_per_pixel = SPH_OPTION_GRIDLINES_PER_PIXEL_Y;
+ }
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
cvtEntry = (FT_ULong)args[1];
point = (FT_UShort)args[0];
@@ -6062,21 +6419,34 @@
if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */
{
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ /* only adjust legacy fonts x otherwise breaks Calibri italic */
+ if ( CUR.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 ( distance > 0 &&
+ ( CUR.sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) &&
+ 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 ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin )
+ if ( FT_ABS( distance - org_dist ) >
+ CUR.GS.control_value_cutin / gridlines_per_pixel )
distance = org_dist;
- distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );
+ distance = CUR_Func_round( distance,
+ CUR.tt_metrics.compensations[0],
+ gridlines_per_pixel );
}
CUR_Func_move( &CUR.zp0, point, distance - org_dist );
@@ -6098,6 +6468,24 @@
{
FT_UShort point;
FT_F26Dot6 org_dist, distance;
+ FT_Int minimum_distance_factor = 64;
+ FT_Int gridlines_per_pixel = 1;
+
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( CUR.ignore_x_mode )
+ {
+ if ( CUR.GS.freeVector.x != 0 &&
+ !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+ {
+ gridlines_per_pixel = SPH_OPTION_GRIDLINES_PER_PIXEL_X;
+ minimum_distance_factor = 64 - gridlines_per_pixel / 3;
+ }
+ else if ( CUR.GS.freeVector.y != 0 &&
+ !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+ gridlines_per_pixel = SPH_OPTION_GRIDLINES_PER_PIXEL_Y;
+ }
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
point = (FT_UShort)args[0];
@@ -6163,11 +6551,13 @@
if ( ( CUR.opcode & 4 ) != 0 )
distance = CUR_Func_round(
org_dist,
- CUR.tt_metrics.compensations[CUR.opcode & 3] );
+ CUR.tt_metrics.compensations[CUR.opcode & 3],
+ gridlines_per_pixel );
else
distance = ROUND_None(
org_dist,
- CUR.tt_metrics.compensations[CUR.opcode & 3] );
+ CUR.tt_metrics.compensations[CUR.opcode & 3],
+ gridlines_per_pixel );
/* minimum distance flag */
@@ -6175,13 +6565,17 @@
{
if ( org_dist >= 0 )
{
- if ( distance < CUR.GS.minimum_distance )
- distance = CUR.GS.minimum_distance;
+ if ( distance < FT_MulDiv( minimum_distance_factor,
+ CUR.GS.minimum_distance, 64 ) )
+ distance = FT_MulDiv( minimum_distance_factor,
+ CUR.GS.minimum_distance, 64 );
}
else
{
- if ( distance > -CUR.GS.minimum_distance )
- distance = -CUR.GS.minimum_distance;
+ if ( distance > -FT_MulDiv( minimum_distance_factor,
+ CUR.GS.minimum_distance, 64 ) )
+ distance = -FT_MulDiv( minimum_distance_factor,
+ CUR.GS.minimum_distance, 64 );
}
}
@@ -6218,10 +6612,37 @@
cur_dist,
org_dist;
+ FT_Int minimum_distance_factor = 64;
+ FT_Int gridlines_per_pixel = 1;
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ FT_Int B1;
+ FT_Int B2;
+ FT_Bool reverse_move = FALSE;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
point = (FT_UShort)args[0];
cvtEntry = (FT_ULong)( args[1] + 1 );
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( CUR.ignore_x_mode )
+ {
+ if ( CUR.GS.freeVector.x != 0 &&
+ !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+ {
+ gridlines_per_pixel = SPH_OPTION_GRIDLINES_PER_PIXEL_X;
+ /* high value emboldens glyphs at lower ppems (< 14); */
+ /* Courier looks better with 52 -- */
+ /* MS ClearType Rasterizer supposedly uses 32 */
+ minimum_distance_factor = 64 - gridlines_per_pixel / 3;
+ }
+
+ else if ( CUR.GS.freeVector.y != 0 &&
+ !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+ gridlines_per_pixel = SPH_OPTION_GRIDLINES_PER_PIXEL_Y;
+ }
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
/* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
if ( BOUNDS( point, CUR.zp1.n_points ) ||
@@ -6237,6 +6658,10 @@
cvt_dist = 0;
else
cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( CUR.sph_tweak_flags & SPH_TWEAK_MIRP_CVT_ZERO )
+ cvt_dist = 0;
+#endif
/* single width test */
@@ -6274,8 +6699,15 @@
if ( ( org_dist ^ cvt_dist ) < 0 )
cvt_dist = -cvt_dist;
}
-
- /* control value cutin and round */
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( 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 )
{
@@ -6296,18 +6728,21 @@
/* `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 ) >
+ CUR.GS.control_value_cutin / gridlines_per_pixel )
cvt_dist = org_dist;
}
distance = CUR_Func_round(
cvt_dist,
- CUR.tt_metrics.compensations[CUR.opcode & 3] );
+ CUR.tt_metrics.compensations[CUR.opcode & 3],
+ gridlines_per_pixel );
}
else
distance = ROUND_None(
cvt_dist,
- CUR.tt_metrics.compensations[CUR.opcode & 3] );
+ CUR.tt_metrics.compensations[CUR.opcode & 3],
+ gridlines_per_pixel );
/* minimum distance test */
@@ -6315,18 +6750,63 @@
{
if ( org_dist >= 0 )
{
- if ( distance < CUR.GS.minimum_distance )
- distance = CUR.GS.minimum_distance;
+ if ( distance < FT_MulDiv( minimum_distance_factor,
+ CUR.GS.minimum_distance, 64 ) )
+ distance = FT_MulDiv( minimum_distance_factor,
+ CUR.GS.minimum_distance, 64 );
}
else
{
- if ( distance > -CUR.GS.minimum_distance )
- distance = -CUR.GS.minimum_distance;
+ if ( distance > -FT_MulDiv( minimum_distance_factor,
+ CUR.GS.minimum_distance, 64 ) )
+ distance = -FT_MulDiv( minimum_distance_factor,
+ CUR.GS.minimum_distance, 64 );
}
}
+#ifdef TT_CONFIG_OPTION_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.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
+ B2 = CUR.zp1.cur[point].y;
+
+ /* Reverse move if necessary */
+ if ( CUR.ignore_x_mode )
+ {
+ if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES ) &&
+ CUR.GS.freeVector.y != 0 && B1 % 64 == 0 && B2 % 64 != 0 )
+ reverse_move = TRUE;
+
+ if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
+ CUR.GS.freeVector.y != 0 && B2 % 64 != 0 && B1 % 64 != 0 )
+ reverse_move = TRUE;
+
+ if ( ( CUR.sph_tweak_flags & SPH_TWEAK_DELTAP_SKIP_EXAGGERATED_VALUES ) &&
+ !reverse_move &&
+ abs ( B1 - B2 ) >= 64 )
+ 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;
@@ -6350,8 +6830,14 @@
FT_F26Dot6 distance;
FT_UNUSED_ARG;
-
-
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( CUR.ignore_x_mode && CUR.iup_called &&
+ ( CUR.sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ goto Fail;
+ }
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
if ( CUR.top < CUR.GS.loop ||
BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
{
@@ -6846,6 +7332,15 @@
contour = 0;
point = 0;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( CUR.ignore_x_mode )
+ {
+ CUR.iup_called = 1;
+ 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;
@@ -6915,7 +7410,9 @@
FT_UShort A;
FT_ULong C;
FT_Long B;
-
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ FT_UShort B1, B2;
+#endif
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
/* Delta hinting is covered by US Patent 5159668. */
@@ -6988,7 +7485,67 @@
B++;
B = B * 64 / ( 1L << CUR.GS.delta_shift );
+#ifdef TT_CONFIG_OPTION_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;
+
+ /* Standard Subpixel Hinting: Allow y move */
+ if ( !CUR.compatibility_mode && CUR.GS.freeVector.y != 0 )
+ CUR_Func_move( &CUR.zp0, A, B );
+
+ /* Compatibility Mode: Allow x or y move if point touched in
+ Y direction */
+ else if ( CUR.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 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.sph_tweak_flags &
+ SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES ) &&
+ B1 % 64 == 0 &&
+ B2 % 64 != 0 ) ||
+ ( ( CUR.sph_tweak_flags &
+ SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
+ B1 % 64 != 0 &&
+ B2 % 64 != 0 )))
+ CUR_Func_move( &CUR.zp0, A, -B );
+ }
+#else
CUR_Func_move( &CUR.zp0, A, B );
+#endif /* *TT_CONFIG_OPTION_SUBPIXEL_HINTING */
}
}
else
@@ -7114,26 +7671,116 @@
Ins_GETINFO( INS_ARG )
{
FT_Long K;
-
-
K = 0;
- /* We return MS rasterizer version 1.7 for the font scaler. */
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ /********************************/
+ /* RASTERIZER VERSION */
+ /* Selector Bit: 0 */
+ /* Return Bit(s): 0-7 */
+ /* */
+ if ( ( args[0] & 1 ) != 0 && CUR.ignore_x_mode )
+ {
+ K = CUR.rasterizer_version;
+#ifdef SPH_DEBUG_MORE_VERBOSE
+ printf(" SETTING AS %d\n", CUR.rasterizer_version );
+#endif
+ }
+ else
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
if ( ( args[0] & 1 ) != 0 )
K = 35;
- /* Has the glyph been rotated? */
+ /********************************/
+ /* 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 ( CUR.ignore_x_mode && CUR.rasterizer_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;
}
@@ -7509,6 +8156,15 @@
cur = *exc;
#endif
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( CUR.ignore_x_mode )
+ {
+ /* ensure some variables are set for this run */
+ CUR.iup_called = FALSE;
+ CUR.in_delta_function = FALSE;
+ }
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
/* set CVT functions */
CUR.tt_metrics.ratio = 0;
if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
@@ -7780,7 +8436,13 @@
break;
case 0x2B: /* CALL */
- Ins_CALL( EXEC_ARG_ args );
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( !CUR.ignore_x_mode ||
+ !CUR.iup_called ||
+ ( CUR.iup_called &&
+ !( CUR.sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) )
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ Ins_CALL( EXEC_ARG_ args );
break;
case 0x2C: /* FDEF */
@@ -7799,6 +8461,9 @@
case 0x30: /* IUP */
case 0x31: /* IUP */
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( CUR.ignore_x_mode ) CUR.iup_called = TRUE;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
Ins_IUP( EXEC_ARG_ args );
break;
@@ -7958,6 +8623,12 @@
break;
case 0x5D: /* DELTAP1 */
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( !CUR.ignore_x_mode ||
+ !CUR.iup_called ||
+ ( CUR.iup_called &&
+ !( CUR.sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) ) )
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
Ins_DELTAP( EXEC_ARG_ args );
break;