Travailler avec la table 'name' | C++
La table de polices TrueType « nom » est le stockage des chaînes de texte liées à cette police. Ces chaînes peuvent être écrites dans différentes langues et représenter diverses entités, telles que des noms de polices, des noms de famille, des noms de concepteurs, des informations de licence, des avis de droits d’auteur, etc. En bref, les lignes contenues dans la table « nom » décrivent les métadonnées de police.
Schéma de la table ’name'.
La spécification détaillée de la table « name » est accessible dans les documentations Microsoft et Apple.
Il existe 2 formats pour une table « nom » avec les numéros 0 et 1 respectivement. En termes de table ’name’, ces numéros de format sont nommés comme version, donc le format 0 est désigné comme version 0 et le format 1 comme version 1.
Le format 1 diffère du format 0 dans l’identification de la langue. Toute entrée de la table ’name’ possède un identifiant de langue, qui est utilisé pour détecter la langue de cette chaîne. Et la différence entre le format 0 et le format 1 réside dans la manière dont ces identifiants de langue sont interprétés.
Les identifiants de langue pour le format 0 ont une interprétation spécifique à la plate-forme, mais les identifiants de langue pour le format 1 sont associés à des chaînes de balises de langue, qui identifient les langues quelle que soit la plate-forme.
Pour plus de précision, le format 1 permet de conserver les identifiants de langue des deux types : les identifiants avec une interprétation spécifique à la plate-forme et les identifiants associés aux chaînes de balises de langue (c’est-à-dire indépendants d’une plate-forme).
La bibliothèque Aspose.Font prend en charge le format 0 de la table ’name’. La prise en charge du format 1 est prévue pour les prochaines versions.
Indépendamment du format de la table ’name’, toute entrée de cette table est basée sur un composant particulier - la structure NameRecord.
Les quatre paramètres principaux de cette structure sont :
- identifiant de plateforme(platformID),
- identifiant spécifique à la plateforme (platformSpecificID),
- identifiant de nom (nameID),
- et l’identifiant de langue (langageID).
Les paramètres platformID
, platformSpecificID
et languageID
sont utilisés pour définir la langue de la chaîne d’une manière spécifique à la plate-forme. Les valeurs des paramètres platformSpecificID
et languageID
n’ont d’importance que dans le contexte du paramètre platformID.
Par exemple, platformSpecificID
égal à 0 définit le script romain pour la plate-forme Mac, et en même temps, platformSpecificID
définit le script romain pour la plate-forme Windows.
De la même manière, la valeur de languageID
n’a d’importance que dans le contexte du paramètre platformID utilisé.
Par exemple, languageID
définissant l’anglais USA est égal à 0 pour platformID = 1 (Mac) et 0x0409 pour platformID
= 3 (Windows).
Les exclusions sont uniquement languageID
pour le format de table de noms 1, associé à une chaîne de balise de langue, qui identifie les langues quelle que soit la plateforme.
Le paramètre nameID
est un nombre qui identifie une catégorie de chaîne logique, telle que le nom de la police, le nom de famille et autres. Il existe un
ensemble prédéfini d’identifiants de nom, qui est le même pour toutes les plates-formes et toutes les langues.
Ainsi, chaque entrée de la table ’nom’ peut être conditionnellement divisée en 3 parties :
- catégorie de chaîne logique,
- langage de chaînes,
- la chaîne elle-même.
Le paramètre nameID
est lié à la première partie, les paramètres platformID
, platformSpecificID
et langageID
sont liés à la deuxième partie.
Comment travailler avec les enregistrements de la table « nom » à l’aide d’Aspose.Font ?
La prise en charge de la table ’name’ est fournie par la classe TtfNameTable. De plus, nous considérons la fonctionnalité de cet objet.
Tout d’abord, décrivons les énumérations nécessaires pour utiliser les fonctionnalités de la classe TtfNameTable.- Les énumérations NameID et PlatformId sont liées aux paramètres décrits ci-dessus comme nameID et platformID.
- Les énumérations UnicodePlatformSpecificId, MacPlatformSpecificId sont liées au paramètre platformSpecificID.
Comme mentionné ci-dessus, “les valeurs des paramètres platformSpecificID et languageID n’ont d’importance que dans le contexte du paramètre platformID”. Ainsi, lorsque platformID est 0 et que cela définit la plate-forme Unicode, utilisez l’énumération UnicodePlatformSpecificId, lorsque platformID est 1 (plate-forme Macintosh), utilisez l’énumération MacPlatformSpecificId et lorsque platformID est 3 (plate-forme Windows), utilisez l’énumération MSPlatformSpecificId. .
Les énumérations MSLanguageId et MacLanguageId sont liées au paramètre LanguageID. Utilisez l’énumération MSLanguageId lorsque platformID est 3 (plate-forme Windows) et utilisez l’énumération MacLanguageId lorsque platformID est 1 (plate-forme Macintosh).
Passons maintenant à la question de l’obtention et de l’actualisation des entrées de la « table des noms ».
Comment récupérer les enregistrements de la table ’name’ ?
Commençons par la méthode GetAllNameRecords(). Cette méthode, comme son nom l’indique, renvoie toutes les entrées sans exclusions de la table ’name’. En pratique, la méthode n’est pas souvent appelée car dans la plupart des cas, les utilisateurs n’ont pas besoin de toutes les entrées, donc pour obtenir l’entrée nécessaire, la liste des entrées doit être soigneusement filtrée.
Le fait est que même dans une catégorie logique, FontFamily par exemple, les données de chaîne de cette catégorie peuvent être dans différentes langues. Ainsi, chaque langue a besoin d’une entrée distincte dans la table « nom » pour cette catégorie logique. Comme si les données de la catégorie FontFamily existaient en anglais, français et allemand, la catégorie FontFamily comprendrait 3 entrées.
De plus, l’entrée de langue peut elle-même être divisée en quelques entrées qui coïncident par les valeurs de données de chaîne et la valeur languageID
, mais diffèrent par les valeurs des paramètres platformID
et platformSpecificID
.
Pour simplifier l’échantillonnage des données de la table ’name’, la bibliothèque Aspose.Font propose les méthodes suivantes :
- GetNameRecordsByNameId()- renvoie la liste des entrées pour l’ensemble par la catégorie logique utilisateur, définie par le paramètre
nameID
. - GetMultiLanguageNameById() - renvoie toutes les entrées pertinentes pour le nameID de catégorie logique transmis en tant qu’objet de type MultiLanguageString. Grâce à l’objet de type - MultiLanguageString, nous pouvons connaître toutes les langues de cette catégorie et obtenir les données de chaîne pour la langue définie.
Vous pouvez obtenir la liste de toutes les langues en appelant la méthode GetAllLanguageIds() de type MultiLanguageString. Après avoir reçu la liste des langues, nous pouvons appeler la méthode GetStringForLanguageId() pour chaque ID de langue. Cette méthode renvoie la chaîne de données écrite dans ce langage.
La classe MultiLanguageString propose également les méthodes suivantes :
- ContainsString (string str)- vérifie si une chaîne passée est présente dans toutes les chaînes de langue de l’objet.
- GetEnglishString() - renvoie une chaîne écrite en anglais si elle est trouvée. Il renvoie la première chaîne, dont l’ID langue est MSLanguageId.English_United_States, MSLanguageId.English_Australia, MSLanguageId.English_United_Kingdom, MSLanguageId.English_Canada ou MSLanguageId.English_New_Zealand. S’il n’existe aucune chaîne avec l’identifiant de langue pertinent, la méthode renvoie la première chaîne de la liste.
- GetAllStrings() - renvoie toutes les chaînes de toutes les langues incluses dans l’objet.
- La méthode la plus simple à utiliser de la classe TtfNameTable est GetNameById(), qui a été conçue pour les cas où vous n’avez besoin que d’obtenir la valeur de la catégorie définie en anglais. Cette méthode recherche un enregistrement qui correspond à 2 critères :
- Cet enregistrement est rédigé en anglais, il a donc la valeur MSLanguageId.English_United_States ou MSLanguageId.English_United_Kingdom pour le paramètre LanguageID.
- Cet enregistrement a platformID avec la valeur égale à FontEnvironment.Current.CurrentPlatformId (3 dans l’implémentation actuelle, qui déclare la plateforme Microsoft).
Comment ajouter/mettre à jour des enregistrements dans la table ’name’ ?
La classe TtfNameTable fournit une méthode
AddName pour ajouter ou mettre à jour des enregistrements dans la table ’name’.
Cette méthode crée la structure de type
NameRecord et l’insère dans la table ’name’. Si l’enregistrement coïncide avec celui ajouté par les paramètres platformID
, platformSpecificID
, langueID
et nameID
existe déjà, la méthode n’ajoute pas de nouvel enregistrement, mais met à jour les données de chaîne dans l’enregistrement existant en utilisant la valeur , défini par le paramètre name
.
Le paramètre nameId
définit la catégorie de chaîne logique pour un enregistrement. Les paramètres platformId
, platformSpecificId
et lingualId
sont utilisés pour définir la langue de la chaîne. Et le dernier paramètre « nom » est utilisé pour définir les données de chaîne pour un enregistrement.
Exemples d’utilisation des fonctions de l’objet TtfNameTable.
Ajoutez des inclusions et utilisez des espaces de noms :
1#include <system/text/string_builder.h>
2#include <system/enum.h>
3#include <system/console.h>
4#include <system/collections/list.h>
5#include <Aspose.Font.Cpp/src/TtfTables/TtfNameTable.h>
6#include <Aspose.Font.Cpp/src/TtfTables/TtfTableRepository.h>
7#include <Aspose.Font.Cpp/src/Ttf/TtfFont.h>
8#include <Aspose.Font.Cpp/src/MultiLanguageString.h>
9#include <Aspose.Font.Cpp/src/FontType.h>
10#include <Aspose.Font.Cpp/src/Font.h>
11
12en utilisant le système d'espace de noms ;
13en utilisant l'espace de noms Aspose::Font::Ttf;
14en utilisant l'espace de noms Aspose::Font::TtfTables ;
Déclaration et initialisation d’une variable de police.
1 System::SharedPtr<Aspose::Font::Ttf::TtfFont> _font;
Les 2 extraits suivants impriment la valeur pour la catégorie Nom complet de la police et produisent le même résultat pour la police Lora-Regular
1 //1
2 String fullFontName = _font->get_TtfTables()->get_NameTable()->GetNameById(TtfNameTable::NameId::FullName);
3 Console::WriteLine(String::Format(u"Full font name: {0}", fullFontName));
4 //2
5 String fullFontName = _font->get_TtfTables()->get_NameTable()->GetMultiLanguageNameById(TtfNameTable::NameId::FullName)->GetEnglishString();
6 Console::WriteLine(String::Format(u"Full font name: {0}", fullFontName));
Impression de tout le contenu de la table ’name'.
L’extrait ci-dessous montre comment effectuer cette opération.
1 System::ArrayPtr<TtfNameTable::NameId> ids = System::Enum<TtfNameTable::NameId>::GetValues();
2
3 for (TtfNameTable::NameId nameId : ids)
4 {
5 System::SharedPtr<MultiLanguageString> mlString = _font->get_TtfTables()->get_NameTable()->GetMultiLanguageNameById(nameId);
6 if (mlString == nullptr)
7 {
8 continue;
9 }
10 System::Console::WriteLine(System::String::Format(u"{0}: {1}", nameId, GetMultiLanguageStringValue(mlString)));
11 }
12
13 //Using of this method has no sense when strings from 'name' table have only single language, but it can be useful when font
14 //'name' table include multilingual strings
15 System::String MetadataExamples::GetMultiLanguageStringValue(System::SharedPtr<MultiLanguageString> mlString)
16 {
17 System::ArrayPtr<int32_t> languages = mlString->GetAllLanguageIds();
18 if (languages->get_Length() == 1)
19 {
20 return mlString->GetEnglishString();
21 }
22
23 System::SharedPtr<System::Text::StringBuilder> sb = System::MakeObject<System::Text::StringBuilder>();
24
25 for (int32_t i = 0; i < languages->get_Length(); i++)
26 {
27 int32_t langId = languages[i];
28 sb->Append(System::String::Format(u"{0}: {1}", System::Enum<TtfNameTable::MSLanguageId>::GetName((TtfNameTable::MSLanguageId)langId), mlString->GetStringForLanguageId(langId)));
29 if (i != (languages->get_Length() - 1))
30 {
31 sb->Append(u", ");
32 }
33 }
34
35 return sb->ToString();
36 }
Mise à jour des valeurs des catégories « Nom de la sous-famille de police » et « Description »
Pour ajouter ou actualiser correctement l’entrée dans la table ’name’, nous devons transmettre les valeurs des paramètres platformID, platformSpecificID et languageID qui coïncident avec celles déjà présentes dans la table ’name’. Pour cela, avant de rafraîchir les données, nous lirons les enregistrements existants de type NameRecord pertinents pour la catégorie logique de rafraîchissement, définie par identifiant de nom.
1 //Struct for update operations
2 struct UpdateData
3 {
4 private:
5 TtfNameTable::NameId _nameId;
6 System::String _data;
7
8 public:
9 UpdateData(TtfNameTable::NameId nameId, String data)
10 {
11 this->_nameId = nameId;
12 this->_data = data;
13 }
14
15 TtfNameTable::NameId get_NameId() const
16 {
17 return this->_nameId;
18 }
19
20 String get_StringData() const
21 {
22 return this->_data;
23 }
24 };
25
26 UpdateData recordsToUpdate[] = {
27 UpdateData(TtfNameTable::NameId::FontSubfamily, String(u"Italic")),
28 UpdateData(TtfNameTable::NameId::Description, String(u"New description"))};
29
30 SharedPtr<TtfNameTable::NameRecord> firstRecord = nullptr;
31
32 for(UpdateData updateData : recordsToUpdate)
33 {
34 //Declare variable for NameRecord structure to use for update operations
35 SharedPtr<TtfNameTable::NameRecord> record = nullptr;
36
37 System::ArrayPtr<System::SharedPtr<TtfNameTable::NameRecord>> records = _font->get_TtfTables()->get_NameTable()->GetNameRecordsByNameId(updateData.get_NameId());
38
39 //In this example we will use only info from the first NameRecord structure returned to update font metadata.
40 //Many actual fonts require serious analyze of all NameRecords returned to update metadata correctly
41
42 //Initialize just created variables
43 if (records->get_Length() == 0)
44 {
45 //If no any record was found for current name identifer,
46 //we will use first found record for any name identifier
47 if (firstRecord == nullptr)
48 {
49 firstRecord = GetFirstExistingRecord(_font->get_TtfTables()->get_NameTable());
50 }
51 record = firstRecord;
52 }
53 else
54 {
55 record = records[0];
56 }
57
58 //Add or update record in 'name' table
59 _font->get_TtfTables()->get_NameTable()->AddName(updateData.get_NameId(), StaticCast<TtfNameTable::PlatformId>(record->get_PlatformId()), record->get_PlatformSpecificId(), record->get_LanguageId(), updateData.get_StringData());
60 }
61
62 System::SharedPtr<Aspose::Font::TtfTables::TtfNameTable::NameRecord> MetadataExamples::GetFirstExistingRecord(System::SharedPtr<Aspose::Font::TtfTables::TtfNameTable> table)
63 {
64 System::ArrayPtr<System::SharedPtr<TtfNameTable::NameRecord>> records;
65 for (TtfNameTable::NameId nameId : System::Enum<TtfNameTable::NameId>::GetValues())
66 {
67 records = table->GetNameRecordsByNameId(nameId);
68 if (records->get_Length() != 0)
69 {
70 return records[0];
71 }
72 }
73
74 return table->GetAllNameRecords()->idx_get(0);
75 }
D’autres exemples pour actualiser la table ’name’ que vous pouvez trouver dans le test solution MetadataExamples.cpp.