Este artigo foi traduzido por máquina.

Fator DirectX

Quem tem medo de glifo é executado?

Charles Petzold

Baixe o código de exemplo

Charles Petzold
Primeiro encontrei há alguns anos o conceito de glifos de caracteres em Windows Presentation Foundation (WPF). Em tipografia, "glifo" refere-se a representação gráfica de um personagem, ao invés de sua função em um determinado idioma escrito, que é indicado pelo valor de Unicode do caractere. Eu sabia que o elemento Glyphs WPF e GlyphRun classe representado de uma forma alternativa para exibir texto, mas pareciam adicionar uma camada de complexidade desnecessária. A estranheza maior envolvido referenciando a fonte desejada, não por um nome de família de fonte, mas pelo caminho do arquivo do arquivo de fonte real. Eu tinha sido codificação para Windows desde as versões beta do 1.0, e eu nunca antes tinha precisava de uma fonte de referência pelo nome do arquivo. Simplesmente não é assim.

Eu rapidamente concluíram que Glyphs e GlyphRun foram muito muito esotérico para programadores mainstream como eu. Apenas anos mais tarde, quando comecei a trabalhar com o Microsoft XML Paper Specification (XPS) que a lógica por trás de glifos tornam-se aparentes.

A distinção básica

Normalmente, quando um programa solicita uma fonte de Windows, ele faz isso usando um nome de família de fonte como Century Schoolbook e atributos como itálico ou negrito. Em tempo de execução, o Windows encontra um arquivo de fonte no sistema do usuário com um tipo de letra que corresponda ao nome de família. Itálico e negrito pode também ser intrínseca a essa fonte ou sintetizada pelo sistema. Para esquematizar o texto, o Windows ou o aplicativo acessa informações de métricas de fonte que descreve os tamanhos dos caracteres de fonte.

O que acontece se dois usuários diferentes tem dois arquivos de fonte diferente em seus sistemas que contêm uma fonte com o nome de família do século Schoolbook, mas com métricas de fonte um pouco diferente? Isso não é um problema real. Porque o texto é formatado e colocado para fora em tempo de execução, o processamento real destas duas fontes pode ser ligeiramente diferente, mas isso não importa. Programas de aplicação são projetados para serem flexíveis dessa forma.

Documentos XPS são diferentes, no entanto. Muito como PDF, XPS descreve um documento de página fixo. Todo o texto em cada página é já estabelecido e precisamente posicionado. Se tal documento é processado com uma fonte que é ligeiramente diferente da fonte usada para projetar a página, não fica bem. Isto é porque o XPS documentos muitas vezes contêm arquivos de fonte incorporada, e porque as páginas XPS usam o elemento Glyphs para esses arquivos de fonte de referência e processar o texto. Qualquer ambigüidade é totalmente eliminada.

Normalmente nos referimos a caracteres de texto por códigos de caracteres. Geralmente não precisamos saber nada sobre o glifo preciso que acontece a ser exibido na sequência usando o código de caracteres com uma determinada fonte. Mas às vezes é importante ter mais controle sobre os glifos próprios.

Você pode assumir que há uma correspondência exacta entre códigos de caracteres e glifos em uma determinada fonte, e que é geralmente o caso. Mas existem exceções muito importantes: Alguns arquivos de fonte contêm ligaduras, que são o único glifos correspondentes para os pares de caracteres tais como fi ou fl. Alguns conjuntos de caracteres não-latinos exigem múltiplos glifos para processar um único caractere. Além disso, alguns arquivos de fonte contêm glifos alternativos para determinados caracteres — por exemplo, um zero com uma barra no meio, pequenas letras maiúsculas usadas para letras minúsculas ou letras com traços estilísticos violentos. Estas alternativas estilísticas são característicos de um arquivo de fonte específico, ao invés de uma fonte. É por isso obtendo o arquivo de fonte certa é crucial.

