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:不使用去尾
if (SUCCEEDED(hr))
{
DWRITE_TRIMMING trim1;
IDWriteInlineObject* trim2 = NULL;
hr = m_pDWriteFactory->CreateTextFormat( L"Arial Black", NULL, DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 20.0, L"en-us",&m_pTF1); if (SUCCEEDED(hr))
{ // 换行模式(DWRITE_WORD_WRAPPING)设置为不换行
hr = m_pTF1->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
} if (SUCCEEDED(hr))
{
trim1.granularity = DWRITE_TRIMMING_GRANULARITY_NONE;
trim1.delimiter = ;
trim1.delimiterCount = ;
hr = m_pTF1->SetTrimming(&trim1,trim2);
}
}
b)以字符为单位去尾
     // 字体格式2:以字符为单位去尾
if (SUCCEEDED(hr))
{
DWRITE_TRIMMING trim1;
IDWriteInlineObject* trim2 = NULL;
hr = m_pDWriteFactory->CreateTextFormat( L"Arial Black", NULL, DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 20.0, L"en-us",&m_pTF2); if (SUCCEEDED(hr))
{ // 换行模式(DWRITE_WORD_WRAPPING)设置为不换行
hr = m_pTF2->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
} if (SUCCEEDED(hr))
{
trim1.granularity = DWRITE_TRIMMING_GRANULARITY_CHARACTER;
trim1.delimiter = ;
trim1.delimiterCount = ;
hr = m_pTF2->SetTrimming(&trim1,trim2);
}
}
c)以单词为单位去尾
     // 字体格式3:以单词为单位去尾
if (SUCCEEDED(hr))
{
DWRITE_TRIMMING trim1;
IDWriteInlineObject* trim2 = NULL;
hr = m_pDWriteFactory->CreateTextFormat( L"Arial Black", NULL, DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 20.0, L"en-us",&m_pTF3); if (SUCCEEDED(hr))
{ // 换行模式(DWRITE_WORD_WRAPPING)设置为不换行
hr = m_pTF3->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
} if (SUCCEEDED(hr))
{
trim1.granularity = DWRITE_TRIMMING_GRANULARITY_WORD;
trim1.delimiter = ;
trim1.delimiterCount = ;
hr = m_pTF3->SetTrimming(&trim1,trim2);
}
}
d)以字符为单位去尾,用省略号代替略去部分
     // 字体格式4:以字符为单位去尾,用省略号代替略去部分
if (SUCCEEDED(hr))
{
DWRITE_TRIMMING trim1;
IDWriteInlineObject* trim2 = NULL;
hr = m_pDWriteFactory->CreateTextFormat( L"Arial Black", NULL, DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 20.0, L"en-us",&m_pTF4); if (SUCCEEDED(hr))
{ // 换行模式(DWRITE_WORD_WRAPPING)设置为不换行
hr = m_pTF4->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
} if (SUCCEEDED(hr))
{              //
m_pDWriteFactory->CreateEllipsisTrimmingSign(m_pTF4,&trim2);
} if (SUCCEEDED(hr))
{
trim1.granularity = DWRITE_TRIMMING_GRANULARITY_CHARACTER;
trim1.delimiter = ;
trim1.delimiterCount = ;
hr = m_pTF4->SetTrimming(&trim1,trim2);
}
}
e)以单词为单位去尾,用省略号代替略去部分
     // 字体格式4:以字符为单位去尾,用省略号代替略去部分
if (SUCCEEDED(hr))
{
DWRITE_TRIMMING trim1;
IDWriteInlineObject* trim2 = NULL;
hr = m_pDWriteFactory->CreateTextFormat( L"Arial Black", NULL, DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 20.0, L"en-us",&m_pTF4); if (SUCCEEDED(hr))
{ // 换行模式(DWRITE_WORD_WRAPPING)设置为不换行
hr = m_pTF4->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
} if (SUCCEEDED(hr))
{
m_pDWriteFactory->CreateEllipsisTrimmingSign(m_pTF4,&trim2);
} if (SUCCEEDED(hr))
{
trim1.granularity = DWRITE_TRIMMING_GRANULARITY_CHARACTER;
trim1.delimiter = ;
trim1.delimiterCount = ;
hr = m_pTF4->SetTrimming(&trim1,trim2);
}
}
 
根据我们的实验发现,如果要实现“字符串去尾”的显示效果,必须先将换行模式(DWRITE_WORD_WRAPPING)设置为不换行;注意让显示的字符串长度超出目标矩形宽度,这样才能看出字符串去尾的效果。
 
在此Demo中,为了更好的展示出字符串去尾的视觉效果,我们将字符串绘制的目标矩形范围使用绿色画刷绘制出来,如下:

