Skip to content
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

[designspace] Proposal to add <fea> #2434

Open
ctrlcctrlv opened this issue Oct 25, 2021 · 14 comments
Open

[designspace] Proposal to add <fea> #2434

ctrlcctrlv opened this issue Oct 25, 2021 · 14 comments

Comments

@ctrlcctrlv
Copy link
Contributor

ctrlcctrlv commented Oct 25, 2021

コピペ of unified-font-object/ufo-spec#194: (via https://twitter.com/fr_brennan/status/1452644352417800197)

I was talking to a bunch of designers and very surprised they don't even know what the binary format allows because Designspace spec has so thoroughly boxed them in.

Designspace allows only a fraction of what is possible in binary format, that is to say, while binary format allows either GPOS or GSUB to contain basically any number of FeatureVariations lookups, Designspace constrains itself to only GSUB LookupType 1, Single Substitution. Despite there being obvious use for all the other types, especially GPOS.

I propose to deprecate <rule> tag, replace with <fea> tag. <fea> tag will hold a subset of Adobe FEA code. It will not allow you to insert anything at the toplevel except lookup. Alternatively, if people prefer, <fea> tag can be provided in multiple and there will be an implied wrapping lookup … { … }.

The new proposal is to have <fea> be a child of <rule>.

Problem solved, no need for @simoncozens idea of complex "variable FEA syntax" (cf. adobe-type-tools/afdko#1350, #2432), no need to change FEA standard at all.

Besides, changing FEA standard is confusing because what, you're adding FeatureVariations to instance UFO FEA's? What if they differ in any way?

OK, I guess Simon would say "well I want a new font format which will allow a toplevel FEA", which, fine. Or someone else might say "I want a multiple master UFO with a toplevel FEA". Again, fine. (I disagree to both, I like UFO, but no need to slow down progress over something like that.)

Alternatively, <rule> can be kept, and <sub> deprecated instead, with <fea> living inside <rule> instead of becoming the new toplevel. I don't like this since it makes less sense, I would rather <fea> hold the <conditionset> and have a filename attribute, but whatever, it's OK.

Detailed proposal

Add new section § 5.1.4 fea element as follows:

  • Defines a group of OpenType features in a subset of Adobe OpenType™ Feature File (FEA) format.
  • A fea element must have a filename attribute pointing to an Adobe FEA. fea without filename, or pointing to a non-existent filename, should be ignored when compiling a font; strict parsers can consider this an error.
  • The subset of FEA format supported is only anything that would be allowed below a lookup {} block, including the lookup block.
  • Should <fea> appear before, after, or between <sub> elements, the features within are to be applied in their XML order.
<rules>
    <rule>
        <conditionset>
            <condition minimum="250" maximum="750" name="weight" />
            <condition minimum="50" maximum="100" name="width" />
        </conditionset>
        <conditionset>
            <condition ... />
            <condition ... />
        </conditionset>
        <fea filename="all_masters.fea" />
    </rule>
</rules>
@ctrlcctrlv ctrlcctrlv changed the title [designspace] Proposal to deprecate <sub> and possibly `<rule> [designspace] Proposal to deprecate <sub> and possibly <rule> Oct 25, 2021
@simoncozens
Copy link
Collaborator

Note that I only proposed variable scalars in AFDKO. Feature variation syntax was @punchcutter’s thing. But both will still be needed because Designspace is not the only way to represent font variations.

@ctrlcctrlv
Copy link
Contributor Author

Yes, and it won't be too hard (I don't think) to just add to UFO spec that FeatureVariations aren't valid in instance UFO FEA's. Do your changes to fontTools have a function like ast.has_feature_variations() -> bool ? That'd help I'm sure. I'm not against your format, this one is just far more practical for me and probably most other people using current generation UFOs.

@belluzj
Copy link
Contributor

belluzj commented Nov 8, 2021

One thing to consider: with <sub> elements there's a way to apply them to static instances by swapping glyph contents (which actually is a bit wonky and doesn't work in more complex situations like many-to-one <sub>s). How are you planning to apply the custom FEA code to static instances? One way might be to stick the FEA code in question in an always-on feature in the static instance?

@belluzj
Copy link
Contributor

belluzj commented Nov 8, 2021

Other question: why not allow feature rvrn { } rvrn; blocks in the fea? That would allow you to say into which feature you want the code to go, e.g. rvrn or rclt, the two usual ones, and potentially put a bit of the code in one and another part in the other (whereas with current designspace's rulesProcessingLast it's all in one or all in the other).

@justvanrossum
Copy link
Collaborator

(For the record, including .fea in designspace is a hard no from me, in case I'd have a vote in this.)

@simoncozens
Copy link
Collaborator

Interesting - why?

@ctrlcctrlv
Copy link
Contributor Author

@belluzj As I understand it, in the binary format, rvrn doesn't actually exist. To explain what I mean by this, the feature tag rvrn is just a hint that the lookup is applied last; that's because FeatureVariations lookups don't have feature tags? Consider this fonttools script that I actually use in production for FRB American Cursive v2:

#!/usr/bin/env python3
# This script is to be used because the Designspace XML format <rules/> element is incomplete and cannot express the full range of possibilities provided by GSUB.
# So, what we do is, we put the feature that we actually want to trigger when the OPSZ design axis is ≥ 48px into `ss01`. We then compile the font with the `ss01` and a fake FeatureVariations table that just changes `A` to `A.alt`.
# We then run this script to replace our fake lookup (only written to be replaced by us now with this script) with all the lookups triggered by ss01. Ta-da…

import sys
import fontTools.ttLib as tt

(_, otf) = sys.argv

f = tt.TTFont(otf)

lli = []
for e in f["GSUB"].table.FeatureList.FeatureRecord:
  if e.FeatureTag == "ss01":
    lli = e.Feature.LookupListIndex
f["GSUB"].table.FeatureVariations.FeatureVariationRecord[0].FeatureTableSubstitution.SubstitutionRecord[0].Feature.LookupListIndex = lli

f.save(otf)

It takes the contents of feature ss01 and copies references to every lookup within into the first FeatureVariationRecord. As I understand it, these records do not have associated feature tags.

@Lorp
Copy link

Lorp commented Nov 9, 2021

@belluzj As I understand it, in the binary format, rvrn doesn't actually exist. To explain what I mean by this, the feature tag rvrn is just a hint that the lookup is applied last; that's because FeatureVariations lookups don't have feature tags? ...

The rvrn tag does indeed exist in the binary. If you drag-drop a font onto Axis-Praxis you’ll see a list of all feature tags in the GSUB table. There’s no special casing in the code that extracts these tags from the font.

@simoncozens
Copy link
Collaborator

I think the point is that there’s nothing remotely special about rvrn as a feature, in terms of variations. Any feature can get a replacement table.

@twardoch
Copy link
Contributor

The point of rvrn is that it's supposed to be applied first, regardless of lookup order, before any shaping features, and in all language systems, and it's always on. Hence: required variations — as opposed to any other feature variations that can, of course, be anywhere.

@ctrlcctrlv
Copy link
Contributor Author

@simoncozens was right, that was indeed my point. I am indeed aware that the number 1920365166 (72:76:72:6ervrn) appears in the tag area of the binary format and is not stripped out if specified, but implementations do not use the number to figure out lookup order, it is at most a hint to the font compiler, because FeatureVariationRecord has no field for a tag.

@justvanrossum
Copy link
Collaborator

Interesting - why?

Let me soften/qualify: I don't think .fea should be embedded in .designspace like Frederick suggests. I'm open to add a field that references an external .fea file. (One per .designspace doc? One per <variable-font> element?)

Sidenote: The <rules> element is deliberately simplistic, and was specifically designed support only the most common use case of Feature Variations. It's similar to how UFO kerning.plist does not support contextual kerning. Being able to step down to .fea should be an option, though.

@ctrlcctrlv
Copy link
Contributor Author

@justvanrossum I'm OK with dropping the part of the proposal that talks about putting FEA code in XML text children. I thought it was cool but if you really don't like it, what's most important to me is that this is possible, not necessarily how it's done; if we can put FEA path as an attribute, that works for me as well.

@ctrlcctrlv
Copy link
Contributor Author

I have updated the proposal.

@ctrlcctrlv ctrlcctrlv changed the title [designspace] Proposal to deprecate <sub> and possibly <rule> [designspace] Proposal to add <fea> Nov 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants