Overview
Latin Script,软件开发者中使用最为广泛的script,同时也是在显示的时候最不复杂的script,特别是当用它来书写英语的时候。使用Latin Script,他们的字符可以被从左至右顺序显示,就像这些字符在内存中存储的顺序一样。有些scripts则需要一些比Latin script更为复杂的渲染的过程。我们把这些scripts称为“复杂scripts”,把用这些scripts书写的文本称为“复杂文本”。复杂scripts的例子有Indic scripts(比如,Devanagari,Tamil,Telugu 和Gujarati),Thai,和阿拉伯。
这些复杂scripts展示了Latin script所不曾有的复杂化。下面会列出复杂文本的主要的复杂化:
ICU LayoutEngine就是设计用来通过一个简单的一致的客户端接口来处理这些复杂化。客户端以读取或“逻辑”的顺序提供Unicode 代码点(Unicode的字符被称为代码点),然后LayoutEngine以正确的顺序,提供需要显示的字形及各个字形的位置信息。
由于ICU LayoutEngine是平台独立的,而文本渲染则固有的依赖于平台,因而LayoutEngine不能直接显示文本。它使用一个抽象的基类来访问字库文件。这个基类建模了某一特定点大小及设备解析度下的TrueType字库。TrueType字库有如下的这样一些特性:
- 一个字库是称为glyph的图片的集合。字库中的每一个Glyph通过一个16-bit的glyph id来引用。
- 有一个由Unicode 代码点到glyph ids的映射关系。字库文件中也许有一些glyphs没有映射。
- 字库包含了叫做4字节 tags(如, ''GSUB'', ''cmap')的数据表。这些表可以被读入内存做处理。
- 有一个方法可以去获取glyph的宽度。
- 有一个方法可以从glyph中获取控制点的位置。
由于复杂文本显示的许多上下文形式,练字,切分开的字符等没有Unicode代码点,因而他们就只能被他们的glyph 索引来指代。因而,LayoutEngine的输出是一个glyph 索引的列表。这意味着输出必须用一个接口来显示,在这个接口中,字符有glyph 索引来说明,而不是代码点。
必须为每一个目标平台都写一个这种基类的具体实例。一个简单的使用标准C库访问TrueType字库文件的例子,可以在 看PortableFontInstance类。
ICU LayoutEngine以如下的方式支持复杂文本:
- 如果字库含有OpenType的表,则LayoutEngine使用这些表。
- 如果字库含有Apple Advanced Typography (AAT)表,那么LayoutEngine使用这些表。
- 对于Arabic和Hebrew,如果没有OpenType表,则LayoutEngine使用Unicode描述形式。
- 对于Thai文本,LayoutEngine使用Microsoft或者Apple Thai形式。
OpenType处理过程在使用OpenType 表之前,,需要先完成某个script的特定处理。ICU LayoutEngine为Arabic,Devanagari,Bengali,Gurmukhi,Gujarati,Oriya,Tamil,Telegu,Kannada,和Malayalam文本执行这个处理。
由于它只在自左向右文本中应用默认的features,所以LayoutEngine中的AAT处理则相对简单。这个处理已经为Devanagari文本做过测试。由于AAT处理不是特定script的,它对其他scripts可能不起作用。
用ICU LayoutEngine 编程
ICU LayoutEngine 被设计出来用于处理一段文本,这段文本的所有glyph可以在相同的一个字库文件里面找到。这段文字具有一致的方向(自左向右或自右向左),同时具有相同的script。客户端可以使用ICU的 处理来确定文本的方向,并使用中的ScriptRun类来查找具有相同script的一段文本。由于字库文件信息的表示方法因应用而已,ICU无法协助查找这些文本段。
一旦文本已经被切分成了LayoutEngine可以处理的文本片段,则可以调用LayoutEngineFactory来创建一个特定于文本的LayoutEngine类的实例。下面的code演示了一个对于LayoutEngineFactory的调用:
LEFontInstace *font = |
下面的例子展示了如何使用LayoutEngine来处理文本:
LEUnicode text[] = |
前面的例子计算了三个数组:一个以显示顺序呈现的glyph索引的数组,一个每个glyph对应其中一个元素的(x,y)位置对的数组,和一个将输出的glyph映射回输入文本数组的数组。使用下面的get 方法来拷贝这些数组:
LEGlyphID *glyphs = new LEGlyphID[glyphCount];le_int32 *indices = new le_int32[glyphCount];float *positions = new float[(glyphCount * 2) + 2];engine->getGlyphs(glyphs, error);engine->getCharIndices(indices, error);engine->getGlyphPositions(positions, error); |
位置数组包含(glyphCount * 2) + 2项。这是由于每个glyph有一个x和一个y位置。额外的两个位置保存文本段末尾的x,y位置。 |
一旦用户获取了glyph 索引和位置,他们就可以使用特定于平台的code来画出glyphs了。比如,在Windows 2000上,用户可以用ETO_GLYPH_INDEX选项来调用ExtTextOut以画出glyph,而在Linux平台上,用户则可以调用 FT_Load_Glyph来获取每一个glyph的bitmap。然而,用户必须自己画出bitmaps。
ICU LayoutEngine是与ICU的其他部分分开开发的,因而它使用了不同的代码规范和基本类型。为了以ICU 代码规范来使用LayoutEngine,用户可以使用ICULayoutEngine类,这是LayoutEngine类的一个检点包装,而且它符合ICU conventions和基本类型。 |
关于如何调用LayoutEngine更详细的例子,可以参考 。这是一个简单的用于验证LayoutEngine是否正常工作的一个测试。它没有做任何的复杂文本的渲染。
更多详情,请参考 ,和。