[MPEG-OTSPEC] VARC component substitution

Skef Iterum skef at skef.org
Wed Jan 31 10:17:37 CET 2024


In my earlier message of August 22nd I raised two questions. One was, in 
effect, about VARC. The other was about substitution in variable 
composites. I opened issue #104 
<https://github.com/harfbuzz/boring-expansion-spec/issues/104> about the 
latter.

I still think a substitution mechanism could be a good addition but I'm 
not able to do a proper proposal. Instead I'm going to outline the 
reasoning and a design. The design turns out to be pretty simple and I 
don't think it would be a burden to specify or support.


      The reasoning

Sometimes the basic design for a glyph or a component is appropriate at 
one part of design space but not at another. This is clear at the glyph 
level, with the dollar sign as an archetypal example. I don't have first 
hand knowledge of this but asking around some designers have indicated 
that glyphs in pre-digital font faces, including CJK glyphs, used to 
differ somewhat more between weights, implying that multi-master based 
design has washed out some of those idiosyncrasies. Even so, I have 
confirmed that Adobe fonts using multi-master design sometimes need 
little differences. Most of these can be handled by playing tricks with 
masters, because they have more to do with proportion than changes in 
the visible elements, but playing tricks with masters in unusual 
locations has its own pitfalls.

Now, suppose it were desirable to have a component of a CJK glyph have a 
distinct design at different points of design space that is either 
non-interpolable or would be difficult to design as interpolable 
(perhaps it would require "trick geometry"). If there were one such 
component with two such designs, every composite that includes the 
component would need two GIDs: one for each design. A composite 
including two such components, assuming they don't "flip" at the same 
location(s), would need four GIDs for the four combinations. And so on. 
Each of these glyphs would duplicate a lot of data, including the 
variable composite records themselves, hmtx, any kerning, and so on.

If instead one could vary /component/ inclusion based on condition sets, 
as long as the component differences don't change the composites out 
"outer metrics" (the normal case, I think), one GID would suffice. And 
having such an option in the spec might feed backward into tools, making 
it easier to vary component designs in this way.


      The design

This is how I would modify the current VARC proposal to support 
component substitution:

 1. The VARC table header gets a new
    Offset32To<CFF2IndexOf<ConditionSet>>. When non-zero this points to
    an index structure of ConditionSet Tables, which in turn have
    offsets to condition tables. For any condition value tables, the
    major and minor numbers pick out an entry in the
    MultiItemVariationStore of the same table.
 2. A new IS_CONDITIONAL variable component flag indicates that the
    component entry has a new optional uint16 field ConditionSetIndex,
    which is the index of a condition set in the added top-level
    ConditionSetIndex.
 3. Variable component records are then processed this way: When the
    first entry has IS_CONDITIONAL set, or an entry has that flag when
    the previous entry did not, the following entries until and
    including the next entry /without/ the flag are grouped together.
    Each condition set is checked in order until one is met, and that
    entry is composited as specified. If none of the condition sets are
    met the last entry (without the flag) is composited as specified.
 4. In order to make this setup complete there should be a compact means
    of specifying an "empty" entry to indicate that nothing should be
    composited when that condition set is met. One option is another
    flag, another option is a special GlyphID24 with that implication.

Note that:

 1. The cost of adding this mechanism and not using it is an extra 4
    bytes per VARC table.
 2. The cost of using it a little is small. Two condition sets with
    three conditions each is 70 to 100 bytes, then add the cost of
    duplicating the variable component records.
 3. The grouping is not difficult to implement or hard to explain in the
    specification.

Thanks,
Skef
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.aau.at/pipermail/mpeg-otspec/attachments/20240131/84a516b4/attachment-0001.htm>


More information about the mpeg-otspec mailing list