DWriteCore 概觀

DWriteCore 是DirectWrite (DirectWrite 的Windows 應用程式 SDK實作是 DirectX API,適用于高品質文字轉譯、解析度無關的大綱字型,以及完整的 Unicode 文字和版面配置支援) 。 DWriteCore 是一種DirectWrite形式,可在 Windows 版本上執行到 Windows 10 版本 1809 (10.0;組建 17763) 。 DWriteCore 會實作與DirectWrite相同的 API,並新增一些如本主題中所述的新增專案。

此簡介主題說明 DWriteCore 是什麼,並示範如何使用它將其安裝到您的開發環境和程式。

對於已使用 DirectWrite 的應用程式,切換至 DWriteCore 需要最少的變更:

在傳回中,無論客戶執行的 Windows 版本為何,應用程式都能取得Windows 應用程式 SDK的優點,也就是存取最新的 API 和功能。

提示

如需作用中開發中 DirectX 元件的描述和連結,請參閱部落格文章 DirectX 登陸頁面

DWriteCore 的價值主張

DirectWrite本身支援豐富的功能陣列,可讓它成為大部分應用程式在 Windows 上選擇的字型轉譯工具,無論是透過直接呼叫還是透過Direct2D。 DirectWrite包含與裝置無關的文字配置系統、高品質的子圖元Microsoft ClearType文字轉譯、硬體加速文字、多格式文字、進階OpenType®印刷樣式功能、寬語言支援,以及GDI相容的版面配置和轉譯。 DirectWrite自 Windows Vista SP2 起已推出,而且已隨著年份而演進,包含更進階的功能,例如變數字型,可讓您將樣式、粗細和其他屬性套用至只有一個字型資源的字型。

不過,由於DirectWrite的生命週期很長,開發中的進展通常會讓舊版的 Windows 落後。 此外,DirectWrite頂級文字轉譯技術的狀態僅限於 Windows,讓跨平臺應用程式能夠撰寫自己的文字轉譯堆疊,或依賴協力廠商解決方案。

DWriteCore 藉由從系統移除程式庫,並以所有可能支援的端點為目標,來解決版本功能孤立和跨平臺相容性的基本問題。 為此,我們已將 DWriteCore 整合到Windows 應用程式 SDK。

DWriteCore 提供您身為開發人員的主要值,Windows 應用程式 SDK是它可讓您存取許多 (,最後所有) DirectWrite 功能。 DWriteCore 的所有功能在所有下層版本上都會運作相同,而不會有任何關於哪些功能在哪些版本上可能運作的差異。

DWriteCore 示範應用程式— DWriteCoreGallery

DWriteCore 是透過 DWriteCoreGallery 範例應用程式示範,現在可供您下載並研究。

開始使用 DWriteCore

DWriteCore 是Windows 應用程式 SDK的一部分。 本節說明如何設定開發環境以使用 DWriteCore 進行程式設計。

安裝適用于Windows 應用程式 SDK的工具

請參閱安裝Windows 應用程式 SDK的工具

建立新專案

