Kitty: OpenType features

Created on 26 Nov 2017  路  23Comments  路  Source: kovidgoyal/kitty

Is it possible to specify a list of OpenType features to enable?

For instance I'd like to enable the zero feature, which gives a slashed zero in most modern fonts.

See for example the Wikipedia page on font features or the font-feature-settings CSS property.

enhancement help wanted

Most helpful comment

Replacing glyphs from different fonts is a nice feature, but not so useful in this case. My font of choice (as well as several other programming fonts) already contains the glyph I need, the slashed zero. I just need to figure out how to enable it.

I've tried a few things. I found that I can enable this feature system-wide using FontConfig, for instance in my ~/.config/fontconfig/fonts.conf:

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
  <match target="font">
    <edit name="fontfeatures" mode="append">
      <string>zero</string>
    </edit>
  </match>
</fontconfig>

This will enable the slashed zero on all fonts that contain it as a builtin option, such as Source Code Pro, FreeMono, Fira Mono and Fira Code.

It works on all programs I've tried so far (Leafpad, Linux Mint's Xed, Sublime Text, other random apps) but not on Kitty. I checked with strace and it does read my fonts.conf file, but then it ignores this particular setting. Do you have any idea why? Is it harfbuzz's fault? I used harfbuzz 1.7.4 compiled from source.

All 23 comments

There is no explicit setting, kitty just delegates glyph shaping to harfbuzz. IIRC harfbuzz does have an API for choosing OpenType features, so it could be theoretically exposed in kitty. Although I'm not convinced of the utility of this. For instance, if you want a slashed zero, why not just use a font that has a slashed zero, without needing to use OpenType features?

That said, I would be willing to merge a patch for this, but it is not something I am going to spend time on myself.

In fact, with kitty's symbol_map feature you can simply replace the 0 glyph in a font that does not have a glyph you like with a glyph from another font (the only limitation being the two fonts should have similar metrics, otherwise the substituted glyph may not look very nice).

So I really dont see a need for this. If you can expand on your use case, I'll be happy to reconsider.

Replacing glyphs from different fonts is a nice feature, but not so useful in this case. My font of choice (as well as several other programming fonts) already contains the glyph I need, the slashed zero. I just need to figure out how to enable it.

I've tried a few things. I found that I can enable this feature system-wide using FontConfig, for instance in my ~/.config/fontconfig/fonts.conf:

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
  <match target="font">
    <edit name="fontfeatures" mode="append">
      <string>zero</string>
    </edit>
  </match>
</fontconfig>

This will enable the slashed zero on all fonts that contain it as a builtin option, such as Source Code Pro, FreeMono, Fira Mono and Fira Code.

It works on all programs I've tried so far (Leafpad, Linux Mint's Xed, Sublime Text, other random apps) but not on Kitty. I checked with strace and it does read my fonts.conf file, but then it ignores this particular setting. Do you have any idea why? Is it harfbuzz's fault? I used harfbuzz 1.7.4 compiled from source.

I still dont understand what you are trying to achieve. If I do

kitty -o font_family=Fira\ Code\ Mono

The zero has a slash through it automatically, without needing any configuration in fontconfig.

screenshot_20171222_070943

Screenshot of slashed zero with fira code mono

A different example might clear this up. Some fonts like Iosevka can be customized via stylistic sets and character variants, both of which are OpenType font features. Kitty currently ignores these.

Stylistic sets are meant to be used in styles, for example, with CSS styling in HTML renders. They are not something that you set font-wide. Terminal text rendering has no escape codes to specify opentype font features. So if you really wanted to implement stylistic sets, you'd first have to invent new escape codes, then add support for them to kitty, then add support for them to actual terminal programs.

As for Iosevka, IIRC you simply enable the stylistic features you want when building the font. You dont select them at runtime.

Stylistic sets are meant to be used in styles, for example, with CSS styling in HTML renders. They are not something that you set font-wide. [...] you simply enable the stylistic features you want when building the font. You dont select them at runtime.

You can, and I absolutely do select them at runtime. fontconfig has build in support for this:

fonts-conf(5): [...] fontfeatures String List of the feature tags in OpenType to be enabled

So if you really wanted to implement stylistic sets, you'd first have to invent new escape codes, then add support for them to kitty, then add support for them to actual terminal programs.

All vte-based terminal emulators support this out-of-the-box, and I have yet to see a terminal program that has problem with character variants.

Like I said in my first post, patches are welcome, I have no interest in spending time on this, as using OpenType features font wide is IMO silly. To help anyone that wants to implement this, you'd just need to modify the code in freetype.c and fontconfig.c to store the font features when finding fonts in fontconfig.c and pass them into freetype when loading the actual fonts.

Enabling stylistic sets (and many other off-by-default) features is rather normal and common, features that need to be enabled for only parts of the text are usually the exception (e.g. the character variants, cvXX, features).

Really, in approximately twenty years of using linux I have never come across the use of stylistic features font-wide. And indeed, as far as I know all OSes (i.e. 99.9999999% of computing devices) other than linux don't provide any hooks for users (as opposed to programs using the font APIs) to do this at all. So if you want to convince me, you are going to have to provide some more justification for your claim than a bald statement.

And anyway, like I said, I have no objections to kitty having support for this, I am just not going to add it myself.

OK.

In case kitty never gets this, you can make a duplicate of your font, bake in some stylistic sets, and set kitty to use the duplicated font: https://github.com/twardoch/fonttools-utils/tree/master/pyftfeatfreeze

