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|FeatureSettingDefn |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