be5invis / Iosevka

Versatile typeface for code, from code.
http://be5invis.github.io/Iosevka
SIL Open Font License 1.1
19.04k stars 570 forks source link

Contextual alternates for more proportional-looking monospace #2081

Open illfygli opened 10 months ago

illfygli commented 10 months ago

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 commented 10 months ago

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 commented 10 months ago

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

illfygli commented 10 months ago

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

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 commented 10 months ago

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 commented 10 months ago

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 commented 10 months ago

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 commented 10 months ago

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 commented 10 months ago

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 commented 10 months ago

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).

AndydeCleyre commented 10 months ago

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 commented 10 months ago

@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 commented 10 months ago

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 commented 10 months ago

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

github-actions[bot] commented 8 months ago

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.

mcchrish commented 1 month ago

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 commented 1 month ago

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