GPOS - Glyph定位表

Glyph定位表(GPOS)爲一個字庫所支持的每種script和language system裏複雜的文本佈局及渲染提供了關於glyph 放置的精確的控制。 api

概覽

複雜的glyph定位在一些書寫系統中變成了一個問題,好比Vietnamese,它使用了diacritical和其餘的marks來改變字符的讀音或意義。爲了易讀性及語言上的精確,這些書寫系統須要控制全部的marks彼此之間的放置。 數組


Figure 4a. Vietnamese words with marks.
app

其餘的書寫系統爲了正確的排版組合而須要複雜的glyph定位。好比,Urdu glyphs是繕寫的,而且沿着一條降低的傾斜的自右向左前進的文本線彼此鏈接。爲了適當地渲染Urdu,一個文字處理客戶端必須同時修改每一個glyph的水平(X)和豎直(Y)位置。 ide


Figure 4b. Urdu layout requires glyph positioning control, as well as contextual substitution
佈局

經過GPOS表,一個字庫開發者能夠在一個 OpenType™字庫中定義一個完整的位置調整features集合。GPOS數據,經過script和language system來組織,被一個文字處理客戶端用於定位glyphs是很簡單的。 字體

經過TrueType 1.0來定位Glyphs

TrueType中的Glyph定位只使用兩個值,placement和advance,來爲文本佈局描述一個glyph的位置。若是說glyphs是相對於一個沿着一條文本的線移動的虛擬的「pen point」來定位的話,則placement描述了相對於當前的「pen point」的glyph位置,而advance則描述了爲了定位下一個glyph而須要把pen point移向何處(參見Figure 4c)。對於水平文字,placement對應於左邊的bearing,而advance對應於advance寬度。 ui


Figure 4c. Glyph positioning with TrueType
this

TureType僅能爲水平佈局在X方向上描述placement和advance,而爲豎直佈局在Y方向上描述這些值。對於簡單的Latin文本佈局,要正確的定位glyphs,這兩個值可能足夠了。可是,對於那些須要更復雜的佈局的文本,則用於定位的值必須覆蓋一個更豐富的範圍。Placement和advance可能須要在豎直方向上作調整,同時也須要在水平方向上作調整。 spa

TrueType中所定義的僅有的定位調整數據是pair kerning,它改變了兩個glyphs之間水平方向上的間隔。一個典型的kerning表列出了glyphs對,並描述了一個文字處理客戶端應該爲glyphs之間加上或去掉多大的間隔來適當的顯示每一個glyphs對。它不提供關於如何調整每一對中的glyphs的特定信息,而且不能調整多於兩個glyphs的上下文。 設計

經過OpenType來定位Glyphs

OpenType字庫爲定位一個單獨的glyph或定位多個glyphs彼此之間的位置提供了出色的控制和靈活性。經過同時使用GPOS表爲placement和advance所定義的X和Y值,並經過使用glyph attachment點,一個客戶端能夠更精確地調整一個glyph的位置。

此外,GPOS表能夠引用一個Device表來定義subtle,在任何字體大小和設備分辨率下依賴於設備的調整任何的placement或advance。好比,一個Device表能夠指定在51 pixel per em(ppem)下的調整值,但50ppem下則不會發生。

OpenType字庫中爲放置操做所描述的X和Y值是在典型的笛卡爾座標系統內的(原點在左邊的base上),而不管是什麼樣的書寫方向。此外,字庫中所描述的全部的值是以font unit度量的。這一點對於字庫設計者特別方便,由於glyphs是在相同的座標系中畫出來的。然而,須要注意的重要的一點是「advance width」的含義改變了,它依賴於書寫方向。

好比,在自左向右的scripts裏,若是第一個glph的advance寬度爲100,則第二個glyph將在100.0處開始畫,。在自右向左的scripts裏,若是第一個glyph的advance寬度爲100,則第二個glyph將在-100.0處開始畫。對於一個top-to-bottom的feature,爲了將一個glyph的advance 高度增長100,則YAdvance = 100。對於任何的feature,無論書寫方向,爲了將一個‘o’上的分音符號(dieresis)下降10個單位,則設置YPlacement = -10。

其餘的GPOS features能夠定義attachment點來結合glyphs並定位它們彼此之間的位置。一個glyph可能具備多個attachment點。這些點的使用將會依賴於被attached的glyph。好比,一個base glyph可能會爲不一樣的diacritical marks而有不一樣的attachment點。


Base glyph with multiple attachment points.

爲了減少字庫文件的大小,一個base glyph也許會爲全部的分配了一個特定類別的mark glyphs使用相同的attachment點。好比,一個base glyph可能有兩個attachment點,一個在glyph的上面,而另外一個在下面。而後全部的依附到glyphs上邊的marks將被依附在高的點上,全部的依附到glyphs下邊的marks將被依附到低的點上。Attachment點在某些scripts頗有用,好比Arabic,它會給元音marks結合許多的glyphs。 

Attachment點對於鏈接草書的glyphs也頗有用。cursive 字庫中的glyphs能夠被設計來在渲染時依附或重疊。做爲選擇,字庫開發者可使用OpenType來建立一個cursive attachment feature併爲每一個glyph定義顯式地退出和進入attachment點(參見Figure 4d)。


Figure 4d. Entry and exit points marked on contextual Urdu glyph variations

GPOS表爲定位和attaching glyphs而支持8種類型的行爲:

一個single adjustment定位一個glyph,好比一個上標或下標。

一個pair adjustment 定位兩個glyphs彼此之間的位置。Kerning是pair adjustment的一個例子。

一個cursive attachment描述了cursive scripts和其餘的在渲染時與attachment點鏈接的glyphs。

一個MarkToBase attachment定位combining marks相對於base glyphs的位置,好比定位Arabic,Hebrew和Vietnamese中的元音(vowels),diacritical marks,或tone marks。

一個MarkToLigature attachment定位combining marks相對於連字glyphs的位置。因爲連字可能具備多個用於依附marks的點,字庫開發者須要將每一個mark關聯到連字的其中一個glyph組件上。

一個MarkToMark attachment定位一個mark相對於另外一個的位置,好比在Vietnamese中定位tone marks相對於vowel diacritical marks的位置。

Contextual positioning描述了在一個可識別的特定的glyphs,glyphs類別或多變的glyphs集合的序列內,如何在上下文中定位一個或多個glyphs。在「輸入」上下文序列中可能會執行一個或多個定位操做。Figure 4e描述了一個須要定位調整的上下文。

Chaining Contextual positioning描述瞭如何在一個連接的上下文中定位一個或多個glyphs,在一個可識別的特定的glyphs,glyphs類別或多變的glyphs集合的序列內。在「輸入」上下文序列中可能會執行一個或多個定位操做。


Figure 4e. Contextual positioning lowered the accent over a vowel glyph that followed an overhanging uppercase glyph

表的組織

GPOS表以一個表頭開始,表頭定義了到一個ScriptList,一個FeatureList和一個LookupList的偏移量(參見Figure 4f):

  • ScriptList描述了字庫中使用了glyph定位操做的全部scripts和language systems。
  • FeatureList定義了渲染這些scripts和language systems所需的全部的glyph定位features。
  • LookupList包含了實現每一個glyph定位feature所需的全部lookup數據。

關於ScriptLists,FeatureLists和LookupLists的詳細討論,請參考OpenType通用表格式。下面的討論將總結GPOS表是如何工做的。


Figure 4f. High-level organization of GPOS table

GPOS表用這種方式進行組織,以使得文字處理客戶端能夠簡單地定位應用於一個特定的script或language system的features和lookups。爲了訪問GPOS信息,客戶端應該使用下面的過程:

  1. 在GPOS ScriptList表中定位當前的script。
  2. 若是language system已知,則搜索script表來找到正確的LangSys表;不然,使用script的默認language system(DefaultLangSys表)。
  3. LangSys表提供了指到GPOS FeatureList表內去的索引數字,客戶端以此來訪問一個所需的feature和許多附加的features。
  4. 檢查每一個feature的FeatureTag,並選擇應用於一個輸入glyph串的features。
  5. 每一個feature提供了一個指向GPOS LookupList表內部的索引值的數組。lookup數據被定義在一個或多個子表中,子表中包含有關於特定的glyphs的信息及將要在它們上面執行的操做的種類。
  6. 由選擇的feature集合收集全部的lookups,並以LookupList表中定義的順序應用這些lookups。

一個lookup使用子表來定義用於實現一個feature的定位行爲的特定的條件,類型和結果。一個lookup中全部的子表必須具備相同的LookupType,LookupType如LookupType Enumeration表中所列的那樣:

LookupType Enumeration table for glyph positioning

Value Type Description
1 Single adjustment Adjust position of a single glyph
2 Pair adjustment Adjust position of a pair of glyphs
3 Cursive attachment Attach cursive glyphs
4 MarkToBase attachment Attach a combining mark to a base glyph
5 MarkToLigature attachment Attach a combining mark to a ligature
6 MarkToMark attachment Attach a combining mark to another mark
7 Context positioning Position one or more glyphs in context
8 Chained Context positioning Position one or more glyphs in chained context
9 Extension positioning Extension mechanism for other positionings
10+ Reserved For future use (set to zero)

