OpenType Feature to Replace Initial Forms

A problem with Initial Forms came to light in Beta testing for Affinity Designer.

Due to a change made by Microsoft in the description for the Initial Forms (init) feature, the feature is enabled by default and not presented to users in the GUI, so it cannot be disabled.

When I designed my fonts, the description of the init feature was different.

Friendly name: > Initial Forms
Registered by: > Microsoft/Adobe
Function: > Replaces glyphs at the beginnings of words with alternate forms designed for this use. This is common in Latin connecting scripts, and required in various non-Latins like Arabic.
Example: > In the typeface Ex Ponto, the default t in the word ‘type’ is replaced with the t.begin form.
Recommended implementation: > The init table maps default alphabetic forms to corresponding beginning forms (GSUB lookup type 1).
Application interface: > The application is responsible for noting word boundaries. For GIDs at the beginnings of words and found in the init coverage table, the application passes a GID to the feature and gets back a new GID.
UI suggestion: > This feature should be active by default.
Script/language sensitivity: > Can be used in any alphabetic script.
Feature interaction: > This feature may be used in combination with other substitution (GSUB) features, whose results it may override. See also medi and fina.

I have therefore decided to remove all Initial Forms features from my fonts and use a Character Variant instead. This seems like an easier option to implement than Contextual Alternates, but it does mean that the user has to disable the feature globally and enable it wherever it is needed.

Is there a better alternative?

It depends on what you want, but init and fina for Latin can be done with calt. I took some code from an earlier post and made some adjustments to enable init through calt:

script latn {
  feature ContextualAlternates;
}

class @uppercase [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];
class @uppercaseinit [A.init B.init C.init D.init E.init F.init G.init H.init I.init J.init K.init L.init M.init N.init O.init P.init Q.init R.init S.init T.init U.init V.init W.init X.init Y.init Z.init];
class @latin_all [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 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 A.init B.init C.init D.init E.init F.init G.init H.init I.init J.init K.init L.init M.init N.init O.init P.init Q.init R.init S.init T.init U.init V.init W.init X.init Y.init Z.init];

feature ContextualAlternates calt {
  lookup ChainingContextInit;
}

lookup ChainingContextInit {
  ignore context (@latin_all) @latin_all;
  context @uppercase;
  sub 0 SingleSubstitutionInitUpper;
}

lookup SingleSubstitutionInitUpper {
  sub @uppercase -> @uppercaseinit;
}

Character Variants support custom naming fields, which you can define with FontCreator. Just keep in mind the code editor doesn’t support it yet.

Thank you. That works as I wanted. It will be active by default, which is not a huge problem if it can be disabled. I will add it to my fonts later.
Contextual Alternates.png

Maybe a feature that is inactive by default is better. I’m not sure which one, but maybe it fits in Stylistic Alternates?

That’s certainly something I should look at before I get too far down the road of fixing my fonts. I have already done Garava and Cankama with Character Alternates and Contextual Alternates.