Extend Adobe interpreter (seac).
This concludes the changes needed to add Type 1 support. * src/psaux/psintrp.c: Update includes. (cf2_interpT2CharString) <cf2_escSEAC>: Implement this similarly to implied seac for CFF. * src/psaux/t1decode.c (t1_lookup_glyph_by_stdcharcode_ps): New function to look up the glyph index. * src/psaux/psft.c (cf2_getT1SeacComponent, cf2_freeT1SeacComponent): New functions to get the charstrings for seac components. * src/psaux/t1decode.h, src/psaux/psft.h: Update declarations.
This commit is contained in:
parent
d55a701de6
commit
d813b5da59
19
ChangeLog
19
ChangeLog
|
@ -1,3 +1,22 @@
|
|||
2017-09-25 Ewald Hew <ewaldhew@gmail.com>
|
||||
|
||||
[psaux] Extend Adobe interpreter (seac).
|
||||
|
||||
This concludes the changes needed to add Type 1 support.
|
||||
|
||||
* src/psaux/psintrp.c: Update includes.
|
||||
(cf2_interpT2CharString) <cf2_escSEAC>: Implement this similarly to
|
||||
implied seac for CFF.
|
||||
|
||||
* src/psaux/t1decode.c (t1_lookup_glyph_by_stdcharcode_ps): New
|
||||
function to look up the glyph index.
|
||||
|
||||
* src/psaux/psft.c (cf2_getT1SeacComponent,
|
||||
cf2_freeT1SeacComponent): New functions to get the charstrings for
|
||||
seac components.
|
||||
|
||||
* src/psaux/t1decode.h, src/psaux/psft.h: Update declarations.
|
||||
|
||||
2017-09-25 Ewald Hew <ewaldhew@gmail.com>
|
||||
|
||||
[psaux] Extend Adobe interpreter (flex in callothersubr).
|
||||
|
|
|
@ -705,6 +705,74 @@
|
|||
}
|
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error )
|
||||
cf2_getT1SeacComponent( PS_Decoder* decoder,
|
||||
FT_UInt glyph_index,
|
||||
CF2_Buffer buf )
|
||||
{
|
||||
FT_Data glyph_data;
|
||||
FT_Error error = FT_Err_Ok;
|
||||
T1_Face face = (T1_Face)decoder->builder.face;
|
||||
T1_Font type1 = &face->type1;
|
||||
|
||||
#ifdef FT_CONFIG_OPTION_INCREMENTAL
|
||||
FT_Incremental_InterfaceRec *inc =
|
||||
face->root.internal->incremental_interface;
|
||||
/* For incremental fonts get the character data using the */
|
||||
/* callback function. */
|
||||
if ( inc )
|
||||
error = inc->funcs->get_glyph_data( inc->object,
|
||||
glyph_index, &glyph_data );
|
||||
else
|
||||
#endif
|
||||
/* For ordinary fonts get the character data stored in the face record. */
|
||||
{
|
||||
glyph_data.pointer = type1->charstrings[glyph_index];
|
||||
glyph_data.length = (FT_Int)type1->charstrings_len[glyph_index];
|
||||
}
|
||||
|
||||
if ( !error )
|
||||
{
|
||||
FT_Byte* charstring_base = (FT_Byte*)glyph_data.pointer;
|
||||
FT_ULong charstring_len = (FT_ULong)glyph_data.length;
|
||||
|
||||
|
||||
FT_ASSERT( charstring_base + charstring_len >= charstring_base );
|
||||
|
||||
FT_ZERO( buf );
|
||||
buf->start =
|
||||
buf->ptr = charstring_base;
|
||||
buf->end = charstring_base + charstring_len;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_LOCAL_DEF( void )
|
||||
cf2_freeT1SeacComponent( PS_Decoder* decoder,
|
||||
CF2_Buffer buf )
|
||||
{
|
||||
T1_Face face;
|
||||
FT_Data data;
|
||||
|
||||
|
||||
FT_ASSERT( decoder );
|
||||
|
||||
#ifdef FT_CONFIG_OPTION_INCREMENTAL
|
||||
face = (T1_Face)decoder->builder.face;
|
||||
|
||||
data.pointer = buf->start;
|
||||
data.length = (FT_Int)( buf->end - buf->start );
|
||||
|
||||
if ( face->root.internal->incremental_interface )
|
||||
face->root.internal->incremental_interface->funcs->free_glyph_data(
|
||||
face->root.internal->incremental_interface->object,
|
||||
&data );
|
||||
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
|
||||
}
|
||||
|
||||
|
||||
FT_LOCAL_DEF( CF2_Int )
|
||||
cf2_initLocalRegionBuffer( PS_Decoder* decoder,
|
||||
CF2_Int subrNum,
|
||||
|
|
|
@ -131,6 +131,14 @@ FT_BEGIN_HEADER
|
|||
cf2_getNominalWidthX( PS_Decoder* decoder );
|
||||
|
||||
|
||||
FT_LOCAL( FT_Error )
|
||||
cf2_getT1SeacComponent( PS_Decoder* decoder,
|
||||
FT_UInt glyph_index,
|
||||
CF2_Buffer buf );
|
||||
FT_LOCAL( void )
|
||||
cf2_freeT1SeacComponent( PS_Decoder* decoder,
|
||||
CF2_Buffer buf );
|
||||
|
||||
/*
|
||||
* FreeType client outline
|
||||
*
|
||||
|
|
|
@ -47,8 +47,9 @@
|
|||
#include "psintrp.h"
|
||||
|
||||
#include "pserror.h"
|
||||
#include "psobjs.h" /* for cff_random */
|
||||
|
||||
#include "psobjs.h" /* for cff_random */
|
||||
#include "t1decode.h" /* for t1 seac */
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
|
@ -1289,12 +1290,179 @@
|
|||
FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
|
||||
else
|
||||
{
|
||||
return t1operator_seac( decoder,
|
||||
top[0],
|
||||
top[1],
|
||||
top[2],
|
||||
Fix2Int( top[3] ),
|
||||
Fix2Int( top[4] ) );
|
||||
FT_Error error2;
|
||||
CF2_Int bchar_index, achar_index;
|
||||
FT_Vector left_bearing, advance;
|
||||
#ifdef FT_CONFIG_OPTION_INCREMENTAL
|
||||
T1_Face face = (T1_Face)decoder->builder.face;
|
||||
#endif
|
||||
CF2_BufferRec component;
|
||||
CF2_Fixed dummyWidth;
|
||||
|
||||
CF2_Int achar = cf2_stack_popInt( opStack );
|
||||
CF2_Int bchar = cf2_stack_popInt( opStack );
|
||||
|
||||
FT_Pos ady = cf2_stack_popFixed ( opStack );
|
||||
FT_Pos adx = cf2_stack_popFixed ( opStack );
|
||||
FT_Pos asb = cf2_stack_popFixed ( opStack );
|
||||
|
||||
|
||||
FT_TRACE4(( " seac\n" ));
|
||||
|
||||
if ( doingSeac )
|
||||
{
|
||||
FT_ERROR(( " nested seac\n" ));
|
||||
lastError = FT_THROW( Invalid_Glyph_Format );
|
||||
goto exit; /* nested seac */
|
||||
}
|
||||
|
||||
if ( decoder->builder.metrics_only )
|
||||
{
|
||||
FT_ERROR(( " unexpected seac\n" ));
|
||||
lastError = FT_THROW( Invalid_Glyph_Format );
|
||||
goto exit; /* unexpected seac */
|
||||
}
|
||||
|
||||
/* `glyph_names' is set to 0 for CID fonts which do not */
|
||||
/* include an encoding. How can we deal with these? */
|
||||
#ifdef FT_CONFIG_OPTION_INCREMENTAL
|
||||
if ( decoder->glyph_names == 0 &&
|
||||
!face->root.internal->incremental_interface )
|
||||
#else
|
||||
if ( decoder->glyph_names == 0 )
|
||||
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
|
||||
{
|
||||
FT_ERROR(( "cf2_interpT2CharString: (Type 1 seac)"
|
||||
" glyph names table not available in this font\n" ));
|
||||
lastError = FT_THROW( Invalid_Glyph_Format );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
||||
/* seac weirdness */
|
||||
adx += decoder->builder.left_bearing->x;
|
||||
|
||||
#ifdef FT_CONFIG_OPTION_INCREMENTAL
|
||||
if ( face->root.internal->incremental_interface )
|
||||
{
|
||||
/* the caller must handle the font encoding also */
|
||||
bchar_index = bchar;
|
||||
achar_index = achar;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
bchar_index = t1_lookup_glyph_by_stdcharcode_ps( decoder, bchar );
|
||||
achar_index = t1_lookup_glyph_by_stdcharcode_ps( decoder, achar );
|
||||
}
|
||||
|
||||
if ( bchar_index < 0 || achar_index < 0 )
|
||||
{
|
||||
FT_ERROR(( "cf2_interpT2CharString: (Type 1 seac)"
|
||||
" invalid seac character code arguments\n" ));
|
||||
lastError = FT_THROW( Invalid_Glyph_Format );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
error2 = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
|
||||
if ( error2 )
|
||||
{
|
||||
lastError = error2; /* pass FreeType error through */
|
||||
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 = (FT_Int)FIXED_TO_INT( adx - asb );
|
||||
subg->arg2 = (FT_Int)FIXED_TO_INT( 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;
|
||||
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* First load `bchar' in builder */
|
||||
/* now load the unscaled outline */
|
||||
|
||||
FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */
|
||||
|
||||
error2 = cf2_getT1SeacComponent( decoder, (FT_UInt)bchar_index, &component );
|
||||
if ( error2 )
|
||||
{
|
||||
lastError = error2; /* pass FreeType error through */
|
||||
goto exit;
|
||||
}
|
||||
cf2_interpT2CharString( font,
|
||||
&component,
|
||||
callbacks,
|
||||
translation,
|
||||
TRUE,
|
||||
0,
|
||||
0,
|
||||
&dummyWidth );
|
||||
cf2_freeT1SeacComponent( decoder, &component );
|
||||
|
||||
/* 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 */
|
||||
|
||||
error2 = cf2_getT1SeacComponent( decoder, (FT_UInt)achar_index, &component );
|
||||
if ( error2 )
|
||||
{
|
||||
lastError = error2; /* pass FreeType error through */
|
||||
goto exit;
|
||||
}
|
||||
cf2_interpT2CharString( font,
|
||||
&component,
|
||||
callbacks,
|
||||
translation,
|
||||
TRUE,
|
||||
adx - asb,
|
||||
ady,
|
||||
&dummyWidth );
|
||||
cf2_freeT1SeacComponent( decoder, &component );
|
||||
|
||||
/* restore the left side bearing and */
|
||||
/* advance width of the base character */
|
||||
|
||||
*decoder->builder.left_bearing = left_bearing;
|
||||
*decoder->builder.advance = advance;
|
||||
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -109,6 +109,55 @@
|
|||
};
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* t1_lookup_glyph_by_stdcharcode_ps */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* Looks up a given glyph by its StandardEncoding charcode. Used to */
|
||||
/* implement the SEAC Type 1 operator in the Adobe engine */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* face :: The current face object. */
|
||||
/* */
|
||||
/* charcode :: The character code to look for. */
|
||||
/* */
|
||||
/* <Return> */
|
||||
/* A glyph index in the font face. Returns -1 if the corresponding */
|
||||
/* glyph wasn't found. */
|
||||
/* */
|
||||
FT_LOCAL_DEF( FT_Int )
|
||||
t1_lookup_glyph_by_stdcharcode_ps( PS_Decoder* decoder,
|
||||
FT_Int charcode )
|
||||
{
|
||||
FT_UInt n;
|
||||
const FT_String* glyph_name;
|
||||
FT_Service_PsCMaps psnames = decoder->psnames;
|
||||
|
||||
|
||||
/* check range of standard char code */
|
||||
if ( charcode < 0 || charcode > 255 )
|
||||
return -1;
|
||||
|
||||
glyph_name = psnames->adobe_std_strings(
|
||||
psnames->adobe_std_encoding[charcode]);
|
||||
|
||||
for ( n = 0; n < decoder->num_glyphs; n++ )
|
||||
{
|
||||
FT_String* name = (FT_String*)decoder->glyph_names[n];
|
||||
|
||||
|
||||
if ( name &&
|
||||
name[0] == glyph_name[0] &&
|
||||
ft_strcmp( name, glyph_name ) == 0 )
|
||||
return (FT_Int)n;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
|
|
|
@ -31,6 +31,9 @@ FT_BEGIN_HEADER
|
|||
FT_CALLBACK_TABLE
|
||||
const T1_Decoder_FuncsRec t1_decoder_funcs;
|
||||
|
||||
FT_LOCAL( FT_Int )
|
||||
t1_lookup_glyph_by_stdcharcode_ps( PS_Decoder* decoder,
|
||||
FT_Int charcode );
|
||||
|
||||
FT_LOCAL( FT_Error )
|
||||
t1_decoder_parse_glyph( T1_Decoder decoder,
|
||||
|
|
Loading…
Reference in New Issue