-
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
[designspaceLib] [varLib] Allow FeatureVariations to be processed *after* other features #1747
[designspaceLib] [varLib] Allow FeatureVariations to be processed *after* other features #1747
Conversation
…t to 'rvrn'); allow said feature to already exist, in which case we append new lookup indices to the existing feature
Thanks Just! I'll take a look tomorrow. |
Something I just realized that I'm not sure how to address: what if there exists multiple features with |
You should update all. Or make the function alternatively take a feature index / set of feature indices and update those, or additionally take script and language tags (and default to updating all). |
Right, I think I understand. Where it currently does this: record = buildFeatureTableSubstitutionRecord(varFeatureIndex, existingLookupIndices + lookupIndices)
featureVariationRecords.append(buildFeatureVariationRecord(conditionTable, [record])) ...it should build a record for each existing feature. |
Done in db04262. |
If we can agree on how to enhance the designspace file format, I can implement that here, too. Looks like it'll be fairly easy to do. |
Designspace file: perhaps But I'm open to suggestions to make this more clear. I'm trying to avoid making this too OpenType-specific, and I want to keep the functionality simple. It is not my intention to implement all that is possible with feature variations, but to make the common case easy to specify. (In hindsight we should've never used 'rvrn' in the first place, but should have went straight to 'rclt'.) |
And in addition to a new ( |
…ttools#1750, as well as the related doc.rulesProcessingLast flag
…ld use 'rvrn' or 'rclt'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good, thanks.
I was only a bit uncertain about the use of rclt
feature, since the spec defines this specifically for contextual alternates (GSUB Lookup 6), but I guess it works with any GSUB lookup type.
Basically, we are relying on the fact that rclt
is always on (like rvrn
), but it is not reordered first and is applied in the order of the lookup list, thus it can override previous ones.
I imagine that you tested that this works on all the major OSes and layout engines (I haven't had the chance yet).
Bonus point if we add a test for the case when rclt is already present.
Wrt 'rclt', see this bit of twitter: https://twitter.com/justvanrossum/status/1184849808462405635?s=19 I have some test results with this approach, with help from @irenevl and @Lorp, which I have to dig up. There will be some caveats ('rclt' is relatively new, but so is 'rvrn') , but right now I am convinced it's the best we've got. I'll work on a test case with existing 'rclt'. |
… have the rulesProcessingLast attribute
Regarding using 'rclt' instead of 'rvrn': I made a test font last year, and @irenevl was so kind to test it in several environments. Here findings on 14 december 2018 were as follows:
The test font from back then: FeaVarTestFont-VF-rclt.ttf.zip It only supports the character 'a', and has a 'smcp' feature, and an axis called TEST that switches |
Expected results:
|
There is also:
Are we sure that extending the rules designspace section possibly ad infinitum is the best course of action? At some point we'll arrive at conditional contextual substitutions and conditional positioning. This really should be done in the FEA syntax and feaLib, I think. |
Even if there are things that will not be implemented in one of the three FEA compilers (makeotf, feaLib and fontforge), I don't think we should consider the FEA syntax tabula rasa. There are FEA syntax aspects that are not implemented in makeotf already, and there are aspects not implemented in feaLib and in fontforge. But that's the difference between spec and implementation. I think that "rules" should remain a simple hack (above all: one that is easily implemented in both static and variable fonts, so limited to 1:1 glyph replacement, and ordering-agnostic). Specifying feature tags in rules is, to me, scary. It starts looking like some kind of "patcher" for FEA that exists only because FEA currently cannot express it. I'm not even sure if the processing=post is a good idea. How would you implement processing=pre vs. processing=post in static instances? |
Though I can see the benefit of processing=pre vs. post. But "no more". I mean, let's try to attack FEA in feaLib for more sophisticated control. |
Is it not sufficient to have an early lookup for the pre rules, and the very last GSUB lookup for the post rules, and have them both associated with "rvrn"? Or do implementations process all the lookups associated with rvrn early, regardless of their place in the lookup order? |
I mean, if I do
Then, when I enter |
No, or this PR would not exist. Check the 'rvrn' spec, and the fonttools issues related to this issue, a recent twitter discussion mentioned above, and a discussion on the OT list last year. |
In retrospect, I think it may have been enough for .designspace rules to only support "last" behavior. But it currently uses 'rvrn', which is pre per spec, and therefore pretty useless if interaction with other features is desired (which is often). And we can't just change the behavior silently, so the only way to address this is to add a flag to .designspace. I wish it hadn't been necessary. |
Please read up on the actual issue before pointing out the obvious, which obviously doesn't work or we wouldn't be in this discussion. |
It's not a hack, just like Just like |
Thanks for the clarification. Sorry for my ignorance :) Of course I'm not opposing higher-level structures, but we know that rules predate FeatureVariations and were intended for swapping in instances. My concern now is that implementing the pre vs post rules behavior in static instances is not specified at all, and may be quite hard to implement. Unless the recommendation would be that post rules are also done in rclt in instances, just without conditions. Pre can best be done in cmap and ccmp, I think. |
With kerning vs. feature kern, it's slightly different. Kerning is deliberately a higher-level structure. Simple rules probably as well. But pre vs. post feels a bit like a hack, made to address the fact that the general-purpose feature building is not up to the task. I know that adding it to rules addresses an immediate need — I just meant to say that it just gives a small step. For things like conditional turning on ligatures as you increase a variable axis value, it still doesn't work. So we still need to work on FEA, I think. |
No, this is deliberately out of scope for designspace rules. Just like eg. script/language-specific kerning or contextual kerning is out of scope for kerning.plist.
Sure! I'm all for it. However, in the plus-three-years that people have been talking about this, I haven't seen any progress on the implementation side. And people still can't seem to agree how things should be spelled. And if it ever gets so far — mark my words — it will feel a lot more like a hack than designspace rules ever did. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding the test! LGTM
This PR implements #1625 and resolves #1371.
Item 2 needs a test case.Update: what follows has been implemented in the meantime.
This needs integration with
varLib._add_GSUB_feature_variations()
, and some way in the designspace file to specify what to do.I propose the following:
Add a
processing
attribute to the<rules>
tag, which can have a value of"pre"
or"post"
. "pre" will be default, and will use thervrn
feature for FeatureVariations. "post" will use therclt
feature instead, and will cause the substitutions to be done last in the GSUB processing order.Example:
I suggest to do designspace integration in a separate PR.Integration with designspaceLib and varLib has also been implemented in this PR.