Fuentes variables OpenType
En este tema se describen las fuentes de variables OpenType, su compatibilidad con DirectWrite y Direct2D y cómo usarlas en la aplicación.
- ¿Qué son las fuentes de variables OpenType?
- Compatibilidad con fuentes de variables OpenType en DirectWrite
- Uso de fuentes de variables OpenType
¿Qué son las fuentes de variables OpenType?
La versión 1.8 de la especificación de formato de fuente OpenType introdujo una nueva extensión al formato conocido como Variaciones de fuente OpenType. Las fuentes que usan estas extensiones se conocen como fuentes de variable OpenType. Una fuente variable OpenType es una sola fuente que se puede comportar como varias fuentes mediante la interpolación continua entre diferentes diseños, todas definidas dentro de la única fuente.
Una fuente variable OpenType puede definir la variación continua de su diseño a lo largo de uno o varios ejes independientes, como el peso o el ancho:
Un desarrollador de fuentes determina un conjunto de ejes de variación que se van a usar en una fuente determinada. Estos ejes pueden incluir un conjunto de ejes conocidos (o "registrados") de variación, como el peso y el ancho, pero también pueden incluir ejes arbitrarios y personalizados de variación definidos por el desarrollador de fuentes.
Al seleccionar un conjunto de ejes de variación para una fuente, el desarrollador de fuentes define un espacio abstracto y n dimensional de variación de diseño para la fuente. Los motores de texto pueden especificar potencialmente cualquier posición, o "instancia", dentro de ese espacio continuo para diseñar y representar texto.
El desarrollador de fuentes también puede seleccionar y asignar nombres a instancias concretas dentro del espacio de variación de diseño; se conocen como "instancias con nombre". Por ejemplo, una fuente con variación de peso puede admitir la variación continua entre trazos muy ligeros y muy pesados, mientras que el desarrollador de fuentes ha seleccionado pesos concretos a lo largo de ese continuo y los nombres asignados a ellos, como "Light", "Regular" y "Semibold".
El formato de fuente de variable OpenType usa tablas de datos que se encuentran en fuentes OpenType tradicionales, además de determinadas tablas adicionales que describen cómo cambian los valores de varios elementos de datos para diferentes instancias. El formato designa una instancia de variación como una "instancia predeterminada", que usa tablas tradicionales para obtener valores predeterminados. Todas las demás instancias dependen de los datos predeterminados más otros datos delta. Por ejemplo, una tabla "glyf" puede tener una descripción de curva Bezier de una forma de glifo nominal, que es la forma utilizada para la instancia predeterminada, mientras que una tabla "gvar" describirá cómo se ajustan los puntos de control Bezier para el glifo para otras instancias. De forma similar, otros valores de fuente pueden tener un valor nominal más datos delta que describen cómo cambian esos valores para diferentes instancias; por ejemplo, x-height y otras métricas de ancho de fuente, o posiciones de delimitación de marcas específicas del glifo y ajustes de inter kerning.
Dado que las fuentes variables pueden admitir un conjunto arbitrario de ejes de variación, requieren un modelo extensible de familias de fuentes que reflejan más directamente cómo los diseñadores de fuentes crean familias de fuentes: una familia de fuentes se define mediante un nombre de familia y determinadas características de diseño que son constantes, con un número arbitrario (determinado por el desarrollador de fuentes) de formas en las que el diseño puede variar. Se puede crear una familia de fuentes con variantes para peso, pero se puede crear una familia de fuentes diferente con variantes para el alto x, serif-size, "funkiness" o lo que desee el desarrollador de fuentes. En este modelo, se describe mejor una selección de cara de fuente mediante el general, o "preferido" o "tipográfico", nombre de familia más un conjunto de pares clave-valor, cada uno que representa un tipo de variación y un valor específico, con los tipos de variación en general como un conjunto extensible. Esta noción general de una familia de fuentes se puede aplicar a fuentes tradicionales y no variables, así como a fuentes variables. Por ejemplo, bajo este modelo de familia tipográfica general, una familia "Selawik VF" podría tener variaciones para el peso, el tamaño óptico y el diseño serif, con instancias como "Semilight Banner Sans".
Sin embargo, algunas implementaciones de software existentes, incluidas las API de DirectWrite existentes, pueden diseñarse suponiendo un modelo más limitado de familias de fuentes. Por ejemplo, algunas aplicaciones pueden suponer que una familia de fuentes puede tener, como máximo, variantes normales, negritas, cursiva y cursiva en negrita. Las interfaces IDWriteFontCollection y IDWriteFontFamily existentes asumen un modelo de familia weight/stretch/style ("WSS"), lo que permite especificar variantes dentro de una familia mediante la DWRITE_FONT_WEIGHT, DWRITE_FONT_STRETCH o DWRITE_FONT_STYLE enumeraciones como parámetros. Tomando el ejemplo anterior, el tamaño óptico y los ejes serif no se tratarían como ejes internos de familia de variación en el modelo WSS.
La compatibilidad completa con fuentes variables requeriría API que permitan especificar un miembro de la familia con potencialmente varios parámetros, según lo determinado por la fuente. Sin embargo, los diseños de API existentes pueden proporcionar compatibilidad parcial con las fuentes variables mediante la proyección de las instancias con nombre definidas en una fuente variable en los modelos de familia de fuentes más limitados. En el ejemplo anterior, "Selawik VF Semilight Banner Sans" podría proyectarse en el modelo WSS como una familia "Selawik VF Banner Sans" con "Semilight" como variante de peso.
Para otro ejemplo, considere una familia de fuentes tipográficas como Sitka, con variantes de tamaño óptico y peso. Las variantes con nombre dentro de la familia incluyen Sitka Text Regular y Sitka Banner Bold (además de muchos otros). El nombre de familia tipográfico es "Sitka", mientras que los nombres de las caras de estas variantes en el modelo de familia tipográfica serían "Text Regular" y "Banner Bold". Los modelos de familia WSS y de cuatro miembros no permiten variantes de tamaño óptico dentro de una familia, por lo que las diferencias de tamaño óptico deben tratarse como distinción de nivel de familia. En la tabla siguiente se muestra cómo se trataría una selección de fuentes de la familia tipográfica Sitka en el modelo de familia WSS:
Modelo de familia tipográfica
Modelo de familia WSS
Familia
Caras
Familia
Caras
Sitka
Texto normal
Sitka Text
Normal
Sitka
Banner Bold
Sitka Banner
Bold
Sitka
Cursiva de título
Título de Sitka
Cursiva
La proyección de nombres de un modelo de familia tipográfica al modelo de familia WSS se puede aplicar a fuentes que no son variables y a las instancias con nombre de las fuentes de variables. Sin embargo, esto no se puede hacer para otras instancias sin nombre del espacio continuo de variación de diseño de una fuente variable. Por este motivo, la compatibilidad con la funcionalidad completa de las fuentes variables requerirá api diseñadas para hacer referencia a caras dentro de una familia tipográfica en términos de un conjunto sin restricciones de ejes de variación y valores de eje.
Compatibilidad con fuentes de variables OpenType en DirectWrite
A partir del lanzamiento de Windows 10 Creators Update, el formato de fuente de la variable OpenType sigue siendo muy nuevo, y los proveedores de fuentes, plataformas y aplicaciones siguen en proceso de implementar el nuevo formato. Esta actualización proporciona una implementación inicial para este formato en DirectWrite.
DirectWrite internos se han actualizado para admitir fuentes de variables OpenType. Con las API actuales, esto proporciona compatibilidad con las instancias con nombre de una fuente variable. Esta compatibilidad se puede usar para flujos de trabajo completos, desde la enumeración de las instancias con nombre, la selección de una instancia con nombre, el uso en el diseño y la forma, hasta la representación e impresión. Para beneficiarse de las aplicaciones que también usan la interoperabilidad de texto GDI para determinadas operaciones, también se ha agregado compatibilidad similar en las API de GDI existentes.
En Windows 10 Creators Update, DirectWrite no admite instancias arbitrarias que usan la funcionalidad de variación continua de fuentes variables.
En muchas operaciones, el comportamiento de DirectWrite de instancias con nombre de una fuente variable no se puede distinguir del comportamiento de las fuentes que no son variables. Además, dado que se proporciona compatibilidad con las API de DirectWrite existentes, las instancias con nombre de fuentes variables pueden incluso funcionar en muchas aplicaciones de DirectWrite existentes sin cambios. Sin embargo, se pueden aplicar excepciones en determinadas situaciones:
- Si una aplicación procesa los datos de fuente directamente para determinadas operaciones. Por ejemplo, si una aplicación lee datos de esquema de glifo directamente desde el archivo de fuente para crear determinados efectos visuales.
- Si una aplicación usa una biblioteca de terceros para determinadas operaciones. Por ejemplo, si una aplicación usa DirectWrite para el diseño, para obtener los índices y posiciones finales del glifo, pero después usa una biblioteca de terceros para la representación.
- Si una aplicación inserta datos de fuente en un documento o de alguna otra manera pasa los datos de fuente a un proceso de bajada.
Si las operaciones se realizan mediante implementaciones que no admiten fuentes variables, es posible que estas operaciones no generen los resultados esperados. Por ejemplo, las posiciones del glifo se pueden calcular para una instancia con nombre de la fuente variable, pero los glifos podrían representarse suponiendo una instancia con nombre diferente. En función de la implementación de la aplicación, los resultados pueden funcionar en algunos contextos, pero no en otros contextos en los que se pueden usar otras bibliotecas. Por ejemplo, el texto puede mostrarse correctamente en pantalla, pero no cuando se imprime. Si los flujos de trabajo de un extremo a otro se implementan usando solo DirectWrite, se puede esperar un comportamiento correcto para las instancias con nombre de una fuente variable.
Dado que las API de DirectWrite existentes admiten la selección de caras mediante el modelo de peso, ajuste y estilo, las instancias con nombre de las fuentes que usan otros ejes de variación se proyectarán desde el modelo de familia tipográfica general en el modelo WSS, como se ha descrito anteriormente. Esto se basa en una fuente variable que incluye una tabla de "atributos de estilo" ('STAT') con subtables de valor de eje, que DWrite usa para distinguir los tokens de nombre de cara que designan atributos de peso, stretch o style de los tokens que pertenecen a otros ejes de variación.
Si una fuente variable no incluye una tabla "STAT", según sea necesario para las fuentes de variable según la especificación OpenType, DirectWrite tratará la fuente como una fuente que no sea variable que contenga solo la instancia predeterminada.
Si una fuente contiene una tabla "STAT", pero no incluye subtables de valor de eje adecuadas, esto puede provocar resultados inesperados, como tener varias caras que tienen nombres de cara idénticos. Estas fuentes no se admiten en este momento.
La especificación OpenType permite representar los datos de esquema del glifo en uno de los dos formatos: mediante una tabla "glyf", que usa el esquema TrueType y el formato de sugerencia, o mediante una tabla "CFF", que usa la representación del formato de fuente compacta ("CFF"). En una fuente variable con esquemas TrueType, se sigue usando la tabla "glyf" y se complementa con una tabla "gvar" que proporciona los datos de variación para los esquemas. Esto significa que la instancia predeterminada de una fuente variable con esquemas TrueType solo usa tablas OpenType tradicionales que se admitirán en software anterior que no tenga compatibilidad con fuentes variables. Sin embargo, en una fuente variable con esquemas de CFF, la tabla "CFF" se sustituye por la tabla "CFF2", que encapsula los datos de esquema predeterminados y los datos de variación asociados en una tabla. Los datos de CFF se procesan mediante un rasterizador independiente de que se usa para los datos TrueType y una tabla "CFF2" requiere un rasterizador CFF actualizado que tenga compatibilidad con "CFF2". Los rasterizadores CFF anteriores no pueden procesar una tabla "CFF2". Para una fuente variable con datos de esquema de CFF, esto significa que incluso la instancia predeterminada no funcionará en software anterior.
En Windows 10 Creators Update, DirectWrite no admite fuentes variables con datos de esquema de CFF mediante la tabla "CFF2".
Uso de fuentes de variables OpenType
Las fuentes de variables OpenType pueden ser fáciles de usar, teniendo en cuenta las limitaciones actuales indicadas anteriormente:
- En este momento solo se admiten instancias con nombre de una fuente variable.
- En este momento solo se admiten fuentes variables que usan datos de esquema de glifo TrueType (no esquemas CFF).
- En el caso de las fuentes que usan ejes de variación de diseño que no sean weight, stretch o style, las instancias con nombre se proyectarán en el modelo de familia WSS, lo que puede dar lugar a que algunas instancias con nombre aparezcan como familias independientes (como sucede en el pasado para las fuentes que no son variables). Para admitir esto, las fuentes de variable deben tener una tabla "STAT" que incluya subtables de valores de eje adecuadas.
- Las instancias con nombre de fuentes de variable se admiten en DirectWrite API, pero si ciertas operaciones se realizan en implementaciones anteriores que no admiten fuentes variables, pueden producir resultados incorrectos.
- Algunas API de DirectWrite usan las enumeraciones de DWRITE_FONT_WEIGHT, DWRITE_FONT_STRETCH y DWRITE_FONT_STYLE para especificar atributos de peso, ajuste y estilo al seleccionar caras. Si una fuente de variable usa los ejes de variación correspondientes, pero tiene muchas instancias con nombre que requieren una granularidad más fina, no todas las instancias con nombre se podrán seleccionar en esas API.
Las fuentes de variables OpenType que cumplan estos requisitos se pueden instalar desde el shell de Windows al igual que otras fuentes OpenType y también se pueden usar en conjuntos de fuentes personalizados creados por una aplicación.
Cuando se instala en el sistema, todas las instancias con nombre de una fuente de variable se incluirán en el conjunto de fuentes devuelto llamando al método IDWriteFontFamily3::GetSystemFontSet . Tenga en cuenta que un conjunto de fuentes es una lista plana sin una jerarquía de agrupación de familias, pero cada elemento del conjunto tiene una propiedad de nombre de familia basada en el modelo de familia WSS. El conjunto de fuentes se puede filtrar para una instancia con nombre de variable determinada mediante los métodos IDWriteFontSet::GetMatchingFonts . Sin embargo, si usa la sobrecarga GetMatchingFonts que toma un familyName, el nombre de familia especificado debe usar el nombre conforme al modelo de familia de fuentes WSS. La lista completa de nombres de familia compatibles con WSS que se producen en un conjunto de fuentes se puede obtener mediante los métodos IDWriteFontSet::GetPropertyValues mediante DWRITE_FONT_PROPERTY_ID_FAMILY_NAME.
Del mismo modo, todas las instancias con nombre de una fuente de variable se representarán en la colección de fuentes devuelta por el método IDWriteFactory::GetSystemFontCollection . Dado que los elementos de una colección de fuentes son familias de fuentes basadas en el modelo WSS, las instancias con nombre de una fuente de variable se pueden representar en una colección como miembros de dos o más familias de fuentes. Si se usa el método IDWriteFontCollection::FindFamilyName , el parámetro familyName debe ser un nombre de familia compatible con WSS. Para buscar todos los nombres de familia compatibles con WSS de una colección de fuentes, una aplicación puede recorrer en bucle cada familia y llamar a IDWriteFontFamily::GetFamilyNames, aunque puede ser más fácil obtener un conjunto de fuentes correspondiente y usar el método GetPropertyValues como se ha descrito anteriormente.
Al trabajar con fuentes personalizadas, se pueden usar varios enfoques descritos en el tema Conjuntos de fuentes personalizados para crear un conjunto de fuentes. Para agregar una fuente de variable a un conjunto de fuentes personalizado, se recomienda el método IDWriteFontSetBuilder1::AddFontFile , ya que admite fuentes de variables y agregará todas las instancias con nombre de una fuente de variable en una sola llamada. En este momento no hay ninguna manera de agregar instancias con nombre individuales de una fuente de variable personalizada a un conjunto de fuentes mediante los métodos IDWriteFontSetBuilder::AddFontFaceReference , ya que no hay ninguna manera de crear una referencia facial de fuente que especifique cuál de las instancias con nombre de un archivo de fuente de variable está pensada. Esto significa que actualmente no hay ninguna manera de agregar instancias con nombre de una fuente personalizada a un conjunto de fuentes personalizado con propiedades personalizadas asignadas. Esto, a su vez, significa que las fuentes de variables personalizadas actualmente no se pueden usar fácilmente junto con DirectWrite API para fuentes remotas. Si las instancias con nombre de una fuente de variable se incluyen en un conjunto de fuentes del sistema, sin embargo, las referencias a caras de fuente para cada instancia con nombre ya existirán y se pueden agregar a conjuntos de fuentes personalizados, incluido el uso de valores de propiedad personalizados. Consulte el tema Conjuntos de fuentes personalizados para obtener más detalles.
Al trabajar con fuentes de variables, las DirectWrite DWRITE_FONT_WEIGHT y las enumeraciones de DWRITE_FONT_STRETCH están estrechamente conectadas a los ejes de variación de grosor y ancho definidos en la especificación OpenType, pero no son los mismos. En primer lugar, la escala numérica de cualquier eje de variación siempre admite valores fraccionarios, mientras que fontWeight y fontStretch usan enteros. La escala del eje de peso OpenType usa valores comprendidos entre 1 y 1000, que también es compatible con fontWeight. Por lo tanto, el cambio de un valor de eje de peso de variación a fontWeight es relativamente menor: el fontWeight notificado para una instancia con nombre se puede redondear desde el valor preciso utilizado para definir la instancia con nombre dentro de la fuente. La distinción entre DirectWrite fontStretch y la escala del eje de ancho OpenType es mayor: DirectWrite usa valores de 1 a 9, siguiendo los valores usWidthClass de la tabla OpenType OS/2, mientras que la escala del eje de ancho OpenType usa valores positivos que representan un porcentaje de ancho normal. La documentación usWidthClass de la especificación OpenType proporciona una asignación entre los valores del 1 al 9 y el porcentaje de valores normales. El valor fontStretch notificado para una instancia con nombre puede implicar redondeo al convertir a partir de valores de eje de ancho.
Al crear un IDWriteTextFormat, se deben especificar una colección de fuentes y propiedades de fuente compatibles con WSS (nombre de familia, peso, stretch y estilo). Esto también se aplica al establecer propiedades de formato de fuente en un intervalo de texto IDWriteTextLayout . Las propiedades se pueden obtener de un objeto IDWriteFontFace3 o de objetos IDWriteFont e IDWriteFontFamily que representan una instancia con nombre determinada. Como se ha observado anteriormente, los valores devueltos por los métodos GetWeight y GetStretch pueden redondear aproximaciones para los valores del eje reales utilizados para definir la instancia con nombre, pero DirectWrite asignará la combinación de propiedades a la instancia con nombre deseada.
De forma similar, si una aplicación usa IDWriteFontFallbackBuilder para crear datos de reserva de fuentes personalizados, las familias se especifican para las asignaciones de intervalo de caracteres mediante nombres de familia compatibles con WSS. La reserva de fuentes dentro de DirectWrite se basa en familias con DirectWrite seleccionar una variante dentro de una familia de reserva que sea una coincidencia más cercana para la variante de la familia inicial. En el caso de las variantes que implican dimensiones distintas del peso, el ajuste y el estilo, DirectWrite actualmente no sería capaz de seleccionar estas variantes dentro de una familia de reserva a menos que se crearan datos de reserva personalizados específicamente para proporcionar asignaciones de reserva para familias que tienen atributos no WSS concretos, como variantes de tamaño óptico "Caption".