[`CFF2`] Allow more than one `vsindex` operation and at any place
Problem statement
Currently, the CFF2 spec says:
The vsindex operator may be used only once in a CharString and must precede the first use of the blend operator.
This imposes a snag when compiling fonts built using very common idioms, as well as disable certain optimizations:
Compiling composite glyphs
Imagine a font designer designed atilde glyph as a composite glyph consisting of an a and a tildecomb glyph. When compiling these to a CFF2 font, the glyph needs to be decomposed, because CFF/CFF2 do not really have the concept of composite glyphs in the same sense.
By the restriction quoted in the last section, the two glyphs a and tildecomb must have the same master configuration. If they don't, the compiler has to synthesize some each of the a and tildecomb in some locations and add back into their master configuration, to ensure they share their master configuration. This is not straightforward, and because of the next problem, is also very costly in terms of bytes. It is similar to trying to merge two fonts with different designspaces.
Reduced file size
Different vsindex'es can optimize for different set of "active", ie. non-zero, tent deltas, which is not currently possible. A lot of blends might end up encoding a lot of zeros as a result. If we allow switching the vsindex in the middle of the CharString, the compiler can optimize things better to avoid those zeros. The ItemVariationStore design, for example, when used to store actual deltas, optimizes them by the width needed to encode each delta value. The same can be applied to optimizing the blend operators in a CFF2 font.
Suggested change:
-
Allow multiple
vsindexoperations and at any place, in both CharStrings and Private dicts. -
The default
vsindexfor a CharString is currently defined to be thevsindexset in the relevant Private dict. The text should be updated to say that it's the lastvsindexoperation in the Private dict that is the defaultvsindexfor processing the CharStrings.
This might be controversial.
I get the reduced filesize possibilities. I'm less clear on the first part. If the glyph is decomposed (which you would expect with VARC) then presumably the outlines for a and the outlines for tildecomb to into separate CFF2 glyphs, each of which can have its own vsindex. So I'm not understanding the problem.
If the glyph is decomposed (which you would expect with VARC)
No I'm not talking about VARC.
When building a regular CFF2 variable-font from sources like Glyphs files that have the composite-glyph feature, but those glyphs needs to be flattened to go into CFF2. Currently it's a big hassle if the components have different master configurations.
Oh, hmm.
The rest of these proposals are probably viable to roll into the spec as clarifications. This would be a very significant change, and I would think at least require upping the minor number on the table. I suspect it would also be a pain to implement across rasterizers and other tools -- a lot of tools expect to be able to set up the model and forget about it.
That said, there's no reason we can't discuss it.
Yes, this is the only change that can break existing rasterizers, but I think we should discuss it. Thank you.