每一個Lookup都經過一個或多個子表來定義,子表的格式則依賴於定位操做的類型,及產生的存儲效率。當glyph信息用多於一種格式來表示最好時,一個單獨的lookup也許會定義多於一個的子表,只要全部的子表具備相同的LookupType便可。好比,一個給定的lookup內,一個glyph索引數組格式多是表示一個目標glyphs集合的最好格式,而一個glyph索引範圍格式對於另一個集合可能更好。相同glyph或子串上的一系列定位操做須要多個lookups,每一個分開的行爲一個。這些狀況下,ValueRecords中的值被累積起來。每一個lookup會被給定一個LookupList表中的不一樣的數組號,而且它們會被以LookupList中的順序應用。

在文字處理過程當中,一個客戶端在移向下一個lookup以前,會對字串中的每個glyph應用一個lookup。對於一個glyph的處理,一個lookup會在客戶端定位到了目標glyph或glyph上下文並執行了一個定位操做(若是指定了的話)以後結束。爲了移向「下一個」glyph,客戶端典型地會跳過全部參與了當前lookup操做的glyphs:被調整位置的glyphs,還有爲操做造成了一個上下文的任何其餘glyphs。

僅有一個例外:一個序列中的「下一個」glyph多是爲剛剛執行的操做造成了一個上下文的那些glyphs中的一個。好比,在pair定位操做(好比,kerning)的情形中,若是第二個glyph的position value record是null,則那個glyph將被看成是序列中的「下一個」glyph。

本章的剩餘部分將會描述GPOS表頭,和爲每種LookupType定義的子表。一些GPOS子表共享其餘的一些表:ValueRecords,Anchor表,和MarkArrays。爲了簡單的引用,被共享的表在本章的結尾處描述。

GPOS表頭

GPOS表以一個表頭開始,它包含有一個最初被設爲1.0(0x00010000)的版本號(Version),和到三個表的偏移量:ScriptList,FeatureList和LookupList。關於這些表的描述,請參考章節, OpenType Common Table Formats。本章結尾處的示例1顯示了一個GPOS表頭的定義。

GPOS Header

Value Type Description
Fixed Version Version of the GPOS table-initially = 0x00010000
Offset ScriptList Offset to ScriptList table-from beginning of GPOS table
Offset FeatureList Offset to FeatureList table-from beginning of GPOS table
Offset LookupList Offset to LookupList table-from beginning of GPOS table

LookupType1:Single Adjustment Positioning Subtable

一個single adjustment positioning子表(SinglePos)被用於調整單個的glyph的位置,好比一個上標或下標。此外,一個SinglePos子表一般被用於爲上下文定位實現lookup數據。

一個SinglePos子表將具備兩種格式中的一種:一種給一系列的glyphs應用相同的adjustment,或者一種爲每一個惟一的glyph應用一個不一樣的adjustment。

Single Adjustment Positioning: Format 1

一個SinglePosFormat1子表給Coverage表中所列出的每一個glyph應用相同的定位值或多個值。例如,當一個字庫使用了老式的數字符號時,這種格式能夠被應用於統一地下降全部的數組符號glyphs的位置。

Format 1子表有一個格式標識符(PosFormat),一個到一個定義了將經過定位值而被調整的glyphs的Coverage表的偏移量(Coverage),及格式標識符(ValueFormat)組成,格式標識符(ValueFormat)描述了ValueRecord中數據的數量和種類。

ValueRecord描述了應用於全部覆蓋的glyphs的一個或多個定位值(Value)。好比,若是Coverage表中全部的glyphs既須要水平調整,又須要豎直的調整,則ValueRecord將既爲XPlacement,又爲YPlacement指定值。

本章結尾處的示例2顯示了一個用於調整上標glyphs placement的SinglePosFormat1子表。

SinglePosFormat1 subtable: Single positioning value

Value Type Description
uint16 PosFormat Format identifier-format = 1
Offset Coverage Offset to Coverage table-from beginning of SinglePos subtable
uint16 ValueFormat Defines the types of data in the ValueRecord
ValueRecord Value Defines positioning value(s)-applied to all glyphs in the Coverage table

Single Adjustment Positioning: Format 2

一個SinglePosFormat2子表提供了一個ValueRecords的數組,其中爲Coverage表中的每一個glyph包含了一個定位值。這種格式相對於Format 1更加的靈活,但它也須要字庫文件中更多的空間。

好比,假設Cyrillic script將被用於左對齊的文本。則對於全部的glyphs,Format 2能夠爲左邊bearings定義位置調整數據來對齊段落的左邊界。爲了達到這一點,Coverage表將列出script中的每個glyph,而且SinglePosFormat2子表將爲每一個覆蓋的glyph定義一個ValueRecord。相應地,每一個ValueRecord將爲左邊bearing指定一個XPlacement調整值。

注意:定義在一個SinglePos子表中的全部的ValueRecord必須具備相同的ValueFormat。在這個例子中,若是XPlacement是一個ValueRecord在光學地對齊glyphs時所需的僅有的值,則XPlacement將是子表的ValueFormat中所描述的僅有的值。

如在Format 1中的同樣,Format 2子表由一個格式標識符(PosFormat),一個到 一個 定義了將經過定位值而被調整的glyphs的Coverage表的偏移量(Coverage),及一個格式標識符(ValueFormat)組成,格式標識符(ValueFormat)描述了ValueRecord中數據的數量和種類。此外,Format 2子表還包括:

一個ValueRecords的個數(ValueCount)。爲Coverage表中的每一個glyph定義一個ValueRecord。

一個ValueRecords的數組,描述了定位值(Value)。因爲這個數組聽從Coverage Index順序,則第一個ValueRecord應用於Coverage表中所列出的第一個glyph,以此類推。

本章結尾處的示例3顯示瞭如何經過一個SinglePosFormat2子表調整三個dash glyphs的間隔。

SinglePosFormat2 subtable: Array of positioning values

Value Type Description
uint16 PosFormat Format identifier-format = 2
Offset Coverage Offset to Coverage table-from beginning of SinglePos subtable
uint16 ValueFormat Defines the types of data in the ValueRecord
uint16 ValueCount Number of ValueRecords
ValueRecord Value
[ValueCount]
Array of ValueRecords-positioning values applied to glyphs

Lookup Type 2: Pair Adjustment Positioning Subtable

一個pair adjustment positioning子表(PairPos)被用於調整兩個glyphs彼此之間的位置-好比,來爲glyphs對描述kerning數據。然而,相比於一個典型的kerning表,一個PairPos子表提供了更多的靈活性及關於glyph定位的精確的控制。PairPos子表能夠同時在X和Y方向上獨立地調整一個pair中的每一個glyph,而且能夠顯式地描述應用於每一個glyph的特定的調整類型。此外,一個PairPos子表可使用Device表在每種字體大小及設備分辨率下,精細地調整glyph的位置。

PairPos子表能夠是兩種格式中的一種:一種經過索引獨立地描述glyphs(Format 1),或者一種經過類別來描述glyphs(Format 2)。

Pair Positioning Adjustment: Format 1

Format 1使用glyph索引來爲一個或多個glyph對訪問定位數據。全部的pair被描述的順序有文本的佈局方向來決定。

注意:對於自右向左書寫的文字,最右端的glyph將是glyph對中的第一個glyph;相反地,對於自左向右書寫書寫的文字,最左端的glyph是第一個。

一個PairPosFormat1子表包含一個格式標識符(PosFormat)和兩個ValueFormats:

  • ValueFormat1應用於每一個pair中第一個glyph的ValueRecord。全部第一個glyphs的ValueRecords必須都使用ValueFormat1。若是ValueFormat1被設爲0,則對應的glyph沒有ValueRecord,而且,不該該被調整位置。
  • ValueFormat2應用於每一個pair中第二個glyph的ValueRecord。全部第二個glyphs的ValueRecords必須都使用ValueFormat2。若是ValueFormat2被設爲null,則pair中的第二個glyph將是一個lokkup應該被執行於其上的「下一個」glyph。

一個PairPos子表也定義了一個到一個Coverage表的偏移量(Coverage),其中列出了每一個pair中第一個glyph的索引。多於一個的pair可使用相同的首glyph,但Coverage表將只列出那個glyph一次。

這個子表也包含一個到PairSet表的偏移量的數組(PairSet)及一個其定義的表的個數(PairSetCount)。PairSet數組爲Coverage表中所列出的每一個glyph包含一個偏移量,並使用與Coverage Index相同的順序。

PairPosFormat1 subtable: Adjustments for glyph pairs

Value Type Description
uint16 PosFormat Format identifier-format = 1
Offset Coverage Offset to Coverage table-from beginning of PairPos subtable-only the first glyph in each pair
uint16 ValueFormat1 Defines the types of data in ValueRecord1-for the first glyph in the pair -may be zero (0)
uint16 ValueFormat2 Defines the types of data in ValueRecord2-for the second glyph in the pair -may be zero (0)
uint16 PairSetCount Number of PairSet tables
Offset PairSetOffset
[PairSetCount]
Array of offsets to PairSet tables-from beginning of PairPos subtable-ordered by Coverage Index

一個PairSet枚舉出了全部以一個覆蓋的相同的glyph開始的glyphs對。一個PairValueRecords數組(PairValueRecord)爲每一個pair包含一個記錄,並以每一個pair中第二個glyph的GlyphID爲序列出記錄。PairValueCount描述了集合中PairValueRecords中的個數。

PairSet table

Value Type Description
uint16 PairValueCount Number of PairValueRecords
struct PairValueRecord
[PairValueCount]
Array of PairValueRecords-ordered by GlyphID of the second glyph

