Übersicht über DWriteCore

DWriteCore ist die Windows App SDK Implementierung von DirectWrite (DirectWrite ist die DirectX-API für hochwertiges Textrendering, auflösungsunabhängige Gliederungsschriftarten und vollständige Unicode-Text- und Layoutunterstützung). DWriteCore ist eine Form von DirectWrite, die unter Windows-Versionen bis Windows 10, Version 1809 (10.0; Build 17763). DWriteCore implementiert dieselbe API wie DirectWrite, mit einigen Ergänzungen, wie in diesem Thema beschrieben.

In diesem einführenden Thema wird beschrieben, was DWriteCore ist, und es wird gezeigt, wie Sie es in Ihrer Entwicklungsumgebung und ihrem Programm damit installieren.

Für eine App, die bereits DirectWrite verwendet, sind minimale Änderungen erforderlich, um zu DWriteCore zu wechseln:

  • Fügen Sie einen Verweis auf das Windows App SDK-Paket hinzu.
  • Schließen Sie dwrite_core.h anstelle von dwrite_3.hein.
  • Link DWriteCore.lib anstelle von DWrite.lib.
  • Rufen Sie DWriteCoreCreateFactory anstelle von DWriteCreateFactory auf.

Im Gegenzug erhält die App die Vorteile von Windows App SDK– nämlich Zugriff auf die neuesten APIs und Funktionen, unabhängig davon, welche Version von Windows Ihr Kunde ausführt.

Tipp

Beschreibungen und Links zu DirectX-Komponenten in der aktiven Entwicklung finden Sie im Blogbeitrag DirectX Landing Page.

Das Wertversprechen von DWriteCore

DirectWrite selbst unterstützt ein umfangreiches Feature-Array, das es zum Tool zum Rendern von Schriftarten der Wahl unter Windows für die meisten Apps macht – sei es durch direkte Aufrufe oder über Direct2D. DirectWrite umfasst ein geräteunabhängiges Textlayoutsystem, hochwertiges Microsoft ClearType-Textrendering unter Pixeln, hardwarebeschleunigten Text, Multiformattext, erweiterte OpenType-Typografiefeatures®, breite Sprachunterstützung sowie GDI-kompatibles Layout und Rendering. DirectWrite ist seit Windows Vista SP2 verfügbar und hat sich im Laufe der Jahre weiterentwickelt, um erweiterte Features wie variable Schriftarten zu enthalten, mit denen Sie Formatvorlagen, Gewichtungen und andere Attribute auf eine Schriftart mit nur einer Schriftartressource anwenden können.

Aufgrund der langen Lebensdauer von DirectWrite haben fortschritte in der Entwicklung jedoch tendenziell ältere Versionen von Windows hinter sich gelassen. Darüber hinaus ist die status von DirectWrite als führende Textrenderingtechnologie nur auf Windows beschränkt, sodass plattformübergreifende Anwendungen entweder einen eigenen Textrenderingstapel schreiben oder sich auf Lösungen von Drittanbietern verlassen können.

DWriteCore löst die grundlegenden Probleme des Verwaisten von Versionsfeatures und der plattformübergreifenden Kompatibilität, indem die Bibliothek aus dem System entfernt wird und alle möglichen unterstützten Endpunkte anvisiert werden. Zu diesem Zweck haben wir DWriteCore in Windows App SDK integriert.

Der primäre Wert, den DWriteCore Ihnen als Entwickler in Windows App SDK bietet, ist, dass es Zugriff auf viele (und letztendlich alle) DirectWrite Features bietet. Alle Features von DWriteCore funktionieren in allen Versionen auf der unteren Ebene gleich, ohne dass unterschiedet wird, welche Features mit welchen Versionen funktionieren können.

Die DWriteCore-Demo-App – DWriteCoreGallery

DWriteCore wird mithilfe der DWriteCoreGallery-Beispiel-App veranschaulicht, die Ihnen jetzt zum Herunterladen und Untersuchen zur Verfügung steht.

Erste Schritte mit DWriteCore

DWriteCore ist Teil des Windows App SDK. In diesem Abschnitt wird beschrieben, wie Sie Ihre Entwicklungsumgebung für die Programmierung mit DWriteCore einrichten.

Installieren von Tools für das Windows App SDK

Weitere Informationen finden Sie unter Installieren von Tools für das Windows App SDK.

Erstellen eines neuen Projekts

Erstellen Sie in Visual Studio ein neues Projekt aus der Projektvorlage Leere App, Verpackt (WinUI 3 in Desktop). Sie können diese Projektvorlage finden, indem Sie die Sprache auswählen: C++; platform: Windows App SDK; Projekttyp: Desktop.

