Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kerning pairs should be defined as "visual left to right" #96

Open
justvanrossum opened this issue Nov 19, 2019 · 15 comments
Open

Kerning pairs should be defined as "visual left to right" #96

justvanrossum opened this issue Nov 19, 2019 · 15 comments
Labels
considering Specification change under consideration. proposal Proposed specification change. ufo4 UFO 4 issues.

Comments

@justvanrossum
Copy link
Contributor

UFO3 defines kerning pairs as "in writing direction", which is confusing and ambiguous, as documented in #16.

That issue is a mess, and it's hard to find important comments such as #16 (comment) and #16 (comment), so I propose to close it in favor of this one, where we can focus on the solution.

It seem the consensus is that the next major version of UFO should define kerning pairs as "visual left to right", to avoid ambiguity (as it was in UFO2).

We should come up with a recommendation of how to upconvert existing mixed LTR/RTL kerning. A special point of interest would be the naming of kern groups: public.kern1.* groups used in UFO3 RTL kerning should become public.kern2.* and vice versa, which may cause name clashes.

@benkiel
Copy link
Contributor

benkiel commented Nov 19, 2019

Agreed on closing the previous issue and starting a focused discussion, this has been dragging out too long (I know I am guilty here).

I believe one thought was to change the plists to hkerning.plist and vkerning.plist when doing this as to add vertical kerning, and have a clear break between the ambiguous kerning. Then tools can up convert if the user wants.

@justvanrossum
Copy link
Contributor Author

I've opened #97 to track vertical kerning. I think the renaming of kerning.plist to hkerning.plist is mostly tangential to this issue. I don't care much either way. A major version bump will be needed anyway.

@typoman
Copy link

typoman commented Jul 13, 2020

