[truetype] Align more to ClearType whitepaper for sph.
This commit is contained in:
parent
610ee58e07
commit
a5fe359596
53
ChangeLog
53
ChangeLog
@ -1,3 +1,56 @@
|
||||
2013-01-26 Infinality <infinality@infinality.net>
|
||||
|
||||
[truetype] Align more to ClearType whitepaper for sph.
|
||||
|
||||
* include/freetype/internal/tttypes.h (TT_FaceRec): Add flags
|
||||
for detected fdefs and compatibility mode.
|
||||
|
||||
* src/truetype/ttgload.c (tt_loader_init): Complete conditional.
|
||||
|
||||
* src/truetype/ttinterp.c: Updated. Remove SPH_DEBUG and replace
|
||||
with FT_TRACE7.
|
||||
(DO_RS): More conditions.
|
||||
(Ins_FDEF): Add more opcode detection patterns. More specific
|
||||
conditions when flagging a fdef. Make compatibility mode only turn
|
||||
on when delta fdefs are found.
|
||||
(Ins_CALL, Ins_LOOPCALL): Set flags for currently executing fdef.
|
||||
(Ins_SHPIX): Remove logic to handle ttfautohinted fonts. Simplify
|
||||
conditionals where possible. Use & instead of % operator for dumb
|
||||
compilers.
|
||||
(Ins_MIAP): Adjust twilight zone conditional. Ensure ingore_x_mode
|
||||
is on when testing sph conditionals.
|
||||
(Ins_MIRP): Ensure ingore_x_mode is on when testing sph conditionals.
|
||||
Do cvt cutin always when in ignore_x_mode. Remove test for
|
||||
ttfautohinted fonts.
|
||||
(Ins_DELTAP): Ensure ingore_x_mode is on when testing sph conditionals.
|
||||
Do cvt cutin always when in ignore_x_mode. Remove test for
|
||||
ttfautohinted fonts. Use & instead of % operator for dumb
|
||||
compilers.
|
||||
(Ins_GETINFO): Remove SPH_DEBUG and replace with FT_TRACE7.
|
||||
|
||||
* src/truetype/ttinterp.h: Updated.
|
||||
(TT_ExecContextRec): Remove compatibility_mode variable. Add variable
|
||||
to indicate when executing in special fdefs for sph.
|
||||
|
||||
* src/truetype/ttobjs.h: Updated.
|
||||
(TT_DefRecord): Add flags to identify special fdefs for sph.
|
||||
(TT_SizeRec): Remove unnecessary ttfautohinted variable.
|
||||
|
||||
* src/truetype/ttsubpix.c: Updated.
|
||||
(COMPATIBILITY_MODE_Rules): Remove all. Auto-detected now.
|
||||
(PIXEL_HINTING_Rules): Remove all. Unnecessary after fixes.
|
||||
(SKIP_NONPIXEL_Y_MOVES_Rules): Remove Ubuntu.
|
||||
(SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions): Add Arial Bold `N'.
|
||||
(SKIP_OFFPIXEL_Y_MOVES_Rules): Remove all. Happens automatically now.
|
||||
(ROUND_NONPIXEL_Y_MOVES_Rules): Remove Ubuntu.
|
||||
(ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions): Remove all.
|
||||
(NORMAL_ROUND_Rules): Remove Verdana.
|
||||
(NO_DELTAP_AFTER_IUP_Rules): Remove all.
|
||||
(sph_set_tweaks): Performance fix. Don't run prep always. Adjust
|
||||
conditional for sph_compatibility_mode.
|
||||
|
||||
* src/truetype/ttsubpix.h: Add new fdef flags for sph.
|
||||
|
||||
2013-01-23 Alexei Podtelezhnikov <apodtele@gmail.com>
|
||||
|
||||
[base] Fix broken emboldening at small sizes.
|
||||
|
@ -1428,6 +1428,12 @@ FT_BEGIN_HEADER
|
||||
FT_ULong horz_metrics_offset;
|
||||
FT_ULong vert_metrics_offset;
|
||||
|
||||
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
||||
FT_ULong sph_found_func_flags; /* special funcs identified */
|
||||
/* for this face */
|
||||
FT_Bool sph_compatibility_mode;
|
||||
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
||||
|
||||
} TT_FaceRec;
|
||||
|
||||
|
||||
|
@ -1949,6 +1949,8 @@
|
||||
grayscale = grayscale_hinting = TRUE;
|
||||
subpixel_hinting = FALSE;
|
||||
}
|
||||
else
|
||||
grayscale = grayscale_hinting = FALSE;
|
||||
|
||||
if ( FT_IS_TRICKY( glyph->face ) )
|
||||
subpixel_hinting = grayscale_hinting = FALSE;
|
||||
|
@ -34,10 +34,6 @@
|
||||
#ifdef TT_USE_BYTECODE_INTERPRETER
|
||||
|
||||
|
||||
#define xxxSPH_DEBUG
|
||||
#define xxxSPH_DEBUG_MORE_VERBOSE
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
@ -3169,14 +3165,23 @@
|
||||
/* subpixel hinting - avoid Typeman Dstroke and */ \
|
||||
/* IStroke and Vacuform rounds */ \
|
||||
\
|
||||
if ( CUR.compatibility_mode && \
|
||||
( I == 24 || I == 22 || I == 8 ) ) \
|
||||
if ( 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 \
|
||||
@ -4458,8 +4463,57 @@
|
||||
|
||||
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
||||
/* arguments to opcodes are skipped by `SKIP_Code' */
|
||||
FT_Byte opcode_pattern[1][12] = {
|
||||
/* #0 TTFautohint bytecode (old) */
|
||||
FT_Byte opcode_pattern[7][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 */
|
||||
@ -4470,10 +4524,27 @@
|
||||
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 */
|
||||
},
|
||||
};
|
||||
FT_UShort opcode_patterns = 1;
|
||||
FT_UShort opcode_pointer[1] = { 0, };
|
||||
FT_UShort opcode_size[1] = { 7, };
|
||||
FT_UShort opcode_patterns = 7;
|
||||
FT_UShort opcode_pointer[7] = { 0, 0, 0, 0, 0, 0, 0 };
|
||||
FT_UShort opcode_size[7] = { 12, 8, 8, 6, 7, 4, 5 };
|
||||
FT_UShort i;
|
||||
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
||||
|
||||
@ -4515,10 +4586,18 @@
|
||||
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. */
|
||||
|
||||
@ -4526,33 +4605,85 @@
|
||||
{
|
||||
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
||||
|
||||
#ifdef SPH_DEBUG_MORE_VERBOSE
|
||||
printf ( "Opcode: %d ", CUR.opcode );
|
||||
#endif
|
||||
|
||||
for ( i = 0; i < opcode_patterns; i++ )
|
||||
{
|
||||
if ( opcode_pointer[i] < opcode_size[i] &&
|
||||
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 ( opcode_pointer[i] == opcode_size[i] )
|
||||
{
|
||||
#ifdef SPH_DEBUG
|
||||
printf( "Function signature %d detected in FDEF %d\n", i, n);
|
||||
#endif
|
||||
|
||||
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:
|
||||
CUR.size->ttfautohinted = TRUE;
|
||||
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;
|
||||
|
||||
}
|
||||
opcode_pointer[i] = 0;
|
||||
}
|
||||
@ -4562,6 +4693,12 @@
|
||||
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 )
|
||||
@ -4607,15 +4744,6 @@
|
||||
|
||||
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++;
|
||||
@ -4686,6 +4814,9 @@
|
||||
if ( !def->active )
|
||||
goto Fail;
|
||||
|
||||
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
||||
CUR.sph_in_func_flags &= def->sph_fdef_flags;
|
||||
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
||||
|
||||
/* check the call stack */
|
||||
if ( CUR.callTop >= CUR.callSize )
|
||||
@ -4708,6 +4839,11 @@
|
||||
def->start );
|
||||
|
||||
CUR.step_ins = FALSE;
|
||||
|
||||
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
||||
CUR.sph_in_func_flags &= !def->sph_fdef_flags;
|
||||
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
||||
|
||||
return;
|
||||
|
||||
Fail:
|
||||
@ -4764,6 +4900,10 @@
|
||||
if ( !def->active )
|
||||
goto Fail;
|
||||
|
||||
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
||||
CUR.sph_in_func_flags &= def->sph_fdef_flags;
|
||||
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
||||
|
||||
/* check stack */
|
||||
if ( CUR.callTop >= CUR.callSize )
|
||||
{
|
||||
@ -4788,6 +4928,10 @@
|
||||
CUR.step_ins = FALSE;
|
||||
}
|
||||
|
||||
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
||||
CUR.sph_in_func_flags &= !def->sph_fdef_flags;
|
||||
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
||||
|
||||
return;
|
||||
|
||||
Fail:
|
||||
@ -5874,7 +6018,7 @@
|
||||
/* 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 */
|
||||
/* - 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 */
|
||||
@ -5891,14 +6035,12 @@
|
||||
( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_INLINE_DELTAS ) )
|
||||
goto Skip;
|
||||
|
||||
if ( CUR.ignore_x_mode &&
|
||||
!CUR.compatibility_mode && CUR.GS.freeVector.y != 0 )
|
||||
if ( !CUR.face->sph_compatibility_mode && CUR.GS.freeVector.y != 0 )
|
||||
MOVE_Zp2_Point( point, dx, dy, TRUE );
|
||||
|
||||
else if ( CUR.ignore_x_mode && CUR.compatibility_mode )
|
||||
else if ( CUR.face->sph_compatibility_mode )
|
||||
{
|
||||
if ( CUR.ignore_x_mode &&
|
||||
( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) )
|
||||
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;
|
||||
@ -5920,21 +6062,15 @@
|
||||
/* 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 & 63 ) != 0 &&
|
||||
( B2 & 63 ) != 0 &&
|
||||
B1 != B2 ) ||
|
||||
( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES ) &&
|
||||
( CUR.face->sph_compatibility_mode &&
|
||||
CUR.GS.freeVector.y != 0 &&
|
||||
B1 % 64 == 0 &&
|
||||
B2 % 64 != 0 &&
|
||||
B1 != B2 &&
|
||||
!CUR.size->ttfautohinted ) )
|
||||
{
|
||||
#ifdef SPH_DEBUG
|
||||
printf( "Reversing ZP2 move\n" );
|
||||
#endif
|
||||
( B1 & 63 ) == 0 &&
|
||||
( B2 & 63 ) != 0 &&
|
||||
B1 != B2 ) )
|
||||
MOVE_Zp2_Point( point, -dx, -dy, TRUE );
|
||||
}
|
||||
}
|
||||
else
|
||||
MOVE_Zp2_Point( point, dx, dy, TRUE );
|
||||
@ -6124,8 +6260,9 @@
|
||||
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 )
|
||||
/* Only adjust when not in sph_compatibility_mode or ignore_x_mode */
|
||||
/* Determined via experimentation and may be incorrect */
|
||||
if ( !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 );
|
||||
@ -6134,7 +6271,8 @@
|
||||
CUR.zp0.cur[point] = CUR.zp0.org[point];
|
||||
}
|
||||
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
||||
if ( ( CUR.sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) &&
|
||||
if ( CUR.ignore_x_mode &&
|
||||
( CUR.sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) &&
|
||||
distance > 0 &&
|
||||
CUR.GS.freeVector.y != 0 )
|
||||
distance = 0;
|
||||
@ -6352,7 +6490,8 @@
|
||||
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 )
|
||||
if ( CUR.ignore_x_mode &&
|
||||
( CUR.sph_tweak_flags & SPH_TWEAK_MIRP_CVT_ZERO ) )
|
||||
cvt_dist = 0;
|
||||
#endif
|
||||
|
||||
@ -6393,7 +6532,8 @@
|
||||
cvt_dist = -cvt_dist;
|
||||
}
|
||||
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
||||
if ( CUR.GS.freeVector.y != 0 &&
|
||||
if ( CUR.ignore_x_mode &&
|
||||
CUR.GS.freeVector.y != 0 &&
|
||||
( CUR.sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) )
|
||||
{
|
||||
if ( cur_dist < -64 )
|
||||
@ -6432,9 +6572,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 ( CUR.ignore_x_mode && CUR.GS.gep0 == CUR.GS.gep1 )
|
||||
{
|
||||
if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
|
||||
cvt_dist = org_dist;
|
||||
}
|
||||
distance = ROUND_None(
|
||||
cvt_dist,
|
||||
CUR.tt_metrics.compensations[CUR.opcode & 3] );
|
||||
}
|
||||
#else
|
||||
distance = ROUND_None(
|
||||
cvt_dist,
|
||||
CUR.tt_metrics.compensations[CUR.opcode & 3] );
|
||||
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
||||
|
||||
/* minimum distance test */
|
||||
|
||||
@ -6461,7 +6615,8 @@
|
||||
( 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 &&
|
||||
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 ) )
|
||||
@ -6476,17 +6631,16 @@
|
||||
/* Reverse move if necessary */
|
||||
if ( CUR.ignore_x_mode )
|
||||
{
|
||||
if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES ) &&
|
||||
if ( CUR.face->sph_compatibility_mode &&
|
||||
CUR.GS.freeVector.y != 0 &&
|
||||
B1 % 64 == 0 &&
|
||||
B2 % 64 != 0 &&
|
||||
!CUR.size->ttfautohinted )
|
||||
( 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 % 64 != 0 &&
|
||||
B1 % 64 != 0 )
|
||||
( B2 & 63 ) != 0 &&
|
||||
( B1 & 63 ) != 0 )
|
||||
reverse_move = TRUE;
|
||||
|
||||
if ( ( CUR.sph_tweak_flags &
|
||||
@ -7216,15 +7370,18 @@
|
||||
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 )
|
||||
#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
|
||||
/* 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 ) )
|
||||
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;
|
||||
@ -7233,7 +7390,7 @@
|
||||
B = FT_PIX_ROUND( B1 + B ) - B1;
|
||||
|
||||
/*
|
||||
* Allow delta move if using compatibility_mode, IUP has not
|
||||
* Allow delta move if using sph_compatibility_mode, IUP has not
|
||||
* been called, and point is touched on Y.
|
||||
*/
|
||||
if ( !CUR.iup_called &&
|
||||
@ -7245,15 +7402,13 @@
|
||||
|
||||
/* 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.size->ttfautohinted ) ||
|
||||
( ( CUR.face->sph_compatibility_mode &&
|
||||
( B1 & 63 ) == 0 &&
|
||||
( B2 & 63 ) != 0 ) ||
|
||||
( ( CUR.sph_tweak_flags &
|
||||
SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
|
||||
B1 % 64 != 0 &&
|
||||
B2 % 64 != 0 ) ) )
|
||||
( B1 & 63 ) != 0 &&
|
||||
( B2 & 63 ) != 0 ) ) )
|
||||
CUR_Func_move( &CUR.zp0, A, -B );
|
||||
}
|
||||
#else
|
||||
@ -7397,9 +7552,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
|
||||
FT_TRACE7(( "Setting rasterizer version %d\n", CUR.rasterizer_version ));
|
||||
}
|
||||
else
|
||||
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
||||
@ -7871,8 +8024,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
||||
if ( CUR.ignore_x_mode )
|
||||
CUR.iup_called = FALSE;
|
||||
CUR.iup_called = FALSE;
|
||||
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
||||
|
||||
/* set CVT functions */
|
||||
|
@ -269,10 +269,6 @@ FT_BEGIN_HEADER
|
||||
FT_Bool ignore_x_mode; /* Standard rendering mode for */
|
||||
/* subpixel hinting. On if gray */
|
||||
/* or subpixel hinting is on ) */
|
||||
FT_Bool compatibility_mode;/* Additional exceptions to */
|
||||
/* native TT rules for legacy */
|
||||
/* fonts. Implies */
|
||||
/* ignore_x_mode. */
|
||||
|
||||
/* The following 4 aren't fully implemented but here for MS rasterizer */
|
||||
/* compatibility. */
|
||||
@ -286,8 +282,12 @@ FT_BEGIN_HEADER
|
||||
|
||||
FT_Bool iup_called; /* IUP called for glyph? */
|
||||
|
||||
FT_ULong sph_tweak_flags; /* flags to control */
|
||||
/* hint tweaks */
|
||||
FT_ULong sph_tweak_flags; /* flags to control */
|
||||
/* hint tweaks */
|
||||
|
||||
FT_ULong sph_in_func_flags; /* flags to indicate if in */
|
||||
/* special functions */
|
||||
|
||||
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
|
||||
|
||||
} TT_ExecContextRec;
|
||||
|
@ -179,6 +179,7 @@ FT_BEGIN_HEADER
|
||||
FT_UInt opc; /* function #, or instruction code */
|
||||
FT_Bool active; /* is it active? */
|
||||
FT_Bool inline_delta; /* is function that defines inline delta? */
|
||||
FT_ULong sph_fdef_flags; /* flags to identify special functions */
|
||||
|
||||
} TT_DefRecord, *TT_DefArray;
|
||||
|
||||
@ -334,7 +335,6 @@ FT_BEGIN_HEADER
|
||||
|
||||
FT_Bool bytecode_ready;
|
||||
FT_Bool cvt_ready;
|
||||
FT_Bool ttfautohinted;
|
||||
|
||||
#endif /* TT_USE_BYTECODE_INTERPRETER */
|
||||
|
||||
|
@ -275,32 +275,24 @@
|
||||
};
|
||||
|
||||
|
||||
/* Special fixes for known legacy fonts; */
|
||||
/* this is the primary workhorse rule for legacy fonts */
|
||||
#define COMPATIBILITY_MODE_RULES_SIZE 4
|
||||
/* Force special legacy fixes for fonts; */
|
||||
#define COMPATIBILITY_MODE_RULES_SIZE 1
|
||||
|
||||
const SPH_TweakRule COMPATIBILITY_MODE_Rules
|
||||
[COMPATIBILITY_MODE_RULES_SIZE] =
|
||||
{
|
||||
{ "MS Legacy Fonts", 0, "", 0 },
|
||||
{ "Apple Legacy Fonts", 0, "", 0 },
|
||||
{ "Misc Legacy Fonts", 0, "", 0 },
|
||||
{ "Verdana Clones", 0, "", 0 },
|
||||
{ "-", 0, "", 0 },
|
||||
};
|
||||
|
||||
|
||||
/* Don't do subpixel (ignore_x_mode) hinting; do normal hinting. */
|
||||
#define PIXEL_HINTING_RULES_SIZE 4
|
||||
#define PIXEL_HINTING_RULES_SIZE 1
|
||||
|
||||
const SPH_TweakRule PIXEL_HINTING_Rules
|
||||
[PIXEL_HINTING_RULES_SIZE] =
|
||||
{
|
||||
/* these characters are almost always safe */
|
||||
{ "", 0, "", '<' },
|
||||
{ "", 0, "", '>' },
|
||||
/* fixes the vanishing stem */
|
||||
{ "Times New Roman", 0, "Bold", 'A' },
|
||||
{ "Times New Roman", 0, "Bold", 'V' },
|
||||
{ "-", 0, "", 0 },
|
||||
};
|
||||
|
||||
|
||||
@ -328,7 +320,7 @@
|
||||
|
||||
/* Skip Y moves that start with a point that is not on a Y pixel */
|
||||
/* boundary and don't move that point to a Y pixel boundary. */
|
||||
#define SKIP_NONPIXEL_Y_MOVES_RULES_SIZE 10
|
||||
#define SKIP_NONPIXEL_Y_MOVES_RULES_SIZE 9
|
||||
|
||||
const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules
|
||||
[SKIP_NONPIXEL_Y_MOVES_RULES_SIZE] =
|
||||
@ -344,7 +336,6 @@
|
||||
/* Cyrillic small letter I */
|
||||
{ "Legacy Sans Fonts", 0, "", 0x438 },
|
||||
{ "Verdana Clones", 0, "",'N' },
|
||||
{ "Ubuntu", 0, "Regular Class", 'N' },
|
||||
/* Fix misshapen x */
|
||||
{ "Verdana", 0, "Bold", 'x' },
|
||||
/* Fix misshapen s */
|
||||
@ -352,7 +343,7 @@
|
||||
};
|
||||
|
||||
|
||||
#define SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 6
|
||||
#define SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 7
|
||||
|
||||
const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions
|
||||
[SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
|
||||
@ -363,22 +354,18 @@
|
||||
{ "Verdana", 11, "Bold", 'x' },
|
||||
/* Cyrillic small letter I */
|
||||
{ "Arial", 0, "", 0x438 },
|
||||
{ "Arial", 11, "Bold", 'N' },
|
||||
{ "Trebuchet MS", 0, "Bold", 0 },
|
||||
};
|
||||
|
||||
|
||||
/* Skip Y moves that move a point off a Y pixel boundary. */
|
||||
/* This fixes Tahoma, Trebuchet oddities and some issues with `$'. */
|
||||
#define SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE 5
|
||||
#define SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE 1
|
||||
|
||||
const SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules
|
||||
[SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE] =
|
||||
{
|
||||
{ "MS Legacy Fonts", 0, "", 0 },
|
||||
{ "Apple Legacy Fonts", 0, "", 0 },
|
||||
{ "Misc Legacy Fonts", 0, "", 0 },
|
||||
{ "Ubuntu", 0, "Regular Class", 0 },
|
||||
{ "Verdana Clones", 0, "", 0 },
|
||||
{ "-", 0, "", 0 },
|
||||
};
|
||||
|
||||
|
||||
@ -392,7 +379,7 @@
|
||||
|
||||
|
||||
/* Round moves that don't move a point to a Y pixel boundary. */
|
||||
#define ROUND_NONPIXEL_Y_MOVES_RULES_SIZE 3
|
||||
#define ROUND_NONPIXEL_Y_MOVES_RULES_SIZE 2
|
||||
|
||||
const SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules
|
||||
[ROUND_NONPIXEL_Y_MOVES_RULES_SIZE] =
|
||||
@ -400,18 +387,15 @@
|
||||
/* Droid font instructions don't snap Y to pixels */
|
||||
{ "Droid Sans", 0, "Regular/Italic Class", 0 },
|
||||
{ "Droid Sans Mono", 0, "", 0 },
|
||||
{ "Ubuntu", 0, "", 0 },
|
||||
};
|
||||
|
||||
|
||||
#define ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 3
|
||||
#define ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1
|
||||
|
||||
const SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions
|
||||
[ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
|
||||
{
|
||||
{ "Droid Sans", 12, "Bold", 0 },
|
||||
{ "Droid Sans", 13, "Bold", 0 },
|
||||
{ "Droid Sans", 16, "Bold", 0 },
|
||||
{ "-", 0, "", 0 },
|
||||
};
|
||||
|
||||
|
||||
@ -466,14 +450,13 @@
|
||||
|
||||
|
||||
/* Don't round to the subpixel grid. Round to pixel grid. */
|
||||
#define NORMAL_ROUND_RULES_SIZE 2
|
||||
#define NORMAL_ROUND_RULES_SIZE 1
|
||||
|
||||
const SPH_TweakRule NORMAL_ROUND_Rules
|
||||
[NORMAL_ROUND_RULES_SIZE] =
|
||||
{
|
||||
/* Fix point "explosions" */
|
||||
/* Fix serif thickness */
|
||||
{ "Courier New", 0, "", 0 },
|
||||
{ "Verdana", 10, "Regular", '4' },
|
||||
};
|
||||
|
||||
|
||||
@ -563,8 +546,7 @@
|
||||
static const SPH_TweakRule DELTAP_SKIP_EXAGGERATED_VALUES_Rules
|
||||
[DELTAP_SKIP_EXAGGERATED_VALUES_RULES_SIZE] =
|
||||
{
|
||||
/* Fix vanishing stems */
|
||||
{ "Ubuntu", 0, "Regular", 'M' },
|
||||
{ "-", 0, "", 0 },
|
||||
};
|
||||
|
||||
|
||||
@ -583,13 +565,12 @@
|
||||
|
||||
|
||||
/* Don't allow DELTAP after IUP. */
|
||||
#define NO_DELTAP_AFTER_IUP_RULES_SIZE 2
|
||||
#define NO_DELTAP_AFTER_IUP_RULES_SIZE 1
|
||||
|
||||
static const SPH_TweakRule NO_DELTAP_AFTER_IUP_Rules
|
||||
[NO_DELTAP_AFTER_IUP_RULES_SIZE] =
|
||||
{
|
||||
{ "Arial", 0, "Bold", 'N' },
|
||||
{ "Verdana", 0, "Regular", '4' },
|
||||
{ "-", 0, "", 0 },
|
||||
};
|
||||
|
||||
|
||||
@ -1046,15 +1027,22 @@
|
||||
TWEAK_RULES( ROUND_NONPIXEL_Y_MOVES );
|
||||
TWEAK_RULES_EXCEPTIONS( ROUND_NONPIXEL_Y_MOVES );
|
||||
|
||||
if ( loader->exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 )
|
||||
if ( loader->exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 &&
|
||||
loader->exec->rasterizer_version != 35 )
|
||||
{
|
||||
loader->exec->rasterizer_version = 35;
|
||||
else
|
||||
loader->exec->size->cvt_ready = FALSE;
|
||||
tt_size_ready_bytecode( loader->exec->size,
|
||||
FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) );
|
||||
}
|
||||
else if ( loader->exec->rasterizer_version !=
|
||||
SPH_OPTION_SET_RASTERIZER_VERSION )
|
||||
{
|
||||
loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION;
|
||||
|
||||
/* re-execute fpgm always to avoid problems */
|
||||
loader->exec->size->cvt_ready = FALSE;
|
||||
tt_size_ready_bytecode( loader->exec->size,
|
||||
FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) );
|
||||
loader->exec->size->cvt_ready = FALSE;
|
||||
tt_size_ready_bytecode( loader->exec->size,
|
||||
FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) );
|
||||
}
|
||||
|
||||
if ( IS_HINTED( loader->load_flags ) )
|
||||
{
|
||||
@ -1064,12 +1052,8 @@
|
||||
|
||||
if ( sph_test_tweak( face, family, ppem, style, glyph_index,
|
||||
COMPATIBILITY_MODE_Rules, COMPATIBILITY_MODE_RULES_SIZE ) )
|
||||
{
|
||||
loader->exec->compatibility_mode |= TRUE;
|
||||
loader->exec->ignore_x_mode |= TRUE;
|
||||
}
|
||||
else
|
||||
loader->exec->compatibility_mode &= FALSE;
|
||||
loader->exec->face->sph_compatibility_mode = TRUE;
|
||||
|
||||
|
||||
if ( IS_HINTED( loader->load_flags ) )
|
||||
{
|
||||
|
@ -29,6 +29,21 @@ FT_BEGIN_HEADER
|
||||
|
||||
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* ID flags to identify special functions at FDEF and runtime. */
|
||||
/* */
|
||||
/* */
|
||||
#define SPH_FDEF_INLINE_DELTA_1 0x0000001
|
||||
#define SPH_FDEF_INLINE_DELTA_2 0x0000002
|
||||
#define SPH_FDEF_DIAGONAL_STROKE 0x0000004
|
||||
#define SPH_FDEF_VACUFORM_ROUND_1 0x0000008
|
||||
#define SPH_FDEF_TTFAUTOHINT_1 0x0000010
|
||||
#define SPH_FDEF_SPACING_1 0x0000020
|
||||
#define SPH_FDEF_SPACING_2 0x0000040
|
||||
#define SPH_FDEF_TYPEMAN_STROKES 0x0000080
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* Tweak flags that are set for each glyph by the below rules. */
|
||||
|
Loading…
Reference in New Issue
Block a user