adobe-type-tools / afdko

Adobe Font Development Kit for OpenType
https://adobe-type-tools.github.io/afdko/
Other
1.04k stars 169 forks source link

[makeotf] substitution without target item does not fail #1737

Open frankrolf opened 6 months ago

frankrolf commented 6 months ago

Unexpectedly, a features.fea looking like this seems to be completely acceptable to makeotf:

languagesystem DFLT dflt;

@letters_lowercase = [ a b c d e f g h i j k l m n o p q r s t u v w x y z ];

feature ccmp {
    sub @letters_lowercase;
} ccmp;

(note no target item in the substitution). This could be a feature – just making sure it’s not accidental.

Example project attached: subs_no_target.zip

skef commented 6 months ago

I think that syntax just amounts to an implicit "by NULL".

skef commented 6 months ago

Yes, I looked at the code and this is treated the same as if there was an explicit "by NULL", so I think it's OK.

frankrolf commented 6 months ago

This whole scenario was encountered by a student in a FDK workshop – they reminded me of what the effect was. Basically, this substitution kills the a in the target font (nothing else):

image

Still expected?

skef commented 6 months ago

I guess the first question is whether putting in an explicit "by NULL" changes the outcome. If it doesn't, then it's more or less expected. If it does change the outcome then there's a discrepancy.

The other question is whether "by NULL" is implemented correctly for this case.

frankrolf commented 6 months ago

more verbose, as suggested:

sub @letters_lowercase by NULL;

same result, only a is affected


try to affect more glyphs than the a

sub @letters_lowercase by NULL NULL;

fails


different feature tag

feature smcp {
    sub @letters_lowercase;
} smcp;

no difference


different logic

@letters_lowercase = [ a b c d e f g h i j k l m n o p q r s t u v w x y z ];
@null_group = [ NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL ];

feature ccmp {
    sub @letters_lowercase by @null_group;
} ccmp;

fails


deliberate

feature ccmp {
    sub a by NULL;
    sub b by NULL;
    sub c by NULL;
    sub d by NULL;
    sub e by NULL;
    sub f by NULL;
    sub g by NULL;
    sub h by NULL;
    sub i by NULL;
    sub j by NULL;
    sub k by NULL;
    sub l by NULL;
    sub m by NULL;
    sub n by NULL;
    sub o by NULL;
    sub p by NULL;
    sub q by NULL;
    sub r by NULL;
    sub s by NULL;
    sub t by NULL;
    sub u by NULL;
    sub v by NULL;
    sub w by NULL;
    sub x by NULL;
    sub y by NULL;
    sub z by NULL;
} ccmp;

works


sneaky NULL

@letters_lowercase = [ a b c d e f g h i j k l m n o p q r s t u v w x y z ];
@null_group = [ a b c d NULL f g h i j k l m n o p q r s t u v w x y z ];

feature ccmp {
    sub @letters_lowercase by @null_group;
} ccmp;

fails

anthrotype commented 6 months ago

this is documented here: https://adobe-type-tools.github.io/afdko/OpenTypeFeatureFileSpecification.html#5a-gsub-lookuptype-1-single-substitution

If the replacement glyph is the reserved word NULL, then the substitution has no replacement, removing the input glyph from the glyph sequence: substitute a by NULL; Omitting the by clause is equivalent to adding by NULL.

frankrolf commented 6 months ago

Thank you Cosimo. I guess my original question is answered there, however some of the results (only the first item of a group is replaced) are surprising.

skef commented 6 months ago

however some of the results (only the first item of a group is replaced) are surprising.

Yes, this seems like it's a bug (assuming it's something we can fix, which seems likely)