Extend Adobe interpreter (hstem, vstem, hstem3, vstem3). * src/psaux/psintrp.c (cf2_interpT2CharString) <cf2_cmdHSTEM, cf2_cmdVSTEM>: Add correction for left sidebearing in Type 1 mode. Allow adding hints mid-charstring. <cf2_escVSTEM3, cf2_escHSTEM3>: Translate into equivalent commands for three normal stem hints. This requires some recalculation of stem positions. Correction for left sidebearing.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
diff --git a/ChangeLog b/ChangeLog
index ce036b1..588c134 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
2017-09-25 Ewald Hew <ewaldhew@gmail.com>
+ Extend Adobe interpreter (hints).
+
+ * src/psaux/psintrp.c (cf2_interpT2CharString) <cf2_cmdHSTEM,
+ cf2_cmdVSTEM>: Add correction for left sidebearing in Type 1 mode.
+ Allow adding hints mid-charstring.
+ <cf2_escVSTEM3, cf2_escHSTEM3>: Translate into equivalent commands
+ for three normal stem hints. This requires some recalculation of
+ stem positions.
+ Correction for left sidebearing.
+
+2017-09-25 Ewald Hew <ewaldhew@gmail.com>
+
[psaux] Extend Adobe interpreter (hsbw, sbw).
* src/psaux/psintrp.c (cf2_doStems): `hsbw' or `sbw' must be the
diff --git a/src/psaux/psintrp.c b/src/psaux/psintrp.c
index 53eca9c..4132931 100644
--- a/src/psaux/psintrp.c
+++ b/src/psaux/psintrp.c
@@ -754,12 +754,28 @@
case cf2_cmdHSTEM:
FT_TRACE4(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" ));
- /* never add hints after the mask is computed */
- if ( cf2_hintmask_isValid( &hintMask ) )
+ if ( !font->isT1 )
{
- FT_TRACE4(( "cf2_interpT2CharString:"
- " invalid horizontal hint mask\n" ));
- break;
+ /* never add hints after the mask is computed */
+ /* except if in Type 1 mode (no hintmask op) */
+ if ( cf2_hintmask_isValid( &hintMask ) )
+ {
+ FT_TRACE4(( "cf2_interpT2CharString:"
+ " invalid horizontal hint mask\n" ));
+ break;
+ }
+ }
+ else
+ {
+ /* Do lsb correction */
+ CF2_F16Dot16 hint_pos;
+
+ FT_ASSERT( ( cf2_stack_count( opStack ) == 2 ) );
+
+ hint_pos = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
+ decoder->builder.left_bearing->y );
+
+ cf2_stack_setReal( opStack, 0, hint_pos );
}
cf2_doStems( font,
@@ -778,12 +794,28 @@
case cf2_cmdVSTEM:
FT_TRACE4(( op1 == cf2_cmdVSTEMHM ? " vstemhm\n" : " vstem\n" ));
- /* never add hints after the mask is computed */
- if ( cf2_hintmask_isValid( &hintMask ) )
+ if ( !font->isT1 )
{
- FT_TRACE4(( "cf2_interpT2CharString:"
- " invalid vertical hint mask\n" ));
- break;
+ /* never add hints after the mask is computed */
+ /* except if in Type 1 mode (no hintmask op) */
+ if ( cf2_hintmask_isValid( &hintMask ) )
+ {
+ FT_TRACE4(( "cf2_interpT2CharString:"
+ " invalid vertical hint mask\n" ));
+ break;
+ }
+ }
+ else
+ {
+ /* Do lsb correction */
+ CF2_F16Dot16 hint_pos;
+
+ FT_ASSERT( ( cf2_stack_count( opStack ) == 2 ) );
+
+ hint_pos = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
+ decoder->builder.left_bearing->x );
+
+ cf2_stack_setReal( opStack, 0, hint_pos );
}
cf2_doStems( font,
@@ -1154,18 +1186,51 @@
break;
case cf2_escVSTEM3:
- if ( !font->isT1 )
- FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
- else
- {
- }
- break;
-
case cf2_escHSTEM3:
- if ( !font->isT1 )
- FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
- else
+ /* Type 1: */ /* Type 2: */
+ /* x0 dx0 x1 dx1 x2 dx2 vstem3 */ /* x dx {dxa dxb}* vstem */
+ /* y0 dy0 y1 dy1 y2 dy2 hstem3 */ /* y dy {dya dyb}* hstem */
+ /* relative to lsb point */ /* relative to zero */
{
+ if ( !font->isT1 )
+ FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+ else
+ {
+ CF2_F16Dot16 v0, v1, v2;
+ CF2_F16Dot16 lsb;
+
+ FT_TRACE4(( op2 == cf2_escVSTEM3 ? " vstem3\n"
+ : " hstem3\n" ));
+
+ FT_ASSERT( ( cf2_stack_count( opStack ) == 6 ) );
+
+ lsb = ( op2 == cf2_escVSTEM3 ? decoder->builder.left_bearing->x
+ : decoder->builder.left_bearing->y );
+
+ v0 = cf2_stack_getReal( opStack, 0 );
+ v1 = cf2_stack_getReal( opStack, 2 );
+ v2 = cf2_stack_getReal( opStack, 4 );
+
+ cf2_stack_setReal( opStack, 0,
+ ADD_INT32( v0,
+ lsb ) );
+ cf2_stack_setReal( opStack, 2,
+ SUB_INT32( SUB_INT32( v1, v0 ),
+ cf2_stack_getReal( opStack, 1 ) ) );
+ cf2_stack_setReal( opStack, 4,
+ SUB_INT32( SUB_INT32( v2, v1 ),
+ cf2_stack_getReal( opStack, 3 ) ) );
+
+ cf2_doStems( font,
+ opStack,
+ op2 == cf2_escVSTEM3 ? &vStemHintArray : &hStemHintArray,
+ width,
+ &haveWidth,
+ 0 );
+
+ if ( decoder->width_only )
+ goto exit;
+ }
}
break;