在 Visual Studio 中,從 [ 桌面]) 專案範本中的 [已封裝 (WinUI 3 空白應用程式 建立新專案。 您可以選擇語言來找到該專案範本:C++;platform:Windows 應用程式 SDK;專案類型:桌面

如需詳細資訊,請參閱 WinUI 3 的專案範本

安裝 Microsoft.ProjectReunion.DWrite NuGet 套件

在 Visual Studio 中,按一下 [專案>管理 NuGet 套件...>搜尋方塊中流覽、輸入或貼上Microsoft.ProjectReunion.DWrite,選取搜尋結果中的專案,然後按一下 [安裝] 以安裝該專案的套件。

或者,從 DWriteCoreGallery 範例應用程式開始

或者,您可以從 DWriteCoreGallery 範例應用程式專案開始以 DWriteCore 進行程式設計,並根據該專案進行開發。 然後,您可以隨意從該範例專案中移除任何現有的原始程式碼 (或檔案) ,並將任何新的原始程式碼 (或檔案) 新增至專案。

在專案中使用 DWriteCore

如需使用 DWriteCore 進行程式設計的詳細資訊,請參閱本主題稍後 的使用 DWriteCore 進行程式設計 一節。

DWriteCore 的發行階段

將DirectWrite移植到 DWriteCore 是足以跨越多個 Windows 發行週期的大型專案。 該專案分成階段,每個階段都會對應至發行中傳遞的功能區塊。

DWriteCore 目前版本中的功能

DWriteCore 是Windows 應用程式 SDK的一部分。 其中包含您身為開發人員的基本工具,需要取用 DWriteCore,包括下列功能。

橫幅功能是色彩字型。 色彩字型可讓您轉譯具有比簡單單一色彩更複雜色彩功能的字型。 例如,色彩字型是讓轉譯 emoji 和工具列圖示字型的能力, (Office 所使用的後者,例如) 。 色彩字型最初是在 Windows 8.1 引進,但此功能在 Windows 10 1607 版 (年度更新版) 中大幅擴充。

清除字型快取和記憶體中字型載入器的工作,可讓您更快速地載入字型,以及記憶體改善。

透過這些功能,您可以立即開始利用一些DirectWrite的新式核心功能,例如變數字型。 變數字型是DirectWrite客戶最重要的功能之一。

我們邀請您成為DirectWrite開發人員

DWriteCore 和其他Windows 應用程式 SDK元件將會以開放性開發開發人員意見反應。 我們邀請您開始探索 DWriteCore,並在我們的Windows 應用程式 SDK GitHub 存放庫上提供功能開發的深入解析或要求。

使用 DWriteCore 進行程式設計

就像DirectWrite一樣,您可以透過IDWriteFactory介面,透過 COM 光 API 使用 DWriteCore 進行程式設計。

若要使用 DWriteCore,您必須包含 dwrite_core.h 標頭檔。

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

dwrite_core.h標頭檔會先定義權杖DWRITE_CORE,然後包含 dwrite_3.h 標頭檔。 DWRITE_CORE權杖很重要,因為它會指示任何後續包含的標頭,讓所有DirectWrite API 可供您使用。 一旦專案包含 dwrite_core.h ,您就可以繼續撰寫程式碼、建置和執行。

DWriteCore 的新功能或不同 API

DWriteCore API 介面與DirectWrite大致相同。 但目前只有 DWriteCore 中有少數新的 API。

建立 Factory 物件

DWriteCoreCreateFactory免費函式會建立 Factory 物件,用於後續建立個別的 DWriteCore 物件。

DWriteCoreCreateFactory的功能與系統版本的 DirectWrite 所匯出的DWriteCreateFactory函式相同。 DWriteCore 函式有不同的名稱,以避免模棱兩可。

建立受限制的 Factory 物件

DWRITE_FACTORY_TYPE列舉具有新的常數,DWRITE_FACTORY_TYPE_ISOLATED2,表示受限制的處理站。 受限制的處理站比隔離處理站更鎖定。 它不會以任何方式與跨進程或持續性字型快取互動。 此外,從此處理站傳回的系統字型集合只包含已知的字型。 以下是當您呼叫DWriteCoreCreateFactory免費函式時,如何使用 DWRITE_FACTORY_TYPE_ISOLATED2來建立受限制的 Factory 物件。

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

如果您將DWRITE_FACTORY_TYPE_ISOLATED2傳遞給不支援它的舊版 DirectWrite,則 DWriteCreateFactory傳回E_INVALIDARG

將圖像繪製至系統記憶體點陣圖

DirectWrite具有點陣圖轉譯目標介面,可支援將圖像轉譯至系統記憶體中的點陣圖。 不過,目前取得基礎圖元資料存取的唯一方式是通過 GDI,因此 API 無法跨平臺使用。 藉由新增方法來擷取圖元資料,即可輕鬆解決此問題。

因此,DWriteCore 引進 IDWriteBitmapRenderTarget2 介面及其方法 IDWriteBitmapRenderTarget2::GetBitmapData。 該方法會採用 (指標的參數,) 類型 DWRITE_BITMAP_DATA_BGRA32,這是新的結構。

您的應用程式會呼叫 IDWriteGdiInterop::CreateBitmapRenderTarget來建立點陣圖轉譯目標。 在 Windows 上,點陣圖轉譯目標會封裝 GDI 記憶體 DC 與 GDI 裝置無關的點陣圖 (DIB) 選取。 IDWriteBitmapRenderTarget::D rawGlyphRun 會將字元轉譯為 DIB。 DirectWrite會轉譯字元本身,而不需經過 GDI。 然後,您的應用程式可以從點陣圖轉譯目標取得 HDC ,並使用 BitBlt 將圖元複製到視窗 HDC

在非 Windows 平臺上,您的應用程式仍然可以建立點陣圖轉譯目標,但它只會封裝不含 HDC 且沒有 DIB 的系統記憶體陣列。 如果沒有 HDC,您的應用程式必須有另一種方式才能取得點陣圖圖元,以便複製它們,否則請使用它們。 即使在 Windows 上,取得實際圖元資料有時也很有用,我們在下列程式碼範例中顯示目前的做法。

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

DWriteCore 與 DirectWrite 之間的其他 API 差異

只有一些 API 只有存根,或它們在非 Windows 平臺上的行為有些不同。 例如,IDWriteGdiInterop::CreateFontFaceFromHdc會在非 Windows 平臺上傳回E_NOTIMPL,因為沒有GDIHDC沒有這類專案。

最後,有一些其他 Windows API 通常會與 DirectWrite (Direct2D 一起使用,這是值得注意的範例) 。 不過,目前 Direct2D 和 DWriteCore 不會互通。 例如,如果您使用 DWriteCore 建立 IDWriteTextLayout ,並將它傳遞至 D2D1RenderTarget::D rawTextLayout,則該呼叫將會失敗。