概述
在Direct2D中,文本的繪制是通過DirectWrite來實現的,DirectWrite實際上已經是一個獨立的DirectX組件了。關於DirectWrite,我摘錄了MSDN的一段文字。
DirectWrite介紹
當今的應用程序應提供高質量的文本渲染,分辨率無關的字體及完整的Unicode文本和布局支持,DirectWrite提供了這些功能,甚至比這更多。下面是DirectWrite的特性
- 設備無關的文本布局系統,提高了文本的可讀性(包括文檔及UI上的文本)
- 高質量的,子像素,ClearType文本的渲染(可以使用GDI及Direct2D或應用程序指定的渲染技術)
- 硬件加速的文本渲染(和Direct2D一起使用時)
- 支持多格式文本
- 支持OpenType fonts的高級typography特性
- 對所支持語言文本的渲染及布局。
- GDI兼容的布局及渲染
DirectWrite API支持多格式文本的度量,繪制及命中測試。DirectWrite處理所有支持語言的文本,包括global及localized應用程序(構建於Windows7核心語言基礎之上)。DirectWrite也提供了底層的glyph渲染。
Direct2D提供了如下兩個繪制文本的函數,稍后的代碼使用第一個函數。
- ID2D1RenderTarget::DrawText
- ID2D1RenderTarget::DrawTextLayout
主要步驟
這里介紹的步驟都是與繪制文本相關的核心步驟,其它步驟比如創建render target或者畫刷,處理Windows消息等是每個Direct2D程序都會涉及的,這里就不再介紹了。
創建ID2D1Factory接口對象
凡事都有個根源,程序也是一樣,在Direct2D中也有一個根源對象,那就是ID2D1Factory接口,它是所有其它資源的根源,包括設備相關的資源及設備無關的資源,有了這個接口,就可以創建其它的D2D對象了,比如render target,畫刷等。所以首要任務是創建一個ID2D1Factory對象。
D2D1Factory* g_pD2DFactory = NULL; HRESULT hr = D2D1CreateFactory( D2D1_FACTORY_TYPE_SINGLE_THREADED, &g_pD2DFactory ); if(FAILED(hr)) { MessageBox(NULL, L"Create Direct2D factory failed!", L"Error", 0); return; }
創建IDWriteFactory接口對象
前面說了,在Direct2D中繪制文本實際上是通過DirectWrite來實現的,一切和文本相關的接口也都是由這個接口來創建的,所以接下來要創建一個IDWriteFactory接口對象,代碼如下。
IDWriteFactory* g_pDWriteFactory = NULL; // Create DirectWrite Factory hr = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(&g_pDWriteFactory) ); if(FAILED(hr)) { MessageBox(NULL, L"Create DirectWrite factory failed!", L"Error", 0); return; }
創建IDWriteTextFormat接口對象
文本有一系列屬性,比如字體類型,Arial還是Consolas?字體大小,14px還是16px? 字體風格,傾斜或加粗?在D2D中,用IDWriteTextFormat來描述文本的這些屬性,所以,下一步需要創建IDWriteTextFormat對象了。需要注意的是文本的顏色並不是由該接口來控制的,而是由畫刷來控制。
IDWriteTextFormat* g_pTextFormat = NULL; hr = g_pDWriteFactory->CreateTextFormat( L"Gabriola", // Font family name NULL, // Font collection(NULL sets it to the system font collection) DWRITE_FONT_WEIGHT_REGULAR, // Weight DWRITE_FONT_STYLE_NORMAL, // Style DWRITE_FONT_STRETCH_NORMAL, // Stretch 50.0f, // Size L"en-us", // Local &g_pTextFormat // Pointer to recieve the created object ); if(FAILED(hr)) { MessageBox(NULL, L"Create IDWriteTextFormat failed!", L"Error", 0); return; }
定義文本繪制區域
下一步,需要確定文本的繪制區域,也就是在哪里繪制文本,這個區域通常是一個矩形結構。所以,只需簡單定義一個rect即可。
// Create text layout rect RECT rc; GetClientRect(hwnd, &rc); D2D1_RECT_F textLayoutRect = D2D1::RectF( static_cast<FLOAT>(rc.left), static_cast<FLOAT>(rc.top), static_cast<FLOAT>(rc.right - rc.left), static_cast<FLOAT>(rc.bottom - rc.top) );
繪制
萬事俱備,只欠東風!下面就是最后一步也是最重要的一步,渲染文本,這里使用接口ID2D1HwndRenderTarget中的函數DrawText來完成具體的繪制工作,這個函數的具體定義如下:
virtual void DrawText( [in] WCHAR *string, UINT stringLength, [in] IDWriteTextFormat *textFormat, [in] const D2D1_RECT_F *layoutRect, [in] ID2D1Brush *defaultForegroundBrush, D2D1_DRAW_TEXT_OPTIONS options = D2D1_DRAW_TEXT_OPTIONS_NONE, DWRITE_MEASURING_MODE measuringMode = DWRITE_MEASURING_MODE_NATURAL ) = 0;
參數說明:
- string, 待繪制的文本,unicode編碼。
- stringLength, 文本長度。
- textFormat, 文本的格式化信息(屬性),上面提到過。
- layoutRect, 繪制區域對應的矩形。
- defaultForegroundBrush, 繪制文本所用的畫刷
最后兩個參數暫時用不到,而且有默認參數,這里就不考慮了。調用代碼如下。
// Draw text g_pRenderTarget->DrawText( wszText, // Text to render cTextLength, // Text length g_pTextFormat, // Text format textLayoutRect, // The region of the window where the text will be rendered g_pBlackBrush // The brush used to draw the text );
效果圖
然后呢?
這篇只是對於文本繪做一個簡單的介紹,在Direct2D與文本相關的東西遠不止這些,在后續的DirectWrite系列中會詳細闡述每個方面,敬請關注!