Latin Script,软件开发者中使用最为普遍的script,同时也是在显示的时候最不复杂的script,特别是当用它来书写英语的时候。使用Latin Script,他们的字符能够被从左至右顺序显示,就像这些字符在内存中存储的顺序同样。有些scripts则须要一些比Latin script更为复杂的渲染的过程。咱们把这些scripts称为“复杂scripts”,把用这些scripts书写的文本称为“复杂文本”。复杂scripts的例子有Indic scripts(好比,Devanagari,Tamil,Telugu 和Gujarati),Thai,和阿拉伯。 html
这些复杂scripts展现了Latin script所未曾有的复杂化。下面会列出复杂文本的主要的复杂化: 编程
ICU LayoutEngine就是设计用来经过一个简单的一致的客户端接口来处理这些复杂化。客户端以读取或“逻辑”的顺序提供Unicode 代码点(Unicode的字符被称为代码点),而后LayoutEngine以正确的顺序,提供须要显示的字形及各个字形的位置信息。 数组
因为ICU LayoutEngine是平台独立的,而文本渲染则固有的依赖于平台,于是LayoutEngine不能直接显示文本。它使用一个抽象的基类来访问字库文件。这个基类建模了某一特定点大小及设备解析度下的TrueType字库。TrueType字库有以下的这样一些特性: app
因为复杂文本显示的许多上下文形式,练字,切分开的字符等没有Unicode代码点,于是他们就只能被他们的glyph 索引来指代。于是,LayoutEngine的输出是一个glyph 索引的列表。这意味着输出必须用一个接口来显示,在这个接口中,字符有glyph 索引来讲明,而不是代码点。 ide
必须为每个目标平台都写一个这种基类的具体实例。一个简单的使用标准C库访问TrueType字库文件的例子,能够在 icu/source/test/letest看PortableFontInstance类。 测试
ICU LayoutEngine以以下的方式支持复杂文本: ui
OpenType处理过程在使用OpenType 表以前,,须要先完成某个script的特定处理。ICU LayoutEngine为Arabic,Devanagari,Bengali,Gurmukhi,Gujarati,Oriya,Tamil,Telegu,Kannada,和Malayalam文本执行这个处理。 spa
因为它只在自左向右文本中应用默认的features,因此LayoutEngine中的AAT处理则相对简单。这个处理已经为Devanagari文本作过测试。因为AAT处理不是特定script的,它对其余scripts可能不起做用。 设计
ICU LayoutEngine 被设计出来用于处理一段文本,这段文本的全部glyph能够在相同的一个字库文件里面找到。这段文字具备一致的方向(自左向右或自右向左),同时具备相同的script。客户端能够使用ICU的Bidi 处理来肯定文本的方向,并使用icu/source/extra/scrptrun中的ScriptRun类来查找具备相同script的一段文本。因为字库文件信息的表示方法因应用而已,ICU没法协助查找这些文本段。 代码规范
一旦文本已经被切分红了LayoutEngine能够处理的文本片断,则能够调用LayoutEngineFactory来建立一个特定于文本的LayoutEngine类的实例。下面的code演示了一个对于LayoutEngineFactory的调用:
LEFontInstace *font = <the text's font>; UScriptCode script = <the text's script>; LEErrorCode error = LE_NO_ERROR; LayoutEngine *engine; engine = LayoutEngine::layoutEngineFactory(font, script, 0, // language - ignored error); |
下面的例子展现了如何使用LayoutEngine来处理文本:
LEUnicode text[] = <the text to process>; le_int32 offset = <the starting offset of the text to process>; le_int32 count = <the number of code points to process>; le_int32 max = <the total number of characters in text>; le_bool rtl = <true if the text is right-to-left, false otherwise>; float x, y = <starting x, y position of the text>; le_int32 glyphCount; glyphCount = engine->layoutChars(text, offset, count, max, rtl, x, y, error); |
前面的例子计算了三个数组:一个以显示顺序呈现的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更详细的例子,能够参考 icu/source/test/letest/letest.cpp。这是一个简单的用于验证LayoutEngine是否正常工做的一个测试。它没有作任何的复杂文本的渲染。
更多详情,请参考 ICU,OpenType Specification和TrueType Font File Specification。