Added functions t2_lookup_glyph_by_stdcharcode and t2_operator_seac

for use in implementing the seac emulation provided by the Type 2
endchar operator.

Extended T2_Parse_CharStrings to add seac emulation for the endchar
operator.
This commit is contained in:
Tom Kacvinsky 2000-12-30 00:39:40 +00:00
parent 86c50ab52a
commit d9d7be77df
1 changed files with 168 additions and 2 deletions

View File

@ -513,6 +513,153 @@
outline->contours[outline->n_contours - 1] = outline->n_points - 1;
}
static
FT_Int t2_lookup_glyph_by_stdcharcode( CFF_Font* cff,
FT_Int charcode )
{
FT_UInt n;
FT_UShort glyph_sid;
/* check range of standard char code */
if ( charcode < 0 || charcode > 255 )
return -1;
/* Get code to SID mapping from `cff_standard_encoding'. */
glyph_sid = cff_standard_encoding[charcode];
for ( n = 0; n < cff->num_glyphs; n++ )
{
if ( cff->charset.sids[n] == glyph_sid )
return n;
}
return -1;
}
static
FT_Error t2_operator_seac( T2_Decoder* decoder,
FT_Pos adx,
FT_Pos ady,
FT_Int bchar,
FT_Int achar )
{
FT_Error error;
FT_Int bchar_index, achar_index, n_base_points;
FT_Outline* base = decoder->builder.base;
TT_Face face = decoder->builder.face;
CFF_Font* cff = (CFF_Font*)(face->extra.data);
FT_Vector left_bearing, advance;
FT_Byte* charstring;
FT_ULong charstring_len;
bchar_index = t2_lookup_glyph_by_stdcharcode( cff, bchar );
achar_index = t2_lookup_glyph_by_stdcharcode( cff, achar );
if ( bchar_index < 0 || achar_index < 0 )
{
FT_ERROR(( "t2_operator_seac:" ));
FT_ERROR(( " invalid seac character code arguments\n" ));
return T2_Err_Syntax_Error;
}
/* if we are trying to load a composite glyph, do not load the */
/* accent character and return the array of subglyphs. */
if ( decoder->builder.no_recurse )
{
FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
FT_GlyphLoader* loader = glyph->internal->loader;
FT_SubGlyph* subg;
/* reallocate subglyph array if necessary */
error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
if ( error )
goto Exit;
subg = loader->current.subglyphs;
/* subglyph 0 = base character */
subg->index = bchar_index;
subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
FT_SUBGLYPH_FLAG_USE_MY_METRICS;
subg->arg1 = 0;
subg->arg2 = 0;
subg++;
/* subglyph 1 = accent character */
subg->index = achar_index;
subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
subg->arg1 = adx;
subg->arg2 = ady;
/* set up remaining glyph fields */
glyph->num_subglyphs = 2;
glyph->subglyphs = loader->base.subglyphs;
glyph->format = ft_glyph_format_composite;
loader->current.num_subglyphs = 2;
}
/* First load `bchar' in builder */
error = CFF_Access_Element( &cff->charstrings_index, bchar_index,
&charstring, &charstring_len );
if ( !error )
{
error = T2_Parse_CharStrings( decoder, charstring, charstring_len );
if ( error )
goto Exit;
CFF_Forget_Element( &cff->charstrings_index, &charstring );
}
n_base_points = base->n_points;
/* save the left bearing and width of the base character */
/* as they will be erased by the next load. */
left_bearing = decoder->builder.left_bearing;
advance = decoder->builder.advance;
decoder->builder.left_bearing.x = 0;
decoder->builder.left_bearing.y = 0;
/* Now load `achar' on top of the base outline */
error = CFF_Access_Element( &cff->charstrings_index, achar_index,
&charstring, &charstring_len );
if ( !error )
{
error = T2_Parse_CharStrings( decoder, charstring, charstring_len );
if ( error )
goto Exit;
CFF_Forget_Element( &cff->charstrings_index, &charstring );
}
/* restore the left side bearing and advance width of the base character */
decoder->builder.left_bearing = left_bearing;
decoder->builder.advance = advance;
/* Finally, move the accent */
if ( decoder->builder.load_points )
{
FT_Outline dummy;
dummy.n_points = base->n_points - n_base_points;
dummy.points = base->points + n_base_points;
FT_Outline_Translate( &dummy, adx, ady );
}
Exit:
return error;
}
/*************************************************************************/
/* */
@ -856,11 +1003,16 @@
case t2_op_vstem:
case t2_op_hstemhm:
case t2_op_vstemhm:
case t2_op_endchar:
case t2_op_rmoveto:
set_width_ok = num_args & 1;
break;
case t2_op_endchar:
/* If there is a width specified for endchar, we either have 1 */
/* argument or 5 arguments. We like to argue. */
set_width_ok = ( ( num_args == 5 ) || ( num_args == 1 ) );
break;
default:
set_width_ok = 0;
break;
@ -870,6 +1022,8 @@
{
decoder->glyph_width = decoder->nominal_width +
( stack[0] >> 16 );
/* Consumed an argument. */
num_args--;
args++;
}
@ -1424,6 +1578,18 @@
case t2_op_endchar:
FT_TRACE4(( " endchar" ));
/* We are going to emulate the seac operator. */
if ( num_args == 4)
{
error = t2_operator_seac( decoder, args[0] >> 16, args[1] >> 16,
args[2] >> 16, args[3] >> 16 );
args += 4;
}
if ( !error )
error = T2_Err_Ok;
close_contour( builder );
/* add current outline to the glyph slot */
@ -1431,7 +1597,7 @@
/* return now! */
FT_TRACE4(( "\n\n" ));
return T2_Err_Ok;
return error;
case t2_op_abs:
FT_TRACE4(( " abs" ));