Partager via


Prise en charge de la police de couleur

Cette rubrique décrit les polices de couleur, leur prise en charge dans DirectWrite et Direct2D (et d’autres frameworks) et comment les utiliser dans votre application.

Que sont les polices de couleur ?

Par défaut, un glyphe a une forme mais aucune couleur intrinsèque. Les deux DirectWrite et Direct2D ont des méthodes DrawGlyphRun qui restituent les exécutions de glyphes en remplissant les formes de glyphe avec une couleur de texte spécifiée. Pour plus de commodité, nous allons parler de rendu de glyphe monochrome . Toutes les polices ont des glyphes monochromes. D’autre part, une police de couleur contient également des représentations en couleur de certains glyphes. Et pour restituer les glyphes en couleur, votre application doit utiliser différentes API de rendu des glyphes (comme nous allons le voir), au lieu d’appeler les méthodes DrawGlyphRun monochromes.

Les polices de couleur sont également appelées polices multicolores ou polices chromatiques. Il s’agit d’une technologie de police qui permet aux concepteurs de polices d’utiliser plusieurs couleurs dans chaque glyphe. Les polices de couleur permettent des scénarios de texte multicolore dans les applications et les sites web avec moins de code et une prise en charge du système d’exploitation plus robuste que les techniques ad hoc implémentées au-dessus du système de rendu de texte.

Les polices que la plupart d’entre nous connaissent ne sont pas des polices de couleur. Ces polices définissent uniquement la forme des glyphes qu’elles contiennent ; avec des contours vectoriels ou des bitmaps monochromatiques. Au moment du dessin, un convertisseur de texte remplit la forme de glyphe à l’aide d’une couleur unique (la couleur de police) spécifiée par l’application ou le document en cours de rendu. Les polices de couleur, d’autre part, contiennent des informations de couleur en plus des informations de forme. Certaines approches permettent aux concepteurs de polices d’offrir plusieurs palettes de couleurs, ce qui donne à la police de couleur une flexibilité artistique.

Voici un glyphe de la police de couleur Emoji de l’interface utilisateur Segoe. Le glyphe est rendu en monochrome à gauche et en couleur à droite.

Affiche les glyphes côte à côte, le glyphe gauche rendu en monochrome, la droite dans la police de couleur Emoji Segoe U I.

Les polices de couleur incluent généralement des informations de secours pour les plateformes qui ne les prennent pas en charge, ou pour les scénarios dans lesquels la fonctionnalité de couleur a été désactivée. Sur ces plateformes, les polices de couleur sont rendues sous forme de polices monochromatiques standard.

Étant donné que la prise en charge de la police de couleur est implémentée au niveau du rendu du glyphe, elle n’affecte pas la disposition du texte. Et c’est vrai que vous utilisez l’interface IDWriteTextLayout ou que vous implémentez votre propre algorithme de disposition de texte. Le mappage des caractères aux glyphes et le positionnement de ces glyphes utilisent tous des ID de glyphes monochromes et les métriques associées. La sortie du processus de disposition de texte est une séquence d’exécutions de glyphes monochromes. Ensuite, la prise en charge de la police de couleur peut être activée en traduisant ces exécutions de glyphes de base monochromes en glyphes de couleur au moment du rendu.

Pourquoi utiliser des polices de couleur ?

Historiquement, les concepteurs et les développeurs ont utilisé diverses techniques pour obtenir du texte multicolore. Par exemple, les sites web utilisent souvent des images raster au lieu du texte afin d’afficher des en-têtes riches. Cette approche offre une flexibilité artistique, mais les graphiques raster ne sont pas bien mis à l’échelle à toutes les tailles d’affichage et ne fournissent pas non plus les mêmes fonctionnalités d’accessibilité que le texte réel. Une autre technique courante consiste à superposer plusieurs polices monochromes dans différentes couleurs de police ; mais cela nécessite généralement du code de disposition supplémentaire à gérer.

Les polices de couleur offrent un moyen d’obtenir ces effets visuels avec toute la simplicité et les fonctionnalités des polices régulières. Le texte rendu dans une police de couleur est identique à un autre texte : il peut être copié et collé, il peut être analysé par les outils d’accessibilité, et ainsi de suite.

Quels types de polices de couleur Windows prend-il en charge ?

La spécification OpenType définit plusieurs façons d’incorporer des informations de couleur dans une police. À partir de Windows 10, la version 1607 (mise à jour anniversaire), DirectWrite et Direct2D (ainsi que les frameworks Windows qui s’en appuient) prennent en charge toutes ces approches :

Technique Description
COLR/Tables CPAL Utilise des couches de vecteurs colorés, dont les formes sont définies de la même manière que les contours de glyphes unicolores. Le support a démarré dans Windows 8.1.
Table SVG Utilise des images vectorielles créées au format SVG (Scalable Vector Graphics). Depuis Windows 10, version 1607 (mise à jour anniversaire), DirectWrite prend en charge un sous-ensemble de la spécification SVG complète. Le rendu de tout le contenu SVG n’est pas garanti dans une police SVG OpenType. Pour plus d’informations, consultez Prise en charge SVG.
CDBT/Tables CBLC Utilise des images bitmap de couleur incorporées.
table sbix Utilise des images bitmap de couleur incorporées.

