Glyph定义(GDEF)表在5个独立的表中包含5种类型的信息:
GSUB和GPOS表可能会引用某一GDEF表的信息。比如,“OpenType Layout通用表格式”里的LookupFlag bit enumeration。
在文字处理过程中,一个客户端可能会使用5个GDEF表中的任何一个或多个。这个概览将解释一下那5个表中的每一个是如何组织,并被使用的(参见 Figure 7a)。
本章的剩余部分将描述独立的GDEF表及他们引用的表。
Figure 7a. High-level organization of GDEF table
Glyph类别定义(GlyphClassDef)表描述了一个字库中四种类型的glyphs:base glyphs,ligature glyphs,combining mark glyphs,和glyph components(参见Figure 7b)。GSUB和GPOS lookups定义并使用这些glyph类别来区别子串中glyphs的类型。比如,GPOS使用glyph类别来区分一个简单的base glyph及其后面跟着的mark glyph。
Figure 7b. A base glyph, ligature glyph, mark glyph, and glyph components
此外,一个客户端使用类别定义来正确的应用GSUB和GPOS LookupFlag数据。比如,一个LookupFlag可能会在一个glyph操作期间专门忽略ligatures和marks。如果字库没有包含一个GlyphClassDef 表,则在使用GSUB和GPOS表时,客户端必须定义并维护这些信息。
Attachment Point List Table(AttachmentList)描述了所有定义在GPOS中的attachment点及他们相关的glphs,从而使得一个客户端可以快速的访问每一个glyph的attachment点的坐标。因此,客户端可以缓存连同glyph bitmaps一起的attachment点的坐标,并避免每次显示一个glyph是都重复计算attachment点。没有这个表,由于客户端将不得不解码定义了attachment 点的GPOS lookups并将点编译进一个列表,则处理速度会更慢。
Ligature Caret List 表(LigatureCaretList),在Arabic和其他具有许多连笔字符的script中特别有用,为在字库中所有的连笔字符上放置插入字符(carets)描述了坐标。客户端可以使用这些数据来选择和高亮显示的子串中连笔字符组成部分(参见 Figure 7c)。
Figure 7c. Proper ligature caret postioning
每一个连笔字符可以具有多于一个的插入字符(caret)位置,依据于script或language system的书写的方向,每一个位置用一个baseline上的X或Y值来定义。字库开发者可以使用三种格式中的任何一种来表示一个插入字符(caret)的坐标值。一种格式只用设计单位来表示值,另一种基于一个设计的轮廓点来调整值,第三种使用一个设备表来调整特定字体大小下的值。
没有一个Ligature Caret List表的话,客户端将不得不在不知道连笔字符成分的情况下,定义插入字符(caret)的位置。最终的高亮或者点击测试可能是引起歧义的。比如,假设一个客户端将一个插入字符(caret)沿着宽度放在假想的一个“wi”连笔字符的中间点位置。由于“w”比“i”更宽,那个位置将不能清楚地表明所选择的成分是哪一个。反而,为了精确的选择,那个插入字符(caret)应该向右移,以使得“w”或“i”可以被清晰地高亮起来。
GDEF表以一个表头开始,表头以一个版本号(Version)开始,当前只定义了0x00010000和0x00010002。一个GDEF表头也包括,到定义了字库中glyphs类型的表(GlyphClassDef)的偏移,到定义了glyphs上的attachment点的列表的偏移(AttachList),一个到连笔字插入字符列表(LigCaretList)的偏移,还有一个到定义了可被附加的marks的类型的列表的偏移(MarkAttachClassDef)。用于MarkAttachClassDef的格式与用于GlyphClassDef的相同。请参考通用表格式中“LookupFlag bit enumeration”一节关于这些成员的信息来获取关于使用lookup标志的更多的信息。
本章结尾处的示例1显示了一个GDEF Header表。GDEF表头的格式0x00010000 组织如下:
Type | Name | Description |
---|---|---|
ULONG | Version | Version of the GDEF table-currently 0x00010000 |
Offset | GlyphClassDef | Offset to class definition table for glyph type-from beginning of GDEF header (may be NULL) |
Offset | AttachList | Offset to list of glyphs with attachment points-from beginning of GDEF header (may be NULL) |
Offset | LigCaretList | Offset to list of positioning points for ligature carets-from beginning of GDEF header (may be NULL) |
Offset | MarkAttachClassDef | Offset to class definition table for mark attachment type-from beginning of GDEF header (may be NULL) |
GDEF表头的格式0x00010002 包含一个额外的指向一个定义了mark glyphs集合定义的列表的偏移量(MarkGlyphSetDef):
Type | Name | Description |
---|---|---|
ULONG | Version | Version of the GDEF table-currently 0x00010002 |
Offset | GlyphClassDef | Offset to class definition table for glyph type-from beginning of GDEF header (may be NULL) |
Offset | AttachList | Offset to list of glyphs with attachment points-from beginning of GDEF header (may be NULL) |
Offset | LigCaretList | Offset to list of positioning points for ligature carets-from beginning of GDEF header (may be NULL) |
Offset | MarkAttachClassDef | Offset to class definition table for mark attachment type-from beginning of GDEF header (may be NULL) |
Offset | MarkGlyphSetsDef | Offset to the table of mark set definitions - from beginning of GDEF header (may be NULL) |
GSUB和GPOS表使用Glyph类别定义表(GlyphClassDef)来描述通过lookups要调整那种glyph类别。
这个表所使用的格式与类别定义表(更详细的情况,请参考通用表格式一章)相同。然而,GlyphClassDef表使用已经定义在GlyphClassDef Enumeration列表里的类别值:
Class | Description |
---|---|
1 | Base glyph (single character, spacing glyph) |
2 | Ligature glyph (multiple character, spacing glyph) |
3 | Mark glyph (non-spacing combining glyph) |
4 | Component glyph (part of single character, spacing glyph) |
字库开发者不一定非要为字库中的每一个glyph都进行分类,但任何一个没有分配类别值的glyph将会落入Class 0中。比如,类别值可能对于字库中的Arabic glyphs很有用,但对Latin glyphs没有用。则GlyphClassDef表将只列出Arabic glyphs,并且—默认地—Latin glyphs将被分配到Class 0里去。Component glyphs可以放在一起以形成连笔字符。一个连笔字符可以通过创建字库中的一个引用了component glyphs的glyph来形成,或者以所需的顺序输出component glyphs来形成。定义任何GSUB或GPOS的格式中不会用到component glyphs。
本章结尾处的示例2定义了一个GlyphClassDef表,其中具有一个被分配了类别值的示例glyph。
Attachment List Table(AttachList)可能被用于缓存连同glyph bitmaps一起的attachment 点的坐标。
这个表由指向了Coverage表(Coverage)的一个偏移量,具有attachment点的glyphs的个数(GlyphCount),及一个偏移量的数组组成,其中Coverage表列出了GPOS表中定了attachment 点的所有glyphs,偏移量的数组中每个成员指向一个AttachPoint表(AttachPoint)。数组列出了AttachPoint表,Coverage表中的每个glyph一个,以与Coverage Index相同的顺序列出。
Type | Name | Description |
---|---|---|
Offset | Coverage | Offset to Coverage table - from beginning of AttachList table |
uint16 | GlyphCount | Number of glyphs with attachment points |
Offset | AttachPoint[GlyphCount] | Array of offsets to AttachPoint tables-from beginning of AttachList table-in Coverage Index order |
一个AttachPoint表由在单个glyph上的attachment点的个数(PointCount),和那些点的轮廓索引(PointIndex)数组组成,其中数组中所列的轮廓索引以数值的增序排列。
本章结尾处的示例3演示了一个AttachList表,其中为两个glyphs定义了attachment点。
Type | Name | Description |
---|---|---|
uint16 | PointCount | Number of attachment points on this glyph |
uint16 | PointIndex[PointCount] | Array of contour point indices -in increasing numerical order |
Ligature Caret List表(LigCaretList)为字库中的所有连笔字符定义了插入字符(caret )的位置。这个表由一个指向了Ceverage表的偏移量(Coverage),定义的连笔字符的个数(LigGlyphCount),和一个偏移量的数组组成,其中Coverage表列出了所有的连笔字符,偏移量数组中的每一项都指向一个LigGlyph表(LigGlyph)。数组列出了LigGlyph表,Coverage表中的每个连笔字符一项,其列出的顺序与Coverage Index一致。
本章结尾处的示例4显示了一个LigCaretList表。
Type | Name | Description |
---|---|---|
Offset | Coverage | Offset to Coverage table - from beginning of LigCaretList table |
uint16 | LigGlyphCount | Number of ligature glyphs |
Offset | LigGlyph[LigGlyphCount] | Array of offsets to LigGlyph tables-from beginning of LigCaretList table-in Coverage Index order |
一个Ligature Glyph表(LigGlyph)包含单个连笔字glyph的插入字符(caret)坐标。坐标值的个数等于连笔字符中成分的个数减去1,而每个坐标值则在一个分开的CaretValue表中定义。
LigGlyph表由为连笔字符定义的CaretValue表的个数(CaretCount),和一个到CaretValue表(CaretValue)的偏移量的数组组成.
本章结尾处的示例4显示了一个LigGlyph表。
Type | Name | Description |
---|---|---|
uint16 | CaretCount | Number of CaretValues for this ligature (components - 1) |
Offset | CaretValue[CaretCount] | Array of offsets to CaretValue tables-from beginning of LigGlyph table-in increasing coordinate order |
一个Caret Values表(CaretValues),为一个连笔字符定义了插入字符(caret)的位置,它可能具有三种可能的格式中的任何一种。一种格式使用设计单位来定义插入字符(caret)的位置。另外的两种格式使用一个轮廓点或设备表来调整某个特定字体大小和设备分辨率下插入字符(caret)的位置。依赖于文字的方向昂,插入字符(caret)坐标是X或者Y值中的一种。
第一种格式(CaretValueFormat1)由一个格式标识符(CaretValueFormat),和紧随其后的插入字符(caret)的单个坐标(Coordinate)组成。坐标是在设计空间的。
这个格式的好处是大小比较小,并且比较简单,但是Coordinate值无法被hinted以便于为不同的设备分辨率优化调整。
本章结尾处的示例4显示了一个CaretValueFormat1表。
Type | Name | Description |
---|---|---|
uint16 | CaretValueFormat | Format identifier-format = 1 |
int16 | Coordinate | X or Y value, in design units |
第二种格式(CaretValueFormat2)依据一个特定的glyph上一个轮廓点的索引来描述插入字符(caret)坐标。在字库hinting过程中,glyph轮廓上的轮廓点可能会移动。hinting之后点的最终位置为渲染一个给定字体大小提供了最终的值。
这个表包含一个格式标识符(CaretValueFormat)和一个轮廓点索引(CaretValuePoint)。
本章结尾处的示例5演示了一个CaretValueFormat2表。
Type | Name | Description |
---|---|---|
uint16 | CaretValueFormat | Format identifier-format = 2 |
uint16 | CaretValuePoint | Contour point index on glyph |
第三种格式(CaretValueFormat3)也是在设计空间描述值,但它使用一个设备表而不是一个轮廓点来调整值。这种格式的好处是,可以为任何设备分辨率优调Coordinate值。(更多关于设备表的信息,可以参考章节,通用表格式。)
这个格式由一个格式标识符(CaretValueFormat),一个X或Y值(Coordinate),和到一个设备表(DeviceTable)的偏移组成。
本章结尾处的示例6显示了一个CaretValueFormat3表。
CaretValueFormat3 table: Design units plus Device table
Type | Name | Description |
---|---|---|
uint16 | CaretValueFormat | Format identifier-format = 3 |
int16 | Coordinate | X or Y value, in design units |
Offset | DeviceTable | Offset to Device table for X or Y value-from beginning of CaretValue table |
一个Mark Attachment Class Definition Table为那些一个mark glyph可能隶属于它的glyph定义类别。这个表使用与类别定义表相同的格式(欲知详情,请参考章节,通用表格式)。
这份文档的示例7显示了一个MarkAttachClassDef表。
GSUB和GPOS lookups中使用mark glyph集合来过滤字串中的哪些marks被考虑,而哪些要被忽略。Mark glyph集合在一个MarkGlyphSets表中定义,它包含一些指向了独立的集合的偏移量,每个独立的集合由一个标准的Coverage表表示:
Type | Name | Description |
---|---|---|
uint16 | MarkSetTableFormat | Format identifier == 1 |
uint16 | MarkSetCount | Number of mark sets defined |
ULONG | Coverage [MarkSetCount] | Array of offsets to mark set coverage tables. |
Mark glyph集被用于和mark attachment classes相同的目的,即作为GSUB和GPOS lookups的过滤器。然而,mark glyph集与mark attachment classes不同,依据字库开发者的需要mark glyph集可以交叉。至于mark attachment classes,在任何给定的lookup中只有一个mark glyph集可以被引用。
注意Coverage表的偏移量的数组使用了ULONG,而不是Offset。
本章剩余的部分将描述所有的GDEF表格式的例子。
示例1显示了一个GDEF表的表头定义,其中包含了到GDEF中主要的表的偏移量。还是使用在OpenType字库文件一文中所使用的那个蒙古文字库文件monbaiti.ttf。由那篇文章最后的例子里,解出来的字库文件头的一些信息,我们可以知道GDEF表的偏移量为0x00049EFC,长度为(0x0000002A = 42)。我们可以看一下在GDEF表中都有些什么东西:
迅速的扫一眼,我们看到在表头的Version部分为0x00010000,因而它是格式0x00010000的表头,它没有MarkGlyphSetsDef。解出GDEF表表头:
类型 | ULONG |
Offset |
Offset |
Offset |
Offset |
字段名 | Version |
GlyphClassDef |
AttachList |
LigCaretList |
MarkAttachClassDef |
实际值 | 0x00010000 | 0x000C | 0x0000 | 0x0022 | 0x0000 |
在示例2中描述了一个GlyphClassDef表,还是使用上个例子中的那个字库文件monbaiti.ttf,GlyphClassDef表的偏移量为0x000C,在文件中的偏移量应该为0x49F08。扫一眼ClassFormat的位置,可以看到是0x0002,因而它是ClassDefFormat2表。参照
OpenType™ Layout通用表格式一文中的相关说明,将GlyphClassDef表的内容解出来:
类型 | uint16 |
uint16 |
字段名 | ClassFormat |
ClassRangeCount |
实际值 | 0x0002 | 0x0003 |
可以看到在这个GlyphClassDef表中,有3个ClassRangeRecord,他们分别是:
字段名(类型) | Start(GlyphID) |
End(GlyphID) |
Class(uint16) |
ClassRangeRecord1 |
0x0000 | 0x06E2 | 0x0001 (base glyphs) |
ClassRangeRecord2 |
0x06E3 | 0x06E3 | 0x0003 (mark glyphs) |
ClassRangeRecord3 |
0x06E4 | 0x071F | 0x0001 (base glyphs) |
在示例3中显示了一个LigCaretList表。还是使用上个例子中的那个字库文件monbaiti.ttf。可以看到LigCaretList表的偏移值为0x0022,所以它在文件中的偏移量应该为0x49f1E。
类型 | Offset |
uint16 |
字段名 | Coverage |
LigGlyphCount |
实际值 | 0x0004 | 0x0000 |
Done。