<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<p>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 <a
href="https://github.com/harfbuzz/boring-expansion-spec/issues/104">#104</a>
about the latter.</p>
<p>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.</p>
<h3>The reasoning</h3>
<p>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.</p>
<p>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.</p>
<p>If instead one could vary <i>component</i> 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.</p>
<h3>The design</h3>
<p>This is how I would modify the current VARC proposal to support
component substitution:</p>
<ol>
<li>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.</li>
<li>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.</li>
<li>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 <i>without</i> 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.</li>
<li>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.</li>
</ol>
<p>Note that:</p>
<ol>
<li>The cost of adding this mechanism and not using it is an extra
4 bytes per VARC table.</li>
<li>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.</li>
<li>The grouping is not difficult to implement or hard to explain
in the specification. <br>
</li>
</ol>
<p>Thanks,<br>
Skef<br>
</p>
</body>
</html>