Ending ligature

Mario Arturo
Mario Arturo Posts: 10
edited January 2016 in Type Design Software
Hello to all,

I am almost finished revising one of my script fonts on FontLab. There is an alternative ending "s" labeled "s.final.1". Under OpenTypeface window, I have it under "calt" feature, it reads like this:
 
ignore substitute s' @LETTER';
substitute s' by s.fina1;

This works fine.

BUT, I wanted to do the same with words ending with "os" so I created a gliph for this ligature called "o_s.fina1". Keep in mind there is also a regular ligature called "o_s" already set up to always subtitute "o" + "s" which works fine. But my final (o_s.fina1) ligature does not. I have set it up, also under calt, like this:
 
ignore substitute o s' @LETTER';
substitute o s' by o_s.fina1;

and as I mention, it does NOT work and I don't understand why.

I would appreciate any tips to make it work, please.

Kind regards






Comments

  • Mark Simonson
    Mark Simonson Posts: 1,736
    edited January 2016
    This should work:

    ignore substitute o_s' @LETTER;
    substitute o_s' by o_s.fina1;

    Be sure that your calt feature comes after your liga feature, otherwise o_s will never be found when calt runs.
  • Also, you can type "sub" instead of "substitute". Saves a bit of time.
  • Hi Mark, thanks BUT it did not work. I am attaching an image so you can see the whole thing.

    Regards

  • I think you need separate lookups for each ignore you want to use. Even though you're not using Glyphs you may find their explanation helpful. The OpenType cookbook too. 
  • Mark Simonson
    Mark Simonson Posts: 1,736
    edited January 2016
    Also, don't put space between the tick mark and the thing it's marking. The tick mark is a way to indicate what gets substituted.

    AND, only one glyph or class in a substitution may be marked in this way. On a couple of your "ignore" lines, you've got tick marks on more than one thing. It should only be attached to the glyph or class you intend to substitute.
  • Thanks Craig and Mark, I will take a closer look at it tonight.
  • Kent Lew
    Kent Lew Posts: 938
    Shouldn’t need multiple lookups for every single ignore sub. The different groups of initial and final rules, however, should probably be split up into separate lookups, since they have different lookbehind and lookahead structures.

    Plus, this could be simplified tremendously by using classes.

    Something like this should work:

    feature calt {
    lookup initials {
    ignore sub @LETTER [e egrave eacute ecircumflex edieresis l]';
    sub [e egrave eacute ecircumflex edieresis l]' by [e.init1 egrave.init1 eacute.init1 ecircumflex.init1 edieresis.init1 l.init1];
    } initials;
    lookup finals {
    ignore sub [s o_s]' @LETTER;
    sub [s o_s]' by [s.fina1 o_s.fina1];
    } finals;
    } calt;

    Naming and defining those classes separately would make writing and editing easier.
  • Thanks Ken. I will follow what you suggest. Great tip on the shortcuts of what I was writing. Regards
  • I mean, Thanks Kent!
  • Hi Kent,

    I pasted your text and added a few more. I followed your advise created a class for init with l and e, é, è, ë, ê. Also a class for fina for s, os, ós, òs, ös, õs, ôs.

    The inital l and the initial e work with all letters except with the regular l and e themselves, meaning I can write "lot" and "eat", but not "let", "ela" "eel", nor "llet"

    Also, the final s does work but os and its derivatives do not. PLEASE HELP!

    This is what I wrote (or pasted) based on your text, (I do not get errors when I compile):

    feature calt {
        lookup initials {
            ignore sub @LETTER [e egrave eacute ecircumflex edieresis l]';
            sub [e egrave eacute ecircumflex edieresis l]' by [e.init egrave.init eacute.init ecircumflex.init edieresis.init l.init];
        } initials;
        lookup finals {
            ignore sub [s o_s ograve_s oacute_s ocircumflex_s otilde_s odieresis_s]' @LETTER;
            sub [s o_s ograve_s oacute_s ocircumflex_s otilde_s odieresis_s]' by [s.fina o_s.fina ograve_s.fina oacute_s.fina ocircumflex_s.fina otilde_s.fina odieresis_s.fina];
        } finals;
    } calt;

    thanks in advance

  • Kent Lew
    Kent Lew Posts: 938
    There is an extraneous semicolon in the ignore sub in your first lookup, in between the @LETTER and the class. That could be prematurely terminating the ignore sub, so that the main sub rule is not actually contextualized and all occurrences of the targets then get replaced.

    Regarding the finals lookup, the o_s et al. substitutions will only work if the liga feature comes before the calt feature, so that the ligatures are already present in the text stream to be targets for the calt lookups. (Mark mentioned this important condition in his first response.)

    I *think* those are the causes of your problems.
  • Hi Kurt, I am a just a humble graphic designer... I took out the extraneous semicolon and the final os and its variables still do not work. This is what I have now:

    feature calt {
        lookup initials {
            ignore sub @LETTER [e egrave eacute ecircumflex edieresis l]';
            sub [e egrave eacute ecircumflex edieresis l]' by [e.init egrave.init eacute.init ecircumflex.init edieresis.init l.init];
        } initials;
        lookup finals {
            ignore sub [s o_s ograve_s oacute_s ocircumflex_s otilde_s odieresis_s]' @LETTER;
            sub [s o_s ograve_s oacute_s ocircumflex_s otilde_s odieresis_s]' by [s.fina o_s.fina ograve_s.fina oacute_s.fina ocircumflex_s.fina otilde_s.fina odieresis_s.fina];
        } finals;
    } calt;


  • It all looks fine to me, but ensure you have the feature assigned to the Latin script:

    feature calt {
     script latn; # Latin
      lookup initials {
    etc.
  • Hi Erwin, That doesn't do it either. Thanks anyways.
  • It works just fine over here, so maybe the solution is not meant for your problem.

    Can you provide an example that shows what you want to achieve?
  • The best way to diagnose a dysfunctional behavior when you're dealing with string of glyphs in coding is just to explicitly write the expected behavior. Could you confirm is this what you wan to achieve:

    c a r s -> c a r s.final.1
    l a m p s -> l a m p s.final.1
    d o g s -> d o g s.final.1
    b r o s -> b r o_s -> b r o_s.final.1

    If that's right, is the liga feature is declared before the calt?

  • Hello, I am attaching a screen shot that explains what does not work for my ending os ligature and obs ligature. There is an individual final "s" that works with the rest of letters as you can see with my example of "is". I show what I have under Classes and what I have writen in the OpenType features. Thanks in advance.
  • Mark Simonson
    Mark Simonson Posts: 1,736
    edited February 2016
    Because your <liga> feature comes after <calt>, o_s will never be found when <calt> runs.

    What I would do in this case is, instead of doing substitutions of ligatures in <calt>, add a substitution for the results of <calt> in your <liga> feature. In other words, add "sub o s.fina by o_s.fina;" to <liga> and remove "o_s" and "o_s.fina" from your <calt> feature, and do the same for your other ligatures of alternates.

    OpenType substitutions work a bit like a search and replace macro in a word processor. The order is important. You have to be careful that what you're trying to match might not be there yet, or that it might have already been substituted with something else by an earlier lookup.
  • Mark Simonson
    Mark Simonson Posts: 1,736
    edited February 2016
    Alternatively, you could move <liga> up before <calt> like I suggested earlier in the discussion, in which case your <calt> feature should probably work as is.
  • Hi Mark, I followed your last sugestion (above) and it worked. Thanks. Now I have the matter of the inital l and the initial e:


    The inital l and the initial e work with all letters except with the regular l and e themselves, meaning I can write "lot" and "eat", but not "let", "ela" "eel", nor "llet.
    I think that's about it!

    Thanks


  • The approach that works for us is to first include init related lookups, then fina, and at last lookups which relate to all characters between first and last character of words.

    This way you don't have to define exceptions, which make the OpenType features a lot easier to read and maintain.



    This forum topic at our website shows how it is done with FontCreator:
    http://forum.high-logic.com/viewtopic.php?p=26623#p26623

  • I'm not sure if this is it, but it looks like maybe your .init and .fina glyphs are not members of your @LETTER class.
  • Using fina, init and related features is the most convenient way to achieve this but the problem is that not all the text engines apply these features on all writing systems. As listed here safari ignores these features on Latin script but works just fine on Arabic.
  • Mark Simonson
    Mark Simonson Posts: 1,736
    edited February 2016
    That's because they were not intended to be used for Latin. You can use them in Latin fonts, and they "work", but not automatically and are not enabled by default. Latin text engines don't do any word boundary checks (at least not in a way that can be used by OpenType).