Dela via


Översikt över DWriteCore

DWriteCore är Windows App SDK:s implementering av DirectWrite (DirectWrite är DirectX API för textrendering av hög kvalitet, upplösningsoberoende outline-teckensnitt och fullständigt stöd för Unicode-text och layout). DWriteCore är en form av DirectWrite som körs på versioner av Windows ner till Windows 10, version 1809 (10.0; Build 17763). DWriteCore implementerar samma API som DirectWrite, med några tillägg enligt beskrivningen i det här avsnittet.

Det här introduktionsavsnittet beskriver vad DWriteCore är och visar hur du installerar det i utvecklingsmiljön och programmet med det.

För en app som redan använder DirectWrite kräver växling till DWriteCore minimala ändringar:

  • Lägg till en referens till Windows App SDK-paketet.
  • Inkludera dwrite_core.h i stället för dwrite_3.h.
  • Länka DWriteCore.lib i stället för DWrite.lib.
  • Anropa DWriteCoreCreateFactory istället för att använda DWriteCreateFactory.

I gengäld får appen fördelarna med Windows App SDK, nämligen åtkomst till de senaste API:erna och funktionerna oavsett vilken version av Windows som kunden kör.

Tips

Beskrivningar av och länkar till DirectX-komponenter i aktiv utveckling finns i blogginlägget DirectX-landningssidan.

Värdeförslaget för DWriteCore

DirectWrite självt stöder en omfattande uppsättning funktioner som gör det till det främsta renderingsverktyget för teckensnitt i Windows för de flesta apparna, oavsett om det är genom direkta samtal eller via Direct2D. DirectWrite innehåller ett enhetsoberoende textlayoutsystem, högkvalitativ subpixel Microsoft ClearType textrendering, maskinvaruaccelererad text, text i flera format, avancerade OpenType® typografifunktioner, brett språkstöd och GDI-kompatibel layout och rendering. DirectWrite har varit tillgängligt sedan Windows Vista SP2 och har utvecklats under åren till att omfatta mer avancerade funktioner som variabelteckensnitt, vilket gör att du kan använda format, vikter och andra attribut för ett teckensnitt med bara en teckensnittsresurs.

På grund av DirectWrites långa livslängd har utvecklingen dock tenderat att lämna äldre versioner av Windows bakom sig. Dessutom är DirectWrite status som den främsta textrenderingstekniken begränsad till Windows, vilket gör att plattformsoberoende program antingen skriver sin egen textrenderingsstack eller förlitar sig på lösningar från tredje part.

DWriteCore löser de grundläggande problemen med överblivna versionsfunktioner och plattformsoberoende kompatibilitet genom att ta bort biblioteket från systemet och rikta in sig på alla möjliga slutpunkter som stöds. Därför har vi integrerat DWriteCore i Windows App SDK.

Det primära värdet som DWriteCore ger dig som utvecklare i Windows App SDK är att det ger åtkomst till många (och så småningom alla) DirectWrite-funktioner. Alla funktioner i DWriteCore fungerar på samma sätt på alla nednivåversioner utan skillnader om vilka funktioner som kan fungera med vilka versioner.

DWriteCore-demoappen DWriteCoreGallery

DWriteCore demonstreras med hjälp av DWriteCoreGallery exempelapp, som du nu kan ladda ned och studera.

Kom igång med DWriteCore

DWriteCore är en del av Windows App SDK. I det här avsnittet beskrivs hur du konfigurerar utvecklingsmiljön för programmering med DWriteCore.

Installera verktyg för Windows App SDK

Se Installera verktyg för Windows App SDK.

Skapa ett nytt projekt

I Visual Studio skapar du ett nytt projekt från Tom app, Paketerad (WinUI 3 i Desktop) projektmall. Du hittar projektmallen genom att välja språk: C++; plattform: Windows App SDK; projekttyp: Desktop.

Mer information finns i Project-mallar för WinUI 3.

Installera NuGet-paketet Microsoft.ProjectReunion.DWrite

I Visual Studio klickar du på Project>Manage NuGet Packages...>Browse, type or paste Microsoft.ProjectReunion.DWrite i sökrutan, välj objektet i sökresultatet och klicka sedan på Installera för att installera paketet för projektet.

Du kan också börja med exempelappen DWriteCoreGallery

Du kan också programmera med DWriteCore genom att börja med DWriteCoreGallery exempelappprojekt och basera din utveckling på det projektet. Du kan sedan ta bort befintlig källkod (eller filer) från exempelprojektet och lägga till eventuell ny källkod (eller filer) i projektet.

Använda DWriteCore i projektet

Mer information om programmering med DWriteCore finns i avsnittet Programmering med DWriteCore senare i det här avsnittet.

Lanseringsfaserna för DWriteCore

Att porta DirectWrite till DWriteCore är ett tillräckligt stort projekt för att sträcka sig över flera Windows-versionscykler. Projektet är indelat i faser, som var och en motsvarar ett segment av funktioner som levereras i en version.

Funktioner i den aktuella versionen av DWriteCore

DWriteCore är en del av Windows App SDK. Den innehåller de grundläggande verktyg som du som utvecklare behöver för att använda DWriteCore, inklusive följande funktioner.

En banderollsfunktion är färgteckensnitt. Med färgteckensnitt kan du återge dina teckensnitt med mer avancerade färgfunktioner utöver enkla enkla färger. Till exempel är färgteckensnitt det som driver möjligheten att återge emoji- och verktygsfältsikonteckensnitt (varav det senare används av Office, till exempel). Färgteckensnitt introducerades först i Windows 8.1, men funktionen utökades kraftigt i Windows 10, version 1607 (Anniversary Update).

