GPOS Subtable Examples

The rest of this chapter describes examples of all the GPOS subtable formats, including each of the three formats available for contextual positioning. All the examples reflect unique parameters described below, but the samples provide a useful reference for building subtables specific to other situations.

All the examples have three columns showing hex data, source, and comments.

Example 1: GPOS Header Table

Example 1 shows a typical GPOS Header table definition with offsets to a ScriptList, FeatureList, and LookupList.

Example 1

Hex Data

Source

Comments

GPOSHeader

TheGPOSHeader

;GPOSHeader table definition

00010000

0x00010000

;Version

000A

TheScriptList

;offset to ScriptList table

001E

TheFeatureList

;offset to FeatureList table

002C

TheLookupList

;offset to LookupList table


Example 2: SinglePosFormat1 Subtable

Example 2 uses the SinglePosFormat1 subtable to lower the Y placement of subscript glyphs in a font. The LowerSubscriptsSubTable defines one Coverage table, called LowerSubscriptsCoverage, which lists one range of glyph indices for the numeral/numeric subscript glyphs. The subtable's ValueFormat setting indicates that the ValueRecord specifies only the YPlacement value, lowering each subscript glyph by 80 design units.

Example 2

Hex Data

Source

Comments

SinglePosFormat1

LowerSubscriptsSubTable

;SinglePos subtable definition

0001

1

;PosFormat

0008

LowerSubscriptsCoverage

;offset to Coverage table

0002

0x0002

;ValueFormat, YPlacement

;Value[0], move Y position down

FFB0

-80

CoverageFormat2

LowerSubscriptsCoverage

;Coverage table definition

0002

2

;CoverageFormat

0001

1

;RangeCount

;RangeRecord[0]

01B3

ZeroSubscriptGlyphID

;Start, first glyphID

01BC

NineSubscriptGlyphID

;End, last glyphID

0000

0

;StartCoverageIndex


Example 3: SinglePosFormat2 Subtable

This example uses a SinglePosFormat2 subtable to adjust the spacing of three dash glyphs by different amounts. The em dash spacing changes by 10 units, the en dash spacing changes by 25 units, and spacing of the standard dash changes by 50 units.

The DashSpacingSubTable contains one Coverage table with three dash glyph indices, plus an array of ValueRecords, one for each covered glyph. The ValueRecords use the same ValueFormat to modify the XPlacement and XAdvance values of each glyph. The ValueFormat bit setting of 0x0005 is produced by adding the XPlacement and XAdvance bit settings.

Example 3

Hex Data

Source

Comments

SinglePosFormat2

DashSpacingSubTable

;SinglePos subtable definition

0002

2

;PosFormat

0014

DashSpacingCoverage

;offset to Coverage table

0005

0x0005

;ValueFormat

; for XPlacement and XAdvance

0003

3

;ValueCount

;Value[0], for dash glyph

0032

50

;XPlacement

0032

50

;XAdvance

;Value[1], for en dash glyph

0019

25

;XPlacement

0019

25

;XAdvance

;Value[2], for em dash glyph

000A

10

;XPlacement

000A

10

;XAdvance

CoverageFormat1

DashSpacingCoverage

;Coverage table definition

0001

1

;CoverageFormat

0003

3

;GlyphCount

004F

DashGlyphID

;GlyphArray[0]

0125

EnDashGlyphID

;GlyphArray[1]

0129

EmDashGlyphID

;GlyphArray[2]


Example 4: PairPosFormat1 Subtable

Example 4 uses a PairPosFormat1 subtable to kern two glyph pairs — "Po" and "To" — by adjusting the XAdvance of the first glyph and the XPlacement of the second glyph. Two ValueFormats are defined, one for each glyph. The subtable contains a Coverage table that lists the index of the first glyph in each pair. It also contains an offset to a PairSet table for each covered glyph.

A PairSet table defines an array of PairValueRecords to specify all the glyph pairs that contain a covered glyph as their first component. In this example, the PPairSet table has one PairValueRecord that identifies the second glyph in the "Po" pair and two ValueRecords, one for the first glyph and one for the second. The TPairSet table also has one PairValueRecord that lists the second glyph in the "To" pair and two ValueRecords, one for each glyph.

Example 4

Hex Data

Source

Comments

PairPosFormat1

PairKerningSubTable

;PairPos subtable definition

0001

1

;PosFormat

001E

PairKerningCoverage

;offset to Coverage table

0004

0x0004

;ValueFormat1

; XAdvance only

0001

0x0001

;ValueFormat2

; XPlacement only

0002

2

;PairSetCount

000E

PPairSetTable

;PairSet[0]

0016

TPairSetTable

;PairSet[1]

PairSetTable

PPairSetTable

;PairSet table definition

0001

1

;PairValueCount

; one pair in set

;PairValueRecord[0]

0059

LowercaseOGlyphID

;SecondGlyph

;Value1

FFE2

-30