一個PairValueRecord描述了一個pair中的第二個glyph(SecondGlyph),併爲每一個glyph定義了一個ValueRecord(Value1和Value2)。若是在PairPos子表中ValueFormat1被設爲了0,ValueRecord1將會是空的;相似地,若是ValueFormat2是0,則Value2將是空的。

本章結尾處的示例4顯示了一個PairPosFormat1子表,其中定義了兩個pair kerning的cases。

PairValueRecord

Value Type Description
GlyphID SecondGlyph GlyphID of second glyph in the pair-first glyph is listed in the Coverage table
ValueRecord Value1 Positioning data for the first glyph in the pair
ValueRecord Value2 Positioning data for the second glyph in the pair

Pair Positioning Adjustment: Format 2

Format 2將一個pair定義爲一個兩glyph類別的集合,而且改變一個類別中全部的glyphs的位置。好比,這個格式在Japanese scripts就頗有用,其中對包含了標點符號glyphs的全部glyphs對應用特定的kerning操做。一個類別將被定義爲全部的可能與標點符號marks結合的glyphs,而另外一個類別將會是類似的標點符號glyphs的羣組。

PairPos Format 2子表以一個格式標識符(PosFormat)和一個到一個Coverage表的偏移量(Coverage)開始,其中偏移量湊PairPos子表的開始處計算起。其中Coverage表中列出了每一個glyph對中可能出現的第一個glyphs的索引。多個pair可能以相同的glyph開始,但Coverage表只列出那個glyph索引一次。

一個PairPosFormat2子表也包含兩個ValueFormat2:

  • ValueFormat1應用於每一個pair中第一個glyph的ValueRecord。全部的第一個glyph的ValueRecords必須都使用ValueFormat1。若是ValueFormat1被設爲了0,則對應的glyph沒有ValueRecord,而且於是不該該被從新定位。
  • ValueFormat2應用於每一個pair中第二個glyph的ValueRecord。全部第二個glyphs的ValueRecords必須都使用ValueFormat2。若是ValueFormat2被設爲null,則pair中的第二個glyph將是一個lokkup應該被執行於其上的「下一個」glyph。

PairPosFormat2須要全部pair中的每一個glyph被分配一個類別,而類別則經過一個稱爲類別值的整數來識別。(關於類別的詳細信息,請參考章節,OpenType通用表格式。)而後Pairs在一個二維數組中被表示爲一個兩類別值的序列。多個pairs可能在一個一個Format 2子表中表示。

一個PairPosFormat2子表包含了到兩個類別定義表的偏移量:一個給全部pairs中的第一個glyphs分配類別值(ClassDef1),一個給全部pairs中的第二個glyphs分配類別值(ClassDef2)。若是一個pair中的兩個glyphs使用相同的類別定義,則ClassDef1和ClassDef2的偏移值能夠是相同的,但它們不須要必定是相同的。這個子表也肯定了定義在ClassDef1中glyph類別值的個數(Class1Count),及ClassDef2中glyph類別值的個數(Class2Count),包括Class 0。

對於ClassDef1表中所肯定的每一個類別值,一個Class1Record枚舉了全部包含了一個特定的類別做爲第一個組件的pairs。Class1Record數組依據類別值存儲全部的Class1Records。

注意:Class1Records不是經過一個類別值標識符來標記的。反而是數組中一個Class1Record的索引值定義了由那個記錄所表明的類別值。好比,第一個Class1Record枚舉了以一個Class 0glyph開始的pairs,第二個Class2Record枚舉了以一個Class 1glyph開始的pairs,以此類推。

PairPosFormat2 subtable: Class pair adjustment

Value Type Description
uint16 PosFormat Format identifier-format = 2
Offset Coverage Offset to Coverage table-from beginning of PairPos subtable-for the first glyph of the pair
uint16 ValueFormat1 ValueRecord definition-for the first glyph of the pair-may be zero (0)
uint16 ValueFormat2 ValueRecord definition-for the second glyph of the pair-may be zero (0)
Offset ClassDef1 Offset to ClassDef table-from beginning of PairPos subtable-for the first glyph of the pair
Offset ClassDef2 Offset to ClassDef table-from beginning of PairPos subtable-for the second glyph of the pair
uint16 Class1Count Number of classes in ClassDef1 table-includes Class0
uint16 Class2Count Number of classes in ClassDef2 table-includes Class0
struct Class1Record
[Class1Count]
Array of Class1 records-ordered by Class1

每一個Class1Record包含一個Class2Records的數組(Class2Record),它也是以類別值來排序的。必須爲ClassDef2表中的每一個類別都聲明一個Class2Record,包括Class 0。

Class1Record

Value Type Description
struct Class2Record[Class2Count] Array of Class2 records-ordered by Class2

一個Class2Record由兩個ValueRecords組成,一個爲一個class pair中的第一個glyph(Value1),一個爲第二個glyph(Value2)。若是PairPos子表中,ValueFormat1或ValueFormat2的值爲0,則對應的記錄(ValueRecord1或ValueRecord2)將是空的。

本章結尾處的示例5演示了經過一個PairPosFormat2子表中的glyph類別實現的pair kerning。

Class2Record

Value Type Description
ValueRecord Value1 Positioning for first glyph-empty if ValueFormat1 = 0
ValueRecord Value2 Positioning for second glyph-empty if ValueFormat2 = 0

Lookup Type 3: Cursive Attachment Positioning Subtable

一些cursive字庫被設計出來,以使得相鄰的glyphs在經過他們默認的定位操做被渲染時結合在一塊兒。然而,若是結合glyphs須要定位調整,那麼一個cursive attachment positioning (CursivePos) 子表能夠描述如何經過對齊兩個錨點(anchor points)來鏈接glyphs:一個glyph指定的退出點和緊跟其後的glyph指定的入口點。

這種子表具備一種格式:CursivePosFormat1。它以一個格式標識符(PosFormat)及一個到一個Coverage表的偏移量(Coverage)開始,其中Coverage表列出了定義了cursive attachment數據的全部glyphs。

此外,這種子表爲Coverage表中所列的每一個glyph包含有一個EntryExitRecord,這種子表還包含有那些記錄的個數(EntryExitCount),及一個與Coverage Index相同順序排序的那些記錄的數組(EntryExitRecord)。

CursivePosFormat1 subtable: Cursive attachment

Value Type Description
uint16 PosFormat Format identifier-format = 1
Offset Coverage Offset to Coverage table-from beginning of CursivePos subtable
uint16 EntryExitCount Number of EntryExit records
struct EntryExitRecord[EntryExitCount] Array of EntryExit records-in Coverage Index order

每一個EntryExitRecord由兩個偏移量組成:一個指向描述了glyph上的入口點的Anchor表(EntryAnchor),一個指向描述了glyph上的退出點的Anchor點(ExitAnchor)。(關於Anchor表的一個完整的描述,請參見本章的結尾處。)

爲了使用CursivePosFormat1子表來定位glyphs,一個文字處理客戶端將一個glyph的ExitAnchor點和它後面的glyph的EntryAnchor點對齊。若是沒有對應的錨點(anchor points)出現,則EntryAnchor或者ExitAnchor偏移量多是NULL。

本章結尾處,示例6描述了Urdu語言中的cursive glyph attachment。

EntryExitRecord

Value Type Description
Offset EntryAnchor Offset to EntryAnchor table-from beginning of CursivePos subtable-may be NULL
Offset ExitAnchor Offset to ExitAnchor table-from beginning of CursivePos subtable-may be NULL

Lookup Type 4: MarkToBase Attachment Positioning Subtable

MarkToBase attachment (MarkBasePos) 子表用於定位combining mark glyphs相對於base glyphs的位置。好比,Arabic,Hebrew和Thai scripts會把元音(vowels),diacritical marks和tone marks結合到baseglyphs。

在MarkBasePos子表中,每個mark glyph具備一個錨點(anchor point)並與一個mark類別關聯起來。每一個base glyph會爲它使用的每種marks類別定義一個錨點(anchor point)。

好比,假設兩種mark類別:全部定位於base glyphs上方的marks(Class 0),及全部定位於base glyphs下方的marks(Class 1)。在這種情形中,使用這些marks的每一個base glyph將定義兩個錨點(anchor point),一個用於附上Class 0中所列出的mark glyphs,一個用於附上Class 1中所列出的mark glyphs。

爲了肯定結合了一個mark的base glyph,文字處理客戶端必須由glyph串中base glyph前面的mark回頭日後看。爲告終合mark和base glyph,客戶端將對齊它們的attachment點,相對於base glyph最終的pen point (advance)位置定位mark。

MarkToBase Attachment子表具備一種格式:MarkBasePosFormat1。該子表以一個格式標識符(PosFormat)及到兩個Coverage表的偏移量開始:一個列出了全部在該子表中引用的mark glyphs (MarkCoverage),一個列出了全部在該子表中引用的base glyphs (BaseCoverage)。

對於MarkCoverage表中的每一個mark glyph,一個記錄肯定了他的類別和一個到它的Anchor表的偏移量,其中Anchor表描述了mark的attachment點 (MarkRecord)。一個mark類別經過一個稱爲類別值的特定整數來識別。ClassCount肯定了全部MarkRecords中所定義的獨特的mark類別的總數。

MarkBasePosFormat1子表也包含一個到一個MarkArray表的偏移量,其中包含有經過MarkCoverage Index存儲於一個數組中的全部的MarkRecords(MarkRecord)。一個MarkArray表也包含有所定義的MarkRecords的個數(MarkCount)。(關於MarkArrays和MarkRecords的詳細信息,請參見本章的結尾處。)

MarkBasePosFormat1子表也包含一個到一個BaseArray表的偏移量(BaseArray)。

MarkBasePosFormat1 subtable: MarkToBase attachment point

Value Type Description
uint16 PosFormat Format identifier-format = 1
Offset MarkCoverage Offset to MarkCoverage table-from beginning of MarkBasePos subtable
Offset BaseCoverage Offset to BaseCoverage table-from beginning of MarkBasePos subtable
uint16 ClassCount Number of classes defined for marks
Offset MarkArray Offset to MarkArray table-from beginning of MarkBasePos subtable
Offset BaseArray Offset to BaseArray table-from beginning of MarkBasePos subtable

BaseArray表由一個數組(BaseRecord)和BaseRecords的個數(BaseCount)組成。數組以與BaseCoverage Index相同的順序存儲了BaseRecords。BaseCoverage表中的每一個base glyph都有一個BaseRecord。

BaseArray table

Value Type Description
uint16 BaseCount Number of BaseRecords
struct BaseRecord[BaseCount] Array of BaseRecords-in order of BaseCoverage Index

一個BaseRecord爲MarkArray的MarkRecords中肯定的每一個mark類別(包括Class 0)聲明一個Anchor表。每一個Anchor表爲base glyph肯定一個用於附上一個特定類別中全部marks的attachment點。一個BaseRecord包含一個到Anchor表的偏移量的數組(BaseAnchor)。基於0的偏移量數組定義了base glyph用於附上mark的attachment 點的完整的集合。

注意:Anchor表不是經過類別值標識符來標記的。相反,數組中一個Anchor表的索引值定義了由該Anchor表表示的類別值。

本章結尾處的示例7經過一個MarkBasePosFormat1子表定義了base glyph上面及下面的mark定位。

BaseRecord

Value Type Description
Offset BaseAnchor[ClassCount] Array of offsets (one per class) to Anchor tables-from beginning of BaseArray table-ordered by class-zero-based

Lookup Type 5: MarkToLigature Attachment Positioning Subtable

MarkToLigature attachment(MarkLigPos)子表用於定位combining mark glyph相對於連字base glyphs的位置。經過前述MarkToBase attachment,一個單獨的base glyph爲mark的每種類別定義一個attachment點。與此相比,MarkToLigature attachment描述了多個組件組合而成的連字glyph,其中每一個組件均可覺得mark的每種類別定義一個attachment點。

於是,對於marks的每種類別,一個連字glyph可能具備多個base attachment點。對於一個mark的特定的attachment點是由連字的組件(其子表與mark關聯在一塊兒)來定義的。

MarkLigPos子表能夠被用於定義多個mark-to-ligature attachments。在這種子表中,每一個mark glyph具備一個錨點(anchor point)並被與一個marks類別關聯在一塊兒。每一個連字glyph指定了一個二維的數據數組:一個連字中的每一個組件定義了一個錨點(anchor point)的數組,每一個marks類別都有一個錨點。好比,假設兩種mark類別:全部定位於base glyphs上方的marks(Class 0),及全部定位於base glyphs下方的marks(Class 1)。在這種情形中,一個base連字glyph的每一個組件均可以定義兩個錨點(anchor point),一個用於附上Class 0中所列出的mark glyphs,一個用於附上Class 1中所列出的mark glyphs。做爲選擇,若是language system不容許在第二個組件上面附上marks,則定一個連字組件也許會定義兩個錨點(anchor point),marks的每種類別一個,而第二個連字組件也許會不定義錨點(anchor point)

爲了使用一個MarkToLigature attachment子表來定位一個combining mark,文字處理客戶端必須從連字glyph前面的mark向後執行。爲了正確地訪問這種子表,客戶端必須跟蹤與相應的mark關聯在一塊兒的組件。對齊attachment點來結合相應的mark和連字。

MarkToLigature attachment子表具備一種格式:MarkLigPosFormat1。這種子表以一個格式標識符(PosFormat)和到兩個Coverage表的偏移量開始,其中Coverage表中列出了這種子表中引用的全部的mark glyphs (MarkCoverage)和連字glyphs (LigatureCoverage)。

對於MarkCoverage表中的每一個glyph,一個MarkRecord肯定了他的類別及一個到它的Anchor表的偏移量,其中Anchor表中描述了那個mark的attachment。一個mark類別是經過一個稱爲類別值的特定整數來標識的。ClassCount記錄了全部MarkRecords中所定義的不一樣mark類別的個數。

MarkBasePosFormat1子表包含一個偏移量,由該子表的起始處計算,指向一個MarkArray表,而該表則以MarkCoverage Index的順序在一個數組中存儲了全部的MarkRecords。(關於MarkArrays和MarkRecords的詳細信息,請參見本章的結尾處。)

MarkBasePosFormat1子表也包含一個到一個LigatureArray表的偏移量(LigatureArray)。

MarkLigPosFormat1 subtable: MarkToLigature attachment

Value Type Description
uint16 PosFormat Format identifier-format = 1
Offset MarkCoverage Offset to Mark Coverage table-from beginning of MarkLigPos subtable
Offset LigatureCoverage Offset to Ligature Coverage table-from beginning of MarkLigPos subtable
uint16 ClassCount Number of defined mark classes
Offset MarkArray Offset to MarkArray table-from beginning of MarkLigPos subtable
Offset LigatureArray Offset to LigatureArray table-from beginning of MarkLigPos subtable

LigatureArray表包含一個個數(LigatureCount),及一個到LigatureAttach表的偏移量的數組(LigatureAttach)。LigatureAttach數組列出了到LigatureAttach表的偏移量,LigatureCoverage表中所列出的每一個連字glyph一個,以與LigatureCoverage Index相同的順序。

LigatureArray table

Value Type Description
uint16 LigatureCount Number of LigatureAttach table offsets
Offset LigatureAttach
[LigatureCount]
Array of offsets to LigatureAttach tables-from beginning of LigatureArray table-ordered by LigatureCoverage Index

每一個LigatureAttach表由一個數組(ComponentRecord)及一個連字中組件glyphs的個數(ComponentCount)組成。數組以與連字中組件相同的排序存儲了ComponentRecords。記錄的排序也對應於位子的書寫方向。對於自左向右書寫的文字,第一個組件在左邊;對於自右向左書寫的文字,第一個組件在右邊。

LigatureAttach table

Value Type Description
uint16 ComponentCount Number of ComponentRecords in this ligature
struct ComponentRecord[ComponentCount] Array of Component records-ordered in writing direction

ComponentRecord,連字中的每一個組件一個,包含一個到相應的Anchor表的偏移量的數組,其中Anchor表定義了用於將attach附到相應的組件上的全部attachment點(LigatureAnchor)。對於MarkArray records中標識的每種mark類別(包括Class 0),會有一個Anchor表描述用於將一個特定的類別中全部的marks附到連字base glyph的點,相對於組件而言。

在一個ComponentRecord中,基於0的LigatureAnchor數組根據類別列出了到Anchor表的偏移量。若是一個組件不爲一個特定的mark類別定義attachment點,則到相應的Anchor表的偏移量將會是NULL。

本章結尾處的示例8顯示了一個在Arabic script中用於將mark accent附到一個連字glyph的MarkLisPosFormat1子表。

ComponentRecord

Value Type Description
Offset LigatureAnchor
[ClassCount]
Array of offsets (one per class) to Anchor tables-from beginning of LigatureAttach table-ordered by class-NULL if a component does not have an attachment for a class-zero-based array

Lookup Type 6: MarkToMark Attachment Positioning Subtable

MarkToMark attachment (MarkMarkPos) 子表與MarkToBase attachment的形式一致的,儘管它的功能不一樣。MarkToMark attachment定義了一個mark相對於另外一個mark的位置,好比,在Vietnamese中,定位tone marks相對於vowel diacritical marks的位置。

衣服的mark是Mark1,被依附的base mark是Mark2。在MarkMarkPos子表中,每一個Mark1 glyph具備一個anchor attachment point並與一個marks類別關聯起來。每一個Mark2 glyph爲每種marks類別定義一個錨點(anchor point)。好比,設想有兩個Mark1類別:全部放在Mark2 glyphs左邊的marks(Class 0),和全部放在Mark2 glyphs右邊的marks(Class 1)。使用了這些marks的每一個Mark2 glyph會定義兩個錨點(anchor point):以用於依附Class 0中所列出的Mark1 glyphs,一個用於依附Class 1中所列出的Mark1 glyphs。

與一個Mark1 gylph結合的Mark2 glyph是glyph串中相應的Mark1 glyph前面的那個glyph(可能會依據LookupFlags而跳過一些glyphs)。The subtable applies precisely when that Mark2 glyph is covered by Mark2Coverage. 爲告終合mark glyphs,相應的Mark1 glyph會被移動,以使得相關的attachment points可以重合。MarkToBase,MarkToLigature和MarkToMark定位表的輸入上下文是被定位的那個mark。若是一個序列包含有多個marks,一個lookup能夠在它上面屢次執行來定位它們。

