DirectWrite文字排版——字符串去尾

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

时间: 2024-08-29 01:58:32

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

文字排版需要遵循的规律

文字排版必须遵循的规律 人类在阅读文字时的基本规则是从上到下,从左到右的.文案的排版应尽量遵从这一个规则,除特殊版式之外,尽可能减少参差不齐或者右对齐排列,大部分情况下,还是使用左对齐或居中对齐最为合适. 在设计中,可能都会遇到使用一些文字的特性,或者带有一点倾斜等,都是遵循左对齐原则. 这样不仅美观而且使阅读不会形成混乱. 当沿着某一版块或素材的左侧排列文字的时候我们使用右对齐会比左对齐和居中对齐要有更好的表达效果. 使用居中对齐让版面整体有自由感. 技巧2:明确 主.副标题与描述 文字的排版

字符串去空格以及反转操作示例

1.字符串去空格 package tan; public class CopyOfStringTest { public static void main(String[] args) { String s = " tan at guigu "; sop(s); String x = MyTrim(s); sop(x); } public static void sop(String str) { System.out.println(str); } // 1.去除字符串两端的空格 p

文字排版

文字排版 发布时间: 2017年10月27日 10:15   最后更新: 2017年10月29日 20:40   时间限制: 1000ms   内存限制: 128M 描述 给一段英文短文,单词之间以空格分隔(每个单词包括其前后紧邻的标点符号).请将短文重新排版,要求如下: 每行不超过80个字符:每个单词居于同一行上:在同一行的单词之间以一个空格分隔:行首和行尾都没有空格. 输入 第一行是一个整数n,表示英文短文中单词的数目. 其后是n个以空格分隔的英文单词(单词包括其前后紧邻的标点符号,且每个单

题目1049:字符串去特定字符(简单字符判断)

题目链接:http://ac.jobdu.com/problem.php?pid=1049 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: // // 1049 字符串去特定字符.cpp // Jobdu // // Created by PengFei_Zheng on 26/04/2017. // Copyright © 2017 PengFei_Zheng. All rights reserved. // #include <s

九度oj 题目1049:字符串去特定字符

题目1049:字符串去特定字符 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:10173 解决:4611 题目描述: 输入字符串s和字符c,要求去掉s中所有的c字符,并输出结果. 输入: 测试数据有多组,每组输入字符串s和字符c. 输出: 对于每组输入,输出去除c字符后的结果. 样例输入: heallo a 样例输出: hello 1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 i

字符串去星

字符串去星 Problem : 903 Time Limit : 1000ms Memory Limit : 65536K description 有一个字符串(长度小于100),要统计其中有多少个*,并输出该字符串去掉*后的新字符串. input 输入数据有多组,每组1个连续的字符串; output 在1行内输出该串内有多少个* 和去掉*后的新串. sample_input Goodggod223**df2*w Qqqq* sample_output 3 Goodggod223df2w 1 Q

Android - 实现两端对齐的文字排版

要实现Android两端对齐的文字排版效果,我们当然可以继承原有的TextView来实现,但一个更简单的方式就是使用WebView,利用HTML样式来实现. 首先定义一个String常量,我们可以将它视为一个HTML模板: private static final String WEBVIEW_CONTENT = "<html><head></head><body style=\"text-align:justify;margin:0;\&qu

php实现兼容Unicode文字的字符串大小写转换strtolower()和strtoupper()

前言 网上流传着这么一个腾讯笔试题: PHP的strtolower()和strtoupper()函数在安装非中文系统的服务器下可能会导致将汉字转换为乱码,请写两个替代的函数实现兼容Unicode文字的字符串大小写转换. 举个例子,我们直接对中英文混排的字符串处理是会出乱码的,如: php > $a = 'abc中华ABC'; php > var_dump(strtoupper($a)); string(12) "ABC??ō?ABC" php > 我们知道中文在 UT

[转] iOS文字排版(CoreText)那些事儿

文章转载自 http://www.cocoachina.com/applenews/devnews/2014/0521/8504.html iOS文字排版(CoreText)那些事儿 转自阿毛的蛋疼地 第一次比较深入接触iOS文字排版相关内容是在12年底,实现某IM项目聊天内容的图文混排,照着nimbus的AttributedLabel和Raywenderlish上的这篇文章<Core Text Tutorial for iOS: Making a Magazine App>改出了一个比较适用