Weitere Informationen finden Sie unter Projektvorlagen für WinUI 3.

Installieren des NuGet-Pakets Microsoft.ProjectReunion.DWrite

Klicken Sie in Visual Studio auf Projekt>NuGet-Pakete verwalten...>Navigieren Sie im Suchfeld nach Microsoft.ProjectReunion.DWrite , und wählen Sie das Element in den Suchergebnissen aus, und klicken Sie dann auf Installieren , um das Paket für dieses Projekt zu installieren.

Alternativ können Sie mit der DWriteCoreGallery-Beispiel-App beginnen.

Alternativ können Sie mit DWriteCore programmieren, indem Sie mit dem DWriteCoreGallery-Beispiel-App-Projekt beginnen und Ihre Entwicklung auf diesem Projekt basieren. Sie können dann alle vorhandenen Quellcodes (oder Dateien) aus diesem Beispielprojekt entfernen und dem Projekt neuen Quellcode (oder Dateien) hinzufügen.

Verwenden von DWriteCore in Ihrem Projekt

Weitere Informationen zur Programmierung mit DWriteCore finden Sie weiter unten in diesem Thema im Abschnitt Programmieren mit DWriteCore .

Die Releasephasen von DWriteCore

Das Portieren DirectWrite zu DWriteCore ist ein ausreichend großes Projekt, um mehrere Windows-Releasezyklen zu umfassen. Dieses Projekt ist in Phasen unterteilt, die jeweils einem Funktionsblock entsprechen, der in einem Release bereitgestellt wird.

Features in der aktuellen Version von DWriteCore

DWriteCore ist Teil des Windows App SDK. Es enthält die grundlegenden Tools, die Sie als Entwickler benötigen, um DWriteCore zu nutzen, einschließlich der folgenden Features.

Ein Bannerfeature sind Farbschriftarten. Mit Farbschriftarten können Sie Ihre Schriftarten mit komplexeren Farbfunktionen rendern, die über einfache Einzelfarben hinausgehen. Beispielsweise sind Farbschriftarten die Möglichkeit, Emoji- und Symbolleistensymbolschriftarten zu rendern (letzteres wird z. B. von Office verwendet). Farbschriftarten wurden erstmals in Windows 8.1 eingeführt, aber das Feature wurde in Windows 10, Version 1607 (Anniversary Update), stark erweitert.

Die Arbeit an der Bereinigung des Schriftartencaches und des In-Memory-Schriftartenladeprogramms ermöglichen ein schnelleres Laden von Schriftarten und Verbesserungen des Arbeitsspeichers.

Mit diesen Features können Sie sofort beginnen, einige der modernen Kernfunktionen von DirectWrite zu nutzen, z. B. variable Schriftarten. Variablenschriftarten sind eines der wichtigsten Features für DirectWrite Kunden.

Unsere Einladung an Sie als DirectWrite Entwickler

DWriteCore wird zusammen mit anderen Windows App SDK Komponenten mit Offenheit für Entwicklerfeedback entwickelt. Wir laden Sie ein, mit der Erkundung von DWriteCore zu beginnen und Einblicke oder Anforderungen zur Featureentwicklung auf unserem Windows App SDK GitHub-Repository zu geben.

Programmieren mit DWriteCore

Genau wie bei DirectWrite programmieren Sie mit DWriteCore über die COM-light-API über die IDWriteFactory-Schnittstelle.

Um DWriteCore verwenden zu können, muss die dwrite_core.h Headerdatei eingeschlossen werden.

// pch.h
...
// DWriteCore header file.
#include <dwrite_core.h>

Die dwrite_core.h Headerdatei definiert zunächst das Token DWRITE_CORE und enthält dann die dwrite_3.h Headerdatei. Das DWRITE_CORE-Token ist wichtig, da es alle nachfolgenden enthaltenen Header angibt, um Ihnen alle DirectWrite-APIs zur Verfügung zu stellen. Sobald Ihr Projekt enthalten dwrite_core.hist, können Sie fortfahren und Code schreiben, erstellen und ausführen.

Neue oder andere APIs für DWriteCore

Die Oberfläche der DWriteCore-API entspricht weitgehend der Oberfläche für DirectWrite. Es gibt jedoch eine kleine Anzahl neuer APIs, die derzeit nur in DWriteCore vorhanden sind.

Erstellen eines Factoryobjekts

Die freie Funktion DWriteCoreCreateFactory erstellt ein Factoryobjekt, das für die nachfolgende Erstellung einzelner DWriteCore-Objekte verwendet wird.