MarkToMark attachment子表只有一種格式:MarkMarkPosFormat1。這種子表以一個格式標識符(PosFormat)和兩個到Coverage表的偏移量開始,一個Coverage表會列出這種子表中引用的全部Mark1 glyphs (Mark1Coverage),另外一個會列出這種子表中引用的全部Mark1 glyphs (Mark2Coverage)。

對於Mark1Coverage表中的每一個mark glyph,一個MarkRecord會描述它的類別幷包含一個指向其Anchor表的偏移量,而Anchor表則描述了mark的attachment點。一個mark類別用一個稱爲類別值的特殊整數來標識。(關於類別的更詳細的信息,請參考章節,OpenType通用表格式。) ClassCount指定了定義在MarkRecords中不一樣的mark類別的總個數。

MarkMarkPosFormat1子表也包含兩個偏移量,由該子表的起始位置算起,指向兩個數組:

  • MarkArray表以Mark1Coverage Index的順序將全部的MarkRecords包含於一個數組中(MarkRecord)。MarkArray表也包含有所定義的MarkRecords的個數(MarkCount)。
  • Mark2Array表由一個數組(Mark2Record)和Mark2Records的個數(Mark2Count)組成。

關於MarkArrays和MarkRecords的詳細信息,請參考本章的末尾處的說明。

MarkMarkPosFormat1 subtable: MarkToMark attachment

Value Type Description
uint16 PosFormat Format identifier-format = 1
Offset Mark1Coverage Offset to Combining Mark Coverage table-from beginning of MarkMarkPos subtable
Offset Mark2Coverage Offset to Base Mark Coverage table-from beginning of MarkMarkPos subtable
uint16 ClassCount Number of Combining Mark classes defined
Offset Mark1Array Offset to MarkArray table for Mark1-from beginning of MarkMarkPos subtable
Offset Mark2Array Offset to Mark2Array table for Mark2-from beginning of MarkMarkPos subtable

Mark2Array,接下來顯示,爲Mark2Coverage表中所列的每一個Mark2 glyph包含有一個Mark2Record。它以與Mark2Coverage Index相同的順序存儲那些records。

Mark2Array table

Value Type Description
uint16 Mark2Count Number of Mark2 records
struct Mark2Record
[Mark2Count]
Array of Mark2 records-in Coverage order

每一個Mark2Record包含一個到Anchor表的偏移量的數組(Mark2Anchor)。基於0的偏移量數組,由Mark2Array表的起始位置算起,定義了用於將Mark1 glyphs依附於一個特定的Mark2 glyph的Mark2 attachment點的完整集合。Mark2Anchor數組中的Anchor表以Mark1的類別值來排序。

一個Mark2Record會爲MarkArray的MarkRecords中所肯定的每一個mark類別(包括 Class 0)都聲明一個Anchor表。每一個Anchor表描述一個用於將一個特定類別中全部的Mark1 glyph依附於相應的Mark2 glyph上的Mark2 attachment點。

本章結尾處的示例9顯示了一個在Arabic script中,用於將一個mark依附於另外一個mark的MarkMarkPosFormat1子表。

Mark2Record

Value Type Description
Offset Mark2Anchor
[ClassCount]
Array of offsets (one per class) to Anchor tables-from beginning of Mark2Array table-zero-based array

Lookup Type 7: Contextual Positioning Subtables

ContextPositoning(ContextPos)子表定義了最爲強大的一種glyph定位lookup類型。它描述了上下文中的glyph定位操做,從而一個文字處理客戶端能夠調整某一glyphs模式中的一個或多個glyphs的位置。每一個子表描述了一個或多個「輸入」glyph序列及將會在那個序列上執行的一個或多個定位操做。

ContextPos能夠是三種格式中的一種,這三種格式與用於上下文glyph置換的格式對應。一種格式。一種格式適用於特定的glyph序列(Format 1),一種按照glyph類別來定義上下文(Format 2),而第三種格式則依照glyphs集合來定義上下文(Format 2)。

ContextPos子表的全部三種格式都在一個PosLookupRecord中描述定位數據。下面是那種record的一個描述。

PosLookupRecord

全部的上下文定位子表都在一個PosLookupRecord中描述定位數據。每一個record包含一個SequenceIndex,它指示了glyph序列中定位操做所發生的地方。此外,一個LookupListIndex肯定了將在由SequenceIndex所指示的glyph位置上應用的lookup

lookups被應用於整個glyph序列的順序,被稱爲「設計順序」,多是很是重要的,於是,PosLookupRecord數據也應該照着來定義。

示例10,11和12中所定義的上下文定位表展現了PosLookupRecords。

PosLookupRecord

Value Type Description
uint16 SequenceIndex Index to input glyph sequence-first glyph = 0
uint16 LookupListIndex Lookup to apply to that position-zero-based

Context Positioning Subtable: Format 1

Format 1將一個glyph定位操做的上下文定義爲一個特定的glyphs序列。好比一個上下文多是<To>,<xyzabc>,<!?*#@>或任何其餘的glyph序列。

在上下文內,Format 1將特定的一些glyph位置(不是glyph索引)標識爲特定的調整的目標。當文本處理客戶端定位到了一個子串中的一個上下文時,它經過應用爲一個目標位置所定義的lookup data來執行位置調整。

好比,suppose that accent mark glyphs above lowercase x-height vowel glyphs must be lowered when an overhanging capital letter glyph precedes the vowel。當客戶端在文字中定位到了這個上下文時,相應的子表肯定了重音符號的位置及一個lookup索引。一個lookup詳述了一個下降元音上的重音符號的位置以使得它不與overhanging capital產生衝突的定位行爲。

ContextPosFormat1在兩個地方定義上下文。一個Coverage表詳述了輸入序列中的第一個glyph,而一個PosRule表則肯定了其他的glyphs。爲了描述前面例子中使用的上下文,Coverage表列出了那個序列的第一個組件的glyph索引(overhanging capital),而一個PosRule表則爲lowercase x-height vowel glyph和重音符號定義了索引。

一個單獨的ContextPosFormat1子表也許會定義多於一個上下文glyph序列。若是不一樣的上下文序列以相同的glyph開始,則相應的Coverage表應該只列出那個glyph一次,由於Coverage表中全部的首glyphs都必須是惟一的。好比,若是有三個上下文每一個都以一個「s」開始,有兩個上下文每一個都以一個「t」開始,則相應的Coverage表中將只列出一個「s」和一個「t」。

對於每一個上下文,會有一個PosRule表順序列出全部跟在首glyph後面的glyphs。這個表也包含有一個PosLookupRecords的數組,其中爲上下文中的每一個glyph位置(包括第一個glyph位置)詳述了定位lookup數據。

全部定義了以相同的首glyph開始的上下文的PosRule會被分爲一組並被定義在一個PosRuleSet表中。好比,三個定義了以「s」開頭的上下文的PosRule表被分爲一組並放進一個PosRuleSet表中,兩個定義了以t」開頭的上下文的PosRule表被分爲一組並放進另外一個PosRuleSet表中。Coverage表中所列出的每一個惟一的glyph都必須具備一個PosRuleSet表來爲一個覆蓋的glyph定義全部的PosRule表。

爲了定位一個上下文glyph序列,文本處理客戶端在每次遇到一個新的文字glyph時都會在Coverage表中搜索。若是Coverage表中存在那個glyph,則客戶端就讀取對應的PosRuleSet表並檢查這個集合中的每一個PosRule表來肯定其中定義的上下文的剩餘部分是否與文字中後面的glyphs匹配。若是上下文與子串匹配,則客戶端會查找目標glyph位置,爲那個位置應用相應的lookup,並完成定位行爲。

一個ContextPosFormat1子表包含一個格式標識符(PosFormat),一個到一個Coverage表的偏移量(Coverage),一個所定義的PosRuleSets的個數(PosRuleSetCount),及一個到PosRuleSet表的偏移量的數組(PosRuleSet)。如前所述,必須爲Coverage表中所列出的每一個glyph定義一個PosRuleSet表。

在PosRuleSet數組中,PosRuleSet表是以Coverage Index的順序排序的。數組中的第一個PosRuleSet應用於Coverage表中所列出的第一個GlyphID,數組中的第二個PosRuleSet應用於Coverage表中所列出的第二個GlyphID,依此類推。

ContextPosFormat1 subtable: Simple context positioning

Value Type Description
uint16 PosFormat Format identifier-format = 1
Offset Coverage Offset to Coverage table-from beginning of ContextPos subtable
uint16 PosRuleSetCount Number of PosRuleSet tables
Offset PosRuleSet
[PosRuleSetCount]
Array of offsets to PosRuleSet tables-from beginning of ContextPos subtable-ordered by Coverage Index

一個PosRuleSet表由一個以任意順序排列的到PosRule表的偏移量的數組(PosRule),及集合中所定義的PosRule表的個數(PosRuleCount)組成。

 PosRuleSet table: All contexts beginning with the same glyph

Value Type Description
uint16 PosRuleCount Number of PosRule tables
Offset PosRule
[PosRuleCount]
Array of offsets to PosRule tables-from beginning of PosRuleSet-ordered by preference

一個PosRule表包含有一個輸入上下文序列中被匹配的glyphs的個數(GlyphCount),包括序列中的第一個glyph,及描述了那個上下文的glyph索引的數組(Input)。Coverage表說明了上下文中第一個glyph的索引,則Input數組以上下文序列中的第二個glyph開始。所以,數組中的第一個索引位置是指定數組1,而不是0。Input數組以對應的glyphs出現的順序列出了字串中的glyph索引。對於自右向左書寫的文本,最右端的glyph將是第一個;相反地,對於自左向右書寫的文本,最左端的glyph將是第一個。

