DirectWrite是 DirectX 家族中专门用来做文本处理的部分,主要配合Direct2D进行渲染工作。
一、字符串去尾介绍
在文字渲染中,不免会遇到字符串去尾的需求。字符串去尾指的是:当字符串在指定的RECT中无法全部显示时,如何对文本进行截取,以适应目标区域大小;DirectWrite中的介绍是设置溢出布局宽度的文本的剪裁。我们把这种截取操作称为“字符串去尾”。
首先,给大家介绍一个DirectWrite中的类,IDWriteTextFormat类用于格式化文本的字体和段落属性,并且它还描述区域设置信息。
(1)IDWriteTextFormat::SetTrimming 方法
设置溢出布局宽度的文本的剪裁选项。
语法
virtual HRESULT SetTrimming( [in] const DWRITE_TRIMMING * trimmingOptions, IDWriteInlineObject * trimmingSign ) = 0;
参数
- trimmingOptions [in]
-
文本剪裁选项。 - trimmingSign
-
应用程序定义的忽略符号。此参数可为 NULL。注意:我们想要用到省略号代替裁剪部分就需要用到这个参数。
返回值
如果该方法成功,则返回 S_OK。 否则,将返回错误代码。HRESULT.
(2)DWRITE_TRIMMING 结构 (SetTrimming函数的第一个参数)
指定用于溢出布局框的文本的剪裁选项。
语法
struct DWRITE_TRIMMING {
DWRITE_TRIMMING_GRANULARITY granularity;
UINT32 delimiter;
UINT32 delimiterCount;
};
成员
- granularity
-
一个值,指定用于对溢出布局框的文本进行剪裁的文本粒度。enum DWRITE_TRIMMING_GRANULARITY {
DWRITE_TRIMMING_GRANULARITY_NONE, //不进行任何剪裁。文本流超出布局宽度。
DWRITE_TRIMMING_GRANULARITY_CHARACTER, //在字符群集边界处进行剪裁
DWRITE_TRIMMING_GRANULARITY_WORD //在字边界处进行剪裁
}; - delimiter
-
一个字符代码,用作指示要保留的文本部分开头的分隔符。对路径省略号最有用,其中分隔符为斜杠。 - delimiterCount
-
一个值,指示要后退的分隔符数量。
(3)DWriteFactory::CreateEllipsisTrimmingSign()方法
此方法可以生成表示省略号的 IDWriteInlineObject(此方法得到的IDWriteInlineObject可以作为SetTrimming方法的第二个参数)。
二、实现字符串去尾效果
字符串裁剪效果完全可以通过配置IDWriteTextFormat对象来实现。下面来展示5种不同情况的字符串去尾效果的IDWriteTextFormat对象的创建及配置过程:
a)不使用去尾
1 // 字体格式1:不使用去尾 2 if (SUCCEEDED(hr)) 3 { 4 DWRITE_TRIMMING trim1; 5 IDWriteInlineObject* trim2 = NULL; 6 hr = m_pDWriteFactory->CreateTextFormat( L"Arial Black", NULL, DWRITE_FONT_WEIGHT_NORMAL, 7 DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 20.0, L"en-us",&m_pTF1); 8 9 if (SUCCEEDED(hr)) 10 { // 换行模式(DWRITE_WORD_WRAPPING)设置为不换行 11 hr = m_pTF1->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); 12 } 13 14 if (SUCCEEDED(hr)) 15 { 16 trim1.granularity = DWRITE_TRIMMING_GRANULARITY_NONE; 17 trim1.delimiter = 1; 18 trim1.delimiterCount = 10; 19 hr = m_pTF1->SetTrimming(&trim1,trim2); 20 } 21 }
b)以字符为单位去尾
1 // 字体格式2:以字符为单位去尾 2 if (SUCCEEDED(hr)) 3 { 4 DWRITE_TRIMMING trim1; 5 IDWriteInlineObject* trim2 = NULL; 6 hr = m_pDWriteFactory->CreateTextFormat( L"Arial Black", NULL, DWRITE_FONT_WEIGHT_NORMAL, 7 DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 20.0, L"en-us",&m_pTF2); 8 9 if (SUCCEEDED(hr)) 10 { // 换行模式(DWRITE_WORD_WRAPPING)设置为不换行 11 hr = m_pTF2->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); 12 } 13 14 if (SUCCEEDED(hr)) 15 { 16 trim1.granularity = DWRITE_TRIMMING_GRANULARITY_CHARACTER; 17 trim1.delimiter = 1; 18 trim1.delimiterCount = 10; 19 hr = m_pTF2->SetTrimming(&trim1,trim2); 20 } 21 }
c)以单词为单位去尾
1 // 字体格式3:以单词为单位去尾 2 if (SUCCEEDED(hr)) 3 { 4 DWRITE_TRIMMING trim1; 5 IDWriteInlineObject* trim2 = NULL; 6 hr = m_pDWriteFactory->CreateTextFormat( L"Arial Black", NULL, DWRITE_FONT_WEIGHT_NORMAL, 7 DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 20.0, L"en-us",&m_pTF3); 8 9 if (SUCCEEDED(hr)) 10 { // 换行模式(DWRITE_WORD_WRAPPING)设置为不换行 11 hr = m_pTF3->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); 12 } 13 14 if (SUCCEEDED(hr)) 15 { 16 trim1.granularity = DWRITE_TRIMMING_GRANULARITY_WORD; 17 trim1.delimiter = 1; 18 trim1.delimiterCount = 10; 19 hr = m_pTF3->SetTrimming(&trim1,trim2); 20 } 21 }
d)以字符为单位去尾,用省略号代替略去部分
1 // 字体格式4:以字符为单位去尾,用省略号代替略去部分 2 if (SUCCEEDED(hr)) 3 { 4 DWRITE_TRIMMING trim1; 5 IDWriteInlineObject* trim2 = NULL; 6 hr = m_pDWriteFactory->CreateTextFormat( L"Arial Black", NULL, DWRITE_FONT_WEIGHT_NORMAL, 7 DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 20.0, L"en-us",&m_pTF4); 8 9 if (SUCCEEDED(hr)) 10 { // 换行模式(DWRITE_WORD_WRAPPING)设置为不换行 11 hr = m_pTF4->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); 12 } 13 14 if (SUCCEEDED(hr)) 15 { // 16 m_pDWriteFactory->CreateEllipsisTrimmingSign(m_pTF4,&trim2); 17 } 18 19 if (SUCCEEDED(hr)) 20 { 21 trim1.granularity = DWRITE_TRIMMING_GRANULARITY_CHARACTER; 22 trim1.delimiter = 1; 23 trim1.delimiterCount = 10; 24 hr = m_pTF4->SetTrimming(&trim1,trim2); 25 } 26 }
e)以单词为单位去尾,用省略号代替略去部分
1 // 字体格式4:以字符为单位去尾,用省略号代替略去部分 2 if (SUCCEEDED(hr)) 3 { 4 DWRITE_TRIMMING trim1; 5 IDWriteInlineObject* trim2 = NULL; 6 hr = m_pDWriteFactory->CreateTextFormat( L"Arial Black", NULL, DWRITE_FONT_WEIGHT_NORMAL, 7 DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 20.0, L"en-us",&m_pTF4); 8 9 if (SUCCEEDED(hr)) 10 { // 换行模式(DWRITE_WORD_WRAPPING)设置为不换行 11 hr = m_pTF4->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); 12 } 13 14 if (SUCCEEDED(hr)) 15 { 16 m_pDWriteFactory->CreateEllipsisTrimmingSign(m_pTF4,&trim2); 17 } 18 19 if (SUCCEEDED(hr)) 20 { 21 trim1.granularity = DWRITE_TRIMMING_GRANULARITY_CHARACTER; 22 trim1.delimiter = 1; 23 trim1.delimiterCount = 10; 24 hr = m_pTF4->SetTrimming(&trim1,trim2); 25 } 26 }
根据我们的实验发现,如果要实现“字符串去尾”的显示效果,必须先将换行模式(DWRITE_WORD_WRAPPING)设置为不换行;注意让显示的字符串长度超出目标矩形宽度,这样才能看出字符串去尾的效果。
在此Demo中,为了更好的展示出字符串去尾的视觉效果,我们将字符串绘制的目标矩形范围使用绿色画刷绘制出来,如下:
Demo链接:http://pan.baidu.com/s/1qXWMkna 密码:4e3o