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中的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):
關於ScriptLists,FeatureLists和LookupLists的詳細討論,請參考OpenType通用表格式。下面的討論將總結GPOS表是如何工做的。
Figure 4f. High-level organization of GPOS table
GPOS表用這種方式進行組織,以使得文字處理客戶端能夠簡單地定位應用於一個特定的script或language system的features和lookups。爲了訪問GPOS信息,客戶端應該使用下面的過程:
一個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表以一個表頭開始,它包含有一個最初被設爲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 |
一個single adjustment positioning子表(SinglePos)被用於調整單個的glyph的位置,好比一個上標或下標。此外,一個SinglePos子表一般被用於爲上下文定位實現lookup數據。
一個SinglePos子表將具備兩種格式中的一種:一種給一系列的glyphs應用相同的adjustment,或者一種爲每一個惟一的glyph應用一個不一樣的adjustment。
一個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 |
一個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 |
一個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)。
Format 1使用glyph索引來爲一個或多個glyph對訪問定位數據。全部的pair被描述的順序有文本的佈局方向來決定。
注意:對於自右向左書寫的文字,最右端的glyph將是glyph對中的第一個glyph;相反地,對於自左向右書寫書寫的文字,最左端的glyph是第一個。
一個PairPosFormat1子表包含一個格式標識符(PosFormat)和兩個ValueFormats:
一個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 |
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:
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 |
一些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 |
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 |
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 |
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子表也包含兩個偏移量,由該子表的起始位置算起,指向兩個數組:
關於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 |
ContextPositoning(ContextPos)子表定義了最爲強大的一種glyph定位lookup類型。它描述了上下文中的glyph定位操做,從而一個文字處理客戶端能夠調整某一glyphs模式中的一個或多個glyphs的位置。每一個子表描述了一個或多個「輸入」glyph序列及將會在那個序列上執行的一個或多個定位操做。
ContextPos能夠是三種格式中的一種,這三種格式與用於上下文glyph置換的格式對應。一種格式。一種格式適用於特定的glyph序列(Format 1),一種按照glyph類別來定義上下文(Format 2),而第三種格式則依照glyphs集合來定義上下文(Format 2)。
ContextPos子表的全部三種格式都在一個PosLookupRecord中描述定位數據。下面是那種record的一個描述。
全部的上下文定位子表都在一個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 |
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 |
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 |
Format3,基於Coverage的上下文定位,將一個上下文規則定義爲一個Coverage的序列。序列中的每一個位置爲與上下文模式匹配的glyphs集合肯定了一個不一樣的Coverage表。經過Format 3,定義在不一樣Coverage表中的glyph集合可能有交叉,而不像Format 2那樣爲lookup肯定了固定的類別分配值(上下文序列中的每一個位置都是一致的)和獨有的類別(一個glyph不能同時屬於多個類別)。
好比,考慮一個輸入上下文,它包含一個大寫字母glyph(位置0),後面跟着一個窄的大寫字母glyph(位置1),而後是另外一個大寫字母glyph(位置2)。這個上下文須要3個Coverage表,每一個位置一個:
注意:位置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 |
一個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 - | a | b | c | d | e | f | g | h | i | j |
i | ||||||||||
Input sequence - | 0 | 1 | ||||||||
Backtrack sequence - | 3 | 2 | 1 | 0 | ||||||
Lookahead sequence - | 0 | 1 | 2 | |
這種格式與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) |
這種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) |
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 |
這中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子表爲定位操做的數據而引用了一個或多個相同的表:ValueRecord,Anchor Table和MarkArray。爲了便於查詢,那些共享的表在此處描述。
本章結尾處的示例14使用了一個ValueFormat表和ValueRecord來在GPOS中描述定位操做的值。
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:
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) |
一個GPOS表使用錨點(anchor point)來定位一個glyph相對於另外一個的位置。每一個glyph定義一個錨點,文字處理客戶端經過對齊它們對應的錨點來附上glyphs。
爲了描述一個錨點,一個Anchor表可使用三種格式中的一種。第一種格式使用設計單位來爲錨點肯定一個位置。另外兩種格式使用輪廓點(Format 2)或設備表(Foramt 3)來改善錨點的位置。
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 |
像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 |
像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) |
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子表的例子。
Done