Add basic support for Type1 charstrings in CFF.

* src/cff/cffgload.c (CFF_Operator, cff_argument_counts): Handle
`seac', `sbw', and `setcurrentpoint' opcodes.
(cff_compute_bias): Add parameter to indicate the charstring type.
Update all callers.
(cff_operator_seac): Add parameter for side bearing.
(cff_decoder_parse_charstrings): Updated for more Type1 support.
This commit is contained in:
Bram Tassyns 2009-11-04 07:21:15 +01:00 committed by Werner Lemberg
parent f186ba682d
commit 8821cc5df1
2 changed files with 122 additions and 22 deletions

View File

@ -1,3 +1,14 @@
2009-11-03 Bram Tassyns <bramt@enfocus.be>
Add basic support for Type1 charstrings in CFF.
* src/cff/cffgload.c (CFF_Operator, cff_argument_counts): Handle
`seac', `sbw', and `setcurrentpoint' opcodes.
(cff_compute_bias): Add parameter to indicate the charstring type.
Update all callers.
(cff_operator_seac): Add parameter for side bearing.
(cff_decoder_parse_charstrings): Updated for more Type1 support.
2009-11-03 Werner Lemberg <wl@gnu.org> 2009-11-03 Werner Lemberg <wl@gnu.org>
Return correct `linearHoriAdvance' value for embedded TT bitmaps too. Return correct `linearHoriAdvance' value for embedded TT bitmaps too.

View File