Arbetet med rensning av teckensnittscachen och den minnesinterna teckensnittsläsaren möjliggör snabbare inläsning av teckensnitt och minnesförbättringar.

Med dessa funktioner kan du omedelbart börja utnyttja några av DirectWrite moderna kärnfunktioner, till exempel variabelteckensnitt. Variabelteckensnitt är en av de viktigaste funktionerna för DirectWrite-kunder.

Vår inbjudan till dig som DirectWrite-utvecklare

DWriteCore, tillsammans med andra Windows App SDK-komponenter, kommer att utvecklas med öppenhet för feedback från utvecklare. Vi inbjuder dig att börja utforska DWriteCore och att ge insikter eller förfrågningar om funktionsutveckling på vår GitHub-lagringsplats för Windows App SDK.

Programmering med DWriteCore

Precis som med DirectWriteprogrammerar du med DWriteCore genom dess COM-light API och använder gränssnittet IDWriteFactory.

Om du vill använda DWriteCore måste du ta med dwrite_core.h-huvudfilen.

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

Den dwrite_core.h huvudfilen definierar först token DWRITE_COREoch innehåller sedan dwrite_3.h-huvudfilen. Den DWRITE_CORE token är viktig eftersom den dirigerar alla senare inkluderade rubriker för att göra alla DirectWrite-API:er tillgängliga för dig. När projektet har inkluderat dwrite_core.hkan du sedan skriva kod, skapa och köra.

API:er som är nya eller annorlunda för DWriteCore

DWriteCore API-ytan är i stort sett densamma som för DirectWrite. Men det finns ett litet antal nya API:er som bara finns i DWriteCore för närvarande.

Skapa ett fabriksobjekt

Den DWriteCoreCreateFactory- kostnadsfria funktionen skapar ett fabriksobjekt som används för efterföljande skapande av enskilda DWriteCore-objekt.

DWriteCoreCreateFactory fungerar på samma sätt som funktionen DWriteCreateFactory som exporteras av systemversionen av DirectWrite. Funktionen DWriteCore har ett annat namn för att undvika tvetydighet.

Skapa ett begränsat fabriksobjekt

Uppräkningen DWRITE_FACTORY_TYPE har en ny konstant,DWRITE_FACTORY_TYPE_ISOLATED2, som anger en begränsad fabrik. En begränsad fabrik är mer låst än en isolerad fabrik. Den interagerar inte med en korsprocess eller beständig teckensnittscache på något sätt. Dessutom innehåller systemteckensnittssamlingen som returneras från den här fabriken endast välkända teckensnitt. Så här kan du använda DWRITE_FACTORY_TYPE_ISOLATED2 för att skapa ett begränsat fabriksobjekt när du anropar funktionen DWriteCoreCreateFactory free.

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

Om du skickar DWRITE_FACTORY_TYPE_ISOLATED2 till en äldre version av DirectWrite som inte stöder den, returnerar DWriteCreateFactoryE_INVALIDARG.

Rita glyfer till en bitmapp för systemminne

DirectWrite har ett målgränssnitt för bitmappsåtergivning som stöder återgivning av glyfer till en bitmapp i systemminnet. Men för närvarande är det enda sättet att få åtkomst till underliggande pixeldata att gå igenom GDI, så API:et kan inte användas på flera plattformar. Detta åtgärdas enkelt genom att lägga till en metod för att hämta pixeldata.

DWriteCore introducerar därför gränssnittet IDWriteBitmapRenderTarget2 och dess metod IDWriteBitmapRenderTarget2::GetBitmapData. Den metoden tar en parameter av typen (pekare till) DWRITE_BITMAP_DATA_BGRA32, vilket är en ny struct.

Programmet skapar ett bitmappsåtergivningsmål genom att anropa IDWriteGdiInterop::CreateBitmapRenderTarget. I Windows kapslar ett bitmappsåtergivningsmål in en GDI-minnes-DC med en GDI-enhetsoberoende bitmapp (DIB) markerad i den. IDWriteBitmapRenderTarget::DrawGlyphRun återger glyfer till DIB. DirectWrite renderar själva glyphs utan att gå igenom GDI. Ditt program kan sedan hämta HDC- från bitmappsåtergivningsmålet och använda BitBlt- för att kopiera bildpunkterna till ett fönster HDC-.

På icke-Windows-plattformar kan programmet fortfarande skapa ett bitmappsåtergivningsmål, men det kapslar helt enkelt in en systemminnesmatris utan HDC- och ingen DIB. Utan en HDC-måste det finnas ett annat sätt för ditt program att hämta bitmappspixlarna så att det kan kopiera dem eller på annat sätt använda dem. Även i Windows är det ibland användbart att hämta faktiska pixeldata, och vi visar det aktuella sättet att göra det i kodexemplet nedan.

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

Andra API-skillnader mellan DWriteCore och DirectWrite

Det finns några API:er som antingen bara är stubs, eller så beter de sig något annorlunda på plattformar som inte är Windows. Till exempel returnerar IDWriteGdiInterop::CreateFontFaceFromHdcE_NOTIMPL på plattformar som inte är Windows-plattformar, eftersom det inte finns någon HDC- utan GDI-.

Och slutligen finns det vissa andra Windows-API:er som vanligtvis används tillsammans med DirectWrite (Direct2D är ett anmärkningsvärt exempel). Men för närvarande samverkar inte Direct2D och DWriteCore. Om du till exempel skapar en IDWriteTextLayout- med DWriteCore och skickar den till D2D1RenderTarget::DrawTextLayout, kommer det anropet att misslyckas.