Работа с таблицей name | .NET

Таблица шрифтов TrueType «имя» — это хранилище текстовых строк, связанных с этим шрифтом. Эти строки могут быть написаны на разных языках и могут представлять различные объекты, такие как имена шрифтов, фамилии, имена дизайнеров, информацию о лицензии, уведомления об авторских правах и т. д. Короче говоря, строки, содержащиеся в таблице «имя», описывают метаданные шрифта.

Схема таблицы «имя»

Подробная спецификация таблицы «name» доступна в документации Microsoft и Apple.

Существует два формата таблицы «имя» с номерами 0 и 1 соответственно. В таблице name эти номера форматов называются версией, поэтому формат 0 обозначается как версия 0, а формат 1 - как версия 1.

Формат 1 отличается от формата 0 идентификацией языка. Любая запись в таблице name имеет идентификатор языка, который используется для определения языка этой строки. А разница между форматом 0 и форматом 1 заключается в том, как интерпретируются эти идентификаторы языка.

Идентификаторы языка для формата 0 интерпретируются в зависимости от платформы, но идентификаторы языка для формата 1 связаны со строками языковых тегов, которые идентифицируют языки независимо от платформы.

Для большей точности формат 1 позволяет хранить идентификаторы языка обоих типов — идентификаторы с интерпретацией, зависящей от платформы, и идентификаторы, связанные со строками языковых тегов (т. е. независимые от платформы).

Библиотека Aspose.Font поддерживает формат 0 таблицы name. Поддержка формата 1 запланирована в будущих выпусках.

Независимо от формата таблицы name, любая запись в этой таблице основана на определенном компоненте — структуре NameRecord.

Четыре основных параметра этой структуры:

Параметры «platformID», «platformSpecificID» и «languageID» используются для установки языка строки в зависимости от платформы. Значения параметров «platformSpecificID» и «languageID» имеют значение только в контексте параметра «platformID».

Например, platformSpecificID, равный 0, определяет латинский алфавит для платформы Mac, и в то же время platformSpecificID определяет латинский алфавит для платформы Windows. Аналогично, значение «languageID» имеет значение только в контексте используемого параметра «ID платформы».

Например, languageID, определяющий английский язык США, равен 0 для идентификатора платформы = 1 (Mac) и 0x0409 для platformID = 3 (Windows).

Исключениями являются только languageID для формата таблицы имен 1, связанного со строкой языкового тега, которая идентифицирует языки независимо от платформы.

Параметр nameID — это число, которое идентифицирует категорию логической строки, например имя шрифта, фамилию и другие. Существует предопределенный набор идентификаторов имен, который одинаков для всех платформ и языков.

Итак, каждую запись таблицы name условно можно разделить на 3 части:

  1. категория логической строки,
  2. строковый язык,
  3. сама строка.

Параметр «nameID» относится к первой части, параметры «platformID», «platformSpecificID» и «languageID» относятся ко второй части.

Как работать с записями таблицы «имя» с помощью Aspose.Font?

Поддержка таблицы name обеспечивается классом TtfNameTable. Далее рассмотрим функционал данного объекта.

Сначала опишем перечисления, необходимые для работы с функциональностью класса TtfNameTable.- Перечисления NameID и PlatformId относятся к таким параметрам, описанным выше, как nameID и PlatformID.

Как было сказано выше, «Значения параметров PlatformSpecificID и LanguageID имеют значение только в контексте параметра PlatformID». Итак, когда идентификатор платформы равен 0 и это определяет платформу Unicode, используйте перечисление UnicodePlatformSpecificId, когда идентификатор платформы равен 1 (платформа Macintosh), используйте перечисление MacPlatformSpecificId, а когда идентификатор платформы равен 3 (платформа Windows), используйте перечисление MSPlatformSpecificId .

Перечисления MSLanguageId и MacLanguageId относятся к параметру LanguageID.

Используйте перечисление MSLanguageId, если идентификатор платформы равен 3 (платформа Windows), и используйте перечисление MacLanguageId, если идентификатор платформы равен 1 (платформа Macintosh).

Теперь приступим к получению и обновлению записей из таблицы имен.

Как получить записи из таблицы name?

Начнем с метода GetAllNameRecords(). Этот метод, как следует из названия, возвращает все записи без исключения таблицы name. На практике метод вызывается нечасто, так как пользователям в большинстве случаев не нужны все записи, поэтому для получения нужной записи список записей приходится тщательно фильтровать.

Дело в том, что даже в одной логической категории, например FontFamily, строковые данные этой категории могут быть на разных языках. Таким образом, для каждого языка требуется отдельная запись в таблице «имя» для этой логической категории. Например, если данные для категории FontFamily существуют на английском, французском и немецком языках, категория FontFamily будет включать 3 записи.

Кроме того, запись языка сама по себе может быть разделена на несколько записей, которые совпадают по значениям строковых данных и значению languageID, но различаются значениями параметров platformID и platformSpecificID.

Для упрощения выборки данных из таблицы name библиотека Aspose.Font предлагает следующие методы:

Класс MultiLanguageString также предлагает следующие методы:

  1. Эта запись написана на английском языке, поэтому она имеет значение MSLanguageId.English_United_States или MSLanguageId.English_United_Kingdom для параметра LanguageID.
  2. Эта запись имеет идентификатор платформы со значением, равным FontEnvironment.Current.CurrentPlatformId (3 в текущей реализации, которая объявляет платформу Microsoft).

Как добавить/обновить записи в таблице «имя»?

Класс TtfNameTable предоставляет метод AddName для добавления или обновления записей в таблице name.

Этот метод создает структуру типа NameRecord и вставляет ее в таблицу name. Если запись совпадает с добавленной по параметрам «platformID», «platformSpecificID», «languageID», «nameID» уже существует, метод не добавляет новую запись, а обновляет строковые данные в существующей записи, используя значение , определяемый параметром name.

Параметр nameId определяет категорию логической строки для записи. Параметры «platformId», «platformSpecificId» и «languageId» используются для установки языка строки. И последний параметр name используется для установки строковых данных для записи.

Примеры использования функций объекта TtfNameTable.

Включите использование для следующих пространств имен:

1using System;
2using System.Text;
3using System.Collections.Generic;
4using Aspose.Font.Ttf;
5using Aspose.Font.TtfTables;

Объявление и инициализация переменной шрифта.

1TtfFont font;

Следующие 2 фрагмента печатают значение для категории Полное имя шрифта и дают тот же результат для шрифта Lora-Regular.

1    //1
2    string fullFontName = font.TtfTables.NameTable.GetNameById(TtfNameTable.NameId.FullName);
3    Console.WriteLine(String.Format("Full font name: {0}", fullFontName ));
4    //2
5    string fullFontName = font.TtfTables.NameTable.GetMultiLanguageNameById(TtfNameTable.NameId.FullName).GetEnglishString();
6    Console.WriteLine(String.Format("Full font name: {0}", fullFontName));

Печать всего содержимого таблицы «имя».

В приведенном ниже фрагменте показано, как выполнить эту операцию.

 1    TtfNameTable.NameId[] ids = Enum.GetValues<TtfNameTable.NameId>();
 2
 3    foreach (TtfNameTable.NameId nameId in ids)
 4    {
 5        MultiLanguageString mlString = font.TtfTables.NameTable.GetMultiLanguageNameById(nameId);
 6            if (mlString == null)
 7                continue;
 8        Console.WriteLine(string.Format("{0}: {1}", nameId, GetMultiLanguageStringValue(mlString)));
 9    }
10    //Using of this method has no sense when strings from 'name' table have only single language, but it can be useful when font
11    //'name' table include multilingual strings
12    string GetMultiLanguageStringValue(MultiLanguageString mlString)
13    {
14        int[] languages = mlString.GetAllLanguageIds();
15        if(languages.Length == 1)
16            return mlString.GetEnglishString();
17
18        StringBuilder sb = new StringBuilder();
19
20        for(int i = 0; i < languages.Length; i++) 
21        {
22            int langId = languages[i];
23            sb.Append(String.Format("{0}: {1}", Enum.GetName<TtfNameTable.MSLanguageId>(
24                (TtfNameTable.MSLanguageId)langId), mlString.GetStringForLanguageId(langId)));
25            if (i != (languages.Length - 1))
26                sb.Append(", ");
27        }
28
29        return sb.ToString();
30    }		

Обновление значений для категорий «Название подсемейства шрифта» и «Описание».

Чтобы правильно добавить или обновить запись в таблице «имя», нам необходимо передать значения параметров «platformID», «platformSpecificID» и «languageID», совпадающие с теми, которые уже присутствуют в таблице «имя». Для этого перед обновлением данных мы прочитаем существующие записи типа NameRecord, относящиеся к категории логики обновления, определенной идентификатором имени.

 1    //Struct for update operations
 2    struct UpdateData
 3    {
 4        private TtfNameTable.NameId _nameId;
 5        private string _data;
 6
 7        public UpdateData(TtfNameTable.NameId nameId, string data)
 8        {
 9            this._nameId = nameId;
10            this._data = data;
11        }
12
13        public TtfNameTable.NameId NameId => this._nameId;
14        public string StringData => this._data;
15    }
16		
17    UpdateData[] recordsToUpdate = new UpdateData[]
18    {
19        new UpdateData(TtfNameTable.NameId.FontSubfamily, "Italic"),
20        new UpdateData(TtfNameTable.NameId.Description, "New description")
21    };
22
23    TtfNameTable.NameRecord firstRecord = null;
24
25    foreach (UpdateData updateData in recordsToUpdate)
26    {
27        TtfNameTable.NameRecord[] records = font.TtfTables.NameTable.GetNameRecordsByNameId(updateData.NameId);
28
29        //Declare variable for NameRecord structure to use for update operations
30        TtfNameTable.NameRecord record = null;
31
32        //In this example we will use only info from the first NameRecord structure returned to update font metadata.
33        //Many actual fonts require serious analyze of all NameRecords returned to update metadata correctly
34
35        //Initialize just created variables
36        if (records.Length == 0)
37        {
38            //If no any record was found for current name identifer,
39            //we will use first found record for any name identifier
40            if (firstRecord == null)
41            {
42                firstRecord = GetFirstExistingRecord(font.TtfTables.NameTable);
43            }
44            record = firstRecord;
45        }
46        else
47        {
48            record = records[0];
49        }
50
51        //Add or update record in 'name' table
52        font.TtfTables.NameTable.AddName(updateData.NameId, (TtfNameTable.PlatformId)record PlatformId, 
53                        record.PlatformSpecificId, record.LanguageId, updateData.StringData);
54    }		
55
56		
57    TtfNameTable.NameRecord GetFirstExistingRecord(TtfNameTable table)
58    {
59        TtfNameTable.NameRecord[] records = null;
60        foreach (TtfNameTable.NameId nameId in Enum.GetValues<TtfNameTable.NameId>())
61        {
62            records = table.GetNameRecordsByNameId(nameId);
63            if (records.Length != 0)
64                return records[0];
65        }
66
67        return table.GetAllNameRecords()[0];
68    } 	

Другие примеры обновления таблицы name вы можете найти в тесте solution MetadataExamples.cs.

Subscribe to Aspose Product Updates

Get monthly newsletters & offers directly delivered to your mailbox.