一個PosRule表也包含一個將在輸入glyph序列上被執行的定位操做的個數(PosCount)及一個PosLookupRecords的數組(PosLookupRecord)。每一個record都指定了一個輸入glyph序列中的位置,及一個將在那個位置應用的定位lookup的LookupList索引。數組應該以設計順序列出記錄,或者lookups應該被應用於整個glyph序列的順序。

本章結尾處的示例10演示了經過一個ContextPosFormat1子表來實現的上下文中的glyph kerning。

PosRule subtable

Value Type Description
uint16 GlyphCount Number of glyphs in the Input glyph sequence
uint16 PosCount Number of PosLookupRecords
GlyphID Input
[GlyphCount - 1]
Array of input GlyphIDs-starting with the second glyph
struct PosLookupRecord[PosCount] Array of positioning lookups-in design order

Context Positioning Subtable: Format 2

Format2,相對於Format1更加靈活,描述了基於類別的上下文定位。對於這種格式,一個稱爲類別值的特定整數必須被分配給全部的上下文glyph序列中的每一個glyph組件。而後上下文被定義爲glyph類別值的序列。這種子表可能在同一時間定義多個的上下文。

爲了闡明基於類別的上下文規則的概念,設想某些三glyphs的序列須要特殊的kerning。該glyph序列由一個懸在右邊的大寫字母glyph,一個標點符號glyph,及一個引用(quote) glyph組成。在這種狀況下,大寫字母glyphs的集合將構成一個glyph類別(Class 1),標點符號glyph的集合將構成第二個glyph類別(Class 2),及引用符號glyphs的集合將構成第三個glyph類別(Class 3)。輸入上下文也許會用一個上下文規則來指定(PosClassRule),其中規則描述爲「造成了三glyphs類別序列的glyph串的集合,一個glyph來自於Class 1,後面跟一個來自於Class 2的glyph,再後面跟一個來自於Class 3的glyph。」

每一個ContextPosFormat2子表都包含一個到一個類別定義表的偏移量(ClassDef),其中定義了該子表描述的輸入上下文中全部的glyphs的類別值。一般,會爲一個字庫中包含的每個ContextPosFormat2子表實例都聲明一個惟一的ClassDef,儘管多個Format 2子表也能夠共享ClassDef表。類別是互斥集;在同一時間一個glyph不能屬於多個類別。替換上下文序列中的glyphs的輸出glyphs不須要類別值,由於它們是在其餘地方用GlyphID來描述的。

ContextPosFormat2子表也包含一個格式標識符(PosFormat),並定義有一個到一個Coverage表的偏移量(Coverage)。對於這種格式,Coverage表將列出可能成爲任何一個基於類別的上下文的首glyph的glyphs的完整集合中每一個glyph的glyph索引(而不是類別)。換句話說,Coverage表爲全部的上下文類別序列中可能成爲首class的全部classes中包含的glyphs包含了glyph索引的列表。好比,若是上下文以一個Class 1或Class 2的glyph開始,則Coverage表將列出全部Class 1和Class 2 glyphs的索引。一個ContextPosFormat2子表也定義了一個到PosClassSet表的偏移量的數組(PosClassSet),及一個PosClassSet表的個數(包括Class 0)(PosClassSetCnt)。在該數組中,PosClassSet表以類別值的升序(從0到PosClassSetCnt - 1)來排序。

一個PosClassSet數組爲每種glyph類別都包含一個偏移量,包括Class 0。PosClassSets不是顯式地用一個類別值來標記的;而是,PosClassSet在PosClassSet數組中的索引值定義了一個PosClassSet所表示的類別。好比,數組中所列的第一個PosClassSet包含全部定義了以一個Class 0 glyphs爲起始glyph的上下文的PosClassRules,第二個PosClassSet包含全部定義了以一個Class 1 glyphs爲起始glyph的上下文的PosClassRules,依此類推。若是沒有以一個特定類別開始的PosClassRules(即,若是一個PosClassSet不包含有PosClassRules),則PosClassSet數組中到那個特定的PosClassSet的偏移量將被設爲NULL。

ContextPosFormat2 subtable: Class-based context glyph positioning

Value Type Description
uint16 PosFormat Format identifier-format = 2
Offset Coverage Offset to Coverage table-from beginning of ContextPos subtable
Offset ClassDef Offset to ClassDef table-from beginning of ContextPos subtable
uint16 PosClassSetCnt Number of PosClassSet tables
Offset PosClassSet
[PosClassSetCnt]
Array of offsets to PosClassSet tables-from beginning of ContextPos subtable-ordered by class-may be NULL

定義了以相同的類別爲起始類別的上下文的全部的PosClassRules被分組在一塊兒並被定義在一個PosClassSet表中。所以,PosClassSet表自己肯定了一個上下文的第一個組件的類別。

一個PosClassSet枚舉了全部以一個特定的glyph類別開始的PosClassRules。好比PosClassSet0表示全部的PosClassRules,其中的每個都描述了以Class 0 glyph開始的上下文;PosClassSet1表示全部的PosClassRules,其中的每個都描述了以Class 1 glyph開始的上下文。

每一個PosClassSet表由一個該PosClassSet中所定義的PosClassRules的個數(PosClassRuleCnt)及一個到PosClassRule表的偏移量的數組(PosClassRule)組成。PosClassSet的PosClassRule數組中的PosClassRule以任意順序排序。

PosClassSet table: All contexts beginning with the same class

Value Type Description
uint16 PosClassRuleCnt Number of PosClassRule tables
Offset PosClassRule[PosClassRuleCnt] Array of offsets to PosClassRule tables-from beginning of PosClassSet-ordered by preference

對於每一個上下文,一個PosClassRule表爲它包含了一個給定上下文中glyph類別的個數(GlyphCount),包括上下文序列中的第一個類別。一個類別數組列出了全部的類別,從第二個類別開始,即上下文中跟在第一個類別後面的類別。所列出的第一個類別表示了上下文序列中的第二個位置。

注意:文本的順序依賴於文字的書寫方向。對於自右向左書寫的文字,最右端的glyph將是第一個。相反地,對於自左向右書寫的文字,最左端的glyph將是第一個。

Class數組中描述的值是那些定義在ClassDef表中的值。好比,考慮一個上下文序列:Class 2,Class 7,Class 5,Class 0。Class數組將是:Class[0] = 7,Class[1] = 5,Class[2] = 0。序列中的第一個類別Class 2,是經過到偏移量的PosClassSet數組的索引值來定義的。Class數組中所列出的glyph類別總數及序列必須與輸入上下文中包含的glyphs類別總數及序列相匹配。

一個PosClassRule也包含一個將在上下文上執行的定位操做的個數(PosCount)及一個PosLookupRecords的數組(PosLookupRecord),其中數組提供了定位數據。對於上下文中須要一個定位操做的每一個位置,會有一個PosLookupRecord肯定了一個LookupList索引及一個輸入glyph類別序列中的位置,其中lookup將在此位置被應用。PosLookupRecord數組以設計順序列出了PosLookupRecords,或者lookups將被應用於整個glyph序列的順序。

本章結尾處的示例11演示了一個ContextPosFormat2子表,它用glyph類別來改變glyph串中重音符號的位置。

PosClassRule table: One class context definition

Value Type Description
uint16 GlyphCount Number of glyphs to be matched
uint16 PosCount Number of PosLookupRecords
uint16 Class
[GlyphCount - 1]
Array of classes-beginning with the second class-to be matched to the input glyph sequence
struct PosLookupRecord[PosCount] Array of positioning lookups-in design order

Context Positioning Subtable: Format 3

Format3,基於Coverage的上下文定位,將一個上下文規則定義爲一個Coverage的序列。序列中的每一個位置爲與上下文模式匹配的glyphs集合肯定了一個不一樣的Coverage表。經過Format 3,定義在不一樣Coverage表中的glyph集合可能有交叉,而不像Format 2那樣爲lookup肯定了固定的類別分配值(上下文序列中的每一個位置都是一致的)和獨有的類別(一個glyph不能同時屬於多個類別)。

好比,考慮一個輸入上下文,它包含一個大寫字母glyph(位置0),後面跟着一個窄的大寫字母glyph(位置1),而後是另外一個大寫字母glyph(位置2)。這個上下文須要3個Coverage表,每一個位置一個:

  • 在位置0,即第一個位置,其Coverage表將列出全部大寫字母glyphs的集合。
  • 在位置1,即第二個位置,其Coverage表將列出全部的窄的大寫字母glyphs的集合,它是位置0所對應的Coverage表中所列出的glyphs的一個子集。
  • 在位置2,其Coverage表將再次列出全部的大寫字母glyphs的集合。

注意:位置0和位置2可使用相同的Coverage表。

不像Format 1和2,這種格式在同一時間只定義一個上下文規則。它由一個格式標識符(PosFormat),一個將被匹配的序列中glyphs的個數(GlyphCount),及描述了輸入上下文序列的一個Coverage偏移量的數組(Coverage)組成。

注意:Coverage數組中所列出的Coverage表必須是依據於書寫方向的文字順序而列出的。對於自右向左書寫的文字,最右端的glyph將是第一個。相反地,對於自左向右書寫的文字,最左端的glyph將是第一個。

