Suporte à fonte de cores

Este tópico descreve fontes de cores, seu suporte em DirectWrite e Direct2D (e algumas outras estruturas) e como usá-las em seu aplicativo.

O que são fontes de cores?

Por padrão, um glifo tem uma forma, mas nenhuma cor intrínseca. Tanto DirectWrite quanto Direct2D têm métodos DrawGlyphRun que renderizam execuções de glifo preenchendo as formas de glifo com uma cor de texto especificada. Para conveniência, vamos nos referir a isso como renderização de glifo monocromático . Todas as fontes têm glifos monocromáticos. Uma fonte de cor, por outro lado, também tem representações de cores de alguns glifos. E para renderizar glifos em cores, seu aplicativo deve usar diferentes APIs de renderização de glifo (como discutiremos), em vez de chamar os métodos DrawGlyphRun monocromáticos.

Fontes de cores também são conhecidas como fontes multicoloridas ou fontes cromáticas. Eles são uma tecnologia de fonte que permite que os designers de fonte usem várias cores dentro de cada glifo. Fontes de cores permitem cenários de texto multicolorido em aplicativos e sites com menos código e suporte mais robusto ao sistema operacional do que as técnicas ad hoc implementadas acima do sistema de renderização de texto.

As fontes com as quais a maioria de nós está familiarizada não são fontes de cores. Essas fontes definem apenas a forma dos glifos que contêm; com estruturas de tópicos vetoriais ou bitmaps monocromáticos. No momento do desenho, um renderizador de texto preenche a forma de glifo usando uma única cor (a cor da fonte) especificada pelo aplicativo ou documento que está sendo renderizado. Fontes de cor, por outro lado, contêm informações de cor, além de informações de forma. Algumas abordagens permitem que os designers de fonte ofereçam várias paletas de cores, proporcionando flexibilidade artística à fonte de cores.

Aqui está um glifo da fonte de cor Segoe UI Emoji. O glifo é renderizado em monocromático à esquerda e em cores à direita.

Mostra glifos lado a lado, o glifo esquerdo renderizado em monocromático, à direita na fonte de cores Segoe U I Emoji.

Fontes de cores normalmente incluem informações de fallback para plataformas que não dão suporte a elas ou para cenários em que a funcionalidade de cor foi desabilitada. Nessas plataformas, as fontes de cores são renderizadas como fontes monocromáticas regulares.

Como o suporte à fonte de cores é implementado no nível de renderização de glifo, isso não afeta o layout de texto. E isso é verdade se você usa a interface IDWriteTextLayout ou se implementa seu próprio algoritmo de layout de texto. O mapeamento de caracteres para glifos e o posicionamento desses glifos usam IDs de glifo monocromáticas e suas métricas associadas. A saída do processo de layout de texto é uma sequência de execuções de glifo monocromático. Em seguida, o suporte à fonte de cores pode ser habilitado traduzindo essas execuções de glifo base monocromática para execuções de glifos de cor no momento da renderização.

Por que usar fontes de cores?

Historicamente, designers e desenvolvedores têm usado uma variedade de técnicas para obter texto multicolorido. Por exemplo, os sites geralmente usam imagens de raster em vez de texto para exibir cabeçalhos avançados. Essa abordagem permite flexibilidade artística, mas os elementos gráficos raster não são dimensionados bem para todos os tamanhos de exibição e nem fornecem os mesmos recursos de acessibilidade que o texto real. Outra técnica comum é sobrepor várias fontes monocromáticas em cores de fonte diferentes; mas isso normalmente requer um código de layout extra para gerenciar.

Fontes de cores oferecem uma maneira de obter esses efeitos visuais com toda a simplicidade e funcionalidade de fontes regulares. O texto renderizado em uma fonte de cor é o mesmo que outro texto: ele pode ser copiado e colado, pode ser analisado por ferramentas de acessibilidade e assim por diante.

Quais tipos de fontes de cor o Windows dá suporte?

A especificação OpenType define várias maneiras de inserir informações de cor em uma fonte. A partir do Windows 10, versão 1607 (Atualização de Aniversário), DirectWrite e Direct2D (e as estruturas do Windows criadas neles) dão suporte a todas essas abordagens:

Técnica Descrição
COLR/Tabelas CPAL Usa camadas de vetores coloridos, cujas formas são definidas da mesma forma que as estruturas de glifo de cor única. Suporte iniciado no Windows 8.1.
Tabela SVG Usa imagens vetoriais criadas no formato SVG (Elementos Gráficos Vetoriais Escalonáveis). A partir do Windows 10, versão 1607 (Atualização de Aniversário), DirectWrite dá suporte a um subconjunto da especificação SVG completa. Nem todo o conteúdo SVG tem a garantia de renderizar em uma fonte SVG OpenType. Para obter mais detalhes, confira Suporte a SVG.
CBDT/Tabelas CBLC Usa imagens de bitmap de cor inseridas.
tabela sbix Usa imagens de bitmap de cor inseridas.

Usando fontes de cor

Da perspectiva do usuário, fontes de cores são apenas fontes. Por exemplo, eles geralmente podem ser instalados e desinstalados do sistema da mesma forma que as fontes monocromáticas podem; e são renderizados como texto regular e selecionável.

