DirectWrite
目的:
今天,应用程序必须支持高质量的文字描绘,分辨率无关的框架字体,完全的支持Unicode文本,DirectWrite就是提供这些或者更多特性的DirectX API。
l 设备无关的文字布局系统改进了文档和UI的文字可视效果;
l 用GDI、Direct2D或应用程序具体的渲染技术支持的高质量ClearType文本渲染;
l 当使用Direct2D的时候还可以提供硬件加速;
l 支持多种格式的字体;
l 支持高级拓扑特性的OpenType字体;
l 支持以所有支持的语言的文本布局渲染;
l 和GDI兼容的文本渲染;
DirectWrite支持多种格式字体的测量、描画、点击测试。DirectWrite以所有支持的语言为本地化或者国际化的应用程序处理字体,构建在windows7上的关键语言基础构架,DirectWrite也为用户提供了一些底层的图形描画API来表现他们自己的布局和Unicode-to-glyph的处理。
运行时要求:
l windows7 或者window vista(sp2)及以上版本。
l windows Server 2008 R2 或以上版本。
Programming Guide
Introducing DirectWrite
独立的渲染系统:
DirectWrite独立于任何特定的渲染技术。应用程序可以选择适合他们自己的渲染技术,这就给应用程序的开发提供了很大的灵活性去用GDI或者Direct3D或Direct2D去渲染程序的某些部分。事实上,应用程序可以用一个专用的渲染栈去渲染directwr。
高质量的排版:
DirectWrite利用了OpenType的优势来达到在windows应用程序中的高质量的排版。DirectWrite字体系统提供了许多服务像字体枚举、字体fallback和字体缓存,这些都是程序处理字体需要的技术。DirectWrite 提供的OpenType支持开发者添加他们自己程序的高级排版特性和国际化字体。
高质量排版特性的支持:
DirectWrite允许开发者解锁一些他们在WinForms或GDI中用不到的OpenType字体特性。
DirectWrite中的IDWriteTypography对象引入了许多OpenType字体的高级特性,如stylistic alternates和swashes。SDK提供了一个OpenType字体的集合,该集合拥有丰富的特性,例如the Pericles和Pescadero字体。
Multiple Layers of Functionality
DirectWrite提供了因素层的功能,每一层都和下一层无缝交互。API的设计给了应用程序开发者很大的自由来适应单个层,当然这要取决于他们的需要和安排。下面的图显示了这些层之间的联系。
文本布局API为DirectWrite提供了高层的布局功能,它为应用程序提供了一些服务,应用这些服务,程序可以测量、显示和富文本字符串交互。这个文本API能够被用于当前用Win32的DrawText构建富文本的UI的应用程序。
实现了自己的布局引擎的文本应用程序可能用下面的层:script processor。该脚本处理器分解文本块成为一个脚本块并处理Unicode和合适的图形表现之间的映射,使得文本可以在正确的语言下正确的显示。被TextLayout API层使用的布局系统建立在font 和脚本处理系统之上。
字体渲染层是最底层的功能并且为实现了自己的文本布局引擎的应用程序提供字形渲染,字体渲染层对于那些实现了自定义的渲染来改进图形描画行为(通过DirectWrite的text-formatting API的回调函数)也是有用的。
DirectWrite字体系统对于所有的DirectWrite功能层都是有效的,它提供了程序访问字体和图形信息的能力并且被设计用来处理共通的字体技术和数据格式。
DirectWrite的字体模型遵循了共通的排版经验,即在相同的字体家族中支持任意的weights、styles和stretches。这个模型具体化了字体只在weight(bold、light等)、style(upright、italic、oblique)或者stretch(narrow、condesed、wide等)的不同仍被认为是一个字体家族的成员。
Improved Text Rendering with ClearType:
所有windows应用程序的关键需求是改善文本的可读性。认知心理学的研究证据表明,我们必须准确地识别每个字母和字母之间的间距来达到快速的处理目的。字母和单词如果是不对称的就被认为是不好的而且会降低阅读体验DirectWrite中的文本使用微软的ClearType技术,这个技术增强了文字的清晰度和可读性。ClearType利用了这一事实,现在液晶显示器每个像素都有RGB条纹而且是单独可控制的。DirectWrite采用了vista和WPF中对ClearType的最新改进,这使得不仅可以评估单个字母而且也可以评估字母之间的间距。在这些改善前,一个10或12点的“Reading”就很难显示,字母间距是1个像素的时候小,2个像素又太大。使用额外的分数间隔才能改善整个页面的对称性和均匀性。
ClearType的子像素定位提供了特别是小尺寸屏幕上的更精确的字符间距。其中一子像素和整个像素之间分别代表了图形宽度的重要的一部分。这就使得文字能够在理想的分辨率空间中进行测量并且以子像素的粒度渲染在LCD的color stripe的很自然的位置。采用这种技术衡量和渲染的文本是分辨率无关的,这就意味着跨越不同显示分辨率的精确相同布局的文字是可实现的。不像GDI的ClearType描画,子像素ClearType提供了最准确的字符的宽度。对于大字体,DirectWrite开启了y轴抗锯齿功能使得文字边界更平滑。
虽然DirectWrite文本是有位置的并且默认使用子像素ClearType渲染,但是其他的渲染选项也是有效的。许多程序都使用GDI去渲染程序的大部分,一些程序使用系统的编辑控件这些控件也是GDI渲染的。当给这些程序加入DirectWrite文本后,牺牲被子像素ClearType改善的阅读体验来达到整个应用一致的外观也是有必要的。
为了达到这样的需求,DirectWrite也提供了下面的渲染选项:
l 子像素ClearType(default)
l 子像素ClearType在水平和垂直方向都是抗锯齿的
l 别名文本。
l GDI natural-width(被微软ReadingView使用的)
l GDI compatible-width(包括东亚的嵌入式位图)
每一种渲染选项都能够用DirectWrite的API通过win7的inbox ClearType tuner(调谐器)进行微调。
API Overview
IDWriteFactory是使用DirectWrite功能的开始点,用于创建其他一系列的对象。
格式和布局操作是其他操作的先决条件,文本在被描画和点击测试之前需要正确的格式和布局,为这个目的被IDWriteFactory创建的两个关键对象是IDWriteTextLayout和IDWriteTextFormat对象。一个IDWriteTextFormat对象代表一个段落的格式化信息。IDWriteFactory::CreateTextLayout函数接受输入字符串,相关约束、尺寸和IDWriteTextFormat对象,全面地分析并格式化成IDWriteLayout用于接下来的操作。应用程序接下来就可以使用DrawTextLayout函数或者通过实现一个被GDI、Direct2D或其他描画系统提供的回调函数来渲染这个图形。对于单一格式的文本,DrawText函数提供了一种简单的方法来绘制文本儿不必先创建IDWriteTextLayout对象。
Accessing the Font System
除了通过IdwriteTextFormat接口具体化一个字体的family name外,DirectWrite还提供给应用程序更多的控制通过字体枚举、基于嵌入式文档字体创建自定义的字体集合。IDWriteFontCollection对象是一个字体家族的集合。DirectWrite提供了通过具体的font collection调用系统的字体集合来访问安装在系统上的字体集的功能。这个功能对应的API是IDWriteFactory::GetSystemFontCollection.应用程序也可以通过程序定义的回调函数创建自定义的字体集合,即被一个程序使用的私有字体或者嵌入在文档中的字体。程序可以调用GetFontFamily方法来获得一个字体集合中具体的FontFamily对象然后调用IDWriteFontFamily::GetFirstMatchingFont来获得一个具体的IDwriteFont对象,这个字体对象代表了字体集合中的一个字体和与之相关的属性和度量。IDWriteFontFace对象是另一个代表字体的对象,它导出了一种字体的完整的衡量标准。这个对象能够以一个font name直接创建,应用程序没有必要获取一个字体集合然后再去访问它。这个对象对于一个文本布局程序是很有用的,例如微软的Word,因为它们需要查询一种具体字体的细节。
下表总结了IDWriteFont和IDWriteFontFace两个对象的使用场景。
Category |
IDWriteFont |
IDWriteFontFace |
APIs to support user interaction such as a font-chooser user interface: description and other informational APIs |
Yes |
No |
APIs to support font mapping: family, style, weight, stretch, character coverage |
Yes |
No |
DrawText API |
Yes |
No |
APIs used for rendering |
No |
Yes |
APIs used for text layout: glyph metrics, and so on |
No |
Yes |
APIs for UI control and text layout: font-wide metrics |
Yes |
Yes |
Text rendering
文本描画APIs可以 渲染一个DirectWrite字体的字形到Direct2D的表面或者GDI设备独立位图,或者被转化成outlines或位图。DirectWrite中的ClearType渲染支持子像素定位改善了前一个windows版本上文字的清晰度和对比度。DirectWrite也支持aliased黑白字体用以支持带有位图的东亚字体这样的情况,这种情况下用户已禁用字体的任何类型平滑。所有的选项都是可调节的通过DirectWrite的APIs或者win7 ClearType调谐器的控制面板。
这里有两个渲染字形的APIs是有效的,一个通过Direct2D提供了硬件加速渲染,另一个提供的渲染到GDI位图的软件。使用IDWriteTextLayout和实现了IDWriteTextRenderer回调的程序都能使用这些函数来响应DrawGlyphRun回调函数,当然,实现了自定义的布局和字形数据的程序也能够使用这些APIs。
1、ID2DRenderTarget::DrawGlyphRun
使用Direct2D API DrawGlyphRun的程序通过使用GPU来实现硬件加速。硬件加速影响文字渲染管线的所有阶段,从merging glyphs into glyph runs 、过滤glyph-run位图,在最后的输出应用ClearType 混合算法。 这个是推荐的渲染性能比较好的API。
2、IDWriteBitmapRenderTarget::DrawGlyphRun
程序可以使用该方法可以执行一个run of glyphs的软件渲染到一个32bpp位图中。IDWriteBitmapRenderTarget封装了一个位图,一个内存设备内容用来渲染字形,如果想和GDI一起使用的话这个方法是很有用的。
如果你有一个使用GDI描画的独立文本布局代码的程序,你想保留现有布局的代码但只是用DirectWrite来为最后一步渲染字形。IDWriteGdiInterop::CreateFontFaceFromHdc在这两个APIs之间提供了一个桥梁。在调用这个函数之前,应用程序应该使用IDWriteGdiInterop::CreateFontFaceFromHdc函数从设备内容中获得一个font-face。
注意:大部分情况下,应用程序不需要使用这些文字渲染API,程序创建完IDWriteTextLayout后,可以直接调用该对象的DrawTextLayout函数来渲染文字。
GDI Interoperability
IDWriteGdiInterop接口提供了和GDI的互操作。这样就可以使得程序继续使用以前的GDI代码,也可以使用DirectWrite布局或渲染。下面的API可以使程序迁移到GDI字体系统或者从GDI迁移到DirectWrite。
CreateFontFromLOGFONT:用LOGFONT创建一个IDWriteFont对象
ConvertFontToLOGFONT:基于被IDWriteFont具体化的GDI兼容的属性初始化一个LOGFONT
ConvertFontFaceToLOGFONT:基于被IDWriteFontFace具体化GDI兼容的属性初始化一个LOGGONT结构体。
CreateFontFaceFromHdc:对应于当前选择的HFONT对象创建一个IDWriteFontFace对象。
Conclusion
改进阅读经历无论是在屏幕上还是在纸上对于用户来说都是很有价值的,DirectWrite为程序的开发者提供了易用性和分层的编程模型来改善文本的经验。应用程序能够使用layout的API为他们的界面或者文档描画丰富格式的文本。对于更复杂的场景,程序可以直接与字形打交道,可以访问字体等,并且可以利用DirectWrite的力量来提供高质量的排版。