Utilisation de polices de couleur

Du point de vue de l’utilisateur, les polices de couleur ne sont que des polices. Par exemple, ils peuvent généralement être installés et désinstallés du système de la même manière que les polices monochromes ; et elles sont rendues sous forme de texte régulier et sélectionnable.

Du point de vue du développeur également, les polices de couleur sont généralement utilisées de la même façon que les polices monochromes. Dans les frameworks XAML et Microsoft Edge, vous pouvez mettre en forme votre texte avec des polices de couleur de la même façon que pour les polices régulières, et par défaut, votre texte sera rendu en couleur. Toutefois, si votre application appelle directement les API Direct2D (ou les API Win2D) pour afficher du texte, elle doit demander explicitement le rendu de la police de couleur.

Utilisation de polices de couleur avec DirectWrite et Direct2D

Votre application peut utiliser les méthodes de dessin de texte de niveau supérieur de Direct2D (DrawText et DrawTextLayout), ou elle peut utiliser des techniques de niveau inférieur pour dessiner des exécutions de glyphes directement. Dans les deux cas, votre application a besoin d’un code spécifique pour gérer correctement les glyphes de couleur. Les API DrawText et DrawTextLayout de Direct2D ne rendent pas les glyphes de couleur par défaut. Il s’agit d’éviter les changements de comportement inattendus dans les applications de rendu de texte qui ont été conçues avant la prise en charge de la police de couleur.

Pour choisir de colorer le rendu du glyphe, passez l’indicateur d’options D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT à la méthode de dessin. L’exemple de code suivant montre comment appeler la méthode DrawText de Direct2D pour afficher une chaîne dans une police de couleur :

// If m_textFormat points to a font with color glyphs, then the following
// call will render m_string using the color glyphs available in that font.
// Any monochromatic glyphs will be rendered with m_defaultFillBrush.
m_deviceContext->DrawText(
    m_string->Data(),
    m_string->Length(),
    m_textFormat.Get(),
    m_layoutRect,
    m_defaultFillBrush.Get(),
    D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT
    );

Si votre application utilise des API de niveau inférieur pour gérer directement les exécutions de glyphes, elle continuera de fonctionner en présence de polices de couleur, mais elle ne sera pas en mesure de dessiner des glyphes de couleur sans logique supplémentaire.

Pour gérer correctement les glyphes de couleur, votre application doit :

  1. Transmettez les informations d’exécution du glyphe à TranslateColorGlyphRun, ainsi qu’un paramètre DWRITE_GLYPH_IMAGE_FORMATS qui indique le ou les types de glyphes de couleur que l’application est prête à gérer. Si des glyphes de couleur sont présents (en fonction de la police et de la DWRITE_GLYPH_IMAGE_FORMATS demandée), DirectWrite fractionnera le glyphe principal en exécutions de glyphes de couleur individuelles, qui sont accessibles via l’objet IDWriteColorGlyphRunEnumerator1 retourné à l’étape 4.
  2. Vérifiez le HRESULT retourné par TranslateColorGlyphRun pour déterminer si des exécutions de glyphes de couleur ont été détectées. Un HRESULT de DWRITE_E_NOCOLOR indique qu’il n’existe pas d’exécution de glyphe de couleur applicable.
  3. Si TranslateColorGlyphRun ne signale aucune exécution de glyphe de couleur (en renvoyant DWRITE_E_NOCOLOR), l’exécution de glyphe entière est traitée comme monochromatique et votre application doit la dessiner comme vous le souhaitez (par exemple, à l’aide de ID2D1DeviceContext::D rawGlyphRun).
  4. Si TranslateColorGlyphRun signale la présence d’exécutions de glyphes de couleur, votre application doit ignorer l’exécution du glyphe principal et utiliser à la place la ou les exécutions de glyphes de couleur retournées par TranslateColorGlyphRun. Pour ce faire, effectuez une itération à travers l’objet IDWriteColorGlyphRunEnumerator1 retourné, en récupérant chaque exécution de glyphe de couleur et en le dessinant en fonction de son format d’image de glyphe (par exemple, vous pouvez utiliser DrawColorBitmapGlyphRun et DrawSvgGlyphRun pour dessiner des glyphes bitmap de couleur et des glyphes SVG, respectivement).

Cet exemple de code montre la structure générale de cette procédure :

