Commit f4253366f1d90e6b28b4b3e34ed74e24aa7c2c31

Werner Lemberg 2017-01-27T00:06:52

[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.

diff --git a/ChangeLog b/ChangeLog
index 7f4017e..c2c2ae8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2017-01-26  Werner Lemberg  <wl@gnu.org>
 
+	[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  <wl@gnu.org>
+
 	[sfnt] Support `name' table format 1.
 
 	* include/freetype/internal/tttypes.h (TT_LangTagRec): New
diff --git a/docs/CHANGES b/docs/CHANGES
index 0dec770..aaaa588 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 cf34c18..ff888b7 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 );
 
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_SfntLangTag                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure to model a language tag entry from an SFNT `name'      */
+  /*    table.                                                             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    string      :: The language tag string, encoded in UTF-16BE        */
+  /*                   (without trailing NULL bytes).                      */
+  /*                                                                       */
+  /*    string_len  :: The length of `string' in *bytes*.                  */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    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;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Sfnt_LangTag                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieve the language tag associated with a language ID of an SFNT */
+  /*    `name' table entry.                                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    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.             */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    alangTag :: The language tag associated with the `name' table      */
+  /*                entry's language ID.                                   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0~means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    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 76ab7b2..868b429 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 */