在Direct2D中,文本的绘制是通过DirectWrite来实现的,DirectWrite实际上已经是一个独立的DirectX组件了。关于DirectWrite,我摘录了MSDN的一段文字。
当今的应用程序应提供高质量的文本渲染,分辨率无关的字体及完整的Unicode文本和布局支持,DirectWrite提供了这些功能,甚至比这更多。下面是DirectWrite的特性
DirectWrite API支持多格式文本的度量,绘制及命中测试。DirectWrite处理所有支持语言的文本,包括global及localized应用程序(构建于Windows7核心语言基础之上)。DirectWrite也提供了底层的glyph渲染。
Direct2D提供了如下两个绘制文本的函数,稍后的代码使用第一个函数。
这里介绍的步骤都是与绘制文本相关的核心步骤,其它步骤比如创建render target或者画刷,处理Windows消息等是每个Direct2D程序都会涉及的,这里就不再介绍了。
凡事都有个根源,程序也是一样,在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; }
前面说了,在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; }
文本有一系列属性,比如字体类型,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;
参数说明:
最后两个参数暂时用不到,而且有默认参数,这里就不考虑了。调用代码如下。
// 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系列中会详细阐述每个方面,敬请关注!