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:
parent
86c50ab52a
commit
d9d7be77df
@ -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" ));
|
||||
|
Loading…
Reference in New Issue
Block a user