From 150c98952d77f9125a361dc482eb96dc79dc2eb2 Mon Sep 17 00:00:00 2001 From: Ewald Hew Date: Mon, 24 Jul 2017 11:42:07 +0800 Subject: [psaux] Extend Adobe interpreter. (seac) This concludes the changes needed to add Type 1 support. * src/psaux/psintrp.c (cf2_interpT2CharString): Update includes. : Implement this similarly to implied seac for CFF. * src/psaux/t1decode.c: New function to lookup the glyph index. * src/psaux/psft.c: New procedures cf2_getT1SeacComponent and cf2_freeT1SeacComponent to get the charstrings for seac components. * src/psaux/t1decode.h, src/psaux/psft.h: Update declarations. --- src/psaux/psft.c | 68 +++++++++++++++++++ src/psaux/psft.h | 8 +++ src/psaux/psintrp.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/psaux/t1decode.c | 49 ++++++++++++++ src/psaux/t1decode.h | 3 + 5 files changed, 303 insertions(+), 7 deletions(-) diff --git a/src/psaux/psft.c b/src/psaux/psft.c index 81d3fd835..b12d9d163 100644 --- a/src/psaux/psft.c +++ b/src/psaux/psft.c @@ -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, diff --git a/src/psaux/psft.h b/src/psaux/psft.h index 1628970cc..95e79542f 100644 --- a/src/psaux/psft.h +++ b/src/psaux/psft.h @@ -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 * diff --git a/src/psaux/psintrp.c b/src/psaux/psintrp.c index 5705af063..e4018c916 100644 --- a/src/psaux/psintrp.c +++ b/src/psaux/psintrp.c @@ -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; diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c index 81f579744..37790c50b 100644 --- a/src/psaux/t1decode.c +++ b/src/psaux/t1decode.c @@ -109,6 +109,55 @@ }; + /*************************************************************************/ + /* */ + /* */ + /* t1_lookup_glyph_by_stdcharcode_ps */ + /* */ + /* */ + /* Looks up a given glyph by its StandardEncoding charcode. Used to */ + /* implement the SEAC Type 1 operator in the Adobe engine */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* charcode :: The character code to look for. */ + /* */ + /* */ + /* 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; + } + + /*************************************************************************/ /* */ /* */ diff --git a/src/psaux/t1decode.h b/src/psaux/t1decode.h index 12c27de77..1ca7e013d 100644 --- a/src/psaux/t1decode.h +++ b/src/psaux/t1decode.h @@ -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, -- cgit v1.2.1