@ -113,6 +113,9 @@
cff_op_closepath, cff_op_closepath,
cff_op_callothersubr, cff_op_callothersubr,
cff_op_pop, cff_op_pop,
cff_op_seac,
cff_op_sbw,
cff_op_setcurrentpoint,
/* do not remove */ /* do not remove */
cff_op_max cff_op_max
@ -201,7 +204,10 @@
2, /* hsbw */ 2, /* hsbw */
0, 0,
0, 0,
0 0,
5, /* seac */
4, /* sbw */
2 /* setcurrentpoint */
}; };
@ -319,17 +325,23 @@
/* subroutines. */ /* subroutines. */
/* */ /* */
/* <Input> */ /* <Input> */
/* num_subrs :: The number of glyph subroutines. */ /* in_charstring_type :: The `CharstringType' value of the top DICT */
/* dictionary. */
/* */
/* num_subrs :: The number of glyph subroutines. */
/* */ /* */
/* <Return> */ /* <Return> */
/* The bias value. */ /* The bias value. */
static FT_Int static FT_Int
cff_compute_bias( FT_UInt num_subrs ) cff_compute_bias( FT_Int in_charstring_type,
FT_UInt num_subrs )
{ {
FT_Int result; FT_Int result;
if ( num_subrs < 1240 ) if ( in_charstring_type == 1 )
result = 0;
else if ( num_subrs < 1240 )
result = 107; result = 107;
else if ( num_subrs < 33900U ) else if ( num_subrs < 33900U )
result = 1131; result = 1131;
@ -380,9 +392,12 @@
cff_builder_init( &decoder->builder, face, size, slot, hinting ); cff_builder_init( &decoder->builder, face, size, slot, hinting );
/* initialize Type2 decoder */ /* initialize Type2 decoder */
decoder->cff = cff;
decoder->num_globals = cff->num_global_subrs; decoder->num_globals = cff->num_global_subrs;
decoder->globals = cff->global_subrs; decoder->globals = cff->global_subrs;
decoder->globals_bias = cff_compute_bias( decoder->num_globals ); decoder->globals_bias = cff_compute_bias(
cff->top_font.font_dict.charstring_type,
decoder->num_globals );
decoder->hint_mode = hint_mode; decoder->hint_mode = hint_mode;
} }
@ -434,7 +449,9 @@
decoder->num_locals = sub->num_local_subrs; decoder->num_locals = sub->num_local_subrs;
decoder->locals = sub->local_subrs; decoder->locals = sub->local_subrs;
decoder->locals_bias = cff_compute_bias( decoder->num_locals ); decoder->locals_bias = cff_compute_bias(
decoder->cff->top_font.font_dict.charstring_type,
decoder->num_locals );
decoder->glyph_width = sub->private_dict.default_width; decoder->glyph_width = sub->private_dict.default_width;
decoder->nominal_width = sub->private_dict.nominal_width; decoder->nominal_width = sub->private_dict.nominal_width;
@ -693,6 +710,7 @@
static FT_Error static FT_Error
cff_operator_seac( CFF_Decoder* decoder, cff_operator_seac( CFF_Decoder* decoder,
FT_Pos asb,
FT_Pos adx, FT_Pos adx,
FT_Pos ady, FT_Pos ady,
FT_Int bchar, FT_Int bchar,
@ -705,6 +723,7 @@
FT_Vector left_bearing, advance; FT_Vector left_bearing, advance;
FT_Byte* charstring; FT_Byte* charstring;
FT_ULong charstring_len; FT_ULong charstring_len;
FT_Pos glyph_width;
if ( decoder->seac ) if ( decoder->seac )
@ -713,6 +732,9 @@
return CFF_Err_Syntax_Error; return CFF_Err_Syntax_Error;
} }
adx += decoder->builder.left_bearing.x;
ady += decoder->builder.left_bearing.y;
#ifdef FT_CONFIG_OPTION_INCREMENTAL #ifdef FT_CONFIG_OPTION_INCREMENTAL
/* Incremental fonts don't necessarily have valid charsets. */ /* Incremental fonts don't necessarily have valid charsets. */
/* They use the character code, not the glyph index, in this case. */ /* They use the character code, not the glyph index, in this case. */
@ -795,16 +817,17 @@
cff_free_glyph_data( face, &charstring, charstring_len ); cff_free_glyph_data( face, &charstring, charstring_len );
} }
/* Save the left bearing and width of the base character */ /* Save the left bearing, advance and glyph width of the base */
/* as they will be erased by the next load. */ /* character as they will be erased by the next load. */
left_bearing = builder->left_bearing; left_bearing = builder->left_bearing;
advance = builder->advance; advance = builder->advance;
glyph_width = decoder->glyph_width;
builder->left_bearing.x = 0; builder->left_bearing.x = 0;
builder->left_bearing.y = 0; builder->left_bearing.y = 0;
builder->pos_x = adx; builder->pos_x = adx - asb;
builder->pos_y = ady; builder->pos_y = ady;
/* Now load `achar' on top of the base outline. */ /* Now load `achar' on top of the base outline. */
@ -824,10 +847,11 @@
cff_free_glyph_data( face, &charstring, charstring_len ); cff_free_glyph_data( face, &charstring, charstring_len );
} }
/* Restore the left side bearing and advance width */ /* Restore the left side bearing, advance and glyph width */
/* of the base character. */ /* of the base character. */
builder->left_bearing = left_bearing; builder->left_bearing = left_bearing;
builder->advance = advance; builder->advance = advance;
decoder->glyph_width = glyph_width;
builder->pos_x = 0; builder->pos_x = 0;
builder->pos_y = 0; builder->pos_y = 0;
@ -869,6 +893,8 @@
FT_Pos x, y; FT_Pos x, y;
FT_Fixed seed; FT_Fixed seed;
FT_Fixed* stack; FT_Fixed* stack;
FT_Int charstring_type =
decoder->cff->top_font.font_dict.charstring_type;
T2_Hints_Funcs hinter; T2_Hints_Funcs hinter;
@ -958,7 +984,8 @@
( (FT_Int32)ip[2] << 8 ) | ( (FT_Int32)ip[2] << 8 ) |
ip[3]; ip[3];
ip += 4; ip += 4;
shift = 0; if ( charstring_type == 2 )
shift = 0;
} }
if ( decoder->top - stack >= CFF_MAX_OPERANDS ) if ( decoder->top - stack >= CFF_MAX_OPERANDS )
goto Stack_Overflow; goto Stack_Overflow;
@ -1032,6 +1059,12 @@
case 0: case 0:
op = cff_op_dotsection; op = cff_op_dotsection;
break; break;
case 1: /* this is actually the Type1 vstem3 operator */
op = cff_op_vstem;
break;
case 2: /* this is actually the Type1 hstem3 operator */
op = cff_op_hstem;
break;
case 3: case 3:
op = cff_op_and; op = cff_op_and;
break; break;
@ -1041,6 +1074,12 @@
case 5: case 5:
op = cff_op_not; op = cff_op_not;
break; break;
case 6:
op = cff_op_seac;
break;
case 7:
op = cff_op_sbw;
break;
case 8: case 8:
op = cff_op_store; op = cff_op_store;
break; break;
@ -1104,6 +1143,9 @@
case 30: case 30:
op = cff_op_roll; op = cff_op_roll;
break; break;
case 33:
op = cff_op_setcurrentpoint;
break;
case 34: case 34:
op = cff_op_hflex; op = cff_op_hflex;
break; break;
@ -1171,7 +1213,7 @@
op = cff_op_hvcurveto; op = cff_op_hvcurveto;
break; break;
default: default:
; break;
} }
if ( op == cff_op_unknown ) if ( op == cff_op_unknown )
@ -1886,6 +1928,21 @@
} }
break; break;
case cff_op_seac:
FT_TRACE4(( " seac\n" ));
error = cff_operator_seac( decoder,
args[0], args[1], args[2],
(FT_Int)( args[3] >> 16 ),
(FT_Int)( args[4] >> 16 ) );
/* add current outline to the glyph slot */
FT_GlyphLoader_Add( builder->loader );
/* return now! */
FT_TRACE4(( "\n" ));
return error;
case cff_op_endchar: case cff_op_endchar:
FT_TRACE4(( " endchar\n" )); FT_TRACE4(( " endchar\n" ));
@ -1895,10 +1952,8 @@
/* Save glyph width so that the subglyphs don't overwrite it. */ /* Save glyph width so that the subglyphs don't overwrite it. */
FT_Pos glyph_width = decoder->glyph_width; FT_Pos glyph_width = decoder->glyph_width;
error = cff_operator_seac( decoder, error = cff_operator_seac( decoder,
args[-4], 0L, args[-4], args[-3],
args[-3],
(FT_Int)( args[-2] >> 16 ), (FT_Int)( args[-2] >> 16 ),
(FT_Int)( args[-1] >> 16 ) ); (FT_Int)( args[-1] >> 16 ) );
@ -2170,10 +2225,42 @@
FT_TRACE4(( " hsbw (invalid op)\n" )); FT_TRACE4(( " hsbw (invalid op)\n" ));
decoder->glyph_width = decoder->nominal_width + decoder->glyph_width = decoder->nominal_width + ( args[1] >> 16 );
(args[1] >> 16);
x = args[0]; decoder->builder.left_bearing.x = args[0];
y = 0; decoder->builder.left_bearing.y = 0;
x = decoder->builder.pos_x + args[0];
y = decoder->builder.pos_y;
args = stack;
break;
case cff_op_sbw:
/* this is an invalid Type 2 operator; however, there */
/* exist fonts which are incorrectly converted from probably */
/* Type 1 to CFF, and some parsers seem to accept it */
FT_TRACE4(( " sbw (invalid op)\n" ));
decoder->glyph_width = decoder->nominal_width + ( args[2] >> 16 );
decoder->builder.left_bearing.x = args[0];
decoder->builder.left_bearing.y = args[1];
x = decoder->builder.pos_x + args[0];
y = decoder->builder.pos_y + args[1];
args = stack;
break;
case cff_op_setcurrentpoint:
/* this is an invalid Type 2 operator; however, there */
/* exist fonts which are incorrectly converted from probably */
/* Type 1 to CFF, and some parsers seem to accept it */
FT_TRACE4(( " setcurrentpoint (invalid op)\n" ));
x = decoder->builder.pos_x + args[0];
y = decoder->builder.pos_y + args[1];
args = stack; args = stack;
break; break;
@ -2184,8 +2271,10 @@
FT_TRACE4(( " callothersubr (invalid op)\n" )); FT_TRACE4(( " callothersubr (invalid op)\n" ));
/* don't modify stack; handle the subr as `unknown' so that */ /* subsequent `pop' operands should add the arguments, */
/* following `pop' operands use the arguments on stack */ /* this is the implementation described for `unknown' other */
/* subroutines in the Type1 spec. */
args -= 2 + ( args[-2] >> 16 );
break; break;
case cff_op_pop: case cff_op_pop: