Partager via


Polices de variable OpenType

Cette rubrique décrit les polices variables OpenType, leur prise en charge dans DirectWrite et Direct2D, et la façon de les utiliser dans votre application. 

Que sont les polices variables OpenType ?

La version 1.8 de la spécification du format de police OpenType a introduit une nouvelle extension au format appelé OpenType Font Variations. Les polices qui utilisent ces extensions sont appelées polices de variables OpenType. Une police de variable OpenType est une police unique qui peut se comporter comme plusieurs polices en utilisant l’interpolation continue entre différentes conceptions, toutes définies dans la police unique.

Une police variable OpenType peut définir une variation continue de sa conception le long d’un ou plusieurs axes indépendants, tels que le poids ou la largeur :

 

Affiche une police variable OpenType utilisant la lettre « G » et montrant différentes variantes le long d’un axe de largeur horizontal et d’un axe de poids vertical.

Un développeur de polices détermine un ensemble d’axes de variation à utiliser dans une police donnée. Ces axes peuvent inclure un ensemble d’axes de variation connus (ou « inscrits »), tels que le poids et la largeur, mais ils peuvent également inclure des axes de variation arbitraires et personnalisés définis par le développeur de polices.  

En sélectionnant un ensemble d’axes de variation pour une police, le développeur de polices définit un espace abstrait à n dimensions de la variation de conception pour la police. Les moteurs de texte peuvent spécifier n’importe quelle position, ou « instance », dans cet espace continu pour la disposition et le rendu du texte. 

Le développeur de polices peut également sélectionner et attribuer des noms à des instances particulières dans l’espace de variantes de conception ; ces instances sont appelées « instances nommées ». Par exemple, une police avec une variation de poids peut prendre en charge la variation continue entre les traits très légers et très lourds, tandis que le développeur de polices a sélectionné des pondérations particulières le long de ce continuum et leur a attribué des noms, tels que « Light », « Regular » et « Semibold ». 

Le format de police variable OpenType utilise des tables de données trouvées dans les polices OpenType traditionnelles, ainsi que certaines tables supplémentaires qui décrivent la façon dont les valeurs des différents éléments de données changent pour différentes instances. Le format désigne une variante instance en tant que « instance par défaut », qui utilise des tables traditionnelles pour obtenir les valeurs par défaut. Toutes les autres instances dépendent des données par défaut et d’autres données delta. Par exemple, une table « glyf » peut avoir une description de courbe de Bézier d’une forme de glyphe nominal, qui est la forme utilisée pour la instance par défaut, tandis qu’une table « gvar » décrit comment les points de contrôle de Bézier pour le glyphe sont ajustés pour d’autres instances. De même, d’autres valeurs de police peuvent avoir une valeur nominale plus des données delta décrivant comment ces valeurs changent pour différentes instances ; par exemple, la hauteur x et d’autres métriques à l’échelle de la police, ou les positions d’ancrage de marque spécifiques au glyphe et les ajustements de crénage. 

Étant donné que les polices variables peuvent prendre en charge un ensemble arbitraire d’axes de variation, elles nécessitent un modèle extensible de familles de polices qui reflète plus directement la façon dont les concepteurs de polices créent des familles de polices : une famille de polices est définie par un nom de famille et certaines caractéristiques de conception constantes, avec un nombre arbitraire (déterminé par le développeur de polices) des façons dont la conception peut varier. Une famille de polices peut être créée avec des variantes pour le poids, mais une autre famille de polices peut être créée avec des variantes pour x-height, serif-size, « funkiness » ou tout ce que le développeur de polices souhaite. Dans ce modèle, une sélection de visage de police est mieux décrite à l’aide du nom de famille général ou « préféré » ou « typographique », ainsi que d’un ensemble de paires clé-valeur, chacune représentant un type de variation et une valeur spécifique, les types de variation étant généralement un ensemble extensible. Cette notion générale d’une famille de polices peut s’appliquer aux polices traditionnelles non variables ainsi qu’aux polices variables. Par exemple, dans ce modèle de famille typographique général, une famille « Selawik VF » peut avoir des variantes pour le poids, la taille optique et la conception du serif, avec des instances telles que « Semilight Banner Sans ». 

Toutefois, certaines implémentations logicielles existantes, y compris les API DirectWrite existantes, peuvent être conçues en supposant un modèle plus limité de familles de polices. Par exemple, certaines applications peuvent supposer qu’une famille de polices peut avoir, au maximum, des variantes régulières, en gras, en italique et en gras italique. Les interfaces IDWriteFontCollection et IDWriteFontFamily existantes supposent un modèle de famille de poids/étirement/style (« WSS »), ce qui permet de spécifier des variantes au sein d’une famille à l’aide des énumérations DWRITE_FONT_WEIGHT, DWRITE_FONT_STRETCH ou DWRITE_FONT_STYLE en tant que paramètres. Dans l’exemple précédent, les axes de taille optique et de empattement ne seraient pas traités comme des axes de variation internes à la famille dans le modèle WSS. 

La prise en charge complète des polices variables nécessite des API qui permettent à un membre de la famille d’être spécifié avec potentiellement plusieurs paramètres, tels que déterminés par la police. Toutefois, les conceptions d’API existantes peuvent fournir une prise en charge partielle des polices variables en projetant les instances nommées définies dans une police de variable dans les modèles de famille de polices plus limités. Dans l’exemple précédent, « Selawik VF Semilight Banner Sans » pouvait être projeté dans le modèle WSS en tant que famille « Selawik VF Banner Sans » avec « Semilight » comme variante de poids. 

Pour un autre exemple, considérez une famille de polices typographiques comme Sitka, avec des variantes de poids et de taille optique. Les variantes nommées au sein de la famille incluent Sitka Text Regular et Sitka Banner Bold (plus beaucoup d’autres). Le nom de famille typographique est « Sitka », tandis que les noms de visage de ces variantes dans le modèle de famille typographique seraient « Text Regular » et « Banner Bold ». Les modèles de la famille à quatre membres et de la famille WSS n’autorisent pas les variantes de taille optique au sein d’une famille, de sorte que les distinctions de taille optique doivent être traitées comme des distinctions au niveau de la famille. Le tableau suivant montre comment une sélection de polices de la famille typographique Sitka serait traitée dans le modèle de la famille WSS :

Modèle de famille typographique

Modèle de famille WSS

Famille

Face

Famille

Face

Sitka

Texte régulier

Texte sitka

Normal

Sitka

Bannière en gras

Bannière Sitka

Gras

Sitka

Légende italique

Sitka Caption

Italique

 

La projection des noms d’un modèle de famille typographique vers le modèle de famille WSS peut être appliquée aux polices non variables et aux instances nommées de polices variables. Toutefois, cela ne peut pas être effectué pour d’autres instances non nommées de l’espace de variation de conception continue d’une police variable. Pour cette raison, la prise en charge de la fonctionnalité complète des polices variables nécessite des API conçues pour référencer des visages au sein d’une famille typographique en termes d’ensemble sans contrainte d’axes de variation et de valeurs d’axe. 

Prise en charge des polices de variables OpenType dans DirectWrite

Depuis la publication de la Windows 10 Creators Update, le format de police variable OpenType est encore très nouveau, et les fournisseurs de polices, plateformes et applications sont toujours en train d’implémenter le nouveau format. Cette mise à jour fournit l’implémentation initiale de ce format dans DirectWrite. 

DirectWrite internes ont été mis à jour pour prendre en charge les polices de variables OpenType. À l’aide des API actuelles, cela permet de prendre en charge toutes les instances nommées d’une police variable. Cette prise en charge peut être utilisée pour des flux de travail complets, depuis l’énumération des instances nommées, la sélection d’un instance nommé, l’utilisation dans la mise en page et la mise en forme, jusqu’au rendu et à l’impression. Pour les applications qui utilisent également l’interopérabilité de texte GDI pour certaines opérations, une prise en charge similaire a également été ajoutée dans les API GDI existantes. 

Dans le Windows 10 Creators Update, DirectWrite ne prend pas en charge les instances arbitraires qui utilisent la fonctionnalité de variation continue des polices variables.