Se você estiver escrevendo um aplicativo de armazenamento do Windows para o Windows 8, você pode fazer uso destas alternativas estilísticas por meio da API de tempo de execução do Windows. Capítulo 16 de "Programação Windows, 6ª edição" (o ' Reilly Media, 2012) tem um programa chamado TypographyDemo que demonstra como fazer isso. Mas o suporte subjacente para glifos no Windows 8 é implementado no DirectX, e o poder de glifos próprios é revelado a mais nesse ambiente.

O suporte DirectX glifo

Explorar como exibir glifos em DirectX envolve traçando um caminho através de várias interfaces, métodos e estruturas.

Vamos começar com a interface ID2D1RenderTarget, que contém os métodos básicos para exibir texto e gráficos 2D. Essa interface define um método DrawGlyphRun. Este método requer uma estrutura do tipo DWRITE_GLYPH_RUN que descreve os glifos para ser exibido, e também referências um objeto do tipo IDWriteFontFace.

Uma maneira de obter um objeto IDWriteFontFace é através do método de CreateFontFace de IDWriteFactory. Esse método requer um objeto IDWriteFontFile, que é obtido através do método de CreateFontFileReference de IDWriteFactory.

O método de CreateFontFileReference faz referência a um arquivo de fonte usando um caminho e nome do arquivo. No entanto, se você estiver usando DirectX em um aplicativo Windows Store, seu aplicativo provavelmente não terá acesso completo e gratuito para o disco rígido do usuário, e geralmente não é possível acessar fontes dessa forma. Qualquer arquivo de fonte que você referência com CreateFontFileReference provavelmente será definido como um recurso de aplicativo e sujeitar-se ao pacote do aplicativo.

No entanto, você não pode incluir qualquer arquivo de fonte no pacote do seu aplicativo. Se uma fonte é parte do seu aplicativo, você deve ter uma licença para distribuir essa fonte. Felizmente, a Microsoft licenciou vários arquivos fonte de Ascender Corp. para o propósito de permitir que você distribui-las com seu aplicativo. Esses arquivos de fonte têm sido utilizados principalmente para aplicações de XNA, mas também são interessantes do ponto de vista de glifos.

Entre o código para download para esta coluna é um programa chamado GlyphDump que criei baseado no modelo DirectX App (XAML) em Visual Studio Express 2013 Preview. Este modelo cria um aplicativo que processa gráficos DirectX em uma SwapChainPanel.

Eu criei um novo filtro (e pasta correspondente) no projeto GlyphDump denominado fontes e adicionado os arquivos de 10 fonte licenciados de Ascender Corp. Um ListBox em DirectXPage.xaml explicitamente lista os nomes de família dessas fontes, com propriedades de Tag, fazendo referência a nomes de arquivo. Quando um é selecionado, o programa constrói o caminho e o nome do arquivo de fonte da seguinte forma:

Package::Current->InstalledLocation->Path +
  "\\Fonts\\" + filename;

A classe GlyphDumpRenderer, em seguida, usa esse caminho para criar um objeto IDWriteFontFile e um objeto IDWriteFontFace.

O resto do trabalho ocorre no método Render, como mostrado em Figura 1.

Figura 1 o método Render em GlyphDump

bool GlyphDumpRenderer::Render()
{
  if (!m_needsRedraw)
      return false;
  ID2D1DeviceContext* context = m_deviceResources->GetD2DDeviceContext();
  context->SaveDrawingState(m_stateBlock.Get());
  context->BeginDraw();
  context->Clear(ColorF(ColorF::White));
  context->SetTransform(m_deviceResources->GetOrientationTransform2D());
  if (m_fontFace != nullptr)
  {
    Windows::Foundation::Size outputBounds = m_deviceResources->GetOutputBounds();
    uint16 glyphCount = m_fontFace->GetGlyphCount();
    int rows = (glyphCount + 16) / 16;
    float boxHeight = outputBounds.Height / (rows + 1);
    float boxWidth = outputBounds.Width / 17;
    // Define entire structure except glyphIndices
    DWRITE_GLYPH_RUN glyphRun;
    glyphRun.fontFace = m_fontFace.Get();
    glyphRun.fontEmSize = 0.75f * min(boxHeight, boxWidth);
    glyphRun.glyphCount = 1;
    glyphRun.glyphAdvances = nullptr;
    glyphRun.glyphOffsets = nullptr;
    glyphRun.isSideways = false;
    glyphRun.bidiLevel = 0;
    for (uint16 index = 0; index < glyphCount; index++)
    {
      glyphRun.glyphIndices = &index;
      context->DrawGlyphRun(Point2F(((index) % 16 + 0.5f) * boxWidth,
                                    ((index) / 16 + 1) * boxHeight),
                                    &glyphRun,
                                    m_blackBrush.Get());
    }
  }
  // We ignore D2DERR_RECREATE_TARGET here.
This error indicates
  // that the device is lost.
It will be handled during
  // the next call to Present.
HRESULT hr = context->EndDraw();
  if (hr != D2DERR_RECREATE_TARGET)
  {
    DX::ThrowIfFailed(hr);
  }
  context->RestoreDrawingState(m_stateBlock.Get());
  m_needsRedraw = false;
  return true;
}

Esse método de renderização exibe todos os glifos no arquivo fonte selecionada em linhas de 16 glifos cada, então ele tenta calcular um valor de fontEmSize suficientemente pequeno para aquela exibição. (Para algumas fontes com muitos glifos, isto não vai funcionar bem.) Normalmente o campo glyphIndices da estrutura DWRITE_GLYPH_RUN é uma matriz de índices de glifo. Aqui eu estou apenas exibindo um glifo de cada vez.

O método DrawGlyphRun requer um ponto de coordenada, a estrutura DWRITE_GLYPH_RUN e um pincel. A coordenada indica onde a borda esquerda da linha de base do glifo é deve ser posicionado. Repare que eu disse "baseline". Isso é diferente da maioria dos métodos de exibição de texto, que exigem especificando o canto superior esquerdo do primeiro caractere.

Figura 2 mostra talvez a fonte mais interessante deste pacote, que tem um nome de família do Pescadero e um nome de arquivo de fonte de Pesca.ttf.

The GlyphDump Program Showing the Pescadero Font
Figura 2 o programa de GlyphDump mostrando a fonte Pescadero

Antes de escrever este programa, eu nunca tinha visto uma exibição como esta. Ele começa procurando algo como uma tabela ASCII tradicional, mas então há um monte de glifos para subscripting numérico e colocação e uma coleção inteira de ligaduras de vários tipos, além de letras maiúsculas com traços violentos decorativos.

Obviamente, o campo de glyphIndices de DWRITE_GLYPH_RUN não é o mesmo que um código de caractere. Estes são os índices que fazem referência os glifos reais dentro do arquivo fonte, e estes glifos não precisam mesmo de ser qualquer tipo de ordem racional.

Texto com glifos

Você já pode ver alguma utilidade em ser capaz de exibir texto usando um arquivo de fonte específica com índices de glifo, ao invés de códigos de caracteres. Você pode especificar exatamente o que glifos que você quer.

O projeto postoelegante demonstra isso. A idéia aqui é que você tem um programa que é principalmente baseada em XAML, mas você quer um título chique usando algumas ligaduras e swashes partir a fonte Pescadero. O projeto inclui o arquivo de Pesca.ttf, e o arquivo XAML define o SwapChainPanel para ter uma largura de 778 e uma altura de 54, valores que eu escolhi empiricamente com base no tamanho do texto processado.

Porque os requisitos de exposição deste projeto são simples, removi o FancyTitleMain classe e as classes de renderização, deixando a classe DirectXPage para processar para o SwapChainPanel. (No entanto, tive que modificar DeviceResources ligeiramente para fazer IDeviceNotify uma interface de classe ref para que DirectXPage poderia implementar IDevice­notificar e ser notificado quando o dispositivo de saída é perdido e recriado.)

A saída de texto mostrada na Figura 3 tem 24 caracteres, mas apenas 22 glifos. Você vai reconhecer as ligaduras e os traços violentos de Figura 2.

The FancyTitle Output
Figura 3 a saída de postoelegante

Eu fiz o fundo DirectX Alice Blue então você pode ver que o SwapChainPanel é pouco maior do que o texto. Claro, é possível prever o tamanho da saída, exatamente porque o arquivo de fonte é parte do aplicativo e os glifos são acessados diretamente.

Você pode obter as ligaduras e glifos alternativos sem o uso de DrawGlyphRun. Você também pode obtê-los com menos precisão usando o elemento TextBlock em tempo de execução do Windows, como a tipografia­programa de demonstração do meu livro Windows 8 demonstra. Em DirectWrite, você pode usar o método de SetTypography de IDWriteTextLayout com um objeto IDWriteTypography, que em última análise, faz referência a um membro da extensa enumeração de DWRITE_FONT_FEATURE_TAG. Mas essas técnicas não são muito certas como especificando os glifos precisamente.

Como conseguir itálico e negrito com DrawGlyphRun? Em muitos casos, os arquivos de fonte diferente irão conter variações em itálico e negrito de uma fonte. Entre as fontes incluídas pelo programa GlyphDump são algumas fontes bold (realce) e uma fonte de luz. No entanto, você também tem a opção para simular oblíquas e bold (realce) caracteres usando sinalizadores DWRITE_FONT_SIMULATIONS em CreateFontFace.

Avança e desloca

Ambos GlyphDump e postoelegante definir dois dos campos em DWRITE_GLYPH_RUN nullptr. Esses dois campos são chamados glyphAdvances e glyphOffsets.

Quando você exibir uma matriz de glifos, você especificar a origem da linha de base à esquerda do primeiro caractere. Para cada personagem sucessiva, a coordenada horizontal da origem é aumentada automaticamente com base na largura do caractere. (Um processo semelhante ocorre quando exibir o texto para os lados). Este aumento é conhecido como um "avanço".

Você pode obter os avanços que o DirectX usa para espaçamento entre caracteres, chamando o método GetDesignGlyphMetrics de IDWriteFontFace. O resultado é uma matriz de DWRITE_GLYPH_METRICS estruturas, uma para cada índice de glifo no qual você está interessado. O campo advanceWidth da estrutura indica o avanço em relação ao campo designUnitsPerEm da estrutura DWRITE_FONT_METRICS obtido a partir do método de GetMetrics de IDWriteFontFace, e que também inclui verticais métricas aplicáveis a todos os glifos dentro de uma determinada fonte.

Ou, você pode chamar o método GetDesignGlyphAdvances de IDWriteFontFace1, que também fornece avanços em relação ao valor de designUnitsPerEm. Dividir os valores por designUnitsPerEm (que é muitas vezes um bom valor redondo como 2.048) e então multiplicar pelo em tamanho especificado em DWRITE_GLYPH_RUN.

A matriz de glyphAdvances comumente é usada para personagens mais perto do espaço juntos ou mais distante do que indicam as métricas do projeto. Se você decidir usá-lo, você precisará definir a glyphAdvances para uma matriz de valores que é pelo menos o tamanho da matriz de índices de glifo, menos um. Um adiantamento não é necessário sobre o glifo de final porque não aparece nada além disso.

O campo glyphOffsets é uma matriz de DWRITE_GLYPH_OFFSET estruturas, uma para cada personagem. Os dois campos são advanceOffset e ascenderOffset, que indica um deslocamento desejado (para a direita e a cima, respectivamente) em relação à localização normal do personagem. Esta facilidade é freqüentemente usada em arquivos XPS para posicionar múltiplos glifos de uma fonte particular por toda a página.

O programa de CenteredGlyphDump demonstra como usar o campo glyphOffsets para exibir todo o conjunto de glifos de um arquivo de fonte particular com uma única chamada DrawGlyphRun:

context->DrawGlyphRun(Point2F(), &m_glyphRun, m_blackBrush.Get());

É a coordenada passada para DrawGlyphRun (0, 0), e glyphAdvances é definido como uma matriz de valores zero para inibir o avanço sucessivos glifos. A posição de cada glifo é inteiramente governada por glyphOffsets. Esta posição baseia-se em métricas de glifo para centralizar cada glifo em sua coluna. A Figura 4 mostra o resultado.

The CenteredGlyphDump Program
Figura 4 o programa de CenteredGlyphDump

Fornecendo seu próprio carregador de fonte

Se um arquivo de fonte é parte de um pacote de aplicativos, é bastante fácil de derivar um caminho de arquivo, que você pode usar com CreateFontReference. Mas se você tiver uma fonte que está localizada em um pacote XPS ou EPUB, ou talvez no armazenamento isolado ou na nuvem?

Contanto que você pode escrever código que acessa o arquivo de fonte, o DirectX pode acessá-lo. Você precisará fornecer duas classes que implementa IDWriteFontFileLoader e outro que implementa IDWriteFontFileStream. Geralmente, a classe que implementa o IDWriteFontFileLoader é um singleton que acessa todos os arquivos de fonte seu aplicativo precisará e atribui a cada um de uma chave. O método CreateStreamFromKey na sua implementação de IDWriteFontFileLoader retorna uma instância de IDWriteFontStream para cada arquivo de fonte.

Para usar essas duas classes, você primeiro instancia uma única instância da classe que implementa IDWriteFontFileLoader e passá-lo para o RegisterFontFileLoader do objeto IDWriteFactory. Então, em vez de chamar o CreateFontFileReference para obter um objeto IDWriteFontFile, chame CreateCustomFontFileReference com esta instância de IDWriteFontFileLoader e uma chave que identifica o arquivo de fonte específico que você quer.

Esta técnica é demonstrada no programa CenteredGlyphDump. O projeto inclui duas classes — PrivateFontFileLoader e PrivateFontFileStream — que implementam as duas interfaces. As classes de fonte de acesso a arquivos no pacote do aplicativo, mas podem ser adaptadas para outros fins.

É provável que sua implementação de IDWriteFontFileLoader vai precisar fazer chamadas de I/O de arquivo, e em um aplicativo Windows Store, estas ligações devem ser assíncronas. Isso faz muito sentido para a classe IDWriteFontFileLoader definir um método assíncrono que carrega todas as fontes na memória e para o IDWriteFontFileStream para simplesmente retornar ponteiros para os blocos de memória. Esta é a abordagem que eu tirei com PrivateFontFileLoader e PrivateFontFileStream, depois de examinar atentamente o Direct2D revista App amostra entre o código de exemplo do Microsoft para Windows 8.1.

A chave identificar cada arquivo, usei o nome do arquivo. Depois que o método de carregamento assíncrono em PrivateFontFileLoader for concluído, o programa de CenteredGlyphDump Obtém esses nomes de arquivo para o ListBox. É por isso que apenas os nomes dos arquivos são exibidos em Figura 4. O programa é ignorante dos nomes de família de fonte associados a cada arquivo.

De personagens de glifos

Claro, exibindo o texto referenciando glifos está bem se você sabe exatamente o que glifos que você precisa, mas você pode exibir caracteres Unicode normais usando DrawGlyphRun?

Você pode, porque o IDWriteFontFace tem um método GetGlyphIndices que converte códigos de caracteres para índices de glifo para o arquivo de fonte específico. Fazendo isso, ele pega o glifo padrão para cada código de caractere, assim você não terá qualquer das alternativas chiques.

Mas os códigos de caracteres que você passar para GetGlyphIndices estão em uma forma talvez única em todas as janelas. Em vez de caracteres de 16 bits códigos (como é o caso quando você normalmente está trabalhando com seqüências de caracteres Unicode), você precisa criar uma matriz de códigos de caracteres de 32 bits. Como sabe, Unicode é na verdade um personagem de 21 bits definido, mas comumente, caracteres são armazenados como valores de 16 bits (chamados UTF-16), que significa que alguns personagens compõem dois valores de 16 bits. Mas GetGlyphIndices quer valores de 32 bits. A menos que sua seqüência de caracteres tem caracteres com códigos acima 0xFFFF, você pode simplesmente transferir valores de um array para outro.

Se você está lidando com caracteres normais do alfabeto latino, você também pode assumir que há uma correspondência exacta entre caracteres e glifos. Caso contrário, você talvez precise criar uma matriz de saída maior para receber os índices.

Esta técnica simples é demonstrada pelo projecto HelloGlyphRun. Figura 5 mostra o código que carrega um arquivo de fonte e define uma estrutura DWRITE_GLYPH_RUN. O método de atualização ajusta os deslocamentos de glifo para alcançar um tipo de ondulação efeito do texto.

Figura 5-definição de um DWRITE_GLYPH_RUN de uma cadeia de caracteres

// Convert string to glyph indices
std::wstring str = L"Hello, Glyph Run!";
uint32 glyphCount = str.length();
std::vector<uint32> str32(glyphCount);
for (uint32 i = 0; i < glyphCount; i++)
     str32[i] = str[i];
m_glyphIndices = std::vector<uint16>(glyphCount);
m_fontFace->GetGlyphIndices(str32.data(), glyphCount, m_glyphIndices.data());
// Allocate array for offsets (set during Update)
m_glyphOffsets = std::vector<DWRITE_GLYPH_OFFSET>(glyphCount);
// Get output bounds
Windows::Foundation::Size outputBounds = m_deviceResources->GetOutputBounds();
// Define fields of DWRITE_GLYPH_RUN structure
m_glyphRun.fontFace = m_fontFace.Get();
m_glyphRun.fontEmSize = outputBounds.Width / 8; // Empirical
m_glyphRun.glyphCount = glyphCount;
m_glyphRun.glyphIndices = m_glyphIndices.data();
m_glyphRun.glyphAdvances = nullptr;
m_glyphRun.glyphOffsets = m_glyphOffsets.data();
m_glyphRun.isSideways = false;
m_glyphRun.bidiLevel = 0;

Embora você provavelmente estará usando DrawGlyphRun somente com arquivos de fonte que você está intimamente familiarizado com, é possível determinar que tipo de glifos estão contidos em um arquivo de fonte específico em tempo de execução. IDWriteFontFace define um método TryGetFontTable que acessa tabelas no arquivo OpenFont. Use uma marca de "cmap" para a tabela de caracteres-para-glyph e "GSUB" para a tabela de substituição de glifo, mas esteja preparado para passar muitas horas excruciantes com a especificação de OpenType para ler essas tabelas com êxito.

Glifo é executado usando fontes de sistema

DrawGlyphRun só é bom para arquivos de fonte que você fornecer a mesmo? A princípio parece que sim, mas você pode usá-lo com fontes do sistema também. Aqui está o processo: Use o método de GetSystemFontCollection de IDWriteFactory para obter um objeto IDWriteFontCollection. Esse objeto permite que você encontre todos os nomes de família associados com as fontes instaladas no sistema. O método GetFontFamily de IDWriteFontCollection retorna um objeto do tipo IDWriteFontFamily. Daí, você pode chamar GetMatchingFonts ou GetFirstMatchingFont para combinar a família de fontes com itálico, negrito e estiramento atributos para obter um IDWriteFont.

Uma vez que você tenha um objeto de IDWriteFont, chamada CreateFontFace para obter um objeto IDWriteFontFace. Isso é o mesmo tipo de objeto obtido CreateFontFace nos programas anteriores! Daquele objeto pode começar a criação de uma estrutura DWRITE_GLYPH_RUN para DrawGlyphRun.

Isso é demonstrado no projeto SystemFontGlyphs. O projeto usa o GetSystemFontCollection em sua classe de DirectXPage para preencher um ListBox com os nomes de família de fonte do sistema. Quando um item é selecionado, um objeto IDWriteFontFace é derivado que é passado para o processador.

A classe SystemFontGlyphsRenderer cria uma estrutura DWRITE_GLYPH_RUN baseada no texto "Annoying vibratório efeito de texto." O método de atualização é então obrigado a definir os valores da matriz de deslocamentos de glifo para números aleatórios entre -3 e 3, fazendo-a parecer como se todos os caracteres da seqüência de caracteres de texto independente estão vibrando.

Não parece ser muita diferença conceitual entre IDWriteFont e IDWriteFontFace, exceto que IDWriteFont sempre representa uma fonte que não é parte de uma coleção de fontes (tais como a coleção de fontes do sistema) quando a necessidade de IDWriteFontFace. IDWriteFontCollection tem um GetFontFromFontFace método que aceita um IDWriteFontFace e retorna o correspondente IDWriteFont, mas funciona somente se o arquivo de fonte associado com o IDWriteFontFace é parte da coleção de fonte.

Coleções fonte personalizada

Agora você viu como usar DrawGlyphRun com arquivos de fonte que carrega o seu aplicativo, bem como com fontes do sistema. É possível usar os métodos de saída de texto regulares (DrawText e DrawTextLayout) com seus próprios arquivos de fonte?

Sim, ele é. Você vai se lembrar que tanto DrawText e DrawTextLayout exigem um objeto IDWriteTextFormat. Você cria esta usando o método de CreateTextFormat de IDWriteFactory, especificando um nome de família de fonte e uma coleção de fontes.

Normalmente, você definir esse argumento de coleção de fonte para nullptr para indicar as fontes do sistema. Mas você também pode criar uma coleção de fontes personalizado chamando o método CreateCustomFontCollection de IDWriteFactory. Você precisará fornecer a sua própria classe que implementa a interface IDWriteFontCollectionLoader e outra classe que implementa IDWriteFontFileEnumerator.

Isso é demonstrado no programa ResourceFontLayout. O programa também inclui as implementações das interfaces IDWriteFontFileLoader e IDWriteFontFileStream de Centered­GlyphDump. Quando você obter a lista de famílias de fontes da coleção fonte personalizada, você observará essa fonte múltiplos arquivos às vezes são consolidados em uma família de fonte única.

O prémio no fundo da caixa

Neste ponto, a importância do IDWriteFontFace deve ser evidente. Você pode criar um objeto de IDWriteFontFace de duas direções: ou diretamente de um arquivo de fonte, ou escolhendo uma fonte particular de uma coleção de fontes. Então você esta IDWriteFontFace em uma estrutura DWRITE_GLYPH_RUN de referência, ou usá-lo para obter métricas de glifo ou para acessar tabelas no arquivo fonte.

IDWriteFontFace também define um método chamado GetGlyphRun­estrutura de tópicos. Os argumentos para esse método são muito semelhantes como os campos da estrutura DWRITE_GLYPH_RUN, mas um argumento adicional é um IDWriteGeometrySink, que é o mesmo que um ID2D1SimplifiedGeometrySink.

Isto significa que você pode converter uma seqüência de caracteres de texto para um ID2D1PathGeometry e em seguida processar e manipular a geometria no que maneira você quer. Figura 6 é um screenshot do programa OutlinedCharacters que mostra uma geometria de caractere que foi traçada e preenchida; a mesma geometria processada com um estilo pontilhado (que está animado para fazer os pontos viajar os caracteres); e a geometria ampliada e delineado, com efeito, delineando os contornos.

The OutlinedCharacters Program
Figura 6 o programa de OutlinedCharacters

E só estou começando.

Charles Petzold é um colaborador de longa data de MSDN Magazine e autor de "Programação Windows, 6ª edição" (o ' Reilly Media, 2012), um livro sobre como escrever aplicativos para Windows 8. Seu site é charlespetzold.com.

Agradecemos aos seguintes especialistas técnicos da Microsoft pela revisão deste artigo: Jim Galasyn e Justin Panian