這個子表也包含一個將在輸入Coverage序列上被執行的定位操做的個數(PosCount)及一個以設計順序排序或以lookups被應用於整個glyph序列的順序排序的PosLookupRecords的數組(PosLookupRecord),

本章結尾處的示例12經過一個ContextPosFormat3子表來改變數學方程式中數學符號glyphs的位置。

ContextPosFormat3 subtable: Coverage-based context glyph positioning

Value Type Description
uint16 PosFormat Format identifier-format = 3
uint16 GlyphCount Number of glyphs in the input sequence
uint16 PosCount Number of PosLookupRecords
Offset Coverage
[GlyphCount]
Array of offsets to Coverage tables-from beginning of ContextPos subtable
struct PosLookupRecord
[PosCount]
Array of positioning lookups-in design order

LookupType 8: Chaining Contextual Positioning Subtable

一個Chaining Contextual Positioning子表(ChainContextPos)描述了上下文中的glyph定位操做,而同時具備一種在glyphs序列中向後看(look back)和/或向前看(look ahead)的能力Chaining Contextual Positioning子表的設計與Contextual Positioning子表的設計是並行的,它也有三種格式可用。

爲了描述上下文,Coverage表列出輸入序列中的第一個glyph,而ChainPosRule子表定義其他的。一旦在位置i處發現了一個覆蓋的glyph,則客戶端會讀取對應的ChainPosRuleSet表,並檢查其中的每一個表,來決定它是否與文本中周圍的glyphs匹配。若是字串<backtrack sequence>+<input sequence>+<lookahead sequence>與文本中位置i- BacktrackGlyphCount處的glyphs匹配。

若是有一個匹配,則客戶端會爲定位操做查找目標glyphs,並執行該操做。請注意(像在ContextPosFormat1子表中那樣)這些lookups須要在文字中被覆蓋的glyph到輸入序列結尾處這一個範圍內來執行。不會爲backtracking序列及lookahead序列定義定位操做。

爲了給input,backtrack和lookahead序列闡明glyph數組的排列,而提供下面的描述。Input序列從i處開始匹配,此處也是輸入序列匹配的開始的位置。backtrack序列從i - 1處開始排列,而且隨着逐漸的遠離i處而增長偏移值。lookahead序列從輸入序列後面的位置開始,並以邏輯順序遞增。

Logical order -
                   
Input sequence -                
Backtrack sequence -            
Lookahead sequence -            

Chaining Context Positioning Format 1: Simple Chaining Context Glyph Positioning

這種格式與Context Positioning lookup的Format 1一直,除了它用一個ChainPosRule表替換了PosRule表。(相應地,ChainPosRuleSet表與PosRuleSet表的不一樣之處也僅僅在於它是列出了到ChainPosRule子表的偏移量,而不是PosRule表;ChainContextPosFormat1子表是列出了到ChainPosRuleSet子表的偏移量而不是PosRuleSet子表。)

ChainContextPosFormat1 subtable: Simple context positioning

Value Type Description
uint16 PosFormat Format identifier-format = 1
Offset Coverage Offset to Coverage table-from beginning of ContextPos subtable
uint16 ChainPosRuleSetCount Number of ChainPosRuleSet tables
Offset ChainPosRuleSet
[ChainPosRuleSetCount]
Array of offsets to ChainPosRuleSet tables-from beginning of ContextPos subtable-ordered by Coverage Index

一個ChainPosRuleSet表由一個以任意順序排序的到ChainPosRule表的偏移量的數組(ChainPosRule),及集合中所定義的ChainPosRule表的個數(ChainPosRuleCount)組成。

ChainPosRuleSet table: All contexts beginning with the same glyph

Value Type Description
uint16 ChainPosRuleCount Number of ChainPosRule tables
Offset ChainPosRule
[ChainPosRuleCount]
Array of offsets to ChainPosRule tables-from beginning of ChainPosRuleSet-ordered by preference

ChainPosRule subtable

Type Name Description
uint16 BacktrackGlyphCount Total number of glyphs in the backtrack sequence (number of glyphs to be matched before the first glyph)
GlyphID Backtrack
[BacktrackGlyphCount]
Array of backtracking GlyphID's (to be matched before the input sequence)
uint16 InputGlyphCount Total number of glyphs in the input sequence (includes the first glyph)
GlyphID Input
[InputGlyphCount - 1]
Array of input GlyphIDs (start with second glyph)
uint16 LookaheadGlyphCount Total number of glyphs in the look ahead sequence (number of glyphs to be matched after the input sequence)
GlyphID LookAhead
[LookAheadGlyphCount]
Array of lookahead GlyphID's (to be matched after the input sequence)
uint16 PosCount Number of PosLookupRecords
struct PosLookupRecord
[PosCount]
Array of PosLookupRecords (in design order)

Chaining Context Positioning Format 2: Class-based Chaining Context Glyph Positioning

這種lookup格式與Context Positioning格式2是平行的,只是將PosClassSet子表變爲ChainPosClassSet,並將PosClassRule子表變爲ChainPosClassRule子表。

爲了連接上下文,三種類別被用於glyph ClassDef表:Backtrack ClassDef,Input ClassDef,和Lookahead ClassDef。

ChainContextPosFormat2 subtable: Chaining class-based context glyph positioning

Value Type Description
uint16 PosFormat Format identifier-format = 2
Offset Coverage Offset to Coverage table-from beginning of ChainContextPos subtable
Offset BacktrackClassDef Offset to ClassDef table containing backtrack sequence context-from beginning of ChainContextPos subtable
Offset InputClassDef Offset to ClassDef table containing input sequence context-from beginning of ChainContextPos subtable
Offset LookaheadClassDef Offset to ClassDef table containing lookahead sequence context-from beginning of ChainContextPos subtable
uint16 ChainPosClassSetCnt Number of ChainPosClassSet tables
Offset ChainPosClassSet
[ChainPosClassSetCnt]
Array of offsets to ChainPosClassSet tables-from beginning of ChainContextPos subtable-ordered by input class-may be NUL

定義了以相同的類別開始的上下文的全部的ChainPosClassRules被分組在一塊兒並被定義在一個ChainPosClassSet表中。所以,ChainPosClassSet表肯定了一個上下文第一個組件的類別。

ChainPosClassSet table: All contexts beginning with the same class

Value Type Description
uint16 ChainPosClassRuleCnt Number of ChainPosClassRule tables
Offset ChainPosClassRule[ChainPosClassRuleCnt] Array of offsets to ChainPosClassRule tables-from beginning of ChainPosClassSet-ordered by preference

ChainPosClassRule subtable

Type Name Description
uint16 BacktrackGlyphCount Total number of glyphs in the backtrack sequence (number of glyphs to be matched before the first glyph)
uint16 Backtrack
[BacktrackGlyphCount]
Array of backtracking classes(to be matched before the input sequence)
uint16 InputGlyphCount Total number of classes in the input sequence (includes the first class)
uint16 Input
[InputGlyphCount - 1]
Array of input classes(start with second class; to be matched with the input glyph sequence)
uint16 LookaheadGlyphCount Total number of classes in the look ahead sequence (number of classes to be matched after the input sequence)
uint16 LookAhead
[LookAheadGlyphCount]
Array of lookahead classes(to be matched after the input sequence)
uint16 PosCount Number of PosLookupRecords
struct PosLookupRecord
[ChainPosCount]
Array of PosLookupRecords (in design order)

Chaining Context Positioning Format 3: Coverage-based Chaining Context Glyph Positioning

Format3將一個連接上下文規則定義爲一個Coverage表的序列。序列中的每一個位置爲與上下文模式匹配的glyphs集合定義了一個不一樣的Coverage表。經過Format 3,不一樣的Coverage表中所定義的glyph集合可能會交叉,不像Format 2那樣肯定了固定的類別分配值(backtrack,input或者lookahead序列中的每一個位置都是一致的)和獨有的類別(一個glyph不能同時屬於多個類別)。

注意:Coverage數組中所列出的Coverage表的順序必須聽從書寫的方向。對於自右向左書寫的文字,則最右端的glyph將是第一個。相反地,對於自左向右書寫的文字,最左端的glyph將會是第一個。

這種子表也包含一個輸入Coverage序列上將被執行的定位操做的個數(PosCount)及一個以設計順序排序的PosLookupRecords的數組(PosLookupRecord):即,lookups應該被應用於整個glyph序列的順序。

ChainContextPosFormat3 subtable: Coverage-based chaining context glyph positioning

Type Name Description
uint16 PosFormat Format identifier-format = 3
uint16 BacktrackGlyphCount Number of glyphs in the backtracking sequence
Offset Coverage[BacktrackGlyphCount] Array of offsets to coverage tables in backtracking sequence, in glyph sequence order
uint16 InputGlyphCount Number of glyphs in input sequence
Offset Coverage[InputGlyphCount] Array of offsets to coverage tables in input sequence, in glyph sequence order
uint16 LookaheadGlyphCount Number of glyphs in lookahead sequence
Offset Coverage[LookaheadGlyphCount] Array of offsets to coverage tables in lookahead sequence, in glyph sequence order
uint16 PosCount Number of PosLookupRecords
struct PosLookupRecord
[PosCount]
Array of PosLookupRecords,in design order

LookupType 9: Extension Positioning