Dans de nombreuses opérations, le comportement dans DirectWrite d’instances nommées d’une police variable ne peut pas être distingué du comportement des polices non variables. Et étant donné que la prise en charge est fournie à l’aide des API DirectWrite existantes, les instances nommées de polices variables peuvent même fonctionner dans de nombreuses applications DirectWrite existantes sans aucune modification. Des exceptions peuvent toutefois s’appliquer dans certaines situations :

  • Si une application traite les données de police directement pour certaines opérations. Par exemple, si une application lit des données de plan de glyphe directement à partir du fichier de polices pour créer certains effets visuels.
  • Si une application utilise une bibliothèque tierce pour certaines opérations. Par exemple, si une application utilise DirectWrite pour la disposition, pour obtenir des index et des positions de glyphe finaux, mais utilise ensuite une bibliothèque tierce pour le rendu.
  • Si une application incorpore des données de police dans un document ou, d’une autre manière, transmet les données de police à un processus en aval.

Si les opérations sont effectuées à l’aide d’implémentations qui ne prennent pas en charge les polices variables, ces opérations peuvent ne pas produire les résultats attendus. Par exemple, les positions de glyphe peuvent être calculées pour une instance nommée de la police variable, mais les glyphes peuvent être rendus en supposant qu’un autre nom instance. Selon l’implémentation de l’application, les résultats peuvent fonctionner dans certains contextes, mais pas dans d’autres contextes dans lesquels d’autres bibliothèques peuvent être utilisées. Par exemple, le texte peut s’afficher correctement à l’écran, mais pas lorsqu’il est imprimé. Si les flux de travail de bout en bout sont implémentés à l’aide de DirectWrite uniquement, un comportement correct pour les instances nommées d’une police variable peut être attendu. 

Étant donné que les API DirectWrite existantes prennent en charge la sélection des visages à l’aide du modèle poids/étirement/style, les instances nommées des polices qui utilisent d’autres axes de variation sont projetées à partir du modèle de famille typographique général dans le modèle WSS, comme décrit ci-dessus. Cela s’appuie sur une police variable comprenant une table « attributs de style » (« STAT ») avec des sous-tables axe-valeur, que DWrite utilise pour distinguer les jetons de nom de visage qui désignent des attributs de poids, d’étirement ou de style des jetons qui se rapportent à d’autres axes de variation.  

Si une police de variable n’inclut pas de table « STAT », comme requis pour les polices variables par la spécification OpenType, DirectWrite traitera la police comme une police non variable contenant uniquement la instance par défaut.  

Si une police contient une table « STAT » mais qu’elle n’inclut pas les sous-tableaux axe-valeur appropriés, cela peut entraîner des résultats inattendus, tels que plusieurs visages ayant des noms de visage identiques. Ces polices ne sont pas prises en charge pour le moment. 

La spécification OpenType permet aux données de plan de glyphe d’être représentées dans l’un des deux formats suivants : à l’aide d’une table « glyf », qui utilise le format de contour et d’indication TrueType, ou à l’aide d’une table « CFF », qui utilise une représentation au format de police compact (« CFF »). Dans une police variable avec des contours TrueType, la table « glyf » continue d’être utilisée et est complétée par une table « gvar » qui fournit les données de variation pour les contours. Cela signifie que la instance par défaut d’une police de variable avec des contours TrueType utilise uniquement les tables OpenType traditionnelles qui seront prises en charge dans les logiciels plus anciens qui n’ont pas de prise en charge de police variable. Dans une police variable avec des contours CFF, toutefois, la table « CFF » est remplacée par la table « CFF2 », qui encapsule les données de plan par défaut et les données de variation associées dans une table. Les données CFF sont traitées par un rastériseur distinct de celui utilisé pour les données TrueType, et une table « CFF2 » nécessite un rastériseur CFF mis à jour qui prend en charge « CFF2 ». Une table « CFF2 » ne peut pas être traitée par des rastériseurs CFF plus anciens. Pour une police variable avec des données de plan CFF, cela signifie que même la instance par défaut ne fonctionnera pas dans les logiciels plus anciens. 

