使用DirectWrite测量Direct2D文字大小

Posted 郭小雷

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用DirectWrite测量Direct2D文字大小相关的知识,希望对你有一定的参考价值。

转载请注明出处:http://www.cnblogs.com/Ray1024

一、概述

最近在使用Direct2D和DirectWrite写引擎,在引擎中需要实现文本标签控件。但是文本标签的尺寸最好不是由我们人为指定的,要不然的话就会出现标签中文本溢出、空白存留等等问题,这样很影响美观。这就需要我们在文本标签的创建时根据文本的字体格式、文字排版等等因素来确定标签大小,而不是人为地指定大小,即实现标签大小的自适应功能(根据文本的内容、字体、格式等等因素得出的宽高来设置标签的大小)。

然而,想要实现标签大小的自适应功能,就需要测量Direct2D文本的大小。但是,如何测量Direct2D文字的大小呢,我在Direct2D中找了很久也没有找到合适的方法,在搜索引擎中也没有找到理想的解决方法。最后,在DirectWrite的MSDN文档中找到了解决方法。

这篇文章就来介绍一下怎样使用DirectWrite来测量Direct2D文本的大小。

 

二、解决方法

以下是我实现的一段用于测量文本宽高尺寸的函数,先贴代码:

// 使用IDWriteTextLayout获取文本大小 
HRESULT GetTextSize(const WCHAR* text, IDWriteTextFormat* pTextFormat, D2D1_SIZE_F& size) 
{  
     HRESULT hr = S_OK;  
     IDWriteTextLayout* pTextLayout = NULL;    
     // 创建文本布局  
     hr = m_pDWriteFactory->CreateTextLayout(text, wcslen(text), pTextFormat, 0.0f, 0.0f, &pTextLayout);    
     if (SUCCEEDED(hr))  
     {      
         // 获取文本尺寸   
         DWRITE_TEXT_METRICS textMetrics;   
         hr = pTextLayout->GetMetrics(&textMetrics);   
         size = D2D1::SizeF(ceil(textMetrics.widthIncludingTrailingWhitespace), ceil(textMetrics.height));
      }  
     SafeRelease(&pTextLayout);  
     return hr; 
 }

如上代码中,测量文本尺寸过程如下:

  1. 使用文本和字体创建IDWriteTextLayout对象

  2. 从创建成功的IDWriteTextLayout对象中获取文本大小信息DWRITE_TEXT_METRICS结构体

  3. 将文本信息结构体中的文本尺寸放到参数的size中,用于返回文本尺寸

 

三、深入解析

上面测量文字大小的代码中,关键的工具就是DirectWrite中的IDWriteTextLayout接口。IDWriteTextLayout接口表示经过完全分析和格式化后的文本块,简单地说就是一个布局后的文本。这个接口中有一个成员函数IDWriteTextLayout::GetMetrics(),我们需要的文本大小信息就可以通过这个函数来获取。重点介绍一下这个函数:

IDWriteTextLayout::GetMetrics 方法介绍 
功能
    检索格式化后的字符串的总体度量。 
语法 
    virtual HRESULT GetMetrics([out]  DWRITE_TEXT_METRICS *textMetrics);
参数 textMetrics [out]     
    此方法返回时,将包含格式化后文本与所关联内容的度量距离。 
返回值     
    如果该方法成功,则返回 S_OK。 否则,将返回错误代码。HRESULT. 

此函数的功能简单的说,就是获取IDWriteLayout对象布局后的文本信息,使用参数来返回我们需要的信息。


关于DWRITE_TEXT_METRICS类型的参数,这是一个结构体,用来盛放取出的文本布局信息。我们来看一下它的成员:

// 布局后与文本相关的信息 
struct DWRITE_TEXT_METRICS 
{     
    FLOAT left; // 格式化文本布局框的最左点     

    FLOAT top; // 格式化文本布局框的最上点

    FLOAT width; // 格式化文本的宽度忽略多余的空白处   

    FLOAT widthIncludingTrailingWhitespace; // 格式化文本的宽度,考虑每行结尾处的尾部空格   

    FLOAT height; // 格式化文本的高度,空字符串的高度由默认字体行高的大小决定     

    FLOAT layoutWidth; // 布局的初始宽度,根据文本是否被换行,它可以大于或小于文本内容宽度     

    FLOAT layoutHeight; // 布局的初始高度,根据文本的长度,它可以大于或小于文本内容高度 
    
    UINT32 maxBidiReorderingDepth; // 任一行文本的最大重新排序计数,用于计算命中测试框的最大数量,如布局没有双向文本或根本没有文本,则最小级别为1     

    UINT32 lineCount; // 文本的总行数     
};         

这个结构体的成员很多,而且都是一些非常有用的信息啊。了解了DWRITE_TEXT_METRICS这个结构体之后,我们就知道取出的文本布局信息都有什么了。那我们除了获取文本大小,还可以获取文本的左上角坐标、总行数等等信息,看来我们可以从这了解很多文本的信息了。

 

四、结语

上面的介绍应该让大家可以完全理解了如何使用DirectWrite测量文本尺寸的过程了。

如有错误,欢迎指正。

以上是关于使用DirectWrite测量Direct2D文字大小的主要内容,如果未能解决你的问题,请参考以下文章

为啥 DirectX/DirectWrite/Direct2D 文本渲染不能像 GDI 一样清晰?

WinRT 和软件 ClearType 字体渲染

Direct2D 第3篇 绘制文字

DirectWrite

uwp 获取系统字体库

.NET中生成水印更好的方法