Skip to content

Commit

Permalink
tottfgpos: Fix occasional fail to create lookups
Browse files Browse the repository at this point in the history
[why]
Sometimes, especially when generating fonts with a lot ligatures,
fontforge can not create the font file correctly. A typical error
message looks like this:

  Attempt to output 68142 into a 16-bit field.
  It will be truncated and the file may not be useful.

This will already happen when the font is opened and generated without
any change. But the generated font must contain the lookups of course.

[how]
When the lookup tables are written we need to check if the indices can
be represented by 16 bit values. Big tables will often be longer.

In the file first is comes the lookups table that points to all lookups.
Then follow the lookups themselves.

When a lookup would violate the 16 bit boundary we need a different and
longer (!) entry in the lookups table, so all lookups will be shifted.
For this reason the function
  tottfgpos.c:g___FigureExtensionSubTables()
does this calculation recursively. Increasing the size of the lookups
table step by step for each lookup, and then checking the previous
lookups again (because they shifted).

Unfortunately the check if the 16 bit boundary would be violated does
not take the grown lookups table into account. Under some circumstances
this means that a lookup, that fittet just-so before is now shifted
because of the bigger lookups table and will then be too far away (i.e.
index > 16 bit).

In the calculation the `len` (size increase) of the lookups table needs
to be included.

[note]
In the `fontforge/tottfgsub.c`:

        g___FigureExtensionSubTables()

        3179: if ( sub->subtable_offset+offset>65535 )
        3218: sub->subtable_offset += len;

and later:

        dumpg___info()

        3410: efile=g___FigureExtensionSubTables(all,offset,is_gpos);
        3423: putshort(g___,offset+sub->subtable_offset);

On line 3179 is decided if a figure-extension has to be used, from the
original offsets sum.

One offset is then changed on line 3218.

On line 3423 we push out the changed offset sum as 16 bits, but did not
check if the changed (3218) offset values would fit.

There is this comment nearby in the code

        /* Offset to lookup data which is in the temp file */
        /* we keep adjusting offset so it reflects the distance between */
        /* here and the place where the temp file will start, and then */
        /* we need to skip l->offset bytes in the temp file */
        /* If it's a big GPOS/SUB table we may also need some extension */
        /*  pointers, but FigureExtension will adjust for that */

[note]
This fix has been triggered by
ryanoasis/nerd-fonts#694

Reported-by: Gulajava Ministudio <GulajavaMinistudio>
Reported-by: Rui Ming (Max) Xiong <xsrvmy>
Signed-off-by: Fini Jastrow <ulf.fini.jastrow@desy.de>
  • Loading branch information
Finii committed Jan 11, 2022
1 parent df9ab42 commit 1545aa3
Showing 1 changed file with 2 additions and 2 deletions.
4 changes: 2 additions & 2 deletions fontforge/tottfgpos.c
Original file line number Diff line number Diff line change
Expand Up @@ -3171,12 +3171,12 @@ return( NULL );
continue;
if ( sub->extra_subtables!=NULL ) {
for ( i=0; sub->extra_subtables[i]!=-1; ++i ) {
if ( sub->extra_subtables[i]+offset>65535 )
if ( sub->extra_subtables[i]+offset+len>65535 )
break;
}
if ( sub->extra_subtables[i]!=-1 )
break;
} else if ( sub->subtable_offset+offset>65535 )
} else if ( sub->subtable_offset+offset+len>65535 )
break;
}
if ( sub!=NULL ) {
Expand Down

0 comments on commit 1545aa3

Please sign in to comment.