summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEwald Hew <ewaldhew@gmail.com>2017-08-10 09:17:29 +0800
committerEwald Hew <ewaldhew@gmail.com>2017-08-28 08:29:08 +0800
commit7e7764219f6e80005a68d8b01e8d6d28961711b2 (patch)
treee6ed980cd883db84aa83aed2f91cfc168f270315
parent8327323b32d3c643f4aee68804ab394a2fb603b4 (diff)
downloadfreetype2-7e7764219f6e80005a68d8b01e8d6d28961711b2.tar.gz
[psaux] Fix Type 1 hinting.
Type 1 hinting breaks sometimes when mid-charstring hints should have been in the initial hintmap. This fix adds a preprocessing pass that reads all hints and builds the correct initial hintmap first, before proceeding to build the glyph outline. * src/psaux/psintrp.c (cf2_interpT2CharString): Add boolean flag. Ignore outline commands and hint changes on first pass. <endchar>: Add section to build hintmap and rewind.
-rw-r--r--src/psaux/psintrp.c76
1 files changed, 66 insertions, 10 deletions
diff --git a/src/psaux/psintrp.c b/src/psaux/psintrp.c
index 77f2632b8..3e0590f92 100644
--- a/src/psaux/psintrp.c
+++ b/src/psaux/psintrp.c
@@ -492,6 +492,7 @@
/* Stuff for Type 1 */
FT_Int known_othersubr_result_cnt = 0;
FT_Bool large_int = FALSE;
+ FT_Bool initial_map_ready = FALSE;
#define PS_STORAGE_SIZE 3
CF2_F16Dot16 results[PS_STORAGE_SIZE]; /* for othersubr results */
FT_Int result_cnt = 0;
@@ -650,6 +651,20 @@
if ( font->isT1 )
{
+ if ( !initial_map_ready &&
+ !( op1 == cf2_cmdHSTEM ||
+ op1 == cf2_cmdVSTEM ||
+ op1 == cf2_cmdHSBW ||
+ op1 == cf2_cmdCALLSUBR ||
+ op1 == cf2_cmdRETURN ||
+ op1 == cf2_cmdESC ||
+ op1 == cf2_cmdENDCHAR ||
+ op1 >= 32 /* Numbers */ ) )
+ {
+ cf2_stack_clear( opStack );
+ continue;
+ }
+
if ( result_cnt > 0 &&
!( op1 == cf2_cmdCALLSUBR ||
op1 == cf2_cmdRETURN ||
@@ -1478,8 +1493,11 @@
if ( builder->metrics_only )
goto exit;
- curX = ADD_INT32( curX, lsb_x );
- curY = ADD_INT32( curY, lsb_y );
+ if ( initial_map_ready )
+ {
+ curX = ADD_INT32( curX, lsb_x );
+ curY = ADD_INT32( curY, lsb_y );
+ }
}
}
break;
@@ -1647,8 +1665,9 @@
if ( arg_cnt != 3 )
goto Unexpected_OtherSubr;
- if ( !decoder->flex_state ||
- decoder->num_flex_vectors != 7 )
+ if ( initial_map_ready &&
+ ( !decoder->flex_state ||
+ decoder->num_flex_vectors != 7 ) )
{
FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
" unexpected flex end\n" ));
@@ -1666,6 +1685,9 @@
if ( arg_cnt != 0 )
goto Unexpected_OtherSubr;
+ if ( !initial_map_ready )
+ break;
+
if ( ps_builder_check_points( &decoder->builder, 6 ) )
goto exit;
@@ -1682,6 +1704,9 @@
if ( arg_cnt != 0 )
goto Unexpected_OtherSubr;
+ if ( !initial_map_ready )
+ break;
+
if ( !decoder->flex_state )
{
FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
@@ -1728,12 +1753,15 @@
if ( arg_cnt != 1 )
goto Unexpected_OtherSubr;
- cf2_arrstack_clear( &vStemHintArray );
- cf2_arrstack_clear( &hStemHintArray );
+ if ( initial_map_ready )
+ {
+ cf2_arrstack_clear( &vStemHintArray );
+ cf2_arrstack_clear( &hStemHintArray );
- cf2_hintmask_init( &hintMask, error );
- hintMask.isValid = FALSE;
- hintMask.isNew = TRUE;
+ cf2_hintmask_init( &hintMask, error );
+ hintMask.isValid = FALSE;
+ hintMask.isNew = TRUE;
+ }
known_othersubr_result_cnt = 1;
break;
@@ -2281,6 +2309,9 @@
{
FT_TRACE4(( " setcurrentpoint" ));
+ if ( !initial_map_ready )
+ break;
+
/* From the T1 specification, section 6.4: */
/* */
/* The setcurrentpoint command is used only in */
@@ -2351,13 +2382,38 @@
if ( builder->metrics_only )
goto exit;
- curX = ADD_INT32( curX, lsb_x );
+ if ( initial_map_ready )
+ curX = ADD_INT32( curX, lsb_x );
}
break;
case cf2_cmdENDCHAR:
FT_TRACE4(( " endchar\n" ));
+ if ( font->isT1 && !initial_map_ready )
+ {
+ FT_TRACE5(( "cf2_interpT2CharString (Type 1 mode): "
+ "Build initial hintmap, rewinding...\n" ));
+
+ /* Trigger initial hintmap build */
+ cf2_glyphpath_moveTo( &glyphPath, curX, curY );
+
+ initial_map_ready = TRUE;
+
+ /* Change hints routine - clear for rewind */
+ cf2_arrstack_clear( &vStemHintArray );
+ cf2_arrstack_clear( &hStemHintArray );
+
+ cf2_hintmask_init( &hintMask, error );
+ hintMask.isValid = FALSE;
+ hintMask.isNew = TRUE;
+
+ /* Rewind charstring */
+ charstring->ptr = charstring->start;
+
+ break;
+ }
+
if ( cf2_stack_count( opStack ) == 1 ||
cf2_stack_count( opStack ) == 5 )
{