Da perspectiva do desenvolvedor também, as fontes de cores geralmente são usadas da mesma maneira que as fontes monocromáticas. Nas estruturas XAML e Microsoft Edge, você pode estilizar seu texto com fontes de cores da mesma maneira que pode com fontes regulares e, por padrão, seu texto será renderizado em cores. No entanto, se seu aplicativo chamar diretamente APIs Direct2D (ou APIs Win2D) para renderizar texto, ele deverá solicitar explicitamente a renderização da fonte de cores.

Usando fontes de cores com DirectWrite e Direct2D

Seu aplicativo pode usar os métodos de desenho de texto de nível superior do Direct2D (DrawText e DrawTextLayout) ou pode usar técnicas de nível inferior para desenhar execuções de glifo diretamente. Em ambos os casos, seu aplicativo requer código específico para lidar com glifos de cor corretamente. As APIs DrawText e DrawTextLayout do Direct2D não renderizam glifos de cor por padrão. Isso é para evitar alterações de comportamento inesperadas em aplicativos de renderização de texto que foram projetados antes do suporte à fonte de cores.

Para aceitar a renderização de glifo de cores, passe o sinalizador de opções de D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT para o método de desenho. O exemplo de código a seguir mostra como chamar o método DrawText do Direct2D para renderizar uma cadeia de caracteres em uma fonte de cor:

// 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
    );

Se o aplicativo usar APIs de nível inferior para manipular execuções de glifo diretamente, ele continuará funcionando na presença de fontes de cor, mas não poderá desenhar glifos de cor sem lógica adicional.

Para lidar corretamente com glifos de cor, seu aplicativo deve:

  1. Passe as informações de execução do glifo para TranslateColorGlyphRun, juntamente com um parâmetro DWRITE_GLYPH_IMAGE_FORMATS que indica quais tipos de glifo de cor o aplicativo está preparado para manipular. Se houver glifos de cor (com base na fonte e no DWRITE_GLYPH_IMAGE_FORMATS solicitado), DirectWrite dividirá o glifo primário executado em execuções de glifo de cor individuais, que podem ser acessadas por meio do objeto IDWriteColorGlyphRunEnumerator1 retornado na Etapa 4.
  2. Verifique o HRESULT retornado por TranslateColorGlyphRun para determinar se alguma execução de glifo de cor foi detectada. Um HRESULT de DWRITE_E_NOCOLOR indica que não há uma execução de glifo de cor aplicável.
  3. Se TranslateColorGlyphRun não relatar execuções de glifo de cor (retornando DWRITE_E_NOCOLOR), toda a execução do glifo será tratada como monocromática e seu aplicativo deverá desenhá-la conforme desejado (por exemplo, usando ID2D1DeviceContext::D rawGlyphRun).
  4. Se TranslateColorGlyphRun relatar a presença de execuções de glifo de cor, seu aplicativo deverá ignorar a execução do glifo primário e, em vez disso, usar as execuções de glifo de cor retornadas por TranslateColorGlyphRun. Para fazer isso, itere por meio do objeto IDWriteColorGlyphRunEnumerator1 retornado, recuperando cada execução de glifo de cor e desenhando-o conforme apropriado para seu formato de imagem de glifo (por exemplo, você pode usar DrawColorBitmapGlyphRun e DrawSvgGlyphRun para desenhar glifos de bitmap de cor e glifos SVG, respectivamente).

Este exemplo de código mostra a estrutura geral deste procedimento:

// 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; 
} 

Usando fontes de cores em um aplicativo XAML

As fontes de cores são compatíveis por padrão com os elementos de texto da plataforma XAML, como TextBlock, TextBox, RichEditBox, Glyphs e FontIcon. Você simplesmente estiliza o texto com uma fonte de cor e todos os glifos de cor serão renderizados em cores.

A sintaxe a seguir mostra uma maneira de estilizar um TextBlock com uma fonte de cor empacotada com seu aplicativo. A mesma técnica se aplica a fontes regulares.

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

Se você quiser que o elemento de texto XAML nunca renderize texto multicolorido, defina sua propriedade IsColorFontEnabledProperty como false.

Dica

Os links acima são para as versões do WinUI 3 desses controles XAML. Você pode encontrar os equivalentes de Plataforma Universal do Windows (UWP) no namespace Windows.UI.Xaml.Controls.

Usando fontes de cores no Microsoft Edge

Fontes de cores são renderizadas por padrão em sites e aplicativos Web em execução no Microsoft Edge, incluindo o controle XAML WebView2 . Basta usar HTML e CSS para estilizar seu texto com uma fonte de cor e todos os glifos de cor serão renderizados em cores.

Usando fontes de cor com Win2D

Semelhante ao Direct2D, as APIs de desenho de texto do Win2D não renderizam glifos de cor por padrão. Para aceitar a renderização de glifo de cores, defina o sinalizador de opções EnableColorFont no objeto de formato de texto que seu aplicativo passa para o método de desenho de texto. O exemplo de código a seguir mostra como renderizar uma cadeia de caracteres em uma fonte de cor usando 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
    );