Panoramica di DWriteCore
DWriteCore è l'implementazione SDK per app di Windows di DirectWrite (DirectWrite è l'API DirectX per il rendering di testo di alta qualità, i tipi di carattere struttura indipendenti dalla risoluzione e il supporto completo di testo e layout Unicode). DWriteCore è una forma di DirectWrite eseguita nelle versioni di Windows fino a Windows 10, versione 1809 (10.0; Build 17763). DWriteCore implementa la stessa API di DirectWrite, con alcune aggiunte descritte in questo argomento.
Questo argomento introduttivo descrive cos'è DWriteCore e illustra come installarlo nell'ambiente di sviluppo e nel programma con esso.
Per un'app che usa già DirectWrite, il passaggio a DWriteCore richiede modifiche minime:
- Aggiungere un riferimento al pacchetto SDK per app di Windows.
- Includere
dwrite_core.h
invece didwrite_3.h
. - Collegamento
DWriteCore.lib
invece diDWrite.lib
. - Chiamare DWriteCoreCreateFactory anziché DWriteCreateFactory.
In cambio, l'app ottiene i vantaggi di SDK per app di Windows, ovvero l'accesso alle API e alle funzionalità più recenti indipendentemente dalla versione di Windows in esecuzione del cliente.
Suggerimento
Per le descrizioni e i collegamenti ai componenti DirectX nello sviluppo attivo, vedere il post di blog DirectX Landing Page(Pagina di destinazione DirectX).
Proposta di valore di DWriteCore
DirectWrite supporta una vasta gamma di funzionalità che lo rende lo strumento di rendering dei tipi di carattere preferito in Windows per la maggior parte delle app, sia tramite chiamate dirette che tramite Direct2D. DirectWrite include un sistema di layout di testo indipendente dal dispositivo, un rendering di testo Microsoft ClearType di alta qualità, testo con accelerazione hardware, testo multiformato, funzionalità di tipografia OpenType® avanzate, supporto per lingue estese e layout e rendering compatibili con GDI. DirectWrite è disponibile da Windows Vista SP2 e si è evoluto nel corso degli anni per includere funzionalità più avanzate, ad esempio tipi di carattere variabili, che consentono di applicare stili, pesi e altri attributi a un tipo di carattere con una sola risorsa carattere.
A causa della lunga durata di DirectWrite, tuttavia, i progressi nello sviluppo hanno teso a lasciare indietro le versioni precedenti di Windows. Inoltre, DirectWrite lo stato in quanto la tecnologia di rendering del testo principale è limitata solo a Windows, lasciando le applicazioni multipiattaforma per scrivere il proprio stack di rendering del testo o per basarsi su soluzioni di terze parti.
DWriteCore risolve i problemi fondamentali della funzionalità di versione orfana e compatibilità multipiattaforma rimuovendo la libreria dal sistema e puntando a tutti i possibili endpoint supportati. A tale scopo, È stato integrato DWriteCore in SDK per app di Windows.
Il valore principale che DWriteCore offre, come sviluppatore, in SDK per app di Windows è che fornisce l'accesso a molte funzionalità (e alla fine tutte) DirectWrite. Tutte le funzionalità di DWriteCore funzioneranno allo stesso modo in tutte le versioni di livello inferiore senza alcuna disparità riguardo alle funzionalità che potrebbero funzionare su quali versioni.
App demo DWriteCore- DWriteCoreGallery
DWriteCore viene dimostrato tramite l'app di esempio DWriteCoreGallery , disponibile per il download e lo studio.
Introduzione a DWriteCore
DWriteCore fa parte del SDK per app di Windows. Questa sezione descrive come configurare l'ambiente di sviluppo per la programmazione con DWriteCore.
Installare gli strumenti per il SDK per app di Windows
Vedere Installare gli strumenti per il SDK per app di Windows.
Creare un nuovo progetto
In Visual Studio creare un nuovo progetto dal modello di progetto App vuota, In pacchetto (WinUI 3 in Desktop). È possibile trovare il modello di progetto scegliendo il linguaggio C++; platform: SDK per app di Windows; tipo di progetto: Desktop.
Per altre info, vedi Modelli di progetto per WinUI 3.
Installare il pacchetto NuGet Microsoft.ProjectReunion.DWrite
In Visual Studio fare clic su Project>Manage NuGet Packages ...>Sfoglia, digita o incolla Microsoft.ProjectReunion.DWrite nella casella di ricerca, seleziona l'elemento nei risultati della ricerca e quindi fai clic su Installa per installare il pacchetto per il progetto.
In alternativa, iniziare con l'app di esempio DWriteCoreGallery
In alternativa, è possibile programmare con DWriteCore iniziando con il progetto di app di esempio DWriteCoreGallery e basando lo sviluppo su tale progetto. È quindi possibile rimuovere qualsiasi codice sorgente esistente (o file) da tale progetto di esempio e aggiungere qualsiasi nuovo codice sorgente (o file) al progetto.
Usare DWriteCore nel progetto
Per altre info sulla programmazione con DWriteCore, vedi la sezione Programmazione con DWriteCore più avanti in questo argomento.
Fasi di rilascio di DWriteCore
La conversione di DirectWrite in DWriteCore è un progetto sufficientemente grande da estendersi su più cicli di rilascio di Windows. Il progetto è suddiviso in fasi, ognuna delle quali corrisponde a un blocco di funzionalità distribuite in una versione.
Funzionalità nella versione corrente di DWriteCore
DWriteCore fa parte del SDK per app di Windows. Contiene gli strumenti di base che gli sviluppatori devono usare DWriteCore, incluse le funzionalità seguenti.
- Enumerazione font.
- API del tipo di carattere.
- Modellatura.
- API di rendering di basso livello. Questa operazione è parziale nella fase corrente: DWriteCore non interagisce con Direct2D, ma è possibile usare IDWriteGlyphRunAnalysis e IDWriteBitmapRenderTarget.
- Funzionalità di layout di testo di base.
- API per il rendering del testo.
- Destinazione di rendering bitmap.
- Tipi di carattere a colori.
- Ottimizzazioni varie (pulizia della cache dei tipi di carattere, caricatore di tipi di carattere in memoria e così via).
- Supporto per la sottolineatura: vedere IDWriteTextLayout::GetUnderline e IDWriteTextLayout::SetUnderline.
- Supporto per il barrato: vedere IDWriteTextLayout::GetStrikethrough e IDWriteTextLayout::SetStrikethrough.
- Supporto per il testo verticale tramite IDWriteTextLayout. VedereTesto verticale.
- Vengono implementati tutti i metodi delle interfacce IDWriteTextAnalyzer e IDWriteTextAnalyzer1 .
Una funzionalità banner è tipi di carattere a colori. I tipi di carattere a colori consentono di eseguire il rendering dei tipi di carattere con funzionalità di colore più sofisticate oltre a semplici colori singoli. Ad esempio, i tipi di carattere a colori consentono di eseguire il rendering dei tipi di carattere emoji e icona della barra degli strumenti (quest'ultimo viene usato da Office, ad esempio). I tipi di carattere a colori sono stati introdotti per la prima volta in Windows 8.1, ma la funzionalità è stata notevolmente ampliata in Windows 10 versione 1607 (aggiornamento dell'anniversario).
Le operazioni di pulizia della cache dei tipi di carattere e del caricatore dei tipi di carattere in memoria consentono un caricamento più rapido dei tipi di carattere e dei miglioramenti della memoria.
Con queste funzionalità, è possibile iniziare immediatamente a sfruttare alcune delle funzionalità di base moderne di DirectWrite, ad esempio i tipi di carattere variabili. I tipi di carattere variabili sono una delle funzionalità più importanti per DirectWrite clienti.
L'invito all'utente come sviluppatore di DirectWrite
DWriteCore, insieme ad altri componenti SDK per app di Windows, verrà sviluppato con apertura al feedback degli sviluppatori. È consigliabile iniziare a esplorare DWriteCore e fornire informazioni dettagliate o richieste per lo sviluppo di funzionalità nel repository GitHub SDK per app di Windows.
Programmazione con DWriteCore
Proprio come con DirectWrite, si programma con DWriteCore tramite l'API COM-light, tramite l'interfaccia IDWriteFactory.
Per usare DWriteCore, è necessario includere il dwrite_core.h
file di intestazione.
// pch.h
...
// DWriteCore header file.
#include <dwrite_core.h>
Il dwrite_core.h
file di intestazione definisce innanzitutto il token DWRITE_CORE e quindi include il dwrite_3.h
file di intestazione. Il token DWRITE_CORE è importante, perché indirizza tutte le intestazioni incluse successivamente per rendere disponibili tutte le API DirectWrite. Dopo aver incluso dwrite_core.h
il progetto, è possibile procedere e scrivere codice, compilare ed eseguire.
API nuove o diverse per DWriteCore
La superficie dell'API DWriteCore è in gran parte uguale a quella per DirectWrite. Tuttavia, al momento ci sono un numero ridotto di nuove API che si trovano solo in DWriteCore.
Creare un oggetto factory
La funzione gratuita DWriteCoreCreateFactory crea un oggetto factory usato per la successiva creazione di singoli oggetti DWriteCore.
DWriteCoreCreateFactory è funzionalmente uguale alla funzione DWriteCreateFactory esportata dalla versione di sistema di DirectWrite. La funzione DWriteCore ha un nome diverso per evitare ambiguità.
Creare un oggetto factory con restrizioni
L'enumerazione DWRITE_FACTORY_TYPE ha una nuova costante, DWRITE_FACTORY_TYPE_ISOLATED2, che indica una factory con restrizioni. Una fabbrica con restrizioni è più bloccata rispetto a una fabbrica isolata. Non interagisce in alcun modo con una cache dei tipi di carattere interprocesso o persistente. Inoltre, la raccolta di tipi di carattere di sistema restituita da questa factory include solo tipi di carattere noti. Ecco come usare DWRITE_FACTORY_TYPE_ISOLATED2 per creare un oggetto factory con restrizioni quando si chiama la funzione gratuita 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 si passa DWRITE_FACTORY_TYPE_ISOLATED2 a una versione precedente di DirectWrite che non la supporta, DWriteCreateFactory restituisce E_INVALIDARG.
Disegno di glifi in una bitmap di memoria di sistema
DirectWrite ha un'interfaccia di destinazione di rendering bitmap che supporta il rendering dei glifi in una bitmap nella memoria di sistema. Attualmente, tuttavia, l'unico modo per accedere ai dati pixel sottostanti consiste nell'passare attraverso GDI e quindi l'API non è utilizzabile multipiattaforma. Questo è facilmente risolto aggiungendo un metodo per recuperare i dati pixel.
DWriteCore introduce quindi l'interfaccia IDWriteBitmapRenderTarget2 e il relativo metodo IDWriteBitmapRenderTarget2::GetBitmapData. Questo metodo accetta un parametro di tipo (puntatore a) DWRITE_BITMAP_DATA_BGRA32, ovvero un nuovo struct.
L'applicazione crea una destinazione di rendering bitmap chiamando IDWriteGdiInterop::CreateBitmapRenderTarget. In Windows, una destinazione di rendering bitmap incapsula un controller di dominio di memoria GDI con una bitmap indipendente dal dispositivo GDI selezionata. IDWriteBitmapRenderTarget::D rawGlyphRun esegue il rendering degli glifi nel DIB. DirectWrite esegue il rendering dei glifi stessi senza passare attraverso GDI. L'applicazione può quindi ottenere HDC dalla destinazione di rendering bitmap e usare BitBlt per copiare i pixel in una finestra HDC.
Nelle piattaforme non Windows l'applicazione può comunque creare una destinazione di rendering bitmap, ma incapsula semplicemente una matrice di memoria di sistema senza HDC e nessun DIB . Senza un HDC, è necessario avere un altro modo per ottenere i pixel bitmap dell'applicazione in modo che possa copiarli o usarli in caso contrario. Anche in Windows, a volte è utile ottenere i dati pixel effettivi e viene illustrato il modo corrente per farlo nell'esempio di codice seguente.
// 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);
}
Altre differenze api tra DWriteCore e DirectWrite
Esistono alcune API che sono solo stub o si comportano in modo leggermente diverso nelle piattaforme non Windows. Ad esempio, IDWriteGdiInterop::CreateFontFaceFromHdc restituisce E_NOTIMPL nelle piattaforme non Windows, poiché non esiste alcuna cosa come HDC senza GDI.
Infine, ci sono alcune altre API di Windows che vengono in genere usate insieme a DirectWrite (Direct2D è un esempio notevole). Attualmente, tuttavia, Direct2D e DWriteCore non interoperabilità. Ad esempio, se si crea un IDWriteTextLayout usando DWriteCore e lo si passa a D2D1RenderTarget::D rawTextLayout, tale chiamata avrà esito negativo.