Trouble with more than one alternate glyph in FontLab

Turoturom's picture

Hello, I am finishing a typeface that has 3 or 4 alternative glyphs for the same letter on FontLab. Not knowing much of programing I've been able to solve a lot problems searching on the web for I find that the FontLab Manual is not very friendly for me.

I use this link (below) for the final touches for my font, this page has been very usefull, but it does not specfy what to do if you have more than one alternative letter for one character

I would write him but he has not replied to any of his question/comments of other users

I named my glyphs as he suggests! For example


...and such

What's written right below is where I get stuck, copied from his web. My main question is, how do I program for a.alt3 and a.alt4?


And finally, the code block for SALT.  Click the + again and cut and paste this:

feature salt { # Stylistic Alternates
# Latin
sub @salt1 by @salt2;
} salt;


This is all I need to complete post my font.

Thanks in advance

Mario Arturo

gargoyle's picture

You're right, the code you reference only provides for one alternate per glyph. A substitution rule for a glyph with several alternates uses a different syntax:

sub glyph from class;

So for an 'a' with four alternates, the rule would be:

sub a from [a.alt1 a.alt2 a.alt3 a.alt4];

Single substitution rules ("by") and alternate substitution rules ("from") can't be used in the same feature/lookup. So if you're using classes to minimize the code for single substitutions (as in the example from the website), you'll need to create separate lookups. For example:

feature salt { # Stylistic Alternates
  lookup single {
    sub @salt1 by @salt2;
  } single;
  lookup alternate {
    sub a from [a.alt1 a.alt2 a.alt3 a.alt4];
  } alternate;
} salt;

Note that glyphs with multiple alternates should be removed from the classes used for single substitutions, so that there's a 1:1 relationship between the glyphs in @salt1 and their alternates in @salt2.

Turoturom's picture

Thanks Gargoyle. Does your last paragraph mean I should eliminate everything I put in CLASSES cause I no longer need them or just leave all the ones I named .alt1?

Turoturom's picture

Thanks Twardoch: I found your link usefull, I do have one question about it: Do I still need to write my alternative glyphs in CLASSES?

Turoturom's picture

I created an alernative lower case e and an alternative lowercase l, designed only to be used as the first letter of any word that starts with either one. Is this possible to program in FontLab?

Nick Shinn's picture

Use "ignore".
It's in the Mac manual, page 873.

Turoturom's picture

Thanks Nick,

As I mentioned before I don't understand programing very much and this is why I am here...simple tasks I can do, so my new question is: Where and how should I type what says in the top of pag 873 of the manual? (in my specific case):

ignore substitute @LETTER e'
substitute e' by e.init

ignore substitute @LETTER l'
substitute l' by l.init

As you may asume I've already re-named my glyphs e.init and l.init.

Any hint will be welcomed


gargoyle's picture

Turoturom: Does your last paragraph mean I should eliminate everything I put in CLASSES cause I no longer need them or just leave all the ones I named .alt1?

Assuming most of your glyphs have only one alternate, and you're using predefined classes to code those alternates in a single rule (as in the example you referenced), then you'd want to strip those classes of any glyphs that have more than one alternate (including the first ".alt1"), and leave just the glyphs that have only one alternate. Since glyphs that have multiple alternates must be coded separately, leaving them in the original classes would be redundant and could possibly lead to conflicts.

If you're following Adam's example (which may well be better practice, especially if you have many glyphs with multiple alternates), it would make more sense to scrap your original classes completely and create new classes containing the alternates for each glyph. So instead of classes like
@salt1 = [a b c d e ...];
@salt2 = [a.alt1 b.alt1 c.alt1 d.alt1 e.alt1 ...];

you'd have classes like
@a_salts = [a.alt1 a.alt2 a.alt3 a.alt4];
@b_salts = [b.alt1 b.alt2];
@c_salts = [c.alt1];

and the corresponding rules in the salt feature would be
sub a from @a_salts;
sub b from @b_salts;
sub c from @c_salts;

Note that using "from" rules requires that even lone alternates be referenced by a class, either predefined (as above), or inline (as in sub c from [c.alt1];).

twardoch's picture

A short explanation for the classes:

1. You can define named classes in the FontLab Classes panel.

