The 'prop'
table
General table information
Introduction
The glyph properties table(tag name: 'prop'
) allows you to create Apple Advanced Typography (AAT) fonts with different properties associated with each glyph. Properties that are currently supported are the following:
- Non-spacing marks. These are non-spacing glyphs that are positioned with reference to a preceding base character. Examples include floating glyphs, such as diacritics, accents, and marks.
- Hanging glyphs. These glyphs hang off of the left or right edge of horizontal lines of text or hang off the top or bottom of vertical lines of text.
- Directional paired glyphs. These glyphs are left-to-right and right-to-left line dependent. An example is bracketing glyphs, such as parentheses, square brackets, and curly brackets.
- Attachment on right. These glyphs physically attach to the glyphs placed to their right. This information is used during justification to guarantee no extra space, ideal or device, is added between glyphs which are thus attached.
All Unicode characters possess directionality. Characters that have left-to-right and right-to-left directionality are called strong types. Characters of strong types are called strong directional characters. The directional types associated with numbers are called weak types. The characters of those types are called weak directional characters. A neutral charactercan be written either right-to-left or left-to-right, depending upon the context of the line.
See The Unicode Standard: Worldwide Character Encoding for additional information concerning properties and directionality.
Glyph Properties Table Format
The glyph properties table consists of a glyph properties table header and a glyph properties lookup table. The overall structure of the glyph properties table is shown in the following figure:
There have been three versions of the glyph properties table since its inception. The versions are summarized in the following table:
Version | Description |
---|---|
1.0 | Initial version, supporting floaters, hanging punctuation, symmetric swapping, and 12 basic Unicode directional properties. |
2.0 | Released with MacOS system 8.5, this version adds support for the "attaches on right" bit. |
3.0 | This is the version currently used on OS X and iOS; it adds support for the additional directional properties defined in Unicode 3.0. |
The format of the glyph properties table is as follows:
Type | Name | Description |
---|---|---|
fixed32 | version | Version number of the glyph properties table. See table above for what each version means. |
uint16 | format | Format of the glyph properties table, set to 0 if no lookup data is present; set to 1 if lookup data is present. |
uint16 | default properties | Default properties applied to a glyph if that glyph is not present in the lookup table. |
variable | lookup data | Lookup table associating glyphs with their properties. See below for details on how to interpret the lookup values. |
A lookup table is used to find the 16-bit property value associated with the particular glyph. This is how to interpret the lookup for each of the 5 lookup table formats:
Lookup table format | Interpretation |
---|---|
0 | Array of 16-bit property values, one for each glyph in the font. |
2 | The value of each lookupSegment is a 16-bit property value for all of the glyphs in that segment. |
4 | The value of each lookupSegment is a 16-bit offset from the start of the lookup table to an array of 16-bit property values, one for each glyph in the segment. |
6 | The value of each lookupSingle is the 16-bit property value for that glyph. |
8 | The valueArray is an array of 16-bit property values, one for each glyph in the trimmed array. |
A single glyph property is 16 bits long. Glyph property bit masks and their descriptions are shown in the following table:
Mask | Interpretation |
---|---|
0x8000 | This glyph is a floater (for example a floating accent or vowel mark). NOTE: It is very important that this bit only be set for glyphs that have a zero advance width. |
0x4000 | This glyph can hang off the left edge of a horizontal line or the top edge of a vertical line. |
0x2000 | This glyph can hang off the right edge of a horizontal line or the bottom edge of a vertical line. |
0x1000 | If this property bit is on, and the glyph ends up in a right-to- left directional grouping, then the complementary bracketing glyph should be substituted for this glyph. |
0x0F00 | These four bits give the offset to the complementary bracketing glyph (or zero if this glyph has no such complementary bracketing glyph). |
0x0080 | This glyph always attaches to the glyph appearing physically to the right of it. Note that this bit was added in version 2.0; it is invalid to set it in a version 1.0 glyph properties table. |
0x0060 | These two bits must be set to zero. This mask is reserved for future properties. |
0x001F | These five bits contain the glyph's directionality class. Note that in versions of Unicode prior to 3.0, only four of these bits are actually used. |
The Unicode reordering algorithm treats characters such as '(' and ')' as open and closed parentheses, rather than as left and right parentheses. This means that the glyphs used to render these bracketing characters will depend upon the final resolved direction of the text, as shown in the following table:
Directionality | Open/Closed | Bracketing Glyphs |
---|---|---|
left-to-right | Open | (, [, { |
left-to-right | Closed | ), ], } |
right-to-left | Open | ), ], } |
right-to-left | Closed | (, [, { |
In order to accommodate the bi-directionality of bracketing glyphs, the 'cmap'
table should always change bracketing characters in glyphs corresponding to their 'natural' direction. Therefore, when one of the two brackets is used, the complementary glyph must be identified to the AAT rendering system. This is accomplished by the use of the 0x1F00 bits. If the glyph is a bracketing glyph, then 0x0F00 bits are treated as a 4-bit signed offset to the glyph index of the corresponding glyph. The 0x1000 bit is used to determine whether the glyph at that specified offset is a right-to-left or left-to-right version of the glyph.
For example, in a Roman font, the order of parenthesis glyphs is usually '(' followed by ')'. The glyph index may be 11 for the '(' glyph and 12 for the ')' glyph. The property masks, 0x1F00, for the '(' glyph would then be 0x1100 for the ')' glyph and 0x1F00 for the ')' glyph. The 0x1100 mask for glyph index="11" indicates that the corresponding glyph is right-to-left and the glyph index offset is +1, glyph index="11" + 1="12." The 0x1F00 mask indicates that the corresponding glyph is also right-to-left and the glyph index offset to it is -1, glyph index="12" - 1="11."
If there are one or more glyphs between the '(' and the ')' in the glyph index, then the this information is conveyed through the mask values. For example, if the glyph indexes were 11 and 13 for the respective parentheses glyphs, property mask 0x1F00 for the '(' glyph would be 0x1200 for the ')' glyph and 0x1E00 for the ')' glyph. The 0x1200 mask indicates that the corresponding glyph is also right-to-left and the glyph index offset is +2, glyph index="11" + 2="13." The 0x1E00 mask indicates that the corresponding glyph is also right-to-left and the glyph index offset to it is -2, glyph index="13" - 2="11."
The Apple Advanced Typography system currently supports the following directionality classes:
Type | Class (decimal) |
Description |
---|---|---|
Strong | 0 | Strong (left-to-right) |
Strong | 1 | Strong (right-to-left, non-Arabic) |
Strong | 2 | Arabic letters (right-to-left) |
Weak | 3 | European number |
Weak | 4 | European number separator |
Weak | 5 | European number terminator |
Weak | 6 | Arabic number |
Weak | 7 | Common number separator |
Neutral | 8 | Block separator |
Neutral | 9 | Segment separator |
Neutral | 10 | Whitespace |
Neutral | 11 | Other neutrals |
Neutral | 12 through 31 | Reserved (some are actually defined in Unicode 3.0) |
NOTE: additional properties have been defined in Unicode 3.0. If these properties are used, make sure the version of this table is set to 3.0 or higher!
Any of the lookup table formats can be used. If the glyphs share similar properties, Format 2 may be appropriate. If only a few glyphs differ from the default, Format 6 may be preferred. If the number of segments will be large, Formats 0 or 8 may be selected.
Glyph Properties Table Examples
Example Font with Hebrew and Roman Characters
This example font will contain both Hebrew and Roman characters. Bidirectional features for this font need to be included to accommodate the fact that the Roman glyphs will be left-to-right and Hebrew glyphs will be right-to-left.
The definition of the default property as being either left-to-right or right-to-left is arbitrary. Specifying the directionality class as 0 defines the default properties of this font as strong left-to-right. This will be fine for the Roman glyphs, but we will need to provide a lookup table that defines the Hebrew glyphs as having right-to- left directionality. Specifying the directionality class as 1 for the Hebrew glyphs defines their non-default properties as strong right-to-left (non-Arabic).
Because many of the glyphs in this font share similar properties, we'll use a format 2 single segment lookup table for the non-default glyphs. We will use two segments, each with its own set of properties. The segments will be contiguous ranges of glyph indices in which all glyphs in the segment will have a single lookup value designating the properties of the segment. Glyph properties data for this font is summarized in the following table:
Glyphs | Glyph index | Directionality class |
Mask value |
---|---|---|---|
Roman | 3-149 | 0 | Not required for the default class. |
Hebrew | 150-225 | 1 | 1 (dec), 0x0001, Segment 2 |
Whitespace | 2 | 10 | 10 (dec), 0x000A, Segment 1 |
The glyph properties table for this example font is as follows:
Offset/ length |
Value | Name | Comment |
---|---|---|---|
0/4 | 0x00030000 | version | Version number of the glyph properties table, in fixed-point format. |
4/2 | 1 | format | Format of the glyph properties table is 1. Lookup data is present. |
6/2 | 0 | default properties | Default properties are left-to-right directionality and non-whitespace; glyphs cannot hang off either end of a line or be floaters. |
(The format 2 lookup table starts here) | |||
8/2 | 2 | format | Lookup table format 2 (segment single format). |
(The next five fields are the lookup table's BinSrchHeader) | |||
10/2 | 6 | unitSize | Size of a LookupSegment: 2 bytes for the starting glyph index, 2 bytes for the ending glyph index, and 2 bytes for the glyph properties value. |
12/2 | 2 | nUnits | Number of entries of the preceding unitSize to be searched. There are 2 properties to be included in the lookup table. |
14/2 | 12 | searchRange | The unitSize times the largest power of two that is less than or equal to nUnits. |
16/2 | 1 | entrySelector | The log base 2 of the largest power of two less than or equal to nUnits. |
18/2 | 0 | rangeShift | The unitSize times the difference of nUnits minus the largest power of two less than or equal to nUnits. |
(The LookupSegment entries start here; the first lookup segment follows) |
|||
20/2 | 2 | lastGlyph | Glyph index for whitespace. This is the last glyph index in this segment. |
22/2 | 2 | firstGlyph | Glyph index for whitespace. This is the first glyph index in this segment. |
24/2 | 0x000A | value | Properties for glyph index 2. Directionality class 10 (whitespace, neutral). |
(The second LookupSegment follows) |
|||
26/2 | 225 | lastGlyph | Ending glyph index for Hebrew glyphs. This is the last glyph index in this segment. |
28/2 | 150 | firstGlyph | Starting glyph index for Hebrew glyphs. This is the first glyph index in this segment. |
30/2 | 0x0001 | value | Properties for glyph index 150 through 225 (right-to-left). |
Example Font with Roman Characters
This example font contains 98 Roman glyphs, covering the glyphs needed for 7-bit ASCII. The glyph properties data for this example font is as follows:
Segment | Glyph index | Glyph | Props | Directionality class |
---|---|---|---|---|
0 | 3 | space | 0x000A | Whitespace (10) |
1 | 4 | ! | 0x000B | Other neutrals (11) |
2 | 5 | " | 0x600B | Other neutrals (11) |
3 | 6-8 | # $ % | 0x0005 | European number terminator (5) |
4 | 9 | & | 0x0000 | Strong (left-to-right) (0) |
5 | 10 | ' | 0x600B | Other neutrals (11) |
6 | 11 | ( | 0x110B | Other neutrals (11) |
7 | 12 | ) | 0x1F0B | Other neutrals (11) |
8 | 13 | * | 0x000B | Other neutrals (11) |
9 | 14 | + | 0x0005 | European number terminator (5) |
10 | 15 | , | 0x0007 | Common number separator (7) |
11 | 16 | ? | 0x0005 | European number terminator (5) |
12 | 17-18 | . / | 0x0004 | European number separator (4) |
13 | 19-28 | 0-9 | 0x0003 | European number (3) |
14 | 29 | : | 0x0007 | Common number separator (7) |
15 | 30 | ; | 0x000B | Other neutrals (11) |
16 | 31 | < | 0x120B | Other neutrals (11) |
17 | 32 | = | 0x000B | Other neutrals (11) |
18 | 33 | > | 0x1E0B | Other neutrals (11) |
19 | 34-35 | ? @ | 0x000B | Other neutrals (11) |
20 | 36-61 | A-Z | 0x0000 | Strong (left-to-right) (0) |
21 | 62 | [ | 0x120B | Other neutrals (11) |
22 | 63 | \ | 0x000B | Other neutrals (11) |
23 | 64 | ] | 0x1E0B | Other neutrals (11) |
24 | 65-93 | ^ _ ` and a-z | 0x0000 | Strong (left-to-right) (0) |
25 | 94 | { | 0x120B | Other neutrals (11) |
26 | 95 | | | 0x000B | Other neutrals (11) |
27 | 96 | } | 0x1E0B | Other neutrals (11) |
28 | 97 | ~ | 0x000B | Other neutrals (11) |
The glyph properties table for this example font is given in the following table:
Offset/length | Value | Name | Comment |
---|---|---|---|
0/4 | 0x00030000 | version | Version number of the glyph properties table, in fixed-point format. |
4/2 | 1 | format | Table format is 1, meaning lookup data is present. |
6/2 | 0 | default | Default properties are left-to-right directionality and non-whitespace; glyphs cannot hang off either end of a line or be floaters. |
(The format 8 lookup table starts here) | |||
8/2 | 8 | format | Lookup table format 8 (trimmed array). |
10/2 | 3 | firstGlyph | First glyph for which we include values in the trimmed array. |
12/2 | 95 | glyphCount | Number of glyphs in the trimmed array. |
(The actual properties follow here, one 16-bit word for each glyph from 3 through 97) | |||
14/2 | 0x000A | valueArray[0] | Glyph 3 is whitespace. |
16/2 | 0x000B | valueArray[1] | Glyph 4 is other neutral. |
18/2 | 0x600B | valueArray[2] | Glyph 5 is other neutral, and is also a hanging punctuation glyph that can hang from either side. |
20/2 | 0x0005 | valueArray[3] | Glyph 6 is a European number terminator. |
22/2 | 0x0005 | valueArray[4] | Glyph 7 is a European number terminator. |
24/2 | 0x0005 | valueArray[5] | Glyph 8 is a European number terminator. |
26/2 | 0x0000 | valueArray[6] | Glyph 9 is left-to-right. |
28/2 | 0x600B | valueArray[7] | Glyph 10 is other neutral, and is also a hanging punctuation glyph that can hang from either side. |
30/2 | 0x110B | valueArray[8] | Glyph 11 is other neutral, and has a bracketing glyph at an offset of +1. |
32/2 | 0x1F0B | valueArray[9] | Glyph 12 is other neutral, and has a bracketing glyph at an offset of -1. |
34/2 | 0x000B | valueArray[10] | Glyph 13 is other neutral. |
36/2 | 0x0005 | valueArray[11] | Glyph 14 is a European number terminator. |
38/2 | 0x0007 | valueArray[12] | Glyph 15 is a Common number terminator. |
40/2 | 0x0005 | valueArray[13] | Glyph 16 is a European number terminator. |
42/2 | 0x0004 | valueArray[14] | Glyph 17 is a European number separator. |
44/2 | 0x0004 | valueArray[15] | Glyph 18 is a European number separator. |
46/2 | 0x0003 | valueArray[16] | Glyph 19 is a European number. |
48/2 | 0x0003 | valueArray[17] | Glyph 20 is a European number. |
50/2 | 0x0003 | valueArray[18] | Glyph 21 is a European number. |
52/2 | 0x0003 | valueArray[19] | Glyph 22 is a European number. |
54/2 | 0x0003 | valueArray[20] | Glyph 23 is a European number. |
56/2 | 0x0003 | valueArray[21] | Glyph 24 is a European number. |
58/2 | 0x0003 | valueArray[22] | Glyph 25 is a European number. |
60/2 | 0x0003 | valueArray[23] | Glyph 26 is a European number. |
62/2 | 0x0003 | valueArray[24] | Glyph 27 is a European number. |
64/2 | 0x0003 | valueArray[25] | Glyph 28 is a European number. |
66/2 | 0x0007 | valueArray[26] | Glyph 29 is a Common number terminator. |
68/2 | 0x000B | valueArray[27] | Glyph 30 is other neutral. |
70/2 | 0x120B | valueArray[28] | Glyph 31 is other neutral, and has a bracketing glyph at an offset of +2. |
72/2 | 0x000B | valueArray[29] | Glyph 32 is other neutral. |
74/2 | 0x1E0B | valueArray[30] | Glyph 33 is other neutral, and has a bracketing glyph at an offset of -2. |
76/2 | 0x000B | valueArray[31] | Glyph 34 is other neutral. |
78/2 | 0x000B | valueArray[32] | Glyph 35 is other neutral. |
80/2 | 0x0000 | valueArray[33] | Glyph 36 is left-to-right. |
82/2 | 0x0000 | valueArray[34] | Glyph 37 is left-to-right. |
84/2 | 0x0000 | valueArray[35] | Glyph 38 is left-to-right. |
86/2 | 0x0000 | valueArray[36] | Glyph 39 is left-to-right. |
88/2 | 0x0000 | valueArray[37] | Glyph 40 is left-to-right. |
90/2 | 0x0000 | valueArray[38] | Glyph 41 is left-to-right. |
92/2 | 0x0000 | valueArray[39] | Glyph 42 is left-to-right. |
94/2 | 0x0000 | valueArray[40] | Glyph 43 is left-to-right. |
96/2 | 0x0000 | valueArray[41] | Glyph 44 is left-to-right. |
98/2 | 0x0000 | valueArray[42] | Glyph 45 is left-to-right. |
100/2 | 0x0000 | valueArray[43] | Glyph 46 is left-to-right. |
102/2 | 0x0000 | valueArray[44] | Glyph 47 is left-to-right. |
104/2 | 0x0000 | valueArray[45] | Glyph 48 is left-to-right. |
106/2 | 0x0000 | valueArray[46] | Glyph 49 is left-to-right. |
108/2 | 0x0000 | valueArray[47] | Glyph 50 is left-to-right. |
110/2 | 0x0000 | valueArray[48] | Glyph 51 is left-to-right. |
112/2 | 0x0000 | valueArray[49] | Glyph 52 is left-to-right. |
114/2 | 0x0000 | valueArray[50] | Glyph 53 is left-to-right. |
116/2 | 0x0000 | valueArray[51] | Glyph 54 is left-to-right. |
118/2 | 0x0000 | valueArray[52] | Glyph 55 is left-to-right. |
120/2 | 0x0000 | valueArray[53] | Glyph 56 is left-to-right. |
122/2 | 0x0000 | valueArray[54] | Glyph 57 is left-to-right. |
124/2 | 0x0000 | valueArray[55] | Glyph 58 is left-to-right. |
126/2 | 0x0000 | valueArray[56] | Glyph 59 is left-to-right. |
128/2 | 0x0000 | valueArray[57] | Glyph 60 is left-to-right. |
130/2 | 0x0000 | valueArray[58] | Glyph 61 is left-to-right. |
132/2 | 0x120B | valueArray[59] | Glyph 62 is other neutral, and has a bracketing glyph at an offset of +2. |
134/2 | 0x000B | valueArray[60] | Glyph 63 is other neutral. |
136/2 | 0x1E0B | valueArray[61] | Glyph 64 is other neutral, and has a bracketing glyph at an offset of -2. |
138/2 | 0x0000 | valueArray[62] | Glyph 65 is left-to-right. |
140/2 | 0x0000 | valueArray[63] | Glyph 66 is left-to-right. |
142/2 | 0x0000 | valueArray[64] | Glyph 67 is left-to-right. |
144/2 | 0x0000 | valueArray[65] | Glyph 68 is left-to-right. |
146/2 | 0x0000 | valueArray[66] | Glyph 69 is left-to-right. |
148/2 | 0x0000 | valueArray[67] | Glyph 70 is left-to-right. |
150/2 | 0x0000 | valueArray[68] | Glyph 71 is left-to-right. |
152/2 | 0x0000 | valueArray[69] | Glyph 72 is left-to-right. |
154/2 | 0x0000 | valueArray[70] | Glyph 73 is left-to-right. |
156/2 | 0x0000 | valueArray[71] | Glyph 74 is left-to-right. |
158/2 | 0x0000 | valueArray[72] | Glyph 75 is left-to-right. |
160/2 | 0x0000 | valueArray[73] | Glyph 76 is left-to-right. |
162/2 | 0x0000 | valueArray[74] | Glyph 77 is left-to-right. |
164/2 | 0x0000 | valueArray[75] | Glyph 78 is left-to-right. |
166/2 | 0x0000 | valueArray[76] | Glyph 79 is left-to-right. |
168/2 | 0x0000 | valueArray[77] | Glyph 80 is left-to-right. |
170/2 | 0x0000 | valueArray[78] | Glyph 81 is left-to-right. |
172/2 | 0x0000 | valueArray[79] | Glyph 82 is left-to-right. |
174/2 | 0x0000 | valueArray[80] | Glyph 83 is left-to-right. |
176/2 | 0x0000 | valueArray[81] | Glyph 84 is left-to-right. |
178/2 | 0x0000 | valueArray[82] | Glyph 85 is left-to-right. |
180/2 | 0x0000 | valueArray[83] | Glyph 86 is left-to-right. |
182/2 | 0x0000 | valueArray[84] | Glyph 87 is left-to-right. |
184/2 | 0x0000 | valueArray[85] | Glyph 88 is left-to-right. |
186/2 | 0x0000 | valueArray[86] | Glyph 89 is left-to-right. |
188/2 | 0x0000 | valueArray[87] | Glyph 90 is left-to-right. |
190/2 | 0x0000 | valueArray[88] | Glyph 91 is left-to-right. |
192/2 | 0x0000 | valueArray[89] | Glyph 92 is left-to-right. |
194/2 | 0x0000 | valueArray[90] | Glyph 93 is left-to-right. |
196/2 | 0x120B | valueArray[91] | Glyph 94 is other neutral, and has a bracketing glyph at an offset of +2. |
198/2 | 0x000B | valueArray[92] | Glyph 95 is other neutral. |
200/2 | 0x1E0B | valueArray[93] | Glyph 96 is other neutral, and has a bracketing glyph at an offset of -2. |
202/2 | 0x000B | valueArray[94] | Glyph 97 is other neutral. |
Platform-specific Information
CoreText currently derives directionality and related property information from the Unicode properties database. It uses the 'prop'
table when determining bidi mirrored glyphs and, when optical alignment is enabled, hanging glyphs. Support in justification for 'prop'
table floaters may be available in future OS releases.
Dependencies
The 'prop'
table sites glyph indices, which must not exceed the glyph index limits found in the maximum profile table.