// An example code snippet demonstrating how to use TranslateColorGlyphRun 
// to handle different kinds of color glyphs. This code does not make any 
// actual drawing calls. 
HRESULT DrawGlyphRun( 
    FLOAT baselineOriginX, 
    FLOAT baselineOriginY, 
    DWRITE_MEASURING_MODE measuringMode, 
    _In_ DWRITE_GLYPH_RUN const* glyphRun, 
    _In_ DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, 
) 
{ 
    // Specify the color glyph formats your app supports. In this example, 
    // the app requests only glyphs defined with PNG or SVG. 
    DWRITE_GLYPH_IMAGE_FORMATS requestedFormats = 
        DWRITE_GLYPH_IMAGE_FORMATS_PNG | DWRITE_GLYPH_IMAGE_FORMATS_SVG; 

    ComPtr<IDWriteColorGlyphRunEnumerator1> glyphRunEnumerator; 
    HRESULT hr = m_dwriteFactory->TranslateColorGlyphRun( 
        D2D1::Point2F(baselineOriginX, baselineOriginY), 
        glyphRun, 
        glyphRunDescription, 
        requestedFormats, // The glyph formats supported by this renderer.
        measuringMode, 
        nullptr, 
        0, 
        &glyphRunEnumerator // On return, may contain color glyph runs.
        ); 

    if (hr == DWRITE_E_NOCOLOR) 
    { 
        // The glyph run has no color glyphs. Draw it as a monochrome glyph 
        // run, for example using the DrawGlyphRun method on a Direct2D 
        // device context. 
    } 
    else 
    { 
        // The glyph run has one or more color glyphs. 
        DX::ThrowIfFailed(hr); 

        // Iterate through the color glyph runs, and draw them. 
        for (;;) 
        { 
            BOOL haveRun; 
            DX::ThrowIfFailed(glyphRunEnumerator->MoveNext(&haveRun)); 
            if (!haveRun) 
            { 
                break; 
            } 

            // Retrieve the color glyph run. 
            DWRITE_COLOR_GLYPH_RUN1 const* colorRun; 
            DX::ThrowIfFailed(glyphRunEnumerator->GetCurrentRun(&colorRun)); 

            // Draw the color glyph run depending on its format. 
            switch (colorRun->glyphImageFormat) 
            { 
            case DWRITE_GLYPH_IMAGE_FORMATS_PNG: 
                // Draw the PNG glyph, for example with 
                // ID2D1DeviceContext4::DrawColorBitmapGlyphRun. 
                break; 

            case DWRITE_GLYPH_IMAGE_FORMATS_SVG: 
                // Draw the SVG glyph, for example with 
                // ID2D1DeviceContext4::DrawSvgGlyphRun. 
                break; 

                // ...etc. 
            } 
        } 
    } 

    return hr; 
} 

Utilisation de polices de couleur dans une application XAML

Les polices de couleur sont prises en charge par défaut par les éléments de texte de la plateforme XAML, tels que TextBlock, TextBox, RichEditBox, Glyphes et FontIcon. Il vous suffit de mettre en forme votre texte avec une police de couleur, et tous les glyphes de couleur seront rendus en couleur.

La syntaxe suivante montre un moyen de styler un TextBlock avec une police de couleur empaquetée avec votre application. La même technique s’applique aux polices régulières.

<TextBlock FontFamily="Assets/TMyColorFont.otf#MyFontFamilyName">Here's some text.</TextBlock>

Si vous souhaitez que votre élément de texte XAML ne rende jamais de texte multicolore, définissez sa propriété IsColorFontEnabledProperty sur false.

Conseil

Les liens ci-dessus sont vers les versions WinUI 3 de ces contrôles XAML. Vous trouverez les équivalents plateforme Windows universelle (UWP) dans l’espace de noms Windows.UI.Xaml.Controls.

Utilisation de polices de couleur dans Microsoft Edge

Les polices de couleur sont rendues par défaut dans les sites web et les applications web s’exécutant sur Microsoft Edge, y compris le contrôle XAML WebView2 . Utilisez simplement HTML et CSS pour styler votre texte avec une police de couleur, et tous les glyphes de couleur seront rendus en couleur.

Utilisation de polices de couleur avec Win2D

Comme pour Direct2D, les API de dessin de texte de Win2D ne rendent pas les glyphes de couleur par défaut. Pour choisir de colorer le rendu du glyphe, définissez l’indicateur d’options EnableColorFont dans l’objet de format de texte que votre application transmet à la méthode de dessin de texte. L’exemple de code suivant montre comment restituer une chaîne dans une police de couleur à l’aide de Win2D :

// The text format that will be used to draw the text. (Declared elsewhere 
// and initialized elsewhere by the app to point to a color font.) 
CanvasTextFormat m_textFormat; 

// Set the EnableColorFont option. 
m_textFormat.Options = CanvasDrawTextOptions.EnableColorFont; 

// If m_textFormat points to a font with color glyphs, then the following
// call will render m_string using the color glyphs available in that font.
// Any monochromatic glyphs will be rendered with m_color.
args.DrawingSession.DrawText(
    m_string,
    m_point,
    m_color,
    m_textFormat
    );