Skip to content

The six GPOS contextual subtable layouts are decoded twice, once to apply and once to report #119

Description

@jakejackson1

Follow-up to #90, which added the second copy.

Otl and OtlDump each decode the six GPOS contextual positioning subtable layouts, from
the spec, independently.

format applied in Otl reported in OtlDump
7/1 _applyGPOScontextPosFormat1, Otl.php:3930 reportGPOScontextPosFormat1, OtlDump.php:2563
7/2 Otl.php:3988 OtlDump.php:2620
7/3 Otl.php:4074 OtlDump.php:2677
8/1 Otl.php:4115 OtlDump.php:2711
8/2 Otl.php:4183 OtlDump.php:2764
8/3 Otl.php:4314 OtlDump.php:2821

Both walk the same records in the same order - a PosRuleSet chosen by coverage index, then
glyphCount, posCount, the input sequence one short of its count, then the
PosLookupRecords - and both had to get the one ordering trap right independently: Type 7
Format 3 puts posCount before the Coverage offsets where Type 8 Format 3 puts it after.

This is the same shape #112 was about, one level down. There the two copies had already
drifted; these two have not yet, because one of them is four weeks old.

Why it is not simply #112 again

The obvious fix - have the parser record what it read and the dump render it - does not
apply here, and #90 says why. TTFontFile never parses a GPOS subtable: it reads position
0's Coverage for the shaper's gate and nothing else. Making it parse all six layouts would
slow every font-cache build for the benefit of a debugging page.

So the sharing has to be at the level below both: the primitives, not the structures.

Where to look

OtlDump.php:2926-3010 already has them, extracted while #90 was written:

coverageOffsets()    the Coverage offsets of one sequence, read in place
coverageGlyphs()     follow them
posLookupRecords()   SequenceIndex + LookupListIndex pairs
glyphSequence()      a sequence naming one glyph per position
classSequence()      a sequence naming one class per position

Those are five methods that take a FontReader and return a structure, which is exactly
the shape of Mpdf\Fonts\Table\Coverage and Mpdf\Fonts\Table\ClassDef. Moving them there
and having both Otl and OtlDump call them would leave each side with its own reason for
reading - applying against the run, or rendering - and one copy of the layout.

Safety

tests/data/fontcache/*.json, tests/data/otldump/*.txt and tests/data/shaping/*.txt
between them pin both sides for every font in tests/data/ttf. Note that 7/2 is covered by
neither, for the reason in the issue filed alongside this one.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions