diff --git a/ChangeLog b/ChangeLog index bc65cbb..acec0e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2017-06-20 Alexei Podtelezhnikov + + [sfnt] Synthesize a Unicode charmap if one is missing. + + * src/sfnt/ttpost.c (tt_get_glyph_name, tt_cmap_unicode_init, + tt_cmap_unicode_done, tt_cmap_unicode_char_index, + tt_cmap_unicode_char_next, tt_cmap_unicode_class_rec): Implement + synthetic Unicode charmap class. + * src/sfnt/ttpost.h (tt_cmap_unicode_class_rec): Declare it. + + * src/sfnt/sfobjs.c (sfnt_load_face) + [TT_CONFIG_OPTION_POSTSCRIPT_NAMES]: If Unicode charmap is missing, + synthesize one. + + * src/sfnt/ttcmap.c (tt_get_cmap_info): Make sure the callback is + available. + + * include/freetype/config/ftoption.h: Document it. + * devel/ftoption.h: Ditto. + + 2017-06-20 Tony Theodore Fix pkg-config in freetype-config for cross-compiling (#51274). diff --git a/devel/ftoption.h b/devel/ftoption.h index db661e7..f11ad00 100644 --- a/devel/ftoption.h +++ b/devel/ftoption.h @@ -563,7 +563,7 @@ FT_BEGIN_HEADER /* */ /* Define TT_CONFIG_OPTION_POSTSCRIPT_NAMES if you want to be able to */ /* load and enumerate the glyph Postscript names in a TrueType or */ - /* OpenType file. */ + /* OpenType file and synthesize a Unicode charmap if one is missing. */ /* */ /* Note that when you do not compile the `PSNames' module by undefining */ /* the above FT_CONFIG_OPTION_POSTSCRIPT_NAMES, the `sfnt' module will */ diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h index 1bf6e8f..d9c8793 100644 --- a/include/freetype/config/ftoption.h +++ b/include/freetype/config/ftoption.h @@ -563,7 +563,7 @@ FT_BEGIN_HEADER /* */ /* Define TT_CONFIG_OPTION_POSTSCRIPT_NAMES if you want to be able to */ /* load and enumerate the glyph Postscript names in a TrueType or */ - /* OpenType file. */ + /* OpenType file and synthesize a Unicode charmap if one is missing. */ /* */ /* Note that when you do not compile the `PSNames' module by undefining */ /* the above FT_CONFIG_OPTION_POSTSCRIPT_NAMES, the `sfnt' module will */ diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c index 3f54d5d..c4257ee 100644 --- a/src/sfnt/sfobjs.c +++ b/src/sfnt/sfobjs.c @@ -40,6 +40,10 @@ #include "ttbdf.h" #endif +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES +#include "ttpost.h" +#endif + /*************************************************************************/ /* */ @@ -1464,7 +1468,8 @@ /* Polish the charmaps. */ /* */ /* Try to set the charmap encoding according to the platform & */ - /* encoding ID of each charmap. */ + /* encoding ID of each charmap. Emulate Unicode charmap if one */ + /* is missing. */ /* */ tt_face_build_cmaps( face ); /* ignore errors */ @@ -1472,7 +1477,10 @@ /* set the encoding fields */ { - FT_Int m; + FT_Int m; +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES + FT_Bool has_unicode = FALSE; +#endif for ( m = 0; m < root->num_charmaps; m++ ) @@ -1482,6 +1490,33 @@ charmap->encoding = sfnt_find_encoding( charmap->platform_id, charmap->encoding_id ); + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES + + if ( charmap->encoding == FT_ENCODING_UNICODE ) + has_unicode = TRUE; + } + + /* synthesize Unicode charmap if one is missing */ + if ( !has_unicode ) + { + FT_CharMapRec cmaprec; + + + cmaprec.face = root; + cmaprec.platform_id = TT_PLATFORM_MICROSOFT; + cmaprec.encoding_id = TT_MS_ID_UNICODE_CS; + cmaprec.encoding = FT_ENCODING_UNICODE; + + + error = FT_CMap_New( (FT_CMap_Class)&tt_cmap_unicode_class_rec, + NULL, &cmaprec, NULL ); + if ( error && + FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) ) + FT_TRACE2(( "sfnt_load_face: failed to emulate Unicode\n" )); + +#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + } } diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c index 5afa6ae..4178b5b 100644 --- a/src/sfnt/ttcmap.c +++ b/src/sfnt/ttcmap.c @@ -3801,8 +3801,10 @@ FT_CMap cmap = (FT_CMap)charmap; TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz; - - return clazz->get_cmap_info( charmap, cmap_info ); + if ( clazz->get_cmap_info ) + return clazz->get_cmap_info( charmap, cmap_info ); + else + return FT_THROW( Invalid_CharMap_Format ); } diff --git a/src/sfnt/ttpost.c b/src/sfnt/ttpost.c index a47ece0..139c639 100644 --- a/src/sfnt/ttpost.c +++ b/src/sfnt/ttpost.c @@ -564,6 +564,105 @@ return FT_Err_Ok; } + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** SYNTHETIC UNICODE ENCODING CMAP *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_CALLBACK_DEF( const char * ) + tt_get_glyph_name( TT_Face face, + FT_UInt idx ) + { + FT_String* PSname; + + + tt_face_get_ps_name( face, idx, &PSname ); + + return PSname; + } + + + FT_CALLBACK_DEF( FT_Error ) + tt_cmap_unicode_init( PS_Unicodes unicodes, + FT_Pointer pointer ) + { + TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + + FT_UNUSED( pointer ); + + + return psnames->unicodes_init( memory, + unicodes, + face->root.num_glyphs, + (PS_GetGlyphNameFunc)&tt_get_glyph_name, + (PS_FreeGlyphNameFunc)NULL, + (FT_Pointer)face ); + } + + + FT_CALLBACK_DEF( void ) + tt_cmap_unicode_done( PS_Unicodes unicodes ) + { + FT_Face face = FT_CMAP_FACE( unicodes ); + FT_Memory memory = FT_FACE_MEMORY( face ); + + + FT_FREE( unicodes->maps ); + unicodes->num_maps = 0; + } + + + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap_unicode_char_index( PS_Unicodes unicodes, + FT_UInt32 char_code ) + { + TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + + + return psnames->unicodes_char_index( unicodes, char_code ); + } + + + FT_CALLBACK_DEF( FT_UInt32 ) + tt_cmap_unicode_char_next( PS_Unicodes unicodes, + FT_UInt32 *pchar_code ) + { + TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + + + return psnames->unicodes_char_next( unicodes, pchar_code ); + } + + + FT_DEFINE_TT_CMAP( + tt_cmap_unicode_class_rec, + + sizeof ( PS_UnicodesRec ), + + (FT_CMap_InitFunc) tt_cmap_unicode_init, /* init */ + (FT_CMap_DoneFunc) tt_cmap_unicode_done, /* done */ + (FT_CMap_CharIndexFunc)tt_cmap_unicode_char_index, /* char_index */ + (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next, /* char_next */ + + (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */ + (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */ + (FT_CMap_VariantListFunc) NULL, /* variant_list */ + (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */ + (FT_CMap_VariantCharListFunc) NULL, /* variantchar_list */ + + -1, + (TT_CMap_ValidateFunc)NULL, /* validate */ + (TT_CMap_Info_GetFunc)NULL /* get_cmap_info */ + ) + #else /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ /* ANSI C doesn't like empty source files */ diff --git a/src/sfnt/ttpost.h b/src/sfnt/ttpost.h index 722485e..0706584 100644 --- a/src/sfnt/ttpost.h +++ b/src/sfnt/ttpost.h @@ -22,6 +22,7 @@ #include +#include "ttcmap.h" #include FT_CONFIG_CONFIG_H #include FT_INTERNAL_TRUETYPE_TYPES_H @@ -38,6 +39,10 @@ FT_BEGIN_HEADER tt_face_free_ps_names( TT_Face face ); + /* synthetic unicode charmap */ + FT_CALLBACK_TABLE const TT_CMap_ClassRec tt_cmap_unicode_class_rec; + + FT_END_HEADER #endif /* TTPOST_H_ */