Build: Handwriting OT font contextual troubles

alan's picture

This post really should be in "Build", but for some reason I'm not allowed to start a topic there. News to me. Anyway ...

Hi everyone,

I'm looking for a little bit of advice on a handwriting font I'm currently working on. The font uses contextual substitution to "flip" through a series of alternates for each glyph, much like LettError's Kosmik, if you're familiar with that. Instead of three variations of each letter, there are nine, but the idea is the same: a kind of controlled randomness (which really isn't random at all).

In addition to the nine variations of each letter, some letters have up to three initial forms and/or up to three final forms. There are also quite a few ligatures, which themselves may have initial and final forms. The ligatures are always constructed of only two letters, no more.

One last detail about the design of the font: it is unicase, so I'm converting all uppercase input to lowercase, for simplicity.

**** Skip down to the next section if you already know how Kosmik works ****

Here's how it works:

First I ask the font to convert all of the letter combinations that will *always* result in a ligature (that is, there are at least nine variations of that ligature). These combinations are: en, er, ju, on, or, te, th, tt. This is contained in the 'liga' feature.

Then I ask the font to begin swapping alternates, using the 'calt' feature. Each glyph belongs to a class of glyphs. There are nine alternates of each letter, so each of the nine glyphs gets put into a separate class. All of the "default" glyphs get put in the "SET_ZERO" class; all of the glyphs ending in ".alt1" get put into the "SET_ONE" class; glyphs ending in ".alt2" are put in the "SET_TWO" class, and so forth.

My 'calt' feature says this:

# first, get rid of all that nasty uppercase stuff
sub @UPPERCASE by @LOWERCASE;

# then use the same method that Kosmik uses to "flip" through classes glyphs
sub @SET_ZERO @SET_ZERO' by @SET_ONE;
sub @SET_ONE @SET_ZERO' by @SET_TWO;
sub @SET_TWO @SET_ZERO' by @SET_THREE;
sub @SET_THREE @SET_ZERO' by @SET_FOUR;
sub @SET_FOUR @SET_ZERO' by @SET_FIVE;
sub @SET_FIVE @SET_ZERO' by @SET_SIX;
sub @SET_SIX @SET_ZERO' by @SET_SEVEN;
sub @SET_SEVEN @SET_ZERO' by @SET_EIGHT;

So, if a user types "mmmmm", they will actually get "m m.alt1 m.alt2 m.alt3 m.alt4". This should be nothing new to many of you.

Please note that the line:
sub @SET_EIGHT @SET_ZERO' by @SET_ZERO;
is omitted, because returning to the original set is understood implicitly.

Every time the user types a glyph, the font looks back at the last glyph, figures out what class it belongs to, and uses that information to determine which variant of the next glyph to place down (at least, that's how I think of it). Even the space character is included in this merry-go-round (yes, there are nine variations of the space character). That way, typing "yes yes yes" won't result in the same three glyphs appearing over and over.

**** This is the next section, welcome back ****

Thanks for your patience if you've gotten this far. Now I'll try to describe some of the issues I've run across.

In order for the flipping to work correctly, every single glyph needs to belong to one of the nine classes (SET_ZERO through SET_EIGHT). That way, when the next letter is layed down, the font knows which version to use by looking at the class of the last glyph. If there were a glyph that ended up on the page which did not belong to any of the nine classes, the next glyph would have no point of reference, and would default to the first variant of that letter. This could have the inconceivably catastrophic effect of the same glyph appearing twice within a relatively small proximity!!!! AAAAAAAAAAHHHH!!

It's something I'd like to avoid. The problem is that not all of the ligatures have nine variations. I have a "tz" ligature that only exists in one form. I can easily write a lookup that says, "whenever an 'a.alt5' is followed by a 't.alt6' and then a 'z.alt7', replace the 't' and 'z' with 't_z', unless it's at the end of a word". And so forth. These specific cases are tedious, but simple to write, as shown in the Bickham Script feature file that Adobe released recently.

But! The "tz" ligature must belong to one of the nine classes so the flipping can continue undisturbed. But there is only *one* "tz" ligature, and the classes used for flipping must each contain the same number of glyphs, or flipping is not allowed!

It's the same case for initial and final forms: not all letters have three of each, but the glyphs all have to belong to a specific class, and the classes cannot have different numbers of glyphs contained within them.

One way to simplify things would be to create the same number of alternates, initials, and finals for every single letter that can be typed with this font. That would eliminate the need to worry about differing numbers of alternates and specifying certain cases where they can and cannot appear. However, this is a handwriting font created from an actual handwriting sample, and making lots of extra letters and ligatures that are convincing is a non-trivial task. I'm willing to do it, if there isn't a way of resolving these issues with OT features.

I'm hoping to work out all the OT features *before* cleaning up the auto-traced characters and tidying up the font, so right now the font is just a cesspool of mismatched character shapes and sizes and weights, with an external text file serving as my underground mad-scientist OT laboratory.

If anyone has any insight, I would greatly appreciate it.

Thanks,
Alan

pablohoney77's picture

hmmm, i'm in no means an expert at this, but here's a bit of code i wrote trying to do something similar, except i only had 2 alternates for lower case letters that switched off with eachother.

feature calt {
sub @class0 @class0' by @class1;
sub @class1 @class1' by @class0;
sub @class0 space @class0' by @class1;
sub @class1 space @class1' by @class0;
sub @class0 space @UC @class0' by @class1;
sub @class1 space @UC @class1' by @class0;
} calt;

one thing in here is that i didn't make 2 variations of the space character, but wrote code to "skip over" the space character. This should work for your t_z lig too just make a class of characters that only have one form and place them in the code above where it says "space". But it's late and maybe that won't really work...
Also, it's too late for me to think this through, but what happens if you put the t_z lig in every set?
okay, i'll go to bed and let the pros sort out the confusion i caused in the morning. nite!

Thomas Phinney's picture

If that t_z lig is the only problem glyph, you could always have 9 different versions of it. Sure, they all *look* the same, but that would make the substitutions work cleanly.

T

alan's picture

Yes, I could make 9 versions of the t_z, but that is one of 30-some ligatures that don't have 9 versions yet. So that's a bit of added work, and on a philosophical level it's not ideal for what I'm doing. But I think that's a very reasonable suggestion, and would save my brain a bit of work, if not my hands.

As for including the t_z and other ligatures in every glyph class, I don't really think that would work. The OT font is not saying, "does t_z belong to SET_FOUR? ... yes". It's saying, "which class does t_z belong to? ... um, all of them?" So I don't think that will be the best solution in this case.

Thanks for your feedback!

Miss Tiffany's picture

Thread to be moved to the BUILD area.

Syndicate content Syndicate content