What does a subtable in GSUB exactly represent?

LexLuengas's picture

For which reason and when are 'subtables' created? Adobe's OpenType Feature File Specification does not help me any further understanding the structure of GPOS/GSUB.

Theunis de Jong's picture

The first match in a subtable is processed, then the rest of this subtable is skipped.
.. can't find a good example right now ..

LexLuengas's picture

Really? Nothing? Is it a more complicated question, or does in fact no one have the faintest idea? :'-(

Karl Stange's picture

Unfortunately I do not have first hand knowledge of GSUB tables, but you may find these links useful:

The Microsoft Typography overview of TrueType in Windows 95 includes the following:

The GSUB and GPOS tables define glyph substitution and positioning features. GSUB supplies five types of substitutions to support different kinds of character-to-glyph mappings, such as many-to-one ligature glyph substitution and one-to-many ligature decomposition.

You may also find the information on the FontForge site useful:

http://fontforge.org/gposgsub.html

This also refers to the following page on Adobe's website:

http://partners.adobe.com/public/developer/opentype/index_table_formats1...

Theunis de Jong's picture

Really? Nothing?

Uh, you got an answer, dintya?

Anyway, here is the promised example: 'frac' -- based on Tal Leming's Fraction Fever discussion.

feature frac {
sub @figures slash' @figures by fraction;
sub @figures' fraction by @numerators;
}

The class '@figures' contains 'zero one two .. nine', and the first line will replace a simple default slash, preceded by a figure, with a proper 'fraction' slash. After that, individual figures should be replaced with superior/inferior forms, to create proper fractions.
It will work as expected if you manually inserted a fraction slash (and the first line will not be used). However, because all sub-tables are terminated a.s.a.p., this code will stop if the first line was executed! So in this case you have to force a sub-table below the first line to make sure the second line is evaluated as well.

Tal Leming's code doesn't specifically mention a sub-table, but I think standard behavior for feature compilers is to automatically create them when deemed necessary. In my example, the first line contains a 'fraction' on the right side of a substitution (target) and the second line on the left side (source), so to be able to process both rules, the compiler creates a sub-table at the second line.

Theunis de Jong's picture

Another application is the 'ignore' rule, which is not really a feature file keyword. It works like this: every "ignore" rule and its "when not ignored" counterpart appear in a sub-table of their own.

ignore [a e m n r u]' [ @alpha ];
subst [a e m n r u]' by [a.end e.end m.end n.end r.end u.en];

This is meant to replace 'a', 'e', etc. with a swashed 'end' form, but of course not if another alphabetic character follows. So the first line is internally compiled to

subst [a e m n r u]' [ @alpha ] by [a e m n r u];

(i.e., it does "nothing"), and if this line gets executed, the next line is skipped. This particular sub-table must end after the next line, because there might be other lines that should be evaluated for the rest of the characters.

LexLuengas's picture

Thank's Karl and Theunis, that were the elaborate answers I was hoping for!

subst [a e m n r u]' [ @alpha ] by [a e m n r u];
(i.e., it does "nothing")

This is really enlightening. I've been using the ‘ignore’ keyword a few times and wasn't able to deduce such an evident fact.

(...) standard behavior for (feature) compilers is to automatically create them when deemed necessary.

I realize my problems to understand OpenType's syntax mostly arise from the fact that the compiler generates subtables behind the scenes.

Another issue is that the ‘subtable’ command is only supported for class kerning, so one must set up an entirely new lookup to avoid line ‘skipping’. I wonder why it hasn't been implemented yet...

One thing that has clarified many of my doubts, re-reading Adobe's OpenType Feature File Specification, is the following part about chaining contextual substitution:

The entire sequence of glyphs – prefix plus input plus suffix – must match in the current context for the rule to be applied. The match sequence is aligned to the current context by aligning the first glyph of the input sequence with the current glyph of the text being processed. If the rule is matched, then the current context moves the current glyph pointer ahead in the original text by the length of the input sequence. Note that in the FDK syntax, the entire context string (backtrack sequence + input sequence + look-ahead sequence) are all written in the text string order. This is worth emphasis, as inside the lookup rule, the glyphs of the backtrack sequence are written in reverse order from the text to be matched.

I've emphasized the mind-blowing parts.

Theunis de Jong's picture

Possible further mind blowing-yet-enlightening may occur if you inspect a few ligature sets. I'd have to go through my font library to find a good example, but I think the text you copied from the specs also apply to sequences of "ff", "ffi", and "ffl" ligatures -- i.e., put them in the wrong order and/or without subtables, and some combo's will not work.
Perhaps one of the OT-savvy techies can recall an appropriate thread from the past where one has to resort to manually inserting a 'subtable' clause in a GSUB feature.

A propos: I am assuming OTF compilers automatically generate subtables for GSUB features, because I can't find a concrete reference to them as well (or these references are very oblique), and the fonts I have are positively brimming with them.

Syndicate content Syndicate content