2. You can define named classes in the lower part of the OpenType panel. Then you use the syntax @a_salts = [a.alt1 a.alt2 a.alt3 a.alt4]; -- in fact, when you define the classes in the Classes panel, when FontLab Studio is compiling feature definitions, it does (behind the scenes) write the classes using the @NAME=[...]; syntax, and then the features are compiled. Note that in the Classes panel, you don't use the "@" in front of the name, but in the OpenType panel, you do.

3. You can define unnamed inline classes as in "sub a from [...];"

These are all interchangable. You can define your "a_salts" OpenType class in the Classes panel, or the "@a_salts" class in the lower part of the OpenType panel, or you can write an unnamed class right in the "salt" feature definition ("sub a from [...];"). That doesn't matter.

Indeed, the "sub ... from ..." syntax ALWAYS uses a single glyph before the "from" and a class after the "from" keyword.


Turoturom's picture

Thanks so much Gargoyle and Adam. You guys are great, if you ever need tips on graphic design just ask...and my last consultation I wrote above, which I re-write here:

I created an alernative lower case e and an alternative lowercase l, designed only to be used as the first letter of any word that starts with either one. I called them e.init and l.init.

I do not grasp the "ignore substitute" from the FontLab manual that Nick Shinn suggest...I read it but it does not give examples for someone not familiar with programing on how to write. Can you give me this last advice?

My font will be called Masana and I will soon post it on fontspace.

Thanks in advance

Mario Arturo

gargoyle's picture

Except for the missing semicolons, the code in your above post appears to be correct. As for where to put it, the calt feature (Contextual Alternates), or possibly cswh (Contextual Swash), seem most appropriate. Add the feature to list in the OpenType panel as you did for your other features, then add the rules.

Like the manual explains, you must define the @LETTERS class to contain every glyph that might appear as part of a word (which may include alternates). That can be done using the Classes panel, adding the class and dragging in the glyphs.

To better explain the contextual code:

ignore substitute @LETTER e';
substitute e' by e.init;

Loosely translated:
Ignore the following substitution rules if there's any letter preceding the glyph 'e'; if there's not, substitute the glyph 'e' with the glyph 'e.init'.

For a broader understanding of the logic behind contextual substitution rules, it might help to read over that entire section of the manual, beginning on page 870.

twardoch's picture

