Visão geral do DWriteCore
DWriteCore é a implementação SDK do Aplicativo Windows de DirectWrite (DirectWrite é a API do DirectX para renderização de texto de alta qualidade, fontes de estrutura de tópicos independentes de resolução e suporte completo de texto e layout Unicode). DWriteCore é uma forma de DirectWrite que é executada em versões do Windows até Windows 10, versão 1809 (10.0; Build 17763). O DWriteCore implementa a mesma API que DirectWrite, com algumas adições, conforme descrito neste tópico.
Este tópico introdutório descreve o que é DWriteCore e mostra como instalá-lo em seu ambiente de desenvolvimento e programa com ele.
Para um aplicativo que já usa DirectWrite, alternar para DWriteCore requer alterações mínimas:
- Adicione uma referência ao pacote SDK do Aplicativo Windows.
- Inclua
dwrite_core.h
em vez dedwrite_3.h
. - Vincule
DWriteCore.lib
em vez deDWrite.lib
. - Chame DWriteCoreCreateFactory em vez de DWriteCreateFactory.
Em troca, o aplicativo obtém os benefícios de SDK do Aplicativo Windows, ou seja, acesso às APIs e funcionalidades mais recentes, independentemente de qual versão do Windows seu cliente está executando.
Dica
Para obter descrições e links para componentes do DirectX no desenvolvimento ativo, consulte a postagem no blog Página de Aterrissagem do DirectX.
A proposta de valor de DWriteCore
DirectWrite em si dá suporte a uma rica variedade de recursos que o torna a ferramenta de renderização de fontes escolhida no Windows para a maioria dos aplicativos, seja por meio de chamadas diretas ou por meio do Direct2D. DirectWrite inclui um sistema de layout de texto independente do dispositivo, renderização de texto Microsoft ClearType de sub pixel de alta qualidade, texto acelerado por hardware, texto de vários formatos, recursos avançados de tipografia OpenType®, suporte a idioma largo e layout e renderização compatíveis com GDI. DirectWrite está disponível desde o Windows Vista SP2 e evoluiu ao longo dos anos para incluir recursos mais avançados, como fontes variáveis, o que permite aplicar estilos, pesos e outros atributos a uma fonte com apenas um recurso de fonte.
Devido ao longo tempo de vida de DirectWrite, no entanto, os avanços no desenvolvimento tendem a deixar versões mais antigas do Windows para trás. Além disso, DirectWrite status como a tecnologia de renderização de texto premier é limitada apenas ao Windows, deixando aplicativos multiplataforma para escrever sua própria pilha de renderização de texto ou para depender de soluções de terceiros.
O DWriteCore resolve os problemas fundamentais da compatibilidade de versão órfã e multiplataforma removendo a biblioteca do sistema e direcionando todos os possíveis pontos de extremidade com suporte. Para isso, integramos o DWriteCore ao SDK do Aplicativo Windows.
O valor principal que dWriteCore fornece a você, como desenvolvedor, em SDK do Aplicativo Windows é que ele fornece acesso a muitos (e, eventualmente, a todos) recursos DirectWrite. Todos os recursos do DWriteCore funcionarão da mesma forma em todas as versões de nível inferior sem qualquer disparidade em relação a quais recursos podem funcionar em quais versões.
O aplicativo de demonstração DWriteCore — DWriteCoreGallery
DWriteCore é demonstrado por meio do aplicativo de exemplo DWriteCoreGallery , que agora está disponível para download e estudo.
Introdução ao DWriteCore
DWriteCore faz parte do SDK do Aplicativo Windows. Esta seção descreve como configurar seu ambiente de desenvolvimento para programação com DWriteCore.
Instalar ferramentas para o SDK do Aplicativo Windows
Confira Instalar ferramentas para o SDK do Aplicativo Windows.
Criar um novo projeto
No Visual Studio, crie um novo projeto do modelo de projeto Aplicativo em Branco, Empacotado (WinUI 3 na Área de Trabalho). Você pode encontrar esse modelo de projeto escolhendo a linguagem: C++; platform: SDK do Aplicativo Windows; tipo de projeto: Desktop.
Para obter mais informações, consulte Modelos de projeto para WinUI 3.
Instalar o pacote NuGet Microsoft.ProjectReunion.DWrite
No Visual Studio, clique em Projeto>Gerenciar Pacotes NuGet...>Procure, digite ou cole Microsoft.ProjectReunion.DWrite na caixa de pesquisa, selecione o item nos resultados da pesquisa e clique em Instalar para instalar o pacote desse projeto.
Como alternativa, comece com o aplicativo de exemplo DWriteCoreGallery
Como alternativa, você pode programar com DWriteCore começando com o projeto de aplicativo de exemplo DWriteCoreGallery e basear seu desenvolvimento nesse projeto. Em seguida, você pode se sentir à vontade para remover qualquer código-fonte existente (ou arquivos) desse projeto de exemplo e adicionar qualquer novo código-fonte (ou arquivos) ao projeto.
Usar DWriteCore em seu projeto
Para obter mais informações sobre programação com DWriteCore, consulte a seção Programação com DWriteCore mais adiante neste tópico.
As fases de lançamento do DWriteCore
Portar DirectWrite para DWriteCore é um projeto suficientemente grande para abranger vários ciclos de lançamento do Windows. Esse projeto é dividido em fases, cada uma das quais corresponde a uma parte da funcionalidade entregue em uma versão.
Recursos na versão atual do DWriteCore
DWriteCore faz parte do SDK do Aplicativo Windows. Ele contém as ferramentas básicas que você, como desenvolvedor, precisa consumir DWriteCore, incluindo os recursos a seguir.
- Enumeração de fonte.
- API de fonte.
- Moldar.
- APIs de renderização de baixo nível. Isso é parcial na fase atual– DWriteCore não interopera com Direct2D, mas você pode usar IDWriteGlyphRunAnalysis e IDWriteBitmapRenderTarget.
- Funcionalidade básica de layout de texto.
- APIs de renderização de texto.
- Destino de renderização de bitmap.
- Fontes de cores.
- Otimizações diversas (limpeza do cache de fontes, carregador de fonte na memória e assim por diante).
- Suporte para sublinhado— consulte IDWriteTextLayout::GetUnderline e IDWriteTextLayout::SetUnderline.
- Suporte para tachado — consulte IDWriteTextLayout::GetStrikethrough e IDWriteTextLayout::SetStrikethrough.
- Suporte para texto vertical por meio de IDWriteTextLayout – consulte Texto vertical.
- Todos os métodos das interfaces IDWriteTextAnalyzer e IDWriteTextAnalyzer1 são implementados.
Um recurso de faixa são fontes de cores. Fontes de cores permitem que você renderize suas fontes com funcionalidade de cores mais sofisticada além de cores simples. Por exemplo, fontes de cores são o que alimenta a capacidade de renderizar fontes de ícone de emoji e barra de ferramentas (a última das quais é usada pelo Office, por exemplo). As fontes de cores foram introduzidas pela primeira vez em Windows 8.1, mas o recurso foi fortemente expandido no Windows 10, versão 1607 (Atualização de Aniversário).
O trabalho na limpeza do cache de fontes e no carregador de fontes na memória permite o carregamento mais rápido de fontes e melhorias de memória.
Com esses recursos, você pode começar imediatamente a aproveitar algumas das funcionalidades básicas modernas do DirectWrite, como fontes variáveis. Fontes variáveis são um dos recursos mais importantes para DirectWrite clientes.
Nosso convite para você como desenvolvedor DirectWrite
O DWriteCore, juntamente com outros componentes SDK do Aplicativo Windows, será desenvolvido com abertura para comentários dos desenvolvedores. Convidamos você a começar a explorar o DWriteCore e a fornecer insights ou solicitações sobre o desenvolvimento de recursos em nosso repositório SDK do Aplicativo Windows GitHub.
Programação com DWriteCore
Assim como acontece com DirectWrite, você programa com DWriteCore por meio de sua API com luz COM, por meio da interface IDWriteFactory.
Para usar DWriteCore, é necessário incluir o dwrite_core.h
arquivo de cabeçalho.
// pch.h
...
// DWriteCore header file.
#include <dwrite_core.h>
O dwrite_core.h
arquivo de cabeçalho primeiro define o token DWRITE_CORE e, em seguida, inclui o dwrite_3.h
arquivo de cabeçalho. O token de DWRITE_CORE é importante, pois direciona todos os cabeçalhos incluídos posteriormente para disponibilizar todas as APIs de DirectWrite para você. Depois que o projeto tiver incluído dwrite_core.h
, você poderá continuar e escrever código, compilar e executar.
APIs novas ou diferentes para DWriteCore
A superfície da API DWriteCore é praticamente a mesma para DirectWrite. Mas há um pequeno número de novas APIs que estão apenas em DWriteCore no momento.
Criar um objeto de fábrica
A função livre DWriteCoreCreateFactory cria um objeto de fábrica usado para a criação subsequente de objetos DWriteCore individuais.
DWriteCoreCreateFactory é funcionalmente igual à função DWriteCreateFactory exportada pela versão do sistema de DirectWrite. A função DWriteCore tem um nome diferente para evitar ambiguidade.
Criar um objeto de fábrica restrito
A enumeração DWRITE_FACTORY_TYPE tem uma nova constante DWRITE_FACTORY_TYPE_ISOLATED2, indicando uma fábrica restrita. Uma fábrica restrita é mais bloqueada do que uma fábrica isolada. Ele não interage com um processo cruzado nem com um cache de fonte persistente de forma alguma. Além disso, a coleção de fontes do sistema retornada dessa fábrica inclui apenas fontes conhecidas. Veja como você pode usar DWRITE_FACTORY_TYPE_ISOLATED2 para criar um objeto de fábrica restrito ao chamar a função livre DWriteCoreCreateFactory .
// Create a factory that doesn't interact with any cross-process nor
// persistent cache state.
winrt::com_ptr<::IDWriteFactory7> spFactory;
winrt::check_hresult(
::DWriteCoreCreateFactory(
DWRITE_FACTORY_TYPE_ISOLATED2,
__uuidof(spFactory),
reinterpret_cast<IUnknown**>(spFactory.put())
)
);
Se você passar DWRITE_FACTORY_TYPE_ISOLATED2 para uma versão mais antiga do DirectWrite que não dá suporte a ela, DWriteCreateFactory retornará E_INVALIDARG.
Desenhando glifos em um bitmap de memória do sistema
DirectWrite tem uma interface de destino de renderização de bitmap que dá suporte à renderização de glifos em um bitmap na memória do sistema. No entanto, atualmente, a única maneira de obter acesso aos dados de pixel subjacentes é passar pela GDI e, portanto, a API não é utilizável entre plataformas. Isso é facilmente remediado adicionando um método para recuperar os dados de pixel.
E assim, DWriteCore introduz a interface IDWriteBitmapRenderTarget2 e seu método IDWriteBitmapRenderTarget2::GetBitmapData. Esse método usa um parâmetro do tipo (ponteiro para) DWRITE_BITMAP_DATA_BGRA32, que é um novo struct.
Seu aplicativo cria um destino de renderização de bitmap chamando IDWriteGdiInterop::CreateBitmapRenderTarget. No Windows, um destino de renderização de bitmap encapsula um DC de memória GDI com um DIB (bitmap independente de dispositivo) GDI selecionado nele. IDWriteBitmapRenderTarget::D rawGlyphRun renderiza glifos para o DIB. DirectWrite renderiza os próprios glifos sem passar pela GDI. Em seguida, seu aplicativo pode obter o HDC do destino de renderização de bitmap e usar BitBlt para copiar os pixels para um HDC de janela.
Em plataformas não Windows, seu aplicativo ainda pode criar um destino de renderização de bitmap, mas simplesmente encapsula uma matriz de memória do sistema sem HDC e sem DIB. Sem um HDC, precisa haver outra maneira de seu aplicativo obter os pixels de bitmap para que ele possa copiá-los ou usá-los de outra forma. Mesmo no Windows, às vezes é útil obter os dados reais de pixel e mostramos a maneira atual de fazer isso no exemplo de código abaixo.
// pch.h
#pragma once
#include <windows.h>
#include <Unknwn.h>
#include <winrt/Windows.Foundation.h>
// WinMain.cpp
#include "pch.h"
#include <dwrite_core.h>
#pragma comment(lib, "Gdi32")
class TextRenderer
{
DWRITE_BITMAP_DATA_BGRA32 m_targetBitmapData;
public:
void InitializeBitmapData(winrt::com_ptr<IDWriteBitmapRenderTarget> const& renderTarget)
{
// Query the bitmap render target for the new interface.
winrt::com_ptr<IDWriteBitmapRenderTarget2> renderTarget2;
renderTarget2 = renderTarget.try_as<IDWriteBitmapRenderTarget2>();
if (renderTarget2)
{
// IDWriteBitmapRenderTarget2 exists, so we can get the bitmap the easy way.
winrt::check_hresult(renderTarget2->GetBitmapData(OUT & m_targetBitmapData));
}
else
{
// We're using an older version that doesn't implement IDWriteBitmapRenderTarget2,
// so we have to get the bitmap by going through GDI. First get the bitmap handle.
HDC hdc = renderTarget->GetMemoryDC();
winrt::handle dibHandle{ GetCurrentObject(hdc, OBJ_BITMAP) };
winrt::check_bool(bool{ dibHandle });
// Call a GDI function to fill in the DIBSECTION structure for the bitmap.
DIBSECTION dib;
winrt::check_bool(GetObject(dibHandle.get(), sizeof(dib), &dib));
m_targetBitmapData.width = dib.dsBm.bmWidth;
m_targetBitmapData.height = dib.dsBm.bmHeight;
m_targetBitmapData.pixels = static_cast<uint32_t*>(dib.dsBm.bmBits);
}
}
};
int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
{
TextRenderer textRenderer;
winrt::com_ptr<IDWriteBitmapRenderTarget> renderTarget{ /* ... */ };
textRenderer.InitializeBitmapData(renderTarget);
}
Outras diferenças de API entre DWriteCore e DirectWrite
Há algumas APIs que são apenas stubs ou se comportam de forma um pouco diferente em plataformas que não são do Windows. Por exemplo, IDWriteGdiInterop::CreateFontFaceFromHdc retorna E_NOTIMPL em plataformas não Windows, pois não existe um HDC sem GDI.
E, por fim, há certas outras APIs do Windows que normalmente são usadas junto com DirectWrite (Direct2D sendo um exemplo notável). No entanto, atualmente, Direct2D e DWriteCore não interoperam. Por exemplo, se você criar um IDWriteTextLayout usando DWriteCore e passá-lo para D2D1RenderTarget::D rawTextLayout, essa chamada falhará.