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 :

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 :

  1. catégorie de chaîne logique,
  2. langage de chaînes,
  3. 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.

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 :

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 :

  1. 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.
  2. 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.

Subscribe to Aspose Product Updates

Get monthly newsletters & offers directly delivered to your mailbox.