There is some more explanation and discussion here:
(although it's for final forms, not initial forms)
and in the link that is included in that thread.


Turoturom's picture

Hi guys, I am doing something wrong with the initial e and l. This is what I am doing:

I open classes panel, hit the + at the bottom left choose "OpentType", write the bottom box of classes:

then drag my e.init1

Repeat and then write:

then drag my l.init1

I think this is where I fail because:
LETTER e': e.init1 changes to: LETTER_e_: e.init1
LETTER l': l.init1 changes to: LETTER_l_: l.init1

Then I go to OpenType panel and hit the + and type gsub and on that top window I write:

feature gsub {
ignore substitute @LETTER e';
substitute e' by e.init;
ignore substitute @LETTER l';
substitute l' by l.init;

} gsub;

and get this error:
[FATAL] glyph class not defined (text was "@LETTER")

It does show in the preview panel but it changes the l and the e in every case not just at the begining of the word

WHY DON'T I GET THIS?...I am not blonde! Please HELP!


the classes with alternative letters works like a charm THANX, I tried using the same coding for alternative ligatures (for example ss, os)and it does not work. why? I did this:

@ss_salts = [ss.alt1];
@os_salts = [os.alt1];

and the corresponding rules in the salt feature:
sub ss from @ss_salts;
sub os from @os_salts;

THAT IS ALL, I hope the next time I write is BIG THANKS!!!!

eliason's picture

When gargoyle wrote the line

ignore substitute @LETTER e';

you should understand that as a line making an instruction about two different elements (separated by the space). It depends on you having a class named LETTER (*not* "LETTER e'") and says ignore the substitution of an e that follows anything in the LETTER class. Your LETTER class should, well, have all your letters in it!

gargoyle's picture

Like eliason said, LETTER is the name of the class, and inside it should go any glyph that would be considered a letter or part of a word -- any glyph that, if it were to appear before an 'e' or 'l', would trigger the "ignore" rule and prevent the substitution. At the minimum, the LETTER class in your Classes panel should include:

LETTER: 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

Add to that list any accented/international letters, ligatures, alternates, etc.

"GSUB" is the technical name of the OpenType table that contains all of the font's substitution features, not the name of any standard feature you should be using for substitutions. The "calt" feature (Contextual Alternates) would be a logical choice.

feature calt {
  ignore substitute @LETTER e';
  substitute e' by e.init;
  ignore substitute @LETTER l';
  substitute l' by l.init;
} calt;

Re: Alternative ligatures -- When you say "alternative ligatures" do you mean that you already have standard versions of those ligatures with the glyph names "ss" and "os"? If that's the case, your code should technically work, although it will only trigger a substitution if the actual ligatures are already present in the text. A better approach might be to have the substitution occur in the "liga" feature if one of the alternates has been substituted.

sub @s_salts @s_salts by ss.alt1;

Translated: substitute any pair of alternate 's'es with the alternate 'ss' ligature.

That may not be the ideal substitution, depending on how the alternates relate to the ligature, but hopefully hints at a potential solution. Also, the naming convention for ligatures is to place an underscore between the letters, i.e. "s_s" "o_s" "s_s.alt1" "o_s.alt1", but that makes no difference technically.

agisaak's picture

Also, the naming convention for ligatures is to place an underscore between the letters, i.e. "s_s" "o_s" "s_s.alt1" "o_s.alt1", but that makes no difference technically.

Actually, it does make a difference technically. If you use nonstandard names such as 'os' or 'ss', it will not always be possible for applications to reconstruct the original unicode values associated with the underlying text which may cause problems for searching, cutting and pasting text, etc. The underscore convention should always be followed.


Turoturom's picture

Hi, EVERY WORKS!!! now thanks to all of you. I did re-named all my ligatures with underscore between letters to be sure.

BUT, on the other hand I can not make work my alternative "os"

I have a (ligature) glyph named o_s and its alternative (swash) glyph called o_s.swsh1

I have nothing on Classes Panel for my swash letters and on my OpenType Panel I wrote:

feature swsh {
sub s from [s.swsh1];
sub t from [t.swsh1];
sub o_s from [o_s.swsh1];

} swsh;

the first two (s.swsh1 and t.swsh1) work perfectly; is that last one I am having trouble with. Once I get some advice on how to figure out that o_s.swsh1 I WILL BE DONE WITH MY FONT!!!!!

Thanks in advance!

Mario Arturo

agisaak's picture

Your 'swsh' feature won't affect the ligature o_s unless your 'liga' feature (or whichever feature you are using for ligature formation) precedes it.

Also, in cases where you only have a single alternate, there is no reason to use the 'sub X from [Y];' syntax -- you can just use 'sub X by Y;'.


Turoturom's picture

I AM DONE WITH MY FONT. Next week I will be posting it in FontSpace as Masana. I want to THANK ALL OF YOU (Adam, André, Eliason, Gargoyle and Nick) for your time and help.

Kind regards

Mario Arturo

Turoturom's picture

I regret to inform that I am stil not done. I was away on vacation and during that time I kept reviewing my font. Now I want to program an alternative last letter, in this case an alternative "s" which I named "s.fina1".

Will it work with the following?:

Classes panel includes:

LETTER: 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
plus accented/international letters, ligatures, alternates, etc.

OpenType Panel "GSUB":

feature calt {
  ignore substitute @LETTER s';
  substitute s' by s.fina1;
} calt;

Am I missing anything keeping in mind that after that final alternative "s" there might be a space, a period, a comma, or quotation marks, etc?

Thanks in advance

Mario Arturo

Scriptor Abbatiſſæ's picture

It appears that you have the class to be ignored on the wrong side of s' in the ignore command, so that you final 's' will never be substituted where 'ſ' follows another letter, but will only be seen where 's' is an isolated letter. Move the @LETTER class to the other side of s' and long 'ſ' will remain long whenever another letter follows, but change to final 's' when a space or punctuation follows.

The other way to do this is the way I'm doing it in the font I'm now working on:

sub s' @calt10 by s.calt;

#where @calt10 is the calss of all punctuation marks and spaces before which long 'ſ' is supposed to change to final 's'.

Turoturom's picture

Thanks Scriptor, but what character is this 'ſ'? I've never seen it before.

Scriptor Abbatiſſæ's picture

Oh sorry, long version of 's', (uni017F). I suppose since you had a final 's', I just assumed that the the long version of 's' were primary.

Turoturom's picture

It worked...thanks a mil. Check out Masana (this is the name of the font) on FontSpace by the end of the week if you want it.

phrostbyte64's picture

So how do you get to more that the first two alternates in CS4, if there are more than two alternates?

Syndicate content Syndicate content