The 'ltag'
table
Introduction
The 'ltag'
table provides a mapping between numeric codes and IETF language tags. The numeric codes are used in language field of the 'name'
table for strings with a Unicode platform. The codes are also used in conjunction with the 'feat'
and 'morx'
tables to provide language-specific shaping.
IETF language tags are used for a number of reasons. First, they are standard and in common use. In particular, they're used by locales on OS X and iOS. Secondly, they are extensible and don't require a pre-determined ennumeration of supported languages.
The table uses two structures.
Type | Name | Description |
---|---|---|
UInt16 | offset | Offset from the start of the table to the beginning of the string |
UInt16 | length | String length (in bytes) |
Type | Name | Description |
---|---|---|
UInt32 | version | Table version; currently 1 |
UInt32 | flags | Table flags; currently none defined |
UInt32 | numTags | Number of language tags which follow |
FTStringRange[] | tagRange | Range for each tag's string |
There is one range per tag. Offsets are from the beginning of the table.
The flags field is currently unused and should be 0. The current version is 1.
IETF language tags are in ASCII and can therefore be interpreted as UTF-8 or any other ASCII-compatible text-encoding.
If we had a font with both English and Spanish names, we could build the following 'ltag'
table:
Type | Value | Description |
---|---|---|
UInt32 | 1 | Version |
UInt32 | 0 | Flags |
UInt32 | 2 | numTags |
FTStringRange | 0,2 | First tag |
FTStringRange | 2,2 | Second tag |
char[] | "ensp" | Tag strings |
This maps English to language code 0 and Spanish to language code 1. We could then use this in the name table with Unicode-platform names:
Language Code | Value |
---|---|
-1 (don't care) | Geneva |
0 | Geneva |
1 | Ginebra |
Language tags are also used by 'feat'
and 'morx'
tables using the new always-exclusive feature 39 (language code).
A standard example of this is a case where Cyrillic italic letters are written one way in Serbia and another way everywhere else. We can add to our 'ltag'
table:
Type | Value | Description |
---|---|---|
UInt32 | 1 | Version |
UInt32 | 0 | Flags |
UInt32 | 3 | numTags |
FTStringRange | 0,2 | First tag |
FTStringRange | 2,2 | Second tag |
FTStringRange | 4,2 | Third tag |
char[] | "enspsr" | Tag strings |
We can then define a font feature with feature type 39 and selector type 3. (We add one to the 'ltag'
index here because a selector type of 0 means "no change" for an exclusive feature.) We can then define a 'morx'
subtable that maps the standard Cyrillic glyphs to the Serbian-specific ones.
Note that the use of the 'ltag'
means that language tag IDs are internal to a specific font. This is similar to the way that glyphIDs are specific to a font. Anything which needs to know the identity of a glyph outside the context of the specific font needs to convert its glyph ID to a PostScript name via the 'post'
table. Similarly, anything which needs to know the identity of a language tag outside the context of a specific font would need to convert the tag ID to an IETF tag via the 'ltag'
table.
UI concerns:
IETF language tie naturally in to the OS X and iOS user interface and tools such as ftxdumperfuser
. One could use a statement like
[[NSLocale autoupdatingCurrentLocale] displayNameForKey:NSLanguageIdentifier value:tag]
to get the proper string to use in the UI. This also ties in well with locale information as used elsewhere in the system.
Platform-specific Information
Support for the 'ltag'
table is available on OS X 10.9 (Mavericks) and later, and on iOS 7.0 and later. The 'ltag'
table is currently supported only in conjunction with 'morx'
(extended metamorphosis) and 'feat'
(font feature) tables.
Tools
'ltag'
tables are fully supported by ftxdumperfuser. ftxenhancer will generate or extended 'ltag'
tables as needed when processing an ATIF.