Dans le Windows 10 Creators Update, DirectWrite ne prend pas en charge les polices variables avec des données de plan CFF à l’aide de la table « CFF2 ». 

Utilisation de polices de variables OpenType

Les polices variables OpenType peuvent être faciles à utiliser, en gardant à l’esprit les limitations actuelles notées ci-dessus :

  • Seules les instances nommées d’une police de variable sont prises en charge pour l’instant.
  • Seules les polices variables qui utilisent des données de plan de glyphe TrueType (et non des contours CFF) sont prises en charge pour l’instant. 
  • Pour les polices qui utilisent des axes de variation de conception autres que le poids, l’étirement ou le style, les instances nommées sont projetées dans le modèle de la famille WSS, ce qui peut entraîner l’apparition de certaines instances nommées sous forme de familles distinctes (comme c’était le cas dans le passé pour les polices non variables). Pour prendre en charge cela, les polices de variables doivent avoir une table « STAT » qui inclut les sous-tableaux axe-valeur appropriés.
  • Les instances nommées de polices variables sont prises en charge dans DirectWrite API, mais si certaines opérations sont effectuées dans des implémentations plus anciennes qui ne prennent pas en charge les polices variables, celles-ci peuvent produire des résultats incorrects. 
  • Certaines API DirectWrite utilisent les énumérations DWRITE_FONT_WEIGHT, DWRITE_FONT_STRETCH et DWRITE_FONT_STYLE pour spécifier des attributs de poids, d’étirement et de style lors de la sélection de visages. Si une police de variable utilise des axes de variation correspondants, mais a de nombreuses instances nommées qui nécessitent une granularité plus fine, toutes les instances nommées ne sont pas sélectionnables dans ces API.

Les polices variables OpenType conformes à ces exigences peuvent être installées à partir de l’interpréteur de commandes Windows comme d’autres polices OpenType, et peuvent également être utilisées dans des jeux de polices personnalisés créés par une application.  

Une fois installées dans le système, toutes les instances nommées d’une police variable sont incluses dans le jeu de polices retourné en appelant la méthode IDWriteFontFamily3::GetSystemFontSet . Notez qu’un jeu de polices est une liste plate sans hiérarchie de regroupement de familles, mais que chaque élément du jeu a une propriété de nom de famille basée sur le modèle de famille WSS. Le jeu de polices peut être filtré pour une variable-police particulière nommée instance à l’aide des méthodes IDWriteFontSet::GetMatchingFonts. Si vous utilisez la surcharge GetMatchingFonts qui prend un familyName, cependant, le familyName spécifié doit utiliser le nom conforme au modèle de famille de police WSS. La liste complète des noms de famille compatibles WSS qui se produisent dans un jeu de polices peut être obtenue à l’aide des méthodes IDWriteFontSet::GetPropertyValues à l’aide de DWRITE_FONT_PROPERTY_ID_FAMILY_NAME.  

De même, toutes les instances nommées d’une police variable seront représentées dans la collection de polices retournée par la méthode IDWriteFactory::GetSystemFontCollection . Étant donné que les éléments d’une collection de polices sont des familles de polices basées sur le modèle WSS, les instances nommées d’une police variable peuvent être représentées dans une collection en tant que membres de deux familles de polices ou plus. Si la méthode IDWriteFontCollection::FindFamilyName est utilisée, le paramètre familyName doit être un nom de famille compatible WSS. Pour rechercher tous les noms de famille compatibles avec WSS à partir d’une collection de polices, une application peut parcourir chaque famille et appeler IDWriteFontFamily::GetFamilyNames, bien qu’il soit plus facile d’obtenir un jeu de polices correspondant et d’utiliser la méthode GetPropertyValues comme décrit ci-dessus. 

