Issue with contextual substitution in Adobe apps

Hello, I’m hoping someone can help with a difficulty I’m having with contextual substitution in Adobe Indesign, Photoshop and Illustrator.

I’ve read that text is treated differently between Adobe programs but the problem I’m having seems to be similar across them all.

This is my first typeface and the visuals below are far from crafted in terms of design, spacing, kerning etc. so please ignore that. My ambition is to create a specific-purpose typeface that substitutes a LOT of words and phases with alternate words and phrases. Also accounting for case (lowercase, all-caps and sentence case).

In Indesign, the issue is this:
— when ‘Adobe Paragraph Composer’ is selected, characters added to extend a word/phase don’t work and the last character of the original word/phrase persists
— when ‘Adobe Word-Ready Paragraph Composer’ is selected, the extended characters work perfectly but wherever a space occurs in the original word/phrase there is a corresponding spacing error in the substituted word/phrase.

In the image below every word/phrase in the left column should change to the word ‘forever’ in the right column.

In Illustrator the issue is observed when switching between ‘Adobe single-line Composer’ and ‘Middle Eastern & South Asian Every-line Composer’ (which needs to be activated through Illustrator preferences).

In Photoshop the issue is observed when switching between ‘Latin and East Asian Layout’ and ‘Middle Eastern and South Asian Layout’.

I’ve arrived at the code below which works almost exactly as desired in programs other than Indesign, Illustrator and Photoshop.

ignore substitute @alpha [N n]’ [O o]’ [W w]’, [N n]’ [O o]’ [W w]’ @alpha;
sub [N n]’ [O o] [W w] by [F.alt f.alt];
sub [F.alt f.alt] [O o]’ [W w] by [O.alt o.alt];
sub [F.alt f.alt] [O.alt o.alt] W’ by R.alt E.alt V.alt E.alt R.alt;
sub [F.alt f.alt] [O.alt o.alt] w’ by r.alt e.alt v.alt e.alt r.alt;
sub [Q q]’ [U u] [I i] [Z z] [Z z] [E e] [D d] by [F.alt f.alt];
sub [F.alt f.alt] [U u]’ [I i] [Z z] [Z z] [E e] [D d] by [O.alt o.alt];
sub [F.alt f.alt] [O.alt o.alt] [I i]’ [Z z] [Z z] [E e] [D d] by [R.alt r.alt];
sub [F.alt f.alt] [O.alt o.alt] [R.alt r.alt] [Z z]’ [Z z] [E e] [D d] by [E.alt e.alt];
sub [F.alt f.alt] [O.alt o.alt] [R.alt r.alt] [E.alt e.alt] [Z z]’ [E e] [D d] by [V.alt v.alt];
sub [F.alt f.alt] [O.alt o.alt] [R.alt r.alt] [E.alt e.alt] [V.alt v.alt] [E e]’ [D d] by [E.alt e.alt];
sub [F.alt f.alt] [O.alt o.alt] [R.alt r.alt] [E.alt e.alt] [V.alt v.alt] [E.alt e.alt] [D d]’ by [R.alt r.alt] ;

sub [A a]’ space [H h] [O o] [L l] [I i] [D d] [A a] [Y y] by [F.alt f.alt];
sub [F.alt f.alt] space’ @uppr [O o] [L l] [I i] [D d] [A a] [Y y] by O.alt;
sub [F.alt f.alt] space’ @lowr [O o] [L l] [I i] [D d] [A a] [Y y] by o.alt;
sub [F.alt f.alt] [O.alt o.alt] [H h]’ [O o] [L l] [I i] [D d] [A a] [Y y] by [R.alt r.alt];
sub [F.alt f.alt] [O.alt o.alt] [R.alt r.alt] [O o]’ [L l] [I i] [D d] [A a] [Y y] by [E.alt e.alt];
sub [F.alt f.alt] [O.alt o.alt] [R.alt r.alt] [E.alt e.alt] [L l]’ [I i] [D d] [A a] [Y y] by [V.alt v.alt];
sub [F.alt f.alt] [O.alt o.alt] [R.alt r.alt] [E.alt e.alt] [V.alt v.alt] [I i]’ [D d] [A a] [Y y] by [E.alt e.alt];
sub [F.alt f.alt] [O.alt o.alt] [R.alt r.alt] [E.alt e.alt] [V.alt v.alt] [E.alt e.alt] [D d]’ [A a] [Y y] by [R.alt r.alt];
sub [F.alt f.alt] [O.alt o.alt] [R.alt r.alt] [E.alt e.alt] [V.alt v.alt] [E.alt e.alt] [R.alt r.alt] [A a]’ [Y y]’ by .notdef;