DWriteCoreCreateFactory ist funktionell identisch mit der DWriteCreateFactory-Funktion, die von der Systemversion von DirectWrite exportiert wird. Die DWriteCore-Funktion hat einen anderen Namen, um Mehrdeutigkeiten zu vermeiden.

Erstellen eines eingeschränkten Factoryobjekts

Die DWRITE_FACTORY_TYPE-Enumeration verfügt über eine neue Konstante – DWRITE_FACTORY_TYPE_ISOLATED2, die eine eingeschränkte Factory angibt. Eine eingeschränkte Factory ist stärker gesperrt als eine isolierte Factory. Es interagiert in keiner Weise mit einem prozessübergreifenden oder persistenten Schriftartencache. Darüber hinaus enthält die von dieser Factory zurückgegebene Systemschriftartauflistung nur bekannte Schriftarten. Hier erfahren Sie, wie Sie DWRITE_FACTORY_TYPE_ISOLATED2 verwenden können, um ein eingeschränktes Factoryobjekt zu erstellen, wenn Sie die kostenlose Funktion DWriteCoreCreateFactory aufrufen.

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

Wenn Sie DWRITE_FACTORY_TYPE_ISOLATED2 an eine ältere Version von DirectWrite übergeben, die sie nicht unterstützt, gibt DWriteCreateFactoryE_INVALIDARG zurück.

Zeichnen von Glyphen in eine Bitmap im Systemspeicher

DirectWrite verfügt über eine Bitmap-Renderzielschnittstelle, die das Rendern von Glyphen in eine Bitmap im Systemspeicher unterstützt. Die einzige Möglichkeit, zugriff auf die zugrunde liegenden Pixeldaten zu erhalten, besteht derzeit jedoch darin, GDI zu durchlaufen, sodass die API nicht plattformübergreifend verwendet werden kann. Dies lässt sich leicht beheben, indem Sie eine -Methode zum Abrufen der Pixeldaten hinzufügen.

Daher führt DWriteCore die IDWriteBitmapRenderTarget2-Schnittstelle und deren Methode IDWriteBitmapRenderTarget2::GetBitmapData ein. Diese Methode akzeptiert einen Parameter vom Typ (Zeiger auf) DWRITE_BITMAP_DATA_BGRA32, bei dem es sich um eine neue Struktur handelt.

Ihre Anwendung erstellt ein Bitmap-Renderziel, indem IDWriteGdiInterop::CreateBitmapRenderTarget aufgerufen wird. Unter Windows kapselt ein Bitmaprenderingziel einen GDI-Speicher-DC, in dem eine geräteunabhängige GDI-Bitmap (DEVICE-Independent Bitmap, DIB) ausgewählt ist. IDWriteBitmapRenderTarget::D rawGlyphRun rendert Glyphen im DIB. DirectWrite rendert die Glyphen selbst, ohne GDI zu durchlaufen. Ihre Anwendung kann dann die HDC vom Bitmap-Renderziel abrufen und bitBlt verwenden, um die Pixel in eine Fenster-HDC zu kopieren.

Auf Nicht-Windows-Plattformen kann Ihre Anwendung weiterhin ein Bitmap-Renderziel erstellen, aber sie kapselt einfach ein Systemspeicherarray ohne HDC und ohne DIB. Ohne HDC muss es für Ihre Anwendung eine andere Möglichkeit geben, die Bitmappixel abzurufen, damit sie sie kopieren oder anderweitig verwenden kann. Selbst unter Windows ist es manchmal nützlich, die tatsächlichen Pixeldaten abzurufen. Die aktuelle Vorgehensweise wird im folgenden Codebeispiel veranschaulicht.

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

Andere API-Unterschiede zwischen DWriteCore und DirectWrite

Es gibt einige APIs, die entweder nur Stubs sind oder sich auf Nicht-Windows-Plattformen etwas anders verhalten. IdWriteGdiInterop::CreateFontFaceFromHdc gibt beispielsweise E_NOTIMPL auf Nicht-Windows-Plattformen zurück, da es ohne GDI keine HDC gibt.

Und schließlich gibt es noch einige andere Windows-APIs, die in der Regel zusammen mit DirectWrite verwendet werden (Direct2D ist ein bemerkenswertes Beispiel). Derzeit arbeiten Direct2D und DWriteCore jedoch nicht zusammen. Wenn Sie beispielsweise ein IDWriteTextLayout mit DWriteCore erstellen und an D2D1RenderTarget::D rawTextLayout übergeben, schlägt dieser Aufruf fehl.