; XAdvance adjustment for first ; glyph

;Value2

FFEC

-20

; XPlacement adjustment for

; second glyph

PairSetTable

PairSetTable

;PairSet table definition

0001

1

;PairValueCount

; one pair in set

;PairValueRecord[0]

0059

LowercaseOGlyphID

;SecondGlyph

;Value1

FFD8

-40

;XAdvance adjustment

; for first glyph

;Value2

FFE7

-25

;XPlacement adjustment

; for second glyph

CoverageFormat1

PairKerningCoverage

;Coverage table definition

0001

1

;CoverageFormat

0002

2

;GlyphCount

002D

UppercasePGlyphID

;GlyphArray[0]

0031

UppercaseTGlyphID

;GlyphArray[1]


Example 5: PairPosFormat2 Subtable

The PairPosFormat2 subtable in this example defines pairs composed of two glyph classes. Two ClassDef tables are defined, one for each glyph class. The first glyph in each pair is in a class of lowercase glyphs with diagonal shapes (v, w, y), defined Class1 in the LowercaseClassDef table. The second glyph in each pair is in a class of punctuation glyphs (comma and period), defined in Class1 in the PunctuationClassDef table. The Coverage table only lists the indices of the glyphs in the LowercaseClassDef table since they occupy the first position in the pairs.

The subtable defines two Class1Records for the classes defined in LowecaseClassDef, including Class0. Each record, in turn, defines a Class2Record for each class defined in PunctuationClassDef, including Class0. The Class2Records specify the positioning adjustments for the glyphs.

The pairs are kerned by reducing the XAdvance of the first glyph by 50 design units. Because no positioning change applies to the second glyph, its ValueFormat2 is set to 0, to indicate that Value2 is empty for each pair.

Since no pairs begin with Class0 or Class2 glyphs, all the ValueRecords referenced in Class1Record[0] contain values of 0 or are empty. However, Class1Record[1] does define an XAdvance value in its Class2Record[1] for kerning all pairs that contain a Class1 glyph followed by a Class2 glyph.

Example 5

Hex Data

Source

Comments

PairPosFormat2

PunctKerningSubTable

;PairPos subtable definition

0002

2

;PosFormat

0018

PunctKerningCoverage

;offset to Coverage table

0004

0x0004

;ValueFormat1

; XAdvance only

0000

0

;ValueFormat2

; no ValueRecord for second

; glyph

0022

LowercaseClassDef

;offset to ClassDef1 table

; for first class in pair

0032

PunctuationClassDef

;offset to ClassDef2 table

; for second class in pair

0002

2

;Class1Count

0002

2

;Class2Count

;Class1Record[0]

; no contexts begin with

; Class0

;Class2Record[0]

0000

0

;Value1

; no change for first glyph

;Value2

; no ValueRecord for second

; glyph

;Class2Record[1]

0000

0

;Value1

; no change for first glyph

;Value2

; no ValueRecord for second

; glyph

;Class1Record[1]

; for contexts beginning with

; Class1

;Class2Record[0]

; no contexts with Class0 as

; second glyph

0000

0

;Value1

; no change for first glyph

;Value2

; no ValueRecord for second

; glyph

;Class2Record[1]

; contexts with Class1 as

; second glyph

FFCE

-50

;Value1

; move punctuation glyph left

;Value2

; no ValueRecord for second

; glyph

CoverageFormat1

PunctKerningCoverage

;Coverage table definition

0001

1

;CoverageFormat, lists

0003

3

;GlyphCount

0046

LowercaseVGlyphID

;GlyphArray[0]

0047

LowercaseWGlyphID

;GlyphArray[1]

0049

LowercaseYGlyphID

;GlyphArray[2]

ClassDefFormat2

LowercaseClassDef

;ClassDef table definition

0002

2

;ClassFormat

0002

2

;ClassRangeCount

;ClassRangeRecord[0]

0046

LowercaseVGlyphID

;Start

0047

LowercaseWGlyphID

;End

0001

1

;Class

;ClassRangeRecord[1]

0049

LowercaseYGlyphID

;Start

0049

LowercaseYGlyphID

;End

0001

1

;Class

ClassDefFormat2

PunctuationClassDef

;ClassDef table definition

0002

2

;ClassFormat

0001

1

;ClassRangeCount

;ClassRangeRecord[0]

006A

PeriodPunctGlyphID

;Start

006B

CommaPunctGlyphID

;End

0001

1

;Class


Example 6: CursivePosFormat1 Subtable

In Example 6, the Urdu language system uses a CursivePosFormat1 subtable to attach glyphs along a diagonal baseline that descends from right to left. Two glyphs are defined with attachment data and listed in the Coverage table—the Kaf and Ha glyphs. For each glyph, the subtable contains an EntryExitRecord that defines offsets to two Anchor tables, an entry attachment point, and an exit attachment point. Each Anchor table defines X and Y coordinate values. To render Urdu down and diagonally, the entry point's Y coordinate is above the baseline and the exit point's Y coordinate is located below the baseline.

Example 6

Hex Data

Source

Comments

CursivePosFormat1

DiagonalWritingSubTable

;CursivePos subtable definition

0001

1

;PosFormat

000E

DiagonalWritingCoverage

;offset to Coverage table

0002

2

;EntryExitCount

;EntryExitRecord[0]

; for Kaf glyph

0016

KafEntryAnchor

;offset to EntryAnchor table

001C

KafExitAnchor

;offset to ExitAnchor table

;EntryExitRecord[1]

; for Ha glyph

0022

HaEntryAnchor

;offset to EntryAnchor table

0028

HaExitAnchor

;offset to ExitAnchor table

CoverageFormat1

DiagonalWritingCoverage

;Coverage table definition

0001

1

;CoverageFormat

0002

2

;GlyphCount

0203

KafGlyphID

;GlyphArray[0]

027E

HaGlyphID

;GlyphArray[1]

AnchorFormat1

KafEntryAnchor

;Anchor table definition

0001

1

;AnchorFormat

05DC

1500

;XCoordinate

002C

44

;YCoordinate

AnchorFormat1

KafExitAnchor

;Anchor table definition

0001

1

;AnchorFormat

0000

0

;XCoordinate

FFEC

-20

;YCoordinate

AnchorFormat1

HaEntryAnchor

;Anchor table definition

0001

1

;AnchorFormat

05DC

1500

;XCoordinate

002C

44

;YCoordinate

AnchorFormat1

HaExitAnchor

;Anchor table definition

0001

1

;AnchorFormat

0000

0

;XCoordinate

FFEC

-20

;Ycoordinate


Example 7: MarkBasePosFormat1 Subtable

The MarkBasePosFormat1 subtable in Example 7 defines one Arabic base glyph, Tah, and two Arabic mark glyphs: a fathatan mark above the base glyph, and a kasra mark below the base glyph. The BaseGlyphsCoverage table lists the base glyph, and the MarkGlyphsCoverage table lists the mark glyphs.

Each mark is also listed in the MarkArray, along with its attachment point data and a mark Class value. The MarkArray defines two mark classes: Class0 consists of marks located above base glyphs, and Class1 consists of marks located below base glyphs.

The BaseArray defines attachment data for base glyphs. In this array, one BaseRecord is defined for the Tah glyph with offsets to two BaseAnchor tables, one for each class of marks. AboveBaseAnchor defines an attachment point for marks placed above the Tah base glyph, and BelowBaseAnchor defines an attachment point for marks placed below it.

Example 7

Hex Data

Source

Comments

MarkBasePosFormat1

MarkBaseAttachSubTable

;MarkBasePos subtable definition

0001

1

;PosFormat

000C

MarkGlyphsCoverage

;offset to MarkCoverage table

0014

BaseGlyphsCoverage

;offset to BaseCoverage table

0002

2

;ClassCount

001A

MarkGlyphsArray

;offset to MarkArray table

0030

BaseGlyphsArray

;offset to BaseArray table

CoverageFormat1

MarkGlyphsCoverage

;Coverage table definition

0001

1

;CoverageFormat

0002

2

;GlyphCount

0333

fathatanMarkGlyphID

;GlyphArray[0]

033F

kasraMarkGlyphID

;GlyphArray[1]

CoverageFormat1

BaseGlyphsCoverage

;Coverage table definition

0001

1

;CoverageFormat

0001

1

;GlyphCount

0190

tahBaseGlyphID

;GlyphArray[0]

MarkArray

MarkGlyphsArray

;MarkArray table definition

0002

2

;MarkCount

;MarkRecord[0]

; in CoverageIndex order

0000

0

;Class, for marks over base

000A

fathatanMarkAnchor

;offset to Anchor table

;MarkRecord[1]

0001

1

;Class, for marks under

0010

kasraMarkAnchor

;offset to Anchor table

AnchorFormat1

fathatanMarkAnchor

;Anchor table definition

0001

1

;AnchorFormat

015A

346

;XCoordinate

FF9E

-98

;YCoordinate

AnchorFormat1

kasraMarkAnchor

;Anchor table definition

0001

1

;AnchorFormat

0105

261

;XCoordinate

0058

88

;YCoordinate

BaseArray

BaseGlyphsArray

;BaseArray table definition

0001

1

;BaseCount

;BaseRecord[0]

0006

AboveBaseAnchor

;BaseAnchor[0]

000C

BelowBaseAnchor

;BaseAnchor[1]

AnchorFormat1

AboveBaseAnchor

;Anchor table definition

0001

1

;AnchorFormat

033E

830

;XCoordinate

0640

1600

;YCoordinate

AnchorFormat1

BelowBaseAnchor

;Anchor table definition

0001

1

;AnchorFormat

033E

830

;XCoordinate

FFAD

-83

;Ycoordinate


Example 8: MarkLigPosFormat1 Subtable

Example 8 uses the MarkLigPosFormat1 subtable to attach marks to a ligature glyph in the Arabic script. The hypothetical ligature is composed of three glyph components: a Lam (initial form), a meem (medial form), and a jeem (medial form). Accent marks are defined for the first two components: the sukun accent is positioned above lam, and the kasratan accent is placed below meem.

The LigGlyphsCoverage table lists the ligature glyph and the MarkGlyphsCoverage table lists the two accent marks. Each mark is also listed in the MarkArray, along with its attachment point data and a mark Class value. The MarkArray defines two mark classes: Class0 consists of marks located above base glyphs, and Class1 consists of marks located below base glyphs.

The LigGlyphsArray has an offset to one LigatureAttach table for the covered ligature glyph. This table, called LamWithMeemWithJeemLigAttach, defines a count and array of the component glyphs in the ligature. Each ComponentRecord defines offsets to two Anchor tables, one for each mark class.

In the example, the first glyph component, lam, specifies a high attachment point for positioning accents above, but does not specify a low attachment point for placing accents below. The second glyph component, meem, defines a low attachment point for placing accents below, but not above. The third component, jeem, has no attachment points since the example defines no accents for it.

Example 8

Hex Data

Source

Comments

MarkLigPosFormat1

MarkLigAttachSubTable

;MarkLigPos subtable definition

0001

1

;PosFormat

000C

MarkGlyphsCoverage

;offset to MarkCoverage table

0014

LigGlyphsCoverage

;offset to LigatureCoverage

; table

0002

2

;ClassCount

001A

MarkGlyphsArray

;offset to MarkArray table

0030

LigGlyphsArray

;offset to LigatureArray table

CoverageFormat1

MarkGlyphsCoverage

;Coverage table definition

0001

1

;CoverageFormat

0002

2

;GlyphCount

033C

sukunMarkGlyphID

;GlyphArray[0]

033F

kasratanMarkGlyphID

;GlyphArray[1]

CoverageFormat1

LigGlyphsCoverage

;Coverage table definition

0001

1

;CoverageFormat

0001

1

;GlyphCount

0234

LamWithMeemWithJeemLigatureGlyphID ;GlyphArray[0]

MarkArray

MarkGlyphsArray

;MarkArray table definition

0002

2

;MarkCount

;MarkRecord[0]

; in CoverageIndex order

0000

0

;Class

; for marks above components

000A

sukunMarkAnchor

;offset to Anchor table

;MarkRecord[1]

0001

1

;Class, for marks below

; components

0010

kasratanMarkAnchor

;offset to Anchor table

AnchorFormat1

sukunMarkAnchor

;Anchor table definition

0001

1

;AnchorFormat

015A

346

;XCoordinate

FF9E

-98

;YCoordinate

AnchorFormat1

kasratanMarkAnchor

;Anchor table definition

0001

1

;AnchorFormat

0105

261

;XCoordinate

01E8

488

;YCoordinate

LigatureArray

LigGlyphsArray

;LigatureArray table definition

0001

1

;LigatureCount

0004

LamWithMeemWithJeemLigAttach

;offset to LigatureAttach table

LigatureAttach

LamWithMeemWithJeemLigAttach

;LigatureAttach table definition

0003

3

;ComponentCount

;ComponentRecord[0]

; Right-to-Left text order

000E

AboveLamAnchor

;offset to LigatureAnchor table

; ordered by mark class value

; for Class0 marks (above)

0000

NULL

;offset to LigatureAnchor table

; no attachment points for

; Class1 marks

;ComponentRecord[1]

0000

NULL

;offset to LigatureAnchor table

; no attachment points for

; Class0 marks

0014

BelowMeemAnchor

;offset to LigatureAnchor table

; for Class1 marks (below)

;ComponentRecord[2]

0000

NULL

;offset to LigatureAnchor table

; no attachment points for

; Class0 marks

0000

NULL

;offset to LigatureAnchor table

; no attachment points for

; Class1 marks

AnchorFormat1

AboveLamAnchor

;Anchor table definition

0001

1

;AnchorFormat

0271

625

;XCoordinate

0708

1800

;YCoordinate

AnchorFormat1

BelowMeemAnchor

;Anchor table definition

0001

1

;AnchorFormat

0178

376

;XCoordinate

FE90

-368

;Ycoordinate


Example 9: MarkMarkPosFormat1 Subtable

The MarkMarkPosFormat1 subtable in Example 9 defines two Arabic marks glyphs. The hanza mark, the base mark (Mark2), is identified in the Mark2GlyphsCoverage table. The damma mark, the attaching mark (Mark1), is defined in the Mark1GlyphsCoverage table.

Each Mark1 glyph is also listed in the Mark1Array, along with its attachment point data and a mark Class value. The Mark1GlyphsArray defines one mark class, Class0, that consists of marks located above Mark2 base glyphs. The Mark1GlyphsArray contains an offset to a dammaMarkAnchor table to specify the coordinate of the damma mark's attachment point.

The Mark2GlyphsArray table defines a count and an array of Mark2Records, one for each covered Mark2 base glyph. Each record contains an offset to a Mark2Anchor table for each Mark1 class. One Anchor table, AboveMark2Anchor, specifies a coordinate value for attaching the damma mark above the hanza base mark.

Example 9

Hex Data

Source

Comments

MarkMarkPosFormat1

MarkMarkAttachSubTable

;MarkBasePos subtable definition

0001

1

;PosFormat

000C

Mark1GlyphsCoverage

;offset to Mark1Coverage table

0012

Mark2GlyphsCoverage

;offset to Mark2Coverage table

0001

1

;ClassCount

0018

Mark1GlyphsArray

;offset to Mark1Array table

0024

Mark2GlyphsArray

;offset to Mark2Array table

CoverageFormat1

Mark1GlyphsCoverage

;Coverage table definition

0001

1

;CoverageFormat

0001

1

;GlyphCount

0296

dammaMarkGlyphID

;GlyphArray[0]

CoverageFormat1

Mark2GlyphsCoverage

;Coverage table definition

0001

1

;CoverageFormat

0001

1

;GlyphCount

0289

hanzaMarkGlyphID

;GlyphArray[1]

MarkArray

Mark1GlyphsArray

;MarkArray table definition

0001

1

;MarkCount

;MarkRecord[0]

; in CoverageIndex order

0000

0

;Class

; for marks above base mark

0006

dammaMarkAnchor

;offset to Anchor table

AnchorFormat1

dammaMarkAnchor

;Anchor table definition

0001

1

;AnchorFormat

00BD

189

;XCoordinate

FF99

-103

;YCoordinate

Mark2Array

Mark2GlyphsArray

;Mark2Array table definition

0001

1

;Mark2Count

;Mark2Record[0]

0004

AboveMark2Anchor

;offset to Anchor table[0]

AnchorFormat1

AboveMark2Anchor

;Anchor table definition

0001

1

;AnchorFormat

00DD

221

;XCoordinate

012D

301

;Ycoordinate


Example 10: ContextPosFormat1 Subtable and PosLookupRecord

Example 10 uses a ContextPosFormat1 subtable to adjust the spacing between three Arabic glyphs in a word. The context is the glyph sequence (from right to left): heh (initial form), thal (final form), and heh (isolated form). In the rendered word, the first two glyphs are connected, but the last glyph (the isolated form of heh), is separate. This subtable reduces the amount of space between the last glyph and the rest of the word.

The subtable contains a WordCoverage table that lists the first glyph in the word, heh (initial), and one PosRuleSet table, called WordPosRuleSet, that defines all contexts beginning with this covered glyph.

The WordPosRuleSet contains one PosRule that describes a word context of three glyphs and identifies the second and third glyphs (the first glyph is identified by the WordPosRuleSet). When a text-processing client locates this context in text, it applies a SinglePos lookup (not shown in the example) at position 3 to reduce the spacing between the glyphs.

Example 10

Hex Data

Source

Comments

ContextPosFormat1

MoveHehInSubtable

;ContextPos subtable definition

0001

1

;PosFormat

0008

WordCoverage

;offset to Coverage table

0001

1

;PosRuleSetCount

000E

WordPosRuleSet

;offset to PosRuleSet[0] table

CoverageFormat1

WordCoverage

;Coverage table offset

0001

1

;CoverageFormat

0001

1

;GlyphCount

02A6

hehInitialGlyphID

;GlyphArray[0]

PosRuleSet

WordPosRuleSet

;PosRuleSet table definition

0001

1

;PosRuleCount

0004

WordPosRule

;Offset to PosRule[0] table

PosRule

WordPosRule

;PosRule table definition

0003

3

;GlyphCount

0001

1

;PosCount

02DD

thalFinalGlyphID

;Input[1]

02C6

hehIsolatedGlyphID

;Input[0]

;PosLookupRecord[0]

0003

3

;SequenceIndex

0001

1

;LookupListIndex


Example 11: ContextPosFormat2 Subtable

The ContextPosFormat2 subtable in Example 11 defines context strings for five glyph classes: Class1 consists of uppercase glyphs that overhang and create a wide open space on their right side; Class2 consists of uppercase glyphs that overhang and create a narrow space on their right side; Class3 contains lowercase x-height vowels; and Class4 contains accent glyphs placed over the lowercase vowels. The rest of the glyphs in the font fall into Class0.

The MoveAccentsSubtable defines two similar context strings. The first consists of a Class1 uppercase glyph followed by a Class3 lowercase vowel glyph with a Class4 accent glyph over the vowel. When this context is found in the text, the client lowers the accent glyph over the vowel so that it does not collide with the overhanging glyph shape. The second context consists of a Class2 uppercase glyph, followed by a Class3 lowercase vowel glyph with a Class4 accent glyph over the vowel. When this context is found in the text, the client increases the advance width of the uppercase glyph to expand the space between it and the accented vowel.

The MoveAccents subtable defines a MoveAccentsCoverage table that identifies the first glyphs in the two contexts and offsets to five PosClassSet tables, one for each class defined in the ClassDef table. Since no contexts begin with Class0, Class3, or Class4 glyphs, the offsets to the PosClassSet tables for these classes are NULL. PosClassSet[1] defines all contexts beginning with Class1 glyphs; it is called UCWideOverhangPosClass1Set. PosClassSet[2] defines all contexts beginning with Class2 glyphs, and it is called UCNarrowOverhangPosClass1Set.

Each PosClassSet defines one PosClassRule. The UCWideOverhangPosClass1Set uses the UCWideOverhangPosClassRule to specify the first context. The first class in this context string is identified by the PosClassSet that includes a PosClassRule, in this case Class1. The PosClassRule table lists the second and third classes in the context as Class3 and Class4. A SinglePos Lookup (not shown) lowers the accent glyph in position 3 in the context string.

The UCNarrowOverhangPosClass1Set defines the UCNarrowOverhangPosClassRule for the second context. This PosClassRule is identical to the UCWideOverhangPosClassRule, except that the first class in the context string is a Class2 lowercase glyph. A SinglePos Lookup (not shown) increases the advance width of the overhanging uppercase glyph in position 0 in the context string.

Example 11

Hex Data

Source

Comments

ContextPosFormat2

MoveAccentsSubtable

;ContextPos subtable definition

0002

2

;PosFormat

0012

MoveAccentsCoverage

;Offset to Coverage table

0020

MoveAccentsClassDef

;Offset to ClassDef

0005

5

;PosClassSetCnt

0000

NULL

;PosClassSet[0]

; no contexts begin with Class0

; glyphs

0060

UCWideOverhangPosClass1Set

;PosClassSet[1]

; contexts beginning with Class1

; glyphs

0070

UCNarrowOverhangPosClass2Set

;PosClassSet[2]

; context beginning with Class2

; glyphs

0000

NULL

;PosClassSet[3]

; no contexts begin with Class3

; glyphs

0000

NULL

;PosClassSet[4]

; no contexts begin with Class4

; glyphs

CoverageFormat1

MoveAccentsCoverage

;Coverage table definition

0001

1

;CoverageFormat

0005

5

;GlyphCount

0029

UppercaseFGlyphID

;GlyphArray[0]

0033

UppercasePGlyphID

;GlyphArray[1]

0037

UppercaseTGlyphID

;GlyphArray[2]

0039

UppercaseVGlyphID

;GlyphArray[3]

003A

UppercaseWGlyphID

;GlyphArray[4]

ClassDefFormat2

MoveAccentsClassDef

;ClassDef table definition

; defines five classes = 0 (all

; else), 1 (T, V, W: UCUnderhang),

; 2 (F, P: UCOverhang), 3 (a, e,

; I, o, u: LCVowels), 4 (tilde,

; umlaut)

0002

2

;ClassFormat, ranges

000A

10

;ClassRangeCount

;ClassRangeRecord[0]

0029

UppercaseFGlyphID

;Start

0029

UppercaseFGlyphID

;End

0002

2

;Class

;ClassRangeRecord[1]

0033

UppercasePGlyphID

;Start

0033

UppercasePGlyphID

;End

0002

2

;Class

;ClassRangeRecord[2]

0037

UppercaseTGlyphID

;Start

0037

UppercaseTGlyphID

;End

0001

1

;Class

;ClassRangeRecord[3]

0039

UppercaseVGlyphID

;Start

003A

UppercaseWGlyphID

;End

0001

1

;Class

;ClassRangeRecord[4]

0042

LowercaseAGlyphID

;Start

0042

LowercaseAGlyphID

;End

0003

3

;Class

;ClassRangeRecord[5]

0046

LowercaseEGlyphID

;Start

0046

LowercaseEGlyphID

;End

0003

3

;Class

;ClassRangeRecord[6]

004A

LowercaseIGlyphID

;Start

004A

LowercaseIGlyphID

;End

0003

3

;Class

;ClassRangeRecord[7]

0051

LowercaseOGlyphID

;Start

0051

LowercaseOGlyphID

;End

0003

3

;Class

;ClassRangeRecord[8]

0056

LowercaseUGlyphID

;Start

0056

LowercaseUGlyphID

;End

0003

3

;Class

;ClassRangeRecord[9]

00F5

TildeAccentGlyphID

;Start

00F6

UmlautAccentGlyphID

;End

0004

4

;Class

PosClassSet

UCWideOverhangPosClass1Set

;PosClassSet table definition

0001

1

;PosClassRuleCnt

0004

UCWideOverhangPosClassRule

;PosClassRule[0]

PosClassRule

UCWideOverhangPosClassRule

