-
Notifications
You must be signed in to change notification settings - Fork 448
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[varLib] Support for sparse kerning / anchors #3168
Comments
Here's my current idea for sparse kerning. We'll add an extension keyword to the .fea format
will signify an sparse kerning block. The implementation simply create a class-kerning table that has 0x7FFF instead of 0 for missing entries. In |
Same idea |
@anthrotype wdyt? |
@cmyr might also be interested. Current behavior, iiuc googlefonts/fontmake#998 correctly, is not entirely intuitive: if a static being merged:
The ability to specify some and let the rest interpolate is notably missing, I quite like the idea. I'm curious if type designers would find this useful, @davelab6 wdyt? |
VERY USEFUL! :) Rod recapped the current situation: Masters can have full set of kerning, which are interpolated across masters, or zero kerning, also meaning kerning is interpolated for their design space locations; but masters currently can not have partial set of kerning and interpolate the rest. This would address that shortcoming. |
Cool. I'll prioritize. I need input on the .fea file extension ( |
@skef penny for Adobe's thoughts? |
There are a lot of potential questions in this space. I'll start by noting a deep rabbit hole we went down considering whether to support a distributed data model in a VF-first workflow. That is, a model where a single hierarchy of fea files could still support supplying kerning data for individual masters separately. At this point we're leaning against that model because although it could work fine in common cases, in the general case it will sometimes be hard to match up lookups between the per-master lists, and accordingly hard to describe the heuristics for doing so and to implement those heuristics in the varying implementations out in the field, which don't currently do anything like that. Given that except for things like chaining rules most of these files are derived from other sources, and can now be given in a centralized format with the appropriate "sparseness caveats" it seems like more trouble than its worth. Given that, and coming into this issue with little background, I would need to know more about the scope and use of this idea. I suppose this is for an interim workflow where 0x7FFF is being used as a signal to the merger that the value is supposed to be interpolated. That does seem like a nice thing to have in the mean time; Adobe has already run into situations with its fonts where we've discussed this sort of thing. Just looking at the description, though, I'm wondering about the matching problem. I take it that uses with an actually empty block would be rare. Usually the problem is that some glyphs are missing from your sparse master and you want to assign kerning values to the rest, with some implication that anything missing gets omitted from the interpolation model at that location. So the problem is how to flag a negative, right? Or maybe I just don't have a grasp on what's being proposed. |
Correct. |
I agree this issue is more of an implementation detail of fontmake, than a general extension I'm proposing to .fea. |
Well, then it seems like the question is how it works when the relevant feature is "partially" rather than "completely" sparse, or I guess alternatively whether this mechanism would be limited to the latter case. |
BTW I hope for Google's sake that they're good for this. I think we're up to 2 pennies now. |
Not sure I understand. User can specify 0 kerns where that's intended. Is that what you mean? |
Maybe we should talk in specifics. Suppose we have something like
in the default master and
in a sparse master, because "d" is missing from it. That's probably just wrong, at least without "enum", because we're pretending there's a single value here and there isn't -- the one for So what about
and the analogous in the sparse master without the "d" lines. That should work conceptually, but what notation in the fea files really helps with this? "d" isn't in the sparse master so you can't "refer" to it in the intermediate file. If you "know" it's missing when merging you can do something clever, but that cleverness doesn't depend on fea grammar. So, all that said, what cases are handled by this extension? In your example the kern feature is either empty or there's just an ellipsis to be understood in the contents. If the former, how often is a whole feature sparse? If the latter, what are some example cases that the keyword is supposed to cover? |
That was my first thought when starting to read that thread. The problem needs to be addressed higher up in the data model, before the kern feature is generates, so in the kerning data structure. And instead of writing one kern feature per master, and try to mash that together on the lookup level, it might be better to write one variable kern feature. Then it is trivial to define what master gets a value and what not. We came up with a proposal of a possible syntax: http://handbook.glyphsapp.com/en/layout/variable-gpos/ |
"one variable kern feature" and "one kern feature per master" are what Adobe has internally been calling the centralized and distributed models, respectively. Until recently we were going down the path of supporting either model, with the distributed model providing some backward compatibility with current practice. The problem we've come to see with the distributed model is that once you allow things to vary even a little, which is the motivation for going beyond current practice, it's hard to match rule for rule in the general case. Existing tools build a set of lookups as they go. If you want to match in the general case, that's probably premature. Say that a feature specification in the default has two blocks of pair positions separated by a single chaining rule. Now a sparse master is missing that chaining rule because none of its glyphs participate in it. The ordinary thing to do when reading those sparse master rules would be to merge all the pair positions together into a single lookup. But now that lookup won't match either of the two pair lookups you built for the default, so you'll have to dig around and try to rematch things. Alternatively, you could, and would probably want to, keep all the data semi-symbolic before merging everything together at a later stage. That can probably be made to work but it's a dramatically different system than what we have now, and would probably drastically add to the upgrade costs for existing systems. (It would certainly do so for AFDKO.) All of this to process files that, in the normal case, are derived using higher-level tools anyway. You could solve many of these problems by disallowing "missing" rules entirely, so that all features in all masters need to match up lexicographically. After all, assuming we're building features late in the process there's no longer any genuine sparseness of glyphs, only different patterns of interpolation you want to wind up with. So instead omitting a statement from a master it could just have "NULL" as the value, as a signal to leave that location out of the interpolation. Maybe this would be worth supporting, we haven't absolutely decided against it. Note that the discussion in adobe-type-tools/afdko#1350 assumes a centralized model, so we assumed that this was the overall direction the community was expecting. |
This is what I have been saying for the past few years to anyone who would listen: these kinds of problems are inherent in a "distributed" build workflow. Using a variable-first kerning syntax all the issues of both sparse masters and aligning rules all go away. Progress isn't improving the merge, it's eliminating it. |
My thinking was this. Eg. default master has:
and Black master has:
Currently if you add this to the Bold master:
then it's assumed that the rest of the pairs ( |
I agree. Hence why this is a fontmake hack not a larger .fea suggestion IMO. |
That said, we do need to think in UFO terms about how to highlight a master as having sparse kerning. With glyph outlines it's easy: a missing glyph is assumed to be sparse. With kerning we assume zero. |
Agreed; fontc aspires to heed this advice. fea-rs will implement adobe-type-tools/afdko#1350 and fontc will convert source kerns to a fea file in this form.
Naively I might then think to add markers in the .designspace, perhaps to designate a source as having sparse kerning. No marker means current behavior. |
Right. @LettError @justvanrossum |
Is there a definition of what sparse kerning is? |
This is what I mean: |
Just one small note: if it turns out that this work is a useful compromise in the near-term, I would consider avoiding introducing a new token into the grammar, in favour of some sort of magic-comment, to reflect the fact that this is a tool-specific hack and not a proposal for a general change. |
Hm interesting! There are some questions to think about:
|
Yes. I can imagine sparse kerning needed at eg. Black Expanded. Or opsz=144.
The
Not necessarily. Again, the |
It seems like in this situation the tool already knows:
So, if we're talking about workarounds for this case involving new syntax or processing, why couldn't the system just assume:
? Right now zeros are ambiguous, but you've already identified how one might get around that in the toolchain: just use a signal value like 0x7FFF until you get to the merging stage. Maybe this leaves some hole that's not occurring to me? |
BTW I still think the situation described in #3168 (comment) is mal-formed without an "enum". That statement is supposed to become one lookup with a single value. A tool that lets sparseness cut across the statement will need to turn it into at least two lookups with different values. I think a good guideline here is that designers should organize their glyph classes in a way that would be compatible with a centralized model, even if they're currently using a distributed one. So, if you have sparse masters, split the glyphs missing from some masters into their own classes and give separate rules for them. Then the difference between master-specific fea files is the absence or presence of statements, rather than statements with somewhat different contents. In cases where the statement is documented as expanding to multiple rules (like with "enum") the tool level can be more flexible. This convention is a bit wordier in the fea files but it makes the processing a lot less mysterious. |
My personal opinion is that the "enum" keyword is implementation detail that has leaked into the .fea format. The compiler should just take care of it... At any rate, our merge tool is smart enough already to take care of differing classes across masters and merging them properly, as well as handling different masters having exception lookup only, classs lookup only, or both. |
If I was to do this again I probably would have done it that way. But changing it now would be a non-backward-compatible change. Hence why I'm asking for a marker in UFO / transient-fea. The reason it was done the way it's done though, is that we wanted the varfont to match the static masters exactly at those locations. |
@behdad are you solving a specific issue or making a general solution? |
With this system, what if a designer needs a mix of actual zeros and interpolated values at a sparse location? Is the idea that this new keyword would turn on the behavior I described? If that is the case, rather than a new keyword couldn't this just be a flag at the tool level, indicating that you want the new overall behavior rather than the backward-compatible behavior? |
Then they would insert an actual kerning of zero. The hacked-up keyword basically only tells the compiler to fill in the unspecified class-kerns with 0x7FFF, and the merger takes it from there.
Possibly. Thanks for the idea. Let me think about that. That's probably much cleaner. |
I'm trying to make a general solution. This has been an actual problem for designers for a long time. For example, @arrowtype demonstrated this issue in his Typographics talk earlier this month, where he wants the kern for My proposed solution would involve inserting two sparse kern masters only with the |
I can already fix |
BTW is there already syntax or method to express "immediately after N" or "immediately before N" when specifying location? Meaning + or - 1/16384 in 2.14 units. It’s a useful thing, as shown by the Q stroke in Apple Skia having a tiny zone that unintentionally interpolates. |
I agree! I was going to suggest this argument as a reason to allow integer normalized (not float) values. But |
We (Adobe) has this on our informal list but we haven't arrived at a notation yet. |
I know it's useful. Mutatormath does it. |
So to recap the discussion so far, it looks like I can do this by just defining a Lib key in the .designspace file; or individual Lib keys in the sparse-kern UFOs. |
@behdad how would this interact with our compile-variable-fea effort at googlefonts/ufo2ft#635 (comment)? As Simon pointed out, sparsity is easy to do with variable fea syntax. To match current semantics, we actually have to first make a union of all kerning pairs used across all UFOs and then fill in the missing values with Oh yeah, not sure if this has been discussed, but in a Light, Regular and Bold setup, if Lt and Bd have a certain kern pair value and Rg does not, does Rg get 1) a zero or 2) an interpolated value? What if there are multiple axes? |
Why do you use
If Rg is default we require it to define the kern. Otherwise, currently it gets zero. With my proposed hack / lib key, it will be out of interpolation. |
Not when trying to match current behaviour. The compile-variable-fea PR would need to know when to just leave stuff out :) |
Ah right. That's indeed what we're also discussing here. |
I want to make sparse kerning / anchor masters possible.
The text was updated successfully, but these errors were encountered: