Ignoring flag for set of glyphs in a substitution

Bahman EslamiBahman Eslami Posts: 73
edited October 2017 in Technique and Theory
I will explain this thoroughly, bear with me even if you know the facts already. As you might know there is a way to ignore marks when it comes to substitute a glyph with another one in case any mark gets in between the sequence of glyphs you're intending to match. Take the following glyph sequence for example:

lam.init kasra alef.fina

Let's say in the above sequence the kasra is a mark and the rest are base glyphs. I can use the IgnoreMarks flag in the OpenType feature syntax in a case I want to match the following substitution on the above glyph sequence:

sub lam.init alef.fina by lam_alef;

So even there is a mark (kasra) between lam.init and alef.fina in the top glyph sequence, the substitution will occur. Let's say I have a glyph like tatweel (kashida) that I want to ignore in all glyph sequences, even when it comes to contextual situations. If I define that glyph as a mark in GDEF, then shaping engine will treat it as a mark and some unexpected results will occur. The question is: have you came across a glyph which is inserted in the glyph sequence like a connection, and it didn't have any function other than fill in shape and you wanted to ignore all the time when it comes to contextual substitutions? This set of glyphs that I want to ignore could be considered as dummy glyphs that will be inserted in between all the letters as a connection and I want to ignore them when it comes to contextual substitution. Solutions in methods other than OpenType feature syntax are also welcome.

Thanks in advance

Edit: spelling

Comments

  • You can use mark filtering sets, I believe the glyph do not need to be marks for it to work.
  • I presume when using UseMarkFilteringSet, only the glyphs inside the class should be matched and the rest are ignored. If what you're implying is to create a class and use UseMarkFilteringSet to only include the class glyphs in the substitution, then this is not having any effect in my situation. Could you provide an example?

    What I tried and only worked so far was to define the glyphs that I want to be ignored as ligatures in the GDEF and use the IgnoreLigatures lookup flag to ignore them in the glyph sequence. Of course this seems to work it comes with limitations that I can't have any ligatures in the context and I have no idea what are the consequences in different shaping engines. So far it works in CoreText and HarfBuzz only.

    I still don't understand why such behavior is not implemented in OpenType.
  • Bandar RaffahBandar Raffah Posts: 5
    edited October 2017
    So there is a crazy way but it breaks kerning unless you take an extra care of that yourself.. but as Reh is the major kerning letter and it does not connect with proceeding letters then it is ok maybe..

    The way is:
    1- Turn every typed glyph that needs a special connection after it into itself and a ghost glyph after it that's .medi and zero width, like this:
    sub lam-ar.init by lam-ar.init ghost.medi; 
    
    # Do this for all other glyphs that will connect also..
    ghost.medi is just a normal glyph you add and rename to that and make zero-width, nothing special about it at all..

    Turning one into multi needs to be coded one by one, no classes accepted in this syntax and can't be done contextually, unfortunately. and you will have to do this line of code for Every letter that got a spacial connection of yours whether it needs it or not, but it seems that you need it for every connection anyway..

    2-Then contextually turn the ghost.medi into the exact shape of the connection that you want, like:
    sub lam-ar.init ghost.medi' yeh-ar.fina by lam-yeh-connection.medi;

    3- Then just pass the ghost glyph when you don't need it? like:

    sub lam-ar.init' ghost.medi alef-ar.fina' by lam_alef-ar;

    الحمد لله ..  Allah inspired me with this method for some crazy effects i'm working on in one of my fonts, where all opentype features didn't help.. I hope you find it useful :)

    In my own tests, the cursor ignores these ghost glyphs and substituted special connections (maybe because they are all zero width and the spacial connections are zero width and sticking out with negative side bearing) so when i forward or backward the cursor it only stops at base letters and tashkeel marks.. and that's a great thing الحمد لله .. 

    I'm not sure if this is what you need, but it is what i needed..
  • Maybe we should ask a more basic question; what kind of substitutions you want to ignore the Kashida in? Can you give some examples?
  • For example, Ruqaa style does not have Kashida at all, so I turned the Kashida into a blank zero width glyph and gave it a mark class. This way no matter how many Kashida characters the user will insert they will be invisible and won't interfere with my substitutions.
  • Bahman EslamiBahman Eslami Posts: 73
    edited October 2017

    Bandar your approach seems interesting. It entails adding extra ghost glyphs that also is extra data. I’m trying to avoid adding anything that would make the glyph set larger. This is not only a matter of data reduction, it’s also about approaching it in a clean systematic way. Also it doesn’t address the issue I’m having to ignore a set of arbitrary glyphs in context.

    Khaled Hosny:
    Maybe we should ask a more basic question; what kind of substitutions you want to ignore the Kashida in? Can you give some examples?

    For example, Ruqaa style does not have Kashida at all, so I turned the Kashida into a blank zero width glyph and gave it a mark class. This way no matter how many Kashida characters the user will insert they will be invisible and won't interfere with my substitutions.

    What I'm doing is eliminating the connecting part in design of the letters and insert them in between the letters after. You might ask why I chose to design connection as a different glyph. This is because I found a repeating pattern in Arabic letterforms and a changing  pattern. So I categorized the changing shapes as connections and this approach reduced the number of glyphs and also made it possible to design the typeface in more systematic way. This also enables me to create kashida by just stretching the connections in a Variable font axis. Also I can chose which letter to stretch and which ones don't in the axis.

    This method works perfectly fine until Kashida comes in. Adding different lengths of kashida per connection doesn’t seem like a right approach so I want to ignore the kashida altogether. Although it would be very interesting if it was possible to change an axis value in a variable font when a character like Kashida comes in.

    My design also uses cursive attachment so your approach to define the connections as marks causes the connections to jump around as you can see in the picture below.






    I was able to ignore kashida by defining it as ligature and ignore it in the substitution using the IgnoreLigatures lookup flag. Now I’m at a stage that I want to control dots using contextual mark positioning. Mark positioning is processed after the substitutions so I also have to include the connections in the context of mark positioning if I can't ignore them. It also makes the file larger. Take a look at the following glyph sequence for example:

    beh.init dotBelow beh.init_jim.medi.conc jim.medi dotBelow jim.medi_zeh.fina.conc zeh.fina dotAbove

    As you can see there is a connection between every letter. So if I want to change position of dotAbove if jim.medi and beh.init comes before the zeh.fina for example, I have to include all the the connections in the context. Please consider that this is only an example and in reality there are situations where some collisions might happen and I need to match those glyphs in context. In these situations including the connection in context is completely redundant; the letters are already defining the context and if the context is long then there would be problems in terms of rendering or compiling. So right now I’m stuck to define these connection as Ligature until another solutions comes in. I still believe that in OpenType there should be a way to ignore a set of arbitrary glyphs in substitution or positioning. It's a pity not being able to do so because it makes me come up with a wacky workaround that might not work everywhere. Maybe an IgnoreClass would have been more rational? UseMarkFilteringSet does not have same effect. I still wonder if anyone else wanted to ignore sets of glyphs other than base glyphs or ligatures and they gave up their design because OpenType doesn't work that way.

  • John HudsonJohn Hudson Posts: 2,955
    Khaled,

    You can use mark filtering sets, I believe the glyph do not need to be marks for it to work.
    I think you're wrong there. As far as I know, mark filtering sets are still expected to contain only glyphs identified as marks in GDEF.

    Andrew Glass and I have had conversations about making it possible to define arbitrary glyph groups for exclusion from lookup processing. It's an idea I'd like to revisit, although there wasn't a lot of enthusiasm last time we raised it with Microsoft.

  • So we have ignoreMarks/useMarkFilterimgSet and ignoreBase but no useBaseFilteringSet?
  • John HudsonJohn Hudson Posts: 2,955
    Correct.
Sign In or Register to comment.