I'm not sure if this is going to solve an issue. I've made a kerning tool that interprets any pair with an RTL entry as an RTL pair. So ر{ is RTL. The logic is based on the UFO3 spec and that is pair entries are written in logical order. You can see the tool here:
https://gitlab.com/typoman/robofont-kerning-tool

I can't see a situation that making the order visual, would solve a problem but maybe it's just because I haven't encountered that kerning pair.

@typoman
Copy link

typoman commented Jul 13, 2020

As for neutral pairs like .{ they're already interpreted as LTR so adding this to the spec would not solve the ambiguity?

@benkiel
Copy link
Contributor

benkiel commented Jul 15, 2020

@typoman it's not neutral when the kerning is stored as writing direction, it leads to abiguity (for example see this comment). Trust me, I used to think that storing kerning in the writing direction order made the most sense or tagging pairs with direction (LTR, RTL, both), but I've come around to what @behdad has been saying: UFO2 was right, visual order is the best encoding for this.

@typoman
Copy link

typoman commented Jul 15, 2020

I also believe that visual order is more logical. What I'm not sure is if this is going to solve an issue or create more issues later, since everything works fine now.

@justvanrossum
Copy link
Contributor Author

justvanrossum commented Jul 15, 2020

As for neutral pairs like .{ they're already interpreted as LTR so adding this to the spec would not solve the ambiguity?

It means you currently can't kern such pairs for RTL. And that is exactly the issue to be solved.

It won't be an easy transition, and I'm sure there will be issues because of this transition, but it will ultimately be worth it.

@benkiel
Copy link
Contributor

benkiel commented Jul 15, 2020

And, to be very clear, any change to how kerning is encoded would mean a new file, like hkerning.plist, so the two would not be mixed.

@schriftgestalt
Copy link

And, to be very clear, any change to how kerning is encoded would mean a new file, like hkerning.plist, so the two would not be mixed.

Exactly. Add a rkerning.plist and keep it in trying order (cause processing it backwards doesn't make it any easier).

@anthrotype
Copy link
Member

anthrotype commented Jul 31, 2020

hkerning.plist as in "horizontal", with accompanying vkerning.plist for vertical.
Glyph pairs are written in visual order, left on the left, right on the right, top, bottom, etc.
Then the compiler encodes the kerning in both the LTR and RTL kern lookups, pruning away from the respective lookups the pairs that can never apply because involve glyphs associated with unicodes that belong to scripts with the other script direction.

@typoman
Copy link

typoman commented Aug 5, 2020

@anthrotype gave me a thorough explanation about how things are changing and why this makes sense. I'm going to put a summary of what I understood from his explanation here on how this is changing the compiler behaviour. This example shows how the encoding of an example neutral kerning pair works in the two specs.

Visual left to right order encoding

UFO

Left Right Value
{ . -30

ufo2ft kern fea

pos parentheses period -30; # inside an LTR lookup
pos period parentheses <-30 0 -30 0>; # inside an RTL lookup

Logical order encoding

UFO

1st 2nd Value
{ . -30

ufo2ft kern fea

pos parentheses period -30; # inside a dflt script lookup

Because the current spec sates the kerning pairs are written in logical order, there is no way to tell if the increase/decrease was in which direction (maybe LTR and RTL, maybe only one). But with visual order (neutral) this pair will be interpreted as an increase/decrease in space between those glyphs regardless of the direction and will be encoded in both LTR/RTL lookups (depending on what scripts are already present in the feature file). I hope I got this right but please correct me if I'm wrong.

@twardoch
Copy link

So let's say I'm writing an UFO version 3 for a font that has only Hebrew letters and some Latin punctuation.

I have 3 kerning pairs:

LEFT: /mem-hb, RIGHT: /dalet-hb, VALUE: -20
LEFT: /period, RIGHT: /dalet-hb, VALUE: -70
LEFT: /slash, RIGHT: /period, VALUE: -50

How am I supposed to store this in kerning.plist ?

  1. The UFO 3-specified way:
{ 
  "dalet-hb": { 
    "mem-hb": -20,
    "period": -70,
  },
  "period": {
    "slash": -50
  }
}

where the visual /slash/period is assumed to be used for RTL only (because no other strong scripts are in the font)?

But what happens if also Latin letters are present?

  1. Or should I risk contradicting the unclear spec, and store this unambiguously, the visual way = in such a way that the LEFT glyph is the top dict key, and the RIGHT glyph is the subdict key:
{ 
  "mem-hb": { 
    "dalet-hb": -20
  },
  "period": {
    "dalet-hb": -70
  },
  "slash": { 
    "period": -50
  }
}

I'm talking about UFO 3, not UFO 4.

@anthrotype
Copy link
Member

of course that's a rethorical question and the answer is "you can't", which is the main reason this issue exists. Would be nice to make progress on this front after three years of inactivity, we just need a "champion" that wants to carry this through the final line

@twardoch
Copy link

  1. But if I have to store, trying to follow the spec as best as poss is still a better choice than going simple/visual?

  2. For visual, we’re waiting for UFO4?

@anthrotype
Copy link
Member

anthrotype commented Nov 29, 2022

since slash and period are both neutral direction-wise, and there's no way to guess whether font developer wants to reduce by -50 the xadvance of slash when it precedes a period in a LTR run of text, and/or reduce both xadvance and xorigin of period by -50 when it precedes a slash in a RTL run, one might argue that one should interpret a pair such as {("slash", "period"): -50} in kerning.plist as visual left/right terms, thus do pos slash period -50;, in the lookup registered under a LTR script; and pos period slash <-50 0 -50 0>; in the lookup registered under RTL scripts...
However, we have been doing just the former in ufo2ft kernFeatureWriter, to stay closer to the logical ordering rule of UFO3 spec. Perhaps we could revise that again since we are touching that code in googlefonts/ufo2ft#679, though I am not 100% convinced this ambiguity is solvable within the current UFO3 logic framework.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
considering Specification change under consideration. proposal Proposed specification change. ufo4 UFO 4 issues.
Projects
None yet
Development

No branches or pull requests

7 participants