Text center alignment at the font level

Hello,

I'm hoping to get some insight on how one can mimic the behavior of center text alignment as in that of text applications. I need this to happen at the font level, within specified contexts. Effectively, the centering rules need to apply after a target character (let's say, "G" as in the image below); the text following would position appropriately, below and centered.


I can manage to position the bottom portion...that part's easy. It's the centering of these characters (as a unit) that is proving quite the challenge. Sure, centering one character is fairly simple: calculate the number of characters above and target the bottom portion at the mid point, apply an offset if necessary and it's done. But what happens when we're dealing with more than one character to center, and at that, how does one compensate for the varying character widths overall, for the top and/or bottom portion? 

Is this achievable within Open type rules?

Many thanks for reading.

Comments

  • Simon Cozens
    Simon Cozens Posts: 741
    edited January 2021
    In general, the answer is no, because the text layout system will also be imposing break points on the text: what if you have another word before your trigger character "AUTOMATICALLY CENTERING" - if shaping is done before layout the font has no idea whether it is entering the next line based on both words or if the layout engine will add a line break due to a narrow column and CENTERING will be the only word on the line. And indeed how can you guarantee that the layout system will insert a line break after G?

    In limited cases, it's possible (you would bin the glyphs into groups by their advance width and use a very large set of contextual rules to "count" the number of characters on each line - I do something very similar in this plugin), but tell me more about what you're trying to achieve and why and we'll see whether it's worth it.
  • If you can manage to get OpenType processing for both lines together (most environments process the features only per line, so the second line doesn’t know that there is a line before it) you can try it with contextual kerning. For each glyph in the first line, you move the caret by half its width to the right, and for each glyph in the second line, move it half its with to the left. 
  • Gentlemen,

    Thank you kindly for your replies.

    My apologies, I should have clarified:

    I'm not trying to invoke a line break. The text I'm entering is on the same line. i.e. Both words would be part of a single string of characters (no carriage returns or the like). Further to this (not shown above), both words would be separated by an underline separator which would also need centering. So, in effect, I'm trying to vertically align and center three items from a single input string; top text, underline, bottom text.

    I already have rules subbing in all of the above and placing them in the required vertical positions, calculating the number of lines (underscores) for the underline width, etc. It's the horizontal centering of this data (in unison and in relation to each other) that's the challenge. 

    I hope this explanation is clearer.

    Thanks again. 
  • Peter Constable
    Peter Constable Posts: 208
    edited January 2021
    For arbitrary strings with one character being a trigger for the "wrap", the only way I can think of doing something like this, off hand, would be to have a bunch of alternate glyphs that have the same outline and metrics and whose only distinction is to indicate an accumulation of advance width from preceding glyphs. 

    So, supposing (for simplicity) all default glyphs have an advance of 100 FUs, substitutions would replace

    [C.dflt E.dflt N.dflt ... T.dflt E.dflt ...]

    with

    [C.dflt E.200 N.300 ... T.dflt E.200 X.300 T.400]

    (After the "wrap" trigger, you'd start over, or you could even end those subs, though that might not be worth it.)

    Then, on the second line, you could do subs that start at the end accumulating the widths back to the beginning of that segment. (This is why subs in the above pass aren't relevant for the second segment.) So, you'd end up with something like

    [G.900.trigger T.400 E.300 X.200 T.400]

    Then you could do a positioning adjustment that has the trigger glyph variant, with accumulated width from the first line, as context, adjusting the width and position of the first glyph on the second line, with amounts determined by the variants of the trigger glyph and the first glyph that each reflect the total width of the respective segments (in this case, +250 pos x and +250 advance].

    Would I want to do this? Only as an experiment to see if what I outlined is actually feasible.
  • For arbitrary strings with one character being a trigger for the "wrap", the only way I can think of doing something like this, off hand, would be to have a bunch of alternate glyphs that have the same outline and metrics and whose only distinction is to indicate an accumulation of advance width from preceding glyphs. 

    So, supposing (for simplicity) all default glyphs have an advance of 100 FUs, substitutions would replace

    [C.dflt E.dflt N.dflt ... T.dflt E.dflt ...]

    with

    [C.dflt E.200 N.300 ... T.dflt E.200 X.300 T.400]

    (After the "wrap" trigger, you'd start over, or you could even end those subs, though that might not be worth it.)

    Then, on the second line, you could do subs that start at the end accumulating the widths back to the beginning of that segment. (This is why subs in the above pass aren't relevant for the second segment.) So, you'd end up with something like

    [G.900.trigger T.400 E.300 X.200 T.400]

    Then you could do a positioning adjustment that has the trigger glyph variant, with accumulated width from the first line, as context, adjusting the width and position of the first glyph on the second line, with amounts determined by the variants of the trigger glyph and the first glyph that each reflect the total width of the respective segments (in this case, +250 pos x and +250 advance].

    Would I want to do this? Only as an experiment to see if what I outlined is actually feasible.
    Thanks Peter,

    I have a sense of what you're saying. I'll have to reread it a few times as I'm still learning the Open Type ropes as it were. Although, I get the sense that there are several ways to do what I need, your approach being one of them. Just guessing, of course.

    Very much appreciate your reply!

  • Would I want to do this? Only as an experiment to see if what I outlined is actually feasible.
    Technically possible, maybe. But probably makes an awfully big font file, as well as being a crazy amount of work.
  • Nick Shinn
    Nick Shinn Posts: 2,208
    I tried to do something like this for nut fractions, but couldn’t get it to work.
    In the end, I made a few pre-composed glyphs for simple fractions, and left the rest to the normal diagonal-virgule method.
  • Ray Larabie
    Ray Larabie Posts: 1,432
    I made a typeface called Numbers with Rings where the user starts with one to six container glyphs. The container includes an offset. Following glyphs have the same offset. Each glyph checks the class of the glyph to the left and uses glyphs from the same class. Space character breaks the chain. It's different from what you're proposing but it centers text in a space...sort of.
  • Bernie Cossentino
    Bernie Cossentino Posts: 19
    edited January 2021
    Technically possible, maybe. But probably makes an awfully big font file, as well as being a crazy amount of work.
    Yep. My font is already fully loaded with other more important routines. This centering feature is just a wishful add-on. 

    I'm working on a method that's sort of what some of you suggested but shouldn't take too many rules to construct. In the end, it may only work in one direction. i.e. Centering may only happen on the bottom portion; the top portion would remain aligned left...it'll sort of work but I'm still working it out in my head :neutral:

    Thank you all for your thoughts and suggestions.
  • AbiRasheed
    AbiRasheed Posts: 238
    edited January 2021
    Just thinking out loud. Why do you need this at the font level? Shouldn't the user/designer be doing this instead which txt editors and design apps make it easy to do already numerically. If you were to do this at the font level, things like kerning, tracking, leading and even pt size would have to be factored in to make it useful I think, eh? Because if those parameters change then you'd have to optically align it. Is that possible with code? Or are you just trying to implement something that's only numerically possible?
  • Bemo said:
    I'm working on a method that's sort of what some of you suggested but shouldn't take too many rules to construct.
    Well, what I described would probably take lots of rules, not to mention glyphs.
    In the end, it may only work in one direction. i.e. Centering may only happen on the bottom portion; the top portion would remain aligned left...
    What? You want the top line to be centered within a column? OpenType lookups operate on glyphs, and the only available info at that level are the glyphs, which have no awareness of the width of the containing column. Not possible!
  • Just thinking out loud. Why do you need this at the font level? Shouldn't the user/designer be doing this instead which txt editors and design apps make it easy to do already numerically. If you were to do this at the font level, things like kerning, tracking, leading and even pt size would have to be factored in to make it useful I think, eh? Because if those parameters change then you'd have to optically align it. Is that possible with code? Or are you just trying to implement something that's only numerically possible?
    The target application can indeed center align text. That isn't the issue. The entry that I'm applying would become a symbol (single line non-spaced text block) on its own, which is why I can't rely on the application's alignment functions. There are other reasons I can't use the app's center alignment that go beyond the topic at hand (you'll have to trust me).

    Pair adjustments are always top of mind. With what I've got going so far, none of the usual glyph adjustments are affected.

    The result I'm going for won't be perfect; I'm well aware that it would take a ton of code to get that going 100% correctly in a font. I'd settle for 85-90% accuracy, which is just about where I'm at now.
  • Bernie Cossentino
    Bernie Cossentino Posts: 19
    edited January 2021
    Bemo said:
    I'm working on a method that's sort of what some of you suggested but shouldn't take too many rules to construct.
    Well, what I described would probably take lots of rules, not to mention glyphs.
    In the end, it may only work in one direction. i.e. Centering may only happen on the bottom portion; the top portion would remain aligned left...
    What? You want the top line to be centered within a column? OpenType lookups operate on glyphs, and the only available info at that level are the glyphs, which have no awareness of the width of the containing column. Not possible!
    I think you may have misinterpreted what I meant about "left aligned". The top portion simply wouldn't move, just the bottom portion.

    As for additional glyphs, I'm not adding any whatsoever.
  • I should add to what I described: the "additional glyphs" wouldn't necessarily need to be extra glyph entries in the 'glyf' table, but could be virtual glyph IDs used only in GSUB lookups for internal encoding of extra information. This might be done in a couple of ways.

    1. Single substitution of a real glyph ID with a virtual glyph ID that represents that glyph plus some extra info. A different virtual glyph ID would be used for each real glyph ID.

    2. Multiple substitution of a real glyph ID with a sequence of that same glyph ID plus a virtual glyph ID, the latter representing only the additional information. The same virtual glyph ID could be used for multiple real glyph IDs when the same additional information is to be indicated.
  • Bernie Cossentino
    Bernie Cossentino Posts: 19
    edited January 2021
    I should add to what I described: the "additional glyphs" wouldn't necessarily need to be extra glyph entries in the 'glyf' table, but could be virtual glyph IDs used only in GSUB lookups for internal encoding of extra information. This might be done in a couple of ways.

    1. Single substitution of a real glyph ID with a virtual glyph ID that represents that glyph plus some extra info. A different virtual glyph ID would be used for each real glyph ID.

    2. Multiple substitution of a real glyph ID with a sequence of that same glyph ID plus a virtual glyph ID, the latter representing only the additional information. The same virtual glyph ID could be used for multiple real glyph IDs when the same additional information is to be indicated.
    Thanks Peter,

    If by virtual glyph ID, you simply mean writing rules to call up (sub to/from)  the original glyphs, then I get it. Beyond that...I've got much to learn with all this lingo!

    In a nutshell, I've got multiple subs happening; one on the first glyph of the input string (applying an underscore and first character), and another multiple at the trigger glyph (inserting multiple underscores...offset...), then I'm able to input the bottom characters with another offset. The rest...centering, is still problematic; and as most of you have concluded, it'll require an insane amount of rules to tame.

    O.T. Anyone know what Open Type resources I should read up on, online classes and the sort? :)

    Thanks to everyone once again.

  • By "virtual glyph ID", I simply mean using an integer to reference a "glyph" in a lookup without there necessarily actually being a glyph with that glyph ID. E.g., suppose the font has 100 glyphs; I could specify substitutions to glyph IDs 101 – 65535 in a lookup as a temporary stage in the derivation as a way of carrying some extra information within the glyph sequence. Of course, the final glyph sequence would need to contain only real glyph IDs.
  • One extra thing about using virtual glyph IDs is that (AFAIK) it is outside what one can do with the usual friendly end-user font editors most people use to create fonts. Such tools generally operate on glyph names, and require them to actually be present in the font to successfully compile the features.

    I would love to be wrong about this, because it is a powerful tool for some fancy operations. I would also be curious to hear what toolchains people envision for getting such lookups into fonts. (And ideally, also how they would interact with using more friendly tools for any "normal" features.)
  • One extra thing about using virtual glyph IDs is that (AFAIK) it is outside what one can do with the usual friendly end-user font editors most people use to create fonts. Such tools generally operate on glyph names, and require them to actually
    be present in the font to successfully compile the features.
    I believe this is the case for me; I'm working with Font Creator. Great app, and I think it handles such features, but not sure. However, I'm sure Erwin (or others) might chime in to enlighten me. Regardless, I've got a long road to learning how this and other advanced techniques are applied.