想看源码的朋友可以点击此处下载,Demo源码是Direct2DTests目录下的DWriteStringTrimming文件。

DirectWrite文字排版——字符串去尾的更多相关文章

  1. OpenJudge计算概论-文字排版

    /*====================================================================== 文字排版 总时间限制: 1000ms 内存限制: 65 ...

  2. 【html】文字排版

    Web开发过程中文字排版,默认的情况下,行末的长单词会撑开容器. 我们想要的是(像word一样.能够自动换行.既不撑大容器.也不强制拆开行末单词.并且不会隐藏行末单词的多余字母) ①不能撑开容器 ②完 ...

  3. iOS开发-UITextView文字排版

    UITextView文本排版 1.配置NSMutableParagraphStyle NSMutableParagraphStyle *MParaStyle = [[NSMutableParagrap ...

  4. 题目1049:字符串去特定字符——九度OJ

    题目1049:字符串去特定字符 http://ac.jobdu.com/problem.php?pid=1049 时间限制:1 秒 内存限制:32 兆 题目描述: 输入字符串s和字符c,要求去掉s中所 ...

  5. (转)iOS7界面设计规范(10) - UI基础 - 文字排版与配色

    明天就是周四了.貌似前几天还在恨周一呢.话说今天几乎开了一整天的会,正经事情没做多少:这种感觉比一整天从早到晚12个小时的忙碌于一件事情还要让人感到疲惫的对叭?那今天的iOS7设计规范更新又是一篇很简 ...

  6. NSIS文字及字符串函数与头文件介绍

    原文 NSIS文字及字符串函数与头文件介绍 文字函数,顾名思义就是处理字符串的函数.使用这些字符串函数前,必须先包含头文件WordFunc.nsh.该头文件目前包含如下一些函数:WordFind.Wo ...

  7. nefu 903 字符串去星

    字符串去星 Problem : 903 Time Limit : 1000ms Memory Limit : 65536K description 有一个字符串(长度小于100),要统计其中有多少个* ...

  8. div介绍 盒子模型边框属性 CSS初始化 文字排版 边框调整 溢出

    今天学习的div,了解了div是干什么用的掌握了什么是盒子模型,以及div的外边距内边距以及边框,运用div和CSS给文字排版,利用边框的来做图像,div溢出的处理 CSS初始化: 精确排版的时候用这 ...

  9. JS保留小数 去尾法 进一法 四舍五入法

    //toFixed 四舍五入遇到坑. 1.235.toFixed(2) = 1.23 1.2350001.toFixed(2) = 1.24 //去尾法 Number.prototype.toFloo ...

随机推荐

  1. Python:常用函数封装

    def is_chinese(uchar): """判断一个unicode是否是汉字""" if uchar >= u'\u4e00' ...

  2. Android按键之Menu详解

    Android手机一般都有三个键,返回键.Home键.菜单键: Android系统的菜单支持主要通过4个接口来实现. 从上图可以看出Menu是一个父类接口,它下面有两个子类一个是ContextMenu ...

  3. liunx 套接字编程(Linux_C++)

    网络中的进程是如何通信的? 在网络中进程之间进行通信的时候,那么每个通信的进程必须知道它要和哪个计算机上的哪个进程通信.否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行 ...

  4. .NET Actor Model Implementations Differ in Approach

    Last week Vaughn Vernon, author of Implementing Domain-Driven Design, published Dotsero, a .NET Acto ...

  5. Struts2中的 配置文件

    struts2中涉及到的配置文件有: web.xml.struts.xml.struts.properties.default.properties.struts-default.xml web.xm ...

  6. sctp和tcp的区别

    作为一个传输层协议,SCTP兼有TCP及UDP两者的特点.SCTP可以称为是TCP的改进协议,但他们之间仍然存在着较大的差别.首先SCTP和TCP之间的最大区别是SCTP的连接可以是多宿主连接的,TC ...

  7. SDN论坛看到BW的问题及相关解答

    SDN论坛看到BW的问题及相关解答 链接: http://blog.sina.com.cn/s/blog_5c58e3c70100r1ou.html 现在有一个 QUERY 运行十分慢 , 所以我想在 ...

  8. WCF客户端承载

    http://www.cnblogs.com/wengyuli/archive/2010/12/27/1918109.html参考 Hi victory,   你提出的问题很好,这个问题,相信很多人学 ...

  9. Openwrt安装软件的方法

    转自:http://blog.csdn.net/jk110333/article/details/8753825     web软件: Naken Web Openwrt安装软件 简介 Openwrt ...

  10. Spring3系列5-Bean的基本用法

    Spring3系列5-Bean的基本用法 本篇讲述了Bean的基本配置方法,以及Spring中怎样运用Bean. 主要内容如下: 一.      Spring中Bean的相互引用 二.      Sp ...