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

Contextual alternates for more proportional-looking monospace #2081

Open
illfygli opened this issue Nov 10, 2023 · 17 comments
Open

Contextual alternates for more proportional-looking monospace #2081

illfygli opened this issue Nov 10, 2023 · 17 comments
Milestone

Comments

@illfygli
Copy link

Is your feature request related to a problem? Please describe.
It's a "problem" common to monospaced fonts, that some letters, e.g. M or Æ look squeezed.

Describe the solution you'd like
Contextual alternates can improve the situation, making M wider in contexts where there's space around it.

Describe alternatives you've considered
I tried the Monaspace font, which has this feature (but they call it "texture healing"). But that's a different font, and I prefer Iosevka.

Additional context
I have attached a screenshot showing how Monaspace handles M in three different contexts, resulting in three different widths, and how smaller letters like i accommodate it by reducing their width.

screen-2023-11-10T09:23:48+0100

@be5invis
Copy link
Owner

I know some other fonts (Monoid) have similar behavior, but, well, implementing this might be tricky, espeically considering how complicated Iosevka already is. I may need to introduce tens of thousands of new glyphs for this feature, and will need a major refactor of the build system -- the font will be built with different "diversity" parameter (the metric factors I added for Aile and Etoile), and then create OT features for that.

@be5invis
Copy link
Owner

I'd like to keep it as a opt-in feature for now, and limit its supported characters, since there will be too many interactions... For now most of the diacritics will work.

image

be5invis added a commit that referenced this issue Nov 10, 2023
  - Currently only available through custom builds with `build-texture-feature = true`.
@illfygli
Copy link
Author

illfygli commented Nov 10, 2023

I figured it wouldn't be easy, but I thought maybe you would find it interesting. 😸

The support in Monaspace actually seems quite limited too. I tested it for a while, and the obvious examples work, but M surrounded by spaces does not work, and e.g. Æ does not have any alternates and remains compressed.

Having limited support would still be really nice I think!

@pagerc
Copy link

pagerc commented Nov 10, 2023

Just saw the monaspace font today too, and here's the github document detailing the "texture healing" concept:
https://github.com/githubnext/monaspace/blob/main/docs/Texture%20Healing.md

The concept of "texture healing" excites me for improving legibility of squished characters and I hope that Iosevka is able to introduce "texture healing" for at least the ASCII alphabetic character set to improve legibility of squished characters. The "texture healing" is focused on making words more legible, so word boundaries (punctuation and whitespace) are also an opportunity to expand squished characters without necessarily needing alternate glyphs to improve legibility.

Succinctly, I believe only 28 contextual alternates are needed for ASCII support (4 alternates for 7 alphabetic characters). Further, expanding on the "texture healing" of these character being adjacent to each other, I believe that the squished characters can be safely expanded any-time they are adjacent to a non-alphabetic character, improving legibility at word boundaries.

Squished ASCII alphabetic characters:
w, W, m, M

Whitespace abundant ASCII alphabetic characters:
i, I, l

@idan
Copy link

idan commented Nov 11, 2023

Hi all!

FYI, the sources for Monaspace are public, so you can see how they were implemented. It's not a trivial amount of work.

Basically, there are three categories of alternate glyphs: .left, .right, and .both. And then there are rules for when a given glyph is swapped out for an alternate.

We want others to be able to adopt this technique, so if there's anything we ought to explain better in the texture healing documentation, please let us know!

.left

Image

.right

Image

.both

Image

@be5invis
Copy link
Owner

be5invis commented Nov 11, 2023

Well I am doing similar things: call the glyph builder recursively multiple times, generate the width variations, then do some GSUB to apply the width variation.
There could have more crazy things to be done, like more extension/shrink grades, or shift the glyphs between a distanced narrow-wide pair using contextual GPOS...

@illfygli
Copy link
Author

I'm testing it with a custom build, it looks great!

Happy to see that Æ is supported too.

screen-2023-11-12T11:03:39+0100

@AndydeCleyre
Copy link

