emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

How to use "smart kerning" font features in Emacs using composition-func


From: Steve Molitor
Subject: How to use "smart kerning" font features in Emacs using composition-function-table
Date: Sun, 26 Nov 2023 09:48:34 -0600

Using composition-function-table, is it possible to have the font
render a glyph for each character, based on the previous and following
character, in a moving window? For example, the rendering of character
1 will depend on what characters 0 and 2 are, character 2 depends on 1
and 3, etc.

Context:

The Commit Mono font has a feature that it calls "smart kerning". The
Monaspace font has a similar feature that it calls "texture healing."
Characters are moved around slightly, or swapped out for a slightly
larger or smaller character to even out the spacing, for example, when
a wide character like an 'm' is followed by a narrow character like an
'l'. It works by looking at the size class of the previous and
following characters to determine if it needs to shift the current
character to the left or right. For reference, the smart kerning
implementation in Commit Mono is here:

https://github.com/eigilnikolajsen/commit-mono/blob/main/src/features/kern_smartkerning.fea

I decided to see if I could get it to work just for the "Commit"
string by adding the following elisp:

    (set-char-table-range composition-function-table ?o
                                     '(["Com" 1 font-shape-gstring]))
    (set-char-table-range composition-function-table ?m
                                    '(["mmi" 1 font-shape-gstring]))

My thinking was if the current character is "o", preceded by a "C" and
followed by an "m", let the font replace the "o". Next, if the current
character is an "m" preceded by an "m" and followed by an "i", let the
font render the middle "m". If that worked I was going to do something
more generic.

It half worked. If I type "Com" it works as expected - the "o" shifts
slightly to the left when I type the "m":

https://cdn.zappy.app/f1506de028c470750428ebf984dfbe41.gif

If I type "mmi" on a separate line it also works - the second "m"
shifts to the left when I type the "i":

https://cdn.zappy.app/6a1a90013d102bfb494fc7d1de54ca32.gif

However, if I type "Commit", the "Com" works (the "o" shifts"), but
nothing happens when I type "mit". If I use three m's and type
"Commmit" I do see the effect on the final "mit":

https://cdn.zappy.app/e98141872235a25bf52f6e332b610d7b.gif

It seems I've created 3 character, non-overlapping gifs, which is not
the effect I want.

For comparison, here it is in VSCode, typing "Commit". Various
shifting effects happen as expected:

https://cdn.zappy.app/8f3bc49a174c4673747c402f7b39d54b.gif

I think when Emacs matches the 3 character regexp in the composition
function table, it assumes that those 3 characters constitute a single
glyph or ligature. That makes sense for ligatures, but it's not what I
want here. I want a "moving window" where the glyph for each character
depends on the previous and following character.

Is this possible to do in Emacs currently?

Thanks!

Steve



reply via email to

[Prev in Thread] Current Thread [Next in Thread]