From f4253366f1d90e6b28b4b3e34ed74e24aa7c2c31 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Fri, 27 Jan 2017 00:06:52 +0100 Subject: [PATCH] [base] Add `FT_Get_Sfnt_LangTag' function. * include/freetype/ftsnames.h (FT_SfntLangTag): New structure. (FT_Get_Sfnt_LangTag): New declaration. * src/base/ftsnames.c (FT_Get_Sfnt_LangTag): New funtion. * docs/CHANGES: Updated. --- ChangeLog | 11 +++++ docs/CHANGES | 7 ++-- include/freetype/ftsnames.h | 80 ++++++++++++++++++++++++++++++++++++- src/base/ftsnames.c | 52 ++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7f4017e9f..c2c2ae880 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2017-01-26 Werner Lemberg + + [base] Add `FT_Get_Sfnt_LangTag' function. + + * include/freetype/ftsnames.h (FT_SfntLangTag): New structure. + (FT_Get_Sfnt_LangTag): New declaration. + + * src/base/ftsnames.c (FT_Get_Sfnt_LangTag): New funtion. + + * docs/CHANGES: Updated. + 2017-01-26 Werner Lemberg [sfnt] Support `name' table format 1. diff --git a/docs/CHANGES b/docs/CHANGES index 0dec77062..aaaa588da 100644 --- a/docs/CHANGES +++ b/docs/CHANGES @@ -41,10 +41,11 @@ CHANGES BETWEEN 2.7.1 and 2.7.2 - Support for SFNT `name' tables has been improved. - . Format 1 `name' tables are now supported. + . Format 1 `name' tables are now supported. Use new function + `FT_Get_Sfnt_LangTag' to access associated language tags. - . Language ID and name ID values have been updated to OpenType version - 1.8.1. + . Language ID and name ID values have been updated to OpenType + version 1.8.1. ====================================================================== diff --git a/include/freetype/ftsnames.h b/include/freetype/ftsnames.h index cf34c1845..ff888b705 100644 --- a/include/freetype/ftsnames.h +++ b/include/freetype/ftsnames.h @@ -81,12 +81,20 @@ FT_BEGIN_HEADER /* See @TT_MAC_LANGID_XXX and @TT_MS_LANGID_XXX for */ /* possible values. */ /* */ + /* Registered OpenType values for `language_id' are */ + /* always smaller than 0x8000; values equal or larger */ + /* than 0x8000 usually indicate a language tag string */ + /* (introduced in OpenType version 1.6). Use function */ + /* @FT_Get_Sfnt_LangTag with `language_id' as its */ + /* argument to retrieve the associated language tag. */ + /* */ /* name_id :: An identifier for `string'. */ /* See @TT_NAME_ID_XXX for possible values. */ /* */ /* string :: The `name' string. Note that its format differs */ - /* depending on the (platform,encoding) pair. It can */ - /* be a Pascal String, a UTF-16 one, etc. */ + /* depending on the (platform,encoding) pair, being */ + /* either a string of bytes (without a terminating */ + /* NULL byte) or containing UTF-16BE entities. */ /* */ /* string_len :: The length of `string' in bytes. */ /* */ @@ -153,12 +161,80 @@ FT_BEGIN_HEADER /* `name' table entries, then do a loop until you get the right */ /* platform, encoding, and name ID. */ /* */ + /* `name' table format~1 entries can use language tags also, see */ + /* @FT_Get_Sfnt_LangTag. */ + /* */ FT_EXPORT( FT_Error ) FT_Get_Sfnt_Name( FT_Face face, FT_UInt idx, FT_SfntName *aname ); + /*************************************************************************/ + /* */ + /* */ + /* FT_SfntLangTag */ + /* */ + /* */ + /* A structure to model a language tag entry from an SFNT `name' */ + /* table. */ + /* */ + /* */ + /* string :: The language tag string, encoded in UTF-16BE */ + /* (without trailing NULL bytes). */ + /* */ + /* string_len :: The length of `string' in *bytes*. */ + /* */ + /* */ + /* Please refer to the TrueType or OpenType specification for more */ + /* details. */ + /* */ + typedef struct FT_SfntLangTag_ + { + FT_Byte* string; /* this string is *not* null-terminated! */ + FT_UInt string_len; /* in bytes */ + + } FT_SfntLangTag; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Sfnt_LangTag */ + /* */ + /* */ + /* Retrieve the language tag associated with a language ID of an SFNT */ + /* `name' table entry. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* langID :: The language ID, as returned by @FT_Get_Sfnt_Name. */ + /* This is always a value larger than 0x8000. */ + /* */ + /* */ + /* alangTag :: The language tag associated with the `name' table */ + /* entry's language ID. */ + /* */ + /* */ + /* FreeType error code. 0~means success. */ + /* */ + /* */ + /* The `string' array returned in the `alangTag' structure is not */ + /* null-terminated. Note that you don't have to deallocate `string' */ + /* by yourself; FreeType takes care of it if you call @FT_Done_Face. */ + /* */ + /* Only `name' table format~1 supports language tags. For format~0 */ + /* tables, this function always returns FT_Err_Invalid_Table. For */ + /* invalid format~1 language ID values, FT_Err_Invalid_Argument is */ + /* returned. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_Sfnt_LangTag( FT_Face face, + FT_UInt langID, + FT_SfntLangTag *alangTag ); + + /*************************************************************************** * * @constant: diff --git a/src/base/ftsnames.c b/src/base/ftsnames.c index 76ab7b210..868b42943 100644 --- a/src/base/ftsnames.c +++ b/src/base/ftsnames.c @@ -88,6 +88,58 @@ } + /* documentation is in ftsnames.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Get_Sfnt_LangTag( FT_Face face, + FT_UInt langID, + FT_SfntLangTag *alangTag ) + { + FT_Error error = FT_ERR( Invalid_Argument ); + + + if ( alangTag && face && FT_IS_SFNT( face ) ) + { + TT_Face ttface = (TT_Face)face; + + + if ( ttface->name_table.format != 1 ) + return FT_THROW( Invalid_Table ); + + if ( langID > 0x8000U && + langID - 0x8000U < ttface->name_table.numLangTagRecords ) + { + TT_LangTag entry = ttface->name_table.langTags + + ( langID - 0x8000U ); + + + /* load name on demand */ + if ( entry->stringLength > 0 && !entry->string ) + { + FT_Memory memory = face->memory; + FT_Stream stream = face->stream; + + + if ( FT_NEW_ARRAY ( entry->string, entry->stringLength ) || + FT_STREAM_SEEK( entry->stringOffset ) || + FT_STREAM_READ( entry->string, entry->stringLength ) ) + { + FT_FREE( entry->string ); + entry->stringLength = 0; + } + } + + alangTag->string = (FT_Byte*)entry->string; + alangTag->string_len = entry->stringLength; + + error = FT_Err_Ok; + } + } + + return error; + } + + #endif /* TT_CONFIG_OPTION_SFNT_NAMES */