Using constraints and assertions for font production

GPOS/SUB/DEF shaping assertions are of interest to me. That might make its way into a future plugin. For now, @SimonC has an implemented as similar idea, see Better Fonts Through Test-Driven Development | Font and Text Technology (there are related project at the end of the page).

1 Like

I don’t know whether it was this post that inspired me directly, or just the problem that I’ve been working on, but I had a great idea about assertions this morning.

I have this very complex Nastaliq font, and I have this very powerful layout rule generation language - two lines of code:

Feature rlig {
  DetectCollisions top;
  DetectCollisions bottom;

generates 20,000 lines of Adobe FEA.

Obviously with that many effects it’s hard to keep track of what happens when you add a new rule and what side-effects it might have when it interacts with other rules. So far I’ve been handling this by using my shaping regression tests, but that’s annoying. You have to re-generate the rules, build the font (which takes a long time), and then run the shaping tests.

I think I’m going to add assertions to the layout language, so that it does not generate rules which break the invariants:

Feature rlig {
  DetectCollisions top;
  DetectCollisions bottom;
  Assert DoesNotCollide "جیر یر"; # I know this case works here

  # ... do some other stuff which fixes a problem ...

  Assert DoesNotCollide "جیر یر"; # Check it still works
  Assert DoesNotCollide "ان چر";  # And also check that I solved the problem

This looks really cool! (Although I don’t know much about Arabic).

Of course, wherever possible, any solution that enforces things are what they are supposed to be (excuse my vague wording) is even better than an assertion-type feature. In modern font editors like Glyphs, we have a multitude of these automatisms already. So, I am not suggesting to turn automatisms into assertions. The question is, have we (the Glyphs team and independent programmers) overlooked things because they cannot be automated/enforced, but would be possible to control via assertions?

I am working on a plugin that checks whether a predicate matches a glyph class. Something like adding

#= $["top" in tags AND "as case" in tags]

at the top of a class in the feature editor that verifies that the set of glyphs matched by the predicate is that same as the set of glyphs added manually. So, essentially the same as writing the $[…] token and letting Glyphs automatically fill the class, but with manual control over the glyph order for usage like

sub @SomeClass by @SomeClassAlt;

where both the class membership and order within the class are important. Or the same for lookups, checking that every member of a predicate is handled as input to the lookup:

lookup some_lookup {
    #input= $["precomposed" in tags]
    sub aacute by a acutecomb;
    # ...
} some_lookup;

Inline assertions for shaping sound like a great idea. Simple rules could be

sub f l by fl;
#assert "f l" [fl]

and custom check-functions would be handled like

ignore pos @H1 @DM' @H1;
pos @H1 @DM' <$dmShift12 0 0 0>;
pos @DM' <${dmShift12*-1} 0 0 0> @H1;
#assert no_collision "t͡ʃ" [t=0|uni0361.narrow=0|esh=2]

I like how inline assertions act as documentation and are easier to edit while working on feature code.

Certainly. But “would be possible to control via assertions” can come at a significant time-investment setting assertions up and updating them when needed. If they save more time than they consume, it’s worth investigating. That’s also why I focus a lot on interaction speed with the Guten Tag plugin; if tagging were too slow, I would have stopped tagging my glyphs already.

You should just move to Fez: Substitute @SomeClass -> @SomeClass.alt;. :wink:

Naming does not suffice to describe glyph relationships in my projects, hence the tagging. But integrating Fez into Glyphs would also be interesting. Main issue I see there is that Fez works on individual fonts while Glyphs’ feature code editor works on a font family.