Would be nice to not have to do this though

I looked a bit into adding a font_features option to kitty config but the codebase is a bit much for 30 minutes. Maybe I'll take another look in a few days.

That being said, @kovidgoyal I do find it curious that your position ("Really, in approximately twenty years of using linux I have never come across the use of stylistic features font-wide.") seems to conflict with you applying a stylistic feature font-wide to "fix" nimbus mono.

On Thu, Sep 19, 2019 at 08:25:01PM -0700, Gus Caplan wrote:

I looked a bit into adding a font_features option to kitty config but the codebase is a bit much for 30 minutes. Maybe I'll take another look in a few days.

That being said, @kovidgoyal I do find it curious that your position ("Really, in approximately twenty years of using linux I have never come across the use of stylistic features font-wide.") seems to conflict with you applying a stylistic feature font-wide to "fix" nimbus mono.

Read more carefully. Stylistic features font wide by users, not by
software.

Not to mention that an application implementing a workaround for a broken font is not a systemwide usage of a font feature.

The PragmataPro font uses stylistic sets to choose between various types of italics, it would be very nice if this feature was implemented.

Hi,

I just wanted to provide some more information about Opentype Features to both projects, kitty and alacritty, as there have been some very similar requests put forward by users. If the maintainers choose to not implement those requests, I can fully understand that, because this is a pretty complicated matter. During the conversations, there were some statements regarding user / system wide configurations, font wide configurations, local configuration or replacement of characters, where I wanted add a few comments.

Where to choose to use an Opentype feature:

  1. OT features are usually not set system wide. E.g. in macOS nothing lets you set any font feature to be used globally, not for the OS itself or for the applications. So it is always an application based use of those features or not.
  2. In an Application it is up to the application to decide if a feature would be used for every text render or if it is based on a configuration of a particular paragraph (e.g. a Text Box in InDesign or a div in html/css). So from my perspective it would actually make sense in a terminal emulator, it the user's preference to use a OT feature could be expressed per font face setting in the terminal emulators config. To implement additional escape sequences for rendering certain areas on screen differently than others based on the context (like it is today for colors or bold/italics) would be non-standard and a pretty high configuration effort as well.

Replacement of characters:

  1. kitty e.g. has the feature, that a character can on-the-fly be replaced by another character, even from another font.
  2. This feature could actually be used if there is the special need to replace one character with one other (or ranges of characters). The prerequisite for that is, that this glyph is actually present and accessible in the other font. To take an example: if someone wanted the standard Fira Code and use the old style numerals, then they would need to have another instance of FiraCode, where the old stlye figures can actually be accessed - the stylistic sets are not (at least to my knowledge). So you would need to put the stylistic variants into the place of the actual previous numbers, hence you would need a font editor (or patcher) and if you already have access to those, you can also patch the original font to your liking. So that will obviate any modification of terminal emulators, but defeats the idea of OT features in the first place.
  3. You cannot access the ssxx glyphs via a replacement procedure, as they do not occupy any unicode code point in the font.
  4. Secondly, this approach would not work for replacing multiple characters, as is the case with ligatures and some ssets, e.g. ss07 of Fira Code "Regexp matching" which actually is some sort of additional ligature on-demand. (https://github.com/tonsky/FiraCode)

Screenshot 2020-04-26 at 15 00 42

Difference of Stylistic Sets and other OT features:

  1. To me it seems interesting, that the importance of ligatures was high enough, that some terminal emulator maintainers chose to implement this feature (and for me it was the deciding factor, why I chose one over the other). Disclaimer: I have to admit, that I do not fully understand, how it works, because, when I type === the ligature appears, e.g. in kitty, but when I move the cursor back one position, the ligature disappears, even though the actual characters below are still the same, just with one block inverted. So somehow the inversion of the last character makes it different enough for the rendering engine, that the ligature is no longer recognized... Beats me, how that is done...
  2. So, if it is possible to enable ligatures (which is basically also only one OT feature, and it is enabled font-wide), then I would assume, that the same mechanism might be provided for the other types of OT features, e.g. stylistic sets.

I attach some screenshots from Glyphs, where you can see, that stylistic variant glyphs do not have a code point and how OT features generally look in a typeface editor.

Screenshot 2020-04-26 at 15 01 20

I just hope that this brings additional information to the discussion. As I said, I completely understand if someone shies away from that matter.

Cheers and I thank both projects for their implementations! Great work!!

Michael.

What you described with the ligatures disappearing under the cursor sounds a bit like you set disable_ligatures to cursor.

You can already enable OpenType features per font, see the font_features
setting in kitty.conf. That seems to be what you are asking for.

You can already enable OpenType features per font, see the font_features
setting in kitty.conf. That seems to be what you are asking for.

Oh, wow - yes, thanks - I have missed that! I thought, I had read through all of the configurations, but I overlooked that. Thanks for kitty again!!

What you described with the ligatures disappearing under the cursor sounds a bit like you set disable_ligatures to cursor.

Yes, I did that - so that means, that kitty itself knows, when to display a ligature. So its not a deep level functionality of the underlying renderer, which replaces ligatures, but a conscious decision of the kitty code. Thanks, that clears that up. I might look into the src to see how that is done. Thanks for the hint!

[Edit: found it in render_line in fonts.c.]

Was this page helpful?
0 / 5 - 0 ratings