That was fast! I don't know if I want this but I'm eager to try it.


I'm guessing the experimental build-texture-feature option makes no sense to use in quasi-proportional builds -- but will it stop the build from working if it's there? I ask because I use some templating to generate build plans.


I gave the option a try (for a non-proportional build), and it failed, complaining:

Error: Target Error Error: Error: Glyph TextureExtL{cyrl/Nje/derive{cyrl/Nje/rightHalf}{cyrl/Nje/leftHalf.serifless}{cyrl/Nje/leftHalf.serifless}} doesn't exist.

@be5invis
Copy link
Owner

be5invis commented Nov 13, 2023

I'm guessing the experimental build-texture-feature option makes no sense to use in quasi-proportional builds -- but will it stop the build from working if it's there? I ask because I use some templating to generate build plans.

For QP it will simply be ignored.

I gave the option a try (for a non-proportional build), and it failed, complaining:

Error: Target Error Error: Error: Glyph TextureExtL{cyrl/Nje/derive{cyrl/Nje/rightHalf}{cyrl/Nje/leftHalf.serifless}{cyrl/Nje/leftHalf.serifless}} doesn't exist.

Just fixed that. Though i tis on the v28 branch, you will need to use camelCase for property names (buildTextureFeature).

be5invis added a commit that referenced this issue Nov 13, 2023
@AndydeCleyre
Copy link

Can anyone suggest software on Linux that definitely supports this feature well? I've compiled with the option but I'm not noticing a change in my primary places: wezterm and sublime text.

@illfygli
Copy link
Author

@AndydeCleyre Did you enable the TXTR font feature? I don't know how to do it in Wezterm, but in fontconfig you can do e.g.:

<match target="pattern">
    <test name="family" compare="contains">
        <string>Iosevka</string>
    </test>
    <edit name="fontfeatures" mode="append">
        ... other features you want ...
        <string>TXTR on</string>
   </edit>
</match>

Many programs pick that up automatically.
I use Kitty, which doesn't, so there I have to also add to kitty.conf:

font_family   Iosevka-Owl-Term-Extended

font_features Iosevka-Owl-Term-Extended +TXTR +otherfeatures

Kitty is what I've been using to take screenshots of both Monaspace and Iosevka with TXTR on, so it definitely works there.

@AndydeCleyre
Copy link

AndydeCleyre commented Nov 13, 2023

Thanks @illfygli , I had not enabled it in fontconfig. Now I have, but haven't seen the effect yet. I have tried enabling it via wezterm's harfbuzz_features setting, but don't see the result. I don't think it's possible to specify these features in Sublime. So I'll try setting up Kitty later. Thanks for that config example too.


EDIT: Yup, without any kitty configuration (but having it set in fontconfig), the effect can be seen:

kitty screenshot

@HaleTom
Copy link

HaleTom commented Nov 15, 2023

@AndydeCleyre @illfygli For wezterm, see my [edited: updated] monaspace config.font_rules here.

omidmnz added a commit to omidmnz/iosevka-omid that referenced this issue Nov 15, 2023
bcorporaal added a commit to bcorporaal/Udon-mono that referenced this issue Jan 13, 2024
Copy link

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 15 days.

@github-actions github-actions bot added the stale label Jan 19, 2024
@be5invis be5invis removed the stale label Jan 19, 2024
@be5invis be5invis added this to the Backlog milestone Jan 19, 2024
@mcchrish
Copy link

Italics m is clipped. This is my custom build.
image

But I guess it happens in general because of the slope (custom build does not change the slope, only the width).
image

I'm using Kitty.

@be5invis
Copy link
Owner

@mcchrish May need to tag connectivity for them...

@jul-sh
Copy link
Contributor

jul-sh commented Jan 27, 2025

For reference: after building a font with this feature, you need to also enable it in css / your editor.

In Zed that's

  "ui_font_features": {
    "TXTR": true
  },
  "buffer_font_features": {
    "TXTR": true
  }

in VSCode

"editor.fontLigatures": "'TXTR'",

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants