Lookup Type 2:
Pair Adjustment Positioning Subtable

A pair adjustment positioning subtable (PairPos) is used to adjust the positions of two glyphs in relation to one another—for instance, to specify kerning data for pairs of glyphs. Compared to a typical kerning table, however, a PairPos subtable offers more flexiblity and precise control over glyph positioning. The PairPos subtable can adjust each glyph in a pair independently in both the X and Y directions, and it can explicitly describe the particular type of adjustment applied to each glyph. In addition, a PairPos subtable can use Device tables to subtly adjust glyph positions at each font size and device resolution.

PairPos subtables can be either of two formats: one that identifies glyphs individually by index (Format 1), or one that identifies glyphs by class (Format 2).

Pair Positioning Adjustment: Format 1

Format 1 uses glyph indices to access positioning data for one or more specific pairs of glyphs. All pairs are specified in the order determined by the layout direction of the text.

Note: For text written from right to left, the right-most glyph will be the first glyph in a pair; conversely, for text written from left to right, the left-most glyph will be first.

A PairPosFormat1 subtable contains a format identifier (PosFormat) and two ValueFormats:

ValueFormat1 applies to the ValueRecord of the first glyph in each pair. ValueRecords for all first glyphs must use ValueFormat1.

ValueFormat2 applies to the ValueRecord of the second glyph in each pair. ValueRecords for all second glyphs must use ValueFormat2.

Either of the two ValueFormats may be set to zero (0) to indicate that the corresponding glyph has no ValueRecord and, therefore, should not be repositioned.

A PairPos subtable also defines an offset to a Coverage table (Coverage) that lists the indices of the first glyphs in each pair. More than one pair can have the same first glyph, but the Coverage table will list that glyph only once.

The subtable also contains an array of offsets to PairSet tables (PairSet) and a count of the defined tables (PairSetCount). The PairSet array contains one offset for each glyph listed in the Coverage table and uses the same order as the Coverage Index.

PairPosFormat1 subtable: Adjustments for glyph pairs

Type

Name

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

ValueRecord

PairSet[PairSetCount]

Array of offsets to PairSet tables

—from beginning of PairPos subtable

—ordered by Coverage Index


A PairSet table enumerates all the glyph pairs that begin with a covered glyph. An array of PairValueRecords (PairValueRecord) contains one record for each pair and lists the records alphabetically by the second glyph in each pair. PairValueCount specifies the number of PairValueRecords in the set.

PairSet table

Type

Name

Description

uint16

PairValueCount

Number of PairValueRecords

struct

PairValueRecord

Array of PairValueRecords

[PairValueCount]

—ordered alphabetically by second glyph


A PairValueRecord specifies the second glyph in a pair (SecondGlyph) and defines a ValueRecord for each glyph (Value1 and Value2). If ValueFormat1 is set to zero (0) in the PairPos subtable, ValueRecord1 will be empty; similarly, if ValueFormat2 is 0, Value2 will be empty.

Example 4 at the end of this chapter shows a PairPosFormat1 subtable that defines two cases of pair kerning.

PairValueRecord

Type

Name

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 defines a pair as a set of two glyph classes and modifies the positions of all the glyphs in a class. For example, this format is useful in Japanese scripts that apply specific kerning operations to all glyph pairs that contain punctuation glyphs. One class would be defined as all glyphs that may be coupled with punctuation marks, and the other classes would be groups of similar punctuation glyphs.

The PairPos Format2 subtable begins with a format identifier (PosFormat) and an offset to a Coverage table (Coverage), measured from the beginning of the PairPos subtable. The Coverage table lists the indices of the first glyphs that may appear in each glyph pair. More than one pair may begin with the same glyph, but the Coverage table lists the glyph index only once.

Note: The ClassDef1 table also identifies the first glyphs in each pair, but the redundant listing in the Coverage table accelerates the lookup process.

A PairPosFormat2 subtable also includes two ValueFormats:

ValueFormat1 applies to the ValueRecord of the first glyph in each pair. The ValueRecords for all the first glyphs must use ValueFormat1.

ValueFormat2 applies to the ValueRecord of the second glyph in each pair. The ValueRecords for all of the second glyphs must use ValueFormat2.

Either of the two ValueFormats may be set to zero (0) to indicate that the corresponding glyph has no ValueRecord and, therefore, should not be repositioned.

PairPosFormat2 requires that each glyph in all pairs be assigned to a class, which is identified by an integer called a class value. (For details about classes, see the chapter, Common Table Formats.) Pairs are then represented in a two-dimensional array as sequences of two class values. Multiple pairs can be represented in one Format 2 subtable.

A PairPosFormat2 subtable contains offsets to two class definition tables: one that assigns class values to all the first glyphs in all pairs (ClassDef1), and one that assigns class values to all the second glyphs in all pairs (ClassDef2). If both glyphs in a pair use the same class definition, the offset value will be the same for ClassDef1 and ClassDef2. The subtable also specifies the number of glyph classes defined in ClassDef1 (Class1Count) and in ClassDef2 (Class2Count), including Class0.

For each class identified in the ClassDef1 table, a Class1Record enumerates all pairs that contain a particular class as a first component. The Class1Record array stores all Class1Records according to class value.

Note: Class1Records are not tagged with a class value identifier. Instead, the index value of a Class1Record in the array defines the class value represented by the record. For example, the first Class1Record enumerates pairs that begin with a Class 0 glyph, the second Class1Record enumerates pairs that begin with a Class1 glyph, and so on.

PairPosFormat2 subtable: Class pair adjustment

Type

Name

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

Array of Class1 records

[Class1Count]

—ordered by Class1


Each Class1Record contains an array of Class2Records (Class2Record), which also are ordered by class value. One Class2Record must be declared for each class in the ClassDef2 table, including Class 0.

Class1Record

Type

Name

Description

struct

Class2Record

Array of Class2 records

[Class2Count]

—ordered by Class2


A Class2Record consists of two ValueRecords, one for the first glyph in a class pair (Value1) and one for the second glyph (Value2). If the PairPos subtable has a value of zero (0) for ValueFormat1 or ValueFormat2, the corresponding record (ValueRecord1 or ValueRecord2) will be empty.

Example 5 at the end of this chapter demonstrates pair kerning with glyph classes in a PairPosFormat2 subtable.

Class2Record

Type

Name

Description

ValueRecord

Value1

Positioning for first glyph

—empty if ValueFormat1 = 0

ValueRecord

Value2

Positioning for second glyph

—empty if ValueFormat2 = 0