sub [O o]’ [N n] [E e] space [D d] [A a] [Y y] by [F.alt f.alt];
sub [F.alt f.alt] [N n]’ [E e] space [D d] [A a] [Y y] by [O.alt o.alt];
sub [F.alt f.alt] [O.alt o.alt] [E e]’ space [D d] [A a] [Y y] by [R.alt r.alt];
sub [F.alt f.alt] [O.alt o.alt] [R.alt r.alt] space’ @uppr [A a] [Y y] by E.alt;
sub [F.alt f.alt] [O.alt o.alt] [R.alt r.alt] space’ @lowr [A a] [Y y] by e.alt;
sub [F.alt f.alt] [O.alt o.alt] [R.alt r.alt] [E.alt e.alt] [D d]’ [A a] [Y y] by [V.alt v.alt];
sub [F.alt f.alt] [O.alt o.alt] [R.alt r.alt] [E.alt e.alt] [V.alt v.alt] [A a]’ [Y y] by [E.alt e.alt];
sub [F.alt f.alt] [O.alt o.alt] [R.alt r.alt] [E.alt e.alt] [V.alt v.alt] [E.alt e.alt] [Y y]’ by [R.alt r.alt] ;

ignore substitute @alpha [A a]’ [S s]’, [A a]’ [S s]’ @alpha;
sub [A a]’ [S s] by [F.alt f.alt];
sub [F.alt f.alt] S’ by O.alt R.alt E.alt V.alt E.alt R.alt;
sub [F.alt f.alt] a’ by o.alt r.alt e.alt v.alt e.alt r.alt;

Any help with this would be greatly appreciated.

A few thoughts:

  • The classic Adobe Paragraph Composer ignores certain features, e.g. ccmp, and is very limited when it comes to contextual substitutions. Hence, it is no surprise that OT features will work differently in different composers. You may find workarounds by finding a different feature that works in both composers, and you may rewrite the

  • Substituting spaces is risky, because layout engines may treat them differently from other glyphs. Looks like InDesign still regards it as space, because that is what was entered, hence the ‘space errors’ in your screenshot.

  • You are doing things with features that OT features have not been intended for, namely so-called semantic exchanges, i.e., one glyph assigned to a Unicode for another assigned to a Unicode. An engine may not expect that, so there is no guarantee it will work everywhere. And there is little you can do about it from within a font, because you cannot predict what an app will do with the data stored in your font.

Thanks @mekkablue . I did suspect I was venturing into sketchy territory with space substitution. Omitting phrases with spaces isn’t a deal breaker though.

Do you know of any documentation on Adobe Paragraph Composers capability? I’ve had a hunt around with little success.

Regarding possible workarounds that may work across different composers, are there any potential features you had in mind that I could start with? No worries if not.

Perhaps rlig, or calt… but the classic composer ignores one-to-many substitutions altogether. Maybe just do not pay so much attention to the classic Adobe Composer. It is only there for historic purposes.

Just wanted to drop back and say thanks @mekkablue for your help with this.

In case it’s valuable for anyone else I got around my ’space error’ issue by only substituting spaces with characters with a width equal to that of the space. Which in my case was any a-z glyph other than i, m and w.