Direct2D教程 绘制文本

xingyun86 3月前 418

Direct2D教程 绘制文本

概述

在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 Factoryhr = 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 rectRECT 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 textg_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);

效果图


×
打赏作者
最新回复 (0)
只看楼主
全部楼主
返回