unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Steve Molitor <stevemolitor@gmail.com>
To: emacs-devel@gnu.org
Subject: How to use "smart kerning" font features in Emacs using composition-function-table
Date: Sun, 26 Nov 2023 09:48:34 -0600	[thread overview]
Message-ID: <CAJrM8VXuBUREzXEymD2J7gUrJtk3N9zfmsHDQvPbvW1BDRsSqQ@mail.gmail.com> (raw)

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	other threads:[~2023-11-26 15:48 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-26 15:48 Steve Molitor [this message]
2023-11-26 17:52 ` How to use "smart kerning" font features in Emacs using composition-function-table Eli Zaretskii
2023-11-26 19:49   ` Steve Molitor
2023-11-26 20:16     ` Eli Zaretskii
2023-11-26 20:42       ` Steve Molitor
2023-11-27 12:03         ` Eli Zaretskii
     [not found]           ` <CAJrM8VW0P+-cO_cup6W-teoJV46nZTcsPrFbaKdXDD_CK_5Rxw@mail.gmail.com>
2023-11-27 15:22             ` Eli Zaretskii
2023-11-27 16:16               ` Steve Molitor
2023-11-28  5:18           ` Yuan Fu
2023-11-28 13:27             ` Steve Molitor
2023-11-29  0:58               ` Yuan Fu
2023-11-28 14:20             ` Eli Zaretskii
2023-11-29  0:57               ` Yuan Fu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAJrM8VXuBUREzXEymD2J7gUrJtk3N9zfmsHDQvPbvW1BDRsSqQ@mail.gmail.com \
    --to=stevemolitor@gmail.com \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).