Lorsque vous travaillez avec des polices personnalisées, différentes approches décrites dans la rubrique Jeux de polices personnalisés peuvent être utilisées pour créer un jeu de polices. Pour ajouter une police variable à un jeu de polices personnalisé, la méthode IDWriteFontSetBuilder1::AddFontFile est recommandée, car elle prend en charge les polices variables et ajoute toutes les instances nommées d’une police de variable dans un seul appel. Pour le moment, il n’existe aucun moyen d’ajouter des instances nommées individuelles d’une police de variable personnalisée à un jeu de polices à l’aide des méthodes IDWriteFontSetBuilder::AddFontFaceReference , car il n’existe aucun moyen de créer une référence de visage de police spécifiant laquelle des instances nommées d’un fichier de police variable est destinée. Cela signifie qu’il n’existe actuellement aucun moyen d’ajouter des instances nommées d’une police personnalisée à un jeu de polices personnalisé avec des propriétés personnalisées affectées. Cela signifie que les polices de variables personnalisées ne peuvent actuellement pas être facilement utilisées conjointement avec DirectWrite API pour les polices distantes. Si des instances nommées d’une police variable sont incluses dans un jeu de polices système, toutefois, des références de police faciale pour chaque instance nommées existent déjà, et celles-ci peuvent être ajoutées à des jeux de polices personnalisés, notamment à l’aide de valeurs de propriété personnalisées. Pour plus d’informations, consultez la rubrique Jeux de polices personnalisés. 

Lors de l’utilisation de polices variables, les énumérations DirectWrite DWRITE_FONT_WEIGHT et DWRITE_FONT_STRETCH sont étroitement liées aux axes de variation de poids et de largeur définis dans la spécification OpenType, mais ne sont pas identiques. Tout d’abord, l’échelle numérique pour n’importe quel axe de variation prend toujours en charge les valeurs fractionnaires, tandis que fontWeight et fontStretch utilisent des entiers. L’échelle de l’axe de pondération OpenType utilise des valeurs comprises entre 1 et 1000, ce qui est également pris en charge par fontWeight. Par conséquent, le changement d’une valeur d’axe de pondération de variation en fontWeight est relativement mineur : la valeur fontWeight signalée pour un instance nommé peut être arrondie à partir de la valeur exacte utilisée pour définir le instance nommé dans la police. La distinction entre DirectWrite fontStretch et l’échelle de l’axe de largeur OpenType est plus grande : DirectWrite utilise des valeurs comprises entre 1 et 9, en suivant les valeurs usWidthClass de la table OpenType OS/2, tandis que l’échelle de l’axe de largeur OpenType utilise des valeurs positives représentant un pourcentage de largeur normale. La documentation usWidthClass de la spécification OpenType fournit un mappage entre les valeurs 1 et 9 et le pourcentage de valeurs normales. La valeur fontStretch signalée pour un instance nommé peut impliquer un arrondi lors de la conversion à partir de valeurs d’axe de largeur. 

Lors de la création d’un IDWriteTextFormat, une collection de polices et des propriétés de police compatibles avec WSS (nom de famille, poids, étirement et style) doivent être spécifiées. Cela s’applique également lors de la définition des propriétés de mise en forme de police sur une plage de texte IDWriteTextLayout . Les propriétés peuvent être obtenues à partir d’un objet IDWriteFontFace3 ou d’objets IDWriteFont et IDWriteFontFamily qui représentent un instance nommé particulier. Comme indiqué ci-dessus, les valeurs retournées par les méthodes GetWeight et GetStretch peuvent être des approximations arrondies pour les valeurs d’axe réelles utilisées pour définir le instance nommé, mais DirectWrite mappera la combinaison de propriétés au instance nommé souhaité. 

De même, si une application utilise IDWriteFontFallbackBuilder pour créer des données de secours de police personnalisées, les familles sont spécifiées pour les mappages de plages de caractères à l’aide de noms de famille compatibles avec WSS. La police de secours dans DirectWrite est basée sur les familles avec DirectWrite la sélection d’une variante au sein d’une famille de secours qui correspond le plus près à la variante de la famille de départ. Pour les variantes qui impliquent des dimensions autres que le poids, l’étirement et le style, DirectWrite ne serait actuellement pas en mesure de sélectionner de telles variantes au sein d’une famille de secours, sauf si des données de secours personnalisées ont été créées spécifiquement pour fournir des mappages de secours pour les familles qui ont des attributs particuliers non-WSS, tels que des variantes de taille optique « Caption ».