;PosClassRule table definition

0003

3

;GlyphCount

0001

1

;PosCount

0003

3

;Class[1]

; lowercase vowel

0004

4

;Class[2]

; accent

;PosLookupRecord[0]

0002

2

;SequenceIndex

0001

1

;LookupListIndex

; lower the accent

PosClassSet

UCNarrowOverhangPosClass2Set

;PosClassSet table definition

0001

1

;PosClassRuleCnt

0004

UCNarrowOverhangPosClassRule

;PosClassRule[0]

PosClassRule

UCNarrowOverhangPosClassRule

;PosClassRule table definition

0003

3

;GlyphCount

0001

1

;PosCount

0003

3

;Class[1]

; lowercase vowel

0004

4

;Class[2]

; accent

;PosLookupRecord[0]

0000

0

;SequenceIndex

0002

2

;LookupListIndex

; increase overhang advance

; width


Example 12: ContextPosFormat3 Subtable

Example 12 uses a ContextPosFormat3 subtable to lower the position of math signs in math equations consisting of a lowercase descender or x-height glyph, a math sign glyph, and any lowercase glyph. Format3 is better to use for this context than the class-based Format2 because the sets of covered glyphs for positions 0 and 2 overlap.

The LowerMathSignsSubtable contains offsets to three Coverage tables (XhtDescLCCoverage, MathSignCoverage, and LCCoverage), one for each position in the context glyph string. When the client finds the context in the text stream, it applies the PosLookupRecord data at position 1 and repositions the math sign.

Example 12

Hex Data

Source

Comments

ContextPosFormat3

LowerMathSignsSubtable

;ContextPos subtable definition

0003

3

;PosFormat

0003

3

;GlyphCount

0001

1

;PosLookup

0010

XhtDescLCCoverage

;Offset to Coverage[0] table

003C

MathSignCoverage

;Offset to Coverage[1] table

0044

LCCoverage

;Offset to Coverage[2] table

;PosLookupRecord[0]

0001

1

;SequenceIndex

0001

1

;LookupListIndex

CoverageFormat1

XhtDescLCCoverage

;Coverage table definition

0001

1

;CoverageFormat

0014

20

;GlyphCount

0033

LCaGlyphID

;GlyphArray[0]

0035

LCcGlyphID

;GlyphArray[1]

0037

LCeGlyphID

;GlyphArray[2]

0039

LCgGlyphID

;GlyphArray[3]

003B

LCiGlyphID

;GlyphArray[4]

003C

LCjGlyphID

;GlyphArray[5]

003F

LCmGlyphID

;GlyphArray[6]

0040

LCnGlyphID

;GlyphArray[7]

0041

LCoGlyphID

;GlyphArray[8]

0042

LCpGlyphID

;GlyphArray[9]

0043

LCqGlyphID

;GlyphArray[10]

0044

LCrGlyphID

;GlyphArray[11]

0045

LCsGlyphID

;GlyphArray[12]

0046

LCtGlyphID

;GlyphArray[13]

0047

LCuGlyphID

;GlyphArray[14]

0048

LCvGlyphID

;GlyphArray[15]

0049

LCwGlyphID

;GlyphArray[16]

004A

LCxGlyphID

;GlyphArray[17]

004B

LCyGlyphID

;GlyphArray[18]

004C

LCzGlyphID

;GlyphArray[19]

CoverageFormat1

MathSignCoverage

;Coverage table definition

0001

1

;CoverageFormat

0002

2

;GlyphCount

011E

EqualsSignGlyphID

;GlyphArray[0]

012D

PlusSignGlyphID

;GlyphArray[1]

CoverageFormat2

LCCoverage

;Coverage table definition

0002

2

;CoverageFormat

0001

1

;RangeCount

;RangeRecord[0]

0033

LCaGlyphID

;Start

004C

LCzGlyphID

;End

0000

0

;StartCoverageIndex


Example 13: PosLookupRecord

The PosLookupRecord in Example 13 identifies a lookup to apply at the second glyph position in a context glyph string.

Example 13

Hex Data

Source

Comments

PosLookupRecord

PosLookupRecord[0]

;PosLookupRecord definition

0001

1

;SequenceIndex

; for second glyph position

0001

1

;LookupListIndex

; apply this lookup to second

; glyph position


Example 14: ValueFormat Table and ValueRecord

Example 14 demonstrates how to specify positioning values in the GPOS table. Here, a SinglePosFormat1 subtable defines the ValueFormat and ValueRecord. The ValueFormat bit setting of 0x0099 says that the corresponding ValueRecord contains values for a glyph's XPlacement and YAdvance. Device tables specify pixel adjustments for these values at font sizes from 11 ppem to 15 ppem.

Example 14

Hex Data

Source

Comments

SinglePosFormat1

OnesSubtable

;SinglePos subtable definition

0001

1

;PosFormat

000E

Cov

;Offset to Coverage table

0099

0x0099

;ValueFormat

