Polices de variables OpenType
Cette rubrique décrit les polices de variables OpenType, leur prise en charge dans DirectWrite et Direct2D et leur utilisation dans votre application.
- Qu’est-ce que les polices de variables OpenType ?
- prise en charge des polices de variables OpenType dans DirectWrite
- Utilisation des polices de variables OpenType
Qu’est-ce que les polices de variables OpenType ?
Version 1.8 de la spécification format de police OpenType introduit une nouvelle extension au format appelé Variantes de police OpenType. 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 à l’aide de l’interpolation continue entre différentes conceptions, toutes définies dans la police unique.
Une police de variable OpenType peut définir une variation continue de sa conception le long d’un ou plusieurs axes indépendants, tels que l’épaisseur ou la largeur :
Un développeur de polices détermine un ensemble d’axes de variante à utiliser dans une police donnée. Ces axes peuvent inclure un ensemble d’axes connus (ou « inscrits ») de variantes, tels que l’épaisseur et la largeur, mais ils peuvent également inclure des axes arbitraires et personnalisés de variantes définis par le développeur de polices.
En sélectionnant un ensemble d’axes de variante pour une police, le développeur de polices définit un espace abstrait et ndimensionnel de variante de conception pour la police. Les moteurs de texte peuvent spécifier potentiellement 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 affecter des noms à des instances particulières dans l’espace de variante de conception ; elles sont appelées « instances nommées ». Par exemple, une police avec variation de poids peut prendre en charge une variation continue entre des traits très légers et très lourds, tandis que le développeur de polices a sélectionné des poids particuliers le long de ce continuum et des noms attribués à eux, tels que « Light », « Normal » et « Semibold ».
Le format de police variable OpenType utilise des tables de données trouvées dans des polices OpenType traditionnelles, ainsi que certaines tables supplémentaires qui décrivent comment les valeurs des différents éléments de données changent pour différentes instances. Le format désigne une instance de variante comme une « instance par défaut », qui utilise des tables traditionnelles pour obtenir des 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 Bezier d’une forme de glyphe nominale, qui est la forme utilisée pour l’instance par défaut, tandis qu’une table « gvar » décrit comment les points de contrôle bezier 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, x-height et d’autres métriques à l’échelle de la police, ou des positions d’ancrage de marque spécifiques au glyphe et des ajustements de crénage.
Étant donné que les polices variables peuvent prendre en charge un ensemble arbitraire d’axes de variantes, elles nécessitent un modèle extensible de familles de polices qui reflètent 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 police souhaite. Dans ce modèle, une sélection de visages de police est la meilleure description à l’aide du nom général ou « typographique » ou « typographique », ainsi que d’un ensemble de paires clé-valeur, chacune représentant un type de variation et une valeur spécifique, avec les types de variantes en général étant un ensemble extensible. Cette notion générale d’une famille de polices peut s’appliquer aux polices traditionnelles et non variables ainsi qu’aux polices de variables. Par exemple, sous ce modèle général de famille typographique, une famille « Selawik VF » peut avoir des variations pour le poids, la taille optique et la conception 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 plus, des variantes italiques standard, gras, italique et italique gras. Les interfaces IDWriteFontCollection et IDWriteFontFamily supposent un modèle de famille de poids/stretch/style (« WSS »), ce qui permet aux variantes d’une famille d’être spécifiées à l’aide de la DWRITE_FONT_WEIGHT, DWRITE_FONT_STRETCH ou DWRITE_FONT_STYLE énumérations en tant que paramètres. En prenant l’exemple précédent, la taille optique et les axes serif ne seraient pas traités comme des axes internes de famille de variation 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, comme déterminé par la police. Toutefois, les conceptions d’API existantes peuvent fournir une prise en charge partielle des polices de variables en projetant les instances nommées définies dans une police variable dans les modèles de famille de polices plus limités. Dans l’exemple précédent, « Selawik VF Semilight Banner Sans » peut être projeté dans le modèle WSS comme une 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 taille optique et de poids. Les variantes nommées de la famille incluent Sitka Text Regular et Sitka Banner Bold (plus beaucoup d’autres). Le nom de la famille typographique est « Sitka », tandis que les noms de visages de ces variantes dans le modèle de famille typographique seraient « Text Regular » et « Banner Bold ». Les modèles de famille À quatre membres et WSS ne permettent pas de variantes de taille optique au sein d’une famille, et les distinctions de taille optique doivent donc ê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 famille WSS :
Modèle de famille typographique
Modèle de famille WSS
Famille
Visage
Famille
Visage
Sitka
Texte normal
Texte Sitka
Régulier
Sitka
Bannière gras
Bannière Sitka
Audacieux
Sitka
Légende italique
Légende Sitka
Italique
La projection de noms d’un modèle de famille typographique au modèle de famille WSS peut être appliquée à des polices non variables et aux instances nommées de polices variables. Cela ne peut pas être fait, toutefois, pour d’autres instances non nommées à partir de l’espace de variante de conception continu d’une police variable. Pour cette raison, la prise en charge de la fonctionnalité complète des polices de variables nécessite des API conçues pour référencer des visages au sein d’une famille typographique en termes d’un ensemble sans contrainte d’axes de variation et de valeurs d’axe.
Prise en charge de la police des variables OpenType dans DirectWrite
À compter de la publication de Windows 10 Creators Update, le format de police variable OpenType est toujours très nouveau, et les fournisseurs de polices, plateformes et applications sont toujours en cours d’implémentation du nouveau format. Cette mise à jour fournit une implémentation initiale pour ce format dans DirectWrite.
Les éléments internes DirectWrite ont été mis à jour pour prendre en charge les polices de variables OpenType. À l’aide des API actuelles, cela prend en charge toutes les instances nommées d’une police variable. Cette prise en charge peut être utilisée pour les flux de travail complets , de l’énumération des instances nommées, de la sélection d’une instance nommée, de l’utilisation dans la disposition et la mise en forme, au rendu et à l’impression. Pour bénéficier des 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 Windows 10 Creators Update, DirectWrite ne prend pas en charge les instances arbitraires qui utilisent la fonctionnalité de variation continue des polices de variables.
Dans de nombreuses opérations, le comportement dans DirectWrite des 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 d’API DirectWrite existantes, les instances nommées de polices variables peuvent même fonctionner dans de nombreuses applications DirectWrite existantes sans aucune modification. Toutefois, les exceptions peuvent 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 police 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 les index et positions de glyphe finals, 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 façon transmet les données de police à un processus en aval.
Si des opérations sont effectuées à l’aide d’implémentations qui ne prennent pas en charge les polices de 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 de variable, mais les glyphes peuvent être rendus en supposant qu’une instance nommée différente. 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 lors de l’impression. Si les flux de travail de bout en bout sont implémentés uniquement à l’aide de DirectWrite, le comportement correct pour les instances nommées d’une police de 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/stretch/style, les instances nommées de polices qui utilisent d’autres axes de variante seront 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, y compris une table « attributs de style » ('STAT') avec des sous-tables de valeur d’axe, 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 nécessaire pour les polices de variables par la spécification OpenType, DirectWrite traite la police comme une police non variable contenant uniquement l’instance par défaut.
Si une police contient une table « STAT », mais qu’elle n’inclut pas les sous-tables de valeur d’axe appropriées, cela peut entraîner des résultats inattendus, tels que la présence de plusieurs visages ayant des noms de visage identiques. Ces polices ne sont pas prises en charge pour l’instant.
La spécification OpenType permet de représenter les données de plan de glyphe dans l’un des deux formats suivants : à l’aide d’une table « glyf », qui utilise le format de contour et d’indicateur TrueType, ou à l’aide d’une table « CFF », qui utilise la représentation Compact Font Format (« CFF »). Dans une police de 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 variante pour les contours. Cela signifie que l’instance par défaut d’une police de variable avec les contours TrueType utilise uniquement les tables OpenType traditionnelles qui seront prises en charge dans les logiciels plus anciens qui n’ont aucune prise en charge de police variable. Dans une police de variable avec des contours CFF, toutefois, la table « CFF » est remplacée par la table « CFF2 », qui encapsule les données hiérarchiques par défaut et les données de variante 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 a la prise en charge de « CFF2 ». Une table « CFF2 » ne peut pas être traitée par des ratériseurs CFF plus anciens. Pour une police de variable avec des données hiérarchiques CFF, cela signifie que même l’instance par défaut ne fonctionnera pas dans les logiciels plus anciens.
Dans Windows 10 Creators Update, DirectWrite ne prend pas en charge les polices variables avec les données hiérarchiques CFF à l’aide de la table « CFF2 ».
Utilisation de polices de variables OpenType
Les polices de variables OpenType peuvent être faciles à utiliser, en gardant à l’esprit les limitations actuelles indiqué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 les données de plan de glyphe TrueType (et non les contours CFF) sont prises en charge pour l’instant.
- Pour les polices qui utilisent des axes de variante de conception autres que le poids, l’étirement ou le style, les instances nommées seront projetées dans le modèle de famille WSS, ce qui peut entraîner l’apparition de certaines instances nommées sous forme de familles distinctes (comme cela se produirait dans le passé pour les polices non variables). Pour prendre en charge cela, les polices de variables doivent avoir une table « STAT » qui inclut des sous-tables de valeur d’axe appropriées.
- Les instances nommées de polices de variables sont prises en charge dans les API DirectWrite, mais si certaines opérations sont effectuées dans des implémentations plus anciennes qui ne prennent pas en charge les polices de variables, celles-ci peuvent produire des résultats incorrects.
- Certaines API DirectWrite utilisent les DWRITE_FONT_WEIGHT, les DWRITE_FONT_STRETCH et les énumérations 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 variante 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 de 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 chaque élément de l’ensemble 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 instance nommée de police variable particulière à l’aide des méthodes IDWriteFontSet ::GetMatchingFonts. Si vous utilisez les GetMatchingFonts surcharge qui prend un nom de famille, cependant, le nom de famille 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 se produisant dans un jeu de polices peut être obtenue à l’aide de l'IDWriteFontSet ::GetPropertyValues méthodes à l’aide de DWRITE_FONT_PROPERTY_ID_FAMILY_NAME.
De même, toutes les instances nommées d’une police variable sont représentées dans la collection de polices retournée par IDWriteFactory ::Méthode 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 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 utilisez 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 de variable à un jeu de polices personnalisé, la méthode IDWriteFontSetBuilder1 ::AddFontFile est recommandée, car elle prend en charge les polices de variables et ajoute toutes les instances nommées d’une police variable dans un seul appel. 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 de l'IDWriteFontSetBuilder ::AddFontFaceReference méthodes, car il n’existe aucun moyen de créer une référence de visage de police spécifiant les instances nommées d’un fichier de police variable. 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 les API DirectWrite pour les polices distantes. Si des instances nommées d’une police variable sont incluses dans un jeu de polices système, toutefois, les références de visage de police pour chaque instance nommée existent déjà, et celles-ci peuvent être ajoutées à des jeux de polices personnalisés, notamment avec l’utilisation de valeurs de propriété personnalisées. Pour plus d’informations, consultez la rubrique Jeux de polices personnalisés.
Lorsque vous utilisez des polices variables, les DWRITE_FONT_WEIGHT DirectWrite et les énumérations 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 variante prend toujours en charge les valeurs fractionnaires, tandis que fontWeight et fontStretch utilisent des entiers. L’échelle de l’axe de poids OpenType utilise des valeurs comprises entre 1 et 1 000, qui est également prise en charge par fontWeight. Par conséquent, la modification d’une valeur d’axe de variation en fontWeight est relativement mineure : la police signalée pour une instance nommée peut être arrondie à partir de la valeur précise utilisée pour définir l’instance nommée dans la police. La distinction entre DirectWrite fontStretch et l’échelle de l’axe de largeur OpenType est supérieure : 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 dans la spécification OpenType fournit un mappage entre les valeurs 1 à 9 et les valeurs normales. La valeur fontStretch signalée pour une instance nommée peut impliquer l’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 WSS (nom de famille, poids, stretch 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 un IDWriteTextLayout plage de texte. Les propriétés peuvent être obtenues à partir d’un objet IDWriteFontFace3 ou d'IDWriteFont et IDWriteFontFamily objets qui représentent une instance nommée particulière. Comme indiqué ci-dessus, les valeurs retournées par les méthodes GetWeight et GetStretch peuvent être arrondies pour les valeurs d’axe réelles utilisées pour définir l’instance nommée, mais DirectWrite mappe la combinaison de propriétés à l’instance nommée souhaitée.
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 WSS. La secours de police dans DirectWrite est basée sur les familles avec DirectWrite sélectionnant une variante dans une famille de secours qui est une correspondance la plus proche pour 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 ces variantes dans 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 non WSS particuliers, tels que des variantes de taille optique « Légende ».