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 di dwrite_3.h.
  • Collegamento DWriteCore.lib invece di DWrite.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.

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.hil 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.