1= Graphite Table Format =
2
3:docinfo:
4:numbered:
5
6== Introduction ==
7
8The Graphite font table format is structured in order that a Graphite binary
9description may be incorporated into a TrueType font. Thus the binary format
10uses the TrueType table structure, identically to how it is used in a TrueType
11font. The only difference between using an external file containing Graphite
12binary information in tables, and inserting the binary information into tables
13in the font is that tables are considered local to their file and are considered
14to override those found in the font file. This allows there to be multiple,
15independent descriptions held in separate files. Those independent descriptions
16would have to be merged, in a way described in this document, if they were to be
17held together in the same font file or binary file.
18
19The description consists of a set of table descriptions. The format of a file
20follows that of a TrueType font containing only those tables pertinent to the
21description (i.e. for a separate binary description, those tables listed here).
22
23As is standard for all TrueType tables, the data is in big-endian format
24(most significant byte first).
25
26== Version ==
27
28This file describes version 4.0 of the Graphite font table specification.
29Modifications from previous versions are indicated in the “Version notes” column
30of the various tables.
31
32== Tables ==
33
34This document describes several additional TrueType table types. The “Silf” and
35“Sile” tables are unique to the needs of Graphite, whilst “Gloc” and “Glat”
36provide an extended glyph attribute mechanism. The “Feat” table is based very
37closely on the GX “feat” table. (If necessary the tables could be restructured
38to be stored inside the single “Silf” table.) In addition, use is made of the
39“name” table type.
40
41This version of the Graphite format includes the ability to compress “Glat” and
42“Silf” tables, the extensions to those table provide a compression scheme field
43permitting up to 32 compression schemes. Currently only 2 schemes are defined:
440 – no compression, and 1 – an LZ4 block decompressor. This is not the LZ4
45framing format just the inner block level format without any checksum.
46
47All compressed tables have the same form the original table's 32bit version
48number followed by a 32 bit compression header. This consists of the top 5 bits
49for the scheme and 27 remaining bits for the uncompressed table size. This is
50then followed by the compression scheme's data.
51
52[[comp_table]]
53.Compressed table
54[cols="3,3,8,3",options="unbreakable,header,compact",width="90%",frame="topbot",grid="none"]
55|===============================================================================
56|Type     |Name            |Description                          |Version notes
57
58|FIXED    |version         |Uncompressed Table version number    |
59|ULONG:5  |scheme          |Compression scheme must not be 0     |5.0 – added
60|ULONG:27 |full_size       |Size of uncompressed table           |5.0 – added
61|BYTE[]   |compressed_data |Compression scheme data              |5.0 – added
62|===============================================================================
63
64The uncompressed form is the complete table including the version number but
65with the scheme always set to 0. The remaining 27 bits are available to the
66uncompressed table.
67
68=== Glat ===
69
70The Glat table type is used for storing glyph attributes. Each glyph may be
71considered to have a sparse array of, at the most, 65536 16-bit signed
72attributes. The Glat table is the mechanism by which they are stored.
73
74The Glat table consists of a table header and an array of Glat_entry items. Two
75formats for the Glat table are typically used. Most fonts will use a version 2
76table without Octabox metrics. Those few fonts that have collision avoidance
77support, will use a version 3 table.
78
79.Glat version 2
80[cols="3,3,8,3",options="unbreakable,header,compact",width="90%",frame="topbot",grid="none"]
81|===============================================================================
82|Type         |Name       |Description                          |Version notes
83
84|FIXED        |version    |Table version: 00030000              |4.0 – 00020000
85|Glat_entry[] |entries    |Glyph attribute entries              |
86|===============================================================================
87
88
89.Glat version 3
90[cols="3,3,8,3",options="unbreakable,header,compact",width="90%",frame="topbot",grid="none"]
91|===============================================================================
92|Type            |Name      |Description                        |Version notes
93
94|FIXED           |version   |Table version: 00030000            |5.0 – 00030000
95|ULONG:5         |scheme    |Compression scheme must be 0       |5.0 – added
96|ULONG:28        |reserved  |                                   |5.0 – added
97|ULONG:1         |octaboxes |Octaboxes are present flag         |5.0 – added
98|Glyph_attrs[]   |entries   |Glyph attribute entries            |
99|===============================================================================
100For the compressed layout see <<comp_table>>.
101
102.Glyph_attrs
103[cols="3,3,8,3",options="unbreakable,header,compact",width="90%",frame="topbot",grid="none"]
104|===============================================================================
105|Type            |Name      |Description                         |Version notes
106
107|Octabox_metrics |octabox    |Octabox metrics, only present if
108                              the Glat header indicates          |5.0 – added
109|Glat_entry[]    |entries    |Glyph attribute entries            |
110|========================================================================
111
112If the octaboxes flag is set in the Glat header then for each per glyph block
113of data specified by the Gloc table, first set of data includes metrics that
114approximate the glyph’s curves. The approximation uses “octoboxes”—rectangles
115with corners that may be cut out at an angle of 45 degrees. Each octobox
116requires 8 values to define. There are metrics for the entire glyph and for a
1174x4 approximation grid, resulting in up to 16 sub-boxes. For some glyphs, no
118sub-box data will be present, in which case the bitmap will be zero. Note that
119the rectangle for the full glyph is not included here, as the bounding box
120rectangle is stored elsewhere in the font.
121
122.Octabox_metrics
123[cols="3,3,8,3",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
124|===============================================================================
125|Type           |Name          |Description                      |Version notes
126
127|USHORT         |subbox_bitmap |Which subboxes exist on 4x4 grid; +
128                                bit-index = (y-index*4) + x-index   |
129|BYTE           |diag_neg_min  |Defines min negatively-sloped diagonal (di) |
130|BYTE           |diag_neg_max  |Defines max negatively-sloped diagonal (da) |
131|BYTE           |diag_pos_min  |Defines min positively-sloped diagonal (si) |
132|BYTE           |diag_pos_max  |Defines max positively-sloped diagonal (sa) |
133|Subbox_entry[] |subboxes      |One entry per bit in subbox_bitmap  |
134|===============================================================================
135
136Note that in the subbox bitmap, bit 3 indicates the presence of the lower right
137cell, and bit 12 the upper left cell as per this diagram.
138
139.subbox_bitmap
140[cols=",,,",width="20%",grid="all"]
141|==============
142|12 |13 |14 |15
143| 8 | 9 |10 |11
144| 4 | 5 | 6 | 7
145| 0 | 1 | 2 | 3
146|==============
147
148.Subbox_entry
149[cols="3,3,8,3",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
150|===============================================================================
151|Type |Name         |Description                                  |Version notes
152
153|BYTE |left         |Left of subbox                               |
154|BYTE |right        |Right of subbox                              |
155|BYTE |bottom       |Bottom of subbox                             |
156|BYTE |top          |Top of subbox                                |
157|BYTE |diag_neg_min |Defines min negatively-sloped diagonal (si)  |
158|BYTE |diag_neg_max |Defines max negatively-sloped diagonal (sa)  |
159|BYTE |diag_pos_min |Defines min positively-sloped diagonal (di)  |
160|BYTE |diag_pos_max |Defines max positively-sloped diagonal (da)  |
161|===============================================================================
162
163Following the glyph curve approximation data, the glyph attributes appear. The
164glyph attributes associated with a particular glyph are identified by number and
165value. To conserve space, this storage is run-length encoded. Thus a glyph will
166have a series of Glat_entrys corresponding to each non-contiguous set of
167attributes. The structure of a Glat_entry is:
168
169.Glat_entry, version 2 & 3
170[cols="2,2,8,5",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
171|===============================================================================
172|Type   |Name         |Description                         |Version notes
173
174|USHORT |attNum       |Attribute number of first attribute |4.0 – BYTE to SHORT
175|USHORT |num          |Number of attributes in this run    |4.0 – BYTE to SHORT
176|SHORT  |attributes[] |Array of num attributes             |
177|===============================================================================
178
179Notice that all glyph attributes are 16-bit signed values. If a 32-bit value is
180required, then two attributes should be assigned and joined together by
181the application.
182
183Attribute numbers are application specific.
184
185Note that if the font does not require more than 256 glyph attributes, version 1
186of the Glat table will be generated, which is defined as follows.
187
188.Glat version 1
189[cols="3,3,8,3",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
190|===============================================================================
191|Type         |Name    |Description                              |Version notes
192
193|FIXED        |version |Table version: 00010000                  |
194|Glat_entry[] |entries |Glyph attribute entries                  |
195|===============================================================================
196
197.Glat_entry, version 1
198[cols="3,3,8,3",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
199|===============================================================================
200|Type  |Name         |Description                                |Version notes
201
202|BYTE  |attNum       |Attribute number of first attribute        |
203|BYTE  |num          |Number of attributes in this run           |
204|SHORT |attributes[] |Array of num attributes                    |
205|===============================================================================
206
207=== Gloc ===
208
209The Gloc table is used to index the Glat table. It is structured identically to
210the loca table type, except that it has a header.
211
212TODO: add a field indicating the number of glyphs in the table (the current
213dependence on the Silf table is not architecturally clean).
214
215.Gloc
216[cols="3,3,8,3",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
217|===============================================================================
218|Type         |Name        |Description                          |Version notes
219
220|FIXED        |version     |Table version: 00010000              |
221|USHORT       |flags       |bit 0 = 1 for Long format,
222                                    0 for short format; +
223                            bit 1 = 1 for attribute names,
224                                    0 for stripped               |
225|USHORT       |numAttribs  |Number of attributes                 |
226|USHORT/ULONG |locations[] |Offsets into Glat for each glyph; +
227                            (number of  glyph IDs + 1) of these  |
228
229|USHORT       |attribIds[] |Debug id for each attribute          |
230|===============================================================================
231
232A version 1.1 (0x00010001) table indicates that the Glat table has octabox
233information. But such a version is not required in that case.
234
235The flags entry contains a bit to indicate whether the locations array is of
236type USHORT or ULONG. The locations array is identically structured to that of
237the loca table. There is one entry per glyph and an extra entry to identify the
238length of the final glyph’s attribute entries. Offsets are given to a Glat_entry
239in the Glat table. The second bit indicates whether there is an attribIds array
240at the end of this table. If there is, then it contains name IDs for each
241attribute. If this bit is not set, then there is no array and the table ends
242after the locations array.
243
244As of version 2 of the Silf table, the values of the breakweight attribute are
245interpreted as follows:
246
247....
248BREAK_WHITESPACE = 10
249BREAK_WORD = 15
250BREAK_INTRA = 20
251BREAK_LETTER = 30
252BREAK_CLIP = 40
253....
254
255=== Feat ===
256
257Graphite stores features in a table whose format is very similar to the GX feat
258table. This makes reference to the name table which is use for storing feature
259names and feature value names.
260
261.Feat
262[cols="3,3,8,5",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
263|===============================================================================
264|Type               |Name |Description                           |Version notes
265
266|FIXED              |version        |Table version: 00020001     |
267|USHORT             |numFeat        |Number of features          |
268|USHORT             |reserved       |                            |
269|ULONG              |reserved       |                            |
270|FeatureDefn        |features[]     |Array of numFeat features   |
271|Feature­SettingDefn |featSettings[] |Array of feature setting
272                                     values, indexed by offset   |
273|===============================================================================
274
275.FeatureDefn
276[cols="3,3,8,3",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
277|===============================================================================
278|Type   |Name        |Description                       |Version notes
279
280|ULONG  |id          |Feature ID number                 |2.0 – added
281|USHORT |numSettings |Number of settings                |
282|USHORT |reserved    |                                  |2.0 – inserted
283|ULONG  |offset      |Offset into featSettings list     |
284|USHORT |flags       |                                  |2.1 - reserved to flags
285|USHORT |label       |Index in name table for UI label  |
286|===============================================================================
287
288The flags value has its own bit structure:
289
290.FeatureFlags
291[cols="3,3,8,3",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
292|===============================================================================
293|Bits |Mask   |Description                                       |Version notes
294
295|0    |0x0001 |This feature is an alias of the previous one.     |2.1 - added
296|1-15 |0xFFFE |Reserved                                          |
297|===============================================================================
298
299.FeatureSettingDefn
300[cols="3,3,8,3",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
301|===============================================================================
302|Type   |Name  |Description                                      |Version notes
303
304|SHORT  |value |Feature setting value                            |
305|USHORT |label |Index into name table for UI label               |
306|===============================================================================
307
308=== Silf ===
309
310The “Silf” table will be used for storing rules and actions for the various
311types of tables in a rendering description. The structure of the Silf table is:
312
313.Silf
314[cols="2,3,8,5",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
315|===============================================================================
316|Type     |Name            |Description               |Version notes
317
318|FIXED    |version         |Table version: 00050000   |2.0 – changed to 00020000
319|         |                |                          |3.0 – changed to 00030000
320|         |                |                          |5.0 – changed to 00050000
321|ULONG:5  |scheme          |scheme must be 0          |5.0 – added
322|FIXED:27 |compilerVersion |Compiler version that
323                            generated this font       |3.0 – added +
324                                                       5.0 – changed to 27 bits
325|USHORT   |numSub          |Number of SIL subtables   |
326|USHORT   |reserved        |                          |
327|ULONG    |offset[]        |Array of numSub offsets to
328                            the subtables relative to
329                            the start of this table   |
330|SIL_Sub  |tables[]        |Array of independent
331                            rendering description
332                            subtables                 |
333|===============================================================================
334For the compressed layout see <<comp_table>>. Since one TrueType file may hold
335multiple independent rendering descriptions, each rendering description is
336described in a subtable. The subtable contains all that is necessary to describe
337the rendering of one set of writing systems.
338
339.SIL_Sub
340[cols="4,6,28,7",options="header",frame="topbot",grid="none"]
341|===============================================================================
342|Type      |Name               |Description                     |Version notes
343
344|FIXED     |ruleVersion        |Stack-machine language version  |3.0 – added
345|USHORT    |passOffset         |offset of oPasses[0] relative to
346                                start of sub-table              |3.0 – added
347|USHORT    |pseudosOffset      |offset of pMaps[0] relative to
348                                start of sub-table              |3.0 – added
349|USHORT    |maxGlyphID         |Maximum valid glyph ID (including
350                                line-break & pseudo-glyphs)     |
351|SHORT     |extraAscent        |Em-units to be added to the
352                                font’s ascent                   |
353|SHORT     |extraDescent       |Em-units to be added to the
354                                font’s descent                  |
355|BYTE      |numPasses          |Number of rendering description
356                                passes                          |
357|BYTE      |iSubst             |Index of 1st substitution pass  |
358|BYTE      |iPos               |Index of 1st Positioning pass   |
359|BYTE      |iJust              |Index of 1st Justification pass |
360|BYTE      |iBidi              |Index of 1st pass after the
361                                bidi pass(must be <= iPos); +
362                                0xFF implies no bidi pass       |
363|BYTE      |flags              |0   - has line end contextuals, +
364                                1   - contextuals, +
365                                2-4 - space contextuals, +
366                                5 - has collision pass          |4.0 – add Bit 1
367|BYTE      |maxPreContext      |Max range for preceding
368                                cross-line-boundary contextualization |
369|BYTE      |maxPostContext     |Max range for following
370                                cross-line-boundary contextualization |
371|BYTE      |attrPsuedo         |Glyph attribute number that is
372                                used for actual glyph ID for a
373                                pseudo-glyph                    |
374|BYTE      |attrBreakWeight    |Glyph attribute number of
375                                breakweight attribute           |
376|BYTE      |attrDirectionality |Glyph attribute number for
377                                directionality attribute        |
378|BYTE      |attrMirroring      |Glyph attribute number for
379                                mirror.glyph (mirror.isEncoded
380                                directly after)                 |2.0 – added; +
381                                                                 4.0 – used
382|BYTE      |attrSkipPasses     |Glyph attribute of bitmap
383                                indicating key glyphs for pass
384                                optimization                    |2.0 – added; +
385                                                                 4.0 – used
386|BYTE      |numJLevels         |Number of justification levels;+
387                                0 if no justification           |2.0 – added
388|JestLevel |jLevels[]          |Justification information for
389                                each level.                     |2.0 – added
390|USHORT    |numLigComp         |Number of initial glyph
391                                attributes that represent
392                                ligature components             |
393|BYTE      |numUserDefn        |Number of user-defined slot
394                                attributes                      |
395|BYTE      |maxCompPerLig      |Maximum number of components per
396                                ligature                        |
397|BYTE      |direction          |Supported direction(s)          |
398|BYTE      |attCollisions      |First of a set of attributes
399                                that hold collision flags and
400                                constraint box                  | 5.0 - used
401|BYTE      |reserved           |                                |
402|BYTE      |reserved           |                                |
403|BYTE      |reserved           |                                |2.0 – added
404|BYTE      |numCritFeatures    |Number of critical features     |2.0 – added
405|USHORT    |critFeatures[]     |Array of critical features      |2.0 – added
406|BYTE      |reserved           |                                |2.0 – added
407|BYTE      |numScriptTag       |Number of scripts in scriptTag  |
408|ULONG     |scriptTag[]        |Array of script tags            |
409|USHORT    |lbGID              |Glyph ID for line-break
410                                psuedo-glyph                    |
411|ULONG     |oPasses[]          |Offets to passes relative to the
412                                start of this subtable; +
413                                numPasses + 1 of these          |
414|USHORT    |numPseudo          |Number of Unicode ->
415                                pseudo-glyph mappings           |
416|USHORT    |searchPseudo       |(max power of 2 <= numPseudo)
417                                * sizeof(PseudoMap) [Deprecated]|
418|USHORT    |pseudoSelector     |log2(max power of 2<= numPseudo)
419                                [Deprecated]                    |
420|USHORT    |pseudoShift        |numPseudo - searchPseudo
421                                [Deprecated]                    |
422|PseudoMap |pMaps[]            |Unicode ->pseudo-glyph mappings
423                                in Unicode order                |
424|ClassMap  |classes            |Classes map storing replacement
425                                classes used in actions         |
426|SIL_Pass  |passes[]]          |Array of passes                 |
427|===============================================================================
428
429Deprecated values will not be removed from the structure, but their meaning is
430lost, they become reserved values that will not be reassigned. Each
431justification level has several glyph attributes associated with it.
432
433Notice that reserved values do not have to be 0. In addition, some values that were
434transitioned from reserved to having a meaning, may also be used in Silf tables
435whose version number is lower than the version in which the meaning was introduced.
436
437This structure was new as of version 2.0.
438
439.JustificationLevel
440[cols="3,3,8,3",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
441|===============================================================================
442|Type |Name        |Description                                  |Version notes
443
444|BYTE |attrStretch |Glyph attribute number for justify.X.stretch |
445|BYTE |attrShrink  |Glyph attribute number for justify.X.shrink  |
446|BYTE |attrStep    |Glyph attribute number for justify.X.step    |
447|BYTE |attrWeight  |Glyph attribute number for justify.X.weight  |
448|BYTE |runto       |Which level starts the next stage            |
449|BYTE |reserved    |                                             |
450|BYTE |reserved    |                                             |
451|BYTE |reserved    |                                             |
452|===============================================================================
453
454A pseudo-glyph is a glyph which contains no font metrics (it has a GID greater
455than the numGlyphs entry in the maxp table) but is used in the rendering
456process. Each pseudo-glyph has an attribute which is the glyph ID of a real
457glyph which will be used to actually render the glyph. The pseudo-glyph map
458contains a mapping between Unicode and pseudo-glyph number:
459
460.PseudoMap
461[cols="3,3,8,3",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
462|===============================================================================
463|Type   |Name    |Description               |Version notes
464
465|ULONG  |unicode |Unicode codepoint         |2.0 – changed from USHORT to ULONG
466|USHORT |nPseudo |Glyph ID of pseudo-glyph  |
467|===============================================================================
468
469The ClassMap stores the replacement class information for the passes in this
470description. Replacement classes are used during substitution where a glyph id
471is looked up in one class and the glyph ID at the corresponding index in another
472class is substituted. The difficulty with the storage of such classes is in
473looking up a glyph ID in an arbitrarily ordered list. One approach is to use a
474linear search; this is very slow, but is stored very simply. Another approach is
475to order the glyphs in the class and to store the index against the glyph. Both
476approaches are supported in the ClassMap table structure:
477
478.ClassMap
479[cols="3,3,8,3",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
480|===============================================================================
481|Type        |Name      |Description                   |Version notes
482
483|USHORT      |numClass  |Number of replacement classes |
484|USHORT      |numLinear |Number of linearly stored
485                         replacement classes           |
486|ULONG       |oClass[]  |Array of numClass + 1 offsets
487                        to class arrays from the
488                        beginning of the class map     | 4.0 changed from USHORT
489|USHORT      |glyphs[]  |Glyphs for linear classes     |
490|LookupClass |lookups[] |An array of numClass –
491                        numLinear lookups              |
492|===============================================================================
493
494The LookupClass stores a fast lookup association between glyph ID and index.
495Each lookup consists of an ordered list of glyph IDs with the corresponding
496index for that glyph. The number of elements in the lookup is specified by
497numIds along with a search Range and shift to initialize a fast binary search
498engine:
499
500.LookupClass
501[cols="3,3,8,3",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
502|===============================================================================
503|Type       |Name          |Description                          |Version notes
504
505|USHORT     |numIDs        |Number of elements in the lookup     |
506|USHORT     |searchRange   |(max power of 2<= numIDs)            |
507|USHORT     |entrySelector |log2(max power of 2<= numIDs)        |
508|USHORT     |rangeShift    |numIds – searchRange                 |
509|LookupPair |lookups[]     |lookups; there are numIDs of these   |
510|===============================================================================
511
512Each element in the lookup consists of a glyphId and the corresponding index in
513the original ordered list.
514
515.LookupPair
516[cols="3,3,8,3",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
517|===============================================================================
518|Type   |Name    |Description                                    |Version notes
519
520|USHORT |glyphId |glyph id to be compared                        |
521|USHORT |index   |index corresponding to glyphId in ordered list |
522|===============================================================================
523
524=== Pass ===
525
526Each processing pass consists of a finite state machine description for rule
527finding, and the actions that are executed when a rule is matched.
528
529.SIL_Pass
530[cols="5,9,34,8",options="header",frame="topbot",grid="none"]
531|===============================================================================
532|Type |Name |Description                                     |Version notes
533
534|BYTE       |flags             |0-2 - number of collision runs; +
535                                3-4 - kerning collisions; +
536                                5 - reverse direction pass   |5.0 - add bits 0-5
537|BYTE       |maxRuleLoop       |MaxRuleLoop for this pass    |
538|BYTE       |maxRuleContext    |Number of slots of input
539                                needed to run this pass      |
540|BYTE       |maxBackup         |Maximum number of slots this
541                                pass is allowed to back up)  |
542|USHORT     |numRules          |Number of action code blocks |
543|USHORT     |fsmOffset         |offset to numRows relative to
544                                the beginning of the SIL_Pass
545                                block                        |2.0 - added; +
546                                                              3.0 - used
547|ULONG      |pcCode            |Offset to pass constraint
548                                code from start of subtable
549                                (*passConstraints[0]*)       |2.0 - added
550|ULONG      |rcCode            |Offset to rule constraint
551                                code from start of subtable
552                                (*ruleConstraints[0]*)       |
553|ULONG      |aCode             |Offset to action code from
554                                start of subtable
555                                (*actions[0]*)               |
556|ULONG      |oDebug            |Offset to debug arrays
557                                (*dActions[0]*); +
558                                0 if debug stripped          |
559|USHORT     |numRows           |Number of FSM states         |
560|USHORT     |numTransitional   |Number of transitional states
561                                in the FSM (length of
562                                *states* matrix)             |
563|USHORT     |numSuccess        |Number of success states in
564                                the FSM (size of *oRuleMap*
565                                array)                       |
566|USHORT     |numColumns        |Number of FSM columns        |
567|USHORT     |numRange          |Number of contiguous glyph ID
568                                ranges which map to columns  |
569|USHORT     |searchRange       |(maxi power of 2 <= numRange)
570                                *sizeof(Pass_Range)[Deprecated]|
571|USHORT     |entrySelector     |log2(maximum power of 2
572                                <= numRange) [Deprecated]    |
573|USHORT     |rangeShift        |numRange*sizeof(Pass_Range)
574                                - searchRange [Deprecated]   |
575|Pass_Range |ranges[]          |Ranges of glyph IDs in this FSM; +
576                                *numRange* of these |
577|USHORT     |oRuleMap[]        |Maps from success state to offset into ruleMap
578                                array from start of array. 1st item corresponds
579                                to state # (numRows – numSuccess);
580                                ie, non-success states are omitted.
581                                [0xFFFF implies rule number is equal to state
582                                number (no entry in ruleMap) – NOT IMPLEMENTED].
583                                There are (numSuccess + 1) entries. |
584|USHORT     |ruleMap[]         |Linear arrays of rule numbers
585                                maping to a success state number |
586|BYTE       |minRulePreContext |Min number of items in any rule
587                                context before 1st modified rule item |
588|BYTE       |maxRulePreContext |Max number of items in any rule
589                                context before 1st modified rule item |
590|USHORT     |startStates[]     |Array of size (maxRulePreContext
591                                - minRulePreContext + 1), indicating the start
592                                state in the state machine based on how many
593                                pre-context items a rule has |
594|USHORT     |ruleSortKeys[]    |Array of *numRules* sort keys,
595                                indicating precedence of rules |
596|BYTE       |rulePreContext[]  |Array of *numRules* items indicating
597                                the number of items in the context
598                                before the 1st modified item,
599                                one for each rule            |
600|BYTE       |collisionThreshold|                             |2.0 - inserted, +
601                                                              5.0 – used
602|USHORT     |pConstraint       |passConstraint block length  |2.0 – added
603|USHORT     |oConstraints[]    |numRules + 1 offsets to constraint code blocks
604                                from start of ruleConstraints. |
605|USHORT     |oActions[]        |numRules + 1 offsets to action code blocks
606                                from start of actions.       |
607|USHORT     |stateTrans[][]    |Array of *numTransitional* rows of *numColumns*
608                                state transitions.           |
609|BYTE       |reserved          |                             |2.0 – inserted
610|BYTE       |passConstraints[] |Sequences of constraint code
611                                for pass-level constraints   |2.0 – added
612|BYTE       |ruleConstraints[] |Sequences of constraint code
613                                for rules                    |
614|BYTE       |actions[]         |Sequences of action code     |
615|footnote:[ Should debug tables go at the end, and be
616            marked via a flag as per Gloc?
617]USHORT     |dActions[]        |Name index for each action for
618                                documentation purposes. +
619                                0 = stripped. length numRules |
620|USHORT     |dStates[]         |Name index for each intermediate
621                                FSM row/state for debugging. +
622                                0 = stripped.
623                                Corresponds to the
624                                last numRows – numRules      |
625|USHORT     |dCols[]           |Name index for each state
626                                (length numRows)             |
627|===============================================================================
628
629Deprecated values will not be removed from the structure, but their meaning is
630lost, they become reserved values that will not be reassigned.
631
632Notice that the ranges array has fast lookup information on the front to allow
633for the quick identification of which range a particular glyph id is in. Each
634range consists of the first and last glyph id in the range.
635
636.Pass_Range
637[cols="3,3,8",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
638|===============================================================================
639|Type   |Name    |Description
640
641|USHORT |firstId |First Glyph id in the range
642|USHORT |lastId  |Last Glyph id in the range
643|USHORT |colId   |Column index for this range
644|===============================================================================
645
646==== Pass Contents ====
647
648A pass contains a Finite State Machine (FSM) which is used to match input
649strings to rules. It also contains constraints for further testing whether a
650matched string should fire, and it contains the action code to execute against
651the matched string.
652
653The FSM consists of a set of states. A state consists of a row of transitions
654between that state and another state dependent upon the next glyph in the input
655stream. Each state may be an acceptance state, in which case it corresponds to a
656rule match, or a transition state, in which case the state is on the way to
657matching a rule, or both. A null state transition is one in which the occurrence
658of this particular class of the following glyph, will result in no extension of
659a rule match anywhere, just fail on all further searching. A final state is one
660in which all its transitions are null transitions.
661
662Note that the stateTrans array only needs to represent transitional states, not
663final states. Similarly, the oRuleMap array only needs entries for acceptance
664states (whether final or transitional). For this reason the FSM is set up
665(conceptually) in the following order: transitional non-accepting states first,
666followed by transitional accepting states, followed by final (accepting) states.
667
668Note also that because there may be more than one matched rule for a given state,
669oRuleMap indicates a list of rule indices in the ruleMap array;
670oRuleMap[i+1] - oRuleMap[i] indicates how many there are for state i.
671
672Normally the start state for an FSM is zero. But for each pass there is the idea
673of a “pre-context,” that is, there are slots that need to be taken into
674consideration in the rule-matching process that are before the current position
675of the input stream. If we are very near the beginning of the input, we may need
676to adjust by skipping some states, which corresponds to skipping the
677“pre-context” slots that not present due to being prior to the beginning of the
678input.  This is what the maxRulePreContext, minRulePreContext, and startStates
679items are used for. Specifically, we need to skip the number of transitions
680equal to the difference between the maxRulePreContext and the current stream
681position, if greater than zero. The startStates array indicates what the
682adjusted start state should be. If the current input position is less than
683minRulePreContext, no rule will match at all.
684
685Rules are matched in order of length, so that longest rules are given precedence
686over shorter rules. However, the length of some rules may have been adjusted to
687allow for a consistent “pre-context” for all rules, so the number of matched
688states in the FSM may not correspond to the actual number of matched items in
689the rule. For this reason, it is not adequate to simply order rules based on the
690number of traversed states in the FSM. Rather, rules are given sort keys
691indicating their precedence, which is based primarily on the length of the rule
692and secondarily on its original position within the source code.
693
694The FSM engine keeps track of all the acceptance states it passes through on its
695path to a final state. This results in a list of rules matched by the string
696sorted by precedence. The engine takes the first rule index off the list and
697looks up the offset to some constraint code. This code is executed and if the
698constraint passes, then the action code associated with that offset is executed
699and the FSM restarts at the returned slot position. If the constraint fails,
700then the FSM considers the next-preferred rule, tests that constraint, and so
701forth. If no accepting state is found or all rules fail their constraints, then
702no rule applies, in which case a single glyph is put into the output stream and
703the current position advances by one slot.
704
705The action strings are simply byte strings of actions, much like hinting code,
706but using a completely different language. (See “Stack Machine Commands.doc”.)
707
708=== Sile ===
709
710This table is used in Graphite table files that rely on an external font for
711rendering of the glyphs. When this table is present, the Graphite file is in
712effect a minimal font that contains information about the actual font to use in
713rendering. This information is stored in the Sile table.
714
715This table was added as of version 2. It is not currently being used.
716
717.Sile
718[cols="3,3,8",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
719|===============================================================================
720|Type   |Name           |Description
721
722|FIXED  |version        |Table version: 00010000
723|ULONG  |checksum       |master checksum (checkSumAdjustment) from the head
724                         table of the base font
725|ULONG  |createTime[2]  |Create time of the base font (64-bits)
726                         from the head table
727|ULONG  |modifyTime[2]  |Modify time of the base font (64-bits)
728                         from the headtable
729|USHORT |fontNameLength |Number of characters in fontName
730|USHORT |fontName[]     |Family name of base font
731|USHORT |fontFileLength |Number of characters in baseFile
732|USHORT |baseFile[]     |Original path and name of base font file
733|===============================================================================
734
735There are four possible situations with regard to the Sile table. The first two
736are considered normal and the second two pathological.
737
738No Sile table is present. In this case, it is assumed that the Graphite table
739file is a normal font containing not only the Graphite tables but also the
740glyphs and metrics needed for rendering.
741
742The base font named in the Sile table is present on the system, and its master
743checksum and dates match those in the Sile table. In this case, the Graphite
744tables are read from the Graphite table file, but the glyphs, metrics, and cmap
745from the base font are what are used for rendering (with the modification
746performed by the Graphite tables).
747
748The base font named in the Sile table is present, but its master checksum and/or
749dates do not match those in the Sile table. In this case the base font is used
750to perform the rendering, but with no Graphite behaviors.
751
752The base font named in the Sile table is not present on the system. In this case
753the Graphite table file is used for the rendering, with no Graphite behaviors,
754resulting in square boxes in place of the expected glyphs.
755
756=== Sill ===
757
758This table maps ISO-639-3 language codes onto feature values. Each language code
759can be a maxmum of 4 ASCII characters (although 2 or 3 characters is what is
760used by the ISO standard).
761
762This table was added as of version 3.
763
764.Sill
765[cols="4,3,8,3",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
766|===============================================================================
767|Type               |Name          |Description                  |Version notes
768
769|FIXED              |version       |Table version: 00010000      |
770|USHORT             |numLangs      |Number of languages supported|
771|USHORT             |searchRange   |(max power of 2 <= numLangs)
772                                    [Deprecated]                 |
773|USHORT             |entrySelector |log2(max power of
774                                    2 <= numLangs) [Deprecated]  |
775|USHORT             |rangeShift    |numLangs-searchRange
776                                    [Deprecated]                 |
777|LanguageEntry      |entries[]     |Languages and pointers to
778                                    feature settings; +
779                                    numLang + 1 length           |
780|LangFeatureSetting |settings[]    |Feature ID / value pairs     |
781|===============================================================================
782
783Each language entry contains a 4-character language code and an offset to the
784list of features. There is one bogus entry at the end that facilitates finding
785the size of the last entry. The offsets are relative to the beginning of the
786Sill table.
787
788The language code is left-aligned with any unused characters padded with NULLs.
789For instance, the code “en” is represented by the four bytes [101, 110, 0, 0].
790
791.LanguageEntry
792[cols="3,3,8,3",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
793|===============================================================================
794|Type   |Name        |Description                                |Version notes
795
796|BYTE   |langcode[4] |4-char ISO-639-3 language code             |
797|USHORT |numSettings |Number of feature settings of language     |
798|USHORT |offset      |Offset to 1st feature setting of language  |
799|===============================================================================
800
801.LangFeatureSetting
802[cols="3,3,8,3",options="unbreakable,header",width="90%",frame="topbot",grid="none"]
803|===============================================================================
804|Type   |Name      |Description                                  |Version notes
805
806|ULONG  |featureId |Feature identifer number (matches ID in
807                    Feat table)                                  |
808|SHORT  |value     |Default feature value for this language      |
809|USHORT |reserved  |Pad bytes                                    |
810|===============================================================================
811
812=== Sild ===
813
814This table holds the debug strings for debugging purposes. Since the strings are
815only used for debugging, they are held somewhat optimised for space over speed
816and are not considered to be multilingual. Thus strings are considered to be
8177-bit ASCII, with a possible extension to UTF-8 at a later stage. The table
818consists of a sequence of strings each preceded by a length byte. The first
819string is id 0 and so on to the end of the table.
820
821NOTE: this table has not been implemented.
822
823== Multiple Descriptions ==
824
825In the case where multiple descriptions are to be stored in the same set of
826tables, the following unifications need to occur:
827
828The feature sets must be unified, thus limiting two features with the same name
829to having the same settings and corresponding values.
830
831The glyph attributes must be unified. This can be done by using different
832attribute number ranges, or by examining for identical attribute mappings or for
833non-intersecting attribute mappings.
834
835The use of the name table must be unified to ensure that two features or feature
836settings do not refer to the same entry in the name table.
837
838Notice that the requirement that any tables declared in an external binary
839description override the corresponding font table in the font, means that a name
840table in an external binary description must be complete, including all the
841strings from the original font.
842
843include::OpCodes.txt[]
844