; for XPlacement, YAdvance, XPlaDevice, YAdvaDevice

;Value

0050

80

; Xplacement value

00D2

210

; Yadvance value

0018

XPlaDeviceTable

;Offset to XPlaDevice table

0020

YAdvDeviceTable

;Offset to YAdvDevice table

CoverageFormat2

Cov

;Coverage table definition

0002

2

;CoverageFormat

0001

1

;RangeCount

;RangeRecord[0]

00C8

200

;Start

; first glyph ID in range

00D1

209

;End

; last glyph ID in range

0000

0

;StartCoverageIndex

DeviceTableFormat1

XPlaDeviceTable

;Device Table definition

000B

11

;StartSize

000F

15

;EndSize

0001

1

;DeltaFormat

1

; increase 11ppem by 1 pixel

1

; increase 12ppem by 1 pixel

1

; increase 13ppem by 1 pixel

1

; increase 14ppem by 1 pixel

5540

1

; increase 15ppem by 1 pixel

DeviceTableFormat1

YAdvDeviceTable

;Device Table definition

000B

11

;StartSize

000F

15

;EndSize

0001

1

;DeltaFormat

1

; increase 11ppem by 1 pixel

1

; increase 12ppem by 1 pixel

1

; increase 13ppem by 1 pixel

1

; increase 14ppem by 1 pixel

5540

1

; increase 15ppem by 1 pixel


Example 15: AnchorFormat1 Table

Example 15 illustrates an Anchor table for the damma mark glyph in the Arabic script. Format1 is used to specify X and Y coordinate values in design units.

Example 15

Hex Data

Source

Comments

AnchorFormat1

dammaMarkAnchor

;Anchor table definition

0001

1

;AnchorFormat

00BD

189

;XCoordinate

FF99

-103

;YCoordinate


Example 16: AnchorFormat2 Table

Example 16 shows an AnchorFormat2 table for an attachment point placed above a base glyph. With this format, the coordinate value for the Anchor depends on the final position of a specific contour point on the base glyph after hinting. The coordinates are specified in design units.

Example 16

Hex Data

Source

Comments

AnchorFormat2

AboveBaseAnchor

;Anchor table definition

0002

2

;AnchorFormat

0142

322

;XCoordinate

0384

900

;Ycoordinate

000D

13

;AnchorPoint

; glyph contour point index


Example 17: AnchorFormat3 Table

Example 17 shows an AnchorFormat3 table that specifies an attachment point above a base glyph. Device tables modify the X and Y coordinates of the Anchor for the point size and resolution of the output font. Here, the Device tables define pixel adjustments for font sizes from 12 ppem to 17 ppem.

Example 17

Hex Data

Source

Comments

AnchorFormat3

AboveBaseAnchor

;Anchor table definition

0003

3

;AnchorFormat

0117

279

;XCoordinate

0515

1301

;YCoordinate

000A

XDevice

;offset to DeviceTable

; for X coordinate

0014

YDevice

;offset to Device table

; for Y coordinate

DeviceTableFormat2

XDevice

;Device Table definition

000C

12

;StartSize

0011

17

;EndSize

0002

2

;DeltaFormat

1

; increase 12ppem by 1 pixel

1

; increase 13ppem by 1 pixel

1

; increase 14ppem by 1 pixel

1111

1

; increase 15ppem by 1 pixel

2

; increase 16ppem by 1 pixel

2200

2

; increase 17ppem by 1 pixel

DeviceTableFormat2

YDevice

;Device Table definition

000C

12

;StartSize

0011

17

;EndSize

0002

2

;DeltaFormat

1

; increase 12ppem by 1 pixel

1

; increase 13ppem by 1 pixel

1

; increase 14ppem by 1 pixel

1111

1

; increase 15ppem by 1 pixel

2

; increase 16ppem by 1 pixel

2200

2

; increase 17ppem by 1 pixel


Example 18: MarkArray Table and MarkRecord

Example 18 shows a MarkArray table with class and attachment point data for two accent marks, a grave and a cedilla. Two MarkRecords are defined, one for each covered mark glyph. The first MarkRecord assigns a mark class value of 0 to accents placed above base glyphs, such as the grave, and has an offset to a graveMarkAnchor table. The second MarkRecord assigns a mark class value of 1 for all accents positioned below base glyphs, such as the cedilla, and has an offset to a cedillaMarkAnchor table.

Example 18

Hex Data

Source

Comments

MarkArray

MarkGlyphsArray

;MarkArray table definition

0002

2

;MarkCount

;MarkRecord[0]

;for first mark in

; MarkCoverage table,

; grave

0000

0

;Class, for marks placed above

; base glyphs

000A

graveMarkAnchor

;offset to Anchor table

;MarkRecord[1]

;for second mark in

; MarkCoverage table =

; cedilla

0001

1

;Class, for marks placed below

; base glyphs

0010

cedillaMarkAnchor

;offset to Anchor table