藉助 C++ 進行 Windows 開發:使用 DirectWrite 和最新 C++ 管理字型

來源:互聯網
上載者:User

DirectWrite 是一種相當強大的文本布局 API。 它支援從 XAML 和 Office 2013 的 Windows 運行 時 (WinRT) 實現到 Internet Explorer 11 和更高版本的幾乎所有領先 Windows 應用程式和技術。 它 本身並不是呈現引擎,但與 Direct2D 有很近的關係,是 Direct2D 在 DirectX 系列中的同級產品。 當然,Direct2D 是首要的硬體加速即時模式圖形 API。

您可以將 DirectWrite 與 Direct2D 結合使用,以提供硬體加速的文本呈現。 說明一下,之前我 在 DirectWrite 方面的著述並不多。 我不希望您認為 Direct2D 只是 DirectWrite 呈現引擎。 Direct2D 遠不只如此。 DirectWrite 還有其他很多功能,在本月的專欄中,我將示範一些使用 DirectWrite 可 以完成的任務,看看最新 C++ 是如何協助簡化編程模型的。
DirectWrite API

我將使用 DirectWrite 探究系統字型集。 首先,我需要擷取 DirectWrite 工廠對象。 這是編寫 任 何要使用 DirectWrite 的出色排版功能的應用程式的第一步。 與大多數 Windows API 相同, DirectWrite 也依賴於 COM 基礎內容。 我需要調用 DWriteCreateFactory 函數來建立 DirectWrite 工廠對象。 此函數返回一個指向該工廠對象的 COM 介面:

ComPtr<IDWriteFactory2> factory;

IDWriteFactory2 介面是今年早些時候隨 Windows 8.1 和 DirectX 11.2 推出的最新版本 DirectWrite 工廠介面。 IDWriteFactory2 繼承自 IDWrite­Factory1,而 IDWrite­Factory1 繼承自 IDWriteFactory。 後者是原始的 DirectWrite 工廠介面,它公開了大部分工廠功能。

我將基於前面的 ComPtr 類模板調用 DWriteCreateFactory 函數:

HR(DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED,
 __uuidof(factory),
reinterpret_cast<IUnknown **>(factory.GetAddressOf())));

DirectWrite 包含一項名為 Windows 字型快取服務 (FontCache) 的 Windows 服務。 第一個參數 指 示獲得的工廠是否參與此跨過程緩衝的字型使用。 有 DWRITE_FACTORY_TYPE_SHARED 和 DWRITE_FACTORY_TYPE_ISOLATED 兩個選項。 SHARED 和 ISOLATED 工廠都可以利用已緩衝的字型資料 。 只有 SHARED 工廠向緩衝返回字型資料。 第二個參數具體指示我希望在第三個和最後一個參數中返回 哪 個版本的 DirectWrite 工廠介面。

在 DirectWrite 工廠對象給定的情況下,我可以直接要求其提供系統字型集:

             ComPtr<IDWriteFontCollection> fonts;
   HR(factory->GetSystemFontCollection(fonts.GetAddressOf()));

GetSystemFontCollection 方法的第二個參數是可選的,指示其是否檢查已安裝字型集的更新或更 改 。 幸運的是,這個參數預設為 false,因此,除非要確保結果集反映最近的更改,否則不必考慮它。 在字型集給定的情況下,我可以擷取集合中的字型系列數,如下所示:

             unsigned const count = fonts- >GetFontFamilyCount();

然後我使用 GetFontFamily 方法通過從零開始的索引檢索單個字型系列對象。 一個字型系列對象 表 示這樣一組字型:它們共用一個名稱,當然也是一種設計,但粗細、樣式和展開並不相同:

             ComPtr<IDWriteFontFamily> family;
   HR(fonts->GetFontFamily(index, family.GetAddressOf()));

IDWriteFontFamily 介面繼承自 IDWriteFontList 介面,因此,我可以枚舉該字型系列中的各種字 體。 能夠檢索字型系列名稱合乎情理並且非常有用。 不過,系列名稱已經過本地化,所以它並不像您 期待的那樣簡單直接。 首先,我需要字型系列提供一個本地化字串對象,該對象針對每種支援的區 域 設定均包含一個系列名稱:

             ComPtr<IDWriteLocalizedStrings> names;
   HR(family->GetFamilyNames(names.GetAddressOf()));

我也可以枚舉系列名稱,但一般只尋找使用者預設區域設定對應的名稱。 事實上, IDWriteLocalizedStrings 介面提供了 FindLocaleName 方法來檢索本地化系列名稱的索引。 我從調 用 GetUserDefaultLocaleName 函數以擷取使用者預設區域設定開始:

             wchar_t locale [LOCALE_NAME_MAX_LENGTH];
   VERIFY(GetUserDefaultLocaleName(locale, countof(locale)));

然後,我將預設區域設定傳遞給 IDWriteLocalizedStrings FindLocaleName 方法,確定該字型系 列 是否有針對目前使用者本地化的名稱:

             unsigned index;
   BOOL exists;
   HR(names->FindLocaleName(locale, &index, &exists));

相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。