What is this problem?

Hello. I hope you are having a good week. Friends, I encountered such an error in FontLab. I can't find any reason. Maybe your have an idea?

FEA compiler error: [F] In feature 'kern' lookup 'KERN_LTR' positioning rules cause an offset overflow (0x10094) to a lookup subtable
FEA compiler error: [F] Fatal error in font "font" in file "features" at line 13242
Features compilation failed. Trying without the [kern] feature

Comments

  • Thomas Phinney
    Thomas Phinney Posts: 2,888
    edited March 19
    So, there is a limit on the size of lookup subtables in features in the compiled OpenType font.

    You can use an "extension" lookup to work around this. Or split your kerning into explicit separate lookups. Or, rework your kerning classes to have fewer of them.

    What version of FontLab are you using btw? IIRC the newer versions will automatically invoke extension lookups when appropriate.
  • Nick Shinn
    Nick Shinn Posts: 2,209
    You can fix this by putting every kerned glyph in a class.
    Thus, even if one character has only one kern (most likely X), make a kerning class for it!
  • So, there is a limit on the size of lookup subtables in features in the compiled OpenType font.

    You can use an "extension" lookup to work around this. Or split your kerning into explicit separate lookups. Or, rework your kerning classes to have fewer of them.

    What version of FontLab are you using btw? IIRC the newer versions will automatically invoke extension lookups when appropriate.
    @Thomas Phinney  It is the latest version of FontLab. This problem occurred after playing with Axis. Even if I reset it, it didn't fix it. By the way, written here 13242 lines are missing in features.
  • Grzegorz Luk (gluk)
    Grzegorz Luk (gluk) Posts: 161
    edited March 20
    With kerning by classes it's hard for me to imagine exceeding table limit (65536 bytes).
    I checked my font and class kerning with 40 classes × 40 classes (the largest class is about 70 glyphs) takes ~5600 bytes.
    Unless you are using kerning pairs, then you can easily check if you have over 10000 pairs.
  • Yves Michel
    Yves Michel Posts: 182
    Why don't you try Fontlab 8 forum (https://forum.fontlab.com/fontlab-8/) to expose your problem. The staff is eager to answer and, after all, they are the authors of the software.
  • @Yves Michel
      I thought exactly as you said. I thought there would be a faster solution here. In the meantime, I solved the problem.

  • Thomas Phinney
    Thomas Phinney Posts: 2,888
    it would be good to share the specific cause/solution, seeing as you posted the problem here!   :D
  • Nick Shinn
    Nick Shinn Posts: 2,209
    I would appreciate it if those who disagreed with my previous comment (or someone else) would explain why, as this is a practice that has worked for me, in removing kerning subtables, so far…
  • John Hudson
    John Hudson Posts: 3,204
    edited March 22
    Hi Nick. I wasn’t one of the people who clicked Disagree with your post, but I can explain why the method you describe might not always work.

    A typical GPOS kerning structure at the table level consists of a series of subtable lookups:
    • glyph to glyph
    • glyph to class
    • class to glyph
    • class to class
    Subtable lookups are processed by OTL engines in sequence until a matching input is found, the positioning is applied, and then the remainder of the subtable lookups are skipped. This is what enables the glyph-to-glyph and glyph-to-mark—and vice versa—to be processed as exceptions that override the class-to-class kerning: they are processed first and then the subsequent kerning subtable lookups are skipped.

    When any of those subtable lookups overruns the max size, it needs to be split into further subtables. So, for example, one might need something like
    • glyph to glyph 1
    • glyph to glyph 2
    • glyph to class
    • class to glyph
    • class to class
    if the glyph-to-glyph kerning exceeds the max subtable size.

    What you are doing when you assign a single glyph to a class as you describe is moving the kerning associated with that glyph out of the glyph-to-glyph kerning subtable, and putting it into the subsequent glyph-to-class, class-to-glyph, and class-to-class subtables. And in many cases that may indeed avoid maxing out the size of the glyph-to-glyph subtable, and the subtable lookups involving classes will always tend to be smaller than glyph-to-glyph subtables, which explains why you’ve had success with this method.

    But any of those typical GPOS kerning subtable lookups can overrun the max size, given a large enough font, complex enough shapes, and sufficient quantity of classes. This is more likely in kerning some scripts than others.

    So I would say your mechanism is a valid one in many cases—and has the benefit of readying the kerning source for future additional glyphs that might be added to those single-glyph classes—, but isn’t guaranteed to avoid the subtable overrun problem.
  • Correct me if I am wrong, but I cannot rule out that in these types of exchanges two things are sometimes intertwined: on the one hand, what the specs describe and on the other hand, how one can handle a problem in a specific font tool. Font tools often make things easy for the end user, but it may not always be completely clear what is happening under the hood. Solutions may therefore be more of a way to circumvent the problems that arise in a particular case. In the case of DTL we use separate files for GDEF, GSUB, and GPOS features that are invoked and possibly subsetted when compiling fonts. That may be a bit more primitive, but we are used to this. To generate kerning we use our own KernMaster and GPOSMaster (see image) tools and I automated the (batch) adjusting, filtering, and ordering of the kerning pairs. My experience with the latter is similar to what John writes.

    DTL GPOSMaster

    The separation into subtables is described in the OpenType specs. As John mentioned, there are in principle four possible formats for kerning-pairs definitions:

          <single> <single>
          <single> <class>
          <class> <single>
          <class> <class>

    Each subtable may contain only one of these formats. For example, if alphabetical sorting mixes the <single> <single> and <single> <class> entries, the subtable is broken, i.e., the spacing does not work if the type of entry differs from that of the beginning of the subtable. The compiler may also attempt to split into subtables without regard to the logic of the groups, breaking the kerning. The number of subtables does not seem to matter much, but the specifications state that many subtables increase the font-file size. A possible approach is:

    • lookup;
          <single> <single>
    – subtable;
          <single> <class>
    – subtable;
          <class> <single>
    • lookup;
          <class> <class>

    and subsequently to separate each character (including UC, LC, SC) into subtables, for example:

          @A_UC @A_UC <0 0 0 0>;
          @A_LC @A_LC <0 0 0 0>;
          @A_SC @A_SC <0 0 0 0>;
    – subtable;
          @B_UC @B_UC <0 0 0 0>;
          @B_LC @B_LC <0 0 0 0>;
          @B_SC @B_SC <0 0 0 0>;
    – subtable;
          @C_UC @C_UC <0 0 0 0>;
          @C_LC @C_LC <0 0 0 0>;
          @C_SC @C_SC <0 0 0 0>;
          etc.

    The pairs <single> <single>, <single> <class>, <class> <single> must be compiled first. This makes sense if one uses enumeration pairs, that is, exceptions to the class definitions. In theory, the <single> <single>, <single> <class> and <class> <single> pairs do not need to be ‘physically’ placed on top. If there is a lookup format, the order of the lookups in the features file will determine the order of processing by the compiler, of course. Empirically I found that separating the <single> <single>/<single> <class>/<class> <single> definitions from the <class> <class> definitions by defining two lookups makes everything work fine.

    By the way, DTL OTMaster can be used to debug kern-features files as it provides a detailed log file.
  • John Hudson
    John Hudson Posts: 3,204
    My workflow is similar to Franks, but substituting FontLab for KernMaster and VOLT for the .fea GPOS syntax. The FontLab-to-VOLT link is via our vfj-to-volt tool, which automatically writes the separate subtabke lookups for kern types and can also split subtables by size.
  • k.l.
    k.l. Posts: 109
    @Tural Alisoy, @Yves Michel gave the right advice – ask on the Fontlab Forum and, upon request, ideally provide the font for testing too. This error should not happen and needs to be addressed right in the application. (Splitting subtables is something that Fontlab should do, exactly so users do not need to even bother.)
  • Tural Alisoy
    Tural Alisoy Posts: 51
    edited March 24
    @Thomas Phinney
     finally, I deleted everything and regrouped. I noticed, I had errors too.
  • k.l.
    k.l. Posts: 109
    (@John Hudson vfj-to-volt splits subtables not ‘by size’ but ‘by count’. Quite a difference in approach and, hence, result.)
  • John Hudson
    John Hudson Posts: 3,204
    Yes. It’s an explicit pair count split, rather than calculating size. I needed it as a quick solution for a specific project with massive kerning data, and that was the quickest way to implement it. It is possible to get close to a size calculation if one is familiar with the kerning data and can estimate the number of pairs that will max out the subtable size.