這中lookup提供了一種機制,以幫助在‘GPOS’表中將任何其餘lookup類型的子表存儲在一個32-bit偏移量的位置處。若是子表的總大小超出了‘GPOS’表中各類其餘的偏移量都會有的16-bts的限制,則會須要用到這種表。這份規範中,把存儲在32-bt偏移量位置處的子表稱做「擴展」子表。

ExtensionPosFormat1 subtable

Type Name Description
USHORT PosFormat Format identifier. Set to 1.
USHORT ExtensionLookupType Lookup type of subtable referenced by ExtensionOffset (i.e. the extension subtable).
ULONG ExtensionOffset Offset to the extension subtable, of lookup type ExtensionLookupType, relative to the start of the ExtensionPosFormat1 subtable.

ExtensionLookupType必須被設爲任何其它的lookup類型而不是9。一個LookupType 9 lookup中的全部子表必須具備相同的ExtensionLookupType擴展子表中全部的偏移量以日常的方式設置,好比,相對於擴展子表自己。

當一個OpenType layout引擎遇到一個LookupType 9 Lookup表時,它應該:

  • 就像Lookup表的LookupType成員被設爲了其子表的ExtensionLookupType同樣來處理。
  • 就像由ExtensionOffset所引用的每一個擴展子表替換了引用它的LookupType 9 子表同樣來處理。

共享的表:ValueRecord,Anchor Table和MarkArray

本章前面描述的一些lookup子表爲定位操做的數據而引用了一個或多個相同的表:ValueRecord,Anchor Table和MarkArray。爲了便於查詢,那些共享的表在此處描述。

本章結尾處的示例14使用了一個ValueFormat表和ValueRecord來在GPOS中描述定位操做的值。

ValueRecord

GPOS子表使用ValueRecord來描述全部用於調整一個glyph或glyphs集合的位置的變量值。一個ValueRecord可能定義加到(正值)字庫中提供的placement和advance上或從中減掉(負值)的任意的X和Y值的組合(以設計單位)。一個ValueRecord也可能爲每一個特定的值包含一個到一個Device表的偏移量。若是一個ValueRecord描述了多個值,則這些值應該以ValueRecord定義中所顯示的順序列出。

文字處理客戶端必須意識到GPOS表中ValueRecord靈活的和多維的屬性。因爲GPOS表爲多種目的而使用ValueRecords,則ValueRecords的大小和內容也許會在子表之間有所不一樣。

ValueRecord (all fields are optional)

Value Type Description
int16 XPlacement Horizontal adjustment for placement-in design units
int16 YPlacement Vertical adjustment for placement-in design units
int16 XAdvance Horizontal adjustment for advance-in design units (only used for horizontal writing)
int16 YAdvance Vertical adjustment for advance-in design units (only used for vertical writing)
Offset XPlaDevice Offset to Device table for horizontal placement-measured from beginning of PosTable (may be NULL)
Offset YPlaDevice Offset to Device table for vertical placement-measured from beginning of PosTable (may be NULL)
Offset XAdvDevice Offset to Device table for horizontal advance-measured from beginning of PosTable (may be NULL)
Offset YAdvDevice Offset to Device table for vertical advance-measured from beginning of PosTable (may be NULL)

一個數據格式(ValueFormat),經常在每一個GPOS子表的開始處聲明,定義了ValueRecords描述的位置調整數據的類型。一般,相同的ValueFormat會應用於特定的GPOS子表中定義的每一個ValueRecord。

ValueFormat決定了ValueRecords:

  • 應用於placement,advance,或二者都有。
  • 應用於水平定位(X 座標),豎直定位(Y座標),或二者均有。
  • 可能會爲特定的值中的任何一些引用一個或多個Device表。

ValueFormat中的每個位對應於ValueRecord中的一個成員,而且將ValueRecord的大小增長2字節。一個0x0000的ValueFormat對應於一個空的ValueRecord,它表示沒有位置的改變。爲了標識每一個ValueRecord中的成員ValueRecord使用了下面所示的位設定。爲了用一個ValueFormat描述多個成員,則相關成員的位設定經過一個邏輯OR操做而被加在一塊兒。

好比,爲了調整一個glyph的左邊bearing,則ValueFormat將被設爲0x0001,而ValueRecord將定義XPlacement值。爲了調整一個不一樣的glyph的advance寬度,其ValueFormat將是0x0004,而ValueRecord將描述XAdvance值。爲了同時調整一個glyphs集合的XPlacement和XAdvance,其ValueFormat將是0x0005,而ValueRecord將以它們在ValueRecord定義中列出的順序描述着二者。

ValueFormat bit enumeration (indicates which fields are present)

Mask Name Description
0x0001 XPlacement Includes horizontal adjustment for placement
0x0002 YPlacement Includes vertical adjustment for placement
0x0004 XAdvance Includes horizontal adjustment for advance
0x0008 YAdvance Includes vertical adjustment for advance
0x0010 XPlaDevice Includes horizontal Device table for placement
0x0020 YPlaDevice Includes vertical Device table for placement
0x0040 XAdvDevice Includes horizontal Device table for advance
0x0080 YAdvDevice Includes vertical Device table for advance
0xF000 Reserved For future use (set to zero)

Anchor表

一個GPOS表使用錨點(anchor point)來定位一個glyph相對於另外一個的位置。每一個glyph定義一個錨點,文字處理客戶端經過對齊它們對應的錨點來附上glyphs。

爲了描述一個錨點,一個Anchor表可使用三種格式中的一種。第一種格式使用設計單位來爲錨點肯定一個位置。另外兩種格式使用輪廓點(Format 2)或設備表(Foramt 3)來改善錨點的位置。

Anchor Table: Format 1

AnchorFormat1由一個格式標識符(AnchorFormat)和描述了錨點位置的一對設計單位的座標(XCoordinate和YCoordinate)組成。這種格式的好處是大小比較小,並且比較簡單,但錨點沒法被hinted來爲不一樣設備分辨率調整它的位置。

本章結尾處的示例15使用了AnchorFormat1

AnchorFormat1 table: Design units only

Value Type Description
uint16 AnchorFormat Format identifier-format = 1
int16 XCoordinate Horizontal value-in design units
int16 YCoordinate Vertical value-in design units

Anchor Table: Format 2

像AnchorFormat1同樣,AnchorFormat2指定了一個格式標識符(AnchorFormat),併爲錨點指定了一對設計單位的座標(Xcoordinate和Ycoordinate)。

爲了微調錨點的位置,AnchorFormat2也提供了在一個glyph的輪廓上的一個glyph輪廓點的索引(AnchorPoint)。Hinting能夠被用於移動AnchorPoint。在被渲染的文字中,AnchorPoint將爲一個給定的ppem大小提供最終的位置調整數據。

本章結尾處的示例16使用AnchorFormat2。

AnchorFormat2 table: Design units plus contour point

Value Type Description
uint16 AnchorFormat Format identifier-format = 2
int16 XCoordinate Horizontal value-in design units
int16 YCoordinate Vertical value-in design units
uint16 AnchorPoint Index to glyph contour point

Anchor Table: Format 3

AnchorFormat1同樣,AnchorFormat3也指定了一個格式標識符(AnchorFormat)並定位了一個錨點(Xcoordinate和Ycoordinate)。而且,像AnchorFormat2同樣,它容許對座標值進行優調。然而,AnchorFormat3是使用Device表,而不是一個輪廓點來作調整。

經過一個Device表,一個客戶端能夠爲任何字體大小和設備分辨率來調整錨點的位置。AnchorFormat3能夠爲X座標(XDeviceTable)和Y座標(YDeviceTable)指定到Device表的偏移量。若是隻有一個座標須要調整,則另外一個座標其到Device表的偏移量能夠被設爲NULL。

本章結尾處的示例17顯示了一個AnchorFormat3表。

AnchorFormat3 table: Design units plus Device tables

Value Type Description
uint16 AnchorFormat Format identifier-format = 3
int16 XCoordinate Horizontal value-in design units
int16 YCoordinate Vertical value-in design units
Offset XDeviceTable Offset to Device table for X coordinate- from beginning of Anchor table (may be NULL)
Offset YDeviceTable Offset to Device table for Y coordinate- from beginning of Anchor table (may be NULL)

Mark Array

MarkArray表爲一個mark glyph定義了類別和錨點。三種GPOS子表-MarkToBase,MarkToLigature和MarkToMark Attachment-使用了MarkArray表來爲attaching mark描述數據。

MarkArray表包含一個mark記錄的個數(MarkCount)及一個那些記錄的數組(MarkRecord)。每一個mark記錄都定義了mark的類別及一個到爲那個mark包含了數據的Anchor表的偏移量。

一個類別值多是0,但MarkRecord必須顯式地分配那個類別值(這不一樣於ClassDef表,ClassDef表中全部未分配類別值的glyphs自動地屬於Class 0)。引用了MarkArray表的GPOS子表use the class assignments for indexing zero-based arrays that contain data for each mark class。

本章結尾處的示例18中,一個MarkArray表和兩個MarkRecords定義了兩個mark類別。

MarkArray table

Value Type Description
uint16 MarkCount Number of MarkRecords
struct MarkRecord
[MarkCount]
Array of MarkRecords-in Coverage order

MarkRecord

Value Type Description
uint16 Class Class defined for this mark
Offset MarkAnchor Offset to Anchor table-from beginning of MarkArray table

GPOS Subtable Examples

本章的剩餘部分將描述一些GPOS子表的例子。

Done

相關文章
相關標籤/搜索