Trabajar con la tabla 'nombre' | .NET
La tabla de fuentes TrueType ’nombre’ es el almacenamiento de cadenas de texto relacionadas con esa fuente. Estas cadenas se pueden escribir en diferentes idiomas y pueden representar varias entidades, como nombres de fuentes, apellidos, nombres de diseñadores, información de licencia, avisos de derechos de autor, etc. En resumen, las líneas que se encuentran en la tabla ’nombre’ describen los metadatos de la fuente.
Esquema de la tabla ’nombre'.
The detailed specification for ’name’ table is accessible in * Microsoft* and Apple documentations.
Hay 2 formatos para una tabla de ’nombre’ con los números 0 y 1 respectivamente. En términos de la tabla ’nombre’, estos números de formato se denominan versión, por lo que el formato 0 se designa como versión 0 y el formato 1, como versión 1.
El formato 1 se diferencia del formato 0 en la identificación del idioma. Cualquier entrada en la tabla ’nombre’ tiene un identificador de idioma, que se utiliza para detectar el idioma de esa cadena. Y la diferencia entre el formato 0 y el formato 1 está en cómo se interpretan estos identificadores de idioma.
Los identificadores de idioma para el formato 0 tienen una interpretación específica de la plataforma, pero los identificadores de idioma para el formato 1 están asociados con cadenas de etiquetas de idioma, que identifican los idiomas independientemente de la plataforma.
Para mayor precisión, el formato 1 permite mantener identificadores de idioma de ambos tipos: identificadores con interpretación específica de la plataforma e identificadores asociados con cadenas de etiquetas de idioma (es decir, independientes de una plataforma).
La biblioteca Aspose.Font admite el formato 0 de la tabla ’nombre’. Está prevista la compatibilidad con el formato 1 para futuras versiones.
Independientemente del formato que tenga la tabla ’nombre’, cualquier entrada en esta tabla se basa en un componente particular: la estructura NameRecord.
Los cuatro parámetros principales de esta estructura son:
- identificador de plataforma(platformID),
- identificador específico de la plataforma (platformSpecificID),
- identificador de nombre (nameID),
- e identificador de idioma (languageID).
Los parámetros platformID
, platformSpecificID
y languageID
se utilizan para configurar el idioma de la cadena de manera específica de la plataforma. Los valores de los parámetros platformSpecificID
y languageID
solo importan en el contexto del parámetro platformID.
Por ejemplo, “platformSpecificID” igual a 0 define la escritura romana para la plataforma Mac y, al mismo tiempo, “platformSpecificID” define la escritura romana para la plataforma Windows. De manera similar, el valor de “languageID” solo importa en el contexto del parámetro platformID utilizado.
Por ejemplo, languageID
que define inglés EE. UU. es igual a 0 para platformID = 1 (Mac) y 0x0409 para platformID
= 3 (Windows).
Las exclusiones solo son languageID
para el formato de tabla de nombres 1, asociado con una cadena de etiqueta de idioma, que identifica los idiomas independientemente de la plataforma.
El parámetro “nameID” es un número que identifica una categoría de cadena lógica, como nombre de fuente, apellido y otros. Hay un conjunto predefinido de identificadores de nombres, que es el mismo para todas las plataformas e idiomas.
Así, cada entrada de la tabla ’nombre’ se puede dividir condicionalmente en 3 partes:
- categoría de cadena lógica,
- lenguaje de cadenas,
- la cuerda misma.
El parámetro nameID
está relacionado con la primera parte, los parámetros platformID
, platformSpecificID
y languageID
están relacionados con la segunda parte.
¿Cómo trabajar con registros de la tabla ’nombre’ usando Aspose.Font?
El soporte para la tabla ’nombre’ lo proporciona la clase TtfNameTable. Además, consideramos la funcionalidad de este objeto.
Primero, describamos las enumeraciones necesarias para trabajar con la funcionalidad de la clase TtfNameTable.- Las enumeraciones NameID y PlatformId están relacionadas con los parámetros descritos anteriormente como nameID y platformID.
- Las enumeraciones UnicodePlatformSpecificId, MacPlatformSpecificId, MSPlatformSpecificId están relacionadas con el parámetro platformSpecificID.
Como se mencionó anteriormente, “los valores de los parámetros platformSpecificID e languageID sólo importan en el contexto del parámetro platformID”. Entonces, cuando platformID es 0 y esto define la plataforma Unicode, use la enumeración UnicodePlatformSpecificId, cuando platformID sea 1 (plataforma Macintosh), use la enumeración MacPlatformSpecificId, y cuando platformID sea 3 (plataforma Windows), use la enumeración MSPlatformSpecificId .
Las enumeraciones MSLanguageId y MacLanguageId están relacionadas con el parámetro languageID. Utilice la enumeración MSLanguageId, cuando el ID de plataforma sea 3 (plataforma Windows) y utilice la enumeración MacLanguageId cuando el ID de plataforma sea 1 (plataforma Macintosh).
Procedamos ahora con la cuestión de obtener y actualizar entradas de la ’tabla de nombres'.
¿Cómo obtener registros de la tabla ’nombre'?
Empecemos por el método GetAllNameRecords(). Este método, como se desprende de su nombre, devuelve todas las entradas sin exclusiones de la tabla ’nombre’. En la práctica, este método no se utiliza con frecuencia ya que los usuarios en la mayoría de los casos no necesitan todas las entradas, por lo que para obtener la entrada necesaria, la lista de entradas debe filtrarse minuciosamente.
El problema es que incluso en una categoría lógica, por ejemplo FontFamily, las cadenas de datos de esta categoría pueden estar en diferentes idiomas. Por lo tanto, cada idioma necesita una entrada separada en la tabla ’nombre’ para esta categoría lógica. Por ejemplo, si los datos de la categoría FontFamily existieran en inglés, francés y alemán, la categoría FontFamily incluiría 3 entradas.
Además, la entrada de idioma se puede dividir en unas pocas entradas que coinciden con los valores de datos de cadena y el valor “languageID”, pero difieren con los valores de los parámetros “platformID” y “platformSpecificID”.
Para simplificar el muestreo de datos de la tabla ’nombre’, la biblioteca Aspose.Font ofrece los siguientes métodos:
- GetNameRecordsByNameId()- devuelve la lista de entradas para el conjunto por categoría lógica de usuario, definida por el parámetro
nameID
. - GetMultiLanguageNameById(): devuelve todas las entradas relevantes para la categoría lógica pasada nameID como un objeto de tipo MultiLanguageString. Por medio del objeto de tipo - MultiLanguageString, podemos encontrar todos los idiomas de esta categoría y obtener los datos de la cadena para el idioma establecido. Puede obtener la lista de todos los idiomas llamando al método GetAllLanguageIds() del tipo MultiLanguageString. Después de recibir la lista de idiomas, podemos llamar al método GetStringForLanguageId() para cada ID de idioma. Este método devuelve la cadena de datos escrita en este idioma.
La clase MultiLanguageString también ofrece los siguientes métodos:
- ContainsString (string str): comprueba si una cadena pasada está presente dentro de todas las cadenas de idioma del objeto.
- GetEnglishString() - devuelve una cadena escrita en inglés si se encuentra. Devuelve la primera cadena, cuyo ID de idioma es MSLanguageId.English_United_States, MSLanguageId.English_Australia, MSLanguageId.English_United_Kingdom, MSLanguageId.English_Canada o MSLanguageId.English_New_Zealand. Si no hay cadenas con el identificador de idioma relevante, el método devuelve la primera cadena de la lista.
- GetAllStrings() - devuelve todas las cadenas de todos los idiomas que incluye el objeto.
- El método más sencillo de usar de la clase TtfNameTable es GetNameById(), que fue diseñado para casos en los que solo necesita obtener el valor de la categoría establecida en inglés. Este método busca un registro, que corresponde a 2 criterios:
- Este registro está escrito en inglés, por lo que tiene el valor MSLanguageId.English_United_States o MSLanguageId.English_United_Kingdom para el parámetro languageID.
- Este registro tiene platformID con el valor igual a FontEnvironment.Current.CurrentPlatformId (3 en la implementación actual, que declara la plataforma Microsoft).
¿Cómo agregar/actualizar registros en la tabla ’nombre'?
La clase TtfNameTable proporciona un método AddName para agregar o actualizar registros en la tabla ’nombre'.
Este método crea la estructura del tipo
NameRecord y la inserta en la tabla ’nombre’. Si el registro coincide con el agregado por los parámetros platformID
, platformSpecificID
, languageID
y nameID
ya existe, el método no agrega un nuevo registro, sino que actualiza los datos de cadena en el registro existente usando el valor , definido por el parámetro nombre
.
El parámetro nameId
define la categoría de cadena lógica para un registro. Los parámetros platformId
, platformSpecificId
y languageId
se utilizan para establecer el idioma de la cadena. Y el último parámetro “nombre” se usa para establecer datos de cadena para un registro.
Ejemplos de uso de funciones del objeto TtfNameTable.
Incluya el uso para los siguientes espacios de nombres:
1using System;
2using System.Text;
3using System.Collections.Generic;
4using Aspose.Font.Ttf;
5using Aspose.Font.TtfTables;
Declarar e inicializar una variable de fuente.
1TtfFont font;
Los siguientes 2 fragmentos imprimen el valor de la categoría Nombre de fuente completo y producen el mismo resultado para la fuente 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));
Imprimiendo todo el contenido de la tabla ’nombre'.
El siguiente fragmento muestra cómo realizar esta operación.
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 }
Actualización de valores para las categorías “Nombre de subfamilia de fuentes” y “Descripción”
Para agregar o actualizar la entrada en la tabla ’nombre’ correctamente, necesitamos pasar los valores de los parámetros platformID, platformSpecificID e languageID que coincidan con los que ya están presentes en la tabla ’nombre’. Para ello, antes de actualizar los datos leeremos los registros existentes del tipo NameRecord relevantes a la categoría lógica de actualización, definida por el identificador de nombre.
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 }
Puede encontrar otros ejemplos para actualizar la tabla ’nombre’ en la prueba solución MetadataExamples.cs.