Open skef opened 1 year ago
Unfortunately this is impossible to express directly with the currently available mechanisms.
One way I thought about this is to synthesize a the sloped line as a new axis with avar2, and use it... But that's very complicated to do a simple thing.
I'm very much in favor of your proposal.
avar2 was my thought too. You’d create a "stem width" axis (XOPQ if you want to align it with the Type Network spec), control it via avar2, and code GSUB substitutions according to it rather than to user axes. I’m not sure there’s a less complicated way to do it. Why do you call it complicated, Behdad?
Why do you call it complicated, Behdad?
I feel like you'd need a new axis for any substitution then. I don't think even the standard parametric axes would do it.
I find stef's proposal much simpler.
Apologies for not reading the PDF properly. It’s a brilliant idea that avoids adding new axes (which would affect numerous other tables and leads to UI annoyances even if "hidden").
A correspondent asked for some example files to make all of this a bit more concrete. In making those I realized I had the opsz
axis backwards (relative to its documented use) in the examples, so I reversed the direction using the labels. These files use the new direction
The first contains the source files used to build the font, and the second is just the font alone.
The font has two codepoints: a
and $
. $
switches between two glyphs using the 8 region workaround from the example. a
contains a dot with a center that moves vertically according to the condition value described in the PDF, except that all magnitudes are divided by 20. If you display both glyphs in a tool that lets you adjust VF axes, you'll see that the substitution happens close to when the dot crosses the baseline (e.g. y = 0). The "close to" is due to the approximation inherent in the workaround.
Based on discussions over at #53, I think we may also want a flag in this new subtable indicating that the value should be boolean-negated. (That is, treated as false when it would normally be treated as true, and vice-versa.)
More complete document with background: conditions.pdf (This version of the PDF was updated August 8th).
Consider the archetypal case of substitution: A variable font has two glyphs for the dollar sign, one with two vertical strokes and another with just one stroke. The designer wants to switch between the glyphs when they judge that the strokes are too thick to leave room for each other. In the usual examples this decision is tied to the
wgwt
axis.However, the thickness of a stroke is not necessarily just a function of one axis. Indeed, the
opsz
axis, which is registered and already used in some variable fonts, also changes the thickness of strokes, with strokes getting somewhat thinner as the axis increases. If a designer's decision about when to substitute is based on thickness, their preference across both axes might look something like this:Unfortunately this is impossible to express directly with the currently available mechanisms. The best you can do is a stepwise approximation, perhaps something like this:
Therefore, even for what isn't all that good an approximation, we now have eight regions plus a default just for one glyph across two axes. If a different glyph needs similar treatment along a different line on the same combination of axes, we can use the same regimentation but will then wind up with 16 regions plus a default. And so on.
Proposal
There there are likely many novel means of addressing the interdependent axis substitution problem, but it seems easiest to choose the least novel. That is, rather than having to invent a bunch of new machinery it seems preferable to use something already available. And in this case the easiest option is to use a normal interpolated value, just like those already used for point locations in glyph outline data or kerning values in GPOS.
Accordingly, suppose that we were to add Condition Table Format 2: "Condition Value":
The way this condition works is what you would expect: It evaluates to true when the value is positive and false when it is 0 or negative. The font engineer making use of the condition value is then responsible for placing the "zero line" where the designer needs it.
(See document above for solution to the sample problem.)