Робота з таблицею 'name' | .NET

Таблиця шрифтів TrueType ’name’ є сховищем для текстових рядків, пов’язаних із цим шрифтом. Ці рядки можуть бути написані різними мовами та можуть представляти різні сутності, такі як назви шрифтів, прізвища, імена дизайнерів, інформація про ліцензію, повідомлення про авторські права тощо. Коротше кажучи, рядки, які містяться в таблиці ’name’, описують метадані шрифту.

Схема таблиці ‘ім’я’.

Детальна специфікація для таблиці ’name’ доступна в Microsoft і Apple документації.

Існує 2 формати для таблиці ’name’ з номерами 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 має значення лише в контексті використовуваного параметра platformID.

Наприклад, «languageID», що визначає англійську, США, дорівнює 0 для platformID = 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». Отже, коли platformID дорівнює 0 і це визначає платформу Unicode, використовуйте перерахування UnicodePlatformSpecificId, коли platformID дорівнює 1 (платформа Macintosh), використовуйте перерахування MacPlatformSpecificId, а коли platformID дорівнює 3 (платформа Windows), використовуйте перерахування MSPlatformSpecificId .

Перерахування MSLanguageId і MacLanguageId пов’язані з параметром languageID. Використовуйте перерахування MSLanguageId, коли platformID дорівнює 3 (платформа Windows), і використовуйте перерахування MacLanguageId, коли platformID дорівнює 1 (платформа Macintosh).

Давайте тепер приступимо до отримання та оновлення записів із «таблиці імен».

Як отримати записи з таблиці ’name'?

Почнемо з методу GetAllNameRecords(). Цей метод, як випливає з назви, повертає всі записи без виключення таблиці ім’я. На практиці цей метод не часто викликається, оскільки користувачам у більшості випадків не потрібні всі записи, тому, щоб отримати потрібний запис, список записів потрібно ретельно відфільтрувати.

Справа в тому, що навіть в одній логічній категорії, наприклад 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).

Як додати/оновити записи в таблиці “name”?

Клас TtfNameTable надає метод AddName для додавання або оновлення записів у таблиці «імен».

Цей метод створює структуру типу 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));

Друк всього вмісту таблиці ’name'.

Наведений нижче фрагмент показує, як виконати цю операцію.

 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    }		

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

Щоб правильно додати або оновити запис у таблиці name, нам потрібно передати значення параметрів platformID, platformSpecificID і languageID, які збігаються з тими, що вже присутні в таблиці name. Для цього перед оновленням даних ми прочитаємо існуючі записи типу 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    } 	

Інші приклади оновлення таблиці «імен» можна знайти в тесті solution MetadataExamples.cs.

Subscribe to Aspose Product Updates

Get monthly newsletters & offers directly delivered to your mailbox.