ICU Layout Engine

Overview

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

  1. 一个字库是称为glyph的图片的集合。字库中的每个Glyph经过一个16-bit的glyph id来引用。
  2. 有一个由Unicode 代码点到glyph ids的映射关系。字库文件中也许有一些glyphs没有映射。
  3. 字库包含了叫作4字节 tags(如, ''GSUB'', ''cmap')的数据表。这些表能够被读入内存作处理。
  4. 有一个方法能够去获取glyph的宽度。
  5. 有一个方法能够从glyph中获取控制点的位置。

因为复杂文本显示的许多上下文形式,练字,切分开的字符等没有Unicode代码点,于是他们就只能被他们的glyph 索引来指代。于是,LayoutEngine的输出是一个glyph 索引的列表。这意味着输出必须用一个接口来显示,在这个接口中,字符有glyph 索引来讲明,而不是代码点。 ide

必须为每个目标平台都写一个这种基类的具体实例。一个简单的使用标准C库访问TrueType字库文件的例子,能够在 icu/source/test/letestPortableFontInstance类。 测试

ICU LayoutEngine以以下的方式支持复杂文本: ui

  1. 若是字库含有OpenType的表,则LayoutEngine使用这些表。
  2. 若是字库含有Apple Advanced Typography (AAT)表,那么LayoutEngine使用这些表。
  3. 对于Arabic和Hebrew,若是没有OpenType表,则LayoutEngine使用Unicode描述形式。
  4. 对于Thai文本,LayoutEngine使用Microsoft或者Apple Thai形式。

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 编程

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是否正常工做的一个测试。它没有作任何的复杂文本的渲染。

更多详情,请参考 ICUOpenType SpecificationTrueType Font File Specification

相关文章
相关标签/搜索